* 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.
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user