* 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:
parent
58402a3f63
commit
5829832825
|
@ -1,3 +1,16 @@
|
|||
2008-12-25 Christopher Faylor <me+cygwin@cgf.cx>
|
||||
|
||||
* 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.
|
||||
|
||||
2008-12-24 Christopher Faylor <me+cygwin@cgf.cx>
|
||||
|
||||
* path.cc (symlink_info::check_shortcut): Ensure that symlink handle is
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* path.cc: path support.
|
||||
/* mount.cc: mount handling.
|
||||
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006, 2007, 2008 Red Hat, Inc.
|
||||
|
@ -13,6 +13,7 @@ details. */
|
|||
#include "miscfuncs.h"
|
||||
#include <mntent.h>
|
||||
#include <ctype.h>
|
||||
#include <winioctl.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <winnetwk.h>
|
||||
|
@ -21,10 +22,10 @@ details. */
|
|||
#include "cygerrno.h"
|
||||
#include "security.h"
|
||||
#include "path.h"
|
||||
#include "shared_info.h"
|
||||
#include "fhandler.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "shared_info.h"
|
||||
#include "cygtls.h"
|
||||
#include "tls_pbuf.h"
|
||||
#include <ntdll.h>
|
||||
|
@ -82,6 +83,201 @@ win32_device_name (const char *src_path, char *win32_path, device& dev)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
inline void
|
||||
mount_info::create_root_entry (const PWCHAR root)
|
||||
{
|
||||
|
@ -1122,7 +1318,6 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
|
|||
table because the mount table might change, causing weird effects
|
||||
from the getmntent user's point of view. */
|
||||
|
||||
slashify (native_path, _my_tls.locals.mnt_fsname, false);
|
||||
ret.mnt_fsname = _my_tls.locals.mnt_fsname;
|
||||
strcpy (_my_tls.locals.mnt_dir, posix_path);
|
||||
ret.mnt_dir = _my_tls.locals.mnt_dir;
|
||||
|
@ -1135,7 +1330,7 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
|
|||
tmp_pathbuf tp;
|
||||
UNICODE_STRING unat;
|
||||
tp.u_get (&unat);
|
||||
get_nt_native_path (_my_tls.locals.mnt_fsname, unat);
|
||||
get_nt_native_path (native_path, unat);
|
||||
if (append_bs)
|
||||
RtlAppendUnicodeToString (&unat, L"\\");
|
||||
mntinfo.update (&unat, NULL);
|
||||
|
@ -1157,6 +1352,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
|
|||
|
||||
ret.mnt_type = _my_tls.locals.mnt_type;
|
||||
|
||||
slashify (native_path, _my_tls.locals.mnt_fsname, false);
|
||||
|
||||
/* mnt_opts is a string that details mount params such as
|
||||
binary or textmode, or exec. We don't print
|
||||
`silent' here; it's a magic internal thing. */
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
/* mount.h: mount definitions.
|
||||
|
||||
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006, 2007, 2008 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
This software is a copyrighted work licensed under the terms of the
|
||||
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#ifndef _MOUNT_H
|
||||
#define _MOUNT_H
|
||||
|
||||
class fs_info
|
||||
{
|
||||
struct status_flags
|
||||
{
|
||||
ULONG flags; /* Volume flags */
|
||||
ULONG samba_version; /* Samba version if available */
|
||||
ULONG name_len; /* MaximumComponentNameLength */
|
||||
unsigned is_remote_drive : 1;
|
||||
unsigned has_buggy_open : 1;
|
||||
unsigned has_buggy_fileid_dirinfo : 1;
|
||||
unsigned has_acls : 1;
|
||||
unsigned hasgood_inode : 1;
|
||||
unsigned caseinsensitive : 1;
|
||||
unsigned is_fat : 1;
|
||||
unsigned is_ntfs : 1;
|
||||
unsigned is_samba : 1;
|
||||
unsigned is_nfs : 1;
|
||||
unsigned is_netapp : 1;
|
||||
unsigned is_cdrom : 1;
|
||||
} status;
|
||||
ULONG sernum;
|
||||
public:
|
||||
void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; }
|
||||
fs_info () { clear (); }
|
||||
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, flags)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, samba_version)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, name_len)
|
||||
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo)
|
||||
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)
|
||||
ULONG serial_number () const { return sernum; }
|
||||
|
||||
bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3)));
|
||||
};
|
||||
|
||||
/* Mount table entry */
|
||||
|
||||
class mount_item
|
||||
{
|
||||
public:
|
||||
/* FIXME: Nasty static allocation. Need to have a heap in the shared
|
||||
area [with the user being able to configure at runtime the max size]. */
|
||||
/* Win32-style mounted partition source ("C:\foo\bar").
|
||||
native_path[0] == 0 for unused entries. */
|
||||
char native_path[CYG_MAX_PATH];
|
||||
int native_pathlen;
|
||||
|
||||
/* POSIX-style mount point ("/foo/bar") */
|
||||
char posix_path[CYG_MAX_PATH];
|
||||
int posix_pathlen;
|
||||
|
||||
unsigned flags;
|
||||
|
||||
void init (const char *dev, const char *path, unsigned flags);
|
||||
|
||||
struct mntent *getmntent ();
|
||||
int build_win32 (char *, const char *, unsigned *, unsigned);
|
||||
};
|
||||
|
||||
/* Warning: Decreasing this value will cause cygwin.dll to ignore existing
|
||||
higher numbered registry entries. Don't change this number willy-nilly.
|
||||
What we need is to have a more dynamic allocation scheme, but the current
|
||||
scheme should be satisfactory for a long while yet. */
|
||||
#define MAX_MOUNTS 30
|
||||
|
||||
#define USER_VERSION 1 // increment when mount table changes and
|
||||
#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION)
|
||||
#define CURR_USER_MAGIC 0xb2232e71U
|
||||
|
||||
class reg_key;
|
||||
struct device;
|
||||
|
||||
/* NOTE: Do not make gratuitous changes to the names or organization of the
|
||||
below class. The layout is checksummed to determine compatibility between
|
||||
different cygwin versions. */
|
||||
class mount_info
|
||||
{
|
||||
public:
|
||||
DWORD sys_mount_table_counter;
|
||||
int nmounts;
|
||||
mount_item mount[MAX_MOUNTS];
|
||||
|
||||
/* cygdrive_prefix is used as the root of the path automatically
|
||||
prepended to a path when the path has no associated mount.
|
||||
cygdrive_flags are the default flags for the cygdrives. */
|
||||
char cygdrive[CYG_MAX_PATH];
|
||||
size_t cygdrive_len;
|
||||
unsigned cygdrive_flags;
|
||||
private:
|
||||
int posix_sorted[MAX_MOUNTS];
|
||||
int native_sorted[MAX_MOUNTS];
|
||||
|
||||
public:
|
||||
void init ();
|
||||
int add_item (const char *dev, const char *path, unsigned flags);
|
||||
int del_item (const char *path, unsigned flags);
|
||||
|
||||
unsigned set_flags_from_win32_path (const char *path);
|
||||
int conv_to_win32_path (const char *src_path, char *dst, device&,
|
||||
unsigned *flags = NULL);
|
||||
int conv_to_posix_path (PWCHAR src_path, char *posix_path,
|
||||
int keep_rel_p);
|
||||
int conv_to_posix_path (const char *src_path, char *posix_path,
|
||||
int keep_rel_p);
|
||||
struct mntent *getmntent (int x);
|
||||
|
||||
int write_cygdrive_info (const char *cygdrive_prefix, unsigned flags);
|
||||
int get_cygdrive_info (char *user, char *system, char* user_flags,
|
||||
char* system_flags);
|
||||
void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p);
|
||||
int get_mounts_here (const char *parent_dir, int,
|
||||
PUNICODE_STRING mount_points,
|
||||
PUNICODE_STRING cygd);
|
||||
|
||||
private:
|
||||
void sort ();
|
||||
void mount_slash ();
|
||||
void create_root_entry (const PWCHAR root);
|
||||
|
||||
bool from_fstab_line (char *line, bool user);
|
||||
bool from_fstab (bool user, WCHAR [], PWCHAR);
|
||||
|
||||
int cygdrive_win32_path (const char *src, char *dst, int& unit);
|
||||
};
|
||||
#endif
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|||
details. */
|
||||
|
||||
#include "devices.h"
|
||||
#include "mount.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -83,51 +84,6 @@ enum path_types
|
|||
};
|
||||
|
||||
class symlink_info;
|
||||
struct fs_info
|
||||
{
|
||||
private:
|
||||
struct status_flags
|
||||
{
|
||||
ULONG flags; /* Volume flags */
|
||||
ULONG samba_version; /* Samba version if available */
|
||||
ULONG name_len; /* MaximumComponentNameLength */
|
||||
unsigned is_remote_drive : 1;
|
||||
unsigned has_buggy_open : 1;
|
||||
unsigned has_buggy_fileid_dirinfo : 1;
|
||||
unsigned has_acls : 1;
|
||||
unsigned hasgood_inode : 1;
|
||||
unsigned caseinsensitive : 1;
|
||||
unsigned is_fat : 1;
|
||||
unsigned is_ntfs : 1;
|
||||
unsigned is_samba : 1;
|
||||
unsigned is_nfs : 1;
|
||||
unsigned is_netapp : 1;
|
||||
unsigned is_cdrom : 1;
|
||||
} status;
|
||||
ULONG sernum;
|
||||
public:
|
||||
void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; }
|
||||
fs_info () { clear (); }
|
||||
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, flags)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, samba_version)
|
||||
IMPLEMENT_STATUS_FLAG (ULONG, name_len)
|
||||
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
|
||||
IMPLEMENT_STATUS_FLAG (bool, has_buggy_fileid_dirinfo)
|
||||
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)
|
||||
ULONG serial_number () const { return sernum; }
|
||||
|
||||
bool update (PUNICODE_STRING, HANDLE) __attribute__ ((regparm (3)));
|
||||
};
|
||||
|
||||
class path_conv
|
||||
{
|
||||
|
|
|
@ -12,96 +12,7 @@ details. */
|
|||
#include "security.h"
|
||||
#include "mtinfo.h"
|
||||
#include "limits.h"
|
||||
|
||||
/* Mount table entry */
|
||||
|
||||
class mount_item
|
||||
{
|
||||
public:
|
||||
/* FIXME: Nasty static allocation. Need to have a heap in the shared
|
||||
area [with the user being able to configure at runtime the max size]. */
|
||||
/* Win32-style mounted partition source ("C:\foo\bar").
|
||||
native_path[0] == 0 for unused entries. */
|
||||
char native_path[CYG_MAX_PATH];
|
||||
int native_pathlen;
|
||||
|
||||
/* POSIX-style mount point ("/foo/bar") */
|
||||
char posix_path[CYG_MAX_PATH];
|
||||
int posix_pathlen;
|
||||
|
||||
unsigned flags;
|
||||
|
||||
void init (const char *dev, const char *path, unsigned flags);
|
||||
|
||||
struct mntent *getmntent ();
|
||||
int build_win32 (char *, const char *, unsigned *, unsigned);
|
||||
};
|
||||
|
||||
/* Warning: Decreasing this value will cause cygwin.dll to ignore existing
|
||||
higher numbered registry entries. Don't change this number willy-nilly.
|
||||
What we need is to have a more dynamic allocation scheme, but the current
|
||||
scheme should be satisfactory for a long while yet. */
|
||||
#define MAX_MOUNTS 30
|
||||
|
||||
#define USER_VERSION 1 // increment when mount table changes and
|
||||
#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION)
|
||||
#define CURR_USER_MAGIC 0xb2232e71U
|
||||
|
||||
class reg_key;
|
||||
struct device;
|
||||
|
||||
/* NOTE: Do not make gratuitous changes to the names or organization of the
|
||||
below class. The layout is checksummed to determine compatibility between
|
||||
different cygwin versions. */
|
||||
class mount_info
|
||||
{
|
||||
public:
|
||||
DWORD sys_mount_table_counter;
|
||||
int nmounts;
|
||||
mount_item mount[MAX_MOUNTS];
|
||||
|
||||
/* cygdrive_prefix is used as the root of the path automatically
|
||||
prepended to a path when the path has no associated mount.
|
||||
cygdrive_flags are the default flags for the cygdrives. */
|
||||
char cygdrive[CYG_MAX_PATH];
|
||||
size_t cygdrive_len;
|
||||
unsigned cygdrive_flags;
|
||||
private:
|
||||
int posix_sorted[MAX_MOUNTS];
|
||||
int native_sorted[MAX_MOUNTS];
|
||||
|
||||
public:
|
||||
void init ();
|
||||
int add_item (const char *dev, const char *path, unsigned flags);
|
||||
int del_item (const char *path, unsigned flags);
|
||||
|
||||
unsigned set_flags_from_win32_path (const char *path);
|
||||
int conv_to_win32_path (const char *src_path, char *dst, device&,
|
||||
unsigned *flags = NULL);
|
||||
int conv_to_posix_path (PWCHAR src_path, char *posix_path,
|
||||
int keep_rel_p);
|
||||
int conv_to_posix_path (const char *src_path, char *posix_path,
|
||||
int keep_rel_p);
|
||||
struct mntent *getmntent (int x);
|
||||
|
||||
int write_cygdrive_info (const char *cygdrive_prefix, unsigned flags);
|
||||
int get_cygdrive_info (char *user, char *system, char* user_flags,
|
||||
char* system_flags);
|
||||
void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p);
|
||||
int get_mounts_here (const char *parent_dir, int,
|
||||
PUNICODE_STRING mount_points,
|
||||
PUNICODE_STRING cygd);
|
||||
|
||||
private:
|
||||
void sort ();
|
||||
void mount_slash ();
|
||||
void create_root_entry (const PWCHAR root);
|
||||
|
||||
bool from_fstab_line (char *line, bool user);
|
||||
bool from_fstab (bool user, WCHAR [], PWCHAR);
|
||||
|
||||
int cygdrive_win32_path (const char *src, char *dst, int& unit);
|
||||
};
|
||||
#include "mount.h"
|
||||
|
||||
class user_info
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue