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
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2010-09-13 15:17:36 +0400
committerCorinna Vinschen <corinna@vinschen.de>2010-09-13 15:17:36 +0400
commitc80480bfa06d18700c434d034db4915fc358efab (patch)
treec08774b847b47bbc038cf551e8dbe7457ce1dd24 /winsup
parentf7382efe279a5cb5fa6dcb0021ba89e8ba98fb31 (diff)
* fhandler.h (class fhandler_base): Change inheritance of fstat_helper
and fstat_by_... methods to private. (fhandler_base::fstat_helper): Drop all redundant arguments. * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call to fstat_by_nfs_ea here. Drop fetching basic file information. Drop setting file attributes. Accommodate change in fstat_helper call. (fhandler_base::fstat_by_name): Simplify. Only fetch directory information to get the inode number. Drop setting file attributes. Accommodate change in fstat_helper call. (fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS. (fhandler_base::fstat_helper): Drop all redundant arguments. Use information already collected in the fhandler. Move heading comment into code and drop dwFileAttributes comment. * mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle. * mount.cc (fs_info::update): Note that has_buggy_basic_info is unused. * path.cc (symlink_info::check_reparse_point): Add comment. (symlink_info::check): Fetch FileNetworkOpenInformation rather than FileBasicInformation throughout, except on NFS. Explain why. Store FILE_NETWORK_OPEN_INFORMATION in conv_hdl. Remove FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point symlinks. * path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION member _fnoi. (path_conv_handle::fnoi): New accessor method for _fnoi. (path_conv::fnoi): New accessor method for cubv_hdl._fnoi. * fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog30
-rw-r--r--winsup/cygwin/fhandler.h15
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc208
-rw-r--r--winsup/cygwin/fhandler_tty.cc2
-rw-r--r--winsup/cygwin/mmap.cc4
-rw-r--r--winsup/cygwin/mount.cc3
-rw-r--r--winsup/cygwin/path.cc45
-rw-r--r--winsup/cygwin/path.h19
8 files changed, 146 insertions, 180 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 00cfd3209..dbea36cdc 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,33 @@
+2010-09-13 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (class fhandler_base): Change inheritance of fstat_helper
+ and fstat_by_... methods to private.
+ (fhandler_base::fstat_helper): Drop all redundant arguments.
+ * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call
+ to fstat_by_nfs_ea here. Drop fetching basic file information.
+ Drop setting file attributes. Accommodate change in fstat_helper call.
+ (fhandler_base::fstat_by_name): Simplify. Only fetch directory
+ information to get the inode number. Drop setting file attributes.
+ Accommodate change in fstat_helper call.
+ (fhandler_base::fstat_fs): Call fstat_by_nfs_ea if on NFS.
+ (fhandler_base::fstat_helper): Drop all redundant arguments. Use
+ information already collected in the fhandler. Move heading comment
+ into code and drop dwFileAttributes comment.
+ * mmap.cc (mmap64): Call fstat_fs rather than fstat_by_handle.
+ * mount.cc (fs_info::update): Note that has_buggy_basic_info is unused.
+ * path.cc (symlink_info::check_reparse_point): Add comment.
+ (symlink_info::check): Fetch FileNetworkOpenInformation rather than
+ FileBasicInformation throughout, except on NFS. Explain why. Store
+ FILE_NETWORK_OPEN_INFORMATION in conv_hdl. Remove
+ FILE_ATTRIBUTE_DIRECTORY attribute in conv_hdl for reparse point
+ symlinks.
+ * path.h (class path_conv_handle): Add FILE_NETWORK_OPEN_INFORMATION
+ member _fnoi.
+ (path_conv_handle::fnoi): New accessor method for _fnoi.
+ (path_conv::fnoi): New accessor method for cubv_hdl._fnoi.
+
+ * fhandler_tty.cc (fhandler_tty_slave::init): Use tty::setpgid method.
+
2010-09-12 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (acl_worker): Remove.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3fcfe1cef..8e232f0c4 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -293,21 +293,14 @@ class fhandler_base
int close_fs () { return fhandler_base::close (); }
virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2)));
+private:
int __stdcall fstat_helper (struct __stat64 *buf,
- PLARGE_INTEGER ChangeTime,
- PLARGE_INTEGER LastAccessTime,
- PLARGE_INTEGER LastWriteTime,
- PLARGE_INTEGER CreationTime,
- DWORD dwVolumeSerialNumber,
- ULONGLONG nFileSize,
- LONGLONG nAllocSize,
- ULONGLONG nFileIndex,
- DWORD nNumberOfLinks,
- DWORD dwFileAttributes)
- __attribute__ ((regparm (3)));
+ DWORD nNumberOfLinks)
+ __attribute__ ((regparm (3)));
int __stdcall fstat_by_nfs_ea (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2)));
+public:
virtual int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int utimens_fs (const struct timespec *) __attribute__ ((regparm (2)));
virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index c7ecf48e8..b9c62b27a 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -345,43 +345,17 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf)
int __stdcall
fhandler_base::fstat_by_handle (struct __stat64 *buf)
{
- NTSTATUS status;
- IO_STATUS_BLOCK io;
-
- if (pc.fs_is_nfs ())
- return fstat_by_nfs_ea (buf);
-
/* Don't use FileAllInformation info class. It returns a pathname rather
than a filename, so it needs a really big buffer for no good reason
since we don't need the name anyway. So we just call the three info
classes necessary to get all information required by stat(2). */
-
- union {
- FILE_BASIC_INFORMATION fbi;
- FILE_NETWORK_OPEN_INFORMATION fnoi;
- } fi;
FILE_STANDARD_INFORMATION fsi;
FILE_INTERNAL_INFORMATION fii;
HANDLE h = get_stat_handle ();
+ NTSTATUS status = 0;
+ IO_STATUS_BLOCK io;
- if (pc.has_buggy_basic_info ())
- {
- status = NtQueryInformationFile (h, &io, &fi, sizeof fi,
- FileNetworkOpenInformation);
- /* The timestamps are in the same relative memory location, only
- the DOS attributes have to be moved. */
- fi.fbi.FileAttributes = fi.fnoi.FileAttributes;
- }
- else
- status = NtQueryInformationFile (h, &io, &fi.fbi,
- sizeof fi.fbi, FileBasicInformation);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("%p = NtQueryInformationFile(%S, FileBasicInformation)",
- status, pc.get_nt_native_path ());
- return -1;
- }
status = NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
FileStandardInformation);
if (!NT_SUCCESS (status))
@@ -402,26 +376,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
}
ino = fii.FileId.QuadPart;
}
- /* If the change time is 0, it's a file system which doesn't
- support a change timestamp. In that case use the LastWriteTime
- entry, as in other calls to fstat_helper. */
- if (pc.is_rep_symlink ())
- fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
- /* Only copy attributes if not a device root dir. */
- if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
- pc.file_attributes (fi.fbi.FileAttributes);
- return fstat_helper (buf,
- fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime
- : &fi.fbi.LastWriteTime,
- &fi.fbi.LastAccessTime,
- &fi.fbi.LastWriteTime,
- &fi.fbi.CreationTime,
- get_dev (),
- fsi.EndOfFile.QuadPart,
- fsi.AllocationSize.QuadPart,
- ino,
- fsi.NumberOfLinks,
- fi.fbi.FileAttributes);
+ return fstat_helper (buf, fsi.NumberOfLinks);
}
int __stdcall
@@ -437,76 +392,35 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
FILE_ID_BOTH_DIR_INFORMATION fdi;
WCHAR buf[NAME_MAX + 1];
} fdi_buf;
- LARGE_INTEGER FileId;
- RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
- InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (),
- NULL, NULL);
- if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
- &attr, &io, FILE_SHARE_VALID_FLAGS,
- FILE_SYNCHRONOUS_IO_NONALERT
- | FILE_OPEN_FOR_BACKUP_INTENT
- | FILE_DIRECTORY_FILE)))
- {
- debug_printf ("%p = NtOpenFile(%S)", status, pc.get_nt_native_path ());
- goto too_bad;
- }
- if (wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ()
- && NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io,
- &fdi_buf.fdi, sizeof fdi_buf,
- FileIdBothDirectoryInformation,
- TRUE, &basename, TRUE)))
- FileId = fdi_buf.fdi.FileId;
- else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, NULL,
- &io, &fdi_buf.fdi,
- sizeof fdi_buf,
- FileBothDirectoryInformation,
- TRUE, &basename, TRUE)))
- FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */
- if (!NT_SUCCESS (status))
+ if (!ino && wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ())
{
- debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
- pc.get_nt_native_path ());
- NtClose (dir);
- goto too_bad;
- }
- NtClose (dir);
- /* If the change time is 0, it's a file system which doesn't
- support a change timestamp. In that case use the LastWriteTime
- entry, as in other calls to fstat_helper. */
- if (pc.is_rep_symlink ())
- fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
- /* Only copy attributes if not a device root dir. */
- if (!(pc.file_attributes () & FILE_ATTRIBUTE_DEVICE))
- pc.file_attributes (fdi_buf.fdi.FileAttributes);
- return fstat_helper (buf,
- fdi_buf.fdi.ChangeTime.QuadPart
- ? &fdi_buf.fdi.ChangeTime : &fdi_buf.fdi.LastWriteTime,
- &fdi_buf.fdi.LastAccessTime,
- &fdi_buf.fdi.LastWriteTime,
- &fdi_buf.fdi.CreationTime,
- pc.fs_serial_number (),
- fdi_buf.fdi.EndOfFile.QuadPart,
- fdi_buf.fdi.AllocationSize.QuadPart,
- FileId.QuadPart,
- 1,
- fdi_buf.fdi.FileAttributes);
-
-too_bad:
- LARGE_INTEGER ft;
- /* Arbitrary value: 2006-12-01 */
- RtlSecondsSince1970ToTime (1164931200L, &ft);
- return fstat_helper (buf,
- &ft,
- &ft,
- &ft,
- &ft,
- 0,
- 0ULL,
- -1LL,
- 0ULL,
- 1,
- pc.file_attributes ());
+ RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
+ InitializeObjectAttributes (&attr, &dirname, pc.objcaseinsensitive (),
+ NULL, NULL);
+ status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
+ &attr, &io, FILE_SHARE_VALID_FLAGS,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_DIRECTORY_FILE);
+ if (!NT_SUCCESS (status))
+ debug_printf ("%p = NtOpenFile(%S)", status,
+ pc.get_nt_native_path ());
+ else
+ {
+ status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io,
+ &fdi_buf.fdi, sizeof fdi_buf,
+ FileIdBothDirectoryInformation,
+ TRUE, &basename, TRUE);
+ NtClose (dir);
+ if (!NT_SUCCESS (status))
+ debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
+ pc.get_nt_native_path ());
+ else
+ ino = fdi_buf.fdi.FileId.QuadPart;
+ }
+ }
+ return fstat_helper (buf, 1);
}
int __stdcall
@@ -519,7 +433,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
if (get_stat_handle ())
{
if (!nohandle () && !is_fs_special ())
- res = fstat_by_handle (buf);
+ res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf);
if (res)
res = fstat_by_name (buf);
return res;
@@ -540,7 +454,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
Since fhandler_base::open only calls CloseHandle if !nohandle,
we have to set it to false before calling close and restore
the state afterwards. */
- res = fstat_by_handle (buf);
+ res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf);
bool no_handle = nohandle ();
nohandle (false);
close_fs ();
@@ -553,39 +467,26 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
return res;
}
-/* The ChangeTime is taken from the NTFS ChangeTime entry, if reading
- the file information using NtQueryInformationFile succeeded. If not,
- it's faked using the LastWriteTime entry from GetFileInformationByHandle
- or FindFirstFile. We're deliberatly not using the creation time anymore
- to simplify interaction with native Windows applications which choke on
- creation times >= access or write times.
-
- Note that the dwFileAttributes member of the file information evaluated
- in the calling function is used here, not the pc.fileattr member, since
- the latter might be old and not reflect the actual state of the file. */
int __stdcall
fhandler_base::fstat_helper (struct __stat64 *buf,
- PLARGE_INTEGER ChangeTime,
- PLARGE_INTEGER LastAccessTime,
- PLARGE_INTEGER LastWriteTime,
- PLARGE_INTEGER CreationTime,
- DWORD dwVolumeSerialNumber,
- ULONGLONG nFileSize,
- LONGLONG nAllocSize,
- ULONGLONG nFileIndex,
- DWORD nNumberOfLinks,
- DWORD dwFileAttributes)
+ DWORD nNumberOfLinks)
{
IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci;
HANDLE h = get_stat_handle ();
-
- to_timestruc_t ((PFILETIME) LastAccessTime, &buf->st_atim);
- to_timestruc_t ((PFILETIME) LastWriteTime, &buf->st_mtim);
- to_timestruc_t ((PFILETIME) ChangeTime, &buf->st_ctim);
- to_timestruc_t ((PFILETIME) CreationTime, &buf->st_birthtim);
- buf->st_rdev = buf->st_dev = dwVolumeSerialNumber;
- buf->st_size = (_off64_t) nFileSize;
+ PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
+ ULONG attributes = pc.file_attributes ();
+
+ to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim);
+ to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim);
+ /* If the ChangeTime is 0, the underlying FS doesn't support this timestamp
+ (FAT for instance). If so, it's faked using LastWriteTime. */
+ to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime
+ : (PFILETIME) &pfnoi->LastWriteTime,
+ &buf->st_ctim);
+ to_timestruc_t ((PFILETIME) &pfnoi->CreationTime, &buf->st_birthtim);
+ buf->st_rdev = buf->st_dev = get_dev ();
+ buf->st_size = (_off64_t) pfnoi->EndOfFile.QuadPart;
/* The number of links to a directory includes the number of subdirectories
in the directory, since all those subdirectories point to it. However,
this is painfully slow, so we do without it. */
@@ -596,19 +497,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
#endif
/* Enforce namehash as inode number on untrusted file systems. */
- if (nFileIndex && pc.isgood_inode (nFileIndex))
- buf->st_ino = (__ino64_t) nFileIndex;
+ if (ino && pc.isgood_inode (ino))
+ buf->st_ino = (__ino64_t) ino;
else
buf->st_ino = get_ino ();
buf->st_blksize = PREFERRED_IO_BLKSIZE;
- if (nAllocSize >= 0LL)
+ if (pfnoi->AllocationSize.QuadPart >= 0LL)
/* A successful NtQueryInformationFile returns the allocation size
correctly for compressed and sparse files as well. */
- buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE;
- else if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_COMPRESSED
- | FILE_ATTRIBUTE_SPARSE_FILE)
+ buf->st_blocks = (pfnoi->AllocationSize.QuadPart + S_BLKSIZE - 1)
+ / S_BLKSIZE;
+ else if (::has_attribute (attributes, FILE_ATTRIBUTE_COMPRESSED
+ | FILE_ATTRIBUTE_SPARSE_FILE)
&& h && !is_fs_special ()
&& !NtQueryInformationFile (h, &st, (PVOID) &fci, sizeof fci,
FileCompressionInformation))
@@ -641,7 +543,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
&buf->st_mode, &buf->st_uid, &buf->st_gid))
{
/* If read-only attribute is set, modify ntsec return value */
- if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY)
+ if (::has_attribute (attributes, FILE_ATTRIBUTE_READONLY)
&& !pc.isdir () && !pc.issymlink ())
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
@@ -660,7 +562,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
{
buf->st_mode |= STD_RBITS;
- if (!::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY))
+ if (!::has_attribute (attributes, FILE_ATTRIBUTE_READONLY))
buf->st_mode |= STD_WBITS;
/* | S_IWGRP | S_IWOTH; we don't give write to group etc */
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 45ab24bcb..f0f850f42 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -717,7 +717,7 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
tty process group leader.
TODO: Investigate how SIGTTIN should be handled with pure-windows
programs. */
- tc->pgid = myself->pgid;
+ tc->setpgid (myself->pgid);
}
if (f != INVALID_HANDLE_VALUE)
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index 710df06e8..57e0a40e7 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -1,7 +1,7 @@
/* mmap.cc
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007 Red Hat, Inc.
+ 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
This file is part of Cygwin.
@@ -865,7 +865,7 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
goto out;
}
- if (fh->fstat_by_handle (&st))
+ if (fh->fstat_fs (&st))
{
__seterrno ();
goto out;
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 8ea1b6295..6c58849b8 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -381,7 +381,8 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
Therefore, for NWFS we have to fallback to the
FileNetworkOpenInformation info class. Unfortunately we can't
use FileNetworkOpenInformation all the time since that fails on
- other filesystems like NFS. */
+ other filesystems like NFS.
+ UNUSED, but keep in for information purposes. */
has_buggy_basic_info (is_nwfs ());
/* Netapp ans NWFS are too dumb to allow non-DOS filesystems
containing trailing dots and spaces when accessed from Windows
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4b8179c8e..470546586 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1946,6 +1946,7 @@ symlink_info::check_reparse_point (HANDLE h)
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer,
subst.Length / sizeof (WCHAR));
pflags |= PATH_SYMLINK | PATH_REP;
+ /* A symlink is never a directory. */
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
return posixify (srcbuf);
}
@@ -2238,7 +2239,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs,
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
- FILE_BASIC_INFORMATION fbi;
suffix_scan suffix;
const ULONG ci_flag = cygwin_shared->obcaseinsensitive
@@ -2409,16 +2409,34 @@ restart:
}
}
+ FILE_BASIC_INFORMATION fbi;
+ PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
+
if (NT_SUCCESS (status)
/* Check file system while we're having the file open anyway.
This speeds up path_conv noticably (~10%). */
- && (fs.inited () || fs.update (&upath, h))
- && NT_SUCCESS (status = fs.has_buggy_basic_info ()
- ? NtQueryAttributesFile (&attr, &fbi)
- : NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
- FileBasicInformation)))
- fileattr = fbi.FileAttributes;
- else
+ && (fs.inited () || fs.update (&upath, h)))
+ {
+ if (fs.is_nfs ())
+ {
+ /* NFS doesn't handle FileNetworkOpenInformation when called
+ via NtQueryInformationFile (STATUS_INVALID_PARAMETER).
+ Since we only need FileAttributes for NFS anyway, we just
+ fetch the FileBasicInformation. */
+ status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
+ FileBasicInformation);
+ if (NT_SUCCESS (status))
+ fileattr = fbi.FileAttributes;
+ }
+ else
+ {
+ status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
+ FileNetworkOpenInformation);
+ if (NT_SUCCESS (status))
+ fileattr = pfnoi->FileAttributes;
+ }
+ }
+ if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryInformationFile (%S)", status, &upath);
fileattr = INVALID_FILE_ATTRIBUTES;
@@ -2504,7 +2522,10 @@ restart:
fileattr = 0;
}
else
- fileattr = fdi_buf.fdi.FileAttributes;
+ {
+ fileattr = fdi_buf.fdi.FileAttributes;
+ memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
+ }
}
ext_tacked_on = !!*ext_here;
goto file_not_symlink;
@@ -2590,7 +2611,11 @@ restart:
pflags &= ~PC_KEEP_HANDLE;
}
else if (res)
- break;
+ {
+ /* A symlink is never a directory. */
+ pfnoi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+ break;
+ }
}
/* This is the old Cygwin method creating symlinks. A symlink will
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 3650f7688..f832016e5 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -89,10 +89,24 @@ enum path_types
PATH_SOCKET = 0x40000000
};
+class symlink_info;
+struct _FILE_NETWORK_OPEN_INFORMATION;
+
class path_conv_handle
{
HANDLE hdl;
ACCESS_MASK acc;
+ /* Identical to FILE_NETWORK_OPEN_INFORMATION. We don't want to pull in
+ ntdll.h here, though. */
+ struct {
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG FileAttributes;
+ } _fnoi;
public:
path_conv_handle () : hdl (NULL), acc (0) {}
inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; }
@@ -114,10 +128,10 @@ public:
}
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 *) &_fnoi; }
};
-class symlink_info;
-
class path_conv
{
DWORD fileattr;
@@ -287,6 +301,7 @@ class path_conv
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 (); }
void reset_conv_handle () { conv_handle.set (NULL, 0); }
void close_conv_handle () { conv_handle.close (); }