diff options
author | Pierre Humblet <phumblet@phumblet.no-ip.org> | 2004-03-14 19:16:45 +0300 |
---|---|---|
committer | Pierre Humblet <phumblet@phumblet.no-ip.org> | 2004-03-14 19:16:45 +0300 |
commit | 83a74ea24a7e60c31858571cb521d2da4ca310f2 (patch) | |
tree | e6c7cba721a08c02de534c8e57868ba4c97fc392 /winsup | |
parent | f8a8e7a1f6364f620685406cf9f3a9770b1d5789 (diff) |
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.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 7 | ||||
-rw-r--r-- | winsup/cygwin/dir.cc | 96 |
2 files changed, 54 insertions, 49 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 42bcc14ae..98a69c568 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,8 @@ +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. + 2004-03-14 Christopher Faylor <cgf@redhat.com> * cygtls.cc (_cygtls::remove): Call remove_wq to ensure that wait stuff @@ -94,7 +99,7 @@ * sigproc.h (waitq): Delete declaration. * wait.cc (wait4): Use _my_tls waitq structure rather than per_thread. -2004-02-11 Pierre Humblet <pierre.humblet@ieee.org> +2004-03-11 Pierre Humblet <pierre.humblet@ieee.org> * cygtls.h (_cygtls::newmask): Delete member. (_cygtls::deltamask): New member. diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 90ca1cab4..2fccabc72 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -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. */ - - /* If directory still exists, restore R/O attribute. */ - if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) - SetFileAttributes (real_dir, real_dir); + /* 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 (is_cwd) + SetCurrentDirectory (cygheap->cwd.win32); + } } + break; } } - syscall_printf ("%d = rmdir (%s)", res, dir); return res; } |