* security.h (NTWriteEA): Change prototype.
* ntea.cc (NTReadEA): Don't check for global ntea setting, now it's caller responsibility. (NTWriteEA): Ditto. * security.cc (get_file_attribute): Read attribute from EA only if 'ntea' is enabled. (set_file_attribute): Ditto. * path.h: (class path_conv): Add members to store file system information. (path_conv::get_drive_type): New function. * syscalls.cc (stat_worker): Use it. * path.cc (path_conv::update_fs_info): New functions. (path_conv::check): Get file system information from device where file resides. On NTFS, try to read symlink contents from EA. (get_symlink_ea): New function. (set_symlink_ea): Ditto. (symlink): Store symlink in extended attribute, if possible.
This commit is contained in:
parent
fa821be37b
commit
149da470f3
|
@ -1,3 +1,23 @@
|
||||||
|
2001-06-05 Egor Duda <deo@logos-m.ru>
|
||||||
|
|
||||||
|
* security.h (NTWriteEA): Change prototype.
|
||||||
|
* ntea.cc (NTReadEA): Don't check for global ntea setting, now
|
||||||
|
it's caller responsibility.
|
||||||
|
(NTWriteEA): Ditto.
|
||||||
|
* security.cc (get_file_attribute): Read attribute from EA only
|
||||||
|
if 'ntea' is enabled.
|
||||||
|
(set_file_attribute): Ditto.
|
||||||
|
* path.h: (class path_conv): Add members to store file system
|
||||||
|
information.
|
||||||
|
(path_conv::get_drive_type): New function.
|
||||||
|
* syscalls.cc (stat_worker): Use it.
|
||||||
|
* path.cc (path_conv::update_fs_info): New functions.
|
||||||
|
(path_conv::check): Get file system information from device where
|
||||||
|
file resides. On NTFS, try to read symlink contents from EA.
|
||||||
|
(get_symlink_ea): New function.
|
||||||
|
(set_symlink_ea): Ditto.
|
||||||
|
(symlink): Store symlink in extended attribute, if possible.
|
||||||
|
|
||||||
Tue Jun 5 11:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
Tue Jun 5 11:18:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* fhandler.cc (fhandler_disk_file::fstat): Always reset file position
|
* fhandler.cc (fhandler_disk_file::fstat): Always reset file position
|
||||||
|
|
|
@ -85,10 +85,6 @@ BOOL NTWriteEA(const char *file, const char *attrname, char *buf, int len);
|
||||||
int __stdcall
|
int __stdcall
|
||||||
NTReadEA (const char *file, const char *attrname, char *attrbuf, int len)
|
NTReadEA (const char *file, const char *attrname, char *attrbuf, int len)
|
||||||
{
|
{
|
||||||
/* return immediately if NTEA usage is turned off */
|
|
||||||
if (!allow_ntea)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
HANDLE hFileSource;
|
HANDLE hFileSource;
|
||||||
int eafound = 0;
|
int eafound = 0;
|
||||||
PFILE_FULL_EA_INFORMATION ea, sea;
|
PFILE_FULL_EA_INFORMATION ea, sea;
|
||||||
|
@ -254,12 +250,8 @@ NTReadEARaw (HANDLE hFileSource, int *len)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL __stdcall
|
BOOL __stdcall
|
||||||
NTWriteEA (const char *file, const char *attrname, char *buf, int len)
|
NTWriteEA (const char *file, const char *attrname, const char *buf, int len)
|
||||||
{
|
{
|
||||||
/* return immediately if NTEA usage is turned off */
|
|
||||||
if (!allow_ntea)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
HANDLE hFileSource;
|
HANDLE hFileSource;
|
||||||
WIN32_STREAM_ID StreamId;
|
WIN32_STREAM_ID StreamId;
|
||||||
DWORD dwBytesWritten;
|
DWORD dwBytesWritten;
|
||||||
|
|
|
@ -306,6 +306,52 @@ mkrelpath (char *path)
|
||||||
strcpy (path, ".");
|
strcpy (path, ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
path_conv::update_fs_info (const char* win32_path)
|
||||||
|
{
|
||||||
|
char tmp_buf [MAX_PATH];
|
||||||
|
strncpy (tmp_buf, win32_path, MAX_PATH);
|
||||||
|
|
||||||
|
if (!rootdir (tmp_buf) &&
|
||||||
|
(!GetCurrentDirectory (sizeof (tmp_buf), tmp_buf) <= sizeof (tmp_buf) ||
|
||||||
|
!rootdir (tmp_buf)))
|
||||||
|
{
|
||||||
|
debug_printf ("Cannot get root component of path %s", win32_path);
|
||||||
|
root_dir [0] = fs_name [0] = '\0';
|
||||||
|
fs_flags = fs_serial = 0;
|
||||||
|
sym_opt = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (tmp_buf, root_dir) != 0)
|
||||||
|
{
|
||||||
|
drive_type = GetDriveType (root_dir);
|
||||||
|
if (drive_type == DRIVE_REMOTE || (drive_type == DRIVE_UNKNOWN && (root_dir[0] == '\\' && root_dir[1] == '\\')))
|
||||||
|
is_remote_drive = 1;
|
||||||
|
else
|
||||||
|
is_remote_drive = 0;
|
||||||
|
|
||||||
|
strncpy (root_dir, tmp_buf, MAX_PATH);
|
||||||
|
if (!GetVolumeInformation (root_dir, NULL, 0, &fs_serial, NULL, &fs_flags,
|
||||||
|
fs_name, sizeof (fs_name)))
|
||||||
|
{
|
||||||
|
debug_printf ("Cannot get volume information (%s), %E", root_dir);
|
||||||
|
fs_name [0] = '\0';
|
||||||
|
fs_flags = fs_serial = 0;
|
||||||
|
sym_opt = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: Samba by default returns "NTFS" in file system name, but
|
||||||
|
* doesn't support Extended Attributes. If there's some fast way to
|
||||||
|
* distinguish between samba and real ntfs, it should be implemented
|
||||||
|
* here.
|
||||||
|
*/
|
||||||
|
sym_opt = (strcmp (fs_name, "NTFS") == 0 ? PC_CHECK_EA : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert an arbitrary path SRC to a pure Win32 path, suitable for
|
/* Convert an arbitrary path SRC to a pure Win32 path, suitable for
|
||||||
passing to Win32 API routines.
|
passing to Win32 API routines.
|
||||||
|
|
||||||
|
@ -350,7 +396,10 @@ path_conv::check (const char *src, unsigned opt,
|
||||||
fileattr = (DWORD) -1;
|
fileattr = (DWORD) -1;
|
||||||
case_clash = FALSE;
|
case_clash = FALSE;
|
||||||
devn = unit = 0;
|
devn = unit = 0;
|
||||||
vol_flags = 0;
|
root_dir[0] = '\0';
|
||||||
|
fs_name[0] = '\0';
|
||||||
|
fs_flags = fs_serial = 0;
|
||||||
|
sym_opt = 0;
|
||||||
drive_type = 0;
|
drive_type = 0;
|
||||||
is_remote_drive = 0;
|
is_remote_drive = 0;
|
||||||
|
|
||||||
|
@ -423,6 +472,8 @@ path_conv::check (const char *src, unsigned opt,
|
||||||
if (error)
|
if (error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
update_fs_info (full_path);
|
||||||
|
|
||||||
/* devn should not be a device. If it is, then stop parsing now. */
|
/* devn should not be a device. If it is, then stop parsing now. */
|
||||||
if (devn != FH_BAD)
|
if (devn != FH_BAD)
|
||||||
{
|
{
|
||||||
|
@ -451,7 +502,7 @@ path_conv::check (const char *src, unsigned opt,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = sym.check (full_path, suff, opt);
|
int len = sym.check (full_path, suff, opt | sym_opt );
|
||||||
|
|
||||||
if (sym.case_clash)
|
if (sym.case_clash)
|
||||||
{
|
{
|
||||||
|
@ -616,31 +667,21 @@ out:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char fs_name[16];
|
update_fs_info (path);
|
||||||
|
if (!fs_name[0])
|
||||||
strcpy (tmp_buf, this->path);
|
|
||||||
|
|
||||||
if (!rootdir (tmp_buf) ||
|
|
||||||
!GetVolumeInformation (tmp_buf, NULL, 0, &vol_serial, NULL,
|
|
||||||
&vol_flags, fs_name, 16))
|
|
||||||
{
|
{
|
||||||
debug_printf ("GetVolumeInformation(%s) = ERR, this->path(%s), set_has_acls(FALSE)",
|
|
||||||
tmp_buf, this->path, GetLastError ());
|
|
||||||
set_has_acls (FALSE);
|
set_has_acls (FALSE);
|
||||||
set_has_buggy_open (FALSE);
|
set_has_buggy_open (FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_isdisk ();
|
set_isdisk ();
|
||||||
debug_printf ("GetVolumeInformation(%s) = OK, this->path(%s), set_has_acls(%d)",
|
debug_printf ("root_dir(%s), this->path(%s), set_has_acls(%d)",
|
||||||
tmp_buf, this->path, vol_flags & FS_PERSISTENT_ACLS);
|
root_dir, this->path, fs_flags & FS_PERSISTENT_ACLS);
|
||||||
drive_type = GetDriveType (tmp_buf);
|
|
||||||
if (drive_type == DRIVE_REMOTE || (drive_type == DRIVE_UNKNOWN && (tmp_buf[0] == '\\' && tmp_buf[1] == '\\')))
|
|
||||||
is_remote_drive = 1;
|
|
||||||
if (!allow_smbntsec && is_remote_drive)
|
if (!allow_smbntsec && is_remote_drive)
|
||||||
set_has_acls (FALSE);
|
set_has_acls (FALSE);
|
||||||
else
|
else
|
||||||
set_has_acls (vol_flags & FS_PERSISTENT_ACLS);
|
set_has_acls (fs_flags & FS_PERSISTENT_ACLS);
|
||||||
/* Known file systems with buggy open calls. Further explanation
|
/* Known file systems with buggy open calls. Further explanation
|
||||||
in fhandler.cc (fhandler_disk_file::open). */
|
in fhandler.cc (fhandler_disk_file::open). */
|
||||||
set_has_buggy_open (strcmp (fs_name, "SUNWNFS") == 0);
|
set_has_buggy_open (strcmp (fs_name, "SUNWNFS") == 0);
|
||||||
|
@ -2316,6 +2357,28 @@ endmntent (FILE *)
|
||||||
|
|
||||||
/********************** Symbolic Link Support **************************/
|
/********************** Symbolic Link Support **************************/
|
||||||
|
|
||||||
|
/* Read symlink from Extended Attribute */
|
||||||
|
int
|
||||||
|
get_symlink_ea (const char* frompath, char* buf, int buf_size)
|
||||||
|
{
|
||||||
|
int res = NTReadEA (frompath, SYMLINK_EA_NAME, buf, buf_size);
|
||||||
|
if (res == 0)
|
||||||
|
debug_printf ("Cannot read symlink from EA");
|
||||||
|
return (res - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save symlink to Extended Attribute */
|
||||||
|
BOOL
|
||||||
|
set_symlink_ea (const char* frompath, const char* topath)
|
||||||
|
{
|
||||||
|
if (!NTWriteEA (frompath, SYMLINK_EA_NAME, topath, strlen (topath) + 1))
|
||||||
|
{
|
||||||
|
debug_printf ("Cannot save symlink in EA");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a symlink from FROMPATH to TOPATH. */
|
/* Create a symlink from FROMPATH to TOPATH. */
|
||||||
|
|
||||||
/* If TRUE create symlinks as Windows shortcuts, if FALSE create symlinks
|
/* If TRUE create symlinks as Windows shortcuts, if FALSE create symlinks
|
||||||
|
@ -2441,8 +2504,10 @@ symlink (const char *topath, const char *frompath)
|
||||||
win32_path.get_win32 (),
|
win32_path.get_win32 (),
|
||||||
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
SetFileAttributesA (win32_path.get_win32 (),
|
SetFileAttributesA (win32_path.get_win32 (),
|
||||||
allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
|
allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
|
||||||
: FILE_ATTRIBUTE_SYSTEM);
|
: FILE_ATTRIBUTE_SYSTEM);
|
||||||
|
if (win32_path.fs_fast_ea ())
|
||||||
|
set_symlink_ea (win32_path, topath);
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2706,6 +2771,14 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
||||||
if (!sym_check)
|
if (!sym_check)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
|
if (sym_check > 0 && opt & PC_CHECK_EA &&
|
||||||
|
(res = get_symlink_ea (suffix.path, contents, sizeof (contents))) > 0)
|
||||||
|
{
|
||||||
|
pflags = PATH_SYMLINK;
|
||||||
|
debug_printf ("Got symlink from EA: %s", contents);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. */
|
||||||
|
|
||||||
h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING,
|
h = CreateFileA (suffix.path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING,
|
||||||
|
@ -2714,6 +2787,9 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
|
/* FIXME: if symlink isn't present in EA, but EAs are supported,
|
||||||
|
* should we write it there?
|
||||||
|
*/
|
||||||
switch (sym_check)
|
switch (sym_check)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -22,7 +22,8 @@ enum pathconv_arg
|
||||||
PC_SYM_IGNORE = 0x0004,
|
PC_SYM_IGNORE = 0x0004,
|
||||||
PC_SYM_CONTENTS = 0x0008,
|
PC_SYM_CONTENTS = 0x0008,
|
||||||
PC_FULL = 0x0010,
|
PC_FULL = 0x0010,
|
||||||
PC_NULLEMPTY = 0x0020
|
PC_NULLEMPTY = 0x0020,
|
||||||
|
PC_CHECK_EA = 0x0040
|
||||||
};
|
};
|
||||||
|
|
||||||
enum case_checking
|
enum case_checking
|
||||||
|
@ -56,14 +57,18 @@ class symlink_info;
|
||||||
class path_conv
|
class path_conv
|
||||||
{
|
{
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
|
char root_dir[MAX_PATH];
|
||||||
|
char fs_name[MAX_PATH];
|
||||||
|
DWORD fs_flags;
|
||||||
|
DWORD fs_serial;
|
||||||
|
DWORD sym_opt; /* additional options to pass to symlink_info resolver */
|
||||||
void add_ext_from_sym (symlink_info&);
|
void add_ext_from_sym (symlink_info&);
|
||||||
|
void update_fs_info (const char*);
|
||||||
|
DWORD drive_type;
|
||||||
bool is_remote_drive;
|
bool is_remote_drive;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
unsigned path_flags;
|
unsigned path_flags;
|
||||||
DWORD vol_flags;
|
|
||||||
DWORD drive_type;
|
|
||||||
DWORD vol_serial;
|
|
||||||
|
|
||||||
int isdisk () const { return path_flags & PATH_ISDISK;}
|
int isdisk () const { return path_flags & PATH_ISDISK;}
|
||||||
int isremote () const {return is_remote_drive;}
|
int isremote () const {return is_remote_drive;}
|
||||||
|
@ -128,11 +133,15 @@ class path_conv
|
||||||
DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;}
|
DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;}
|
||||||
short get_unitn () {return devn == FH_BAD ? 0 : unit;}
|
short get_unitn () {return devn == FH_BAD ? 0 : unit;}
|
||||||
DWORD file_attributes () {return fileattr;}
|
DWORD file_attributes () {return fileattr;}
|
||||||
|
DWORD get_drive_type () {return drive_type;}
|
||||||
|
BOOL fs_fast_ea () {return sym_opt & PC_CHECK_EA;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Symlink marker */
|
/* Symlink marker */
|
||||||
#define SYMLINK_COOKIE "!<symlink>"
|
#define SYMLINK_COOKIE "!<symlink>"
|
||||||
|
|
||||||
|
#define SYMLINK_EA_NAME ".CYGSYMLINK"
|
||||||
|
|
||||||
/* Socket marker */
|
/* Socket marker */
|
||||||
#define SOCKET_COOKIE "!<socket >"
|
#define SOCKET_COOKIE "!<socket >"
|
||||||
|
|
||||||
|
|
|
@ -1199,9 +1199,14 @@ get_file_attribute (int use_ntsec, const char *file,
|
||||||
if (!attribute)
|
if (!attribute)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int oatt = *attribute;
|
if (allow_ntea)
|
||||||
res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
|
{
|
||||||
*attribute |= oatt;
|
int oatt = *attribute;
|
||||||
|
res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
|
||||||
|
*attribute |= oatt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = 0;
|
||||||
|
|
||||||
/* symlinks are everything for everyone!*/
|
/* symlinks are everything for everyone!*/
|
||||||
if ((*attribute & S_IFLNK) == S_IFLNK)
|
if ((*attribute & S_IFLNK) == S_IFLNK)
|
||||||
|
@ -1523,7 +1528,7 @@ set_file_attribute (int use_ntsec, const char *file,
|
||||||
if ((attribute & S_IFLNK) == S_IFLNK)
|
if ((attribute & S_IFLNK) == S_IFLNK)
|
||||||
attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
|
attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
|
||||||
|
|
||||||
if (!use_ntsec || !allow_ntsec)
|
if (allow_ntea && (!use_ntsec || !allow_ntsec))
|
||||||
{
|
{
|
||||||
if (!NTWriteEA (file, ".UNIXATTR", (char *) &attribute,
|
if (!NTWriteEA (file, ".UNIXATTR", (char *) &attribute,
|
||||||
sizeof (attribute)))
|
sizeof (attribute)))
|
||||||
|
|
|
@ -198,4 +198,4 @@ extern SECURITY_ATTRIBUTES *__stdcall sec_user (PVOID sa_buf, PSID sid2 = NULL,
|
||||||
extern SECURITY_ATTRIBUTES *__stdcall sec_user_nih (PVOID sa_buf, PSID sid2 = NULL);
|
extern SECURITY_ATTRIBUTES *__stdcall sec_user_nih (PVOID sa_buf, PSID sid2 = NULL);
|
||||||
|
|
||||||
int __stdcall NTReadEA (const char *file, const char *attrname, char *buf, int len);
|
int __stdcall NTReadEA (const char *file, const char *attrname, char *buf, int len);
|
||||||
BOOL __stdcall NTWriteEA (const char *file, const char *attrname, char *buf, int len);
|
BOOL __stdcall NTWriteEA (const char *file, const char *attrname, const char *buf, int len);
|
||||||
|
|
|
@ -1040,7 +1040,7 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
|
||||||
|
|
||||||
debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ());
|
debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ());
|
||||||
|
|
||||||
dtype = real_path.drive_type;
|
dtype = real_path.get_drive_type ();
|
||||||
|
|
||||||
if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) ||
|
if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) ||
|
||||||
(os_being_run == winNT
|
(os_being_run == winNT
|
||||||
|
|
Loading…
Reference in New Issue