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:
parent
9143eba0c6
commit
a900e641fa
51 changed files with 1841 additions and 514 deletions
101
lib/utimensat.c
101
lib/utimensat.c
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue