changeset 592:4f6ba8f1fb3d

[xemacs-hg @ 2001-05-31 12:03:37 by adrian] [PATCH] Fix time preservation in (copy-file ...) on native Windows <1yp8gt63.fsf@rapier.ecf.teradyne.com>
author adrian
date Thu, 31 May 2001 12:03:39 +0000
parents ec73ae6e772b
children 5fd7ba8b56e7
files src/ChangeLog src/fileio.c src/nt.c src/nt.h src/sysdep.c src/systime.h
diffstat 6 files changed, 116 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu May 31 02:05:18 2001 +0000
+++ b/src/ChangeLog	Thu May 31 12:03:39 2001 +0000
@@ -1,3 +1,17 @@
+2001-05-29  Adrian Aichner  <adrian@xemacs.org>
+
+	* fileio.c: Include nt.h.  Remove lisp_string_set_file_times()
+	because set_file_times() now takes Lisp_Object path, instead of
+	char*.
+	* nt.c: Include buffer.h.
+	* nt.c (convert_from_time_t): New.
+	* nt.c (mswindows_utime): New.  Use utime, since SetFileTime does
+	not set mtime correctly.
+	* nt.h: Declare mswindows_utime().
+	* sysdep.c (set_file_times): set_file_times() now takes Lisp_Object
+	path, instead of char*.
+	* systime.h: Include <sys/utime.h> on WIN32_NATIVE.
+
 2001-05-30  William M. Perry  <wmperry@gnu.org>
 
 	* emacs-marshals.c: Regenerated from lisp.
--- a/src/fileio.c	Thu May 31 02:05:18 2001 +0000
+++ b/src/fileio.c	Thu May 31 12:03:39 2001 +0000
@@ -54,6 +54,7 @@
 #endif /* HPUX */
 
 #ifdef WIN32_NATIVE
+#include "nt.h"
 #define IS_DRIVE(x) isalpha (x)
 /* Need to lower-case the drive letter, or else expanded
    filenames will sometimes compare inequal, because
@@ -1596,16 +1597,6 @@
   return;
 }
 
-/* A slightly higher-level interface than `set_file_times' */
-static int
-lisp_string_set_file_times (Lisp_Object filename,
-			    EMACS_TIME atime, EMACS_TIME mtime)
-{
-  char *ext_filename;
-  LISP_STRING_TO_EXTERNAL (filename, ext_filename, Qfile_name);
-  return set_file_times (ext_filename, atime, mtime);
-}
-
 DEFUN ("copy-file", Fcopy_file, 2, 4,
        "fCopy file: \nFCopy %s to file: \np\nP", /*
 Copy FILENAME to NEWNAME.  Both args must be strings.
@@ -1743,8 +1734,8 @@
 	    EMACS_TIME atime, mtime;
 	    EMACS_SET_SECS_USECS (atime, st.st_atime, 0);
 	    EMACS_SET_SECS_USECS (mtime, st.st_mtime, 0);
-	    if (lisp_string_set_file_times (newname, atime, mtime))
-	      report_file_error ("I/O error", newname);
+	    if (set_file_times (newname, atime, mtime))
+	      report_file_error ("I/O error", list1 (newname));
 	  }
 	chmod ((const char *) XSTRING_DATA (newname),
 	       st.st_mode & 07777);
--- a/src/nt.c	Thu May 31 02:05:18 2001 +0000
+++ b/src/nt.c	Thu May 31 12:03:39 2001 +0000
@@ -29,6 +29,8 @@
 #include "lisp.h"
 #undef getwd
 
+#include "buffer.h"
+
 #include "systime.h"
 #include "syssignal.h"
 #include "sysproc.h"
@@ -1177,6 +1179,7 @@
 #endif /* 0 */
 
 static FILETIME utc_base_ft;
+static long double utc_base;
 static int init = 0;
 
 #if 0
@@ -2237,6 +2240,81 @@
   close_file_data (&executable);
 }
 
