[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Don't interpret EOVERFLOW to mean nonexistence
From: |
Paul Eggert |
Subject: |
[PATCH] Don't interpret EOVERFLOW to mean nonexistence |
Date: |
Sun, 30 Jul 2017 13:08:06 -0700 |
* lib/fts.c (fts_stat): If lstat fails, report its errno, which
may be EOVERFLOW; this is likely more useful than reporting the
stat errno.
* lib/glob.c (link_stat): Rename from link_exists2_p and
return -1/0 instead of 0/1. Caller changed.
* lib/glob.c (link_exists_p):
* lib/renameat2.c (rename_noreplace, renameat2):
* lib/tempname.c (try_nocreate):
If errno == EOVERFLOW then the directory entry exists, so do not
act as if it does not exist.
---
ChangeLog | 12 ++++++++++++
lib/canonicalize-lgpl.c | 2 ++
lib/fts.c | 4 +---
lib/glob.c | 28 ++++++++++++++++------------
lib/renameat2.c | 4 ++--
lib/tempname.c | 2 +-
6 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a6909f6..5ef4b1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2017-07-30 Paul Eggert <address@hidden>
+ Don't interpret EOVERFLOW to mean nonexistence
+ * lib/fts.c (fts_stat): If lstat fails, report its errno, which
+ may be EOVERFLOW; this is likely more useful than reporting the
+ stat errno.
+ * lib/glob.c (link_stat): Rename from link_exists2_p and
+ return -1/0 instead of 0/1. Caller changed.
+ * lib/glob.c (link_exists_p):
+ * lib/renameat2.c (rename_noreplace, renameat2):
+ * lib/tempname.c (try_nocreate):
+ If errno == EOVERFLOW then the directory entry exists, so do not
+ act as if it does not exist.
+
backup-rename: new module
It is like backupfile, except it avoids some race conditions,
and it does not output to stderr or exit.
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index 34b3711..f76ea4c 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -270,6 +270,8 @@ __realpath (const char *name, char *resolved)
#endif
*dest = '\0';
+ /* FIXME: if lstat fails with errno == EOVERFILE,
+ the entry exists. */
#ifdef _LIBC
if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
#else
diff --git a/lib/fts.c b/lib/fts.c
index 790f71c..a870054 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1813,7 +1813,6 @@ internal_function
fts_stat(FTS *sp, register FTSENT *p, bool follow)
{
struct stat *sbp = p->fts_statp;
- int saved_errno;
if (p->fts_level == FTS_ROOTLEVEL && ISSET(FTS_COMFOLLOW))
follow = true;
@@ -1825,13 +1824,12 @@ fts_stat(FTS *sp, register FTSENT *p, bool follow)
*/
if (ISSET(FTS_LOGICAL) || follow) {
if (stat(p->fts_accpath, sbp)) {
- saved_errno = errno;
if (errno == ENOENT
&& lstat(p->fts_accpath, sbp) == 0) {
__set_errno (0);
return (FTS_SLNONE);
}
- p->fts_errno = saved_errno;
+ p->fts_errno = errno;
goto err;
}
} else if (fstatat(sp->fts_cwd_fd, p->fts_accpath, sbp,
diff --git a/lib/glob.c b/lib/glob.c
index 3b3194a..d061017 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -1531,12 +1531,12 @@ weak_alias (__glob_pattern_p, glob_pattern_p)
allocated with alloca to be recycled. */
static int
__attribute_noinline__
-link_exists2_p (const char *dir, size_t dirlen, const char *fname,
- glob_t *pglob
+link_stat (const char *dir, size_t dirlen, const char *fname,
+ glob_t *pglob
# if !defined _LIBC && !HAVE_FSTATAT
- , int flags
+ , int flags
# endif
- )
+ )
{
size_t fnamelen = strlen (fname);
char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
@@ -1549,10 +1549,10 @@ link_exists2_p (const char *dir, size_t dirlen, const
char *fname,
if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
{
struct_stat64 st64;
- return __stat64 (fullname, &st64) == 0;
+ return __stat64 (fullname, &st64);
}
# endif
- return (*pglob->gl_stat) (fullname, &st) == 0;
+ return (*pglob->gl_stat) (fullname, &st);
}
/* Return true if DIR/FNAME exists. */
@@ -1560,19 +1560,21 @@ static int
link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
glob_t *pglob, int flags)
{
+ int status;
# if defined _LIBC || HAVE_FSTATAT
if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
- return link_exists2_p (dir, dirlen, fname, pglob);
+ status = link_stat (dir, dirlen, fname, pglob);
else
{
/* dfd cannot be -1 here, because dirfd never returns -1 on
glibc, or on hosts that have fstatat. */
struct_stat64 st64;
- return __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0;
+ status = __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0);
}
# else
- return link_exists2_p (dir, dirlen, fname, pglob, flags);
+ status = link_stat (dir, dirlen, fname, pglob, flags);
# endif
+ return status == 0 || errno == EOVERFLOW;
}
#endif /* !defined GLOB_ONLY_P */
@@ -1643,9 +1645,11 @@ glob_in_dir (const char *pattern, const char *directory,
int flags,
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
"/", 1),
pattern, patlen + 1);
- if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
- ? (*pglob->gl_stat) (fullname, &ust.st)
- : __stat64 (fullname, &ust.st64)) == 0)
+ if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
+ ? (*pglob->gl_stat) (fullname, &ust.st)
+ : __stat64 (fullname, &ust.st64))
+ == 0)
+ || errno == EOVERFLOW)
/* We found this file to be existing. Now tell the rest
of the function to copy this name into the result. */
flags |= GLOB_NOCHECK;
diff --git a/lib/renameat2.c b/lib/renameat2.c
index 4f9e3d1..60b721c 100644
--- a/lib/renameat2.c
+++ b/lib/renameat2.c
@@ -53,7 +53,7 @@ rename_noreplace (char const *src, char const *dst)
{
/* This has a race between the call to lstat and the call to rename. */
struct stat st;
- return (lstat (dst, &st) == 0 ? errno_fail (EEXIST)
+ return (lstat (dst, &st) == 0 || errno == EOVERFLOW ? errno_fail (EEXIST)
: errno == ENOENT ? rename (src, dst)
: -1);
}
@@ -103,7 +103,7 @@ renameat2 (int fd1, char const *src, int fd2, char const
*dst,
{
/* This has a race between the call to lstatat and the calls to
renameat below. */
- if (lstatat (fd2, dst, &dst_st) == 0)
+ if (lstatat (fd2, dst, &dst_st) == 0 || errno == EOVERFLOW)
return errno_fail (EEXIST);
if (errno != ENOENT)
return -1;
diff --git a/lib/tempname.c b/lib/tempname.c
index 2cd9032..9c4a3c2 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -279,7 +279,7 @@ try_nocreate (char *tmpl, void *flags _GL_UNUSED)
{
struct_stat64 st;
- if (__lxstat64 (_STAT_VER, tmpl, &st) == 0)
+ if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW)
__set_errno (EEXIST);
return errno == ENOENT ? 0 : -1;
}
--
2.7.4
- [PATCH] Don't interpret EOVERFLOW to mean nonexistence,
Paul Eggert <=