mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-26 07:11:34 -08:00
Fix the MinGW build as followup to recent "nofollow" changes
* src/w32.c (fdutimens): Call utimensat instead of utime. (set_file_times): Function deleted. (convert_from_timespec): Renamed from convert_from_time_t and modified to accept 'struct timespec' argument instead of 'time_t'. (utimensat): Renamed from utime and modified to accept 'struct timespec [2]' argument and an additional argument FLAG. Emulate Posix 'utimensat'. Call 'convert_from_timespec'. (w32_copy_file): Call 'utimensat' instead of 'set_file_times'. * src/fileio.c (Fcopy_file) [WINDOWSNT]: Make the error message be identical to that on Posix platforms. * nt/inc/sys/stat.h (utimensat): Provide prototype. * nt/mingw-cfg.site (ac_cv_func_futimens) (gl_cv_func_futimens_works, ac_cv_func_utimensat) (gl_cv_func_utimensat_works): Override Gnulib tests. * nt/gnulib-cfg.mk (OMIT_GNULIB_MODULE_futimens) (OMIT_GNULIB_MODULE_utimensat): Disable these Gnulib modules.
This commit is contained in:
parent
0a3f8da6e1
commit
66bc47d12a
5 changed files with 88 additions and 46 deletions
|
|
@ -65,3 +65,5 @@ OMIT_GNULIB_MODULE_unistd = true
|
|||
OMIT_GNULIB_MODULE_canonicalize-lgpl = true
|
||||
OMIT_GNULIB_MODULE_fchmodat = true
|
||||
OMIT_GNULIB_MODULE_lchmod = true
|
||||
OMIT_GNULIB_MODULE_futimens = true
|
||||
OMIT_GNULIB_MODULE_utimensat = true
|
||||
|
|
|
|||
|
|
@ -164,4 +164,9 @@ int __cdecl __MINGW_NOTHROW fstatat (int, char const *,
|
|||
struct stat *, int);
|
||||
int __cdecl __MINGW_NOTHROW chmod (const char*, int);
|
||||
|
||||
/* Provide prototypes of library functions that are emulated on w32
|
||||
and whose prototypes are usually found in sys/stat.h on POSIX
|
||||
platforms. */
|
||||
extern int utimensat (int, const char *, struct timespec const[2], int);
|
||||
|
||||
#endif /* INC_SYS_STAT_H_ */
|
||||
|
|
|
|||
|
|
@ -105,6 +105,10 @@ gl_cv_func_fstatat_zero_flag=yes
|
|||
ac_cv_func_fchmodat=yes
|
||||
gl_cv_func_fchmodat_works="not-needed-so-yes"
|
||||
ac_cv_func_lchmod=yes
|
||||
ac_cv_func_futimens=not-needed
|
||||
gl_cv_func_futimens_works="not-needed-so-yes"
|
||||
ac_cv_func_utimensat=yes
|
||||
gl_cv_func_utimensat_works=yes
|
||||
# Aliased to _commit in ms-w32.h
|
||||
ac_cv_func_fsync=yes
|
||||
ac_cv_func_fdatasync=yes
|
||||
|
|
|
|||
|
|
@ -2077,7 +2077,7 @@ permissions. */)
|
|||
report_file_error ("Copying permissions from", file);
|
||||
case -3:
|
||||
xsignal2 (Qfile_date_error,
|
||||
build_string ("Resetting file times"), newname);
|
||||
build_string ("Cannot set file date"), newname);
|
||||
case -4:
|
||||
report_file_error ("Copying permissions to", newname);
|
||||
}
|
||||
|
|
|
|||
121
src/w32.c
121
src/w32.c
|
|
@ -3178,33 +3178,9 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
|
|||
return _futime (fd, &_ut);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct utimbuf ut;
|
||||
|
||||
ut.actime = timespec[0].tv_sec;
|
||||
ut.modtime = timespec[1].tv_sec;
|
||||
/* Call 'utime', which is implemented below, not the MS library
|
||||
function, which fails on directories. */
|
||||
return utime (file, &ut);
|
||||
}
|
||||
return utimensat (fd, file, timespec, 0);
|
||||
}
|
||||
|
||||
/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
|
||||
ATIME and MTIME, respectively.
|
||||
FD must be either negative -- in which case it is ignored --
|
||||
or a file descriptor that is open on FILE.
|
||||
If FD is nonnegative, then FILE can be NULL. */
|
||||
static int
|
||||
set_file_times (int fd, const char *filename,
|
||||
struct timespec atime, struct timespec mtime)
|
||||
{
|
||||
struct timespec timespec[2];
|
||||
timespec[0] = atime;
|
||||
timespec[1] = mtime;
|
||||
return fdutimens (fd, filename, timespec);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* IO support and wrapper functions for the Windows API. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
|
@ -4985,7 +4961,7 @@ convert_time (FILETIME ft)
|
|||
}
|
||||
|
||||
static void
|
||||
convert_from_time_t (time_t time, FILETIME * pft)
|
||||
convert_from_timespec (struct timespec time, FILETIME * pft)
|
||||
{
|
||||
ULARGE_INTEGER tmp;
|
||||
|
||||
|
|
@ -4996,7 +4972,8 @@ convert_from_time_t (time_t time, FILETIME * pft)
|
|||
}
|
||||
|
||||
/* time in 100ns units since 1-Jan-1601 */
|
||||
tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base;
|
||||
tmp.QuadPart =
|
||||
(ULONGLONG) time.tv_sec * 10000000L + time.tv_nsec / 100 + utc_base;
|
||||
pft->dwHighDateTime = tmp.HighPart;
|
||||
pft->dwLowDateTime = tmp.LowPart;
|
||||
}
|
||||
|
|
@ -5663,8 +5640,8 @@ fstatat (int fd, char const *name, struct stat *st, int flags)
|
|||
return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
|
||||
}
|
||||
|
||||
/* Provide fstat and utime as well as stat for consistent handling of
|
||||
file timestamps. */
|
||||
/* Provide fstat and utimensat as well as stat for consistent handling
|
||||
of file timestamps. */
|
||||
int
|
||||
fstat (int desc, struct stat * buf)
|
||||
{
|
||||
|
|
@ -5775,23 +5752,65 @@ fstat (int desc, struct stat * buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* A version of 'utime' which handles directories as well as
|
||||
files. */
|
||||
/* Emulate utimensat. */
|
||||
|
||||
int
|
||||
utime (const char *name, struct utimbuf *times)
|
||||
utimensat (int fd, const char *name, const struct timespec times[2], int flag)
|
||||
{
|
||||
struct utimbuf deftime;
|
||||
struct timespec ltimes[2];
|
||||
HANDLE fh;
|
||||
FILETIME mtime;
|
||||
FILETIME atime;
|
||||
DWORD flags_and_attrs = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
|
||||
/* Rely on a hack: an open directory is modeled as file descriptor 0.
|
||||
This is good enough for the current usage in Emacs, but is fragile.
|
||||
|
||||
FIXME: Add proper support for utimensat.
|
||||
Gnulib does this and can serve as a model. */
|
||||
char fullname[MAX_UTF8_PATH];
|
||||
|
||||
if (fd != AT_FDCWD)
|
||||
{
|
||||
char lastc = dir_pathname[strlen (dir_pathname) - 1];
|
||||
|
||||
if (_snprintf (fullname, sizeof fullname, "%s%s%s",
|
||||
dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
|
||||
< 0)
|
||||
{
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
name = fullname;
|
||||
}
|
||||
|
||||
if (times == NULL)
|
||||
{
|
||||
deftime.modtime = deftime.actime = time (NULL);
|
||||
times = &deftime;
|
||||
memset (ltimes, 0, sizeof (ltimes));
|
||||
ltimes[0] = ltimes[1] = current_timespec ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
|
||||
return 0; /* nothing to do */
|
||||
if ((times[0].tv_nsec != UTIME_NOW && times[0].tv_nsec != UTIME_OMIT
|
||||
&& !(0 <= times[0].tv_nsec && times[0].tv_nsec < 1000000000))
|
||||
|| (times[1].tv_nsec != UTIME_NOW && times[1].tv_nsec != UTIME_OMIT
|
||||
&& !(0 <= times[1].tv_nsec && times[1].tv_nsec < 1000000000)))
|
||||
{
|
||||
errno = EINVAL; /* reject invalid timespec values */
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (ltimes, times, sizeof (ltimes));
|
||||
if (ltimes[0].tv_nsec == UTIME_NOW)
|
||||
ltimes[0] = current_timespec ();
|
||||
if (ltimes[1].tv_nsec == UTIME_NOW)
|
||||
ltimes[1] = current_timespec ();
|
||||
}
|
||||
|
||||
if (flag == AT_SYMLINK_NOFOLLOW)
|
||||
flags_and_attrs |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
if (w32_unicode_filenames)
|
||||
{
|
||||
wchar_t name_utf16[MAX_PATH];
|
||||
|
|
@ -5805,7 +5824,7 @@ utime (const char *name, struct utimbuf *times)
|
|||
allows other processes to delete files inside it,
|
||||
while we have the directory open. */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
0, OPEN_EXISTING, flags_and_attrs, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5816,13 +5835,26 @@ utime (const char *name, struct utimbuf *times)
|
|||
|
||||
fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
0, OPEN_EXISTING, flags_and_attrs, NULL);
|
||||
}
|
||||
if (fh != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
convert_from_time_t (times->actime, &atime);
|
||||
convert_from_time_t (times->modtime, &mtime);
|
||||
if (!SetFileTime (fh, NULL, &atime, &mtime))
|
||||
FILETIME *patime, *pmtime;
|
||||
if (ltimes[0].tv_nsec == UTIME_OMIT)
|
||||
patime = NULL;
|
||||
else
|
||||
{
|
||||
convert_from_timespec (ltimes[0], &atime);
|
||||
patime = &atime;
|
||||
}
|
||||
if (ltimes[1].tv_nsec == UTIME_OMIT)
|
||||
pmtime = NULL;
|
||||
else
|
||||
{
|
||||
convert_from_timespec (ltimes[1], &mtime);
|
||||
pmtime = &mtime;
|
||||
}
|
||||
if (!SetFileTime (fh, NULL, patime, pmtime))
|
||||
{
|
||||
CloseHandle (fh);
|
||||
errno = EACCES;
|
||||
|
|
@ -6741,16 +6773,16 @@ w32_copy_file (const char *from, const char *to,
|
|||
FIXME? */
|
||||
else if (!keep_time)
|
||||
{
|
||||
struct timespec now;
|
||||
struct timespec tnow[2];
|
||||
DWORD attributes;
|
||||
|
||||
tnow[0] = tnow[1] = current_timespec ();
|
||||
if (w32_unicode_filenames)
|
||||
{
|
||||
/* Ensure file is writable while its times are set. */
|
||||
attributes = GetFileAttributesW (to_w);
|
||||
SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY);
|
||||
now = current_timespec ();
|
||||
if (set_file_times (-1, to, now, now))
|
||||
if (utimensat (AT_FDCWD, to, tnow, 0))
|
||||
{
|
||||
/* Restore original attributes. */
|
||||
SetFileAttributesW (to_w, attributes);
|
||||
|
|
@ -6765,8 +6797,7 @@ w32_copy_file (const char *from, const char *to,
|
|||
{
|
||||
attributes = GetFileAttributesA (to_a);
|
||||
SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
|
||||
now = current_timespec ();
|
||||
if (set_file_times (-1, to, now, now))
|
||||
if (utimensat (AT_FDCWD, to, tnow, 0))
|
||||
{
|
||||
SetFileAttributesA (to_a, attributes);
|
||||
if (acl)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue