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
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2007-08-01 18:46:09 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-08-01 18:46:09 +0400
commit8884a1682ad6f67fa3473a3e0405ea2898e01863 (patch)
treec0cf39c46fe878ce32bdd8c48fd3eaac9f461525
parente9ff75192a61741d7f0b3c61e04a7648b195aed5 (diff)
* ntdll.h (STATUS_ACCESS_DENIED): Define.
* syscalls.cc (check_dir_not_empty): New static function. (unlink_nt): Move code checking for non-empty dir to check_dir_not_empty and call check_dir_not_empty instead. (rename): Add fault handler. Check oldpath and newpath for trailing . and .. path components and return EINVAL if so. Check oldpath for being on a vrtual file system. If renaming a dir fails with STATUS_ACCESS_DENIED, check if the target dir is non-empty and return ENOTEMPTY if so.
-rw-r--r--winsup/cygwin/ChangeLog12
-rw-r--r--winsup/cygwin/ntdll.h1
-rw-r--r--winsup/cygwin/syscalls.cc92
3 files changed, 80 insertions, 25 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3d3ea9b01..222d03f31 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,17 @@
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
+ * ntdll.h (STATUS_ACCESS_DENIED): Define.
+ * syscalls.cc (check_dir_not_empty): New static function.
+ (unlink_nt): Move code checking for non-empty dir to check_dir_not_empty
+ and call check_dir_not_empty instead.
+ (rename): Add fault handler. Check oldpath and newpath for trailing
+ . and .. path components and return EINVAL if so. Check oldpath
+ for being on a vrtual file system. If renaming a dir fails with
+ STATUS_ACCESS_DENIED, check if the target dir is non-empty and return
+ ENOTEMPTY if so.
+
+2007-08-01 Corinna Vinschen <corinna@vinschen.de>
+
* localtime.cc (tzsetwall): Don't set TZ.
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 8936dd44c..0eca36275 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -17,6 +17,7 @@
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
+#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 6e1f78185..1c202e33e 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -228,6 +228,38 @@ try_to_bin (path_conv &win32_path, HANDLE h)
recycler, status);
}
+static NTSTATUS
+check_dir_not_empty (HANDLE dir)
+{
+ IO_STATUS_BLOCK io;
+ const ULONG bufsiz = 3 * sizeof (FILE_NAMES_INFORMATION)
+ + 3 * NAME_MAX * sizeof (WCHAR);
+ PFILE_NAMES_INFORMATION pfni = (PFILE_NAMES_INFORMATION)
+ alloca (bufsiz);
+ NTSTATUS status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, pfni,
+ bufsiz, FileNamesInformation,
+ FALSE, NULL, TRUE);
+ if (!NT_SUCCESS (status))
+ {
+ syscall_printf ("Checking if directory is empty failed, "
+ "status = %p", status);
+ return status;
+ }
+ int cnt = 1;
+ while (pfni->NextEntryOffset)
+ {
+ pfni = (PFILE_NAMES_INFORMATION)
+ ((caddr_t) pfni + pfni->NextEntryOffset);
+ ++cnt;
+ }
+ if (cnt > 2)
+ {
+ syscall_printf ("Directory not empty");
+ return STATUS_DIRECTORY_NOT_EMPTY;
+ }
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
unlink_nt (path_conv &pc)
{
@@ -284,33 +316,12 @@ unlink_nt (path_conv &pc)
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 (fh, NULL, NULL, 0, &io, pfni,
- bufsiz, FileNamesInformation,
- FALSE, NULL, TRUE);
+ status = check_dir_not_empty (fh);
if (!NT_SUCCESS (status))
{
NtClose (fh);
- syscall_printf ("Checking if directory is empty failed, "
- "status = %p", status);
return status;
}
- int cnt = 1;
- while (pfni->NextEntryOffset)
- {
- pfni = (PFILE_NAMES_INFORMATION)
- ((caddr_t) pfni + pfni->NextEntryOffset);
- ++cnt;
- }
- if (cnt > 2)
- {
- NtClose (fh);
- syscall_printf ("Directory not empty");
- return STATUS_DIRECTORY_NOT_EMPTY;
- }
}
}
}
@@ -1347,7 +1358,18 @@ rename (const char *oldpath, const char *newpath)
IO_STATUS_BLOCK io;
ULONG size;
PFILE_RENAME_INFORMATION pfri;
-
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ if (has_dot_last_component (oldpath, true)
+ || has_dot_last_component (newpath, true))
+ {
+ set_errno (EINVAL);
+ goto out;
+ }
+
oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
if (oldpc.error)
{
@@ -1359,6 +1381,11 @@ rename (const char *oldpath, const char *newpath)
set_errno (ENOENT);
goto out;
}
+ if (oldpc.isspecial ()) /* No renames from virtual FS */
+ {
+ set_errno (EROFS);
+ goto out;
+ }
olen = strlen (oldpath);
if (oldpc.known_suffix
&& (strcasematch (oldpath + olen - 4, ".lnk")
@@ -1371,7 +1398,7 @@ rename (const char *oldpath, const char *newpath)
set_errno (newpc.error);
goto out;
}
- if (newpc.isspecial ()) /* No renames out of the FS */
+ if (newpc.isspecial ()) /* No renames to virtual FSes */
{
set_errno (EROFS);
goto out;
@@ -1509,7 +1536,22 @@ rename (const char *oldpath, const char *newpath)
res = 0;
}
else
- __seterrno_from_nt_status (status);
+ {
+ /* Check in case of STATUS_ACCESS_DENIED and pc.isdir(),
+ whether we tried to rename to an existing non-empty dir.
+ In this case we have to set errno to EEXIST. */
+ if (status == STATUS_ACCESS_DENIED && dstpc->isdir ()
+ && NT_SUCCESS (NtOpenFile (&fh, FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ dstpc->get_object_attr (attr, sec_none_nih),
+ &io, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_SYNCHRONOUS_IO_NONALERT)))
+ {
+ status = check_dir_not_empty (fh);
+ NtClose (fh);
+ }
+ __seterrno_from_nt_status (status);
+ }
NtClose (fh);
out: