]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
Minor fixes in w32-shell-execute.
[gnu-emacs] / src / w32.c
index bff0e53e8c8705b7920a0317e218a7a83a600aef..dde74bfcdd988857e063e751dc7bdbb8f404b572 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,5 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
+
+Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -140,6 +141,7 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 #include <sddl.h>
 
 #include <sys/acl.h>
+#include <acl.h>
 
 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
    define them by hand if not already defined.  */
@@ -1344,7 +1346,7 @@ w32_valid_pointer_p (void *p, int size)
 
      More generally, passing to library functions (e.g., fopen or
      opendir) file names already encoded in the ANSI codepage is
-     explictly *verboten*, as all those functions, as shadowed and
+     explicitly *verboten*, as all those functions, as shadowed and
      emulated here, assume they will receive UTF-8 encoded file names.
 
      For the same reasons, no CRT function or Win32 API can be called
@@ -1371,7 +1373,7 @@ w32_valid_pointer_p (void *p, int size)
    . Running subprocesses in non-ASCII directories and with non-ASCII
      file arguments is limited to the current codepage (even though
      Emacs is perfectly capable of finding an executable program file
-     even in a directory whose name cannot be encoded in the curreent
+     even in a directory whose name cannot be encoded in the current
      codepage).  This is because the command-line arguments are
      encoded _before_ they get to the w32-specific level, and the
      encoding is not known in advance (it doesn't have to be the
@@ -1731,9 +1733,28 @@ getloadavg (double loadavg[], int nelem)
   ULONGLONG idle, kernel, user;
   time_t now = time (NULL);
 
+  /* If system time jumped back for some reason, delete all samples
+     whose time is later than the current wall-clock time.  This
+     prevents load average figures from becoming frozen for prolonged
+     periods of time, when system time is reset backwards.  */
+  if (last_idx >= 0)
+    {
+      while (difftime (now, samples[last_idx].sample_time) < -1.0)
+       {
+         if (last_idx == first_idx)
+           {
+             first_idx = last_idx = -1;
+             break;
+           }
+         last_idx = buf_prev (last_idx);
+       }
+    }
+
   /* Store another sample.  We ignore samples that are less than 1 sec
      apart.  */
-  if (difftime (now, samples[last_idx].sample_time) >= 1.0 - 2*DBL_EPSILON*now)
+  if (last_idx < 0
+      || (difftime (now, samples[last_idx].sample_time)
+         >= 1.0 - 2*DBL_EPSILON*now))
     {
       sample_system_load (&idle, &kernel, &user);
       last_idx = buf_next (last_idx);
@@ -4887,7 +4908,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
              && !(is_a_symlink && follow_symlinks)
              /* The 2 file-name comparisons below support only ASCII
                 characters, and will lose (compare not equal) when
-                the file names include non-ASCII charcaters that are
+                the file names include non-ASCII characters that are
                 the same but for the case.  However, doing this
                 properly involves: (a) converting both file names to
                 UTF-16, (b) lower-casing both names using CharLowerW,
@@ -4921,7 +4942,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
                  /* If NAME includes characters not representable by
                     the current ANSI codepage, filename_to_ansi
                     usually replaces them with a '?'.  We don't want
-                    to let FindFirstFileA interpret those as widlcards,
+                    to let FindFirstFileA interpret those as wildcards,
                     and "succeed", returning us data from some random
                     file in the same directory.  */
                  if (_mbspbrk (name_a, "?"))
@@ -6001,6 +6022,116 @@ careadlinkat (int fd, char const *filename,
   return NULL;
 }
 
+int
+w32_copy_file (const char *from, const char *to,
+              int keep_time, int preserve_ownership, int copy_acls)
+{
+  acl_t acl = NULL;
+  BOOL copy_result;
+  wchar_t from_w[MAX_PATH], to_w[MAX_PATH];
+  char from_a[MAX_PATH], to_a[MAX_PATH];
+
+  /* We ignore preserve_ownership for now.  */
+  preserve_ownership = preserve_ownership;
+
+  if (copy_acls)
+    {
+      acl = acl_get_file (from, ACL_TYPE_ACCESS);
+      if (acl == NULL && acl_errno_valid (errno))
+       return -2;
+    }
+  if (w32_unicode_filenames)
+    {
+      filename_to_utf16 (from, from_w);
+      filename_to_utf16 (to, to_w);
+      copy_result = CopyFileW (from_w, to_w, FALSE);
+    }
+  else
+    {
+      filename_to_ansi (from, from_a);
+      filename_to_ansi (to, to_a);
+      copy_result = CopyFileA (from_a, to_a, FALSE);
+    }
+  if (!copy_result)
+    {
+      /* CopyFile doesn't set errno when it fails.  By far the most
+        "popular" reason is that the target is read-only.  */
+      DWORD err = GetLastError ();
+
+      switch (err)
+       {
+       case ERROR_FILE_NOT_FOUND:
+         errno = ENOENT;
+         break;
+       case ERROR_ACCESS_DENIED:
+         errno = EACCES;
+         break;
+       case ERROR_ENCRYPTION_FAILED:
+         errno = EIO;
+         break;
+       default:
+         errno = EPERM;
+         break;
+       }
+
+      if (acl)
+       acl_free (acl);
+      return -1;
+    }
+  /* CopyFile retains the timestamp by default.  However, see
+     "Community Additions" for CopyFile: it sounds like that is not
+     entirely true.  Testing on Windows XP confirms that modified time
+     is copied, but creation and last-access times are not.
+     FIXME?  */
+  else if (!keep_time)
+    {
+      struct timespec now;
+      DWORD attributes;
+
+      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))
+           {
+             /* Restore original attributes.  */
+             SetFileAttributesW (to_w, attributes);
+             if (acl)
+               acl_free (acl);
+             return -3;
+           }
+         /* Restore original attributes.  */
+         SetFileAttributesW (to_w, attributes);
+       }
+      else
+       {
+         attributes = GetFileAttributesA (to_a);
+         SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
+         now = current_timespec ();
+         if (set_file_times (-1, to, now, now))
+           {
+             SetFileAttributesA (to_a, attributes);
+             if (acl)
+               acl_free (acl);
+             return -3;
+           }
+         SetFileAttributesA (to_a, attributes);
+       }
+    }
+  if (acl != NULL)
+    {
+      bool fail =
+       acl_set_file (to, ACL_TYPE_ACCESS, acl) != 0;
+      acl_free (acl);
+      if (fail && acl_errno_valid (errno))
+       return -4;
+    }
+
+  return 0;
+}
+
 \f
 /* Support for browsing other processes and their attributes.  See
    process.c for the Lisp bindings.  */
@@ -8472,7 +8603,7 @@ check_windows_init_file (void)
         need to ENCODE_FILE here, but we do need to convert the file
         names from UTF-8 to ANSI.  */
       init_file = build_string ("term/w32-win");
-      fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil);
+      fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0);
       if (fd < 0)
        {
          Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);