[newlib-cygwin] Cygwin: try_to_bin: don't reopen the file

Corinna Vinschen corinna@sourceware.org
Tue Jan 8 20:48:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=dee6cb133a5876c636ca1c544a5f95167dab5d09

commit dee6cb133a5876c636ca1c544a5f95167dab5d09
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue Jan 8 21:43:25 2019 +0100

    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>

Diff:
---
 winsup/cygwin/syscalls.cc | 55 ++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index cb62a62..fcf2d86 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. */



More information about the Cygwin-cvs mailing list