diff options
author | Pádraig Brady <P@draigBrady.com> | 2015-05-31 03:08:52 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2015-05-31 03:44:51 +0100 |
commit | 8c9cfa07e6eb6a3365a516c90568fc6c5f3fcd34 (patch) | |
tree | d17818b3b9621dfb72add4e13ef646cfa487fbe0 /lib/readlinkat.c | |
parent | 04e445830cb607c69888534d88e6f1f6eb01839e (diff) | |
download | gnulib-8c9cfa07e6eb6a3365a516c90568fc6c5f3fcd34.tar.gz |
readlinkat: avoid OS X 10.10 trailing slash bug
* doc/posix-functions/readlink.texi: Mention that OS X 10.10
has this bug.
* doc/posix-functions/readlinkat.texi: Likewise. Also mention
that OS X 10.10 has this function.
* lib/readlinkat.c (rpl_readlinkat): Handle the trailing slash bug,
as done for readlink().
* m4/readlinkat.m4 (gl_FUNC_READLINKAT): Check for the readlink()
trailing slash bug, and assume readlinkat() has the same issue.
Also fix a typo where $gl_cv_decl_readlink_works was tested,
rather than the correct $gl_cv_decl_readlinkat_works.
Diffstat (limited to 'lib/readlinkat.c')
-rw-r--r-- | lib/readlinkat.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/readlinkat.c b/lib/readlinkat.c index f4826f9202..c91cf0e820 100644 --- a/lib/readlinkat.c +++ b/lib/readlinkat.c @@ -18,7 +18,10 @@ #include <config.h> +#include <errno.h> #include <unistd.h> +#include <string.h> +#include <sys/stat.h> #if HAVE_READLINKAT @@ -27,6 +30,21 @@ 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); } |