diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0c9478ed6..592344286 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2015-04-23 Corinna Vinschen + + * path.cc (path_conv::set_nt_native_path): New function. + * path.h (path_conv::set_nt_native_path): Add prototype. + * syscall.cc (try_to_bin): Handle moving files to the recycler + accessed via a local virtual drive (subst). Fix a problem renaming + the file to the unique replacement name on Samba. Align comment. + 2015-04-22 Corinna Vinschen * fhandler_tty.cc (fhandler_pty_slave::fch_close_handles): Don't close diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 1dd96cf10..446d746cc 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -486,6 +486,18 @@ get_nt_native_path (const char *path, UNICODE_STRING& upath, bool dos) return &upath; } +/* Handle with extrem care! Only used in a certain instance in try_to_bin. + Every other usage needs a careful check. */ +void +path_conv::set_nt_native_path (PUNICODE_STRING new_path) +{ + wide_path = (PWCHAR) crealloc_abort (wide_path, new_path->MaximumLength); + memcpy (wide_path, new_path->Buffer, new_path->Length); + uni_path.Length = new_path->Length; + uni_path.MaximumLength = new_path->MaximumLength; + uni_path.Buffer = wide_path; +} + PUNICODE_STRING path_conv::get_nt_native_path () { diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index a668eae6e..5c464dc9a 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -270,6 +270,7 @@ class path_conv ~path_conv (); inline const char *get_win32 () const { return path; } + void set_nt_native_path (PUNICODE_STRING); PUNICODE_STRING get_nt_native_path (); inline POBJECT_ATTRIBUTES get_object_attr (OBJECT_ATTRIBUTES &attr, SECURITY_ATTRIBUTES &sa) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index d2fb3534b..c08d12fa9 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -314,15 +314,35 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags) RtlAppendUnicodeToString (&recycler, L"\\Recycled\\"); else goto out; - /* Is the file a subdir of the recycler? */ RtlInitCountedUnicodeString(&fname, pfni->FileName, pfni->FileNameLength); + /* Is the file a subdir of the recycler? */ if (RtlEqualUnicodePathPrefix (&fname, &recycler, TRUE)) goto out; /* Is fname the recycler? Temporarily hide trailing backslash. */ recycler.Length -= sizeof (WCHAR); if (RtlEqualUnicodeString (&fname, &recycler, TRUE)) goto out; + /* Is fname really a subcomponent of the full path? If not, there's + a high probability we're acessing the file via a virtual drive + created with "subst". Check and accommodate it. Note that we + ony get here if the virtual drive is really pointing to a local + drive. Otherwise pc.isremote () returns "true". */ + if (!RtlEqualUnicodePathSuffix (pc.get_nt_native_path (), &fname, TRUE)) + { + WCHAR drive[3] = { pc.get_nt_native_path ()->Buffer[4], ':', '\0' }; + PWCHAR tgt = tp.w_get (); + if (QueryDosDeviceW (drive, tgt, NT_MAX_PATH) + && !wcsncmp (tgt, L"\\??\\", 4)) + { + UNICODE_STRING new_path; + + wcsncpy (tgt + 6, fname.Buffer, fname.Length / sizeof (WCHAR)); + RtlInitCountedUnicodeString(&new_path, tgt, + 6 * sizeof (WCHAR) + fname.Length); + pc.set_nt_native_path (&new_path); + } + } /* Create root dir path from file name information. */ RtlSplitUnicodePath (&fname, &fname, NULL); RtlSplitUnicodePath (pc.get_nt_native_path (), &root, NULL); @@ -367,9 +387,11 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags) starting at U+dc00. Use plain ASCII chars on filesystems not supporting Unicode. The rest of the filename is the inode number in hex encoding and a hash of the full NT path in hex. The combination allows to remove - multiple hardlinks to the same file. */ + multiple hardlinks to the same file. Samba doesn't like the transposed + names. */ RtlAppendUnicodeToString (&recycler, - pc.fs_flags () & FILE_UNICODE_ON_DISK + (pc.fs_flags () & FILE_UNICODE_ON_DISK + && !pc.fs_is_samba ()) ? L".\xdc63\xdc79\xdc67" : L".cyg"); pfii = (PFILE_INTERNAL_INFORMATION) infobuf; /* Note: Modern Samba versions apparently don't like buffer sizes of more