* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop

usage of path_conv::volser().
	(fhandler_base::fstat_by_name): Ditto.
	* ntdll.h (STATUS_NO_MEDIA_IN_DEVICE): Define.
	(STATUS_OBJECT_NAME_NOT_FOUND): Define.
	(FILE_REMOVABLE_MEDIA, FILE_READ_ONLY_DEVICE, FILE_FLOPPY_DISKETTE)
	(FILE_WRITE_ONCE_MEDIA, FILE_REMOTE_DEVICE, FILE_DEVICE_IS_MOUNTED)
	(FILE_VIRTUAL_VOLUME, FILE_AUTOGENERATED_DEVICE_NAME)
	FILE_DEVICE_SECURE_OPEN): Define Device Characteristics.
	(struct _FILE_FS_DEVICE_INFORMATION): Define.
	* path.cc (MAX_FS_INFO_CNT): Remove.
	(fsinfo): Remove.
	(fsinfo_cnt): Remove.
	(fs_info::update): Rewrite using native NT functions.  Drop fs_info
	cashing since it's incorrect.
	(path_conv::fillin): Use NtQueryInformationFile.  Drop setting serial
	number.
	(path_conv::check): Accommodate new fs_info::update parameters.
	(fillout_mntent): Ditto.
	* path.h (fs_info): Drop serial, has_ea and drive_type status
	flags.
	(fs_info::update): Declare with new parameters.
	(path_conf::drive_type): Remove.
	(path_conf::fs_has_ea): Remove.
	(path_conf::volser): Remove.
This commit is contained in:
Corinna Vinschen 2007-08-01 12:55:25 +00:00
parent 67629eb258
commit d3dd7d3682
5 changed files with 134 additions and 98 deletions

View File

@ -1,3 +1,31 @@
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop
usage of path_conv::volser().
(fhandler_base::fstat_by_name): Ditto.
* ntdll.h (STATUS_NO_MEDIA_IN_DEVICE): Define.
(STATUS_OBJECT_NAME_NOT_FOUND): Define.
(FILE_REMOVABLE_MEDIA, FILE_READ_ONLY_DEVICE, FILE_FLOPPY_DISKETTE)
(FILE_WRITE_ONCE_MEDIA, FILE_REMOTE_DEVICE, FILE_DEVICE_IS_MOUNTED)
(FILE_VIRTUAL_VOLUME, FILE_AUTOGENERATED_DEVICE_NAME)
FILE_DEVICE_SECURE_OPEN): Define Device Characteristics.
(struct _FILE_FS_DEVICE_INFORMATION): Define.
* path.cc (MAX_FS_INFO_CNT): Remove.
(fsinfo): Remove.
(fsinfo_cnt): Remove.
(fs_info::update): Rewrite using native NT functions. Drop fs_info
cashing since it's incorrect.
(path_conv::fillin): Use NtQueryInformationFile. Drop setting serial
number.
(path_conv::check): Accommodate new fs_info::update parameters.
(fillout_mntent): Ditto.
* path.h (fs_info): Drop serial, has_ea and drive_type status
flags.
(fs_info::update): Declare with new parameters.
(path_conf::drive_type): Remove.
(path_conf::fs_has_ea): Remove.
(path_conf::volser): Remove.
2007-08-01 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (check_posix_perms): Remove.

View File

