+2025-08-14 Bruno Haible <bruno@clisp.org>
+
+ fchmodat: Use issymlinkat.
+ * lib/fchmodat.c (fchmodat): Use issymlinkat instead of readlinkat.
+ * modules/fchmodat (Depends-on): Add issymlinkat, openat.
+
2025-08-14 Bruno Haible <bruno@clisp.org>
lchmod: Use issymlink, issymlinkat.
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
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);
/* 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;
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]