Index: ntea.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/ntea.cc,v retrieving revision 1.3 diff -u -p -2 -r1.3 ntea.cc --- ntea.cc 2000/09/08 02:56:54 1.3 +++ ntea.cc 2001/05/14 13:51:11 @@ -86,8 +86,4 @@ 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; @@ -255,10 +251,6 @@ NTReadEARaw (HANDLE hFileSource, int *le 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; Index: path.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/path.cc,v retrieving revision 1.139 diff -u -p -2 -r1.139 path.cc --- path.cc 2001/05/14 02:52:12 1.139 +++ path.cc 2001/05/14 13:51:12 @@ -331,4 +331,44 @@ mkrelpath (char *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) + { + 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 any 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. @@ -375,4 +415,8 @@ path_conv::check (const char *src, unsig case_clash = FALSE; devn = unit = 0; + root_dir[0] = '\0'; + fs_name[0] = '\0'; + fs_flags = fs_serial = 0; + sym_opt = 0; if (!(opt & PC_NULLEMPTY)) @@ -442,4 +486,6 @@ path_conv::check (const char *src, unsig unit, &sym.pflags); + update_fs_info (full_path); + /* devn should not be a device. If it is, then stop parsing now. */ if (devn != FH_BAD) @@ -470,5 +516,5 @@ path_conv::check (const char *src, unsig } - int len = sym.check (full_path, suff, opt); + int len = sym.check (full_path, suff, opt | sym_opt ); if (sym.case_clash) @@ -634,16 +680,8 @@ out: return; } - - DWORD serial, volflags; - char fs_name[16]; - strcpy (tmp_buf, this->path); - - if (!rootdir (tmp_buf) || - !GetVolumeInformation (tmp_buf, NULL, 0, &serial, NULL, - &volflags, 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); @@ -652,12 +690,12 @@ out: { set_isdisk (); - debug_printf ("GetVolumeInformation(%s) = OK, this->path(%s), set_has_acls(%d)", - tmp_buf, this->path, volflags & FS_PERSISTENT_ACLS); + debug_printf ("root_dir(%s), this->path(%s), set_has_acls(%d)", + root_dir, this->path, fs_flags & FS_PERSISTENT_ACLS); if (!allow_smbntsec - && ((tmp_buf[0] == '\\' && tmp_buf[1] == '\\') - || GetDriveType (tmp_buf) == DRIVE_REMOTE)) + && ((root_dir[0] == '\\' && root_dir[1] == '\\') + || GetDriveType (root_dir) == DRIVE_REMOTE)) set_has_acls (FALSE); else - set_has_acls (volflags & 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). */ @@ -2319,4 +2357,26 @@ 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. */ @@ -2423,4 +2483,6 @@ symlink (const char *topath, const char && WriteFile (h, w32topath, win_len, &written, NULL) && written == win_len; + if (win32_path.fs_fast_ea ()) + set_symlink_ea (win32_path, topath); } else @@ -2706,4 +2768,12 @@ symlink_info::check (char *path, const s 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); + goto out; + } + /* Open the file. */ @@ -2714,4 +2784,7 @@ symlink_info::check (char *path, const s goto file_not_symlink; + /* FIXME: if symlink isn't present in EA, but EAs are supported, + * should we write it there? + */ switch (sym_check) { Index: path.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/path.h,v retrieving revision 1.26 diff -u -p -2 -r1.26 path.h --- path.h 2001/04/17 23:12:11 1.26 +++ path.h 2001/05/14 13:51:12 @@ -23,5 +23,6 @@ enum pathconv_arg PC_SYM_CONTENTS = 0x0008, PC_FULL = 0x0010, - PC_NULLEMPTY = 0x0020 + PC_NULLEMPTY = 0x0020, + PC_CHECK_EA = 0x0040 }; @@ -57,5 +58,11 @@ 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*); public: @@ -124,8 +131,11 @@ class path_conv short get_unitn () {return devn == FH_BAD ? 0 : unit;} DWORD file_attributes () {return fileattr;} + BOOL fs_fast_ea () {return sym_opt & PC_CHECK_EA;} }; /* Symlink marker */ #define SYMLINK_COOKIE "!" + +#define SYMLINK_EA_NAME ".CYGSYMLINK" /* Socket marker */ Index: security.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/security.cc,v retrieving revision 1.46 diff -u -p -2 -r1.46 security.cc --- security.cc 2001/04/30 21:19:42 1.46 +++ security.cc 2001/05/14 13:51:12 @@ -545,5 +545,8 @@ get_file_attribute (int use_ntsec, const return 0; - res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute)); + if (allow_ntea) + res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute)); + else + res = 0; /* symlinks are everything for everyone!*/ @@ -869,5 +872,5 @@ set_file_attribute (int use_ntsec, const attribute |= S_IRWXU | S_IRWXG | S_IRWXO; - if (!use_ntsec || !allow_ntsec) + if (allow_ntea && (!use_ntsec || !allow_ntsec)) { if (!NTWriteEA (file, ".UNIXATTR", Index: security.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/security.h,v retrieving revision 1.7 diff -u -p -2 -r1.7 security.h --- security.h 2001/04/30 21:19:42 1.7 +++ security.h 2001/05/14 13:51:12 @@ -103,3 +103,3 @@ extern SECURITY_ATTRIBUTES *__stdcall se 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);