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:
-rw-r--r--winsup/cygwin/ChangeLog21
-rw-r--r--winsup/cygwin/fhandler.h1
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc43
-rw-r--r--winsup/cygwin/ntdll.h10
-rw-r--r--winsup/cygwin/path.cc151
-rw-r--r--winsup/cygwin/path.h16
6 files changed, 117 insertions, 125 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 582d769e8..12a4129cc 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,24 @@
+2010-09-07 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (fhandler_base::get_stat_access): Delete.
+ * fhandler_disk_file.cc (fhandler_base::fstat_helper): Always check
+ executable suffix to get x-bits for .exe files also in notexec case.
+ Always reopen file when checking for file header.
+ * ntdll.h (wait_pending): Delete.
+ * path.cc (symlink_info::check_shortcut): Drop call to wait_pending
+ since file is always opened for sync IO.
+ (symlink_info::check_sysfile): Ditto.
+ (MIN_STAT_ACCESS): Remove.
+ (FULL_STAT_ACCESS): Remove.
+ (symlink_info::check): Drop access flag. Revert to open file with
+ just read attributes access. Reorder symlink check to check for
+ reparse points first. Don't check reparse points for anything else,
+ even on remote drives. Open file for GENERIC_READ when trying to
+ read shortcuts or system-bit symlinks. Accommodate dropped access
+ flag in call to path_conv_handle::set.
+ * path.h (class path_conv_handle): Drop access flag and accommodate
+ all related methods.
+
2010-09-06 Corinna Vinschen <corinna@vinschen.de>
* posix_ipc.cc (ipc_mutex_init): Call NtCreateMutant to make sure the
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 5110d6d8c..42a0f2407 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -198,7 +198,6 @@ class fhandler_base
int get_access () const { return access; }
void set_access (int x) { access = x; }
- int get_stat_access () const { return pc.handle () ? pc.access () : access; }
int get_flags () { return openflags; }
void set_flags (int x, int supplied_bin = 0);
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 13ed5ed5e..aea62a1b2 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -591,7 +591,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
{
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 ();
@@ -604,34 +604,28 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
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 ());
@@ -641,9 +635,8 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
pc.set_exec ();
buf->st_mode |= STD_XBITS;
}
+ NtClose (h);
}
- if (opened)
- NtClose (h);
}
}
if (pc.exec_state () == is_executable)
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 1bbc78bc3..41c84a2ce 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -879,16 +879,6 @@ typedef enum _EVENT_INFORMATION_CLASS
#define NtCurrentProcess() ((HANDLE) 0xffffffff)
#define NtCurrentThread() ((HANDLE) 0xfffffffe)
-/* Helper macro for sync I/O with async handle. */
-inline NTSTATUS
-wait_pending (NTSTATUS status, HANDLE h, IO_STATUS_BLOCK &io)
-{
- if (status != STATUS_PENDING)
- return status;
- WaitForSingleObject (h, INFINITE);
- return io.Status;
-}
-
extern "C"
{
NTSTATUS NTAPI NtAdjustPrivilegesToken (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES,
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);
}
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 877334f55..c5b10e3c7 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -95,7 +95,6 @@ struct _FILE_NETWORK_OPEN_INFORMATION;
class path_conv_handle
{
HANDLE hdl;
- ACCESS_MASK acc;
union {
/* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in
ntdll.h here, though. */
@@ -112,26 +111,22 @@ class path_conv_handle
fattr3 _fattr3;
} attribs;
public:
- path_conv_handle () : hdl (NULL), acc (0) {}
- inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; }
+ path_conv_handle () : hdl (NULL) {}
+ inline void set (HANDLE h) { hdl = h; }
inline void close ()
{
if (hdl)
CloseHandle (hdl);
- set (NULL, 0);
+ set (NULL);
}
inline void dup (path_conv_handle &pch)
{
if (!DuplicateHandle (GetCurrentProcess (), pch.handle (),
GetCurrentProcess (), &hdl,
0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- hdl = NULL;
- acc = 0;
- }
+ hdl = NULL;
}
inline HANDLE handle () const { return hdl; }
- inline ACCESS_MASK access () const { return acc; }
inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi ()
{ return (struct _FILE_NETWORK_OPEN_INFORMATION *) &attribs._fnoi; }
inline struct fattr3 *nfsattr ()
@@ -325,10 +320,9 @@ class path_conv
bool is_binary ();
HANDLE handle () const { return conv_handle.handle (); }
- ACCESS_MASK access () const { return conv_handle.access (); }
struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return conv_handle.fnoi (); }
struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
- void reset_conv_handle () { conv_handle.set (NULL, 0); }
+ void reset_conv_handle () { conv_handle.set (NULL); }
void close_conv_handle () { conv_handle.close (); }
__ino64_t get_ino_by_handle (HANDLE h);