diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2015-07-04 17:17:09 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2015-07-04 17:17:09 +0300 |
commit | cc78bdc31749e9754120ae5a9d4849f4832b40a4 (patch) | |
tree | 4f9e3f2064e56651ed8d41ae9d8ce8b08fc5241b /lib/readlinkat.c | |
parent | 8425beb209e6fedf50bcdd934ced14dfa0d7b596 (diff) | |
parent | 71cd8e3a743046573744123777061b64881bf372 (diff) | |
download | coreutils-cc78bdc31749e9754120ae5a9d4849f4832b40a4.tar.gz |
Merge tag 'upstream/8.24'
Upstream version 8.24
Conflicts:
INSTALL
Makefile.in
aclocal.m4
build-aux/config.guess
build-aux/config.rpath
build-aux/config.sub
build-aux/depcomp
build-aux/missing
build-aux/test-driver
build-aux/texinfo.tex
doc/coreutils.info
doc/stamp-vti
doc/version.texi
gnulib-tests/Makefile.in
po/Makefile.in.in
Diffstat (limited to 'lib/readlinkat.c')
-rw-r--r-- | lib/readlinkat.c | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/lib/readlinkat.c b/lib/readlinkat.c index c8a60500..c91cf0e8 100644 --- a/lib/readlinkat.c +++ b/lib/readlinkat.c @@ -1,5 +1,5 @@ /* Read a symlink relative to an open directory. - Copyright (C) 2009-2014 Free Software Foundation, Inc. + Copyright (C) 2009-2015 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 @@ -18,7 +18,37 @@ #include <config.h> +#include <errno.h> #include <unistd.h> +#include <string.h> +#include <sys/stat.h> + +#if HAVE_READLINKAT + +# undef readlinkat + +ssize_t +rpl_readlinkat (int fd, char const *file, char *buf, size_t len) +{ +# if READLINK_TRAILING_SLASH_BUG + size_t file_len = strlen (file); + if (file_len && file[file_len - 1] == '/') + { + /* Even if FILE without the slash is a symlink to a directory, + both lstat() and stat() must resolve the trailing slash to + the directory rather than the symlink. We can therefore + safely use stat() to distinguish between EINVAL and + ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */ + struct stat st; + if (stat (file, &st) == 0) + errno = EINVAL; + return -1; + } +# endif /* READLINK_TRAILING_SLASH_BUG */ + return readlinkat (fd, file, buf, len); +} + +#else /* Gnulib provides a readlink stub for mingw; use it for distinction between EINVAL and ENOENT, rather than always failing with ENOSYS. */ @@ -34,14 +64,16 @@ then readlink/restore_cwd. If either the save_cwd or the restore_cwd fails, then give a diagnostic and exit nonzero. */ -#define AT_FUNC_NAME readlinkat -#define AT_FUNC_F1 readlink -#define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len -#define AT_FUNC_POST_FILE_ARGS , buf, len -#define AT_FUNC_RESULT ssize_t -#include "at-func.c" -#undef AT_FUNC_NAME -#undef AT_FUNC_F1 -#undef AT_FUNC_POST_FILE_PARAM_DECLS -#undef AT_FUNC_POST_FILE_ARGS -#undef AT_FUNC_RESULT +# define AT_FUNC_NAME readlinkat +# define AT_FUNC_F1 readlink +# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len +# define AT_FUNC_POST_FILE_ARGS , buf, len +# define AT_FUNC_RESULT ssize_t +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS +# undef AT_FUNC_RESULT + +#endif |