From: Eric Blake Date: Tue, 22 Sep 2009 23:14:23 +0000 (-0600) Subject: readlink: fix cygwin 1.5.x bug with return type X-Git-Tag: v0.1~5429 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=5b192b3998d3b3bcea45594d180200cd44f35e3b;p=gnulib.git readlink: fix cygwin 1.5.x bug with return type On older systems, readlink returned int instead of ssize_t, making the use of readlink via function pointer harder. * m4/readlink.m4 (gl_FUNC_READLINK): Require correct signature. * lib/unistd.in.h (readlink): Use ssize_t. * lib/readlink.c (readlink): Likewise. * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add witness. * modules/unistd (Makefile.am): Substitute it. * lib/unistd.in.h (readlink): Declare replacement. * doc/posix-functions/readlink.texi (readlink): Document this. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index ab0e91a22..2a0d7f77f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2009-09-23 Eric Blake + readlink: fix cygwin 1.5.x bug with return type + * m4/readlink.m4 (gl_FUNC_READLINK): Require correct signature. + * lib/unistd.in.h (readlink): Use ssize_t. + * lib/readlink.c (readlink): Likewise. + * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add witness. + * modules/unistd (Makefile.am): Substitute it. + * lib/unistd.in.h (readlink): Declare replacement. + * doc/posix-functions/readlink.texi (readlink): Document this. + symlink: use throughout gnulib * m4/symlinkat.m4 (gl_FUNC_SYMLINKAT): Omit symlink check. * lib/symlinkat.c (symlinkat) [!HAVE_SYMLINK]: Document why diff --git a/doc/posix-functions/readlink.texi b/doc/posix-functions/readlink.texi index e2a2a1e3a..dd7bcb991 100644 --- a/doc/posix-functions/readlink.texi +++ b/doc/posix-functions/readlink.texi @@ -9,6 +9,10 @@ Gnulib module: readlink Portability problems fixed by Gnulib: @itemize @item +On some platforms, @code{readlink} returns @code{int} instead of +@code{ssize_t}: +FreeBSD 6.0, OpenBSD 3.8, Cygwin 1.5.x. +@item This function is missing on some platforms: mingw. @end itemize diff --git a/lib/readlink.c b/lib/readlink.c index 5cccdc962..58379b1d0 100644 --- a/lib/readlink.c +++ b/lib/readlink.c @@ -1,5 +1,5 @@ /* Stub for readlink(). - Copyright (C) 2003-2007 Free Software Foundation, Inc. + Copyright (C) 2003-2007, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,30 +20,39 @@ #include #include -#include +#include #include -#include #if !HAVE_READLINK /* readlink() substitute for systems that don't have a readlink() function, such as DJGPP 2.03 and mingw32. */ -/* The official POSIX return type of readlink() is ssize_t, but since here - we have no declaration in a public header file, we use 'int' as return - type. */ - -int -readlink (const char *path, char *buf, size_t bufsize) +ssize_t +readlink (const char *name, char *buf _UNUSED_PARAMETER_, + size_t bufsize _UNUSED_PARAMETER_) { struct stat statbuf; /* In general we should use lstat() here, not stat(). But on platforms - without symbolic links lstat() - if it exists - would be equivalent to + without symbolic links, lstat() - if it exists - would be equivalent to stat(), therefore we can use stat(). This saves us a configure check. */ - if (stat (path, &statbuf) >= 0) + if (stat (name, &statbuf) >= 0) errno = EINVAL; return -1; } -#endif +#else /* HAVE_READLINK */ + +# undef readlink + +/* readlink() wrapper that uses correct types, for systems like cygwin + 1.5.x where readlink returns int. */ + +ssize_t +rpl_readlink (const char *name, char *buf, size_t bufsize) +{ + return readlink (name, buf, bufsize); +} + +#endif /* HAVE_READLINK */ diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 76d987e5f..600f22408 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -41,7 +41,9 @@ /* mingw, BeOS, Haiku declare environ in , not in . */ #include -#if @GNULIB_WRITE@ && @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@ +#if ((@GNULIB_WRITE@ && @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@) \ + || (@GNULIB_READLINK@ && (!@HAVE_READLINK@ || @REPLACE_READLINK@)) \ + || (@GNULIB_READLINKAT@ && !@HAVE_READLINKAT@)) /* Get ssize_t. */ # include #endif @@ -621,13 +623,16 @@ extern int pipe2 (int fd[2], int flags); #if @GNULIB_READLINK@ +# if @REPLACE_READLINK@ +# define readlink rpl_readlink +# endif /* Read the contents of the symbolic link FILE and place the first BUFSIZE bytes of it into BUF. Return the number of bytes placed into BUF if successful, otherwise -1 and errno set. See the POSIX:2001 specification . */ -# if !@HAVE_READLINK@ -extern int readlink (const char *file, char *buf, size_t bufsize); +# if !@HAVE_READLINK@ || @REPLACE_READLINK@ +extern ssize_t readlink (const char *file, char *buf, size_t bufsize); # endif #elif defined GNULIB_POSIXCHECK # undef readlink diff --git a/m4/readlink.m4 b/m4/readlink.m4 index ff3f1f587..b7b74de1e 100644 --- a/m4/readlink.m4 +++ b/m4/readlink.m4 @@ -1,4 +1,4 @@ -# readlink.m4 serial 5 +# readlink.m4 serial 6 dnl Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,6 +12,19 @@ AC_DEFUN([gl_FUNC_READLINK], HAVE_READLINK=0 AC_LIBOBJ([readlink]) gl_PREREQ_READLINK + else + AC_CACHE_CHECK([whether readlink signature is correct], + [gl_cv_decl_readlink_works], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + /* Cause compilation failure if original declaration has wrong type. */ + ssize_t readlink (const char *, char *, size_t);]])], + [gl_cv_decl_readlink_works=yes], [gl_cv_decl_readlink_works=no])]) + if test "$gl_cv_decl_readlink_works" != yes; then + REPLACE_READLINK=1 + AC_LIBOBJ([readlink]) + fi fi ]) diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 index 0a263d2fd..23345823b 100644 --- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -101,6 +101,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], REPLACE_LCHOWN=0; AC_SUBST([REPLACE_LCHOWN]) REPLACE_LINK=0; AC_SUBST([REPLACE_LINK]) REPLACE_LSEEK=0; AC_SUBST([REPLACE_LSEEK]) + REPLACE_READLINK=0; AC_SUBST([REPLACE_READLINK]) REPLACE_RMDIR=0; AC_SUBST([REPLACE_RMDIR]) REPLACE_SYMLINK=0; AC_SUBST([REPLACE_SYMLINK]) REPLACE_UNLINK=0; AC_SUBST([REPLACE_UNLINK]) diff --git a/modules/unistd b/modules/unistd index d2568b20b..875efb0cc 100644 --- a/modules/unistd +++ b/modules/unistd @@ -93,6 +93,7 @@ unistd.h: unistd.in.h -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ + -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \