* 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:
Christopher Faylor
2008-12-25 15:55:31 +00:00
parent 58402a3f63
commit 5829832825
6 changed files with 365 additions and 334 deletions

View File

@ -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)
{