Bruno added the issymlink and issymlinkat inline functions to Gnulib to make code like this easier to understand:
char dummy[1]; if (0 <= readlink (dir, dummy, 1)) { /* Handle symbolic links here. */ } This patch converts the few cases used in coreutils. Will push tomorrow, unless there is any objections. Collin
>From 5fdb6e1b9b3096a6a5708d435af2bb82049cdd0b Mon Sep 17 00:00:00 2001 Message-ID: <5fdb6e1b9b3096a6a5708d435af2bb82049cdd0b.1756877797.git.collin.fu...@gmail.com> From: Collin Funk <collin.fu...@gmail.com> Date: Tue, 2 Sep 2025 22:25:46 -0700 Subject: [PATCH] maint: prefer issymlink to readlink with a small buffer * bootstrap.conf (gnulib_modules): Add issymlink and issymlinkat. * src/copy.c: Include issymlink.h. (copy_reg): Use issymlink instead of readlinkat. * src/rmdir.c: Include issymlink.h. (main): Use issymlink instead of readlink. * src/tail.c: Include issymlink.h. (recheck, any_symlinks): Use issymlink instead of readlink. * src/test.c: Include issymlink.h. (unary_operator): Use issymlink instead of readlink. --- bootstrap.conf | 2 ++ src/copy.c | 6 +++--- src/rmdir.c | 4 ++-- src/tail.c | 7 +++---- src/test.c | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index 49fcf30f3..7d09752bc 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -152,6 +152,8 @@ gnulib_modules=" isapipe isatty isblank + issymlink + issymlinkat largefile lchmod ldtoastr diff --git a/src/copy.c b/src/copy.c index 73ded6857..e89f376f2 100644 --- a/src/copy.c +++ b/src/copy.c @@ -49,6 +49,7 @@ #include "hashcode-file.h" #include "ignore-value.h" #include "ioblksize.h" +#include "issymlink.h" #include "quote.h" #include "renameatu.h" #include "root-uid.h" @@ -1444,7 +1445,7 @@ copy_reg (char const *src_name, char const *dst_name, /* When trying to copy through a dangling destination symlink, the above open fails with EEXIST. If that happens, and - readlinkat shows that it is a symlink, then we + issymlinkat shows that it is a symlink, then we have a problem: trying to resolve this dangling symlink to a directory/destination-entry pair is fundamentally racy, so punt. If x->open_dangling_dest_symlink is set (cp sets @@ -1454,8 +1455,7 @@ copy_reg (char const *src_name, char const *dst_name, only when copying, i.e., not in move_mode. */ if (dest_desc < 0 && dest_errno == EEXIST && ! x->move_mode) { - char dummy[1]; - if (0 <= readlinkat (dst_dirfd, dst_relname, dummy, sizeof dummy)) + if (issymlinkat (dst_dirfd, dst_relname) == 1) { if (x->open_dangling_dest_symlink) { diff --git a/src/rmdir.c b/src/rmdir.c index fead0bb19..9ca3f7ed1 100644 --- a/src/rmdir.c +++ b/src/rmdir.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include "system.h" +#include "issymlink.h" #include "prog-fprintf.h" /* The official name of this program (e.g., no 'g' prefix). */ @@ -269,8 +270,7 @@ main (int argc, char **argv) /* Ensure the last component was a symlink. */ char *dir_arg = xstrdup (dir); strip_trailing_slashes (dir); - char linkbuf[1]; - if (0 <= readlink (dir, linkbuf, 1)) + if (issymlink (dir) == 1) { error (0, 0, _("failed to remove %s:" diff --git a/src/tail.c b/src/tail.c index ce3a3285b..753963937 100644 --- a/src/tail.c +++ b/src/tail.c @@ -39,6 +39,7 @@ #include "fcntl--.h" #include "iopoll.h" #include "isapipe.h" +#include "issymlink.h" #include "posixver.h" #include "quote.h" #include "stat-size.h" @@ -976,8 +977,7 @@ recheck (struct File_spec *f, bool blocking) affirm (valid_file_spec (f)); - char linkbuf[1]; - if (! disable_inotify && 0 <= readlink (f->name, linkbuf, 1)) + if (! disable_inotify && issymlink (f->name) == 1) { /* Diagnose the edge case where a regular file is changed to a symlink. We avoid inotify with symlinks since @@ -1350,9 +1350,8 @@ any_non_remote_file (const struct File_spec *f, int n_files) static bool any_symlinks (const struct File_spec *f, int n_files) { - char linkbuf[1]; for (int i = 0; i < n_files; i++) - if (0 <= readlink (f[i].name, linkbuf, 1)) + if (issymlink (f[i].name) == 1) return true; return false; } diff --git a/src/test.c b/src/test.c index 0c0785b9c..61bf8b741 100644 --- a/src/test.c +++ b/src/test.c @@ -41,6 +41,7 @@ #include "system.h" #include "assure.h" #include "c-ctype.h" +#include "issymlink.h" #include "quote.h" #include "stat-time.h" #include "strnumcmp.h" @@ -467,8 +468,7 @@ unary_operator (void) case 'h': /* File is a symbolic link? */ unary_advance (); - char linkbuf[1]; - return 0 <= readlink (argv[pos - 1], linkbuf, 1); + return issymlink (argv[pos - 1]) == 1; case 'u': /* File is setuid? */ unary_advance (); -- 2.51.0