diff options
| author | Eli Zaretskii | 2013-11-16 16:38:04 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-11-16 16:38:04 +0200 |
| commit | f5c287f4fa22070b4b65fc6e731dd359daa7acce (patch) | |
| tree | 969763f88c69015147e5308eb98a0493fc80f797 /src | |
| parent | 44b322511dfa8af002e92fc2a335065f4ac8e033 (diff) | |
| download | emacs-f5c287f4fa22070b4b65fc6e731dd359daa7acce.tar.gz emacs-f5c287f4fa22070b4b65fc6e731dd359daa7acce.zip | |
sys_rename_replace converted.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 117 |
1 files changed, 81 insertions, 36 deletions
| @@ -3847,9 +3847,10 @@ int | |||
| 3847 | sys_rename_replace (const char *oldname, const char *newname, BOOL force) | 3847 | sys_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 | ||