aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2015-09-07 18:26:36 +0300
committerEli Zaretskii2015-09-07 18:26:36 +0300
commitcaf4a0192621f49b677ad05fe86e358020a88b7e (patch)
tree0ca50fcfa4969ef71319af161a310772ea18c894 /src
parent066b26d6c47d1384d5ed3ce09c6379a9df350256 (diff)
downloademacs-caf4a0192621f49b677ad05fe86e358020a88b7e.tar.gz
emacs-caf4a0192621f49b677ad05fe86e358020a88b7e.zip
Fix deletion of symlinks to directories on MS-Windows
* src/w32.c (sys_unlink): If 'unlink' fails, and the argument is a symlink to a directory, try again with 'rmdir'. (is_symlink): If the argument is a symlink to a directory, set a bit in the return value to indicate that fact.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/w32.c b/src/w32.c
index cc55507919c..bb514960e43 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4534,6 +4534,8 @@ sys_rmdir (const char * path)
4534int 4534int
4535sys_unlink (const char * path) 4535sys_unlink (const char * path)
4536{ 4536{
4537 int rmstatus, e;
4538
4537 path = map_w32_filename (path, NULL); 4539 path = map_w32_filename (path, NULL);
4538 4540
4539 if (w32_unicode_filenames) 4541 if (w32_unicode_filenames)
@@ -4541,9 +4543,18 @@ sys_unlink (const char * path)
4541 wchar_t path_w[MAX_PATH]; 4543 wchar_t path_w[MAX_PATH];
4542 4544
4543 filename_to_utf16 (path, path_w); 4545 filename_to_utf16 (path, path_w);
4544 /* On Unix, unlink works without write permission. */ 4546 /* On Unix, unlink works without write permission. */
4545 _wchmod (path_w, 0666); 4547 _wchmod (path_w, 0666);
4546 return _wunlink (path_w); 4548 rmstatus = _wunlink (path_w);
4549 e = errno;
4550 /* Symlinks to directories can only be deleted by _rmdir;
4551 _unlink returns EACCES. */
4552 if (rmstatus != 0
4553 && errno == EACCES
4554 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4555 rmstatus = _wrmdir (path_w);
4556 else
4557 errno = e;
4547 } 4558 }
4548 else 4559 else
4549 { 4560 {
@@ -4551,8 +4562,17 @@ sys_unlink (const char * path)
4551 4562
4552 filename_to_ansi (path, path_a); 4563 filename_to_ansi (path, path_a);
4553 _chmod (path_a, 0666); 4564 _chmod (path_a, 0666);
4554 return _unlink (path_a); 4565 rmstatus = _unlink (path_a);
4566 e = errno;
4567 if (rmstatus != 0
4568 && errno == EACCES
4569 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4570 rmstatus = _rmdir (path_a);
4571 else
4572 errno = e;
4555 } 4573 }
4574
4575 return rmstatus;
4556} 4576}
4557 4577
4558static FILETIME utc_base_ft; 4578static FILETIME utc_base_ft;
@@ -5626,7 +5646,8 @@ symlink (char const *filename, char const *linkname)
5626/* A quick inexpensive test of whether FILENAME identifies a file that 5646/* A quick inexpensive test of whether FILENAME identifies a file that
5627 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME 5647 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5628 must already be in the normalized form returned by 5648 must already be in the normalized form returned by
5629 map_w32_filename. 5649 map_w32_filename. If the symlink is to a directory, the
5650 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5630 5651
5631 Note: for repeated operations on many files, it is best to test 5652 Note: for repeated operations on many files, it is best to test
5632 whether the underlying volume actually supports symlinks, by 5653 whether the underlying volume actually supports symlinks, by
@@ -5684,6 +5705,8 @@ is_symlink (const char *filename)
5684 attrs_mean_symlink = 5705 attrs_mean_symlink =
5685 (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 5706 (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5686 && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK; 5707 && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5708 if (attrs_mean_symlink)
5709 attrs_mean_symlink |= (wfdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5687 } 5710 }
5688 else if (_mbspbrk (filename_a, "?")) 5711 else if (_mbspbrk (filename_a, "?"))
5689 { 5712 {
@@ -5697,6 +5720,8 @@ is_symlink (const char *filename)
5697 attrs_mean_symlink = 5720 attrs_mean_symlink =
5698 (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 5721 (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5699 && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK; 5722 && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5723 if (attrs_mean_symlink)
5724 attrs_mean_symlink |= (wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5700 } 5725 }
5701 if (fh == INVALID_HANDLE_VALUE) 5726 if (fh == INVALID_HANDLE_VALUE)
5702 return 0; 5727 return 0;