diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 4e049211e9..955684e232 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -92,6 +92,8 @@ set_winsymlinks (const char *buf) ? WSYM_nativestrict : WSYM_native; else if (ascii_strncasematch (buf, "deepcopy", 8)) allow_winsymlinks = WSYM_deepcopy; + else if (ascii_strncasematch (buf, "nativeordeepcopy", 8)) + allow_winsymlinks = WSYM_native_or_deepcopy; else allow_winsymlinks = WSYM_sysfile; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index ab2c205609..f05bdb753e 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -57,7 +57,8 @@ enum winsym_t WSYM_nativestrict, WSYM_nfs, WSYM_sysfile, - WSYM_deepcopy + WSYM_deepcopy, + WSYM_native_or_deepcopy }; exit_states NO_COPY exit_state; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 33eb644780..d6a29dd354 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2287,6 +2287,9 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict) && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) wsym_type = WSYM_default; + else if (wsym_type == WSYM_native_or_deepcopy + && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) + wsym_type = WSYM_deepcopy; /* Attach .lnk suffix when shortcut is requested. */ if (wsym_type == WSYM_lnk && !win32_newpath.exists () @@ -2319,6 +2322,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) res = symlink_nfs (oldpath, win32_newpath); __leave; case WSYM_deepcopy: +case_WSYM_deepcopy: res = symlink_deepcopy (oldpath, win32_newpath); if (!res || res == -1) __leave; @@ -2327,6 +2331,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) break; case WSYM_native: case WSYM_nativestrict: + case WSYM_native_or_deepcopy: res = symlink_native (oldpath, win32_newpath); if (!res) __leave; @@ -2337,6 +2342,12 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) __seterrno (); __leave; } + /* With deepcopy fall back? Let's do that, then */ + if (res == -1 && wsym_type == WSYM_native_or_deepcopy) + { + wsym_type = WSYM_deepcopy; + goto case_WSYM_deepcopy; + } /* Otherwise, fall back to default symlink type. */ wsym_type = WSYM_default; fallthrough; diff --git a/winsup/doc/cygwinenv.xml b/winsup/doc/cygwinenv.xml index 4ea63b407a..754a9c1cfb 100644 --- a/winsup/doc/cygwinenv.xml +++ b/winsup/doc/cygwinenv.xml @@ -104,7 +104,7 @@ back to the parent process. -winsymlinks:{lnk,native,nativestrict,sys} +winsymlinks:{lnk,native,nativestrict,sys,deepcopy,nativeordeepcopy} @@ -133,6 +133,22 @@ system call will immediately fail. plain files with the system attribute, containing a magic cookie followed by the path to which the link points. + + +If set to winsymlinks:deepcopy, a copy of the source +will be created at the target (a "deep" copy in the case of directories, i.e. +the source directory will be copied recursively). This mode makes a trade-off +between compatibility and interoperability with Win32 programs, favoring the +latter. + + + +If set to winsymlinks:nativeordeepcopy Cygwin creates +symlinks as native Windows symlinks if supported (i.e. on file systems +supporting symbolic links, and when the current user is permitted to create +symbolic links, e.g. in Windows 10's "Developer Mode"), and fall back to +creating a deep copy in case symlinks are not supported. + Note that this setting has no effect where Cygwin knows that the