4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-18 12:29:32 +08:00

Fetch and store FileAllInformation rather than FileNetworkOpenInformation

* path.h (class path_conv_handle): Use FILE_ALL_INFORMATION instead of
        FILE_NETWORK_OPEN_INFORMATION.  Use definitions from ntdll.h since it's
        included anyway.
        (path_conv_handle::fai): Change name from fnoi.
        (path_conv::fai): Ditto.
        (file_get_fai): Change name from file_get_fnoi.  Drop second parameter.
        * path.cc (file_get_fai): Ditto.  Fetch FileAllInformation rather than
        FileNetworkOpenInformation.  Convert STATUS_BUFFER_OVERFLOW to
        STATUS_SUCCESS.  Remove workaround to fetch FileBasicInformation and
        FileStandardInformation on filesystems with broken
        FileNetworkOpenInformation handling.
        (symlink_info::check): Accommodate above changes.  In case of using
        the NtQueryDirectoryFile fallback, fetch FileIdBothDirectoryInformation
        to get inode number as well.
        * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop outdated
        comment.  Accommodate change to using FileAllInformation.  Drop
        extra function calls to fetch NumberOfLinks and IndexNumber.  Set ino
        directly from IndexNumber stored in pc.fai().  Drop second argument
        from call to fstat_helper.
        (fhandler_base::fstat_by_name): Drop second argument from call to
        fstat_helper.
        (fhandler_base::fstat_helper): Drop second parameter.  Accommodate
        the fact that we access a FILE_ALL_INFORMATION structure now.
        (fhandler_base::open_fs): Set ino directly from IndexNumber stored in
        pc.fai().
        * fhandler.h (fhandler_base::fstat_helper): Fix declaration accrdingly.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2015-12-10 00:02:34 +01:00
parent a0e7563eb0
commit eed35efbe6
5 changed files with 83 additions and 119 deletions

View File

@ -1,3 +1,32 @@
2015-12-10 Corinna Vinschen <corinna@vinschen.de>
* path.h (class path_conv_handle): Use FILE_ALL_INFORMATION instead of
FILE_NETWORK_OPEN_INFORMATION. Use definitions from ntdll.h since it's
included anyway.
(path_conv_handle::fai): Change name from fnoi.
(path_conv::fai): Ditto.
(file_get_fai): Change name from file_get_fnoi. Drop second parameter.
* path.cc (file_get_fai): Ditto. Fetch FileAllInformation rather than
FileNetworkOpenInformation. Convert STATUS_BUFFER_OVERFLOW to
STATUS_SUCCESS. Remove workaround to fetch FileBasicInformation and
FileStandardInformation on filesystems with broken
FileNetworkOpenInformation handling.
(symlink_info::check): Accommodate above changes. In case of using
the NtQueryDirectoryFile fallback, fetch FileIdBothDirectoryInformation
to get inode number as well.
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop outdated
comment. Accommodate change to using FileAllInformation. Drop
extra function calls to fetch NumberOfLinks and IndexNumber. Set ino
directly from IndexNumber stored in pc.fai(). Drop second argument
from call to fstat_helper.
(fhandler_base::fstat_by_name): Drop second argument from call to
fstat_helper.
(fhandler_base::fstat_helper): Drop second parameter. Accommodate
the fact that we access a FILE_ALL_INFORMATION structure now.
(fhandler_base::open_fs): Set ino directly from IndexNumber stored in
pc.fai().
* fhandler.h (fhandler_base::fstat_helper): Fix declaration accrdingly.
2015-12-10 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (path_conv::ndisk_links): Drop unused method.

View File

@ -341,8 +341,7 @@ class fhandler_base
void __reg2 stat_fixup (struct stat *buf);
int __reg2 fstat_fs (struct stat *buf);
private:
int __reg3 fstat_helper (struct stat *buf,
DWORD nNumberOfLinks);
int __reg2 fstat_helper (struct stat *buf);
int __reg2 fstat_by_nfs_ea (struct stat *buf);
int __reg2 fstat_by_handle (struct stat *buf);
int __reg2 fstat_by_name (struct stat *buf);

View File

