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:
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc151
1 files changed, 73 insertions, 78 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index bc655c84f..02ec2b398 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1752,7 +1752,6 @@ symlink_info::check_shortcut (HANDLE h)
buf = (char *) alloca (fsi.EndOfFile.LowPart + 1);
status = NtReadFile (h, NULL, NULL, NULL, &io, buf, fsi.EndOfFile.LowPart,
&off, NULL);
- status = wait_pending (status, h, io);
if (!NT_SUCCESS (status))
{
if (status != STATUS_END_OF_FILE)
@@ -1817,7 +1816,6 @@ symlink_info::check_sysfile (HANDLE h)
status = NtReadFile (h, NULL, NULL, NULL, &io, cookie_buf,
sizeof (cookie_buf), &off, NULL);
- status = wait_pending (status, h, io);
if (!NT_SUCCESS (status))
{
debug_printf ("ReadFile1 failed %p", status);
@@ -1851,7 +1849,6 @@ symlink_info::check_sysfile (HANDLE h)
{
status = NtReadFile (h, NULL, NULL, NULL, &io, srcbuf,
NT_MAX_PATH, &off, NULL);
- status = wait_pending (status, h, io);
if (!NT_SUCCESS (status))
{
debug_printf ("ReadFile2 failed");
@@ -2257,10 +2254,6 @@ restart:
PVOID eabuf = &nfs_aol_ffei;
ULONG easize = sizeof nfs_aol_ffei;
-# define MIN_STAT_ACCESS (READ_CONTROL | FILE_READ_ATTRIBUTES)
-# define FULL_STAT_ACCESS (SYNCHRONIZE | GENERIC_READ)
- ACCESS_MASK access = 0;
-
bool had_ext = !!*ext_here;
while (suffix.next ())
{
@@ -2278,23 +2271,14 @@ restart:
symlink (which would spoil the task of this method quite a bit).
Fortunately it's ignored on most other file systems so we don't have
to special case NFS too much. */
- status = NtCreateFile (&h, access = FULL_STAT_ACCESS, &attr, &io, NULL,
- 0, FILE_SHARE_VALID_FLAGS, FILE_OPEN,
+ status = NtCreateFile (&h,
+ READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA,
+ &attr, &io, NULL, 0, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN,
FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT,
eabuf, easize);
- if (status == STATUS_ACCESS_DENIED && eabuf)
- {
- status = NtCreateFile (&h, access = MIN_STAT_ACCESS | FILE_READ_EA,
- &attr, &io, NULL, 0, FILE_SHARE_VALID_FLAGS,
- FILE_OPEN,
- FILE_OPEN_REPARSE_POINT
- | FILE_OPEN_FOR_BACKUP_INTENT,
- eabuf, easize);
- debug_printf ("%p = NtCreateFile (2:%S)", status, &upath);
- }
- else
- debug_printf ("%p = NtCreateFile (1:%S)", status, &upath);
+ debug_printf ("%p = NtCreateFile (%S)", status, &upath);
/* No right to access EAs or EAs not supported? */
if (!NT_SUCCESS (status)
&& (status == STATUS_ACCESS_DENIED
@@ -2314,20 +2298,11 @@ restart:
eabuf = NULL;
easize = 0;
}
- status = NtOpenFile (&h, access = FULL_STAT_ACCESS, &attr, &io,
- FILE_SHARE_VALID_FLAGS,
+ status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES,
+ &attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_REPARSE_POINT
| FILE_OPEN_FOR_BACKUP_INTENT);
- if (status == STATUS_ACCESS_DENIED)
- {
- status = NtOpenFile (&h, access = MIN_STAT_ACCESS, &attr, &io,
- FILE_SHARE_VALID_FLAGS,
- FILE_OPEN_REPARSE_POINT
- | FILE_OPEN_FOR_BACKUP_INTENT);
- debug_printf ("%p = NtOpenFile (no-EAs 2:%S)", status, &upath);
- }
- else
- debug_printf ("%p = NtOpenFile (no-EA 1:%S)", status, &upath);
+ debug_printf ("%p = NtOpenFile (no-EAs %S)", status, &upath);
}
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
@@ -2559,19 +2534,66 @@ restart:
res = -1;
+ /* Reparse points are potentially symlinks. This check must be
+ performed before checking the SYSTEM attribute for sysfile
+ symlinks, since reparse points can have this flag set, too.
+ For instance, Vista starts to create a couple of reparse points
+ with SYSTEM and HIDDEN flags set. */
+ if ((fileattr & FILE_ATTRIBUTE_REPARSE_POINT))
+ {
+ /* Don't check reparse points on remote filesystems. A reparse point
+ pointing to another file on the remote system will be mistreated
+ as pointing to a local file on the local system. This breaks the
+ way reparse points are transparently handled on remote systems. */
+ if (fs.is_remote_drive())
+ res = 0;
+ else
+ res = check_reparse_point (h);
+ if (res == -1)
+ {
+ /* Volume mount point. The filesystem information for the top
+ level directory should be for the volume top level directory,
+ rather than for the reparse point itself. So we fetch the
+ filesystem information again, but with a NULL handle.
+ This does what we want because fs_info::update opens the
+ handle without FILE_OPEN_REPARSE_POINT. */
+ fs.update (&upath, NULL);
+ /* Make sure the open handle is not used in later stat calls.
+ The handle has been opened with the FILE_OPEN_REPARSE_POINT
+ flag, so it's a handle to the reparse point, not a handle
+ to the volumes root dir. */
+ pflags &= ~PC_KEEP_HANDLE;
+ }
+ else if (res)
+ {
+ /* A symlink is never a directory. */
+ conv_hdl.fnoi ()->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+ break;
+ }
+ }
+
/* Windows shortcuts are potentially treated as symlinks. Valid Cygwin
& U/WIN shortcuts are R/O, but definitely not directories. */
- if ((fileattr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY))
+ else if ((fileattr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY))
== FILE_ATTRIBUTE_READONLY && suffix.lnk_match ())
{
- if (!(access & GENERIC_READ))
+ HANDLE sym_h;
+
+ status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS (status))
res = 0;
else
- res = check_shortcut (h);
+ {
+ res = check_shortcut (sym_h);
+ NtClose (sym_h);
+ }
if (!res)
{
- /* If searching for `foo' and then finding a `foo.lnk' which is
- no shortcut, return the same as if file not found. */
+ /* If searching for `foo' and then finding a `foo.lnk' which
+ is no shortcut, return the same as if file not found. */
if (ext_tacked_on)
{
fileattr = INVALID_FILE_ATTRIBUTES;
@@ -2593,53 +2615,26 @@ restart:
continue;
}
- /* Reparse points are potentially symlinks. This check must be
- performed before checking the SYSTEM attribute for sysfile
- symlinks, since reparse points can have this flag set, too.
- For instance, Vista starts to create a couple of reparse points
- with SYSTEM and HIDDEN flags set.
- Also don't check reparse points on remote filesystems.
- A reparse point pointing to another file on the remote system will be
- mistreated as pointing to a local file on the local system. This
- breaks the way reparse points are transparently handled on remote
- systems. */
- else if ((fileattr & FILE_ATTRIBUTE_REPARSE_POINT)
- && !fs.is_remote_drive())
- {
- res = check_reparse_point (h);
- if (res == -1)
- {
- /* Volume mount point. The filesystem information for the top
- level directory should be for the volume top level directory,
- rather than for the reparse point itself. So we fetch the
- filesystem information again, but with a NULL handle.
- This does what we want because fs_info::update opens the
- handle without FILE_OPEN_REPARSE_POINT. */
- fs.update (&upath, NULL);
- /* Make sure the open handle is not used in later stat calls.
- The handle has been opened with the FILE_OPEN_REPARSE_POINT
- flag, so it's a handle to the reparse point, not a handle
- to the volumes root dir. */
- pflags &= ~PC_KEEP_HANDLE;
- }
- else if (res)
- {
- /* A symlink is never a directory. */
- conv_hdl.fnoi ()->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
- break;
- }
- }
-
/* This is the old Cygwin method creating symlinks. A symlink will
have the `system' file attribute. Only files can be symlinks
(which can be symlinks to directories). */
else if ((fileattr & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY))
== FILE_ATTRIBUTE_SYSTEM)
{
- if (!(access & GENERIC_READ))
+ HANDLE sym_h;
+
+ status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_SYNCHRONOUS_IO_NONALERT);
+
+ if (!NT_SUCCESS (status))
res = 0;
else
- res = check_sysfile (h);
+ {
+ res = check_sysfile (sym_h);
+ NtClose (sym_h);
+ }
if (res)
break;
}
@@ -2665,7 +2660,7 @@ restart:
if (h)
{
if (pflags & PC_KEEP_HANDLE)
- conv_hdl.set (h, access);
+ conv_hdl.set (h);
else
NtClose (h);
}