+static void
+convert_from_time_t (time_t time, FILETIME * pft)
+{
+  long double tmp;
+
+  if (!init)
+    {
+      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
+      SYSTEMTIME st;
+
+      st.wYear = 1970;
+      st.wMonth = 1;
+      st.wDay = 1;
+      st.wHour = 0;
+      st.wMinute = 0;
+      st.wSecond = 0;
+      st.wMilliseconds = 0;
+
+      SystemTimeToFileTime (&st, &utc_base_ft);
+      utc_base = (long double) utc_base_ft.dwHighDateTime
+	* 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
+      init = 1;
+    }
+
+  /* time in 100ns units since 1-Jan-1601 */
+  tmp = (long double) time * 1e7 + utc_base;
+  pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
+  pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) *
+                                pft->dwHighDateTime);
+}
+
+int
+mswindows_utime (Lisp_Object path, struct utimbuf *times)
+{
+  struct utimbuf deftime;
+  HANDLE fh;
+  static FILETIME mtime;
+  static FILETIME atime;
+  Extbyte *filename;
+
+  if (times == NULL)
+    {
+      deftime.modtime = deftime.actime = time (NULL);
+      times = &deftime;
+    }
+
+  LISP_STRING_TO_EXTERNAL (path, filename, Qmswindows_tstr);
+  /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */
+#if 0
+  /* Need write access to set times.  */
+  fh = CreateFile (filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+		   0, OPEN_EXISTING, 0, NULL);
+  if (fh)
+    {
+      convert_from_time_t (times->actime, &atime);
+      convert_from_time_t (times->modtime, &mtime);
+      if (!SetFileTime (fh, NULL, &atime, &mtime))
+	{
+	  CloseHandle (fh);
+	  errno = EACCES;
+	  return -1;
+	}
+      CloseHandle (fh);
+    }
+  else
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  return 0;
+#else
+  return utime (filename, &times);
+#endif
+}
+
 /* Close the system structures associated with the given file.  */
 void
 close_file_data (file_data *p_file)
--- a/src/nt.h	Thu May 31 02:05:18 2001 +0000
+++ b/src/nt.h	Thu May 31 12:03:39 2001 +0000
@@ -105,6 +105,7 @@
 
 void set_process_dir (const char * dir);
 time_t convert_time (FILETIME ft);
+int mswindows_utime (Lisp_Object path, struct utimbuf *times);
 
 extern void init_ntproc (void);
 extern void term_ntproc (int unused);
--- a/src/sysdep.c	Thu May 31 02:05:18 2001 +0000
+++ b/src/sysdep.c	Thu May 31 12:03:39 2001 +0000
@@ -3378,17 +3378,26 @@
    access to those functions goes through the following. */
 
 int
-set_file_times (char *filename, EMACS_TIME atime, EMACS_TIME mtime)
+set_file_times (Lisp_Object path, EMACS_TIME atime, EMACS_TIME mtime)
 {
-#if defined (HAVE_UTIME)
+#if defined (WIN32_NATIVE)
   struct utimbuf utb;
   utb.actime = EMACS_SECS (atime);
   utb.modtime = EMACS_SECS (mtime);
+  return mswindows_utime (path, &utb);
+#elif defined (HAVE_UTIME)
+  struct utimbuf utb;
+  Extbyte *filename;
+  utb.actime = EMACS_SECS (atime);
+  utb.modtime = EMACS_SECS (mtime);
+  LISP_STRING_TO_EXTERNAL (path, filename, Qfile_name);
   return utime (filename, &utb);
 #elif defined (HAVE_UTIMES)
   struct timeval tv[2];
+  Extbyte *filename;
   tv[0] = atime;
   tv[1] = mtime;
+  LISP_STRING_TO_EXTERNAL (path, filename, Qfile_name);
   return utimes (filename, tv);
 #else
   /* No file times setting function available. */
--- a/src/systime.h	Thu May 31 02:05:18 2001 +0000
+++ b/src/systime.h	Thu May 31 12:03:39 2001 +0000
@@ -63,10 +63,16 @@
 
 #endif /* WIN32_NATIVE */
 
+/* struct utimbuf */
+
 #ifdef HAVE_UTIME
 # include <utime.h>
 #endif
 
+#ifdef WIN32_NATIVE
+# include <sys/utime.h>
+#endif
+
 #if defined(HAVE_TZNAME) && !defined(WIN32_NATIVE) && !defined(CYGWIN)
 #ifndef tzname		/* For SGI.  */
 extern char *tzname[];	/* RS6000 and others want it this way.  */
@@ -228,7 +234,9 @@
 #define EMACS_SET_SECS_USECS(time, secs, usecs) 		\
   (EMACS_SET_SECS (time, secs), EMACS_SET_USECS (time, usecs))
 
-int set_file_times (char *filename, EMACS_TIME atime, EMACS_TIME mtime);
+#ifdef emacs
+int set_file_times (Lisp_Object path, EMACS_TIME atime, EMACS_TIME mtime);
+#endif
 
 void get_process_times (double *user_time, double *system_time,
 			double *real_time);