emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 66bc47d: Fix the MinGW build as followup to recent "nofollow" cha


From: Eli Zaretskii
Subject: master 66bc47d: Fix the MinGW build as followup to recent "nofollow" changes
Date: Sun, 8 Mar 2020 11:01:07 -0400 (EDT)

branch: master
commit 66bc47d12aba72ff738a9f5575e0b93eefc641ba
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    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.
---
 nt/gnulib-cfg.mk  |   2 +
 nt/inc/sys/stat.h |   5 +++
 nt/mingw-cfg.site |   4 ++
 src/fileio.c      |   2 +-
 src/w32.c         | 121 ++++++++++++++++++++++++++++++++++--------------------
 5 files changed, 88 insertions(+), 46 deletions(-)

diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index 1d120a9..e3b9457 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -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
diff --git a/nt/inc/sys/stat.h b/nt/inc/sys/stat.h
index 7bf780d..f58d5ab 100644
--- a/nt/inc/sys/stat.h
+++ b/nt/inc/sys/stat.h
@@ -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_ */
diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site
index 5bd5b83..2271eef 100644
--- a/nt/mingw-cfg.site
+++ b/nt/mingw-cfg.site
@@ -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
diff --git a/src/fileio.c b/src/fileio.c
index 82fd798..ffe7955 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -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);
     }
diff --git a/src/w32.c b/src/w32.c
index 40f286a..698e10e 100644
--- a/src/w32.c
+++ b/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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]