Add "path.h" include throughout, where needed. Use new path_conv methods and

operators to simplify testing for directory and attributes, throughout.
* path.h (path_conv::exists): New method.
(path_conv::has_attribute): Ditto.
(path_conv::isdir): Ditto.
(path_conv::DWORD &): New operator.
(path_conv::int &): Ditto.
* dir.cc (rmdir): Eliminate a goto.
* dtable.cc (dtable::build_fhandler): Accept opt and suffix info for
path_conv.check.  Return fh == NULL on path_conv error.  Pass unit to set_name
as appropriate.
(dtable::reset_unix_path_name): New method.
* dtable.h (dtable): Declare new method.  Reflect arg changes to
build_fhandler.
* fhandler.cc (fhandler_disk_dummy_name): Eliminate.
(fhandler_base::set_name): Expect paths to be NULL.  Build unix_path_name from
win32_path_name when it is a device.
(fhandler_base::reset_unix_path_name): New method.
(fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION or
ERROR_INVALID_PARAMETER and reading a directory.
(fhandler_disk_file::fstat): Don't call stat_dev since we should now never be
calling fhandler_disk_file methods with devices.
(fhandler_base::fhandler_base): Clear {unix,win32}_path_name.
(fhandler_base::~fhandler_base): Always free {unix,win32}_path_name.
(fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names kludge.
(fhandler_disk_file::open): Ditto.
* fhandler.h (fhandler_base::no_free_names): Eliminate.
(fhandler_base::set_no_free_names): Ditto.
* fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set
unix_path_name here.
* path.cc (fchdir): Lock fd table throughout.  Use new
dtable::reset_unix_path_name method to reset path.
* syscalls.cc (stat_worker): Reorganize to always call fstat method.  Pass
path_conv method to fhandler_*::open.
(chroot): Elminate a goto.
This commit is contained in:
Christopher Faylor
2001-10-01 04:10:07 +00:00
parent c25c4c5ffc
commit 47063f00e4
37 changed files with 315 additions and 293 deletions

View File

@@ -367,79 +367,76 @@ rmdir (const char *dir)
if (real_dir.error)
{
set_errno (real_dir.error);
goto done;
res = -1;
}
/* Does the file exist? */
if (real_dir.file_attributes () == (DWORD) -1)
else if (!real_dir.exists ())
{
set_errno (ENOENT);
goto done;
res = -1;
}
/* Is `dir' a directory? */
if (!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
else if (!real_dir.isdir ())
{
set_errno (ENOTDIR);
goto done;
}
/* Even own directories can't be removed if R/O attribute is set. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY)
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes () &
~FILE_ATTRIBUTE_READONLY);
if (RemoveDirectoryA (real_dir.get_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 (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1)
set_errno (ENOTEMPTY);
else
res = 0;
res = -1;
}
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))
{
DWORD err = GetLastError ();
if (!SetCurrentDirectory ("c:\\"))
SetLastError (err);
else
return rmdir (dir);
}
if (GetLastError() == ERROR_ACCESS_DENIED)
{
/* Even own directories can't be removed if R/O attribute is set. */
if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (real_dir,
(DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY);
/* On 9X ERROR_ACCESS_DENIED is returned if you try to remove
a non-empty directory. */
if (wincap.access_denied_on_delete ())
if (RemoveDirectory (real_dir))
{
/* 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 (GetFileAttributes (real_dir) != (DWORD) -1)
set_errno (ENOTEMPTY);
else
__seterrno ();
res = 0;
}
else
__seterrno ();
{
/* 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))
{
DWORD err = GetLastError ();
if (!SetCurrentDirectory ("c:\\"))
SetLastError (err);
else if ((res = rmdir (dir)))
SetCurrentDirectory (cygheap->cwd.win32);
}
if (GetLastError () == ERROR_ACCESS_DENIED)
{
/* If directory still exists, restore R/O attribute. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY)
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes ());
/* On 9X ERROR_ACCESS_DENIED is returned if you try to remove
a non-empty directory. */
if (wincap.access_denied_on_delete ())
set_errno (ENOTEMPTY);
else
__seterrno ();
}
else
__seterrno ();
/* If directory still exists, restore R/O attribute. */
if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (real_dir, real_dir);
}
}
done:
syscall_printf ("%d = rmdir (%s)", res, dir);
return res;
}