* fhandler_disk_file.cc (fhandler_base::fstat_by_name): Use

RtlSplitUnicodePath.
	(fhandler_disk_file::fstat): Rename oret to opened.  Open file using NT
	functions right here.  Try to open parent dir instead of root directory
	to avoid call to rootdir.  Use NtFsControlFile.
	* ntdll.h (RtlSplitUnicodePath): Define.
This commit is contained in:
Corinna Vinschen 2007-07-27 10:10:57 +00:00
parent 655639ba89
commit ceaf31f416
3 changed files with 55 additions and 36 deletions

View File

@ -1,3 +1,12 @@
2007-07-27 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_base::fstat_by_name): Use
RtlSplitUnicodePath.
(fhandler_disk_file::fstat): Rename oret to opened. Open file using NT
functions right here. Try to open parent dir instead of root directory
to avoid call to rootdir. Use NtFsControlFile.
* ntdll.h (RtlSplitUnicodePath): Define.
2007-07-27 Corinna Vinschen <corinna@vinschen.de> 2007-07-27 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (is_volume_mountpoint): New static inline * fhandler_disk_file.cc (is_volume_mountpoint): New static inline

View File

@ -335,16 +335,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
set_errno (ENOENT); set_errno (ENOENT);
return -1; return -1;
} }
/* Split path in dirname and basename */ RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
dirname = *pc.get_nt_native_path ();
USHORT len = dirname.Length / sizeof (WCHAR);
while (len > 0 && dirname.Buffer[--len] != L'\\')
;
++len;
RtlInitCountedUnicodeString (&basename,
dirname.Length - len * sizeof (WCHAR),
&dirname.Buffer[len]);
dirname.Length = len * sizeof (WCHAR);
InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE, InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE,
NULL, NULL); NULL, NULL);
if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
@ -627,46 +618,51 @@ fhandler_disk_file::fstat (struct __stat64 *buf)
int __stdcall int __stdcall
fhandler_disk_file::fstatvfs (struct statvfs *sfs) fhandler_disk_file::fstatvfs (struct statvfs *sfs)
{ {
int ret = -1, oret = 0; int ret = -1, opened = 0;
NTSTATUS status; NTSTATUS status;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
const size_t fvi_size = sizeof (FILE_FS_VOLUME_INFORMATION) const size_t fvi_size = sizeof (FILE_FS_VOLUME_INFORMATION)
+ 256 * sizeof (WCHAR); + (NAME_MAX + 1) * sizeof (WCHAR);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION) PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size); alloca (fvi_size);
const size_t fai_size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION) const size_t fai_size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION)
+ 256 * sizeof (WCHAR); + (NAME_MAX + 1) * sizeof (WCHAR);
PFILE_FS_ATTRIBUTE_INFORMATION pfai = (PFILE_FS_ATTRIBUTE_INFORMATION) PFILE_FS_ATTRIBUTE_INFORMATION pfai = (PFILE_FS_ATTRIBUTE_INFORMATION)
alloca (fai_size); alloca (fai_size);
FILE_FS_FULL_SIZE_INFORMATION full_fsi; FILE_FS_FULL_SIZE_INFORMATION full_fsi;
FILE_FS_SIZE_INFORMATION fsi; FILE_FS_SIZE_INFORMATION fsi;
HANDLE fh = get_handle ();
if (!get_io_handle ()) if (!fh)
{ {
query_open (query_read_control); OBJECT_ATTRIBUTES attr;
oret = open_fs (O_RDONLY | O_BINARY, 0); opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL,
if (!oret) pc.get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT));
if (!opened)
{ {
/* Can't open file. Try again with rootdir. */ /* Can't open file. Try again with parent dir. */
char root[CYG_MAX_PATH]; UNICODE_STRING dirname;
if (!rootdir (get_win32_name (), root)) RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, NULL);
goto out; attr.ObjectName = &dirname;
pc.check (root, PC_SYM_NOFOLLOW); opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, &attr, &io,
oret = open_fs (O_RDONLY | O_BINARY, 0); FILE_SHARE_VALID_FLAGS,
if (!oret) FILE_OPEN_FOR_BACKUP_INTENT));
if (!opened)
goto out; goto out;
} }
} }
/* Get basic volume information. */ /* Get basic volume information. */
status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size, status = NtQueryVolumeInformationFile (fh, &io, pfvi, fvi_size,
FileFsVolumeInformation); FileFsVolumeInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
goto out; goto out;
} }
status = NtQueryVolumeInformationFile (get_handle (), &io, pfai, fai_size, status = NtQueryVolumeInformationFile (fh, &io, pfai, fai_size,
FileFsAttributeInformation); FileFsAttributeInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
@ -682,8 +678,7 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
/* Get allocation related information. Try to get "full" information /* Get allocation related information. Try to get "full" information
first, which is only available since W2K. If that fails, try to first, which is only available since W2K. If that fails, try to
retrieve normal allocation information. */ retrieve normal allocation information. */
status = NtQueryVolumeInformationFile (get_handle (), &io, &full_fsi, status = NtQueryVolumeInformationFile (fh, &io, &full_fsi, sizeof full_fsi,
sizeof full_fsi,
FileFsFullSizeInformation); FileFsFullSizeInformation);
if (NT_SUCCESS (status)) if (NT_SUCCESS (status))
{ {
@ -696,11 +691,12 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
{ {
/* Quotas active. We can't trust TotalAllocationUnits. */ /* Quotas active. We can't trust TotalAllocationUnits. */
NTFS_VOLUME_DATA_BUFFER nvdb; NTFS_VOLUME_DATA_BUFFER nvdb;
DWORD bytes;
if (!DeviceIoControl (get_handle (), FSCTL_GET_NTFS_VOLUME_DATA, NULL, status = NtFsControlFile (fh, NULL, NULL, NULL, &io,
0, &nvdb, sizeof nvdb, &bytes, NULL)) FSCTL_GET_NTFS_VOLUME_DATA,
debug_printf ("DeviceIoControl (%s) failed, %E", get_name ()); NULL, 0, &nvdb, sizeof nvdb);
if (!NT_SUCCESS (status))
debug_printf ("NtFsControlFile (%s) failed, status %lx", status);
else else
sfs->f_blocks = nvdb.TotalClusters.QuadPart; sfs->f_blocks = nvdb.TotalClusters.QuadPart;
} }
@ -708,8 +704,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
} }
else else
{ {
status = NtQueryVolumeInformationFile (get_handle (), &io, &fsi, status = NtQueryVolumeInformationFile (fh, &io, &fsi, sizeof fsi,
sizeof fsi, FileFsSizeInformation); FileFsSizeInformation);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); __seterrno_from_nt_status (status);
@ -723,8 +719,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
ret = 0; ret = 0;
} }
out: out:
if (oret) if (opened)
close_fs (); NtClose (fh);
syscall_printf ("%d = fstatvfs (%s, %p)", ret, get_name (), sfs); syscall_printf ("%d = fstatvfs (%s, %p)", ret, get_name (), sfs);
return ret; return ret;
} }

View File

@ -805,4 +805,18 @@ extern "C"
dest->Length = dest->MaximumLength = len; dest->Length = dest->MaximumLength = len;
dest->Buffer = (PWSTR) buf; dest->Buffer = (PWSTR) buf;
} }
inline
VOID NTAPI RtlSplitUnicodePath (PUNICODE_STRING path, PUNICODE_STRING dir,
PUNICODE_STRING file)
{
USHORT len = path->Length / sizeof (WCHAR);
while (len > 0 && path->Buffer[--len] != L'\\')
;
++len;
if (dir)
RtlInitCountedUnicodeString (dir, len * sizeof (WCHAR), path->Buffer);
if (file)
RtlInitCountedUnicodeString (file, path->Length - len * sizeof (WCHAR),
&path->Buffer[len]);
}
} }