[Patch]: rmdir

Pierre A. Humblet pierre@phumblet.no-ip.org
Sun Mar 14 15:47:00 GMT 2004


2004-03-14  Pierre Humblet <pierre.humblet@ieee.org>

	* dir.cc (rmdir): Construct real_dir with flag PC_FULL.
	Use a loop instead of recursion to handle the current directory.

-------------- next part --------------
Index: dir.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dir.cc,v
retrieving revision 1.77
diff -u -p -r1.77 dir.cc
--- dir.cc	26 Nov 2003 13:23:27 -0000	1.77
+++ dir.cc	14 Mar 2004 15:42:29 -0000
@@ -308,7 +308,7 @@ rmdir (const char *dir)
   int res = -1;
   DWORD devn;

-  path_conv real_dir (dir, PC_SYM_NOFOLLOW);
+  path_conv real_dir (dir, PC_SYM_NOFOLLOW | PC_FULL);

   if (real_dir.error)
     set_errno (real_dir.error);
@@ -326,60 +326,60 @@ rmdir (const char *dir)
 	SetFileAttributes (real_dir,
 			   (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY);

-      int rc = RemoveDirectory (real_dir);
-      DWORD att = GetFileAttributes (real_dir);
+      for (bool is_cwd = false; ; is_cwd = true)
+        {
+	  int rc = RemoveDirectory (real_dir);
+	  DWORD att = GetFileAttributes (real_dir);

-      /* Sometimes smb indicates failure when it really succeeds, so check for
-	 this case specifically. */
-      if (rc || att == INVALID_FILE_ATTRIBUTES)
-	{
-	  /* RemoveDirectory on a samba drive doesn't return an error if the
-	     directory can't be removed because it's not empty. Checking for
-	     existence afterwards keeps us informed about success. */
-	  if (att != INVALID_FILE_ATTRIBUTES)
-	    set_errno (ENOTEMPTY);
-	  else
-	    res = 0;
-	}
-      else
-	{
-	  /* This kludge detects if we are attempting to remove the current working
-	     directory.  If so, we will move elsewhere to potentially allow the
-	     rmdir to succeed.  This means that cygwin's concept of the current working
-	     directory != Windows concept but, hey, whaddaregonnado?
-	     Note that this will not cause something like the following to work:
-		     $ cd foo
-		     $ rmdir .
-	     since the shell will have foo "open" in the above case and so Windows will
-	     not allow the deletion.
-	     FIXME: A potential workaround for this is for cygwin apps to *never* call
-	     SetCurrentDirectory. */
-	  if (strcasematch (real_dir, cygheap->cwd.win32)
-	      && !strcasematch ("c:\\", cygheap->cwd.win32))
+	  /* Sometimes smb indicates failure when it really succeeds, so check for
+	     this case specifically. */
+	  if (rc || att == INVALID_FILE_ATTRIBUTES)
 	    {
-	      DWORD err = GetLastError ();
-	      if (!SetCurrentDirectory ("c:\\"))
-		SetLastError (err);
-	      else if ((res = rmdir (dir)))
-		SetCurrentDirectory (cygheap->cwd.win32);
+	      /* RemoveDirectory on a samba drive doesn't return an error if the
+		 directory can't be removed because it's not empty. Checking for
+		 existence afterwards keeps us informed about success. */
+	      if (att != INVALID_FILE_ATTRIBUTES)
+		set_errno (ENOTEMPTY);
+	      else
+		res = 0;
 	    }
-	  if (res)
+	  else
 	    {
-	      if (GetLastError () != ERROR_ACCESS_DENIED
-		  || !wincap.access_denied_on_delete ())
-		__seterrno ();
-	      else
-		set_errno (ENOTEMPTY);	/* On 9X ERROR_ACCESS_DENIED is
-					       returned if you try to remove a
-					       non-empty directory. */
+	      /* This kludge detects if we are attempting to remove the current working
+		 directory.  If so, we will move elsewhere to potentially allow the
+		 rmdir to succeed.  This means that cygwin's concept of the current working
+		 directory != Windows concept but, hey, whaddaregonnado?
+		 FIXME: A potential workaround for this is for cygwin apps to *never* call
+		 SetCurrentDirectory. */
+	      if (strcasematch (real_dir, cygheap->cwd.win32)
+		  && !strcasematch ("c:\\", cygheap->cwd.win32) && !is_cwd)
+	        {
+		  DWORD err = GetLastError ();
+		  if (!SetCurrentDirectory ("c:\\"))
+		    SetLastError (err);
+		  else
+		    continue;
+		}
+	      if (res)
+	        {
+		  if (GetLastError () != ERROR_ACCESS_DENIED
+		      || !wincap.access_denied_on_delete ())
+		    __seterrno ();
+		  else
+		    set_errno (ENOTEMPTY);	/* On 9X ERROR_ACCESS_DENIED is
+						   returned if you try to remove a
+						   non-empty directory. */

-	      /* If directory still exists, restore R/O attribute. */
-	      if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
-		SetFileAttributes (real_dir, real_dir);
+		  /* If directory still exists, restore R/O attribute. */
+		  if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
+		    SetFileAttributes (real_dir, real_dir);
+		  if (is_cwd)
+		    SetCurrentDirectory (cygheap->cwd.win32);
+		}
 	    }
+	  break;
 	}
     }
-
   syscall_printf ("%d = rmdir (%s)", res, dir);
   return res;
 }


More information about the Cygwin-patches mailing list