* 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.
This commit is contained in:
Corinna Vinschen 2010-09-13 11:17:36 +00:00
parent f7382efe27
commit c80480bfa0
8 changed files with 144 additions and 178 deletions

View File

@ -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> 2010-09-12 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (acl_worker): Remove. * sec_acl.cc (acl_worker): Remove.

View File

@ -293,21 +293,14 @@ class fhandler_base
int close_fs () { return fhandler_base::close (); } int close_fs () { return fhandler_base::close (); }
virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); virtual int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2))); int __stdcall fstat_fs (struct __stat64 *buf) __attribute__ ((regparm (2)));
private:
int __stdcall fstat_helper (struct __stat64 *buf, int __stdcall fstat_helper (struct __stat64 *buf,
PLARGE_INTEGER ChangeTime, DWORD nNumberOfLinks)
PLARGE_INTEGER LastAccessTime, __attribute__ ((regparm (3)));
PLARGE_INTEGER LastWriteTime,
PLARGE_INTEGER CreationTime,
DWORD dwVolumeSerialNumber,
ULONGLONG nFileSize,
LONGLONG nAllocSize,
ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
__attribute__ ((regparm (3)));
int __stdcall fstat_by_nfs_ea (struct __stat64 *buf) __attribute__ ((regparm (2))); 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_handle (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_name (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))); virtual int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
int utimens_fs (const struct timespec *) __attribute__ ((regparm (2))); int utimens_fs (const struct timespec *) __attribute__ ((regparm (2)));
virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1))); virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));

View File

