diff options
| author | Po Lu | 2024-06-14 10:44:20 +0800 |
|---|---|---|
| committer | Po Lu | 2024-06-14 10:45:02 +0800 |
| commit | a458dc5dc828cfbe5d74226d6ef45a3d205cb7d8 (patch) | |
| tree | 780d96eddea66c83d50d69210a98ab25fad68fb4 | |
| parent | 4124b98509bf049a3ccf0f7319b7edf7cae3b6a0 (diff) | |
| download | emacs-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.c | 39 |
1 files changed, 29 insertions, 10 deletions
| @@ -4740,10 +4740,11 @@ int | |||
| 4740 | sys_rename_replace (const char *oldname, const char *newname, BOOL force) | 4740 | sys_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 | ||