X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/f5ebe84d75bb75156db9e2e0a7ab356941b4ea75..eb0f65b4fbbea60100b53cb40a1d7138d47ad0d2:/lib/readlinkat.c 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 +#include #include +#include +#include #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); }