diff options
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 21 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 43 | ||||
-rw-r--r-- | winsup/cygwin/ntdll.h | 10 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 151 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 16 |
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); |