@ -345,43 +345,17 @@ fhandler_base::fstat_by_nfs_ea (struct __stat64 *buf)
int __stdcall int __stdcall
fhandler_base::fstat_by_handle (struct __stat64 *buf) 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 /* 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 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 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). */ 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_STANDARD_INFORMATION fsi;
FILE_INTERNAL_INFORMATION fii; FILE_INTERNAL_INFORMATION fii;
HANDLE h = get_stat_handle (); 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, status = NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
FileStandardInformation); FileStandardInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
@ -402,26 +376,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
} }
ino = fii.FileId.QuadPart; ino = fii.FileId.QuadPart;
} }
/* If the change time is 0, it's a file system which doesn't return fstat_helper (buf, fsi.NumberOfLinks);
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);
} }
int __stdcall int __stdcall
@ -437,76 +392,35 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
FILE_ID_BOTH_DIR_INFORMATION fdi; FILE_ID_BOTH_DIR_INFORMATION fdi;
WCHAR buf[NAME_MAX + 1]; WCHAR buf[NAME_MAX + 1];
} fdi_buf; } fdi_buf;
LARGE_INTEGER FileId;
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename); if (!ino && wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo ())
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 ()); RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
goto too_bad; 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;
}
} }
if (wincap.has_fileid_dirinfo () && !pc.has_buggy_fileid_dirinfo () return fstat_helper (buf, 1);
&& 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))
{
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 ());
} }
int __stdcall int __stdcall
@ -519,7 +433,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
if (get_stat_handle ()) if (get_stat_handle ())
{ {
if (!nohandle () && !is_fs_special ()) 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) if (res)
res = fstat_by_name (buf); res = fstat_by_name (buf);
return res; return res;
@ -540,7 +454,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
Since fhandler_base::open only calls CloseHandle if !nohandle, Since fhandler_base::open only calls CloseHandle if !nohandle,
we have to set it to false before calling close and restore we have to set it to false before calling close and restore
the state afterwards. */ 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 (); bool no_handle = nohandle ();
nohandle (false); nohandle (false);
close_fs (); close_fs ();
@ -553,39 +467,26 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
return res; 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 int __stdcall
fhandler_base::fstat_helper (struct __stat64 *buf, fhandler_base::fstat_helper (struct __stat64 *buf,
PLARGE_INTEGER ChangeTime, DWORD nNumberOfLinks)
PLARGE_INTEGER LastAccessTime,
PLARGE_INTEGER LastWriteTime,
PLARGE_INTEGER CreationTime,
DWORD dwVolumeSerialNumber,
ULONGLONG nFileSize,
LONGLONG nAllocSize,
ULONGLONG nFileIndex,
DWORD nNumberOfLinks,
DWORD dwFileAttributes)
{ {
IO_STATUS_BLOCK st; IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci; FILE_COMPRESSION_INFORMATION fci;
HANDLE h = get_stat_handle (); HANDLE h = get_stat_handle ();
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
ULONG attributes = pc.file_attributes ();
to_timestruc_t ((PFILETIME) LastAccessTime, &buf->st_atim); to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim);
to_timestruc_t ((PFILETIME) LastWriteTime, &buf->st_mtim); to_timestruc_t ((PFILETIME) &pfnoi->LastWriteTime, &buf->st_mtim);
to_timestruc_t ((PFILETIME) ChangeTime, &buf->st_ctim); /* If the ChangeTime is 0, the underlying FS doesn't support this timestamp
to_timestruc_t ((PFILETIME) CreationTime, &buf->st_birthtim); (FAT for instance). If so, it's faked using LastWriteTime. */
buf->st_rdev = buf->st_dev = dwVolumeSerialNumber; to_timestruc_t (pfnoi->ChangeTime.QuadPart ? (PFILETIME) &pfnoi->ChangeTime
buf->st_size = (_off64_t) nFileSize; : (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 /* The number of links to a directory includes the number of subdirectories
in the directory, since all those subdirectories point to it. However, in the directory, since all those subdirectories point to it. However,
this is painfully slow, so we do without it. */ this is painfully slow, so we do without it. */
@ -596,19 +497,20 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
#endif #endif
/* Enforce namehash as inode number on untrusted file systems. */ /* Enforce namehash as inode number on untrusted file systems. */
if (nFileIndex && pc.isgood_inode (nFileIndex)) if (ino && pc.isgood_inode (ino))
buf->st_ino = (__ino64_t) nFileIndex; buf->st_ino = (__ino64_t) ino;
else else
buf->st_ino = get_ino (); buf->st_ino = get_ino ();
buf->st_blksize = PREFERRED_IO_BLKSIZE; buf->st_blksize = PREFERRED_IO_BLKSIZE;
if (nAllocSize >= 0LL) if (pfnoi->AllocationSize.QuadPart >= 0LL)
/* A successful NtQueryInformationFile returns the allocation size /* A successful NtQueryInformationFile returns the allocation size
correctly for compressed and sparse files as well. */ correctly for compressed and sparse files as well. */
buf->st_blocks = (nAllocSize + S_BLKSIZE - 1) / S_BLKSIZE; buf->st_blocks = (pfnoi->AllocationSize.QuadPart + S_BLKSIZE - 1)
else if (::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_COMPRESSED / S_BLKSIZE;
| FILE_ATTRIBUTE_SPARSE_FILE) else if (::has_attribute (attributes, FILE_ATTRIBUTE_COMPRESSED
| FILE_ATTRIBUTE_SPARSE_FILE)
&& h && !is_fs_special () && h && !is_fs_special ()
&& !NtQueryInformationFile (h, &st, (PVOID) &fci, sizeof fci, && !NtQueryInformationFile (h, &st, (PVOID) &fci, sizeof fci,
FileCompressionInformation)) FileCompressionInformation))
@ -641,7 +543,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
&buf->st_mode, &buf->st_uid, &buf->st_gid)) &buf->st_mode, &buf->st_uid, &buf->st_gid))
{ {
/* If read-only attribute is set, modify ntsec return value */ /* 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 ()) && !pc.isdir () && !pc.issymlink ())
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); 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; buf->st_mode |= STD_RBITS;
if (!::has_attribute (dwFileAttributes, FILE_ATTRIBUTE_READONLY)) if (!::has_attribute (attributes, FILE_ATTRIBUTE_READONLY))
buf->st_mode |= STD_WBITS; buf->st_mode |= STD_WBITS;
/* | S_IWGRP | S_IWOTH; we don't give write to group etc */ /* | S_IWGRP | S_IWOTH; we don't give write to group etc */

View File

@ -717,7 +717,7 @@ fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
tty process group leader. tty process group leader.
TODO: Investigate how SIGTTIN should be handled with pure-windows TODO: Investigate how SIGTTIN should be handled with pure-windows
programs. */ programs. */
tc->pgid = myself->pgid; tc->setpgid (myself->pgid);
} }
if (f != INVALID_HANDLE_VALUE) if (f != INVALID_HANDLE_VALUE)

View File

