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-03-02 23:04:26 +0300
committerCorinna Vinschen <corinna@vinschen.de>2007-03-02 23:04:26 +0300
commit788e7da136e19ec6e3e5d40872eb728677f9a4cc (patch)
treeb43e12c495987dd926f951918252aa5419f18c14 /winsup
parent35328778895f786e1db88faba245c96a377e0b38 (diff)
* ntdll.h (struct _OBJECT_NAME_INFORMATION): Define.
* syscalls.cc (unlink_nt): Check shared directory for being empty before trying to move and mark for deletion.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/ntdll.h8
-rw-r--r--winsup/cygwin/syscalls.cc53
3 files changed, 65 insertions, 2 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 12a48d1c4..0d5144b1f 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,11 @@
2007-03-02 Corinna Vinschen <corinna@vinschen.de>
+ * ntdll.h (struct _OBJECT_NAME_INFORMATION): Define.
+ * syscalls.cc (unlink_nt): Check shared directory for being empty
+ before trying to move and mark for deletion.
+
+2007-03-02 Corinna Vinschen <corinna@vinschen.de>
+
* security.cc (get_file_attribute): Avoid compiler warning.
2007-03-01 Christopher Faylor <me@cgf.cx>
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 4fc5da599..0bbb5a521 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -79,6 +79,14 @@ typedef enum _FILE_INFORMATION_CLASS
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+typedef struct _FILE_NAMES_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
+
typedef struct _FILE_BOTH_DIR_INFORMATION
{
ULONG NextEntryOffset;
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 30a67b876..e564eddc5 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -283,8 +283,57 @@ unlink_nt (path_conv &win32_name, bool setattrs)
if (status == STATUS_SHARING_VIOLATION)
{
move_to_bin = true;
- status = NtOpenFile (&h, DELETE, &attr, &io, FILE_SHARE_VALID_FLAGS,
- flags);
+ if (!win32_name.isdir () || win32_name.isremote ())
+ status = NtOpenFile (&h, DELETE, &attr, &io, FILE_SHARE_VALID_FLAGS,
+ flags);
+ else
+ {
+ /* It's getting tricky. The directory is opened in some process,
+ so we're supposed to move it to the recycler and mark it for
+ deletion. But what if the directory is not empty? The move
+ will work, but the subsequent delete will fail. So we would
+ have to move it back. That's bad, because the directory would
+ be moved around which results in a temporary inconsistent state.
+ So, what we do here is to test if the directory is empty. If
+ not, we bail out with ERROR_DIR_NOT_EMTPY. The below code
+ tests for at least three entries in the directory, ".", "..",
+ and another one. Three entries means, not empty. This doesn't
+ work for the root directory of a drive, but the root dir can
+ neither be deleted, nor moved anyway. */
+ status = NtOpenFile (&h, DELETE | SYNCHRONIZE | FILE_LIST_DIRECTORY,
+ &attr, &io, FILE_SHARE_VALID_FLAGS,
+ flags | FILE_SYNCHRONOUS_IO_NONALERT);
+ if (NT_SUCCESS (status))
+ {
+ const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
+ + 3 * NAME_MAX * sizeof (WCHAR);
+ PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
+ alloca (bufsiz);
+ status = NtQueryDirectoryFile (h, NULL, NULL, 0, &io, pfni,
+ bufsiz, FileNamesInformation,
+ FALSE, NULL, TRUE);
+ if (!NT_SUCCESS (status))
+ {
+ NtClose (h);
+ syscall_printf ("Checking if directory is empty failed, "
+ "status = %p", status);
+ return RtlNtStatusToDosError (status);
+ }
+ int cnt = 1;
+ while (pfni->NextEntryOffset)
+ {
+ pfni = (PFILE_NAMES_INFORMATION)
+ ((caddr_t) pfni + pfni->NextEntryOffset);
+ ++cnt;
+ }
+ if (cnt > 2)
+ {
+ NtClose (h);
+ syscall_printf ("Directory not empty");
+ return ERROR_DIR_NOT_EMPTY;
+ }
+ }
+ }
}
if (!NT_SUCCESS (status))
{