How _not_ to fix glibc 2.10 function collisions

Following my previous how not to fix post I’d like to explain also how not to fix the other kind of glibc 2.10 failure: function collisions.

With the new version of glibc, support for the latest POSIX C library specification is added; this means that, among other things, a few functions that previously were only available as GNU extensions are now standardised and, thus, visible by default unless requesting a strictly older POSIX version.

The functions that were, before, available as GNU extensions were usually hidden unless the _GNU_SOURCE feature selection macro was defined; in autotools, that meant using the AC_SYSTEM_EXTENSIONS macro to request them explicitly. Now these are visible by default; this wouldn’t be a problem if some packages didn’t decide to either reimplement them, or call their functions just like that.

Most commonly the colliding function is getline(); the reason for which is that the name is really too generic and I would probably curse POSIX committees for accepting it with the same name in the C library; I already cursed GNU for adding it with that name to glibc. With the name of getline() there are over tons of functions, with the most different interfaces, that try to get lines from any kind of media. The solution for these is to rename them to some different name so that the collision is avoided.

More interesting is instead the software that, wanting to use something alike to strndup() decide to create its own version, because some system do lack that function. In this case, renaming the functions, like I’ve seen one user propose today, is crazy. The system already provide the function; use that!

This can be done quite easily with autotools-based packages (and can be applied to other build systems, like cmake, that work on the basis of understanding what the system provides):

# in configure.ac
AC_SYSTEM_EXTENSIONS
AC_CHECK_FUNCS([strndup])

/* in a private header */
#include "config.h"

#ifndef HAVE_STRNDUP
char *strndup(const char *str, size_t len);
#endif

/* in an implementation file */
#ifndef HAVE_STRNDUP
char *strndup(const char *str, size_t len)
{
  [...]
}
#endif

When building on any glibc (2.7+ at least, I’d say), this code will use the system-provided function, without adding further duplicate, useless code; when building on systems where the function is not (yet) available, like FreeBSD 7, then the custom functions will be used.

Of course it takes slightly more time than renaming the function, but we’re here to fix stuff in the right way, aren’t we?

Exit mobile version