* ntdll.h (struct _FILE_FS_OBJECTID_INFORMATION): Define.

* path.cc (struct smb_extended_info): Define.
	(fs_info::update): Request object id info to get Samba information.
	Set flags according to new implementation.
	* path.h (struct fs_info): Add samba_version to status_flags.
	Implement flags() and samba_version() using IMPLEMENT_STATUS_FLAG.
This commit is contained in:
Corinna Vinschen 2008-01-22 17:43:22 +00:00
parent 226f5a32da
commit 4a96b0aa85
4 changed files with 62 additions and 12 deletions

View File

@ -1,3 +1,12 @@
2008-01-22 Corinna Vinschen <corinna@vinschen.de>
* ntdll.h (struct _FILE_FS_OBJECTID_INFORMATION): Define.
* path.cc (struct smb_extended_info): Define.
(fs_info::update): Request object id info to get Samba information.
Set flags according to new implementation.
* path.h (struct fs_info): Add samba_version to status_flags.
Implement flags() and samba_version() using IMPLEMENT_STATUS_FLAG.
2008-01-21 Corinna Vinschen <corinna@vinschen.de> 2008-01-21 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::link): Open file with * fhandler_disk_file.cc (fhandler_disk_file::link): Open file with

View File

@ -712,6 +712,11 @@ typedef struct _FILE_FS_FULL_SIZE_INFORMATION
ULONG BytesPerSector; ULONG BytesPerSector;
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
typedef struct _FILE_FS_OBJECTID_INFORMATION {
UCHAR ObjectId[16];
UCHAR ExtendedInfo[48];
} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION;
typedef enum _FSINFOCLASS { typedef enum _FSINFOCLASS {
FileFsVolumeInformation = 1, FileFsVolumeInformation = 1,
FileFsLabelInformation, FileFsLabelInformation,

View File

@ -378,6 +378,22 @@ mkrelpath (char *path)
strcpy (path, "."); strcpy (path, ".");
} }
/* Beginning with Samba 3.2, 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 bool
fs_info::update (PUNICODE_STRING upath, bool exists) fs_info::update (PUNICODE_STRING upath, bool exists)
{ {
@ -387,6 +403,7 @@ fs_info::update (PUNICODE_STRING upath, bool exists)
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
bool no_media = false; bool no_media = false;
FILE_FS_DEVICE_INFORMATION ffdi; FILE_FS_DEVICE_INFORMATION ffdi;
FILE_FS_OBJECTID_INFORMATION ffoi;
PFILE_FS_ATTRIBUTE_INFORMATION pffai; PFILE_FS_ATTRIBUTE_INFORMATION pffai;
UNICODE_STRING fsname, testname; UNICODE_STRING fsname, testname;
@ -444,11 +461,11 @@ fs_info::update (PUNICODE_STRING upath, bool exists)
debug_printf ("Cannot get volume attributes (%S), %08lx", debug_printf ("Cannot get volume attributes (%S), %08lx",
attr.ObjectName, status); attr.ObjectName, status);
has_buggy_open (false); has_buggy_open (false);
flags () = 0; flags (0);
NtClose (vol); NtClose (vol);
return false; return false;
} }
flags () = pffai->FileSystemAttributes; flags (pffai->FileSystemAttributes);
/* Should be reevaluated for each new OS. Right now this mask is valid up /* 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 to Vista. The important point here is to test only flags indicating
capabilities and to ignore flags indicating a specific state of this capabilities and to ignore flags indicating a specific state of this
@ -476,12 +493,30 @@ fs_info::update (PUNICODE_STRING upath, bool exists)
pffai->FileSystemNameLength); pffai->FileSystemNameLength);
is_fat (RtlEqualUnicodePathPrefix (&fsname, L"FAT", TRUE)); is_fat (RtlEqualUnicodePathPrefix (&fsname, L"FAT", TRUE));
RtlInitUnicodeString (&testname, L"NTFS"); RtlInitUnicodeString (&testname, L"NTFS");
is_samba (RtlEqualUnicodeString (&fsname, &testname, FALSE) if (is_remote_drive ())
&& (ffdi.Characteristics & FILE_REMOTE_DEVICE) {
&& (FS_IS_SAMBA || FS_IS_SAMBA_WITH_QUOTA)); /* This always fails on NT4. */
is_netapp (RtlEqualUnicodeString (&fsname, &testname, FALSE) status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi,
&& (ffdi.Characteristics & FILE_REMOTE_DEVICE) FileFsObjectIdInformation);
&& FS_IS_NETAPP_DATAONTAP); 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 older Samba releases not supporting the extended info. */
if (!is_samba ())
is_samba (RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& (FS_IS_SAMBA || FS_IS_SAMBA_WITH_QUOTA));
is_netapp (!is_samba ()
&& RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& FS_IS_NETAPP_DATAONTAP);
}
is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE) is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& !is_samba () && !is_netapp ()); && !is_samba () && !is_netapp ());
RtlInitUnicodeString (&testname, L"NFS"); RtlInitUnicodeString (&testname, L"NFS");

View File

@ -97,7 +97,8 @@ struct fs_info
private: private:
struct status_flags struct status_flags
{ {
DWORD flags; /* Volume flags */ DWORD flags; /* Volume flags */
DWORD samba_version; /* Samba version if available */
unsigned is_remote_drive : 1; unsigned is_remote_drive : 1;
unsigned has_buggy_open : 1; unsigned has_buggy_open : 1;
unsigned has_acls : 1; unsigned has_acls : 1;
@ -110,11 +111,11 @@ struct fs_info
unsigned is_cdrom : 1; unsigned is_cdrom : 1;
} status; } status;
public: public:
void clear () { memset (this, 0 , sizeof *this); } void clear () { memset (&status, 0 , sizeof status); }
fs_info () { clear (); } fs_info () { clear (); }
inline DWORD& flags () {return status.flags;}; IMPLEMENT_STATUS_FLAG (DWORD, flags)
IMPLEMENT_STATUS_FLAG (DWORD, samba_version)
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive) IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open) IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
IMPLEMENT_STATUS_FLAG (bool, has_acls) IMPLEMENT_STATUS_FLAG (bool, has_acls)