summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog29
-rw-r--r--winsup/cygwin/fhandler.h3
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc81
-rw-r--r--winsup/cygwin/path.cc68
-rw-r--r--winsup/cygwin/path.h21
5 files changed, 83 insertions, 119 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 079aa89f8..3c9804b28 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,34 @@
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.
(fhandler_base::fstat_helper): Drop unused call to ndisk_links.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 43e56efa6..adb84414e 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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);
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index e7e22a240..fe9dd03fc 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -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,
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index d86cf99a7..e49f18043 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -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
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index ab7222ee0..730f943c9 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -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);