@ -1,7 +1,7 @@
/* mmap.cc /* mmap.cc
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 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. 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; goto out;
} }
if (fh->fstat_by_handle (&st)) if (fh->fstat_fs (&st))
{ {
__seterrno (); __seterrno ();
goto out; goto out;

View File

@ -381,7 +381,8 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
Therefore, for NWFS we have to fallback to the Therefore, for NWFS we have to fallback to the
FileNetworkOpenInformation info class. Unfortunately we can't FileNetworkOpenInformation info class. Unfortunately we can't
use FileNetworkOpenInformation all the time since that fails on 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 ()); has_buggy_basic_info (is_nwfs ());
/* Netapp ans NWFS are too dumb to allow non-DOS filesystems /* Netapp ans NWFS are too dumb to allow non-DOS filesystems
containing trailing dots and spaces when accessed from Windows containing trailing dots and spaces when accessed from Windows

View File

@ -1946,6 +1946,7 @@ symlink_info::check_reparse_point (HANDLE h)
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer, sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer,
subst.Length / sizeof (WCHAR)); subst.Length / sizeof (WCHAR));
pflags |= PATH_SYMLINK | PATH_REP; pflags |= PATH_SYMLINK | PATH_REP;
/* A symlink is never a directory. */
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY; fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
return posixify (srcbuf); return posixify (srcbuf);
} }
@ -2238,7 +2239,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs,
UNICODE_STRING upath; UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
FILE_BASIC_INFORMATION fbi;
suffix_scan suffix; suffix_scan suffix;
const ULONG ci_flag = cygwin_shared->obcaseinsensitive 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) if (NT_SUCCESS (status)
/* Check file system while we're having the file open anyway. /* Check file system while we're having the file open anyway.
This speeds up path_conv noticably (~10%). */ This speeds up path_conv noticably (~10%). */
&& (fs.inited () || fs.update (&upath, h)) && (fs.inited () || fs.update (&upath, h)))
&& NT_SUCCESS (status = fs.has_buggy_basic_info () {
? NtQueryAttributesFile (&attr, &fbi) if (fs.is_nfs ())
: NtQueryInformationFile (h, &io, &fbi, sizeof fbi, {
FileBasicInformation))) /* NFS doesn't handle FileNetworkOpenInformation when called
fileattr = fbi.FileAttributes; via NtQueryInformationFile (STATUS_INVALID_PARAMETER).
else 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); debug_printf ("%p = NtQueryInformationFile (%S)", status, &upath);
fileattr = INVALID_FILE_ATTRIBUTES; fileattr = INVALID_FILE_ATTRIBUTES;
@ -2504,7 +2522,10 @@ restart:
fileattr = 0; fileattr = 0;
} }
else else
fileattr = fdi_buf.fdi.FileAttributes; {
fileattr = fdi_buf.fdi.FileAttributes;
memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
}
} }
ext_tacked_on = !!*ext_here; ext_tacked_on = !!*ext_here;
goto file_not_symlink; goto file_not_symlink;
@ -2590,7 +2611,11 @@ restart:
pflags &= ~PC_KEEP_HANDLE; pflags &= ~PC_KEEP_HANDLE;
} }
else if (res) 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 /* This is the old Cygwin method creating symlinks. A symlink will

View File

@ -89,10 +89,24 @@ enum path_types
PATH_SOCKET = 0x40000000 PATH_SOCKET = 0x40000000
}; };
class symlink_info;
struct _FILE_NETWORK_OPEN_INFORMATION;
class path_conv_handle class path_conv_handle
{ {
HANDLE hdl; HANDLE hdl;
ACCESS_MASK acc; 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: public:
path_conv_handle () : hdl (NULL), acc (0) {} path_conv_handle () : hdl (NULL), acc (0) {}
inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; } inline void set (HANDLE h, ACCESS_MASK a) { hdl = h; acc = a; }
@ -114,10 +128,10 @@ public:
} }
inline HANDLE handle () const { return hdl; } inline HANDLE handle () const { return hdl; }
inline ACCESS_MASK access () const { return acc; } 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 class path_conv
{ {
DWORD fileattr; DWORD fileattr;
@ -287,6 +301,7 @@ class path_conv
HANDLE handle () const { return conv_handle.handle (); } HANDLE handle () const { return conv_handle.handle (); }
ACCESS_MASK access () const { return conv_handle.access (); } 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 reset_conv_handle () { conv_handle.set (NULL, 0); }
void close_conv_handle () { conv_handle.close (); } void close_conv_handle () { conv_handle.close (); }