>From 65d54010990b8c417cd0584b338edc5ead82cbf7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 24 Dec 2020 11:38:48 -0800 Subject: [PATCH 03/10] stat failing with EOVERFLOW implies existence * lib/euidaccess.c (euidaccess): * lib/file-has-acl.c (file_has_acl): * lib/link.c (link, rpl_link): * lib/mkdir.c (rpl_mkdir): * lib/mkfifo.c (rpl_mkfifo): * lib/mknod.c (rpl_mknod): * lib/ptsname_r.c (__ptsname_r): * lib/symlink.c (rpl_symlink): * lib/symlinkat.c (rpl_symlinkat): * lib/unlink.c (rpl_unlink): * lib/unlinkat.c (rpl_unlinkat): * lib/utime.c (utime): If stat fails with EOVERFLOW the file exists, so treat it that way in file-existence tests that do not need struct stat values. --- ChangeLog | 16 ++++++++++++++++ lib/euidaccess.c | 9 ++++++--- lib/file-has-acl.c | 2 +- lib/link.c | 6 +++--- lib/mkdir.c | 2 +- lib/mkfifo.c | 2 +- lib/mknod.c | 2 +- lib/ptsname_r.c | 2 +- lib/symlink.c | 2 +- lib/symlinkat.c | 2 +- lib/unlink.c | 3 ++- lib/unlinkat.c | 3 ++- lib/utime.c | 2 +- 13 files changed, 37 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0cad381a..3d2186fb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2020-12-24 Paul Eggert + stat failing with EOVERFLOW implies existence + * lib/euidaccess.c (euidaccess): + * lib/file-has-acl.c (file_has_acl): + * lib/link.c (link, rpl_link): + * lib/mkdir.c (rpl_mkdir): + * lib/mkfifo.c (rpl_mkfifo): + * lib/mknod.c (rpl_mknod): + * lib/ptsname_r.c (__ptsname_r): + * lib/symlink.c (rpl_symlink): + * lib/symlinkat.c (rpl_symlinkat): + * lib/unlink.c (rpl_unlink): + * lib/unlinkat.c (rpl_unlinkat): + * lib/utime.c (utime): + If stat fails with EOVERFLOW the file exists, so treat it that way + in file-existence tests that do not need struct stat values. + canonicalize-lgpl: remove freea macro * lib/canonicalize-lgpl.c (freea) [_LIBC]: Remove; not needed. diff --git a/lib/euidaccess.c b/lib/euidaccess.c index b352123ae..a32e3366e 100644 --- a/lib/euidaccess.c +++ b/lib/euidaccess.c @@ -107,7 +107,10 @@ euidaccess (const char *file, int mode) safe. */ if (mode == F_OK) - return stat (file, &stats); + { + int result = stat (file, &stats); + return result != 0 && errno == EOVERFLOW ? 0 : result; + } else { int result; @@ -142,8 +145,8 @@ euidaccess (const char *file, int mode) /* If we are not set-uid or set-gid, access does the same. */ return access (file, mode); - if (stat (file, &stats) != 0) - return -1; + if (stat (file, &stats) == -1) + return mode == F_OK && errno == EOVERFLOW ? 0 : -1; /* The super-user can read and write any file, and execute any file that anyone can execute. */ diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index c667ae9d2..4adb7f6f1 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -353,7 +353,7 @@ file_has_acl (char const *name, struct stat const *sb) { struct stat statbuf; - if (stat (name, &statbuf) < 0) + if (stat (name, &statbuf) == -1 && errno != EOVERFLOW) return -1; return acl_nontrivial (count, entries); diff --git a/lib/link.c b/lib/link.c index 797cdf8b9..3c0c341d5 100644 --- a/lib/link.c +++ b/lib/link.c @@ -107,7 +107,7 @@ link (const char *file1, const char *file2) char *p = strchr (dir, '\0'); while (dir < p && (*--p != '/' && *p != '\\')); *p = '\0'; - if (p != dir && stat (dir, &st) == -1) + if (p != dir && stat (dir, &st) != 0 && errno != EOVERFLOW) { int saved_errno = errno; free (dir); @@ -181,7 +181,7 @@ rpl_link (char const *file1, char const *file2) struct stat st; /* Don't allow IRIX to dereference dangling file2 symlink. */ - if (!lstat (file2, &st)) + if (lstat (file2, &st) == 0 || errno == EOVERFLOW) { errno = EEXIST; return -1; @@ -218,7 +218,7 @@ rpl_link (char const *file1, char const *file2) if (p) { *p = '\0'; - if (stat (dir, &st) == -1) + if (stat (dir, &st) != 0 && errno != EOVERFLOW) { int saved_errno = errno; free (dir); diff --git a/lib/mkdir.c b/lib/mkdir.c index c0d4b6165..386344fcd 100644 --- a/lib/mkdir.c +++ b/lib/mkdir.c @@ -77,7 +77,7 @@ rpl_mkdir (char const *dir, mode_t mode maybe_unused) || (last[1] == '.' && last[2] == '\0'))) { struct stat st; - if (stat (tmp_dir, &st) == 0) + if (stat (tmp_dir, &st) == 0 || errno == EOVERFLOW) errno = EEXIST; return -1; } diff --git a/lib/mkfifo.c b/lib/mkfifo.c index 706297c0a..952ffc0fe 100644 --- a/lib/mkfifo.c +++ b/lib/mkfifo.c @@ -48,7 +48,7 @@ rpl_mkfifo (char const *name, mode_t mode) if (len && name[len - 1] == '/') { struct stat st; - if (stat (name, &st) == 0) + if (stat (name, &st) == 0 || errno == EOVERFLOW) errno = EEXIST; return -1; } diff --git a/lib/mknod.c b/lib/mknod.c index 4e778fa15..1de2794c6 100644 --- a/lib/mknod.c +++ b/lib/mknod.c @@ -56,7 +56,7 @@ rpl_mknod (char const *name, mode_t mode, dev_t dev) if (len && name[len - 1] == '/') { struct stat st; - if (stat (name, &st) == 0) + if (stat (name, &st) == 0 || errno == EOVERFLOW) errno = EEXIST; return -1; } diff --git a/lib/ptsname_r.c b/lib/ptsname_r.c index 12b8e66f0..99d1701dc 100644 --- a/lib/ptsname_r.c +++ b/lib/ptsname_r.c @@ -198,7 +198,7 @@ __ptsname_r (int fd, char *buf, size_t buflen) buf[sizeof (_PATH_DEV) - 1] = 't'; # endif - if (__stat (buf, &st) < 0) + if (__stat (buf, &st) < 0 && errno != EOVERFLOW) return errno; __set_errno (save_errno); diff --git a/lib/symlink.c b/lib/symlink.c index e7dbd184a..b1196b9ee 100644 --- a/lib/symlink.c +++ b/lib/symlink.c @@ -36,7 +36,7 @@ rpl_symlink (char const *contents, char const *name) if (len && name[len - 1] == '/') { struct stat st; - if (lstat (name, &st) == 0) + if (lstat (name, &st) == 0 || errno == EOVERFLOW) errno = EEXIST; return -1; } diff --git a/lib/symlinkat.c b/lib/symlinkat.c index 5ce2fc9d5..2e0ff9a79 100644 --- a/lib/symlinkat.c +++ b/lib/symlinkat.c @@ -38,7 +38,7 @@ rpl_symlinkat (char const *contents, int fd, char const *name) if (len && name[len - 1] == '/') { struct stat st; - if (fstatat (fd, name, &st, 0) == 0) + if (fstatat (fd, name, &st, 0) == 0 || errno == EOVERFLOW) errno = EEXIST; return -1; } diff --git a/lib/unlink.c b/lib/unlink.c index ba5f6269c..58b1e9001 100644 --- a/lib/unlink.c +++ b/lib/unlink.c @@ -63,7 +63,7 @@ rpl_unlink (char const *name) can't delete a directory via a symlink. */ struct stat st; result = lstat (name, &st); - if (result == 0) + if (result == 0 || errno == EOVERFLOW) { /* Trailing NUL will overwrite the trailing slash. */ char *short_name = malloc (len); @@ -79,6 +79,7 @@ rpl_unlink (char const *name) return -1; } free (short_name); + result = 0; } } if (!result) diff --git a/lib/unlinkat.c b/lib/unlinkat.c index 442368641..02ac851ee 100644 --- a/lib/unlinkat.c +++ b/lib/unlinkat.c @@ -59,7 +59,7 @@ rpl_unlinkat (int fd, char const *name, int flag) directory. */ struct stat st; result = lstatat (fd, name, &st); - if (result == 0) + if (result == 0 || errno == EOVERFLOW) { /* Trailing NUL will overwrite the trailing slash. */ char *short_name = malloc (len); @@ -78,6 +78,7 @@ rpl_unlinkat (int fd, char const *name, int flag) return -1; } free (short_name); + result = 0; } } if (!result) diff --git a/lib/utime.c b/lib/utime.c index 6de8adbb3..bf7d7c534 100644 --- a/lib/utime.c +++ b/lib/utime.c @@ -276,7 +276,7 @@ utime (const char *name, const struct utimbuf *ts) { struct stat buf; - if (stat (name, &buf) < 0) + if (stat (name, &buf) == -1 && errno != EOVERFLOW) return -1; } # endif /* REPLACE_FUNC_UTIME_FILE */ -- 2.27.0