* fhandler_disk_file.cc (get_ino_by_handle): Rename pfai to fai.
(fhandler_base::fstat_by_handle): Drop fai_size and pfai in favor of static struct fai_buf. Restructure. (fhandler_base::fstat_by_name): Drop fvi_size and pfvi. Drop fdi_size and pfdi in favor of static struct fdi_buf. Drop redundant test for existance. Use FileDirectoryInformation class instead of FileBothDirectoryInformation. Drop call to NtQueryVolumeInformationFile in favor of using pc.fs_serial_number (). Fix FileId information given to fstat_helper. (fhandler_disk_file::fstatvfs): Drop fvi_size, pfvi, fai_size and pfai. Drop getting FileFsVolumeInformation and FileFsAttributeInformation in favor of using the related path_conv info. (fhandler_disk_file::opendir): Fix comment. (fhandler_disk_file::readdir): Ditto. Use FileDirectoryInformation class instead of FileBothDirectoryInformation. * path.cc (fs_info::update): Store MaximumComponentNameLength in new member name_len. * path.h (struct fs_info): Use ULONG rather than DWORD. Add member name_len to store MaximumComponentNameLength. Add accessor methods. (path_conv::fs_name_len): New method.
This commit is contained in:
parent
0d3f365881
commit
380b8bac12
|
@ -1,3 +1,26 @@
|
|||
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler_disk_file.cc (get_ino_by_handle): Rename pfai to fai.
|
||||
(fhandler_base::fstat_by_handle): Drop fai_size and pfai in favor of
|
||||
static struct fai_buf. Restructure.
|
||||
(fhandler_base::fstat_by_name): Drop fvi_size and pfvi. Drop fdi_size
|
||||
and pfdi in favor of static struct fdi_buf. Drop redundant test for
|
||||
existance. Use FileDirectoryInformation class instead of
|
||||
FileBothDirectoryInformation. Drop call to NtQueryVolumeInformationFile
|
||||
in favor of using pc.fs_serial_number (). Fix FileId information given
|
||||
to fstat_helper.
|
||||
(fhandler_disk_file::fstatvfs): Drop fvi_size, pfvi, fai_size and pfai.
|
||||
Drop getting FileFsVolumeInformation and FileFsAttributeInformation in
|
||||
favor of using the related path_conv info.
|
||||
(fhandler_disk_file::opendir): Fix comment.
|
||||
(fhandler_disk_file::readdir): Ditto. Use FileDirectoryInformation
|
||||
class instead of FileBothDirectoryInformation.
|
||||
* path.cc (fs_info::update): Store MaximumComponentNameLength in new
|
||||
member name_len.
|
||||
* path.h (struct fs_info): Use ULONG rather than DWORD. Add member
|
||||
name_len to store MaximumComponentNameLength. Add accessor methods.
|
||||
(path_conv::fs_name_len): New method.
|
||||
|
||||
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler.h (dirent_states): Add dirent_nfs_d_ino state and add it to
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -457,6 +457,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
|
|||
return false;
|
||||
}
|
||||
flags (ffai_buf.ffai.FileSystemAttributes);
|
||||
name_len (ffai_buf.ffai.MaximumComponentNameLength);
|
||||
/* Should be reevaluated for each new OS. Right now this mask is valid up
|
||||
to Vista. The important point here is to test only flags indicating
|
||||
capabilities and to ignore flags indicating a specific state of this
|
||||
|
|
|
@ -95,8 +95,9 @@ struct fs_info
|
|||
private:
|
||||
struct status_flags
|
||||
{
|
||||
DWORD flags; /* Volume flags */
|
||||
DWORD samba_version; /* Samba version if available */
|
||||
ULONG flags; /* Volume flags */
|
||||
ULONG samba_version; /* Samba version if available */
|
||||
ULONG name_len; /* MaximumComponentNameLength */
|
||||
unsigned is_remote_drive : 1;
|
||||
unsigned has_buggy_open : 1;
|
||||
unsigned has_acls : 1;
|
||||
|
@ -113,8 +114,9 @@ struct fs_info
|
|||
void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; }
|
||||
fs_info () { clear (); }
|
||||
|
||||
IMPLEMENT_STATUS_FLAG (DWORD, flags)
|
||||
IMPLEMENT_STATUS_FLAG (DWORD, samba_version)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, flags)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, samba_version)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, name_len)
|
||||
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_acls)
|
||||
|
@ -269,6 +271,7 @@ class path_conv
|
|||
DWORD file_attributes () const {return fileattr;}
|
||||
void file_attributes (DWORD new_attr) {fileattr = new_attr;}
|
||||
DWORD fs_flags () {return fs.flags ();}
|
||||
DWORD fs_name_len () {return fs.name_len ();}
|
||||
bool fs_is_fat () const {return fs.is_fat ();}
|
||||
bool fs_is_ntfs () const {return fs.is_ntfs ();}
|
||||
bool fs_is_samba () const {return fs.is_samba ();}
|
||||
|
|
Loading…
Reference in New Issue