2009-09-23 Eric Blake <ebb9@byu.net>
+ 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
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
/* 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
#include <unistd.h>
#include <errno.h>
-#include <sys/types.h>
+#include <string.h>
#include <sys/stat.h>
-#include <stddef.h>
#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 */
/* mingw, BeOS, Haiku declare environ in <stdlib.h>, not in <unistd.h>. */
#include <stdlib.h>
-#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 <sys/types.h>
#endif
#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
<http://www.opengroup.org/susv3xsh/readlink.html>. */
-# 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
-# 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,
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 <unistd.h>
+ /* 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
])
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])
-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' \