summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/mount.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2008-12-25 15:55:31 +0000
committerChristopher Faylor <me@cgf.cx>2008-12-25 15:55:31 +0000
commit5829832825e44ecd7fd35e36867d54ee3acced3c (patch)
tree33f2ad6d8dca0a99a8e30fe615f7f212b03ddb3c /winsup/cygwin/mount.cc
parent58402a3f63a23a8706c5dc58305c06b3df228170 (diff)
downloadcygnal-5829832825e44ecd7fd35e36867d54ee3acced3c.tar.gz
cygnal-5829832825e44ecd7fd35e36867d54ee3acced3c.tar.bz2
cygnal-5829832825e44ecd7fd35e36867d54ee3acced3c.zip
* 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.
Diffstat (limited to 'winsup/cygwin/mount.cc')
-rw-r--r--winsup/cygwin/mount.cc205
1 files changed, 201 insertions, 4 deletions
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 <mntent.h>
#include <ctype.h>
+#include <winioctl.h>
#include <wingdi.h>
#include <winuser.h>
#include <winnetwk.h>
@@ -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 <ntdll.h>
@@ -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. */