diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 5a6a8c2fc..f3d47e4c8 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2008-12-25 Christopher Faylor + + * mount.cc: Change comment. + (smb_extended_info): Move here from path.cc. + (fs_info::update): Ditto. + (mount_info::create_root_entry): Delay conversion to slashes and use + passed in buffer to figure out fs type. + * path.cc (smb_extended_info): Move. + (fs_info::update): Ditto. + * mount.h: New file. Move mount information here. + * path.h: (fs_info::update): Move. + * shared_info.h (mount_item): Ditto. + 2008-12-24 Christopher Faylor * path.cc (symlink_info::check_shortcut): Ensure that symlink handle is diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 2768ce53c..34b7b72ff 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -1,4 +1,4 @@ -/* path.cc: path support. +/* mount.cc: mount handling. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. @@ -13,6 +13,7 @@ details. */ #include "miscfuncs.h" #include #include +#include #include #include #include @@ -21,10 +22,10 @@ details. */ #include "cygerrno.h" #include "security.h" #include "path.h" +#include "shared_info.h" #include "fhandler.h" #include "dtable.h" #include "cygheap.h" -#include "shared_info.h" #include "cygtls.h" #include "tls_pbuf.h" #include @@ -82,6 +83,201 @@ win32_device_name (const char *src_path, char *win32_path, device& dev) return true; } +/* Beginning with Samba 3.0.28a, Samba allows to get version information using + the ExtendedInfo member returned by a FileFsObjectIdInformation request. + We just store the samba_version information for now. Older versions than + 3.2 are still guessed at by testing the file system flags. */ +#define SAMBA_EXTENDED_INFO_MAGIC 0x536d4261 /* "SmBa" */ +#define SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH 28 +#pragma pack(push,4) +struct smb_extended_info { + DWORD samba_magic; /* Always SAMBA_EXTENDED_INFO_MAGIC */ + DWORD samba_version; /* Major/Minor/Release/Revision */ + DWORD samba_subversion; /* Prerelease/RC/Vendor patch */ + LARGE_INTEGER samba_gitcommitdate; + char samba_version_string[SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH]; +}; +#pragma pack(pop) + +bool +fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) +{ + NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + HANDLE vol; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + bool no_media = false; + FILE_FS_DEVICE_INFORMATION ffdi; + FILE_FS_OBJECTID_INFORMATION ffoi; + struct { + FILE_FS_ATTRIBUTE_INFORMATION ffai; + WCHAR buf[NAME_MAX + 1]; + } ffai_buf; + struct { + FILE_FS_VOLUME_INFORMATION ffvi; + WCHAR buf[NAME_MAX + 1]; + } ffvi_buf; + UNICODE_STRING fsname, testname; + + clear (); + if (in_vol) + vol = in_vol; + else + { + /* Always caseinsensitive. We really just need access to the drive. */ + InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, + NULL); + status = NtOpenFile (&vol, READ_CONTROL, &attr, &io, + FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); + while (!NT_SUCCESS (status) + && (attr.ObjectName->Length > 7 * sizeof (WCHAR) + || status == STATUS_NO_MEDIA_IN_DEVICE)) + { + UNICODE_STRING dir; + RtlSplitUnicodePath (attr.ObjectName, &dir, NULL); + attr.ObjectName = &dir; + if (status == STATUS_NO_MEDIA_IN_DEVICE) + { + no_media = true; + dir.Length = 6 * sizeof (WCHAR); + } + else if (dir.Length > 7 * sizeof (WCHAR)) + dir.Length -= sizeof (WCHAR); + status = NtOpenFile (&vol, READ_CONTROL, &attr, &io, + FILE_SHARE_VALID_FLAGS, + FILE_OPEN_FOR_BACKUP_INTENT); + } + if (!NT_SUCCESS (status)) + { + debug_printf ("Cannot access path %S, status %08lx", + attr.ObjectName, status); + NtClose (vol); + return false; + } + } + + status = NtQueryVolumeInformationFile (vol, &io, &ffvi_buf.ffvi, + sizeof ffvi_buf, + FileFsVolumeInformation); + sernum = NT_SUCCESS (status) ? ffvi_buf.ffvi.VolumeSerialNumber : 0; + status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi, + FileFsDeviceInformation); + if (!NT_SUCCESS (status)) + ffdi.DeviceType = ffdi.Characteristics = 0; + + if (ffdi.Characteristics & FILE_REMOTE_DEVICE + || (!ffdi.DeviceType + && RtlEqualUnicodePathPrefix (attr.ObjectName, L"\\??\\UNC\\", TRUE))) + is_remote_drive (true); + else + is_remote_drive (false); + + if (!no_media) + status = NtQueryVolumeInformationFile (vol, &io, &ffai_buf.ffai, + sizeof ffai_buf, + FileFsAttributeInformation); + if (no_media || !NT_SUCCESS (status)) + { + debug_printf ("Cannot get volume attributes (%S), %08lx", + attr.ObjectName, status); + if (!in_vol) + NtClose (vol); + return false; + } + flags (ffai_buf.ffai.FileSystemAttributes); + name_len (ffai_buf.ffai.MaximumComponentNameLength); +/* Should be reevaluated for each new OS. Right now this mask is valid up + to Vista. The important point here is to test only flags indicating + capabilities and to ignore flags indicating a specific state of this + volume. At present these flags to ignore are FILE_VOLUME_IS_COMPRESSED + and FILE_READ_ONLY_VOLUME. */ +#define GETVOLINFO_VALID_MASK (0x003701ffUL) +#define TEST_GVI(f,m) (((f) & GETVOLINFO_VALID_MASK) == (m)) + +/* Volume quotas are potentially supported since Samba 3.0, object ids and + the unicode on disk flag since Samba 3.2. */ +#define SAMBA_IGNORE (FILE_VOLUME_QUOTAS \ + | FILE_SUPPORTS_OBJECT_IDS \ + | FILE_UNICODE_ON_DISK) +#define FS_IS_SAMBA TEST_GVI(flags () & ~SAMBA_IGNORE, \ + FILE_CASE_SENSITIVE_SEARCH \ + | FILE_CASE_PRESERVED_NAMES \ + | FILE_PERSISTENT_ACLS) +#define FS_IS_NETAPP_DATAONTAP TEST_GVI(flags (), \ + FILE_CASE_SENSITIVE_SEARCH \ + | FILE_CASE_PRESERVED_NAMES \ + | FILE_UNICODE_ON_DISK \ + | FILE_PERSISTENT_ACLS \ + | FILE_NAMED_STREAMS) + RtlInitCountedUnicodeString (&fsname, ffai_buf.ffai.FileSystemName, + ffai_buf.ffai.FileSystemNameLength); + is_fat (RtlEqualUnicodePathPrefix (&fsname, L"FAT", TRUE)); + RtlInitUnicodeString (&testname, L"NTFS"); + if (is_remote_drive ()) + { + /* This always fails on NT4. */ + status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi, + FileFsObjectIdInformation); + if (NT_SUCCESS (status)) + { + smb_extended_info *extended_info = (smb_extended_info *) + &ffoi.ExtendedInfo; + if (extended_info->samba_magic == SAMBA_EXTENDED_INFO_MAGIC) + { + is_samba (true); + samba_version (extended_info->samba_version); + } + } + /* Test for Samba on NT4 or for older Samba releases not supporting + extended info. */ + if (!is_samba ()) + is_samba (RtlEqualUnicodeString (&fsname, &testname, FALSE) + && FS_IS_SAMBA); + + if (!is_samba ()) + { + is_netapp (RtlEqualUnicodeString (&fsname, &testname, FALSE) + && FS_IS_NETAPP_DATAONTAP); + + RtlInitUnicodeString (&testname, L"NFS"); + is_nfs (RtlEqualUnicodeString (&fsname, &testname, FALSE)); + + if (!is_nfs ()) + { + /* Known remote file systems which can't handle calls to + NtQueryDirectoryFile(FileIdBothDirectoryInformation) */ + RtlInitUnicodeString (&testname, L"UNIXFS"); + has_buggy_fileid_dirinfo (RtlEqualUnicodeString (&fsname, + &testname, + FALSE)); + + /* Known remote file systems with buggy open calls. Further + explanation in fhandler.cc (fhandler_disk_file::open). */ + RtlInitUnicodeString (&testname, L"SUNWNFS"); + has_buggy_open (RtlEqualUnicodeString (&fsname, &testname, + FALSE)); + } + } + } + is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE) + && !is_samba () && !is_netapp ()); + is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM); + + has_acls (flags () & FS_PERSISTENT_ACLS); + hasgood_inode (((flags () & FILE_PERSISTENT_ACLS) && !is_netapp ()) + || is_nfs ()); + /* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set, + except on Samba which handles Windows clients case insensitive. + NFS doesn't set the FILE_CASE_SENSITIVE_SEARCH flag but is case + sensitive. */ + caseinsensitive ((!(flags () & FILE_CASE_SENSITIVE_SEARCH) || is_samba ()) + && !is_nfs ()); + + if (!in_vol) + NtClose (vol); + return true; +} + inline void mount_info::create_root_entry (const PWCHAR root) { @@ -1122,7 +1318,6 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags) table because the mount table might change, causing weird effects from the getmntent user's point of view. */ - slashify (native_path, _my_tls.locals.mnt_fsname, false); ret.mnt_fsname = _my_tls.locals.mnt_fsname; strcpy (_my_tls.locals.mnt_dir, posix_path); ret.mnt_dir = _my_tls.locals.mnt_dir; @@ -1135,7 +1330,7 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags) tmp_pathbuf tp; UNICODE_STRING unat; tp.u_get (&unat); - get_nt_native_path (_my_tls.locals.mnt_fsname, unat); + get_nt_native_path (native_path, unat); if (append_bs) RtlAppendUnicodeToString (&unat, L"\\"); mntinfo.update (&unat, NULL); @@ -1157,6 +1352,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags) ret.mnt_type = _my_tls.locals.mnt_type; + slashify (native_path, _my_tls.locals.mnt_fsname, false); + /* mnt_opts is a string that details mount params such as binary or textmode, or exec. We don't print `silent' here; it's a magic internal thing. */ diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h new file mode 100644 index 000000000..45e7a8484 --- /dev/null +++ b/winsup/cygwin/mount.h @@ -0,0 +1,149 @@ +/* mount.h: mount definitions. + + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _MOUNT_H +#define _MOUNT_H + +class fs_info +{ + struct status_flags + { + ULONG flags; /* Volume flags */ + ULONG samba_version; /* Samba version if available */ + ULONG name_len; /* MaximumComponentNameLength */ + unsigned is_remote_drive : 1; + unsigned has_buggy_open : 1; + unsigned has_buggy_fileid_dirinfo : 1; + unsigned has_acls : 1; + unsigned hasgood_inode : 1; + unsigned caseinsensitive : 1; + unsigned is_fat : 1; + unsigned is_ntfs : 1; + unsigned is_samba : 1; + unsigned is_nfs : 1; + unsigned is_netapp : 1; + unsigned is_cdrom : 1; + } status; + ULONG sernum; + public: + void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; } + fs_info () { clear (); } + + IMPLEMENT_STATUS_FLAG (ULONG, flags) + IMPLEMENT_STATUS_FLAG (ULONG, samba_version) + IMPLEMENT_STATUS_FLAG (ULONG, name_len) + IMPLEMENT_STATUS_FLAG (bool, is_remote_drive) + IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) + IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo) + IMPLEMENT_STATUS_FLAG (bool, has_acls) + IMPLEMENT_STATUS_FLAG (bool, hasgood_inode) + IMPLEMENT_STATUS_FLAG (bool, caseinsensitive) + IMPLEMENT_STATUS_FLAG (bool, is_fat) + IMPLEMENT_STATUS_FLAG (bool, is_ntfs) + IMPLEMENT_STATUS_FLAG (bool, is_samba) + IMPLEMENT_STATUS_FLAG (bool, is_nfs) + IMPLEMENT_STATUS_FLAG (bool, is_netapp) + IMPLEMENT_STATUS_FLAG (bool, is_cdrom) + ULONG serial_number () const { return sernum; } + + bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3))); +}; + +/* Mount table entry */ + +class mount_item +{ + public: + /* FIXME: Nasty static allocation. Need to have a heap in the shared + area [with the user being able to configure at runtime the max size]. */ + /* Win32-style mounted partition source ("C:\foo\bar"). + native_path[0] == 0 for unused entries. */ + char native_path[CYG_MAX_PATH]; + int native_pathlen; + + /* POSIX-style mount point ("/foo/bar") */ + char posix_path[CYG_MAX_PATH]; + int posix_pathlen; + + unsigned flags; + + void init (const char *dev, const char *path, unsigned flags); + + struct mntent *getmntent (); + int build_win32 (char *, const char *, unsigned *, unsigned); +}; + +/* Warning: Decreasing this value will cause cygwin.dll to ignore existing + higher numbered registry entries. Don't change this number willy-nilly. + What we need is to have a more dynamic allocation scheme, but the current + scheme should be satisfactory for a long while yet. */ +#define MAX_MOUNTS 30 + +#define USER_VERSION 1 // increment when mount table changes and +#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION) +#define CURR_USER_MAGIC 0xb2232e71U + +class reg_key; +struct device; + +/* NOTE: Do not make gratuitous changes to the names or organization of the + below class. The layout is checksummed to determine compatibility between + different cygwin versions. */ +class mount_info +{ + public: + DWORD sys_mount_table_counter; + int nmounts; + mount_item mount[MAX_MOUNTS]; + + /* cygdrive_prefix is used as the root of the path automatically + prepended to a path when the path has no associated mount. + cygdrive_flags are the default flags for the cygdrives. */ + char cygdrive[CYG_MAX_PATH]; + size_t cygdrive_len; + unsigned cygdrive_flags; + private: + int posix_sorted[MAX_MOUNTS]; + int native_sorted[MAX_MOUNTS]; + + public: + void init (); + int add_item (const char *dev, const char *path, unsigned flags); + int del_item (const char *path, unsigned flags); + + unsigned set_flags_from_win32_path (const char *path); + int conv_to_win32_path (const char *src_path, char *dst, device&, + unsigned *flags = NULL); + int conv_to_posix_path (PWCHAR src_path, char *posix_path, + int keep_rel_p); + int conv_to_posix_path (const char *src_path, char *posix_path, + int keep_rel_p); + struct mntent *getmntent (int x); + + int write_cygdrive_info (const char *cygdrive_prefix, unsigned flags); + int get_cygdrive_info (char *user, char *system, char* user_flags, + char* system_flags); + void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); + int get_mounts_here (const char *parent_dir, int, + PUNICODE_STRING mount_points, + PUNICODE_STRING cygd); + + private: + void sort (); + void mount_slash (); + void create_root_entry (const PWCHAR root); + + bool from_fstab_line (char *line, bool user); + bool from_fstab (bool user, WCHAR [], PWCHAR); + + int cygdrive_win32_path (const char *src, char *dst, int& unit); +}; +#endif diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 5cacaba3b..ccbd9164f 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -353,201 +353,6 @@ mkrelpath (char *path, bool caseinsensitive) strcpy (path, "."); } -/* Beginning with Samba 3.0.28a, Samba allows to get version information using - the ExtendedInfo member returned by a FileFsObjectIdInformation request. - We just store the samba_version information for now. Older versions than - 3.2 are still guessed at by testing the file system flags. */ -#define SAMBA_EXTENDED_INFO_MAGIC 0x536d4261 /* "SmBa" */ -#define SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH 28 -#pragma pack(push,4) -struct smb_extended_info { - DWORD samba_magic; /* Always SAMBA_EXTENDED_INFO_MAGIC */ - DWORD samba_version; /* Major/Minor/Release/Revision */ - DWORD samba_subversion; /* Prerelease/RC/Vendor patch */ - LARGE_INTEGER samba_gitcommitdate; - char samba_version_string[SAMBA_EXTENDED_INFO_VERSION_STRING_LENGTH]; -}; -#pragma pack(pop) - -bool -fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) -{ - NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; - HANDLE vol; - OBJECT_ATTRIBUTES attr; - IO_STATUS_BLOCK io; - bool no_media = false; - FILE_FS_DEVICE_INFORMATION ffdi; - FILE_FS_OBJECTID_INFORMATION ffoi; - struct { - FILE_FS_ATTRIBUTE_INFORMATION ffai; - WCHAR buf[NAME_MAX + 1]; - } ffai_buf; - struct { - FILE_FS_VOLUME_INFORMATION ffvi; - WCHAR buf[NAME_MAX + 1]; - } ffvi_buf; - UNICODE_STRING fsname, testname; - - clear (); - if (in_vol) - vol = in_vol; - else - { - /* Always caseinsensitive. We really just need access to the drive. */ - InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, - NULL); - status = NtOpenFile (&vol, READ_CONTROL, &attr, &io, - FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); - while (!NT_SUCCESS (status) - && (attr.ObjectName->Length > 7 * sizeof (WCHAR) - || status == STATUS_NO_MEDIA_IN_DEVICE)) - { - UNICODE_STRING dir; - RtlSplitUnicodePath (attr.ObjectName, &dir, NULL); - attr.ObjectName = &dir; - if (status == STATUS_NO_MEDIA_IN_DEVICE) - { - no_media = true; - dir.Length = 6 * sizeof (WCHAR); - } - else if (dir.Length > 7 * sizeof (WCHAR)) - dir.Length -= sizeof (WCHAR); - status = NtOpenFile (&vol, READ_CONTROL, &attr, &io, - FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT); - } - if (!NT_SUCCESS (status)) - { - debug_printf ("Cannot access path %S, status %08lx", - attr.ObjectName, status); - NtClose (vol); - return false; - } - } - - status = NtQueryVolumeInformationFile (vol, &io, &ffvi_buf.ffvi, - sizeof ffvi_buf, - FileFsVolumeInformation); - sernum = NT_SUCCESS (status) ? ffvi_buf.ffvi.VolumeSerialNumber : 0; - status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi, - FileFsDeviceInformation); - if (!NT_SUCCESS (status)) - ffdi.DeviceType = ffdi.Characteristics = 0; - - if (ffdi.Characteristics & FILE_REMOTE_DEVICE - || (!ffdi.DeviceType - && RtlEqualUnicodePathPrefix (attr.ObjectName, L"\\??\\UNC\\", TRUE))) - is_remote_drive (true); - else - is_remote_drive (false); - - if (!no_media) - status = NtQueryVolumeInformationFile (vol, &io, &ffai_buf.ffai, - sizeof ffai_buf, - FileFsAttributeInformation); - if (no_media || !NT_SUCCESS (status)) - { - debug_printf ("Cannot get volume attributes (%S), %08lx", - attr.ObjectName, status); - if (!in_vol) - NtClose (vol); - return false; - } - flags (ffai_buf.ffai.FileSystemAttributes); - name_len (ffai_buf.ffai.MaximumComponentNameLength); -/* Should be reevaluated for each new OS. Right now this mask is valid up - to Vista. The important point here is to test only flags indicating - capabilities and to ignore flags indicating a specific state of this - volume. At present these flags to ignore are FILE_VOLUME_IS_COMPRESSED - and FILE_READ_ONLY_VOLUME. */ -#define GETVOLINFO_VALID_MASK (0x003701ffUL) -#define TEST_GVI(f,m) (((f) & GETVOLINFO_VALID_MASK) == (m)) - -/* Volume quotas are potentially supported since Samba 3.0, object ids and - the unicode on disk flag since Samba 3.2. */ -#define SAMBA_IGNORE (FILE_VOLUME_QUOTAS \ - | FILE_SUPPORTS_OBJECT_IDS \ - | FILE_UNICODE_ON_DISK) -#define FS_IS_SAMBA TEST_GVI(flags () & ~SAMBA_IGNORE, \ - FILE_CASE_SENSITIVE_SEARCH \ - | FILE_CASE_PRESERVED_NAMES \ - | FILE_PERSISTENT_ACLS) -#define FS_IS_NETAPP_DATAONTAP TEST_GVI(flags (), \ - FILE_CASE_SENSITIVE_SEARCH \ - | FILE_CASE_PRESERVED_NAMES \ - | FILE_UNICODE_ON_DISK \ - | FILE_PERSISTENT_ACLS \ - | FILE_NAMED_STREAMS) - RtlInitCountedUnicodeString (&fsname, ffai_buf.ffai.FileSystemName, - ffai_buf.ffai.FileSystemNameLength); - is_fat (RtlEqualUnicodePathPrefix (&fsname, L"FAT", TRUE)); - RtlInitUnicodeString (&testname, L"NTFS"); - if (is_remote_drive ()) - { - /* This always fails on NT4. */ - status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi, - FileFsObjectIdInformation); - if (NT_SUCCESS (status)) - { - smb_extended_info *extended_info = (smb_extended_info *) - &ffoi.ExtendedInfo; - if (extended_info->samba_magic == SAMBA_EXTENDED_INFO_MAGIC) - { - is_samba (true); - samba_version (extended_info->samba_version); - } - } - /* Test for Samba on NT4 or for older Samba releases not supporting - extended info. */ - if (!is_samba ()) - is_samba (RtlEqualUnicodeString (&fsname, &testname, FALSE) - && FS_IS_SAMBA); - - if (!is_samba ()) - { - is_netapp (RtlEqualUnicodeString (&fsname, &testname, FALSE) - && FS_IS_NETAPP_DATAONTAP); - - RtlInitUnicodeString (&testname, L"NFS"); - is_nfs (RtlEqualUnicodeString (&fsname, &testname, FALSE)); - - if (!is_nfs ()) - { - /* Known remote file systems which can't handle calls to - NtQueryDirectoryFile(FileIdBothDirectoryInformation) */ - RtlInitUnicodeString (&testname, L"UNIXFS"); - has_buggy_fileid_dirinfo (RtlEqualUnicodeString (&fsname, - &testname, - FALSE)); - - /* Known remote file systems with buggy open calls. Further - explanation in fhandler.cc (fhandler_disk_file::open). */ - RtlInitUnicodeString (&testname, L"SUNWNFS"); - has_buggy_open (RtlEqualUnicodeString (&fsname, &testname, - FALSE)); - } - } - } - is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE) - && !is_samba () && !is_netapp ()); - is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM); - - has_acls (flags () & FS_PERSISTENT_ACLS); - hasgood_inode (((flags () & FILE_PERSISTENT_ACLS) && !is_netapp ()) - || is_nfs ()); - /* Case sensitivity is supported if FILE_CASE_SENSITIVE_SEARCH is set, - except on Samba which handles Windows clients case insensitive. - NFS doesn't set the FILE_CASE_SENSITIVE_SEARCH flag but is case - sensitive. */ - caseinsensitive ((!(flags () & FILE_CASE_SENSITIVE_SEARCH) || is_samba ()) - && !is_nfs ()); - - if (!in_vol) - NtClose (vol); - return true; -} - void path_conv::fillin (HANDLE h) { diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 4c6f5cba1..1159ba8d4 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -10,6 +10,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include "devices.h" +#include "mount.h" #include #include @@ -83,51 +84,6 @@ enum path_types }; class symlink_info; -struct fs_info -{ - private: - struct status_flags - { - ULONG flags; /* Volume flags */ - ULONG samba_version; /* Samba version if available */ - ULONG name_len; /* MaximumComponentNameLength */ - unsigned is_remote_drive : 1; - unsigned has_buggy_open : 1; - unsigned has_buggy_fileid_dirinfo : 1; - unsigned has_acls : 1; - unsigned hasgood_inode : 1; - unsigned caseinsensitive : 1; - unsigned is_fat : 1; - unsigned is_ntfs : 1; - unsigned is_samba : 1; - unsigned is_nfs : 1; - unsigned is_netapp : 1; - unsigned is_cdrom : 1; - } status; - ULONG sernum; - public: - void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; } - fs_info () { clear (); } - - IMPLEMENT_STATUS_FLAG (ULONG, flags) - IMPLEMENT_STATUS_FLAG (ULONG, samba_version) - IMPLEMENT_STATUS_FLAG (ULONG, name_len) - IMPLEMENT_STATUS_FLAG (bool, is_remote_drive) - IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) - IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo) - IMPLEMENT_STATUS_FLAG (bool, has_acls) - IMPLEMENT_STATUS_FLAG (bool, hasgood_inode) - IMPLEMENT_STATUS_FLAG (bool, caseinsensitive) - IMPLEMENT_STATUS_FLAG (bool, is_fat) - IMPLEMENT_STATUS_FLAG (bool, is_ntfs) - IMPLEMENT_STATUS_FLAG (bool, is_samba) - IMPLEMENT_STATUS_FLAG (bool, is_nfs) - IMPLEMENT_STATUS_FLAG (bool, is_netapp) - IMPLEMENT_STATUS_FLAG (bool, is_cdrom) - ULONG serial_number () const { return sernum; } - - bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3))); -}; class path_conv { diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index efd79c600..97b46c5a2 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -12,96 +12,7 @@ details. */ #include "security.h" #include "mtinfo.h" #include "limits.h" - -/* Mount table entry */ - -class mount_item -{ - public: - /* FIXME: Nasty static allocation. Need to have a heap in the shared - area [with the user being able to configure at runtime the max size]. */ - /* Win32-style mounted partition source ("C:\foo\bar"). - native_path[0] == 0 for unused entries. */ - char native_path[CYG_MAX_PATH]; - int native_pathlen; - - /* POSIX-style mount point ("/foo/bar") */ - char posix_path[CYG_MAX_PATH]; - int posix_pathlen; - - unsigned flags; - - void init (const char *dev, const char *path, unsigned flags); - - struct mntent *getmntent (); - int build_win32 (char *, const char *, unsigned *, unsigned); -}; - -/* Warning: Decreasing this value will cause cygwin.dll to ignore existing - higher numbered registry entries. Don't change this number willy-nilly. - What we need is to have a more dynamic allocation scheme, but the current - scheme should be satisfactory for a long while yet. */ -#define MAX_MOUNTS 30 - -#define USER_VERSION 1 // increment when mount table changes and -#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION) -#define CURR_USER_MAGIC 0xb2232e71U - -class reg_key; -struct device; - -/* NOTE: Do not make gratuitous changes to the names or organization of the - below class. The layout is checksummed to determine compatibility between - different cygwin versions. */ -class mount_info -{ - public: - DWORD sys_mount_table_counter; - int nmounts; - mount_item mount[MAX_MOUNTS]; - - /* cygdrive_prefix is used as the root of the path automatically - prepended to a path when the path has no associated mount. - cygdrive_flags are the default flags for the cygdrives. */ - char cygdrive[CYG_MAX_PATH]; - size_t cygdrive_len; - unsigned cygdrive_flags; - private: - int posix_sorted[MAX_MOUNTS]; - int native_sorted[MAX_MOUNTS]; - - public: - void init (); - int add_item (const char *dev, const char *path, unsigned flags); - int del_item (const char *path, unsigned flags); - - unsigned set_flags_from_win32_path (const char *path); - int conv_to_win32_path (const char *src_path, char *dst, device&, - unsigned *flags = NULL); - int conv_to_posix_path (PWCHAR src_path, char *posix_path, - int keep_rel_p); - int conv_to_posix_path (const char *src_path, char *posix_path, - int keep_rel_p); - struct mntent *getmntent (int x); - - int write_cygdrive_info (const char *cygdrive_prefix, unsigned flags); - int get_cygdrive_info (char *user, char *system, char* user_flags, - char* system_flags); - void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); - int get_mounts_here (const char *parent_dir, int, - PUNICODE_STRING mount_points, - PUNICODE_STRING cygd); - - private: - void sort (); - void mount_slash (); - void create_root_entry (const PWCHAR root); - - bool from_fstab_line (char *line, bool user); - bool from_fstab (bool user, WCHAR [], PWCHAR); - - int cygdrive_win32_path (const char *src, char *dst, int& unit); -}; +#include "mount.h" class user_info {