bug-gnulib
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]