* 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:
@ -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");
|
||||
|
Reference in New Issue
Block a user