Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-01-26 15:25:23 +0300
committerCorinna Vinschen <corinna@vinschen.de>2007-01-26 15:25:23 +0300
commit3be6ababd859281d09ab68ff1a596d93f8fc7860 (patch)
treee26b4b16a166e7ce1b2cece07da549206aa582cc /winsup
parent2731a97413e8d3d035588da5e74ef8ea9e11fd90 (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog8
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc20
-rw-r--r--winsup/cygwin/syscalls.cc38
3 files changed, 48 insertions, 18 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index addb06f6a..0bb91878a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* net.cc (if_nametoindex): This time, really free IP_ADAPTER_ADDRESSES
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 43aeff6b4..7de7e56ba 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1447,15 +1447,31 @@ fhandler_disk_file::mkdir (mode_t mode)
int
fhandler_disk_file::rmdir ()
{
+ extern DWORD unlink_nt (path_conv &win32_name, bool setattrs);
+
int res = -1;
+ if (!pc.isdir ())
+ {
+ set_errno (ENOTDIR);
+ return -1;
+ }
/* Even own directories can't be removed if R/O attribute is set. */
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (get_win32_name (),
(DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
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 ())
att = GetFileAttributes (get_win32_name ());
@@ -1488,7 +1504,7 @@ fhandler_disk_file::rmdir ()
__seterrno_from_win_error (err);
/* 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);
return res;
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 85a43818d..8aec2e649 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -225,7 +225,8 @@ try_to_bin (path_conv &win32_path, HANDLE h)
pfri->FileNameLength = uname.Length;
status = NtSetInformationFile (h, &io, pfri, size, FileRenameInformation);
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
@@ -236,7 +237,7 @@ unlink_9x (path_conv &win32_name)
return GetLastError ();
}
-static DWORD
+DWORD
unlink_nt (path_conv &win32_name, bool setattrs)
{
WCHAR wpath[CYG_MAX_PATH + 10];
@@ -247,19 +248,24 @@ unlink_nt (path_conv &win32_name, bool setattrs)
HANDLE h;
ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT;
- /* Don't try "delete on close" if the file is on a remote share. If two
- processes have open handles on a file and one of them calls unlink,
- then it happens that the file is remove from the remote share even
- though the other process still has an open handle. This other process
- than gets Win32 error 59, ERROR_UNEXP_NET_ERR when trying to access the
- file.
- That does not happen when using DeleteFile (NtSetInformationFile, class
- 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.isremote ())
+ /* Don't open directories with "delete on close", because the NT internal
+ semantic is apparently different from the file semantic. If a directory
+ is opened "delete on close", the rename operation in try_to_bin fails
+ with STATUS_ACCESS_DENIED. So directories must be deleted using
+ NtSetInformationFile, class FileDispositionInformation, which works fine.
+
+ Don't try "delete on close" if the file is on a remote share. If two
+ processes have open handles on a file and one of them calls unlink, then
+ it happens that the file is removed from the remote share even though the
+ other process still has an open handle. This other process than gets
+ Win32 error 59, ERROR_UNEXP_NET_ERR when trying to access the file. That
+ does not happen when using NtSetInformationFile, class
+ 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;
/* Add the reparse point flag to native symlinks, otherwise we remove the
target, not the symlink. */
@@ -301,7 +307,7 @@ unlink_nt (path_conv &win32_name, bool setattrs)
DWORD lasterr = 0;
- if (win32_name.isremote ())
+ if (win32_name.isdir () || win32_name.isremote ())
{
FILE_DISPOSITION_INFORMATION disp = { TRUE };
status = NtSetInformationFile (h, &io, &disp, sizeof disp,