summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2019-01-08 21:43:25 +0100
committerCorinna Vinschen <corinna@vinschen.de>2019-01-08 21:47:28 +0100
commitdee6cb133a5876c636ca1c544a5f95167dab5d09 (patch)
treeb98914ce79674832cf878e378d78bb60c3400a43
parentec36c59f1a9349e690849e393251623f5936408c (diff)
downloadcygnal-dee6cb133a5876c636ca1c544a5f95167dab5d09.tar.gz
cygnal-dee6cb133a5876c636ca1c544a5f95167dab5d09.tar.bz2
cygnal-dee6cb133a5876c636ca1c544a5f95167dab5d09.zip
Cygwin: try_to_bin: don't reopen the file
So far we reopened the file if it was opened case sensitive to workaround the problem that the recycler could be named in camel back or all upper case, depending on who created it. That's a problem for O_TMPFILE on pre-W10. As soon as the original HANDLE gets closed, delete-on-close is converted to full delete disposition and all useful operations on the file cease to work (STATUS_ACCESS_DENIED or STATUS_FILE_DELETED). To avoid that problem drop the reopen code and check for the exact recycler filename, either $Recycle.Bin or $RECYCLE.BIN, if the file has been opened case sensitive. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r--winsup/cygwin/syscalls.cc55
1 files changed, 30 insertions, 25 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index cb62a6242..fcf2d8601 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -232,31 +232,6 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags)
them into the recycler. */
if (pfni->FileNameLength == 2) /* root dir. */
goto out;
- /* The recycler name is $Recycler.Bin by default. If the recycler dir
- disappeared for some reason, the shell32.dll recreates the directory in
- all upper case. So, we never know beforehand if the dir is written in
- mixed case or in all upper case. That's a problem when using
- casesensitivity. If the file handle given to FileRenameInformation
- has been opened casesensitive, the call also handles the path to the
- target dir casesensitive. Rather than trying to find the right name
- of the recycler, we just reopen the file to move with OBJ_CASE_INSENSITIVE,
- so the subsequent FileRenameInformation works caseinsensitive in terms of
- the recycler directory name, too. */
- if (!pc.objcaseinsensitive ())
- {
- InitializeObjectAttributes (&attr, &ro_u_empty, OBJ_CASE_INSENSITIVE,
- fh, NULL);
- status = NtOpenFile (&tmp_fh, access, &attr, &io, FILE_SHARE_VALID_FLAGS,
- flags);
- if (!NT_SUCCESS (status))
- debug_printf ("NtOpenFile (%S) for reopening caseinsensitive failed, "
- "status = %y", pc.get_nt_native_path (), status);
- else
- {
- NtClose (fh);
- fh = tmp_fh;
- }
- }
/* Initialize recycler path. */
RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf);
if (!pc.isremote ())
@@ -312,6 +287,36 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags)
recycler.Length -= sizeof (WCHAR);
/* Store length of recycler base dir, if it's necessary to create it. */
recycler_base_len = recycler.Length;
+ /* The recycler name is $Recycler.Bin by default. If the recycler dir
+ disappears for some reason, shell32.dll recreates it in all upper
+ case. So we never know if the dir is written in camel back or in
+ upper case. That's a problem when using casesensitivity: If the
+ file handle given to FileRenameInformation has been opened
+ casesensitive, the call also handles the path to the target dir
+ casesensitive. Check for the right name here.
+
+ Note that, originally, we reopened the file case insensitive instead.
+ But that's a problem for O_TMPFILE on pre-W10. As soon as the
+ original HANDLE gets closed, delete-on-close is converted to full
+ delete disposition and all useful operations on the file cease to
+ work (STATUS_ACCESS_DENIED or STATUS_FILE_DELETED). */
+ if (!pc.objcaseinsensitive ())
+ {
+ PFILE_BASIC_INFORMATION pfbi;
+
+ InitializeObjectAttributes (&attr, &recycler, 0, rootdir, NULL);
+ pfbi = (PFILE_BASIC_INFORMATION) infobuf;
+ status = NtQueryAttributesFile (&attr, pfbi);
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ wcscpy (recycler.Buffer, L"$RECYCLE.BIN\\");
+ status = NtQueryAttributesFile (&attr, pfbi);
+ /* Keep the uppercase name if it exists, otherwise revert to
+ camel back to create a nicer name than shell32.dll. */
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+ wcscpy (recycler.Buffer, L"$Recycle.Bin\\");
+ }
+ }
/* On NTFS or ReFS the recycler dir contains user specific subdirs, which
are the actual recycle bins per user. The name of this dir is the
string representation of the user SID. */