* 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:
Corinna Vinschen
2006-11-30 10:17:24 +00:00
parent 7d79436443
commit 8eca536272
8 changed files with 118 additions and 97 deletions

View File

@ -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;
}