@ -279,7 +279,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
{
debug_printf ("%u = NtQueryVolumeInformationFile)",
RtlNtStatusToDosError (status));
pfvi->VolumeSerialNumber = pc.volser ();
pfvi->VolumeSerialNumber = 0;
}
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
FileAllInformation);
@ -371,7 +371,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
{
debug_printf ("%u = NtQueryVolumeInformationFile)",
RtlNtStatusToDosError (status));
pfvi->VolumeSerialNumber = pc.volser ();
pfvi->VolumeSerialNumber = 0;
}
NtClose (dir);
/* If the change time is 0, it's a file system which doesn't
@ -403,7 +403,7 @@ too_bad:
*(FILETIME *) &ft,
*(FILETIME *) &ft,
*(FILETIME *) &ft,
pc.volser (),
0,
0ULL,
-1LL,
0ULL,

View File

@ -16,7 +16,9 @@
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
#define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xc0000013)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
@ -38,6 +40,17 @@
#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0
#define WSLE_PAGE_SHAREABLE 0x100
/* Device Characteristics. */
#define FILE_REMOVABLE_MEDIA 0x00000001
#define FILE_READ_ONLY_DEVICE 0x00000002
#define FILE_FLOPPY_DISKETTE 0x00000004
#define FILE_WRITE_ONCE_MEDIA 0x00000008
#define FILE_REMOTE_DEVICE 0x00000010
#define FILE_DEVICE_IS_MOUNTED 0x00000020
#define FILE_VIRTUAL_VOLUME 0x00000040
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
#define FILE_DEVICE_SECURE_OPEN 0x00000100
typedef enum _FILE_INFORMATION_CLASS
{
FileDirectoryInformation = 1,
@ -633,6 +646,12 @@ typedef struct _FILE_COMPRESSION_INFORMATION
UCHAR ClusterSizeShift;
} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
typedef struct _FILE_FS_DEVICE_INFORMATION
{
ULONG DeviceType;
ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
{
ULONG FileSystemAttributes;

View File

@ -377,61 +377,74 @@ mkrelpath (char *path)
strcpy (path, ".");
}
#define MAX_FS_INFO_CNT 25
fs_info fsinfo[MAX_FS_INFO_CNT];
LONG fsinfo_cnt;
bool
fs_info::update (const char *win32_path)
fs_info::update (PUNICODE_STRING upath, bool exists)
{
char fsname [CYG_MAX_PATH];
char root_dir [CYG_MAX_PATH];
bool ret;
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;
PFILE_FS_ATTRIBUTE_INFORMATION pffai;
UNICODE_STRING fsname, testname;
if (!::rootdir (win32_path, root_dir))
InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (exists)
status = NtOpenFile (&vol, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
while (!NT_SUCCESS (status) && attr.ObjectName->Length > 6 * sizeof (WCHAR))
{
debug_printf ("Cannot get root component of path %s", win32_path);
UNICODE_STRING dir;
RtlSplitUnicodePath (attr.ObjectName, &dir, NULL);
dir.Length -= sizeof (WCHAR);
attr.ObjectName = &dir;
if (status == STATUS_NO_MEDIA_IN_DEVICE)
{
no_media = true;
dir.Length = 6 * 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);
clear ();
NtClose (vol);
return false;
}
status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi,
FileFsDeviceInformation);
if (!NT_SUCCESS (status))
ffdi.DeviceType = ffdi.Characteristics = 0;
__ino64_t tmp_name_hash = hash_path_name (1, root_dir);
if (tmp_name_hash == name_hash)
return true;
int idx = 0;
LONG cur_fsinfo_cnt = fsinfo_cnt;
while (idx < cur_fsinfo_cnt && fsinfo[idx].name_hash)
{
if (tmp_name_hash == fsinfo[idx].name_hash)
{
*this = fsinfo[idx];
return true;
}
++idx;
}
name_hash = tmp_name_hash;
root_len = strlen (root_dir);
drive_type (GetDriveType (root_dir));
if (drive_type () == DRIVE_REMOTE
|| (drive_type () == DRIVE_UNKNOWN
&& (root_dir[0] == '\\' && root_dir[1] == '\\')))
if (ffdi.Characteristics & FILE_REMOTE_DEVICE
|| (!ffdi.DeviceType
&& RtlEqualUnicodePathPrefix (attr.ObjectName, L"\\??\\UNC\\", TRUE)))
is_remote_drive (true);
else
is_remote_drive (false);
ret = GetVolumeInformation (root_dir, NULL, 0, &status.serial, NULL,
&status.flags, fsname, sizeof (fsname));
if (!ret && !is_remote_drive ())
if (!no_media)
{
debug_printf ("Cannot get volume information (%s), %E", root_dir);
const ULONG size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION)
+ NAME_MAX * sizeof (WCHAR);
pffai = (PFILE_FS_ATTRIBUTE_INFORMATION) alloca (size);
status = NtQueryVolumeInformationFile (vol, &io, pffai, size,
FileFsAttributeInformation);
}
if (no_media || !NT_SUCCESS (status))
{
debug_printf ("Cannot get volume attributes (%S), %08lx",
attr.ObjectName, status);
has_buggy_open (false);
has_ea (false);
flags () = serial () = 0;
flags () = 0;
NtClose (vol);
return false;
}
flags () = pffai->FileSystemAttributes;
/* 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
@ -455,63 +468,46 @@ fs_info::update (const char *win32_path)
| FILE_UNICODE_ON_DISK \
| FILE_PERSISTENT_ACLS \
| FILE_NAMED_STREAMS)
is_fat (strncasematch (fsname, "FAT", 3));
is_samba (strcmp (fsname, "NTFS") == 0 && is_remote_drive ()
RtlInitCountedUnicodeString (&fsname, pffai->FileSystemName,
pffai->FileSystemNameLength);
is_fat (RtlEqualUnicodePathPrefix (&fsname, L"FAT", TRUE));
RtlInitUnicodeString (&testname, L"NTFS");
is_samba (RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& (ffdi.Characteristics & FILE_REMOTE_DEVICE)
&& (FS_IS_SAMBA || FS_IS_SAMBA_WITH_QUOTA));
is_netapp (strcmp (fsname, "NTFS") == 0 && is_remote_drive ()
is_netapp (RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& (ffdi.Characteristics & FILE_REMOTE_DEVICE)
&& FS_IS_NETAPP_DATAONTAP);
is_ntfs (strcmp (fsname, "NTFS") == 0 && !is_samba () && !is_netapp ());
is_nfs (strcmp (fsname, "NFS") == 0);
is_cdrom (drive_type () == DRIVE_CDROM);
is_ntfs (RtlEqualUnicodeString (&fsname, &testname, FALSE)
&& !is_samba () && !is_netapp ());
RtlInitUnicodeString (&testname, L"NFS");
is_nfs (RtlEqualUnicodeString (&fsname, &testname, FALSE));
is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM);
has_ea (is_ntfs ());
has_acls ((flags () & FS_PERSISTENT_ACLS)
&& (allow_smbntsec || !is_remote_drive ()));
hasgood_inode (((flags () & FILE_PERSISTENT_ACLS)
&& drive_type () != DRIVE_UNKNOWN
&& !is_netapp ())
hasgood_inode (((flags () & FILE_PERSISTENT_ACLS) && !is_netapp ())
|| is_nfs ());
/* Known file systems with buggy open calls. Further explanation
in fhandler.cc (fhandler_disk_file::open). */
has_buggy_open (!strcmp (fsname, "SUNWNFS"));
RtlInitUnicodeString (&testname, L"SUNWNFS");
has_buggy_open (RtlEqualUnicodeString (&fsname, &testname, FALSE));
/* Only append non-removable drives to the global fsinfo storage */
if (drive_type () != DRIVE_REMOVABLE && !is_cdrom () && idx < MAX_FS_INFO_CNT)
{
LONG exc_cnt;
while ((exc_cnt = InterlockedExchange (&fsinfo_cnt, -1)) == -1)
low_priority_sleep (0);
if (exc_cnt < MAX_FS_INFO_CNT)
{
/* Check if another thread has already appended that very drive */
while (idx < exc_cnt)
{
if (fsinfo[idx++].name_hash == name_hash)
goto done;
}
fsinfo[exc_cnt++] = *this;
}
done:
InterlockedExchange (&fsinfo_cnt, exc_cnt);
}
NtClose (vol);
return true;
}
void
path_conv::fillin (HANDLE h)
{
BY_HANDLE_FILE_INFORMATION local;
if (!GetFileInformationByHandle (h, &local))
{
fileattr = INVALID_FILE_ATTRIBUTES;
fs.serial () = 0;
}
IO_STATUS_BLOCK io;
FILE_BASIC_INFORMATION fbi;
if (NT_SUCCESS (NtQueryInformationFile (h, &io, &fbi, sizeof fbi,
FileBasicInformation)))
fileattr = fbi.FileAttributes;
else
{
fileattr = local.dwFileAttributes;
fs.serial () = local.dwVolumeSerialNumber;
}
fs.drive_type (DRIVE_UNKNOWN);
fileattr = INVALID_FILE_ATTRIBUTES;
}
void
@ -1111,7 +1107,7 @@ out:
}
}
if (fs.update (path))
if (fs.update (get_nt_native_path (), exists ()))
{
debug_printf ("this->path(%s), has_acls(%d)", path, fs.has_acls ());
if (fs.has_acls () && allow_ntsec)
@ -2628,7 +2624,11 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
reasonable guesses for popular types. */
fs_info mntinfo;
mntinfo.update (native_path); /* this pulls from a cache, usually. */
UNICODE_STRING unat;
size_t size = (strlen (native_path) + 1) * sizeof (WCHAR);
RtlInitEmptyUnicodeString (&unat, (PWSTR) alloca (size), size);
get_nt_native_path (native_path, unat);
mntinfo.update (&unat, true); /* this pulls from a cache, usually. */
if (mntinfo.is_samba())
strcpy (_my_tls.locals.mnt_type, (char *) "smbfs");

View File

@ -98,13 +98,10 @@ struct fs_info
struct status_flags
{
DWORD flags; /* Volume flags */
DWORD serial; /* Volume serial number */
unsigned is_remote_drive : 1;
unsigned has_buggy_open : 1;
unsigned has_ea : 1;
unsigned has_acls : 1;
unsigned hasgood_inode : 1;
unsigned drive_type : 3;
unsigned is_fat : 1;
unsigned is_ntfs : 1;
unsigned is_samba : 1;
@ -117,13 +114,11 @@ struct fs_info
{
name_hash = 0;
root_len = 0;
flags () = serial () = 0;
flags () = 0;
is_remote_drive (false);
has_buggy_open (false);
has_ea (false);
has_acls (false);
hasgood_inode (false);
drive_type (false);
is_fat (false);
is_ntfs (false);
is_samba (false);
@ -132,15 +127,12 @@ struct fs_info
is_cdrom (false);
}
inline DWORD& flags () {return status.flags;};
inline DWORD& serial () {return status.serial;};
inline int length () const {return root_len;}
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
IMPLEMENT_STATUS_FLAG (bool, has_ea)
IMPLEMENT_STATUS_FLAG (bool, has_acls)
IMPLEMENT_STATUS_FLAG (bool, hasgood_inode)
IMPLEMENT_STATUS_FLAG (DWORD, drive_type)
IMPLEMENT_STATUS_FLAG (bool, is_fat)
IMPLEMENT_STATUS_FLAG (bool, is_ntfs)
IMPLEMENT_STATUS_FLAG (bool, is_samba)
@ -148,7 +140,7 @@ struct fs_info
IMPLEMENT_STATUS_FLAG (bool, is_netapp)
IMPLEMENT_STATUS_FLAG (bool, is_cdrom)
bool update (const char *);
bool update (PUNICODE_STRING, bool) __attribute__ ((regparm (3)));
};
class path_conv
@ -284,9 +276,7 @@ class path_conv
short get_unitn () const {return dev.minor;}
DWORD file_attributes () const {return fileattr;}
void file_attributes (DWORD new_attr) {fileattr = new_attr;}
DWORD drive_type () const {return fs.drive_type ();}
DWORD fs_flags () {return fs.flags ();}
bool fs_has_ea () const {return fs.has_ea ();}
bool fs_is_fat () const {return fs.is_fat ();}
bool fs_is_ntfs () const {return fs.is_ntfs ();}
bool fs_is_samba () const {return fs.is_samba ();}
@ -294,7 +284,6 @@ class path_conv
bool fs_is_netapp () const {return fs.is_netapp ();}
bool fs_is_cdrom () const {return fs.is_cdrom ();}
void set_path (const char *p) {strcpy (path, p);}
DWORD volser () { return fs.serial (); }
void fillin (HANDLE h);
inline size_t size ()
{