diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 53e527475..cffd26f84 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2012-02-16 Corinna Vinschen + + * autoload.cc (NetUseGetInfo): Define. + * fhandler_disk_file.cc (fhandler_cygdrive::opendir): Rename flptst + to drive. Call new get_disk_type function rather than is_floppy and + check SMB drives with the NetUseGetInfo function. Explain why. + * mount.cc (get_disk_type): New function to evaluate disk type from + native NT device name. + (is_floppy): Remove. + * mount.h (enum disk_type): Define. + (get_disk_type): Declare. + * path.h (is_floppy): Drop declaration. + 2012-02-15 Corinna Vinschen * miscfuncs.cc: Revert change from 2012-02-13 which used the diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 442a2e695..edd72f8d9 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -406,6 +406,7 @@ LoadDLLfunc (WNetOpenEnumA, 20, mpr) LoadDLLfunc (DsGetDcNameW, 24, netapi32) LoadDLLfunc (NetApiBufferFree, 4, netapi32) +LoadDLLfunc (NetUseGetInfo, 16, netapi32) LoadDLLfunc (NetUserGetGroups, 28, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32) LoadDLLfunc (NetUserGetLocalGroups, 32, netapi32) diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 13b9d6919..1fe12b0a2 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -25,6 +25,7 @@ details. */ #include "tls_pbuf.h" #include "pwdgrp.h" #include +#include #define _COMPILING_NEWLIB #include @@ -2412,7 +2413,7 @@ fhandler_cygdrive::opendir (int fd) int fhandler_cygdrive::readdir (DIR *dir, dirent *de) { - char flptst[] = "X:"; + WCHAR drive[] = L"X:"; while (true) { @@ -2426,8 +2427,29 @@ fhandler_cygdrive::readdir (DIR *dir, dirent *de) } return ENMFILE; } - if (!is_floppy ((flptst[0] = *pdrive, flptst)) - && GetFileAttributes (pdrive) != INVALID_FILE_ATTRIBUTES) + disk_type dt = get_disk_type ((drive[0] = *pdrive, drive)); + if (dt == DT_SHARE_SMB) + { + /* Calling NetUseGetInfo on SMB drives allows to fetch the + current state of the drive without trying to open a file + descriptor on the share (GetFileAttributes). This avoids + waiting for SMB timeouts. Of course, there's a downside: + If a drive becomes availabe again, it can take a couple of + minutes to recognize it. As long as this didn't happen, + the drive will not show up in the cygdrive dir. */ + PUSE_INFO_1 pui1; + DWORD status; + + if (NetUseGetInfo (NULL, drive, 1, (PBYTE *) &pui1) == NERR_Success) + { + status = pui1->ui1_status; + NetApiBufferFree (pui1); + if (status == USE_OK) + break; + } + } + else if (dt != DT_FLOPPY + && GetFileAttributes (pdrive) != INVALID_FILE_ATTRIBUTES) break; pdrive = strchr (pdrive, '\0') + 1; } diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index ef7d746df..17d5c571f 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -1840,13 +1840,42 @@ cygwin_umount (const char *path, unsigned flags) return res; } -bool -is_floppy (const char *dos) +#define is_dev(d,s) wcsncmp((d),(s),sizeof(s) - 1) + +disk_type +get_disk_type (LPCWSTR dos) { - char dev[256]; - if (!QueryDosDevice (dos, dev, 256)) - return false; - return ascii_strncasematch (dev, "\\Device\\Floppy", 14); + WCHAR dev[MAX_PATH], *d = dev; + if (!QueryDosDeviceW (dos, dev, MAX_PATH)) + return DT_NODISK; + if (is_dev (dev, L"\\Device\\")) + { + d += 8; + switch (toupper (*d)) + { + case 'C': + if (is_dev (d, L"CdRom")) + return DT_CDROM; + break; + case 'F': + if (is_dev (d, L"Floppy")) + return DT_FLOPPY; + break; + case 'H': + if (is_dev (d, L"Harddisk")) + return DT_HARDDISK; + break; + case 'L': + if (is_dev (d, L"LanmanRedirector\\")) + return DT_SHARE_SMB; + break; + case 'M': + if (is_dev (d, L"MRxNfs\\")) + return DT_SHARE_NFS; + break; + } + } + return DT_NODISK; } extern "C" FILE * @@ -1855,9 +1884,11 @@ setmntent (const char *filep, const char *) _my_tls.locals.iteration = 0; _my_tls.locals.available_drives = GetLogicalDrives (); /* Filter floppy drives on A: and B: */ - if ((_my_tls.locals.available_drives & 1) && is_floppy ("A:")) + if ((_my_tls.locals.available_drives & 1) + && get_disk_type (L"A:") == DT_FLOPPY) _my_tls.locals.available_drives &= ~1; - if ((_my_tls.locals.available_drives & 2) && is_floppy ("B:")) + if ((_my_tls.locals.available_drives & 2) + && get_disk_type (L"B:") == DT_FLOPPY) _my_tls.locals.available_drives &= ~2; return (FILE *) filep; } diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h index 606e9f595..1c8a6cd5c 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, 2010, 2011 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. This file is part of Cygwin. @@ -12,6 +12,18 @@ details. */ #ifndef _MOUNT_H #define _MOUNT_H +enum disk_type +{ + DT_NODISK, + DT_CDROM, + DT_FLOPPY, + DT_HARDDISK, + DT_SHARE_SMB, + DT_SHARE_NFS +}; + +disk_type get_disk_type (LPCWSTR); + enum fs_info_type { none = 0, diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 3ef857a89..07302b6e2 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -424,7 +424,6 @@ bool has_dot_last_component (const char *dir, bool test_dot_dot) __attribute__ ( int path_prefix_p (const char *path1, const char *path2, int len1, bool caseinsensitive) __attribute__ ((regparm (3))); -bool is_floppy (const char *); NTSTATUS file_get_fnoi (HANDLE, bool, struct _FILE_NETWORK_OPEN_INFORMATION *); int normalize_win32_path (const char *, char *, char *&); int normalize_posix_path (const char *, char *, char *&);