@ -319,59 +319,25 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf)
int __reg2
fhandler_base::fstat_by_handle (struct stat *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). */
FILE_STANDARD_INFORMATION fsi;
FILE_INTERNAL_INFORMATION fii;
HANDLE h = get_stat_handle ();
NTSTATUS status = 0;
IO_STATUS_BLOCK io;
/* If the file has been opened for other purposes than stat, we can't rely
on the information stored in pc.fnoi. So we overwrite them here. */
on the information stored in pc.fai. So we overwrite them here. */
if (get_io_handle ())
{
status = file_get_fnoi (h, pc.has_broken_fnoi (), pc.fnoi ());
status = file_get_fai (h, pc.fai ());
if (!NT_SUCCESS (status))
{
debug_printf ("%y = NtQueryInformationFile(%S, "
"FileNetworkOpenInformation)",
debug_printf ("%y = NtQueryInformationFile(%S, FileAllInformation)",
status, pc.get_nt_native_path ());
return -1;
}
}
if (!pc.hasgood_inode ())
fsi.NumberOfLinks = 1;
else
{
status = NtQueryInformationFile (h, &io, &fsi, sizeof fsi,
FileStandardInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%y = NtQueryInformationFile(%S, "
"FileStandardInformation)",
status, pc.get_nt_native_path ());
return -1;
}
if (!ino)
{
status = NtQueryInformationFile (h, &io, &fii, sizeof fii,
FileInternalInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%y = NtQueryInformationFile(%S, "
"FileInternalInformation)",
status, pc.get_nt_native_path ());
return -1;
}
else if (pc.isgood_inode (fii.IndexNumber.QuadPart))
ino = fii.IndexNumber.QuadPart;
}
}
return fstat_helper (buf, fsi.NumberOfLinks);
if (pc.hasgood_inode ()
&& pc.isgood_inode (pc.fai ()->InternalInformation.IndexNumber.QuadPart))
ino = pc.fai ()->InternalInformation.IndexNumber.QuadPart;
return fstat_helper (buf);
}
int __reg2
@ -415,7 +381,7 @@ fhandler_base::fstat_by_name (struct stat *buf)
ino = fdi_buf.fdi.FileId.QuadPart;
}
}
return fstat_helper (buf, 1);
return fstat_helper (buf);
}
int __reg2
@ -463,22 +429,23 @@ fhandler_base::fstat_fs (struct stat *buf)
}
int __reg3
fhandler_base::fstat_helper (struct stat *buf, DWORD nNumberOfLinks)
fhandler_base::fstat_helper (struct stat *buf)
{
IO_STATUS_BLOCK st;
FILE_COMPRESSION_INFORMATION fci;
HANDLE h = get_stat_handle ();
PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
PFILE_ALL_INFORMATION pfai = pc.fai ();
ULONG attributes = pc.file_attributes ();
to_timestruc_t (&pfnoi->LastAccessTime, &buf->st_atim);
to_timestruc_t (&pfnoi->LastWriteTime, &buf->st_mtim);
to_timestruc_t (&pfai->BasicInformation.LastAccessTime, &buf->st_atim);
to_timestruc_t (&pfai->BasicInformation.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 ? &pfnoi->ChangeTime
: &pfnoi->LastWriteTime,
to_timestruc_t (pfai->BasicInformation.ChangeTime.QuadPart
? &pfai->BasicInformation.ChangeTime
: &pfai->BasicInformation.LastWriteTime,
&buf->st_ctim);
to_timestruc_t (&pfnoi->CreationTime, &buf->st_birthtim);
to_timestruc_t (&pfai->BasicInformation.CreationTime, &buf->st_birthtim);
buf->st_dev = get_dev ();
/* CV 2011-01-13: Observations on the Cygwin mailing list point to an
interesting behaviour in some Windows versions. Apparently the size of
@ -487,11 +454,13 @@ fhandler_base::fstat_helper (struct stat *buf, DWORD nNumberOfLinks)
0 in the first call and size > 0 in the second call. This in turn can
affect applications like newer tar.
FIXME: Is the allocation size affected as well? */
buf->st_size = pc.isdir () ? 0 : (off_t) pfnoi->EndOfFile.QuadPart;
buf->st_size = pc.isdir ()
? 0
: (off_t) pfai->StandardInformation.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. */
buf->st_nlink = nNumberOfLinks;
buf->st_nlink = pc.fai()->StandardInformation.NumberOfLinks;
/* Enforce namehash as inode number on untrusted file systems. */
if (ino && pc.isgood_inode (ino))
@ -501,11 +470,11 @@ fhandler_base::fstat_helper (struct stat *buf, DWORD nNumberOfLinks)
buf->st_blksize = PREFERRED_IO_BLKSIZE;
if (pfnoi->AllocationSize.QuadPart >= 0LL)
if (pfai->StandardInformation.AllocationSize.QuadPart >= 0LL)
/* A successful NtQueryInformationFile returns the allocation size
correctly for compressed and sparse files as well. */
buf->st_blocks = (pfnoi->AllocationSize.QuadPart + S_BLKSIZE - 1)
/ S_BLKSIZE;
buf->st_blocks = (pfai->StandardInformation.AllocationSize.QuadPart
+ S_BLKSIZE - 1) / S_BLKSIZE;
else if (::has_attribute (attributes, FILE_ATTRIBUTE_COMPRESSED
| FILE_ATTRIBUTE_SPARSE_FILE)
&& h && !is_fs_special ()
@ -1509,7 +1478,9 @@ fhandler_base::open_fs (int flags, mode_t mode)
return 0;
}
ino = pc.get_ino_by_handle (get_handle ());
if (pc.hasgood_inode ()
&& pc.isgood_inode (pc.fai ()->InternalInformation.IndexNumber.QuadPart))
ino = pc.fai ()->InternalInformation.IndexNumber.QuadPart;
out:
syscall_printf ("%d = fhandler_disk_file::open(%S, %y)", res,

View File

@ -1300,44 +1300,18 @@ path_conv::is_binary ()
&& (bin == SCS_32BIT_BINARY || bin == SCS_64BIT_BINARY);
}
/* Helper function to fill the fnoi datastructure for a file. */
/* Helper function to fill the fai datastructure for a file. */
NTSTATUS
file_get_fnoi (HANDLE h, bool skip_network_open_inf,
PFILE_NETWORK_OPEN_INFORMATION pfnoi)
file_get_fai (HANDLE h, PFILE_ALL_INFORMATION pfai)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
/* Some FSes (Netapps) don't implement FileNetworkOpenInformation. */
status = skip_network_open_inf ? STATUS_INVALID_PARAMETER
: NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
FileNetworkOpenInformation);
if (status == STATUS_INVALID_PARAMETER)
{
/* Apart from accessing Netapps, this also occurs when accessing SMB
share root dirs hosted on NT4. */
FILE_BASIC_INFORMATION fbi;
FILE_STANDARD_INFORMATION fsi;
status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation);
if (NT_SUCCESS (status))
{
memcpy (pfnoi, &fbi, 4 * sizeof (LARGE_INTEGER));
if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fsi,
sizeof fsi,
FileStandardInformation)))
{
pfnoi->EndOfFile.QuadPart = fsi.EndOfFile.QuadPart;
pfnoi->AllocationSize.QuadPart
= fsi.AllocationSize.QuadPart;
}
else
pfnoi->EndOfFile.QuadPart
= pfnoi->AllocationSize.QuadPart = 0;
pfnoi->FileAttributes = fbi.FileAttributes;
}
}
status = NtQueryInformationFile (h, &io, pfai, sizeof *pfai,
FileAllInformation);
if (status == STATUS_BUFFER_OVERFLOW)
status = STATUS_SUCCESS;
return status;
}
@ -2833,10 +2807,9 @@ restart:
}
else
{
status = file_get_fnoi (h, fs.has_broken_fnoi (),
conv_hdl.fnoi ());
status = file_get_fai (h, conv_hdl.fai ());
if (NT_SUCCESS (status))
fileattr = conv_hdl.fnoi ()->FileAttributes;
fileattr = conv_hdl.fai ()->BasicInformation.FileAttributes;
}
}
if (!NT_SUCCESS (status))
@ -2874,7 +2847,7 @@ restart:
OBJECT_ATTRIBUTES dattr;
HANDLE dir;
struct {
FILE_BOTH_DIR_INFORMATION fdi;
FILE_ID_BOTH_DIR_INFORMATION fdi;
WCHAR dummy_buf[NAME_MAX + 1];
} fdi_buf;
@ -2906,7 +2879,7 @@ restart:
{
status = NtQueryDirectoryFile (dir, NULL, NULL, NULL, &io,
&fdi_buf, sizeof fdi_buf,
FileBothDirectoryInformation,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE);
/* Take the opportunity to check file system while we're
having the handle to the parent dir. */
@ -2932,18 +2905,20 @@ restart:
}
else
{
PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
PFILE_ALL_INFORMATION pfai = conv_hdl.fai ();
fileattr = fdi_buf.fdi.FileAttributes;
memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
/* Amazing, but true: The FILE_NETWORK_OPEN_INFORMATION
structure has the AllocationSize and EndOfFile members
interchanged relative to the directory information
classes. */
pfnoi->AllocationSize.QuadPart
memcpy (&pfai->BasicInformation.CreationTime,
&fdi_buf.fdi.CreationTime,
4 * sizeof (LARGE_INTEGER));
pfai->BasicInformation.FileAttributes = fileattr;
pfai->StandardInformation.AllocationSize.QuadPart
= fdi_buf.fdi.AllocationSize.QuadPart;
pfnoi->EndOfFile.QuadPart
pfai->StandardInformation.EndOfFile.QuadPart
= fdi_buf.fdi.EndOfFile.QuadPart;
pfai->StandardInformation.NumberOfLinks = 1;
pfai->InternalInformation.IndexNumber.QuadPart
= fdi_buf.fdi.FileId.QuadPart;
}
}
ext_tacked_on = !!*ext_here;
@ -2977,7 +2952,8 @@ restart:
if (res > 0)
{
/* A symlink is never a directory. */
conv_hdl.fnoi ()->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
conv_hdl.fai ()->BasicInformation.FileAttributes
&= ~FILE_ATTRIBUTE_DIRECTORY;
break;
}
else

