bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

symlinkat: Fix trailing slash handling


From: Bruno Haible
Subject: symlinkat: Fix trailing slash handling
Date: Tue, 05 Jan 2021 05:58:50 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-197-generic; KDE/5.18.0; x86_64; ; )

In the symlink() replacement, the trailing slash handling uses lstat()
to test whether the designated file exists:

      struct stat st;
      if (lstat (name, &st) == 0 || errno == EOVERFLOW)
        errno = EEXIST;
      return -1;

By symmetry, in the symlinkat() handling, it should use lstatat() (as
defined in openat.h), i.e. fstatat() with AT_SYMLINK_NOFOLLOW flag.

(The POSIX spec
<https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html>
is not very clear to me on this point.)

Thus this patch. Tested on AIX (which is the platform for which this
workaround was implemented in 2014).


2021-01-04  Bruno Haible  <bruno@clisp.org>

        symlinkat: Fix trailing slash handling.
        * lib/symlinkat.c (rpl_symlinkat): Don't follow symlinks during the
        trailing slash handling.
        * modules/symlinkat (Depends-on): Update conditions.

diff --git a/lib/symlinkat.c b/lib/symlinkat.c
index 404fa65..58ddb89 100644
--- a/lib/symlinkat.c
+++ b/lib/symlinkat.c
@@ -27,6 +27,7 @@
 #if HAVE_SYMLINKAT
 # undef symlinkat
 
+#include <fcntl.h>
 #include <sys/stat.h>
 #include <string.h>
 
@@ -38,7 +39,8 @@ rpl_symlinkat (char const *contents, int fd, char const *name)
   if (len && name[len - 1] == '/')
     {
       struct stat st;
-      if (fstatat (fd, name, &st, 0) == 0 || errno == EOVERFLOW)
+      if (fstatat (fd, name, &st, AT_SYMLINK_NOFOLLOW) == 0
+          || errno == EOVERFLOW)
         errno = EEXIST;
       return -1;
     }
diff --git a/modules/symlinkat b/modules/symlinkat
index 16d0fcc..03b6a40 100644
--- a/modules/symlinkat
+++ b/modules/symlinkat
@@ -9,10 +9,10 @@ m4/symlinkat.m4
 Depends-on:
 unistd
 extensions
+fcntl-h         [test $HAVE_SYMLINKAT = 0 || test $REPLACE_SYMLINKAT = 1]
 at-internal     [test $HAVE_SYMLINKAT = 0]
 errno           [test $HAVE_SYMLINKAT = 0]
 fchdir          [test $HAVE_SYMLINKAT = 0]
-fcntl-h         [test $HAVE_SYMLINKAT = 0]
 filename        [test $HAVE_SYMLINKAT = 0]
 openat-die      [test $HAVE_SYMLINKAT = 0]
 openat-h        [test $HAVE_SYMLINKAT = 0]




reply via email to

[Prev in Thread] Current Thread [Next in Thread]