aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-11-16 16:38:04 +0200
committerEli Zaretskii2013-11-16 16:38:04 +0200
commitf5c287f4fa22070b4b65fc6e731dd359daa7acce (patch)
tree969763f88c69015147e5308eb98a0493fc80f797 /src
parent44b322511dfa8af002e92fc2a335065f4ac8e033 (diff)
downloademacs-f5c287f4fa22070b4b65fc6e731dd359daa7acce.tar.gz
emacs-f5c287f4fa22070b4b65fc6e731dd359daa7acce.zip
sys_rename_replace converted.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c117
1 files changed, 81 insertions, 36 deletions
diff --git a/src/w32.c b/src/w32.c
index b4d305f2aff..1ae0bb0d3d7 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3847,9 +3847,10 @@ int
3847sys_rename_replace (const char *oldname, const char *newname, BOOL force) 3847sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3848{ 3848{
3849 BOOL result; 3849 BOOL result;
3850 char temp[MAX_PATH]; 3850 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];;
3851 int newname_dev; 3851 int newname_dev;
3852 int oldname_dev; 3852 int oldname_dev;
3853 bool have_temp_a = false;
3853 3854
3854 /* MoveFile on Windows 95 doesn't correctly change the short file name 3855 /* MoveFile on Windows 95 doesn't correctly change the short file name
3855 alias in a number of circumstances (it is not easy to predict when 3856 alias in a number of circumstances (it is not easy to predict when
@@ -3874,17 +3875,20 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3874 char * o; 3875 char * o;
3875 char * p; 3876 char * p;
3876 int i = 0; 3877 int i = 0;
3878 char oldname_a[MAX_PATH];
3877 3879
3878 oldname = map_w32_filename (oldname, NULL); 3880 oldname = map_w32_filename (oldname, NULL);
3879 if ((o = strrchr (oldname, '\\'))) 3881 filename_to_ansi (oldname, oldname_a);
3882 filename_to_ansi (temp, temp_a);
3883 if ((o = strrchr (oldname_a, '\\')))
3880 o++; 3884 o++;
3881 else 3885 else
3882 o = (char *) oldname; 3886 o = (char *) oldname_a;
3883 3887
3884 if ((p = strrchr (temp, '\\'))) 3888 if ((p = strrchr (temp_a, '\\')))
3885 p++; 3889 p++;
3886 else 3890 else
3887 p = temp; 3891 p = temp_a;
3888 3892
3889 do 3893 do
3890 { 3894 {
@@ -3892,12 +3896,13 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3892 seems to make the second rename work properly. */ 3896 seems to make the second rename work properly. */
3893 sprintf (p, "_.%s.%u", o, i); 3897 sprintf (p, "_.%s.%u", o, i);
3894 i++; 3898 i++;
3895 result = rename (oldname, temp); 3899 result = rename (oldname_a, temp_a);
3896 } 3900 }
3897 /* This loop must surely terminate! */ 3901 /* This loop must surely terminate! */
3898 while (result < 0 && errno == EEXIST); 3902 while (result < 0 && errno == EEXIST);
3899 if (result < 0) 3903 if (result < 0)
3900 return -1; 3904 return -1;
3905 have_temp_a = true;
3901 } 3906 }
3902 3907
3903 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists 3908 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
@@ -3916,41 +3921,81 @@ sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3916 /* volume_info is set indirectly by map_w32_filename. */ 3921 /* volume_info is set indirectly by map_w32_filename. */
3917 newname_dev = volume_info.serialnum; 3922 newname_dev = volume_info.serialnum;
3918 3923
3919 result = rename (temp, newname); 3924 if (w32_unicode_filenames)
3920
3921 if (result < 0 && force)
3922 { 3925 {
3923 DWORD w32err = GetLastError (); 3926 wchar_t temp_w[MAX_PATH], newname_w[MAX_PATH];
3924 3927
3925 if (errno == EACCES 3928 filename_to_utf16 (temp, temp_w);
3926 && newname_dev != oldname_dev) 3929 filename_to_utf16 (newname, newname_w);
3930 result = _wrename (temp_w, newname_w);
3931 if (result < 0 && force)
3927 { 3932 {
3928 /* The implementation of `rename' on Windows does not return 3933 DWORD w32err = GetLastError ();
3929 errno = EXDEV when you are moving a directory to a 3934
3930 different storage device (ex. logical disk). It returns 3935 if (errno == EACCES
3931 EACCES instead. So here we handle such situations and 3936 && newname_dev != oldname_dev)
3932 return EXDEV. */ 3937 {
3933 DWORD attributes; 3938 /* The implementation of `rename' on Windows does not return
3934 3939 errno = EXDEV when you are moving a directory to a
3935 if ((attributes = GetFileAttributes (temp)) != -1 3940 different storage device (ex. logical disk). It returns
3936 && (attributes & FILE_ATTRIBUTE_DIRECTORY)) 3941 EACCES instead. So here we handle such situations and
3937 errno = EXDEV; 3942 return EXDEV. */
3938 } 3943 DWORD attributes;
3939 else if (errno == EEXIST) 3944
3940 { 3945 if ((attributes = GetFileAttributesW (temp_w)) != -1
3941 if (_chmod (newname, 0666) != 0) 3946 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
3942 return result; 3947 errno = EXDEV;
3943 if (_unlink (newname) != 0) 3948 }
3944 return result; 3949 else if (errno == EEXIST)
3945 result = rename (temp, newname); 3950 {
3951 if (_wchmod (newname_w, 0666) != 0)
3952 return result;
3953 if (_wunlink (newname_w) != 0)
3954 return result;
3955 result = _wrename (temp_w, newname_w);
3956 }
3957 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
3958 && is_symlink (temp))
3959 {
3960 /* This is Windows prohibiting the user from creating a
3961 symlink in another place, since that requires
3962 privileges. */
3963 errno = EPERM;
3964 }
3946 } 3965 }
3947 else if (w32err == ERROR_PRIVILEGE_NOT_HELD 3966 }
3948 && is_symlink (temp)) 3967 else
3968 {
3969 char newname_a[MAX_PATH];
3970
3971 if (!have_temp_a)
3972 filename_to_ansi (temp, temp_a);
3973 filename_to_ansi (newname, newname_a);
3974 result = rename (temp_a, newname_a);
3975 if (result < 0 && force)
3949 { 3976 {
3950 /* This is Windows prohibiting the user from creating a 3977 DWORD w32err = GetLastError ();
3951 symlink in another place, since that requires 3978
3952 privileges. */ 3979 if (errno == EACCES
3953 errno = EPERM; 3980 && newname_dev != oldname_dev)
3981 {
3982 DWORD attributes;
3983
3984 if ((attributes = GetFileAttributesA (temp_a)) != -1
3985 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
3986 errno = EXDEV;
3987 }
3988 else if (errno == EEXIST)
3989 {
3990 if (_chmod (newname_a, 0666) != 0)
3991 return result;
3992 if (_unlink (newname_a) != 0)
3993 return result;
3994 result = rename (temp_a, newname_a);
3995 }
3996 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
3997 && is_symlink (temp))
3998 errno = EPERM;
3954 } 3999 }
3955 } 4000 }
3956 4001