Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/ntea.cc10
-rw-r--r--winsup/cygwin/path.cc114
-rw-r--r--winsup/cygwin/path.h17
-rw-r--r--winsup/cygwin/security.cc13
-rw-r--r--winsup/cygwin/security.h2
-rw-r--r--winsup/cygwin/syscalls.cc2
7 files changed, 140 insertions, 38 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3e15d5ee8..0a3a2082b 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* fhandler.cc (fhandler_disk_file::fstat): Always reset file position
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
index 85cc4187f..1d5c77cd4 100644
--- a/winsup/cygwin/ntea.cc
+++ b/winsup/cygwin/ntea.cc
@@ -85,10 +85,6 @@ BOOL NTWriteEA(const char *file, const char *attrname, char *buf, int len);
int __stdcall
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;
int eafound = 0;
PFILE_FULL_EA_INFORMATION ea, sea;
@@ -254,12 +250,8 @@ NTReadEARaw (HANDLE hFileSource, int *len)
*/
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;
WIN32_STREAM_ID StreamId;
DWORD dwBytesWritten;
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4f40db818..76a009854 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -306,6 +306,52 @@ mkrelpath (char *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
passing to Win32 API routines.
@@ -350,7 +396,10 @@ path_conv::check (const char *src, unsigned opt,
fileattr = (DWORD) -1;
case_clash = FALSE;
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;
is_remote_drive = 0;
@@ -423,6 +472,8 @@ path_conv::check (const char *src, unsigned opt,
if (error)
return;
+ update_fs_info (full_path);
+
/* devn should not be a device. If it is, then stop parsing now. */
if (devn != FH_BAD)
{
@@ -451,7 +502,7 @@ path_conv::check (const char *src, unsigned opt,
goto out;
}
- int len = sym.check (full_path, suff, opt);
+ int len = sym.check (full_path, suff, opt | sym_opt );
if (sym.case_clash)
{
@@ -616,31 +667,21 @@ out:
return;
}
- char fs_name[16];
-
- strcpy (tmp_buf, this->path);
-
- if (!rootdir (tmp_buf) ||
- !GetVolumeInformation (tmp_buf, NULL, 0, &vol_serial, NULL,
- &vol_flags, fs_name, 16))
+ update_fs_info (path);
+ if (!fs_name[0])
{
- debug_printf ("GetVolumeInformation(%s) = ERR, this->path(%s), set_has_acls(FALSE)",
- tmp_buf, this->path, GetLastError ());
set_has_acls (FALSE);
set_has_buggy_open (FALSE);
}
else
{
set_isdisk ();
- debug_printf ("GetVolumeInformation(%s) = OK, this->path(%s), set_has_acls(%d)",
- tmp_buf, this->path, vol_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;
+ debug_printf ("root_dir(%s), this->path(%s), set_has_acls(%d)",
+ root_dir, this->path, fs_flags & FS_PERSISTENT_ACLS);
if (!allow_smbntsec && is_remote_drive)
set_has_acls (FALSE);
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
in fhandler.cc (fhandler_disk_file::open). */
set_has_buggy_open (strcmp (fs_name, "SUNWNFS") == 0);
@@ -2316,6 +2357,28 @@ endmntent (FILE *)
/********************** 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. */
/* 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 (),
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
SetFileAttributesA (win32_path.get_win32 (),
- allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
- : FILE_ATTRIBUTE_SYSTEM);
+ allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
+ : FILE_ATTRIBUTE_SYSTEM);
+ if (win32_path.fs_fast_ea ())
+ set_symlink_ea (win32_path, topath);
res = 0;
}
else
@@ -2706,6 +2771,14 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
if (!sym_check)
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. */
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)
goto file_not_symlink;
+ /* FIXME: if symlink isn't present in EA, but EAs are supported,
+ * should we write it there?
+ */
switch (sym_check)
{
case 1:
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index 9bc36c01c..b72a20c14 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -22,7 +22,8 @@ enum pathconv_arg
PC_SYM_IGNORE = 0x0004,
PC_SYM_CONTENTS = 0x0008,
PC_FULL = 0x0010,
- PC_NULLEMPTY = 0x0020
+ PC_NULLEMPTY = 0x0020,
+ PC_CHECK_EA = 0x0040
};
enum case_checking
@@ -56,14 +57,18 @@ class symlink_info;
class path_conv
{
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 update_fs_info (const char*);
+ DWORD drive_type;
bool is_remote_drive;
public:
unsigned path_flags;
- DWORD vol_flags;
- DWORD drive_type;
- DWORD vol_serial;
int isdisk () const { return path_flags & PATH_ISDISK;}
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;}
short get_unitn () {return devn == FH_BAD ? 0 : unit;}
DWORD file_attributes () {return fileattr;}
+ DWORD get_drive_type () {return drive_type;}
+ BOOL fs_fast_ea () {return sym_opt & PC_CHECK_EA;}
};
/* Symlink marker */
#define SYMLINK_COOKIE "!<symlink>"
+#define SYMLINK_EA_NAME ".CYGSYMLINK"
+
/* Socket marker */
#define SOCKET_COOKIE "!<socket >"
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 82f1dd8e6..155b0d934 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -1199,9 +1199,14 @@ get_file_attribute (int use_ntsec, const char *file,
if (!attribute)
return 0;
- int oatt = *attribute;
- res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
- *attribute |= oatt;
+ if (allow_ntea)
+ {
+ int oatt = *attribute;
+ res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
+ *attribute |= oatt;
+ }
+ else
+ res = 0;
/* symlinks are everything for everyone!*/
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)
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,
sizeof (attribute)))
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index ef39fabd6..f307ac013 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -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);
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);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index f4fcb464c..788adc1e8 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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 ());
- dtype = real_path.drive_type;
+ dtype = real_path.get_drive_type ();
if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) ||
(os_being_run == winNT