aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2024-06-14 10:44:20 +0800
committerPo Lu2024-06-14 10:45:02 +0800
commita458dc5dc828cfbe5d74226d6ef45a3d205cb7d8 (patch)
tree780d96eddea66c83d50d69210a98ab25fad68fb4
parent4124b98509bf049a3ccf0f7319b7edf7cae3b6a0 (diff)
downloademacs-a458dc5dc828cfbe5d74226d6ef45a3d205cb7d8.tar.gz
emacs-a458dc5dc828cfbe5d74226d6ef45a3d205cb7d8.zip
Restore file's original name after a failed rename_replace on Windows 9X
* src/w32.c (sys_rename_replace): If the rename operation fails and an intermediate name was generated and applied to the input file, restore the original.
-rw-r--r--src/w32.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/src/w32.c b/src/w32.c
index 6d0b178e978..1c6a56bcbd9 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4740,10 +4740,11 @@ int
4740sys_rename_replace (const char *oldname, const char *newname, BOOL force) 4740sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4741{ 4741{
4742 BOOL result; 4742 BOOL result;
4743 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];; 4743 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];
4744 int newname_dev; 4744 int newname_dev;
4745 int oldname_dev; 4745 int oldname_dev;
4746 bool have_temp_a = false; 4746 bool have_temp_a = false;
4747 char oldname_a[MAX_PATH];
4747 4748
4748 /* MoveFile on Windows 95 doesn't correctly change the short file name 4749 /* MoveFile on Windows 95 doesn't correctly change the short file name
4749 alias in a number of circumstances (it is not easy to predict when 4750 alias in a number of circumstances (it is not easy to predict when
@@ -4768,7 +4769,6 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4768 char * o; 4769 char * o;
4769 char * p; 4770 char * p;
4770 int i = 0; 4771 int i = 0;
4771 char oldname_a[MAX_PATH];
4772 4772
4773 oldname = map_w32_filename (oldname, NULL); 4773 oldname = map_w32_filename (oldname, NULL);
4774 filename_to_ansi (oldname, oldname_a); 4774 filename_to_ansi (oldname, oldname_a);
@@ -4844,7 +4844,7 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4844 DWORD attributes_new; 4844 DWORD attributes_new;
4845 4845
4846 if (_wchmod (newname_w, 0666) != 0) 4846 if (_wchmod (newname_w, 0666) != 0)
4847 return result; 4847 goto return_result;
4848 attributes_old = GetFileAttributesW (temp_w); 4848 attributes_old = GetFileAttributesW (temp_w);
4849 attributes_new = GetFileAttributesW (newname_w); 4849 attributes_new = GetFileAttributesW (newname_w);
4850 if (attributes_old != -1 && attributes_new != -1 4850 if (attributes_old != -1 && attributes_new != -1
@@ -4855,15 +4855,16 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4855 errno = ENOTDIR; 4855 errno = ENOTDIR;
4856 else 4856 else
4857 errno = EISDIR; 4857 errno = EISDIR;
4858 return -1; 4858 result = -1;
4859 goto return_result;
4859 } 4860 }
4860 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0) 4861 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0)
4861 { 4862 {
4862 if (_wrmdir (newname_w) != 0) 4863 if (_wrmdir (newname_w) != 0)
4863 return result; 4864 goto return_result;
4864 } 4865 }
4865 else if (_wunlink (newname_w) != 0) 4866 else if (_wunlink (newname_w) != 0)
4866 return result; 4867 goto return_result;
4867 result = _wrename (temp_w, newname_w); 4868 result = _wrename (temp_w, newname_w);
4868 } 4869 }
4869 else if (w32err == ERROR_PRIVILEGE_NOT_HELD 4870 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
@@ -4902,7 +4903,7 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4902 DWORD attributes_new; 4903 DWORD attributes_new;
4903 4904
4904 if (_chmod (newname_a, 0666) != 0) 4905 if (_chmod (newname_a, 0666) != 0)
4905 return result; 4906 goto return_result;
4906 attributes_old = GetFileAttributesA (temp_a); 4907 attributes_old = GetFileAttributesA (temp_a);
4907 attributes_new = GetFileAttributesA (newname_a); 4908 attributes_new = GetFileAttributesA (newname_a);
4908 if (attributes_old != -1 && attributes_new != -1 4909 if (attributes_old != -1 && attributes_new != -1
@@ -4913,15 +4914,16 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4913 errno = ENOTDIR; 4914 errno = ENOTDIR;
4914 else 4915 else
4915 errno = EISDIR; 4916 errno = EISDIR;
4916 return -1; 4917 result = -1;
4918 goto return_result;
4917 } 4919 }
4918 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0) 4920 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0)
4919 { 4921 {
4920 if (_rmdir (newname_a) != 0) 4922 if (_rmdir (newname_a) != 0)
4921 return result; 4923 goto return_result;
4922 } 4924 }
4923 else if (_unlink (newname_a) != 0) 4925 else if (_unlink (newname_a) != 0)
4924 return result; 4926 goto return_result;
4925 result = rename (temp_a, newname_a); 4927 result = rename (temp_a, newname_a);
4926 } 4928 }
4927 else if (w32err == ERROR_PRIVILEGE_NOT_HELD 4929 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
@@ -4930,6 +4932,23 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4930 } 4932 }
4931 } 4933 }
4932 4934
4935 return_result:
4936 /* This label is also invoked on failure, and on Windows 9X, restores
4937 the initial name of files that will have been renamed in
4938 preparation for being moved. It ought to be valid to rename temp_a
4939 to its previous name, just as it would, but for the failure, have
4940 been renamed to the target. */
4941
4942 if (have_temp_a && result)
4943 {
4944 int save_errno = errno;
4945
4946 /* XXX: what if a new file has replaced oldname_a in the
4947 meantime? */
4948 rename (temp_a, oldname_a);
4949 errno = save_errno;
4950 }
4951
4933 return result; 4952 return result;
4934} 4953}
4935 4954