From 33cb946e7ee09ba7725b383e55bbdc1ca441e62f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 23 May 2013 14:23:01 +0000 Subject: [PATCH] * environ.cc (set_winsymlinks): Handle "winsymlinks:nativestrict" option. On pre-Vista warn the user if the "winsymlinks:native*" option is set. * globals.cc (enum winsym_t): Add WSYM_nativestrict. * path.cc (symlink_native): Don't create native symlink if target does not exist. Explain why. Improve comments. (symlink_worker): Change AFS symlink handling to WSYM_nativestrict. Handle WSYM_nativestrict throughout. Change condition for bail out to wsym_type == WSYM_nativestrict. Add comment. Fix formatting. * shared_info.h (CURR_USER_MAGIC): Change to reflect change in class user_info. (class user_info): Add member warned_nonativesyms. --- winsup/cygwin/ChangeLog | 15 +++++++++++++++ winsup/cygwin/environ.cc | 19 ++++++++++++++++--- winsup/cygwin/globals.cc | 1 + winsup/cygwin/path.cc | 27 +++++++++++++++++++++------ winsup/cygwin/shared_info.h | 3 ++- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ff3a31f8f..e91432d3e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2013-05-23 Corinna Vinschen + + * environ.cc (set_winsymlinks): Handle "winsymlinks:nativestrict" + option. On pre-Vista warn the user if the "winsymlinks:native*" option + is set. + * globals.cc (enum winsym_t): Add WSYM_nativestrict. + * path.cc (symlink_native): Don't create native symlink if target + does not exist. Explain why. Improve comments. + (symlink_worker): Change AFS symlink handling to WSYM_nativestrict. + Handle WSYM_nativestrict throughout. Change condition for bail out + to wsym_type == WSYM_nativestrict. Add comment. Fix formatting. + * shared_info.h (CURR_USER_MAGIC): Change to reflect change in + class user_info. + (class user_info): Add member warned_nonativesyms. + 2013-05-22 Corinna Vinschen * spinlock.h (ULONG): Replace LONG operator with ULONG to accommodate diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 175c516ed..f73c232c9 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -97,9 +97,22 @@ set_winsymlinks (const char *buf) else if (ascii_strncasematch (buf, "lnk", 3)) allow_winsymlinks = WSYM_lnk; /* Make sure to try native symlinks only on systems supporting them. */ - else if (ascii_strncasematch (buf, "native", 6) - && wincap.max_sys_priv () >= SE_CREATE_SYMBOLIC_LINK_PRIVILEGE) - allow_winsymlinks = WSYM_native; + else if (ascii_strncasematch (buf, "native", 6)) + { + if (wincap.max_sys_priv () < SE_CREATE_SYMBOLIC_LINK_PRIVILEGE) + { + if (!user_shared->warned_nonativesyms) + { + small_printf ("\"winsymlinks:%s\" option detected in CYGWIN environment variable.\n" + "Native symlinks are not supported on Windows versions prior to\n" + "Windows Vista/Server 2008. This option will be ignored.\n", buf); + user_shared->warned_nonativesyms = 1; + } + } + else + allow_winsymlinks = ascii_strcasematch (buf + 6, "strict") + ? WSYM_nativestrict : WSYM_native; + } } /* The structure below is used to set up an array which is used to diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 9462c7a0c..da732a493 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -56,6 +56,7 @@ enum winsym_t WSYM_sysfile = 0, WSYM_lnk, WSYM_native, + WSYM_nativestrict, WSYM_nfs }; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 0567a91ac..16571b12e 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1542,9 +1542,19 @@ symlink_native (const char *oldpath, path_conv &win32_newpath) final_oldpath = win32_oldpath.get_nt_native_path (); final_oldpath->Buffer += dirpath.Length / sizeof (WCHAR); } + /* If the symlink target doesn't exist, don't create native symlink. + Otherwise the directory flag in the symlink is potentially wrong + when the target comes into existence, and native tools will fail. + This is so screwball. This is no problem on AFS, fortunately. */ + if (!win32_oldpath.exists () && !win32_oldpath.fs_is_afs ()) + { + SetLastError (ERROR_FILE_NOT_FOUND); + return -1; + } + /* Convert native path to DOS UNC path. */ final_newpath = win32_newpath.get_nt_native_path (); - /* Convert native to DOS UNC path. */ final_newpath->Buffer[1] = L'\\'; + /* Try to create native symlink. */ if (!CreateSymbolicLinkW (final_newpath->Buffer, final_oldpath->Buffer, win32_oldpath.isdir () ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0)) @@ -1618,10 +1628,10 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice) set_errno (EPERM); goto done; } - wsym_type = WSYM_native; + wsym_type = WSYM_nativestrict; } /* Don't try native symlinks on filesystems not supporting reparse points. */ - else if (wsym_type == WSYM_native + else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict) && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) wsym_type = WSYM_sysfile; @@ -1662,13 +1672,17 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice) res = symlink_nfs (oldpath, win32_newpath); goto done; case WSYM_native: + case WSYM_nativestrict: res = symlink_native (oldpath, win32_newpath); - /* AFS? Too bad. Otherwise, just try the default symlink type. */ - if (win32_newpath.fs_is_afs ()) + if (!res) + goto done; + /* Strictly native? Too bad. */ + if (wsym_type == WSYM_nativestrict) { __seterrno (); goto done; } + /* Otherwise, fall back to default symlink type. */ wsym_type = WSYM_sysfile; break; default: @@ -1853,7 +1867,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice) so for now we don't request WRITE_DAC on remote drives. */ access |= READ_CONTROL | WRITE_DAC; - status = NtCreateFile (&fh, access, win32_newpath.get_object_attr (attr, sec_none_nih), + status = NtCreateFile (&fh, access, + win32_newpath.get_object_attr (attr, sec_none_nih), &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS, isdevice ? FILE_OVERWRITE_IF : FILE_CREATE, diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index f3605e402..6733b3636 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -15,7 +15,7 @@ details. */ #include "limits.h" #include "mount.h" -#define CURR_USER_MAGIC 0x6467403bU +#define CURR_USER_MAGIC 0xab1fcce8U class user_info { @@ -25,6 +25,7 @@ public: DWORD cb; bool warned_msdos; bool warned_notty; + bool warned_nonativesyms; mount_info mountinfo; friend void dll_crt0_1 (void *); static void create (bool);