Portability of Standard Functions
=================================

Many standard library functions have portability limitations, although they are specified in the Posix standard (http://www.opengroup.org/susv3).  In this section, we mention only functions that behave differently than specified; we don't mention functions that are not implemented at all on some platforms, or that are implemented but not declared on some platforms.  Many of the portability problems have a solution in Gnulib.

a64l
     This function was not correctly implemented in glibc versions before 2.2.5.

accept
     Some systems don't have a socklen_t type; in this case this function's third argument type is int *.

asctime
     This function may overflow its internal buffer if an invalid year is passed.

asctime_r
     This function may put more than 26 bytes into the argument buffer if an invalid year is passed.

basename
     glibc has two different functions basename: the POSIX version and the GNU version.

     basename assumes file names in POSIX syntax; it does not with file names in Windows syntax.

bcmp
     This function is marked as ``legacy'' in POSIX.  Better use memcmp instead.

bcopy
     This function is marked as ``legacy'' in POSIX.  Better use memcpy or memmove instead.

btowc
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

bzero
     This function is marked as ``legacy'' in POSIX.  Better use memset instead.

chown
     When applied to a symbolic link, some implementations don't dereference the symlink, i.e. they behave like lchown.

cproj
cprojf
cprojl
     The glibc implementation is or was broken.

creat
     On Windows, this function returns a file handle in O_TEXT mode.  If you need a file handle in O_BINARY mode, you need to use the function open instead.

     On platforms where off_t is a 32-bit type, creat may not work correctly to create files larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

ctime
     This function may overflow its internal buffer if an invalid year is passed.

ctime_r
     This function may put more than 26 bytes into the argument buffer if an invalid year is passed.

dirname
     dirname assumes file names in POSIX syntax; it does not with file names in Windows syntax.

dlopen
     If the file name argument is not absolute, the file is searched for.  The search algorithm is system specific.

dlsym
     The visibility of symbols loaded in dependent shared libraries or present in the main executable is system dependent.

ecvt
     This function is marked as ``legacy'' in POSIX.  Better use sprintf instead.

errno
     On Windows, the socket functions don't set errno; their error code is available through WSAGetLastError() instead.

fclose
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

fcvt
     This function is marked as ``legacy'' in POSIX.  Better use sprintf instead.

fdopen
fflush
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

fgetc
fgets
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

fgetwc
fgetws
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

fnmatch
     This function is broken in some version of Solaris or glibc.

fopen
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

     On Windows, this function returns a file stream in "text" mode by default; this means that it translates '\n' to CR/LF by default.  Use the "b" flag if you need reliable binary I/O.

fork
     On some systems, fork followed by a call of the exec family (execl, execlp, execle, execv, execvp, or execve) is less efficient than vfork followed by the same call.  vfork is a variant of fork that has been introduced to optimize the fork/exec pattern.

     On Windows systems (excluding Cygwin), this function is not implemented; use spawnvp instead.

fprintf
     On NetBSD and Windows, this function doesn't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines this function so that it is POSIX compliant.

     On Windows, this function doesn't support the ' flag and the hh, ll, j, t, z size specifiers.

fputc
fputs
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

fputwc
fputws
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

fread
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

free
     On old systems, free (NULL) is not allowed.

freopen
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

fscanf
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

     On Windows, this function doesn't support the hh, ll, j, t, z size specifiers.

fseek
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

fstat
     On platforms where off_t is a 32-bit type, stat may not report correctly the size of files or block devices larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

     On Cygwin, fstat applied to the file descriptors 0 and 1, returns different st_ino values, even if standard input and standard output are not redirected and refer to the same terminal.

ftime
     This function is marked as ``legacy'' in POSIX.  Better use gettimeofday or clock_gettime instead, and use ftime only as a fallback for portability to Windows systems.

fwide
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

     fwide is not guaranteed to be able to change a file stream's mode to a different mode than the current one.

fwprintf
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

fwrite
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

fwscanf
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

gcvt
     This function is marked as ``legacy'' in POSIX.  Better use sprintf instead.

getaddrinfo
     On Windows, this function is declared in <ws2tcpip.h> rather than in <netdb.h>.

getc
getchar
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

getcwd
     On glibc systems, getcwd (NULL, n) allocates memory for the result. On other systems, this call is not allowed.

getgroups
     On Ultrix 4.3, getgroups (0, 0) always fails.  See macro AC_FUNC_GETGROUPS.

gethostname
     If the given buffer is too small for the host name, some implementations fail with EINVAL, instead of returning a truncated host name.

getopt
     The glibc implementation of getopt by default allows mixing option and non-option arguments on the command line in any order.  Other implementations, such as the one in Cygwin, enfore strict POSIX compliance: they require that the option arguments precede the non-option arguments.  This is something to watch out in your program's testsuite.

getpeername
     Some systems don't have a socklen_t type; in this case this function's third argument type is int *.

getrusage
     Many systems don't fill in all the fields of struct rusage with meaningful values.

gets
     This function should never be used, because it can overflow any given buffer.

     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

getsockname
     Some systems don't have a socklen_t type; in this case this function's third argument type is int *.

getsockopt
     Some systems don't have a socklen_t type; in this case this function's fifth argument type is int *.

     Many socket options are not available on all systems.

     BeOS has the setsockopt function, but not the getsockopt function.

gettimeofday
     On some systems, gettimeofday clobbers the buffer in which localtime returns its result.

getwc
getwchar
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

getwd
     The size of the buffer required for this function is not a compile-time constant. Also, the function truncates a result that would be larger than the minimum buffer size. For these reasons, this function is marked as ``legacy'' in POSIX.  Better use the getcwd function instead.

glob
     Some systems may store additional flags in the gl_flags field.

gmtime_r
     Some systems define a function of this name that is incompatible to POSIX.

iconv
     This function was not correctly implemented in glibc versions before 2.2.

     When iconv encounters an input character that is valid but that can not be converted to the output character set, glibc's and GNU libiconv's iconv stop the conversion.  Some other implementations put an implementation-defined character in the output buffer.

iconv_open
     The set of supported encodings and conversions is system dependent.

index
     This function is marked as ``legacy'' in POSIX.  Better use strchr instead.

inet_addr
     On some old systems, this function returns a struct in_addr rather than a scalar type such as unsigned int or unsigned long.

ioctl
     Most ioctl requests are platform and hardware specific.

isatty
     On Windows, isatty also returns true for character devices such as "NUL".

iswalnum
iswalpha
iswblank
iswcntrl
iswctype
iswdigit
iswgraph
iswlower
iswprint
iswpunct
iswspace
iswupper
iswxdigit
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

l64a
     This function was not correctly implemented in glibc versions before 2.2.5.

localtime_r
     Some systems define a function of this name that is incompatible to POSIX.

longjmp
     The effects of this call are system and compiler optimization dependent, since it restores the contents of register-allocated variables but not the contents of stack-allocated variables.

     When longjumping out of a signal handler that was being executed on an alternate stack (installed through sigaltstack), on FreeBSD, NetBSD, OpenBSD, you need to clear the SS_ONSTACK flag in the stack_t structure managed by the kernel.

lseek
     POSIX does not specify which file descriptors support seeking and which don't. In practice, regular files and block devices support seeking, and ttys, pipes, and most character devices don't support it.

     On platforms where off_t is a 32-bit type, lseek does not work correctly with files larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

lstat
     When the argument ends in a slash, some systems don't dereference the argument.

     On platforms where off_t is a 32-bit type, lstat may not report correctly the size of files or block devices larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

mbrtowc
mbsrtowcs
mbstowcs
mbtowc
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

mkdir
     When the argument ends in a slash, the function call fails on some systems.

     On Windows systems (excluding Cygwin), this function is called _mkdir and takes only one argument.  The fix is to define a macro like this:

          #define mkdir ((int (*)()) _mkdir)

mkstemp
     On some systems (HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a silly limit that it can create no more than 26 files from a given template.  On OSF/1 4.0f, it can create only 32 files per process.

     On systems other than glibc 2.0.7 or newer, mkstemp can create a world or group writable or readable file, if you haven't set the process' umask to 077.  This is a security risk.

mktemp
     This function is not appropriate for creating temporary files.  (It has security risks.)  Therefore it is marked as ``legacy'' in POSIX.  Better use mkstemp instead.

mktime
     Some implementations of mktime may go into an endless loop.

mmap
     To get anonymous memory, on some systems, you can use the flags MAP_ANONYMOUS | MAP_PRIVATE and -1 instead of a file descriptor; on others you have to use a read-only file descriptor of /dev/zero.

     On HP-UX, passing a non-NULL first argument, as a hint for the address (even without MAP_FIXED, often causes mmap to fail.  Better pass NULL in this case.

     On HP-UX, MAP_FIXED basically never works.  On other systems, it depends on the circumstances whether memory can be returned at a given address.

mprotect
     On AIX, it is not possible to use mprotect on memory regions allocated with malloc.

msync
     On NetBSD, msync takes only two arguments.

nanosleep

nice
     In glibc before glibc 2.2.4, nice returned 0 upon success.

nl_langinfo
     Some older versions of glibc had nl_langinfo but not the CODESET macro.

     On Cygwin, which doesn't have locales, nl_langinfo(CODESET) always returns "US-ASCII".

open
     On Windows, this function returns a file handle in O_TEXT mode by default; this means that it translates '\n' to CR/LF by default.  Use the O_BINARY flag if you need reliable binary I/O.

     On platforms where off_t is a 32-bit type, open may not work correctly with files larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

poll
     On MacOS X 10.4.0 and AIX 5.3, this function doesn't work on special files like /dev/null and ttys like /dev/tty.

printf
     On NetBSD and Windows, this function doesn't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines this function so that it is POSIX compliant.

     On Windows, this function doesn't support the ' flag and the hh, ll, j, t, z size specifiers.

pthread_create
     On Linux/glibc systems before the advent of NPTL, signals could only be executed in one particular thread, not by any thread of the process.

putc
putchar
puts
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

putwc
putwchar
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

readlink
     When readlink is called on a directory: In the case of NFS mounted directories, Cygwin sets errno to ENOENT or EIO instead of EINVAL.  To avoid this problem, check for a directory before calling readlink.

     When readlink is called on a file that is not a symbolic link: Irix may set errno to ENXIO instead of EINVAL.  Cygwin may set errno to EACCES instead of EINVAL.

realpath
     This function does not allow to determine the required size of output buffer; PATH_MAX - if it is defined - is nothing more than a guess.

recvfrom
     Some systems don't have a socklen_t type; in this case this function's sixth argument type is int *.

regcomp
regexec
     Many regular expression implementations have bugs.

rename
     This function does not work on SunOS 4.1 when the source file name ends in a slash.

rewind
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

rindex
     This function is marked as ``legacy'' in POSIX.  Better use strrchr instead.

rmdir
     When rmdir fails because the specified directory is not empty, the errno value is system dependent.

scanf
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

     On Windows, this function doesn't support the hh, ll, j, t, z size specifiers.

select
     When you call select with a timeout, some implementations modify the timeout parameter so that upon return from the function, it contains the amount of time not slept.  Other implementations leave the timeout parameter unmodified.

     On Windows systems (excluding Cygwin) and on BeOS, select can only be called on descriptors created by the socket function, not on regular file descriptors.

     On Linux, when some file descriptor refers to a regular file, select may fail, setting errno to EBADF.

setcontext
     The effects of this call are system and compiler optimization dependent, since it restores the contents of register-allocated variables but not the contents of stack-allocated variables.

setenv
     In some versions of glibc (e.g. 2.3.3), setenv doesn't fail if the first argument contains a = character.

setjmp
     POSIX does not specify whether setjmp saves the signal mask in the jmp_buf.  It does on BSD systems, and on glibc systems when _BSD_SOURCE is defined; in this case setjmp behaves like sigsetjmp, and functions _setjmp and _longjmp are available that don't save or restore the signal mask.  On System V systems, and on glibc systems by default, setjmp doesn't save the signal mask.

setlocale
     On Cygwin, which doesn't have locales, setlocale(LC_ALL,NULL) always returns "C".

setsockopt
     Many socket options are not available on all systems.

setvbuf
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

shmat
     Attempts to shmat into a previously malloc-ed region fail on SunOS 4, with errno set to EINVAL, even if there is an munmap call in between.

     On Linux, the flag SHM_REMAP is needed in order to force shmat to replace existing memory mappings in the specify address range.  On other systems, it is not needed.

shmget
     On many systems (not Linux), SHMMAX is so small that it is unusable for reasonable applications, and/or shmget requires superuser privileges.

sigaction
     The symbolic value SIG_IGN for the SIGCHLD signal is equivalent to a signal handler

          void handle_child (int sigchld)
          {
            while (waitpid (-1, NULL, WNOHANG) > 0)
              ;
          }

     except that SIG_IGN for SIGCHLD has the effect that the children execution times are not accounted in the times function. On some systems (BSD? SystemV? Linux?), you need to use the sigaction flag SA_NOCLDWAIT in order to obtain this behaviour.

sigaltstack
     sigaltstack doesn't work on HP-UX 11/IA-64 and OpenBSD 3.6/Sparc64.

signal
     On System V systems, when the signal is triggered, the kernel uninstalls the handler (i.e. resets the signal's action to SIG_DFL) before invoking the handler.  This opens the door to race conditions: undesired things happen if the signal is triggered twice and the signal handler was not quick enough reinstalling itself as a handler.  On BSD systems and glibc systems, on the other hand, when the signal is triggered, the kernel blocks the signal before invoking the handler.  This is saner, but POSIX still allows either behaviour.  To avoid this problem, use sigaction instead of signal.

sigtimedwait
     Linux implements the meaning of NULL timeout by doing what sigwaitinfo does; other systems may not do the same.

sigwait
     On Linux/glibc systems before the advent of NPTL, signals could only be executed in one particular thread, not by any thread of the process.

sleep
     According to POSIX, the sleep function may interfere with the program's use of the SIGALRM signal.  On Linux, it doesn't; on other platforms, it may.

snprintf
     On NetBSD and Windows, this function doesn't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines this function so that it is is POSIX compliant.

     On Windows, this function doesn't support the ' flag and the hh, ll, j, t, z size specifiers.

socket
     On BeOS, the descriptors returned by the socket function can not be used in calls to read, write, and close; you have to use recv, send, closesocket in these cases instead.

sprintf
     On NetBSD and Windows, this function doesn't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines this function so that it is is POSIX compliant.

     On Windows, this function doesn't support the ' flag and the hh, ll, j, t, z size specifiers.

sscanf
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

     On Windows, this function doesn't support the hh, ll, j, t, z size specifiers.

stat
     On platforms where off_t is a 32-bit type, stat may not report correctly the size of files or block devices larger than 2 GB.  The fix is to use the AC_SYS_LARGEFILE macro.

     Cygwin's stat function sometimes sets errno to EACCES when ENOENT would be more appropriate.

strcasecmp
strcasestr
     As of 2006, no system is known that implements these functions correctly in multibyte locales.

strerror_r
     glibc has an incompatible version of this function.  The POSIX compliant code

          char *s = (strerror_r (err, buf, buflen) == 0 ? buf : NULL);

     is essentially equivalent to this code using the glibc function:

          char *s = strerror_r (err, buf, buflen);

strstr
     As of 2006, no system is known that implements this function correctly in multibyte locales.

swprintf
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

     On Windows, this function does not take a buffer size as second argument.

system
     On Windows systems (excluding Cygwin), the command processor used by the system function is cmd.exe, not /bin/sh.  Accordingly, the rules for quoting shell arguments containing spaces, quote or other special characters are different.

tcdrain
     On some systems, tcdrain on a non-tty fails with errno set to EINVAL or, on MacOS X, also EOPNOTSUPP or ENODEV, rather than ENOTTY.

tcflush
     On some systems, tcflush of TCIFLUSH on a non-tty fails with errno set to EINVAL rather than ENOTTY.

     On some systems, tcflush of TCOFLUSH on a non-tty fails with errno set to EINVAL or, on IRIX, also ENOSYS, or, on MacOS X, also EOPNOTSUPP or ENODEV, rather than ENOTTY.

tempnam
     This function is not appropriate for creating temporary files.  (It has security risks.)  Better use mkstemp instead.

tmpnam
     This function is not appropriate for creating temporary files.  (It has security risks.)  Better use mkstemp instead.

towctrans
towlower
towupper
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

ungetc
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

ungetwc
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

unlink
     Removing an open file is unportable: On Unix this allows the programs that have the file already open to continue working with it; the file's storage is only freed when the no process has the file open any more.  On Windows, the attempt to remove an open file fails.

usleep
     According to POSIX, the usleep function may interfere with the program's use of the SIGALRM signal.  On Linux, it doesn't; on other platforms, it may.

utime
     On some systems, utime (file, NULL) fails to set the file's timestamp to the current time.

utimes
     This function is marked as ``legacy'' in POSIX.  Better use utime instead.

va_arg
     The second argument of va_arg must be a type that is invariant under the ``default argument promotions'' (ISO C 99 6.5.2.2 paragraph 6).  This means that the following are not valid here:

     float
          Use double instead.

     bool
          Use int instead.

     Integer types smaller than int.
          Use int or unsigned int instead.

     This is a portability problem because you don't know the width of some abstract types like uid_t, gid_t, mode_t.  So, instead of

          mode = va_arg (ap, mode_t);

     you have to write

          mode = (sizeof (mode_t) < sizeof (int)
                  ? va_arg (ap, int)
                  : va_arg (ap, mode_t));

va_copy
     Some platforms don't provide this macro.  You can use __va_copy where available instead, or otherwise an assignment or memcpy call.

vfprintf
     On NetBSD and Windows, this function doesn't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines this function so that it is POSIX compliant.

     On Windows, this function doesn't support the ' flag and the hh, ll, j, t, z size specifiers.

vfscanf
     On Windows systems (excluding Cygwin), this function does not set errno upon failure.

     On Windows, this function doesn't support the hh, ll, j, t, z size specifiers.

vprintf
vsnprintf
vsprintf
     On NetBSD and Windows, these functions don't support format directives that access arguments in an arbitrary order, such as "%2$s".  The fix is to include <libintl.h> from GNU gettext; it redefines these functions so that they are POSIX compliant.

     On Windows, these functions don't support the ' flag and the hh, ll, j, t, z size specifiers.

vscanf

vsscanf
     On Windows systems (excluding Cygwin), these functions do not set errno upon failure.

     On Windows, these functions don't support the hh, ll, j, t, z size specifiers.

vswprintf
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

     On Windows, this function does not take a buffer size as second argument.

waitid
     As of 2005, no system is known on which waitid with flag WNOWAIT works correctly.

wcrtomb
wcscat
wcschr
wcscmp
wcscoll
wcscpy
wcscspn
wcsftime
wcslen
wcsncat
wcsncmp
wcsncpy
wcspbrk
wcsrchr
wcsrtombs
wcsspn
wcsstr
wcstod
wcstof
wcstoimax
wcstok
wcstol
wcstold
wcstoll
wcstombs
wcstoul
wcstoull
wcstoumax
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

wcswcs
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.

     This function is marked as ``legacy'' in POSIX.  Better use wcsstr instead.

wcswidth
wcsxfrm
wctob
wctomb
wctrans
wctype
wcwidth
wmemchr
wmemcmp
wmemcpy
wmemmove
wmemset
wprintf
wscanf
     On Windows systems, wchar_t is a 16-bit type and therefore cannot accomodate all Unicode characters.