From c04ed45d82f5bcf20b2018f6b92b27a0e95aae72 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 12 Jan 2010 14:47:46 +0000 Subject: * globals.cc (ro_u_nwfs): New R/O unicode string. * mount.cc (fs_info::update): Check for NWFS filesystem. Set has_buggy_basic_info, if so. Add comment to explain why. (fillout_mntent): Add "nwfs" string to fs_names array. * mount.h (enum fs_info_type): Add nwfs. (class fs_info): Add has_buggy_basic_info status flag. Add accessors for has_buggy_basic_info and is_nwfs. * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Accommodate filesystems with broken FileBasicInformation handling. * path.cc (symlink_info::check): Ditto. * path.h (path_conv::has_buggy_basic_info): Add method. --- winsup/cygwin/ChangeLog | 14 ++++++++++++ winsup/cygwin/fhandler_disk_file.cc | 45 ++++++++++++++++++++++++------------- winsup/cygwin/globals.cc | 3 ++- winsup/cygwin/mount.cc | 14 +++++++++--- winsup/cygwin/mount.h | 6 ++++- winsup/cygwin/path.cc | 16 +++++++------ winsup/cygwin/path.h | 1 + 7 files changed, 71 insertions(+), 28 deletions(-) (limited to 'winsup/cygwin') diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 724eb4458..02a0659a7 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +2010-01-12 Corinna Vinschen + + * globals.cc (ro_u_nwfs): New R/O unicode string. + * mount.cc (fs_info::update): Check for NWFS filesystem. Set + has_buggy_basic_info, if so. Add comment to explain why. + (fillout_mntent): Add "nwfs" string to fs_names array. + * mount.h (enum fs_info_type): Add nwfs. + (class fs_info): Add has_buggy_basic_info status flag. Add accessors + for has_buggy_basic_info and is_nwfs. + * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Accommodate + filesystems with broken FileBasicInformation handling. + * path.cc (symlink_info::check): Ditto. + * path.h (path_conv::has_buggy_basic_info): Add method. + 2010-01-12 Corinna Vinschen * dtable.cc (build_fh_name_worker): Remove. Move all functionality diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 797f42063..8be74add5 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -337,12 +337,25 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) 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_BASIC_INFORMATION fbi; + + union { + FILE_BASIC_INFORMATION fbi; + FILE_NETWORK_OPEN_INFORMATION fnoi; + } fi; FILE_STANDARD_INFORMATION fsi; FILE_INTERNAL_INFORMATION fii; - status = NtQueryInformationFile (get_handle (), &io, &fbi, sizeof fbi, - FileBasicInformation); + if (pc.has_buggy_basic_info ()) + { + status = NtQueryInformationFile (get_handle (), &io, &fi, sizeof fi, + FileNetworkOpenInformation); + /* The timestamps are in the same relative memory location, only + the DOS attributes have to be moved. */ + fi.fbi.FileAttributes = fi.fnoi.FileAttributes; + } + else + status = NtQueryInformationFile (get_handle (), &io, &fi.fbi, sizeof fi.fbi, + FileBasicInformation); if (!NT_SUCCESS (status)) { debug_printf ("%p = NtQueryInformationFile(%S, FileBasicInformation)", @@ -369,20 +382,20 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf) support a change timestamp. In that case use the LastWriteTime entry, as in other calls to fstat_helper. */ if (pc.is_rep_symlink ()) - fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; - pc.file_attributes (fbi.FileAttributes); + fi.fbi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; + pc.file_attributes (fi.fbi.FileAttributes); return fstat_helper (buf, - fbi.ChangeTime.QuadPart ? &fbi.ChangeTime - : &fbi.LastWriteTime, - &fbi.LastAccessTime, - &fbi.LastWriteTime, - &fbi.CreationTime, - get_dev (), - fsi.EndOfFile.QuadPart, - fsi.AllocationSize.QuadPart, - fii.FileId.QuadPart, - fsi.NumberOfLinks, - fbi.FileAttributes); + fi.fbi.ChangeTime.QuadPart ? &fi.fbi.ChangeTime + : &fi.fbi.LastWriteTime, + &fi.fbi.LastAccessTime, + &fi.fbi.LastWriteTime, + &fi.fbi.CreationTime, + get_dev (), + fsi.EndOfFile.QuadPart, + fsi.AllocationSize.QuadPart, + fii.FileId.QuadPart, + fsi.NumberOfLinks, + fi.fbi.FileAttributes); } int __stdcall diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 9554ac834..5934a72b7 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -1,7 +1,7 @@ /* globals.cc - Define global variables here. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -106,6 +106,7 @@ UNICODE_STRING _RDATA ro_u_ntfs = _ROU (L"NTFS"); UNICODE_STRING _RDATA ro_u_sunwnfs = _ROU (L"SUNWNFS"); UNICODE_STRING _RDATA ro_u_udf = _ROU (L"UDF"); UNICODE_STRING _RDATA ro_u_unixfs = _ROU (L"UNIXFS"); +UNICODE_STRING _RDATA ro_u_nwfs = _ROU (L"NWFS"); UNICODE_STRING _RDATA ro_u_volume = _ROU (L"\\??\\Volume{"); #undef _ROU diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index b99a9b811..63507e78c 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -1,7 +1,7 @@ /* mount.cc: mount handling. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -289,6 +289,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) && !is_ntfs (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)) && !is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE)) && !is_csc_cache (RtlEqualUnicodeString (&fsname, &ro_u_csc, FALSE)) + && !is_nwfs (RtlEqualUnicodeString (&fsname, &ro_u_nwfs, FALSE)) && is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM)) is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE)); if (!got_fs ()) @@ -300,8 +301,14 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) strlwr (fsn); } has_acls (flags () & FS_PERSISTENT_ACLS); - /* Netapp inodes numbers are fly-by-night. */ + /* Netapp inode numbers are fly-by-night. */ hasgood_inode ((has_acls () && !is_netapp ()) || is_nfs ()); + /* NWFS is known to have a broken FileBasicInformation info class. It + can't be used to fetch information, only to set information. Therefore, + for NWFS we have to fallback to the FileNetworkOpenInformation info + class. Unfortunately we can't use FileNetworkOpenInformation all the + time since that fails on other filesystems like NFS. */ + has_buggy_basic_info (is_nwfs ()); /* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set, except on Samba which handles Windows clients case insensitive. @@ -1443,7 +1450,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags) "sunwnfs", "unixfs", "mvfs", - "cifs" + "cifs", + "nwfs" }; if (mntinfo.what_fs () > 0 && mntinfo.what_fs () < max_fs_type) diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h index 39d27569c..95a158ad7 100644 --- a/winsup/cygwin/mount.h +++ b/winsup/cygwin/mount.h @@ -1,7 +1,7 @@ /* mount.h: mount definitions. Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. This file is part of Cygwin. @@ -27,6 +27,7 @@ enum fs_info_type unixfs, mvfs, cifs, + nwfs, /* Always last. */ max_fs_type }; @@ -49,6 +50,7 @@ class fs_info unsigned caseinsensitive : 1; unsigned has_buggy_open : 1; unsigned has_buggy_fileid_dirinfo : 1; + unsigned has_buggy_basic_info : 1; } status; ULONG sernum; /* Volume Serial Number */ char fsn[80]; /* Windows filesystem name */ @@ -72,6 +74,7 @@ class fs_info IMPLEMENT_STATUS_FLAG (bool, caseinsensitive) IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo) + IMPLEMENT_STATUS_FLAG (bool, has_buggy_basic_info) IMPLEMENT_FS_FLAG (is_fat, fat) IMPLEMENT_FS_FLAG (is_ntfs, ntfs) IMPLEMENT_FS_FLAG (is_samba, samba) @@ -84,6 +87,7 @@ class fs_info IMPLEMENT_FS_FLAG (is_unixfs, unixfs) IMPLEMENT_FS_FLAG (is_mvfs, mvfs) IMPLEMENT_FS_FLAG (is_cifs, cifs) + IMPLEMENT_FS_FLAG (is_nwfs, nwfs) fs_info_type what_fs () const { return status.fs_type; } ULONG serial_number () const { return sernum; } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 47274b4e0..8ad8d2e52 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2260,9 +2260,16 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, } } } + + /* Check file system while we're having the file open anyway. + This speeds up path_conv noticably (~10%). */ + if (!fs_update_called) + fs.update (&upath, h); + if (NT_SUCCESS (status) - && NT_SUCCESS (status - = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, + && NT_SUCCESS (status = fs.has_buggy_basic_info () + ? NtQueryAttributesFile (&attr, &fbi) + : NtQueryInformationFile (h, &io, &fbi, sizeof fbi, FileBasicInformation))) fileattr = fbi.FileAttributes; else @@ -2359,11 +2366,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt, continue; } - /* Check file system while we're having the file open anyway. - This speeds up path_conv noticably (~10%). */ - if (!fs_update_called) - fs.update (&upath, h); - ext_tacked_on = !!*ext_here; res = -1; diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index b310dc7bc..18eb494bc 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -111,6 +111,7 @@ class path_conv int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;} int has_buggy_open () const {return fs.has_buggy_open ();} int has_buggy_fileid_dirinfo () const {return fs.has_buggy_fileid_dirinfo ();} + int has_buggy_basic_info () const {return fs.has_buggy_basic_info ();} int binmode () const { if (path_flags & PATH_BINARY) -- cgit v1.2.3