diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-21 04:48:28 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-02-21 04:48:28 +0000 |
commit | 4a670c2bb6adbb34cb7e244fe1ef2cc888449e6f (patch) | |
tree | b160799684ed01021d01b25d45ee88357b5a193b /win32 | |
parent | 2098b5aea5e197f23a40d95933306bf09e782aa3 (diff) |
merge revision(s) 49634,49658,49663: [Backport #10865]
* win32/win32.c (wrename): return EXDEV if moving a directory to
another drive, since MoveFileExW does not set proper error code.
[ruby-core:68162] [Bug #10865]
* win32/win32.c (different_device_p): compare by volume serial
numbers, not by path names.
numbers, not by path names. [ruby-core:68162] [Bug #10865]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@49672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32')
-rw-r--r-- | win32/win32.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/win32/win32.c b/win32/win32.c index 34d42b0ded..b7d7e32935 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4701,6 +4701,31 @@ rb_w32_getenv(const char *name) return w32_getenv(name, CP_ACP); } +/* License: Ruby's */ +static DWORD +get_volume_serial_number(const WCHAR *path) +{ + const DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; + const DWORD creation = OPEN_EXISTING; + const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; + BY_HANDLE_FILE_INFORMATION st = {0}; + HANDLE h = CreateFileW(path, 0, share_mode, NULL, creation, flags, NULL); + BOOL ret; + + if (h == INVALID_HANDLE_VALUE) return 0; + ret = GetFileInformationByHandle(h, &st); + CloseHandle(h); + if (!ret) return 0; + return st.dwVolumeSerialNumber; +} + +/* License: Ruby's */ +static int +different_device_p(const WCHAR *oldpath, const WCHAR *newpath) +{ + return get_volume_serial_number(oldpath) != get_volume_serial_number(newpath); +} + /* License: Artistic or GPL */ static int wrename(const WCHAR *oldpath, const WCHAR *newpath) @@ -4724,8 +4749,14 @@ wrename(const WCHAR *oldpath, const WCHAR *newpath) if (!MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED)) res = -1; - if (res) - errno = map_errno(GetLastError()); + if (res) { + DWORD e = GetLastError(); + if ((e == ERROR_ACCESS_DENIED) && (oldatts & FILE_ATTRIBUTE_DIRECTORY) && + different_device_p(oldpath, newpath)) + errno = EXDEV; + else + errno = map_errno(e); + } else SetFileAttributesW(newpath, oldatts); }); |