]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
Remove support for ':timeout' from w32 tray notifications
[gnu-emacs] / src / w32.c
index cc55507919cd9f8c9bc438d748e5d8bca6d90245..15cfd92a29a555f4c82dc2e392c6aac39b580b84 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -67,7 +67,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #undef localtime
 
 #include "lisp.h"
-#include "epaths.h"    /* for SHELL */
+#include "epaths.h"    /* for PATH_EXEC */
 
 #include <pwd.h>
 #include <grp.h>
@@ -224,20 +224,22 @@ typedef struct _REPARSE_DATA_BUFFER {
 
 #include <iphlpapi.h>  /* should be after winsock2.h */
 
+#include <c-strcase.h>
+
 #include "w32.h"
 #include <dirent.h>
 #include "w32common.h"
-#include "w32heap.h"
 #include "w32select.h"
-#include "systime.h"
+#include "systime.h"           /* for current_timespec, struct timespec */
 #include "dispextern.h"                /* for xstrcasecmp */
 #include "coding.h"            /* for Vlocale_coding_system */
 
 #include "careadlinkat.h"
 #include "allocator.h"
 
-/* For serial_configure and serial_open.  */
+/* For Lisp_Process, serial_configure and serial_open.  */
 #include "process.h"
+#include "systty.h"
 
 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
   (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
@@ -4534,6 +4536,8 @@ sys_rmdir (const char * path)
 int
 sys_unlink (const char * path)
 {
+  int rmstatus, e;
+
   path = map_w32_filename (path, NULL);
 
   if (w32_unicode_filenames)
@@ -4541,9 +4545,18 @@ sys_unlink (const char * path)
       wchar_t path_w[MAX_PATH];
 
       filename_to_utf16 (path, path_w);
-      /* On Unix, unlink works without write permission. */
+      /* On Unix, unlink works without write permission.  */
       _wchmod (path_w, 0666);
-      return _wunlink (path_w);
+      rmstatus = _wunlink (path_w);
+      e = errno;
+      /* Symlinks to directories can only be deleted by _rmdir;
+        _unlink returns EACCES.  */
+      if (rmstatus != 0
+         && errno == EACCES
+         && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
+       rmstatus = _wrmdir (path_w);
+      else
+       errno = e;
     }
   else
     {
@@ -4551,8 +4564,17 @@ sys_unlink (const char * path)
 
       filename_to_ansi (path, path_a);
       _chmod (path_a, 0666);
-      return _unlink (path_a);
+      rmstatus = _unlink (path_a);
+      e = errno;
+      if (rmstatus != 0
+         && errno == EACCES
+         && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
+       rmstatus = _rmdir (path_a);
+      else
+       errno = e;
     }
+
+  return rmstatus;
 }
 
 static FILETIME utc_base_ft;
@@ -5626,7 +5648,8 @@ symlink (char const *filename, char const *linkname)
 /* A quick inexpensive test of whether FILENAME identifies a file that
    is a symlink.  Returns non-zero if it is, zero otherwise.  FILENAME
    must already be in the normalized form returned by
-   map_w32_filename.
+   map_w32_filename.  If the symlink is to a directory, the
+   FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
 
    Note: for repeated operations on many files, it is best to test
    whether the underlying volume actually supports symlinks, by
@@ -5684,6 +5707,8 @@ is_symlink (const char *filename)
       attrs_mean_symlink =
        (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
        && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
+      if (attrs_mean_symlink)
+       attrs_mean_symlink |= (wfdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
     }
   else if (_mbspbrk (filename_a, "?"))
     {
@@ -5697,6 +5722,8 @@ is_symlink (const char *filename)
       attrs_mean_symlink =
        (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
        && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
+      if (attrs_mean_symlink)
+       attrs_mean_symlink |= (wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
     }
   if (fh == INVALID_HANDLE_VALUE)
     return 0;