summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_disk_file.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc185
1 files changed, 72 insertions, 113 deletions
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index a8558a700..56f6809b9 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -168,11 +168,11 @@ static inline __ino64_t
get_ino_by_handle (HANDLE hdl)
{
IO_STATUS_BLOCK io;
- FILE_INTERNAL_INFORMATION pfai;
+ FILE_INTERNAL_INFORMATION fai;
- if (NT_SUCCESS (NtQueryInformationFile (hdl, &io, &pfai, sizeof pfai,
+ if (NT_SUCCESS (NtQueryInformationFile (hdl, &io, &fai, sizeof fai,
FileInternalInformation)))
- return pfai.FileId.QuadPart;
+ return fai.FileId.QuadPart;
return 0;
}
@@ -329,38 +329,38 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
if (pc.fs_is_nfs ())
return fstat_by_nfs_ea (buf);
- /* The entries potentially contain a name of MAX_PATH wide characters. */
- const DWORD fai_size = (NAME_MAX + 1) * sizeof (WCHAR)
- + sizeof (FILE_ALL_INFORMATION);
- PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
+ struct {
+ FILE_ALL_INFORMATION fai;
+ WCHAR buf[NAME_MAX + 1];
+ } fai_buf;
- status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
- FileAllInformation);
- if (NT_SUCCESS (status))
+ status = NtQueryInformationFile (get_handle (), &io, &fai_buf.fai,
+ sizeof fai_buf, FileAllInformation);
+ if (!NT_SUCCESS (status))
{
- /* 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 ())
- pfai->BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
- pc.file_attributes (pfai->BasicInformation.FileAttributes);
- return fstat_helper (buf,
- pfai->BasicInformation.ChangeTime.QuadPart
- ? *(FILETIME *) &pfai->BasicInformation.ChangeTime
- : *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
- *(FILETIME *) &pfai->BasicInformation.LastAccessTime,
- *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
- *(FILETIME *) &pfai->BasicInformation.CreationTime,
- get_dev (),
- pfai->StandardInformation.EndOfFile.QuadPart,
- pfai->StandardInformation.AllocationSize.QuadPart,
- pfai->InternalInformation.FileId.QuadPart,
- pfai->StandardInformation.NumberOfLinks,
- pfai->BasicInformation.FileAttributes);
- }
- debug_printf ("%p = NtQueryInformationFile(%S)",
- status, pc.get_nt_native_path ());
- return -1;
+ debug_printf ("%p = NtQueryInformationFile(%S)",
+ status, pc.get_nt_native_path ());
+ return -1;
+ }
+ /* 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 ())
+ fai_buf.fai.BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+ pc.file_attributes (fai_buf.fai.BasicInformation.FileAttributes);
+ return fstat_helper (buf,
+ fai_buf.fai.BasicInformation.ChangeTime.QuadPart
+ ? *(FILETIME *) &fai_buf.fai.BasicInformation.ChangeTime
+ : *(FILETIME *) &fai_buf.fai.BasicInformation.LastWriteTime,
+ *(FILETIME *) &fai_buf.fai.BasicInformation.LastAccessTime,
+ *(FILETIME *) &fai_buf.fai.BasicInformation.LastWriteTime,
+ *(FILETIME *) &fai_buf.fai.BasicInformation.CreationTime,
+ get_dev (),
+ fai_buf.fai.StandardInformation.EndOfFile.QuadPart,
+ fai_buf.fai.StandardInformation.AllocationSize.QuadPart,
+ fai_buf.fai.InternalInformation.FileId.QuadPart,
+ fai_buf.fai.StandardInformation.NumberOfLinks,
+ fai_buf.fai.BasicInformation.FileAttributes);
}
int __stdcall
@@ -372,22 +372,12 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
UNICODE_STRING dirname;
UNICODE_STRING basename;
HANDLE dir;
- const DWORD fdi_size = (NAME_MAX + 1) * sizeof (WCHAR)
- + sizeof (FILE_ID_BOTH_DIR_INFORMATION);
- const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
- + sizeof (FILE_FS_VOLUME_INFORMATION);
- PFILE_ID_BOTH_DIR_INFORMATION pfdi = (PFILE_ID_BOTH_DIR_INFORMATION)
- alloca (fdi_size);
- PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
- alloca (fvi_size);
+ struct {
+ FILE_ID_BOTH_DIR_INFORMATION fdi;
+ WCHAR buf[NAME_MAX + 1];
+ } fdi_buf;
LARGE_INTEGER FileId;
- if (!pc.exists ())
- {
- debug_printf ("already determined that pc does not exist");
- set_errno (ENOENT);
- return -1;
- }
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE,
NULL, NULL);
@@ -402,13 +392,13 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
}
if (wincap.has_fileid_dirinfo ()
&& NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
- pfdi, fdi_size,
+ &fdi_buf.fdi, sizeof fdi_buf,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE)))
- FileId = pfdi->FileId;
+ FileId = fdi_buf.fdi.FileId;
else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
- pfdi, fdi_size,
- FileBothDirectoryInformation,
+ &fdi_buf.fdi, sizeof fdi_buf,
+ FileDirectoryInformation,
TRUE, &basename, TRUE)))
FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */
if (!NT_SUCCESS (status))
@@ -418,34 +408,26 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
NtClose (dir);
goto too_bad;
}
- status = NtQueryVolumeInformationFile (dir, &io, pfvi, fvi_size,
- FileFsVolumeInformation);
- if (!NT_SUCCESS (status))
- {
- debug_printf ("%p = NtQueryVolumeInformationFile(%S)",
- status, pc.get_nt_native_path ());
- pfvi->VolumeSerialNumber = 0;
- }
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 ())
- pfdi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
- pc.file_attributes (pfdi->FileAttributes);
+ fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
+ pc.file_attributes (fdi_buf.fdi.FileAttributes);
return fstat_helper (buf,
- pfdi->ChangeTime.QuadPart ?
- *(FILETIME *) &pfdi->ChangeTime :
- *(FILETIME *) &pfdi->LastWriteTime,
- *(FILETIME *) &pfdi->LastAccessTime,
- *(FILETIME *) &pfdi->LastWriteTime,
- *(FILETIME *) &pfdi->CreationTime,
- pfvi->VolumeSerialNumber,
- pfdi->EndOfFile.QuadPart,
- pfdi->AllocationSize.QuadPart,
- pfdi->FileId.QuadPart,
+ fdi_buf.fdi.ChangeTime.QuadPart ?
+ *(FILETIME *) &fdi_buf.fdi.ChangeTime :
+ *(FILETIME *) &fdi_buf.fdi.LastWriteTime,
+ *(FILETIME *) &fdi_buf.fdi.LastAccessTime,
+ *(FILETIME *) &fdi_buf.fdi.LastWriteTime,
+ *(FILETIME *) &fdi_buf.fdi.CreationTime,
+ pc.fs_serial_number (),
+ fdi_buf.fdi.EndOfFile.QuadPart,
+ fdi_buf.fdi.AllocationSize.QuadPart,
+ FileId.QuadPart,
1,
- pfdi->FileAttributes);
+ fdi_buf.fdi.FileAttributes);
too_bad:
LARGE_INTEGER ft;
@@ -679,14 +661,6 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
int ret = -1, opened = 0;
NTSTATUS status;
IO_STATUS_BLOCK io;
- const size_t fvi_size = sizeof (FILE_FS_VOLUME_INFORMATION)
- + (NAME_MAX + 1) * sizeof (WCHAR);
- PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
- alloca (fvi_size);
- const size_t fai_size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION)
- + (NAME_MAX + 1) * sizeof (WCHAR);
- PFILE_FS_ATTRIBUTE_INFORMATION pfai = (PFILE_FS_ATTRIBUTE_INFORMATION)
- alloca (fai_size);
FILE_FS_FULL_SIZE_INFORMATION full_fsi;
FILE_FS_SIZE_INFORMATION fsi;
HANDLE fh = get_handle ();
@@ -712,27 +686,12 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
}
}
- /* Get basic volume information. */
- status = NtQueryVolumeInformationFile (fh, &io, pfvi, fvi_size,
- FileFsVolumeInformation);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- goto out;
- }
- status = NtQueryVolumeInformationFile (fh, &io, pfai, fai_size,
- FileFsAttributeInformation);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- goto out;
- }
sfs->f_files = ULONG_MAX;
sfs->f_ffree = ULONG_MAX;
sfs->f_favail = ULONG_MAX;
- sfs->f_fsid = pfvi->VolumeSerialNumber;
- sfs->f_flag = pfai->FileSystemAttributes;
- sfs->f_namemax = pfai->MaximumComponentNameLength;
+ sfs->f_fsid = pc.fs_serial_number ();
+ sfs->f_flag = pc.fs_flags ();
+ sfs->f_namemax = pc.fs_name_len ();
/* Get allocation related information. Try to get "full" information
first, which is only available since W2K. If that fails, try to
retrieve normal allocation information. */
@@ -1608,7 +1567,7 @@ fhandler_disk_file::opendir (int fd)
OS/FS combinations (say, Win2K/CDFS or so). Instead of
testing in readdir for yet another error code, let's use
FileIdBothDirectoryInformation only on filesystems supporting
- persistent ACLs, FileBothDirectoryInformation otherwise.
+ persistent ACLs, FileDirectoryInformation otherwise.
On older NFS clients (up to SFU 3.5), dangling symlinks
are hidden from directory queries, unless you use the
@@ -1825,20 +1784,20 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
nicely, but only up to the 128th entry in the directory. After
reaching this entry, the next call to NtQueryDirectoryFile
(FileIdBothDirectoryInformation) returns STATUS_INVALID_LEVEL.
- Why should we care, we can just switch to
- FileBothDirectoryInformation, isn't it? Nope! The next call to
- NtQueryDirectoryFile(FileBothDirectoryInformation) actually
- returns STATUS_NO_MORE_FILES, regardless how many files are left
- unread in the directory. This does not happen when using
- FileBothDirectoryInformation right from the start, but since
+ Why should we care, we can just switch to FileDirectoryInformation,
+ isn't it? Nope! The next call to
+ NtQueryDirectoryFile(FileDirectoryInformation)
+ actually returns STATUS_NO_MORE_FILES, regardless how many files
+ are left unread in the directory. This does not happen when using
+ FileDirectoryInformation right from the start, but since
we can't decide whether the server we're talking with has this
bug or not, we end up serving Samba shares always in the slow
- mode using FileBothDirectoryInformation. So, what we do here is
+ mode using FileDirectoryInformation. So, what we do here is
to implement the solution suggested by Andrew Tridgell, we just
reread all entries up to dir->d_position using
- FileBothDirectoryInformation.
+ FileDirectoryInformation.
However, We do *not* mark this server as broken and fall back to
- using FileBothDirectoryInformation further on. This would slow
+ using FileDirectoryInformation further on. This would slow
down every access to such a server, even for directories under
128 entries. Also, bigger dirs only suffer from one additional
call per full directory scan, which shouldn't be too big a hit.
@@ -1852,7 +1811,7 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
{
status = NtQueryDirectoryFile (get_handle (), NULL, NULL,
0, &io, d_cache (dir), DIR_BUF_SIZE,
- FileBothDirectoryInformation,
+ FileDirectoryInformation,
FALSE, NULL, cnt == 0);
if (!NT_SUCCESS (status))
goto go_ahead;
@@ -1872,7 +1831,7 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
d_cache (dir), DIR_BUF_SIZE,
(dir->__flags & dirent_nfs_d_ino)
? FileNamesInformation
- : FileBothDirectoryInformation,
+ : FileDirectoryInformation,
FALSE, NULL, dir->__d_position == 0);
}
@@ -1904,9 +1863,9 @@ go_ahead:
}
else
{
- FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
- FileNameLength = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileNameLength;
- FileAttributes = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileAttributes;
+ FileName = ((PFILE_DIRECTORY_INFORMATION) buf)->FileName;
+ FileNameLength = ((PFILE_DIRECTORY_INFORMATION) buf)->FileNameLength;
+ FileAttributes = ((PFILE_DIRECTORY_INFORMATION) buf)->FileAttributes;
}
RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);