1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

Update from Gnulib by running admin/merge-gnulib

This commit is contained in:
Paul Eggert 2021-01-22 11:45:38 -08:00
parent 9143eba0c6
commit a900e641fa
51 changed files with 1841 additions and 514 deletions

View file

@ -24,14 +24,40 @@
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "stat-time.h"
#include "timespec.h"
#include "utimens.h"
#if HAVE_UTIMENSAT
#if HAVE_NEARLY_WORKING_UTIMENSAT
/* Use the original utimensat(), but correct the trailing slash handling. */
int
rpl_utimensat (int fd, char const *file, struct timespec const times[2],
int flag)
# undef utimensat
{
size_t len = strlen (file);
if (len && file[len - 1] == '/')
{
struct stat st;
if (fstatat (fd, file, &st, flag & AT_SYMLINK_NOFOLLOW) < 0)
return -1;
if (!S_ISDIR (st.st_mode))
{
errno = ENOTDIR;
return -1;
}
}
return utimensat (fd, file, times, flag);
}
#else
# if HAVE_UTIMENSAT
/* If we have a native utimensat, but are compiling this file, then
utimensat was defined to rpl_utimensat by our replacement
@ -42,24 +68,25 @@
local_utimensat provides the fallback manipulation. */
static int local_utimensat (int, char const *, struct timespec const[2], int);
# define AT_FUNC_NAME local_utimensat
# define AT_FUNC_NAME local_utimensat
/* Like utimensat, but work around native bugs. */
int
rpl_utimensat (int fd, char const *file, struct timespec const times[2],
int flag)
# undef utimensat
{
# if defined __linux__ || defined __sun
# if defined __linux__ || defined __sun
struct timespec ts[2];
# endif
# endif
/* See comments in utimens.c for details. */
static int utimensat_works_really; /* 0 = unknown, 1 = yes, -1 = no. */
if (0 <= utimensat_works_really)
{
int result;
# if defined __linux__ || defined __sun
# if defined __linux__ || defined __sun
struct stat st;
/* As recently as Linux kernel 2.6.32 (Dec 2009), several file
systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
@ -90,7 +117,7 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2],
ts[1] = times[1];
times = ts;
}
# ifdef __hppa__
# ifdef __hppa__
/* Linux kernel 2.6.22.19 on hppa does not reject invalid tv_nsec
values. */
else if (times
@ -104,8 +131,36 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2],
errno = EINVAL;
return -1;
}
# endif
# endif
# if defined __APPLE__ && defined __MACH__
/* macOS 10.13 does not reject invalid tv_nsec values either. */
if (times
&& ((times[0].tv_nsec != UTIME_OMIT
&& times[0].tv_nsec != UTIME_NOW
&& ! (0 <= times[0].tv_nsec
&& times[0].tv_nsec < TIMESPEC_HZ))
|| (times[1].tv_nsec != UTIME_OMIT
&& times[1].tv_nsec != UTIME_NOW
&& ! (0 <= times[1].tv_nsec
&& times[1].tv_nsec < TIMESPEC_HZ))))
{
errno = EINVAL;
return -1;
}
size_t len = strlen (file);
if (len > 0 && file[len - 1] == '/')
{
struct stat statbuf;
if (fstatat (fd, file, &statbuf, 0) < 0)
return -1;
if (!S_ISDIR (statbuf.st_mode))
{
errno = ENOTDIR;
return -1;
}
}
# endif
# endif
result = utimensat (fd, file, times, flag);
/* Linux kernel 2.6.25 has a bug where it returns EINVAL for
UTIME_NOW or UTIME_OMIT with non-zero tv_sec, which
@ -129,11 +184,11 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2],
return local_utimensat (fd, file, times, flag);
}
#else /* !HAVE_UTIMENSAT */
# else /* !HAVE_UTIMENSAT */
# define AT_FUNC_NAME utimensat
# define AT_FUNC_NAME utimensat
#endif /* !HAVE_UTIMENSAT */
# endif /* !HAVE_UTIMENSAT */
/* Set the access and modification timestamps of FILE to be
TIMESPEC[0] and TIMESPEC[1], respectively; relative to directory
@ -146,15 +201,17 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2],
Return 0 on success, -1 (setting errno) on failure. */
/* AT_FUNC_NAME is now utimensat or local_utimensat. */
#define AT_FUNC_F1 lutimens
#define AT_FUNC_F2 utimens
#define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
#define AT_FUNC_POST_FILE_PARAM_DECLS , struct timespec const ts[2], int flag
#define AT_FUNC_POST_FILE_ARGS , ts
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
# define AT_FUNC_F1 lutimens
# define AT_FUNC_F2 utimens
# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
# define AT_FUNC_POST_FILE_PARAM_DECLS , struct timespec const ts[2], int flag
# define AT_FUNC_POST_FILE_ARGS , ts
# include "at-func.c"
# undef AT_FUNC_NAME
# undef AT_FUNC_F1
# undef AT_FUNC_F2
# undef AT_FUNC_USE_F1_COND
# undef AT_FUNC_POST_FILE_PARAM_DECLS
# undef AT_FUNC_POST_FILE_ARGS
#endif /* !HAVE_NEARLY_WORKING_UTIMENSAT */