{
buf->st_mode |= S_IFREG;
/* Check suffix for executable file. */
- if (pc.exec_state () == dont_know_if_executable)
+ if (pc.exec_state () != is_executable)
{
PUNICODE_STRING path = pc.get_nt_native_path ();
shebang scripts. */
if (pc.exec_state () == dont_know_if_executable)
{
- LARGE_INTEGER off = { QuadPart:0LL };
- char magic[3];
+ OBJECT_ATTRIBUTES attr;
NTSTATUS status = 0;
IO_STATUS_BLOCK io;
- bool opened = false;
- if (h == get_handle ())
- {
- /* We have been opened via fstat. We have to re-open the
- file. Either the file is not opened for reading, or the
- read will change the file position. */
- OBJECT_ATTRIBUTES attr;
- pc.init_reopen_attr (&attr, h);
- status = NtOpenFile (&h, SYNCHRONIZE | FILE_READ_DATA,
- &attr, &io, FILE_SHARE_VALID_FLAGS,
- FILE_OPEN_FOR_BACKUP_INTENT
- | FILE_OPEN_REPARSE_POINT);
- if (!NT_SUCCESS (status))
- debug_printf ("%p = NtOpenFile(%S)", status,
- pc.get_nt_native_path ());
- else
- opened = true;
- }
- if (NT_SUCCESS (status))
+ /* We have to re-open the file. Either the file is not opened
+ for reading, or the read will change the file position of the
+ original handle. */
+ pc.init_reopen_attr (&attr, h);
+ status = NtOpenFile (&h, SYNCHRONIZE | FILE_READ_DATA,
+ &attr, &io, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS (status))
+ debug_printf ("%p = NtOpenFile(%S)", status,
+ pc.get_nt_native_path ());
+ else
{
+ LARGE_INTEGER off = { QuadPart:0LL };
+ char magic[3];
+
status = NtReadFile (h, NULL, NULL, NULL,
&io, magic, 3, &off, NULL);
- status = wait_pending (status, h, io);
if (!NT_SUCCESS (status))
debug_printf ("%p = NtReadFile(%S)", status,
pc.get_nt_native_path ());
pc.set_exec ();
buf->st_mode |= STD_XBITS;
}
+ NtClose (h);
}
- if (opened)
- NtClose (h);
}
}
if (pc.exec_state () == is_executable)
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)
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);
{
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");
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 ())
{
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
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)
{
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;
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;
}
if (h)
{
if (pflags & PC_KEEP_HANDLE)
- conv_hdl.set (h, access);
+ conv_hdl.set (h);
else
NtClose (h);
}