From eea9688d521634c58efa81130e509f647bbd9ff9 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 9 Mar 2022 13:54:53 -0800 Subject: [PATCH 2/2] statat: now obsolete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lib/openat.h (statat, lstatat): Now deprecated. All uses removed, and replaced with fstatat. * modules/statat: Mark as obsolete, because it’s confusing: it’s not clear whether it should use AT_NO_AUTOMOUNT, which is implied by stat and by lstat, but not by fstatat. * tests/test-statat.c: Disable deprecated-declarations warnings. --- ChangeLog | 8 ++++++++ NEWS | 3 +++ lib/fchownat.c | 2 +- lib/openat.h | 2 ++ lib/renameatu.c | 15 ++++++++------- lib/unlinkat.c | 5 +++-- modules/fchownat | 1 - modules/renameatu | 1 - modules/statat | 7 +++++++ modules/unlinkat | 1 - tests/test-statat.c | 4 ++++ 11 files changed, 36 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 58873a1762..294f6286f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2022-03-09 Paul Eggert + statat: now obsolete + * lib/openat.h (statat, lstatat): Now deprecated. + All uses removed, and replaced with fstatat. + * modules/statat: Mark as obsolete, because it’s confusing: + it’s not clear whether it should use AT_NO_AUTOMOUNT, + which is implied by stat and by lstat, but not by fstatat. + * tests/test-statat.c: Disable deprecated-declarations warnings. + fts: be consistent about AT_NO_AUTOMOUNT * lib/fts.c (fts_stat): Use fstatat with AT_NO_AUTOMOUNT consistently, instead of sometimes using stat (which implies diff --git a/NEWS b/NEWS index c13a115ada..8f90d8e958 100644 --- a/NEWS +++ b/NEWS @@ -66,6 +66,9 @@ User visible incompatible changes Date Modules Changes +2022-03-09 statat This module is deprecated. Use fstatat instead, + to specify whether you want AT_NO_AUTOMOUNT. + 2022-01-05 stack This module now uses idx_t instead of size_t for indexes and counts. diff --git a/lib/fchownat.c b/lib/fchownat.c index c0d97db98b..ff368d356d 100644 --- a/lib/fchownat.c +++ b/lib/fchownat.c @@ -103,7 +103,7 @@ rpl_fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag) struct stat st; if (len && file[len - 1] == '/') { - if (statat (fd, file, &st)) + if (fstatat (fd, file, &st, 0)) return -1; if (flag == AT_SYMLINK_NOFOLLOW) return fchownat (fd, file, owner, group, 0); diff --git a/lib/openat.h b/lib/openat.h index 5c8ff90b80..56919ef8dc 100644 --- a/lib/openat.h +++ b/lib/openat.h @@ -98,12 +98,14 @@ lchmodat (int fd, char const *file, mode_t mode) # define STATAT_INLINE _GL_INLINE # endif +_GL_ATTRIBUTE_DEPRECATED STATAT_INLINE int statat (int fd, char const *name, struct stat *st) { return fstatat (fd, name, st, 0); } +_GL_ATTRIBUTE_DEPRECATED STATAT_INLINE int lstatat (int fd, char const *name, struct stat *st) { diff --git a/lib/renameatu.c b/lib/renameatu.c index 0eb33ab6fd..b4e317d6e5 100644 --- a/lib/renameatu.c +++ b/lib/renameatu.c @@ -133,12 +133,13 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, break; case RENAME_NOREPLACE: - /* This has a race between the call to lstatat and the calls to - renameat below. This lstatat is needed even if RENAME_EXCL + /* This has a race between the call to fstatat and the calls to + renameat below. This fstatat is needed even if RENAME_EXCL is defined, because RENAME_EXCL is buggy on macOS 11.2: renameatx_np (fd, "X", fd, "X", RENAME_EXCL) incorrectly succeeds when X exists. */ - if (lstatat (fd2, dst, &dst_st) == 0 || errno == EOVERFLOW) + if (fstatat (fd2, dst, &dst_st, AT_SYMLINK_NOFOLLOW) == 0 + || errno == EOVERFLOW) return errno_fail (EEXIST); if (errno != ENOENT) return -1; @@ -164,14 +165,14 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, the source does not exist, or if the destination cannot be turned into a directory, give up now. Otherwise, strip trailing slashes before calling rename. */ - if (lstatat (fd1, src, &src_st)) + if (fstatat (fd1, src, &src_st, AT_SYMLINK_NOFOLLOW)) return -1; if (dst_found_nonexistent) { if (!S_ISDIR (src_st.st_mode)) return errno_fail (ENOENT); } - else if (lstatat (fd2, dst, &dst_st)) + else if (fstatat (fd2, dst, &dst_st, AT_SYMLINK_NOFOLLOW)) { if (errno != ENOENT || !S_ISDIR (src_st.st_mode)) return -1; @@ -196,7 +197,7 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, goto out; } strip_trailing_slashes (src_temp); - if (lstatat (fd1, src_temp, &src_st)) + if (fstatat (fd1, src_temp, &src_st, AT_SYMLINK_NOFOLLOW)) { rename_errno = errno; goto out; @@ -213,7 +214,7 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, goto out; } strip_trailing_slashes (dst_temp); - if (lstatat (fd2, dst_temp, &dst_st)) + if (fstatat (fd2, dst_temp, &dst_st, AT_SYMLINK_NOFOLLOW)) { if (errno != ENOENT) { diff --git a/lib/unlinkat.c b/lib/unlinkat.c index eae60074d4..c9ff3ab2f1 100644 --- a/lib/unlinkat.c +++ b/lib/unlinkat.c @@ -58,7 +58,7 @@ rpl_unlinkat (int fd, char const *name, int flag) rule of letting unlink("link-to-dir/") attempt to unlink a directory. */ struct stat st; - result = lstatat (fd, name, &st); + result = fstatat (fd, name, &st, AT_SYMLINK_NOFOLLOW); if (result == 0 || errno == EOVERFLOW) { /* Trailing NUL will overwrite the trailing slash. */ @@ -71,7 +71,8 @@ rpl_unlinkat (int fd, char const *name, int flag) memcpy (short_name, name, len); while (len && ISSLASH (short_name[len - 1])) short_name[--len] = '\0'; - if (len && (lstatat (fd, short_name, &st) || S_ISLNK (st.st_mode))) + if (len && (fstatat (fd, short_name, &st, AT_SYMLINK_NOFOLLOW) + || S_ISLNK (st.st_mode))) { free (short_name); errno = EPERM; diff --git a/modules/fchownat b/modules/fchownat index ea2f2e678c..49c4b18096 100644 --- a/modules/fchownat +++ b/modules/fchownat @@ -19,7 +19,6 @@ lchown [test $HAVE_FCHOWNAT = 0 || test $REPLACE_FCHOWNAT = 1] openat-die [test $HAVE_FCHOWNAT = 0 || test $REPLACE_FCHOWNAT = 1] openat-h [test $HAVE_FCHOWNAT = 0 || test $REPLACE_FCHOWNAT = 1] save-cwd [test $HAVE_FCHOWNAT = 0 || test $REPLACE_FCHOWNAT = 1] -statat [test $REPLACE_FCHOWNAT = 1] configure.ac: gl_FUNC_FCHOWNAT diff --git a/modules/renameatu b/modules/renameatu index 5ce8e47587..e0c1ce3176 100644 --- a/modules/renameatu +++ b/modules/renameatu @@ -13,7 +13,6 @@ extensions fcntl-h filenamecat-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] openat-h [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] -statat [test $REPLACE_RENAMEAT = 1] stdbool [test $REPLACE_RENAMEAT = 1] at-internal [test $HAVE_RENAMEAT = 0] filename [test $HAVE_RENAMEAT = 0] diff --git a/modules/statat b/modules/statat index 074d342bd8..bf274e054d 100644 --- a/modules/statat +++ b/modules/statat @@ -1,6 +1,13 @@ Description: statat() and lstatat() functions: Return info about a file at a directory. +Status: +obsolete + +Notice: +This module is obsolete. Please use fstatat instead, and decide +whether you want AT_NO_AUTOMOUNT in each fstatat call. + Files: lib/statat.c diff --git a/modules/unlinkat b/modules/unlinkat index 0efc1cc1b2..ed11c1e971 100644 --- a/modules/unlinkat +++ b/modules/unlinkat @@ -13,7 +13,6 @@ extensions fcntl-h [test $HAVE_UNLINKAT = 0 || test $REPLACE_UNLINKAT = 1] openat-h [test $HAVE_UNLINKAT = 0 || test $REPLACE_UNLINKAT = 1] sys_stat [test $HAVE_UNLINKAT = 0 || test $REPLACE_UNLINKAT = 1] -statat [test $REPLACE_UNLINKAT = 1] at-internal [test $HAVE_UNLINKAT = 0] errno [test $HAVE_UNLINKAT = 0] fchdir [test $HAVE_UNLINKAT = 0] diff --git a/tests/test-statat.c b/tests/test-statat.c index a573604e1c..f46c3f58b5 100644 --- a/tests/test-statat.c +++ b/tests/test-statat.c @@ -18,6 +18,10 @@ #include "openat.h" +#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #include "signature.h" SIGNATURE_CHECK (statat, int, (int, char const *, struct stat *)); SIGNATURE_CHECK (lstatat, int, (int, char const *, struct stat *)); -- 2.35.1