* dir.cc (mkdir): Check last path component for "..".
(rmdir): Don't check last path component for "..". * fhandler_disk_file.cc (fhandler_disk_file::rmdir): Drop kludge which tries to allow deleting the current working directory. * path.cc (has_dot_last_component): Add parameter to indicate testing for "..". Take trailing slash into account. (symlink_info::posixify): Rely on cygheap->cwd.win32 having a useful value. (cwdstuff::init): Initialize cygheap->cwd with current working directory. Change to windows_system_directory afterwards. (cwdstuff::set): Never call SetCurrentDirectory here. Just check if changing into target directory would be allowed. Add comment to explain why. * path.h (has_dot_last_component): Declare with second parameter. * pinfo.cc (pinfo::zap_cwd): Remove. (pinfo::exit): Drop call to zap_cwd. * pinfo.h (class pinfo): Remove declaration of zap_cwd. * spawn.cc (spawn_guts): Set current working directory for non-Cygwin child applications. Drop call to zap_cwd.
This commit is contained in:
@ -1449,70 +1449,42 @@ fhandler_disk_file::rmdir ()
|
||||
SetFileAttributes (get_win32_name (),
|
||||
(DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
|
||||
|
||||
for (bool is_cwd = false; ; is_cwd = true)
|
||||
DWORD err, att = 0;
|
||||
int rc = RemoveDirectory (get_win32_name ());
|
||||
|
||||
if (isremote () && exists ())
|
||||
att = GetFileAttributes (get_win32_name ());
|
||||
|
||||
/* Sometimes smb indicates failure when it really succeeds, so check for
|
||||
this case specifically. */
|
||||
if (rc || att == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD err, att = 0;
|
||||
int rc = RemoveDirectory (get_win32_name ());
|
||||
/* 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 (!isremote () || att == INVALID_FILE_ATTRIBUTES)
|
||||
return res;
|
||||
|
||||
if (isremote () && exists ())
|
||||
att = GetFileAttributes (get_win32_name ());
|
||||
|
||||
/* 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 (!isremote () || att == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
err = ERROR_DIR_NOT_EMPTY;
|
||||
}
|
||||
else
|
||||
err = GetLastError ();
|
||||
|
||||
/* 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. (Actually it does on 9X.)
|
||||
FIXME: A potential workaround for this is for cygwin apps to *never*
|
||||
call SetCurrentDirectory. */
|
||||
|
||||
extern char windows_system_directory[];
|
||||
if (strcasematch (get_win32_name (), cygheap->cwd.win32)
|
||||
&& !strcasematch (windows_system_directory, cygheap->cwd.win32)
|
||||
&& !is_cwd
|
||||
&& SetCurrentDirectory (windows_system_directory))
|
||||
continue;
|
||||
|
||||
/* On 9X ERROR_ACCESS_DENIED is returned if you try to remove a
|
||||
non-empty directory. */
|
||||
if (err == ERROR_ACCESS_DENIED
|
||||
&& wincap.access_denied_on_delete ())
|
||||
err = ERROR_DIR_NOT_EMPTY;
|
||||
/* ...and, that's *not* funny, when trying to remove a non-existing
|
||||
directory on a share, which is hosted by a 9x machine, the error
|
||||
code ERROR_INVALID_FUNCTION is returned. */
|
||||
else if (err == ERROR_INVALID_FUNCTION)
|
||||
err = ERROR_FILE_NOT_FOUND;
|
||||
|
||||
__seterrno_from_win_error (err);
|
||||
|
||||
/* Directory still exists, restore its characteristics. */
|
||||
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
|
||||
SetFileAttributes (get_win32_name (), (DWORD) pc);
|
||||
if (is_cwd)
|
||||
SetCurrentDirectory (get_win32_name ());
|
||||
break;
|
||||
err = ERROR_DIR_NOT_EMPTY;
|
||||
}
|
||||
else
|
||||
err = GetLastError ();
|
||||
/* On 9X ERROR_ACCESS_DENIED is returned if you try to remove a
|
||||
non-empty directory. */
|
||||
if (err == ERROR_ACCESS_DENIED
|
||||
&& wincap.access_denied_on_delete ())
|
||||
err = ERROR_DIR_NOT_EMPTY;
|
||||
/* ...and, that's *not* funny, when trying to remove a non-existing
|
||||
directory on a share, which is hosted by a 9x machine, the error
|
||||
code ERROR_INVALID_FUNCTION is returned. */
|
||||
else if (err == ERROR_INVALID_FUNCTION)
|
||||
err = ERROR_FILE_NOT_FOUND;
|
||||
|
||||
__seterrno_from_win_error (err);
|
||||
|
||||
/* Directory still exists, restore its characteristics. */
|
||||
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
|
||||
SetFileAttributes (get_win32_name (), (DWORD) pc);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
Reference in New Issue
Block a user