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

@@ -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,