From ceaf31f416220413feedcad1cc3e9f30f57dc28f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 27 Jul 2007 10:10:57 +0000 Subject: * 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. --- winsup/cygwin/ChangeLog | 9 +++++ winsup/cygwin/fhandler_disk_file.cc | 68 +++++++++++++++++-------------------- winsup/cygwin/ntdll.h | 14 ++++++++ 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ca68bb8bd..e8574d5dd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2007-07-27 Corinna Vinschen + + * 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 * fhandler_disk_file.cc (is_volume_mountpoint): New static inline diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index bebc225e3..9264285d6 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -335,16 +335,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf) set_errno (ENOENT); return -1; } - /* Split path in dirname and 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); + RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename); InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE, NULL, NULL); if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, @@ -627,46 +618,51 @@ fhandler_disk_file::fstat (struct __stat64 *buf) int __stdcall fhandler_disk_file::fstatvfs (struct statvfs *sfs) { - int ret = -1, oret = 0; + int ret = -1, opened = 0; NTSTATUS status; IO_STATUS_BLOCK io; 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) alloca (fvi_size); 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) alloca (fai_size); FILE_FS_FULL_SIZE_INFORMATION full_fsi; FILE_FS_SIZE_INFORMATION fsi; + HANDLE fh = get_handle (); - if (!get_io_handle ()) + if (!fh) { - query_open (query_read_control); - oret = open_fs (O_RDONLY | O_BINARY, 0); - if (!oret) + OBJECT_ATTRIBUTES attr; + opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, + 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. */ - char root[CYG_MAX_PATH]; - if (!rootdir (get_win32_name (), root)) - goto out; - pc.check (root, PC_SYM_NOFOLLOW); - oret = open_fs (O_RDONLY | O_BINARY, 0); - if (!oret) + /* Can't open file. Try again with parent dir. */ + UNICODE_STRING dirname; + RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, NULL); + attr.ObjectName = &dirname; + opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, &attr, &io, + FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT)); + if (!opened) goto out; } } /* Get basic volume information. */ - status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size, + status = NtQueryVolumeInformationFile (fh, &io, pfvi, fvi_size, FileFsVolumeInformation); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); goto out; } - status = NtQueryVolumeInformationFile (get_handle (), &io, pfai, fai_size, + status = NtQueryVolumeInformationFile (fh, &io, pfai, fai_size, FileFsAttributeInformation); if (!NT_SUCCESS (status)) { @@ -682,8 +678,7 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) /* 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. */ - status = NtQueryVolumeInformationFile (get_handle (), &io, &full_fsi, - sizeof full_fsi, + status = NtQueryVolumeInformationFile (fh, &io, &full_fsi, sizeof full_fsi, FileFsFullSizeInformation); if (NT_SUCCESS (status)) { @@ -696,11 +691,12 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) { /* Quotas active. We can't trust TotalAllocationUnits. */ NTFS_VOLUME_DATA_BUFFER nvdb; - DWORD bytes; - if (!DeviceIoControl (get_handle (), FSCTL_GET_NTFS_VOLUME_DATA, NULL, - 0, &nvdb, sizeof nvdb, &bytes, NULL)) - debug_printf ("DeviceIoControl (%s) failed, %E", get_name ()); + status = NtFsControlFile (fh, NULL, NULL, NULL, &io, + FSCTL_GET_NTFS_VOLUME_DATA, + NULL, 0, &nvdb, sizeof nvdb); + if (!NT_SUCCESS (status)) + debug_printf ("NtFsControlFile (%s) failed, status %lx", status); else sfs->f_blocks = nvdb.TotalClusters.QuadPart; } @@ -708,8 +704,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) } else { - status = NtQueryVolumeInformationFile (get_handle (), &io, &fsi, - sizeof fsi, FileFsSizeInformation); + status = NtQueryVolumeInformationFile (fh, &io, &fsi, sizeof fsi, + FileFsSizeInformation); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); @@ -723,8 +719,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) ret = 0; } out: - if (oret) - close_fs (); + if (opened) + NtClose (fh); syscall_printf ("%d = fstatvfs (%s, %p)", ret, get_name (), sfs); return ret; } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index d3837bb99..cb2cccfa1 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -805,4 +805,18 @@ extern "C" dest->Length = dest->MaximumLength = len; 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]); + } } -- cgit v1.2.3