2020-12-24 Paul Eggert <eggert@cs.ucla.edu>
+ 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.
safe. */
if (mode == F_OK)
- return stat (file, &stats);
+ {
+ int result = stat (file, &stats);
+ return result != 0 && errno == EOVERFLOW ? 0 : result;
+ }
else
{
int result;
/* 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. */
{
struct stat statbuf;
- if (stat (name, &statbuf) < 0)
+ if (stat (name, &statbuf) == -1 && errno != EOVERFLOW)
return -1;
return acl_nontrivial (count, entries);
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);
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;
if (p)
{
*p = '\0';
- if (stat (dir, &st) == -1)
+ if (stat (dir, &st) != 0 && errno != EOVERFLOW)
{
int saved_errno = errno;
free (dir);
|| (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;
}
if (len && name[len - 1] == '/')
{
struct stat st;
- if (stat (name, &st) == 0)
+ if (stat (name, &st) == 0 || errno == EOVERFLOW)
errno = EEXIST;
return -1;
}
if (len && name[len - 1] == '/')
{
struct stat st;
- if (stat (name, &st) == 0)
+ if (stat (name, &st) == 0 || errno == EOVERFLOW)
errno = EEXIST;
return -1;
}
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);
if (len && name[len - 1] == '/')
{
struct stat st;
- if (lstat (name, &st) == 0)
+ if (lstat (name, &st) == 0 || errno == EOVERFLOW)
errno = EEXIST;
return -1;
}
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;
}
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);
return -1;
}
free (short_name);
+ result = 0;
}
}
if (!result)
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);
return -1;
}
free (short_name);
+ result = 0;
}
}
if (!result)
{
struct stat buf;
- if (stat (name, &buf) < 0)
+ if (stat (name, &buf) == -1 && errno != EOVERFLOW)
return -1;
}
# endif /* REPLACE_FUNC_UTIME_FILE */