2017-07-30 Paul Eggert <eggert@cs.ucla.edu>
+ 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.
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;
*/
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,
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);
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. */
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 */
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;
{
/* 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);
}
{
/* 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;