* mount.h (enum fs_info_type): New type.

(IMPLEMENT_FS_FLAG): New define.
	(class fs_info): Convert filesystem type status flags into an enum
	fs_info_type.  Add cifs FS.  Revert change to has_buggy_open and
	has_buggy_fileid_dirinfo.  Make them normal; status flags again.
	Implement is_FS functions using IMPLEMENT_FS_FLAG.
	* mount.cc (fs_info::update): Define MINIMAL_WIN_NTFS_FLAGS and
	FS_IS_WINDOWS_NTFS.  Add comment.  Only test remote filesystems
	for "NTFS" once.  Add is_cifs check using FS_IS_WINDOWS_NTFS.
	Set has_buggy_open flag for SUNWNFS.  Set has_buggy_fileid_dirinfo
	flag for UNIXFS and all cifs type filesystems.  Only check for
	caseinsensitivity once.
	(fillout_mntent): Create locale fs_names array.  Use for setting
	_my_tls.locals.mnt_type.
This commit is contained in:
Corinna Vinschen 2009-07-28 10:39:55 +00:00
parent d826cbf322
commit 8d641a5b46
3 changed files with 131 additions and 84 deletions

View File

@ -1,3 +1,20 @@
2009-07-27 Corinna Vinschen <corinna@vinschen.de>
* mount.h (enum fs_info_type): New type.
(IMPLEMENT_FS_FLAG): New define.
(class fs_info): Convert filesystem type status flags into an enum
fs_info_type. Add cifs FS. Revert change to has_buggy_open and
has_buggy_fileid_dirinfo. Make them normal; status flags again.
Implement is_FS functions using IMPLEMENT_FS_FLAG.
* mount.cc (fs_info::update): Define MINIMAL_WIN_NTFS_FLAGS and
FS_IS_WINDOWS_NTFS. Add comment. Only test remote filesystems
for "NTFS" once. Add is_cifs check using FS_IS_WINDOWS_NTFS.
Set has_buggy_open flag for SUNWNFS. Set has_buggy_fileid_dirinfo
flag for UNIXFS and all cifs type filesystems. Only check for
caseinsensitivity once.
(fillout_mntent): Create locale fs_names array. Use for setting
_my_tls.locals.mnt_type.
2009-07-27 Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
* posix.sgml (std-notes): Remove obsolete reference to CYGWIN=server.

View File

