diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 76002fb22..f970d8ab4 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2014-10-09 Corinna Vinschen + + * fhandler_procsys.cc (fhandler_procsys::readdir): Just test + ObjectTypeName for object types rather than calling lstat to avoid + performance hit. + * globals.cc (ro_u_natdir): Define. + (ro_u_natsyml): Define. + (ro_u_natdev): Define. + 2014-10-09 Corinna Vinschen * fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Set d_type diff --git a/winsup/cygwin/fhandler_procsys.cc b/winsup/cygwin/fhandler_procsys.cc index 98fa9e212..1e937c89d 100644 --- a/winsup/cygwin/fhandler_procsys.cc +++ b/winsup/cygwin/fhandler_procsys.cc @@ -177,30 +177,28 @@ fhandler_procsys::exists (struct stat *buf) /* Don't call NtQueryInformationFile unless we know it's a safe type. The call is known to crash machines, if the underlying driver is badly written. */ - if (!NT_SUCCESS (status)) + if (NT_SUCCESS (status)) { - NtClose (h); - return file_type; - } - if (ffdi.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) - file_type = virt_blk; - else if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE) - file_type = internal ? virt_blk : virt_pipe; - else if (ffdi.DeviceType == FILE_DEVICE_DISK - || ffdi.DeviceType == FILE_DEVICE_CD_ROM - || ffdi.DeviceType == FILE_DEVICE_DFS - || ffdi.DeviceType == FILE_DEVICE_VIRTUAL_DISK) - { - /* Check for file attributes. If we get them, we peeked - into a real FS through /proc/sys. */ - status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, - FileBasicInformation); - debug_printf ("NtQueryInformationFile: %y", status); - if (!NT_SUCCESS (status)) + if (ffdi.DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) file_type = virt_blk; - else - file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) - ? virt_fsdir : virt_fsfile; + else if (ffdi.DeviceType == FILE_DEVICE_NAMED_PIPE) + file_type = internal ? virt_blk : virt_pipe; + else if (ffdi.DeviceType == FILE_DEVICE_DISK + || ffdi.DeviceType == FILE_DEVICE_CD_ROM + || ffdi.DeviceType == FILE_DEVICE_DFS + || ffdi.DeviceType == FILE_DEVICE_VIRTUAL_DISK) + { + /* Check for file attributes. If we get them, we peeked + into a real FS through /proc/sys. */ + status = NtQueryInformationFile (h, &io, &fbi, sizeof fbi, + FileBasicInformation); + debug_printf ("NtQueryInformationFile: %y", status); + if (!NT_SUCCESS (status)) + file_type = virt_blk; + else + file_type = (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ? virt_fsdir : virt_fsfile; + } } NtClose (h); } @@ -346,7 +344,6 @@ fhandler_procsys::readdir (DIR *dir, dirent *de) WCHAR buf[2][NAME_MAX + 1]; } f; int res = EBADF; - tmp_pathbuf tp; if (dir->__handle != INVALID_HANDLE_VALUE) { @@ -358,16 +355,19 @@ fhandler_procsys::readdir (DIR *dir, dirent *de) res = ENMFILE; else { - struct stat st; - char *file = tp.c_get (); - sys_wcstombs (de->d_name, NAME_MAX + 1, f.dbi.ObjectName.Buffer, f.dbi.ObjectName.Length / sizeof (WCHAR)); de->d_ino = hash_path_name (get_ino (), de->d_name); - stpcpy (stpcpy (stpcpy (file, get_name ()), "/"), de->d_name); - if (!lstat64 (file, &st)) - de->d_type = IFTODT (st.st_mode); - else + if (RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natdir, + FALSE)) + de->d_type = DT_DIR; + else if (RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natsyml, + FALSE)) + de->d_type = DT_LNK; + else if (!RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natdev, + FALSE)) + de->d_type = DT_CHR; + else /* Can't nail down "Device" objects without further testing. */ de->d_type = DT_UNKNOWN; res = 0; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index a004276d7..ff80a4b6d 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -148,6 +148,9 @@ extern "C" { extern UNICODE_STRING _RDATA ro_u_pipedir = _ROU (L"\\\\?\\PIPE\\"); extern UNICODE_STRING _RDATA ro_u_globalroot = _ROU (L"\\\\.\\GLOBALROOT"); extern UNICODE_STRING _RDATA ro_u_null = _ROU (L"\\Device\\Null"); + extern UNICODE_STRING _RDATA ro_u_natdir = _ROU (L"Directory"); + extern UNICODE_STRING _RDATA ro_u_natsyml = _ROU (L"SymbolicLink"); + extern UNICODE_STRING _RDATA ro_u_natdev = _ROU (L"Device"); #undef _ROU /* Cygwin properties are meant to be readonly data placed in the DLL, but