Mercurial > hg > octave-nkf > gnulib-hg
changeset 12044:1b85d0321310
openat: fix fstatat bugs on Solaris 9
fstatat(fd,"file/",buf,flag) mistakenly succeeded.
* lib/fstatat.c (rpl_fstatat): Copy recent fixes from lstat and
stat.
* doc/posix-functions/fstatat.texi (fstatat): Document this.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Fri, 18 Sep 2009 19:38:46 -0600 |
parents | fc84db4ef49d |
children | 2bd4d1ff29e9 |
files | ChangeLog doc/posix-functions/fstatat.texi lib/fstatat.c |
diffstat | 3 files changed, 39 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2009-09-19 Eric Blake <ebb9@byu.net> + openat: fix fstatat bugs on Solaris 9 + * lib/fstatat.c (rpl_fstatat): Copy recent fixes from lstat and + stat. + * doc/posix-functions/fstatat.texi (fstatat): Document this. + test-unlinkat: enhance test, to expose Solaris 9 bug * tests/test-unlink.c (main): Factor guts... * tests/test-unlink.h (test_rmdir_func): ...into new file.
--- a/doc/posix-functions/fstatat.texi +++ b/doc/posix-functions/fstatat.texi @@ -13,8 +13,22 @@ 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 +On some platforms, @code{fstatat(fd,"file/",buf,flag)} succeeds instead of +failing with @code{ENOTDIR}. +Solaris 9. +@item +For symlinks, when the argument ends in a slash, some platforms don't +dereference the argument: +Solaris 9. @end itemize Portability problems not fixed by Gnulib: @itemize +@item +On platforms where @code{off_t} is a 32-bit type, @code{fstatat} may +not correctly report the size of files or block devices larger than 2 +GB. The fix is to use the @code{AC_SYS_LARGEFILE} macro. +@item +On Windows platforms (excluding Cygwin), @code{st_ino} is always 0. @end itemize
--- a/lib/fstatat.c +++ b/lib/fstatat.c @@ -28,31 +28,37 @@ #undef fstatat /* fstatat should always follow symbolic links that end in /, but on - Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. This is - the same problem that lstat.c addresses, so solve it in a similar - way. */ + Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. + Likewise, trailing slash on a non-directory should be an error. + These are the same problems that lstat.c and stat.c address, so + solve it in a similar way. */ int rpl_fstatat (int fd, char const *file, struct stat *st, int flag) { int result = fstatat (fd, file, st, flag); + size_t len; - if (result == 0 && (flag & AT_SYMLINK_NOFOLLOW) && S_ISLNK (st->st_mode) - && file[strlen (file) - 1] == '/') + if (result != 0) + return result; + len = strlen (file); + if (flag & AT_SYMLINK_NOFOLLOW) { - /* FILE refers to a symbolic link and the name ends with a slash. - Get info about the link's referent. */ - result = fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); - if (result == 0 && ! S_ISDIR (st->st_mode)) + /* Fix lstat behavior. */ + if (file[len - 1] != '/' || S_ISDIR (st->st_mode)) + return 0; + if (!S_ISLNK (st->st_mode)) { - /* fstatat succeeded and FILE references a non-directory. - But it was specified via a name including a trailing - slash. Fail with errno set to ENOTDIR to indicate the - contradiction. */ errno = ENOTDIR; return -1; } + result = fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); } - + /* Fix stat behavior. */ + if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/') + { + errno = ENOTDIR; + return -1; + } return result; }