[[!meta copyright="Copyright © 2012, 2013 Free Software Foundation, Inc."]] [[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable id="license" text="Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled [[GNU Free Documentation License|/fdl]]."]]"""]] Porting Guide for Dummies ========================= The problems addressed here were encountered while working on fixing **PATH_MAX** and **MAXPATHLEN**. [[!toc startlevel=2 levels=3]] * * * Test on Hurd ------------ ### Installing the required files As `apt-get source` will download and extract many files, you may want to create a dedicated folder for the package and work from there. mkdir PACKAGE cd PACKAGE sudo apt-get build-dep PACKAGE apt-get source PACKAGE ### Trying to build the package cd PACKAGE_SOURCE dpkg-buildpackage -us -uc -rfakeroot -tc ### Test a quick fix In all the files that use **PATH_MAX**, include those lines at the beginning. #ifndef PATH_MAX #define PATH_MAX 4196 #endif Try to rebuild the package and see if it's solved the problem. If yes, you can start working on the package. * * * Basic things ------------ ### Maintaining a original version mkdir old cp -r PACKAGE_SOURCE old/ ### Coding style Follow the conventions used in the source code! if (condition) { do_smthg(); } is not the same as: if (condition) { do_smthg(); } and is not the same as: if (condition) do_smthg(); Pay attention to spaces surrounding, or not, arithmetic signs and symbols: a = do_smthg( b + c ); a = do_smthg(b+c); ### Indentation By default use 8 spaces as the size for 1 tab. Then figure out if the code uses tab + 1/2 tab: ....if (condition) { ------->do_smthg(); ....} or tab only: ------->if (condition) { ------->------->do_smthg(); ------->} ### Creating a patch diff -Naur old/PACKAGE-VERSION PACKAGE-VERSION > fix_FTBFS4Hurd.patch * * * Known problems -------------- ### Dynamically allocated buffer returned by a function Use a static buffer ### Buffer used to format an expression containing an INTEGER The length of an INTEGER in a string can be up to sizeof (int) * 3 + 1. > The usual trick for "%d" is to use the constant 'sizeof (int) * 3 + 1'. I included + 1 for the sign, but it's not really necessary if we exepect sizeof(int) >= 2, which we probably should. **Jérémie Koenig** log(MAX_INT) = log(2 ^ 32) = 32 * log(2) = 4 * 8 * log(2) = sizeof(int) * 2.40823997 < sizeof(int) * 3 ### Proper use of realloc() use a new_buff to check if everything went fine Free buf if realloc failed (and prog doesn't exit) ### Reading lines from file Function to read line (no size limit, ending with "\n") from a file. static char *get_line(FILE *f) { char *buff = NULL; char *new_buff = NULL; size_t buff_size = 0; size_t last = 0; while (!feof(f)) { buff_size = buff_size ? buff_size * 2 : BUFSIZ; new_buff = realloc(buff, buff_size); if (new_buff == NULL) { free(buff); return NULL; } buff = new_buff; if (fgets(buff + last, buff_size - last, f) == NULL) { free(buff); return NULL; } last = strlen(buff); if (buff[last - 1] == '\n') return buff; } return buff; } ### Proper use of readlink() One has to rely on lstat() to get the size of the link that readlink() returns. Declare what you need: char *linkname = NULL; struct stat sb; ssize_t len = -1; Call lstat() and check return value: if (lstat(filename, &sb) == -1) { Create a buffer of the appropriate size and check the return value: linkname = malloc(sb.st_size + 1); if (linkname == NULL) { Call readlink(), check return value and set the null char in the linkname: len = readlink(filename, linkname, sb.st_size + 1); if (len < 0 || len > sb.st_size) { ... linkname[sb.st_size] = '\0'; ### Alternative use of readlink(): readlink_malloc() In some cases the above approch doesn't work.for instance when reading from **/proc/*/exe** on Linux. In this case you can try the following function. The code comes from [[https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/806-BSI.html]] static char *readlink_malloc(const char *filename) { int size = 100; while (1) { char *buff = malloc(size); if (buff == NULL) return NULL; int nchars = readlink(filename, buff, size); if (nchars < 0) { free(buff); return NULL; } if (nchars < size) { buff[nchars] = '\0'; return buff; } free (buff); size *= 2; } }