Mercurial > hg > octave-nkf > gnulib-hg
changeset 12047:21ec8b9a3f27
openat: fix openat bugs on Solaris 9
openat(fd,"file/",O_RDONLY) mistakenly succeeded.
* lib/openat.c (rpl_openat): Work around Solaris 9 bug.
* m4/openat.m4 (gl_FUNC_OPENAT): Also replace openat on Solaris.
* modules/openat (Depends-on): Add open.
* m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Provide new default.
* modules/fcntl-h (Makefile.am): Substitute it.
* lib/fcntl.in.h (openat): Declare replacement.
* doc/posix-functions/openat.texi (openat): Document this.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Sat, 19 Sep 2009 11:16:58 -0600 |
parents | fb58acddad72 |
children | 0f01e7ffb856 |
files | ChangeLog doc/posix-functions/openat.texi lib/fcntl.in.h lib/openat.c m4/fcntl_h.m4 m4/openat.m4 modules/fcntl-h modules/openat |
diffstat | 8 files changed, 125 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2009-09-19 Eric Blake <ebb9@byu.net> + openat: fix openat bugs on Solaris 9 + * lib/openat.c (rpl_openat): Work around Solaris 9 bug. + * m4/openat.m4 (gl_FUNC_OPENAT): Also replace openat on Solaris. + * modules/openat (Depends-on): Add open. + * m4/fcntl_h.m4 (gl_FCNTL_H_DEFAULTS): Provide new default. + * modules/fcntl-h (Makefile.am): Substitute it. + * lib/fcntl.in.h (openat): Declare replacement. + * doc/posix-functions/openat.texi (openat): Document this. + openat: move fstatat and unlinkat into correct files * m4/openat.m4 (gl_FUNC_OPENAT): Adjust which files will be compiled.
--- a/doc/posix-functions/openat.texi +++ b/doc/posix-functions/openat.texi @@ -13,6 +13,11 @@ glibc 2.3.6, MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Cygwin 1.5.x, mingw, Interix 3.5, BeOS. But the replacement function is not safe to be used in libraries and is not multithread-safe. +@item +This function does not fail when the file name argument ends in a slash +and (without the slash) names a nonexistent file or a file that is not a +directory, on some platforms: +Solaris 9. @end itemize Portability problems not fixed by Gnulib:
--- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h @@ -62,9 +62,11 @@ #endif #if @GNULIB_OPENAT@ -# if !@HAVE_OPENAT@ +# if @REPLACE_OPENAT@ # undef openat # define openat rpl_openat +# endif +# if !@HAVE_OPENAT@ || @REPLACE_OPENAT@ int openat (int fd, char const *file, int flags, /* mode_t mode */ ...); # endif #elif defined GNULIB_POSIXCHECK
--- a/lib/openat.c +++ b/lib/openat.c @@ -22,12 +22,107 @@ #include <stdarg.h> #include <stddef.h> +#include <string.h> #include <sys/stat.h> #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ #include "openat-priv.h" #include "save-cwd.h" +#if HAVE_OPENAT + +# undef openat + +/* Like openat, but work around Solaris 9 bugs with trailing slash. */ +int +rpl_openat (int dfd, char const *filename, int flags, ...) +{ + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + <http://www.opengroup.org/susv3/functions/open.html> says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +#endif + + fd = openat (dfd, filename, flags, mode); + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +#endif + + return fd; +} + +#else /* !HAVE_OPENAT */ + /* Replacement for Solaris' openat function. <http://www.google.com/search?q=openat+site:docs.sun.com> First, try to simulate it via open ("/proc/self/fd/FD/FILE"). @@ -156,3 +251,5 @@ return needs_fchdir; } + +#endif /* !HAVE_OPENAT */
--- a/m4/fcntl_h.m4 +++ b/m4/fcntl_h.m4 @@ -1,4 +1,4 @@ -# serial 3 +# serial 4 # Configure fcntl.h. dnl Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation @@ -91,9 +91,10 @@ AC_DEFUN([gl_FCNTL_H_DEFAULTS], [ - GNULIB_OPEN=0; AC_SUBST([GNULIB_OPEN]) - GNULIB_OPENAT=0; AC_SUBST([GNULIB_OPENAT]) + GNULIB_OPEN=0; AC_SUBST([GNULIB_OPEN]) + GNULIB_OPENAT=0; AC_SUBST([GNULIB_OPENAT]) dnl Assume proper GNU behavior unless another module says otherwise. - HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT]) - REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN]) + HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT]) + REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN]) + REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT]) ])
--- a/m4/openat.m4 +++ b/m4/openat.m4 @@ -1,4 +1,4 @@ -# serial 23 +# serial 24 # See if we need to use our replacement for Solaris' openat et al functions. dnl Copyright (C) 2004-2009 Free Software Foundation, Inc. @@ -32,6 +32,8 @@ yes+*) # Solaris 9 has *at functions, but uniformly mishandles trailing # slash in all of them. + AC_LIBOBJ([openat]) + REPLACE_OPENAT=1 AC_LIBOBJ([fstatat]) REPLACE_FSTATAT=1 AC_LIBOBJ([unlinkat])
--- a/modules/fcntl-h +++ b/modules/fcntl-h @@ -28,6 +28,7 @@ -e 's|@''GNULIB_OPEN''@|$(GNULIB_OPEN)|g' \ -e 's|@''GNULIB_OPENAT''@|$(GNULIB_OPENAT)|g' \ -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \ + -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \ -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \ < $(srcdir)/fcntl.in.h; \