From: Bruno Haible Date: Thu, 14 Aug 2025 20:18:57 +0000 (+0200) Subject: fchmodat: Use issymlinkat. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f0b2ccec3c91a61515a2bf1d6ac9aa9d1ff30c9;p=thirdparty%2Fgnulib.git fchmodat: Use issymlinkat. * lib/fchmodat.c (fchmodat): Use issymlinkat instead of readlinkat. * modules/fchmodat (Depends-on): Add issymlinkat, openat. --- diff --git a/ChangeLog b/ChangeLog index 9df8c9b99b..386c8bd475 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2025-08-14 Bruno Haible + + fchmodat: Use issymlinkat. + * lib/fchmodat.c (fchmodat): Use issymlinkat instead of readlinkat. + * modules/fchmodat (Depends-on): Add issymlinkat, openat. + 2025-08-14 Bruno Haible lchmod: Use issymlink, issymlinkat. diff --git a/lib/fchmodat.c b/lib/fchmodat.c index eb82e1cafb..57222e58eb 100644 --- a/lib/fchmodat.c +++ b/lib/fchmodat.c @@ -84,8 +84,6 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) if (flags == AT_SYMLINK_NOFOLLOW) { # if HAVE_READLINKAT - char readlink_buf[1]; - # ifdef O_PATH /* Open a file descriptor with O_NOFOLLOW, to make sure we don't follow symbolic links, if /proc is mounted. O_PATH is used to @@ -96,17 +94,20 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) return fd; int err; - if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) - err = EOPNOTSUPP; - else if (errno == EINVAL) - { - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; - } - else - err = errno == ENOENT ? -1 : errno; + { + int ret = issymlinkat (fd, ""); + if (ret > 0) + err = EOPNOTSUPP; + else if (ret == 0) + { + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; + } + else + err = errno == ENOENT ? -1 : errno; + } close (fd); @@ -117,7 +118,7 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) /* O_PATH + /proc is not supported. */ - if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf)) + if (issymlinkat (dir, file) > 0) { errno = EOPNOTSUPP; return -1; diff --git a/modules/fchmodat b/modules/fchmodat index 3afd0efd30..914825c1a4 100644 --- a/modules/fchmodat +++ b/modules/fchmodat @@ -14,6 +14,8 @@ fcntl-h [test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1] unistd-h [test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1] intprops [test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1] c99 [test $REPLACE_FCHMODAT = 1] +issymlinkat [test $REPLACE_FCHMODAT = 1] +openat [test $REPLACE_FCHMODAT = 1] at-internal [test $HAVE_FCHMODAT = 0] chmod [test $HAVE_FCHMODAT = 0] extern-inline [test $HAVE_FCHMODAT = 0]