@ -198,6 +198,10 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
}
flags (ffai_buf.ffai.FileSystemAttributes);
name_len (ffai_buf.ffai.MaximumComponentNameLength);
RtlInitCountedUnicodeString (&fsname, ffai_buf.ffai.FileSystemName,
ffai_buf.ffai.FileSystemNameLength);
if (is_remote_drive ())
{
/* 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
@ -215,16 +219,23 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
FILE_CASE_SENSITIVE_SEARCH \
| FILE_CASE_PRESERVED_NAMES \
| FILE_PERSISTENT_ACLS)
/* Netapp DataOnTap. TODO: Find out if that's the only flag combination. */
#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);
if (is_remote_drive ())
{
/* These are the minimal flags supported by NTFS since NT4. Every filesystem
not supporting these flags is not a native NTFS. We subsume them under
the filesystem type "cifs". */
#define MINIMAL_WIN_NTFS_FLAGS (FILE_CASE_SENSITIVE_SEARCH \
| FILE_CASE_PRESERVED_NAMES \
| FILE_UNICODE_ON_DISK \
| FILE_PERSISTENT_ACLS \
| FILE_FILE_COMPRESSION)
#define FS_IS_WINDOWS_NTFS TEST_GVI(flags () & MINIMAL_WIN_NTFS_FLAGS, \
MINIMAL_WIN_NTFS_FLAGS)
/* This always fails on NT4. */
status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi,
FileFsObjectIdInformation);
@ -238,14 +249,17 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
samba_version (extended_info->samba_version);
}
}
if (!got_fs ()
/* First check the remote filesystems faking to be NTFS. */
if (!got_fs () && RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)
/* Test for Samba on NT4 or for older Samba releases not supporting
extended info. */
&& !is_samba (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)
&& FS_IS_SAMBA)
&& !is_samba (FS_IS_SAMBA)
/* Netapp inode info is unusable. */
&& !is_netapp (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)
&& FS_IS_NETAPP_DATAONTAP)
&& !is_netapp (FS_IS_NETAPP_DATAONTAP))
/* Any other remote FS faking to be NTFS. */
is_cifs (!FS_IS_WINDOWS_NTFS);
/* Then check remote filesystems honest about their name. */
if (!got_fs ()
/* Microsoft NFS needs distinct access methods for metadata. */
&& !is_nfs (RtlEqualUnicodeString (&fsname, &ro_u_nfs, FALSE))
/* MVFS == Rational ClearCase remote filesystem. Has a couple of
@ -257,25 +271,23 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
&& !is_unixfs (RtlEqualUnicodeString (&fsname, &ro_u_unixfs, FALSE)))
/* Known remote file system with buggy open calls. Further
explanation in fhandler.cc (fhandler_disk_file::open). */
is_sunwnfs (RtlEqualUnicodeString (&fsname, &ro_u_sunwnfs, FALSE));
{
is_sunwnfs (RtlEqualUnicodeString (&fsname, &ro_u_sunwnfs, FALSE));
has_buggy_open (is_sunwnfs ());
}
/* Not only UNIXFS is known to choke on FileIdBothDirectoryInformation.
Some other CIFS servers have problems with this call as well.
Know example: EMC NS-702. We just don't use that info class on
any remote CIFS. */
if (got_fs ())
has_buggy_fileid_dirinfo (is_cifs () || is_unixfs ());
}
if (!got_fs ()
&& !is_ntfs (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE))
&& !is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE))
&& !is_csc_cache (RtlEqualUnicodeString (&fsname, &ro_u_csc, FALSE))
&& is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM))
{
is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE));
/* UDF on NT 5.x is broken (at least) in terms of case sensitivity.
The UDF driver reports the FILE_CASE_SENSITIVE_SEARCH capability
but:
- Opening the root directory for query seems to work at first,
but the filenames in the directory listing are mutilated.
- When trying to open a file or directory case sensitive, the file
appears to be non-existant. */
if (is_udf () && wincap.has_broken_udf ())
caseinsensitive (true);
}
is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE));
if (!got_fs ())
{
/* The filesystem name is only used in fillout_mntent and only if
@ -289,10 +301,20 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
hasgood_inode ((has_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 ());
sensitive.
UDF on NT 5.x is broken (at least) in terms of case sensitivity.
The UDF driver reports the FILE_CASE_SENSITIVE_SEARCH capability
but:
- Opening the root directory for query seems to work at first,
but the filenames in the directory listing are mutilated.
- When trying to open a file or directory case sensitive, the file
appears to be non-existant. */
caseinsensitive (((!(flags () & FILE_CASE_SENSITIVE_SEARCH) || is_samba ())
&& !is_nfs ())
|| (is_udf () && wincap.has_broken_udf ()));
if (!in_vol)
NtClose (vol);
@ -1405,28 +1427,25 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
RtlAppendUnicodeToString (&unat, L"\\");
mntinfo.update (&unat, NULL);
if (mntinfo.is_ntfs ())
strcpy (_my_tls.locals.mnt_type, (char *) "ntfs");
else if (mntinfo.is_fat ())
strcpy (_my_tls.locals.mnt_type, (char *) "vfat");
else if (mntinfo.is_samba())
strcpy (_my_tls.locals.mnt_type, (char *) "smbfs");
else if (mntinfo.is_nfs ())
strcpy (_my_tls.locals.mnt_type, (char *) "nfs");
else if (mntinfo.is_udf ())
strcpy (_my_tls.locals.mnt_type, (char *) "udf");
else if (mntinfo.is_cdrom ())
strcpy (_my_tls.locals.mnt_type, (char *) "iso9660");
else if (mntinfo.is_netapp ())
strcpy (_my_tls.locals.mnt_type, (char *) "netapp");
else if (mntinfo.is_csc_cache ())
strcpy (_my_tls.locals.mnt_type, (char *) "csc-cache");
else if (mntinfo.is_mvfs ())
strcpy (_my_tls.locals.mnt_type, (char *) "mvfs");
else if (mntinfo.is_unixfs ())
strcpy (_my_tls.locals.mnt_type, (char *) "unixfs");
else if (mntinfo.is_sunwnfs ())
strcpy (_my_tls.locals.mnt_type, (char *) "sunwnfs");
/* Order must be identical to mount.h, enum fs_info_type. */
const char *fs_names[] = {
"none",
"vfat",
"ntfs",
"smbfs",
"nfs",
"netapp",
"iso9660",
"udf",
"csc-cache",
"sunwnfs",
"unixfs",
"mvfs",
"cifs"
};
if (mntinfo.what_fs () > 0 && mntinfo.what_fs () < max_fs_type)
strcpy (_my_tls.locals.mnt_type, fs_names[mntinfo.what_fs ()]);
else
strcpy (_my_tls.locals.mnt_type, mntinfo.fsname ());

View File

@ -12,39 +12,47 @@ details. */
#ifndef _MOUNT_H
#define _MOUNT_H
enum fs_info_type
{
none = 0,
fat,
ntfs,
samba,
nfs,
netapp,
cdrom,
udf,
csc_cache,
sunwnfs,
unixfs,
mvfs,
cifs,
/* Always last. */
max_fs_type
};
#define IMPLEMENT_FS_FLAG(func, flag) \
bool func (bool val) { if (val) status.fs_type = flag; return val; } \
bool func () const { return status.fs_type == flag; }
class fs_info
{
struct status_flags
{
ULONG flags; /* Volume flags */
ULONG samba_version; /* Samba version if available */
ULONG name_len; /* MaximumComponentNameLength */
ULONG flags; /* Volume flags */
ULONG samba_version; /* Samba version if available */
ULONG name_len; /* MaximumComponentNameLength */
fs_info_type fs_type; /* Filesystem type */
unsigned is_remote_drive : 1;
unsigned has_acls : 1;
unsigned hasgood_inode : 1;
unsigned caseinsensitive : 1;
union
{
struct
{
unsigned is_fat : 1;
unsigned is_ntfs : 1;
unsigned is_samba : 1;
unsigned is_nfs : 1;
unsigned is_netapp : 1;
unsigned is_cdrom : 1;
unsigned is_udf : 1;
unsigned is_csc_cache : 1;
unsigned is_sunwnfs : 1;
unsigned is_unixfs : 1;
unsigned is_mvfs : 1;
};
unsigned long fs_flags;
};
unsigned has_buggy_open : 1;
unsigned has_buggy_fileid_dirinfo : 1;
} status;
ULONG sernum;
char fsn[80];
unsigned long got_fs () { return status.fs_flags; }
ULONG sernum; /* Volume Serial Number */
char fsn[80]; /* Windows filesystem name */
unsigned long got_fs () const { return status.fs_type != none; }
public:
void clear ()
@ -62,21 +70,24 @@ class fs_info
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)
IMPLEMENT_STATUS_FLAG (bool, is_udf)
IMPLEMENT_STATUS_FLAG (bool, is_csc_cache)
IMPLEMENT_STATUS_FLAG (bool, is_sunwnfs)
IMPLEMENT_STATUS_FLAG (bool, is_unixfs)
IMPLEMENT_STATUS_FLAG (bool, is_mvfs)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo)
IMPLEMENT_FS_FLAG (is_fat, fat)
IMPLEMENT_FS_FLAG (is_ntfs, ntfs)
IMPLEMENT_FS_FLAG (is_samba, samba)
IMPLEMENT_FS_FLAG (is_nfs, nfs)
IMPLEMENT_FS_FLAG (is_netapp, netapp)
IMPLEMENT_FS_FLAG (is_cdrom, cdrom)
IMPLEMENT_FS_FLAG (is_udf, udf)
IMPLEMENT_FS_FLAG (is_csc_cache, csc_cache)
IMPLEMENT_FS_FLAG (is_sunwnfs, sunwnfs)
IMPLEMENT_FS_FLAG (is_unixfs, unixfs)
IMPLEMENT_FS_FLAG (is_mvfs, mvfs)
IMPLEMENT_FS_FLAG (is_cifs, cifs)
fs_info_type what_fs () const { return status.fs_type; }
ULONG serial_number () const { return sernum; }
int has_buggy_open () const {return is_sunwnfs ();}
int has_buggy_fileid_dirinfo () const {return is_unixfs ();}
const char *fsname () const { return fsn[0] ? fsn : "unknown"; }
bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3)));