4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-31 11:30:56 +08:00

* fhandler_disk_file.cc (fhandler_disk_file::rmdir): Implement rmdir

on NT by calling unlink_nt.  Check for directory here.
	* syscalls.cc (try_to_bin): Fix buggy debug_printf statement.
	(unlink_nt): Make non-static.  Don't use delete-on-close semantics on
	directoires.  Explain why.
This commit is contained in:
Corinna Vinschen 2007-01-26 12:25:23 +00:00
parent 2731a97413
commit 3be6ababd8
3 changed files with 48 additions and 18 deletions

View File

@ -1,3 +1,11 @@
2007-01-26 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::rmdir): Implement rmdir
on NT by calling unlink_nt. Check for directory here.
* syscalls.cc (try_to_bin): Fix buggy debug_printf statement.
(unlink_nt): Make non-static. Don't use delete-on-close semantics on
directoires. Explain why.
2007-01-24 Corinna Vinschen <corinna@vinschen.de> 2007-01-24 Corinna Vinschen <corinna@vinschen.de>
* net.cc (if_nametoindex): This time, really free IP_ADAPTER_ADDRESSES * net.cc (if_nametoindex): This time, really free IP_ADAPTER_ADDRESSES

View File

@ -1447,15 +1447,31 @@ fhandler_disk_file::mkdir (mode_t mode)
int int
fhandler_disk_file::rmdir () fhandler_disk_file::rmdir ()
{ {
extern DWORD unlink_nt (path_conv &win32_name, bool setattrs);
int res = -1; int res = -1;
if (!pc.isdir ())
{
set_errno (ENOTDIR);
return -1;
}
/* Even own directories can't be removed if R/O attribute is set. */ /* Even own directories can't be removed if R/O attribute is set. */
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY)) if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (get_win32_name (), SetFileAttributes (get_win32_name (),
(DWORD) pc & ~FILE_ATTRIBUTE_READONLY); (DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
DWORD err, att = 0; DWORD err, att = 0;
int rc = RemoveDirectory (get_win32_name ()); int rc;
if (wincap.is_winnt ())
{
rc = !(err = unlink_nt (pc, pc.has_attribute (FILE_ATTRIBUTE_READONLY)));
if (err)
SetLastError (err);
}
else
rc = RemoveDirectory (get_win32_name ());
if (isremote () && exists ()) if (isremote () && exists ())
att = GetFileAttributes (get_win32_name ()); att = GetFileAttributes (get_win32_name ());
@ -1488,7 +1504,7 @@ fhandler_disk_file::rmdir ()
__seterrno_from_win_error (err); __seterrno_from_win_error (err);
/* Directory still exists, restore its characteristics. */ /* Directory still exists, restore its characteristics. */
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY)) if (!wincap.is_winnt () && pc.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (get_win32_name (), (DWORD) pc); SetFileAttributes (get_win32_name (), (DWORD) pc);
return res; return res;

View File

@ -225,7 +225,8 @@ try_to_bin (path_conv &win32_path, HANDLE h)
pfri->FileNameLength = uname.Length; pfri->FileNameLength = uname.Length;
status = NtSetInformationFile (h, &io, pfri, size, FileRenameInformation); status = NtSetInformationFile (h, &io, pfri, size, FileRenameInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
debug_printf ("Move %s to %s failed, status = %p", status); debug_printf ("Move %s to %s failed, status = %p", win32_path.get_win32 (),
recycler, status);
} }
static DWORD static DWORD
@ -236,7 +237,7 @@ unlink_9x (path_conv &win32_name)
return GetLastError (); return GetLastError ();
} }
static DWORD DWORD
unlink_nt (path_conv &win32_name, bool setattrs) unlink_nt (path_conv &win32_name, bool setattrs)
{ {
WCHAR wpath[CYG_MAX_PATH + 10]; WCHAR wpath[CYG_MAX_PATH + 10];
@ -247,19 +248,24 @@ unlink_nt (path_conv &win32_name, bool setattrs)
HANDLE h; HANDLE h;
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT; ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
/* Don't try "delete on close" if the file is on a remote share. If two /* Don't open directories with "delete on close", because the NT internal
processes have open handles on a file and one of them calls unlink, semantic is apparently different from the file semantic. If a directory
then it happens that the file is remove from the remote share even is opened "delete on close", the rename operation in try_to_bin fails
though the other process still has an open handle. This other process with STATUS_ACCESS_DENIED. So directories must be deleted using
than gets Win32 error 59, ERROR_UNEXP_NET_ERR when trying to access the NtSetInformationFile, class FileDispositionInformation, which works fine.
file.
That does not happen when using DeleteFile (NtSetInformationFile, class Don't try "delete on close" if the file is on a remote share. If two
FileDispositionInformation), which nicely succeeds but still, the file processes have open handles on a file and one of them calls unlink, then
is available for the other process. it happens that the file is removed from the remote share even though the
Microsoft KB 837665 describes this problem as a bug in 2K3, but I have other process still has an open handle. This other process than gets
reproduced it on shares on Samba 2.2.8, Samba 3.0.2, NT4SP6, XP64SP1 and Win32 error 59, ERROR_UNEXP_NET_ERR when trying to access the file. That
2K3 and in all cases, DeleteFile works, "delete on close" does not. */ does not happen when using NtSetInformationFile, class
if (!win32_name.isremote ()) FileDispositionInformation, which nicely succeeds but still, the file is
available for the other process. Microsoft KB 837665 describes this
problem as a bug in 2K3, but I have reproduced it on shares on Samba
2.2.8, Samba 3.0.2, NT4SP6, XP64SP1 and 2K3 and in all cases, DeleteFile
works, "delete on close" does not. */
if (!win32_name.isdir () && !win32_name.isremote ())
flags |= FILE_DELETE_ON_CLOSE; flags |= FILE_DELETE_ON_CLOSE;
/* Add the reparse point flag to native symlinks, otherwise we remove the /* Add the reparse point flag to native symlinks, otherwise we remove the
target, not the symlink. */ target, not the symlink. */
@ -301,7 +307,7 @@ unlink_nt (path_conv &win32_name, bool setattrs)
DWORD lasterr = 0; DWORD lasterr = 0;
if (win32_name.isremote ()) if (win32_name.isdir () || win32_name.isremote ())
{ {
FILE_DISPOSITION_INFORMATION disp = { TRUE }; FILE_DISPOSITION_INFORMATION disp = { TRUE };
status = NtSetInformationFile (h, &io, &disp, sizeof disp, status = NtSetInformationFile (h, &io, &disp, sizeof disp,