diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2022-06-12 13:46:52 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2022-06-12 13:47:12 -0700 |
commit | d682f8de7f9d384f4cfc482a3ba2960329a8db21 (patch) | |
tree | 65d04a8b5e462b2b4939b3addf0982de988a1bac /lib/lchmod.c | |
parent | 2cd86e5891af0cdb7d88d076e9613e5c8475e1ee (diff) | |
download | gnulib-d682f8de7f9d384f4cfc482a3ba2960329a8db21.tar.gz |
fchmodat: port better to MS-Windows etc.
MS-Windows problem reported by Bruno Haible in:
https://lists.gnu.org/r/bug-gnulib/2022-06/msg00041.html
Although I don’t use MS-Windows I see some related fstatat etc.
problems and am trying to fix them with this further patch.
* lib/fchmodat.c (fchmodat):
* lib/lchmod.c (lchmod):
* lib/lchown.c (lchown)
[!HAVE_LCHOWN && HAVE_CHOWN && !CHOWN_MODIFIES_SYMLINK]:
* lib/renameatu.c (renameatu)
[HAVE_RENAME && RENAME_TRAILING_SLASH_SOURCE_BUG]:
Use readlinkat/readlink instead of fstatat/lstat to test merely
whether a string names a symlink, as this avoids problems
with EOVERFLOW. Also, I hope it works around the MS-Windows
issues that Bruno noted.
* m4/fchmodat.m4 (gl_PREREQ_FCHMODAT):
Check for readlinkat, not lchmod.
* m4/lchmod.m4 (gl_FUNC_LCHMOD): Do not require AC_CANONICAL_HOST
or check for lstat.
(gl_PREREQ_LCHMOD): Check for readlink.
* modules/lchown (Depends-on): Add readlink. Do not depend on
lstat merely because !HAVE_LCHOWN.
* modules/renameatu (Depends-on): Add fstatat, readlinkat.
Diffstat (limited to 'lib/lchmod.c')
-rw-r--r-- | lib/lchmod.c | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/lib/lchmod.c b/lib/lchmod.c index b4cc0a8176..f21bf7f652 100644 --- a/lib/lchmod.c +++ b/lib/lchmod.c @@ -45,7 +45,10 @@ int lchmod (char const *file, mode_t mode) { -#ifdef O_PATH +#if HAVE_READLINK + 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 avoid a failure if the file is not readable. @@ -55,8 +58,7 @@ lchmod (char const *file, mode_t mode) return fd; int err; - char buf[1]; - if (0 <= readlinkat (fd, "", buf, sizeof buf)) + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) err = EOPNOTSUPP; else if (errno == EINVAL) { @@ -73,16 +75,11 @@ lchmod (char const *file, mode_t mode) errno = err; if (0 <= err) return err == 0 ? 0 : -1; -#endif +# endif /* O_PATH + /proc is not supported. */ -#if HAVE_LSTAT - struct stat st; - int lstat_result = lstat (file, &st); - if (lstat_result != 0) - return lstat_result; - if (S_ISLNK (st.st_mode)) + if (0 <= readlink (file, readlink_buf, sizeof readlink_buf)) { errno = EOPNOTSUPP; return -1; |