+2025-08-14 Bruno Haible <bruno@clisp.org>
+
+ lchown: Use issymlink.
+ * lib/lchown.c (lchown): Use issymlink instead of readlink.
+ * modules/lchown (Depends-on): Remove readlink. Add issymlink.
+
2025-08-14 Bruno Haible <bruno@clisp.org>
chown: Use issymlink.
{
# if HAVE_CHOWN
# if ! CHOWN_MODIFIES_SYMLINK
- char readlink_buf[1];
-
- if (0 <= readlink (file, readlink_buf, sizeof readlink_buf))
+ if (issymlink (file) > 0)
{
errno = EOPNOTSUPP;
return -1;
{
/* Prefer readlink to lstat+S_ISLNK, to avoid EOVERFLOW issues
in the common case where FILE is a non-symlink. */
- char linkbuf[1];
- int r = readlink (file, linkbuf, 1);
- if (r < 0)
- return errno == EINVAL ? chown (file, uid, gid) : r;
+ int ret = issymlink (file);
+ if (ret < 0)
+ return -1;
+ if (ret == 0)
+ /* FILE is not a symlink. */
+ return chown (file, uid, gid);
/* Later code can use the status, so get it if possible. */
- r = lstat (file, &st);
- if (r < 0)
- return r;
- stat_valid = true;
+ ret = lstat (file, &st);
+ if (ret < 0)
+ return -1;
/* An easy check: did FILE change from a symlink to a non-symlink? */
if (!S_ISLNK (st.st_mode))
return chown (file, uid, gid);
+
+ stat_valid = true;
}
# endif
Depends-on:
unistd-h
-readlink [test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1]
+issymlink [test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1]
chown [test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1]
errno-h [test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1]
bool [test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1]