View File

@ -91,23 +91,12 @@ enum path_types
};
class symlink_info;
struct _FILE_NETWORK_OPEN_INFORMATION;
class path_conv_handle
{
HANDLE hdl;
union {
/* 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;
FILE_ALL_INFORMATION _fai;
/* For NFS. */
fattr3 _fattr3;
} attribs;
@ -128,8 +117,8 @@ public:
hdl = NULL;
}
inline HANDLE handle () const { return hdl; }
inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi ()
{ return (struct _FILE_NETWORK_OPEN_INFORMATION *) &attribs._fnoi; }
inline PFILE_ALL_INFORMATION fai ()
{ return (PFILE_ALL_INFORMATION) &attribs._fai; }
inline struct fattr3 *nfsattr ()
{ return (struct fattr3 *) &attribs._fattr3; }
};
@ -390,7 +379,7 @@ class path_conv
bool is_binary ();
HANDLE handle () const { return conv_handle.handle (); }
struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return conv_handle.fnoi (); }
PFILE_ALL_INFORMATION fai () { return conv_handle.fai (); }
struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
void reset_conv_handle () { conv_handle.set (NULL); }
void close_conv_handle () { conv_handle.close (); }
@ -444,7 +433,7 @@ bool __reg2 has_dot_last_component (const char *dir, bool test_dot_dot);
int __reg3 path_prefix_p (const char *path1, const char *path2, int len1,
bool caseinsensitive);
NTSTATUS file_get_fnoi (HANDLE, bool, struct _FILE_NETWORK_OPEN_INFORMATION *);
NTSTATUS file_get_fai (HANDLE, PFILE_ALL_INFORMATION);
int normalize_win32_path (const char *, char *, char *&);
int normalize_posix_path (const char *, char *, char *&);
PUNICODE_STRING __reg3 get_nt_native_path (const char *, UNICODE_STRING&, bool);