Provides and conflicts with msys2-runtime, so can be used to replace it if wanted. Keep this as a separate package to test for regressions in cygwin and to have (in theory) a runtime that supports 32bit in the repo. There is no guarantee for how long we are going to keep this.
235 lines
7.1 KiB
Diff
235 lines
7.1 KiB
Diff
From bb01dd41c6717f478c94f3790b90138c2a7c2660 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B8=CC=86=20=D0=9F?=
|
|
=?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=BE=D0=B2?= <alexey.pawlow@gmail.com>
|
|
Date: Sun, 14 Apr 2019 21:47:21 +0300
|
|
Subject: [PATCH 07/N] Instead of creating Cygwin symlinks, use deep copy by
|
|
default
|
|
|
|
The new `winsymlinks` mode `deepcopy` (which is made the default) lets
|
|
calls to `symlink()` create (deep) copies of the source file/directory.
|
|
|
|
This is necessary because unlike Cygwin, MSYS2 does not try to be its
|
|
own little ecosystem that lives its life separate from regular Win32
|
|
programs: the latter have _no idea_ about Cygwin-emulated symbolic links
|
|
(i.e. system files whose contents start with `!<symlink>\xff\xfe` and
|
|
the remainder consists of the NUL-terminated, UTF-16LE-encoded symlink
|
|
target).
|
|
|
|
To support Cygwin-style symlinks, the new mode `sysfile` is introduced.
|
|
|
|
Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
|
---
|
|
winsup/cygwin/environ.cc | 4 +
|
|
winsup/cygwin/globals.cc | 3 +-
|
|
winsup/cygwin/path.cc | 154 +++++++++++++++++++++++++++++++++++++++
|
|
3 files changed, 160 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
|
|
index f746841..296c890 100644
|
|
--- a/winsup/cygwin/environ.cc
|
|
+++ b/winsup/cygwin/environ.cc
|
|
@@ -88,6 +88,10 @@ set_winsymlinks (const char *buf)
|
|
else if (ascii_strncasematch (buf, "native", 6))
|
|
allow_winsymlinks = ascii_strcasematch (buf + 6, "strict")
|
|
? WSYM_nativestrict : WSYM_native;
|
|
+ else if (ascii_strncasematch (buf, "deepcopy", 8))
|
|
+ allow_winsymlinks = WSYM_deepcopy;
|
|
+ else
|
|
+ allow_winsymlinks = WSYM_sysfile;
|
|
}
|
|
|
|
/* 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 5687a1e..1b8d8e2 100644
|
|
--- a/winsup/cygwin/globals.cc
|
|
+++ b/winsup/cygwin/globals.cc
|
|
@@ -59,6 +59,7 @@ enum winsym_t
|
|
WSYM_nativestrict,
|
|
WSYM_nfs,
|
|
WSYM_sysfile,
|
|
+ WSYM_deepcopy
|
|
};
|
|
|
|
exit_states NO_COPY exit_state;
|
|
@@ -72,7 +73,7 @@ bool ignore_case_with_glob;
|
|
bool pipe_byte;
|
|
bool reset_com;
|
|
bool wincmdln;
|
|
-winsym_t allow_winsymlinks = WSYM_default;
|
|
+winsym_t allow_winsymlinks = WSYM_deepcopy;
|
|
bool disable_pcon;
|
|
|
|
bool NO_COPY in_forkee;
|
|
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
|
|
index a430d98..17646a8 100644
|
|
--- a/winsup/cygwin/path.cc
|
|
+++ b/winsup/cygwin/path.cc
|
|
@@ -1682,6 +1682,89 @@ conv_path_list (const char *src, char *dst, size_t size,
|
|
|
|
/********************** Symbolic Link Support **************************/
|
|
|
|
+/*
|
|
+ Create a deep copy of src as dst, while avoiding descending in origpath.
|
|
+*/
|
|
+static int
|
|
+recursiveCopy (char * src, char * dst, const char * origpath)
|
|
+{
|
|
+ WIN32_FIND_DATA dHfile;
|
|
+ HANDLE dH = INVALID_HANDLE_VALUE;
|
|
+ BOOL findfiles;
|
|
+ int srcpos = strlen (src);
|
|
+ int dstpos = strlen (dst);
|
|
+ int res = -1;
|
|
+
|
|
+ debug_printf("recursiveCopy (%s, %s)", src, dst);
|
|
+
|
|
+ /* Create the destination directory */
|
|
+ if (!CreateDirectoryEx (src, dst, NULL))
|
|
+ {
|
|
+ debug_printf("CreateDirectoryEx(%s, %s, 0) failed", src, dst);
|
|
+ __seterrno ();
|
|
+ goto done;
|
|
+ }
|
|
+ /* Descend into the source directory */
|
|
+ if (srcpos + 2 >= MAX_PATH || dstpos + 1 >= MAX_PATH)
|
|
+ {
|
|
+ set_errno (ENAMETOOLONG);
|
|
+ goto done;
|
|
+ }
|
|
+ strcat (src, "\\*");
|
|
+ strcat (dst, "\\");
|
|
+ dH = FindFirstFile (src, &dHfile);
|
|
+ debug_printf("dHfile(1): %s", dHfile.cFileName);
|
|
+ findfiles = FindNextFile (dH, &dHfile);
|
|
+ debug_printf("dHfile(2): %s", dHfile.cFileName);
|
|
+ findfiles = FindNextFile (dH, &dHfile);
|
|
+ while (findfiles)
|
|
+ {
|
|
+ /* Append the directory item filename to both source and destination */
|
|
+ int filelen = strlen (dHfile.cFileName);
|
|
+ debug_printf("dHfile(3): %s", dHfile.cFileName);
|
|
+ if (srcpos + 1 + filelen >= MAX_PATH ||
|
|
+ dstpos + 1 + filelen >= MAX_PATH)
|
|
+ {
|
|
+ set_errno (ENAMETOOLONG);
|
|
+ goto done;
|
|
+ }
|
|
+ strcpy (&src[srcpos+1], dHfile.cFileName);
|
|
+ strcpy (&dst[dstpos+1], dHfile.cFileName);
|
|
+ debug_printf("%s -> %s", src, dst);
|
|
+ if (dHfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
+ {
|
|
+ /* Recurse into the child directory */
|
|
+ debug_printf("%s <-> %s", src, origpath);
|
|
+ if (strcmp (src, origpath)) // avoids endless recursion
|
|
+ if (recursiveCopy (src, dst, origpath))
|
|
+ goto done;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* Just copy the file */
|
|
+ if (!CopyFile (src, dst, FALSE))
|
|
+ {
|
|
+ __seterrno ();
|
|
+ goto done;
|
|
+ }
|
|
+ }
|
|
+ findfiles = FindNextFile (dH, &dHfile);
|
|
+ }
|
|
+ if (GetLastError() != ERROR_NO_MORE_FILES)
|
|
+ {
|
|
+ __seterrno ();
|
|
+ goto done;
|
|
+ }
|
|
+ res = 0;
|
|
+
|
|
+done:
|
|
+
|
|
+ if (dH != INVALID_HANDLE_VALUE)
|
|
+ FindClose (dH);
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
/* Create a symlink from FROMPATH to TOPATH. */
|
|
|
|
extern "C" int
|
|
@@ -2219,6 +2302,77 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
|
|
}
|
|
else /* wsym_type == WSYM_sysfile */
|
|
{
|
|
+ if (wsym_type == WSYM_deepcopy)
|
|
+ {
|
|
+ path_conv src_path;
|
|
+ src_path.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
|
|
+ if (src_path.error)
|
|
+ {
|
|
+ set_errno (src_path.error);
|
|
+ __leave;
|
|
+ }
|
|
+ if (!src_path.isdevice () && !src_path.is_fs_special ())
|
|
+ {
|
|
+ /* MSYS copy file instead make symlink */
|
|
+
|
|
+ char * real_oldpath;
|
|
+ if (isabspath (oldpath))
|
|
+ strcpy (real_oldpath = tp.c_get (), oldpath);
|
|
+ else
|
|
+ /* Find the real source path, relative
|
|
+ to the directory of the destination */
|
|
+ {
|
|
+ /* Determine the character position of the last path component */
|
|
+ const char *newpath = win32_newpath.get_posix();
|
|
+ int pos = strlen (newpath);
|
|
+ while (--pos >= 0)
|
|
+ if (isdirsep (newpath[pos]))
|
|
+ break;
|
|
+ /* Append the source path to the directory
|
|
+ component of the destination */
|
|
+ if (pos+1+strlen(oldpath) >= MAX_PATH)
|
|
+ {
|
|
+ set_errno(ENAMETOOLONG);
|
|
+ __leave;
|
|
+ }
|
|
+ strcpy (real_oldpath = tp.c_get (), newpath);
|
|
+ strcpy (&real_oldpath[pos+1], oldpath);
|
|
+ }
|
|
+
|
|
+ /* As a MSYS limitation, the source path must exist. */
|
|
+ path_conv win32_oldpath;
|
|
+ win32_oldpath.check (real_oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
|
|
+ if (!win32_oldpath.exists ())
|
|
+ {
|
|
+ set_errno (ENOENT);
|
|
+ __leave;
|
|
+ }
|
|
+
|
|
+ char *w_newpath;
|
|
+ char *w_oldpath;
|
|
+ stpcpy (w_newpath = tp.c_get (), win32_newpath.get_win32());
|
|
+ stpcpy (w_oldpath = tp.c_get (), win32_oldpath.get_win32());
|
|
+ if (win32_oldpath.isdir())
|
|
+ {
|
|
+ char *origpath;
|
|
+ strcpy (origpath = tp.c_get (), w_oldpath);
|
|
+ res = recursiveCopy (w_oldpath, w_newpath, origpath);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (!CopyFile (w_oldpath, w_newpath, FALSE))
|
|
+ {
|
|
+ __seterrno ();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ res = 0;
|
|
+ }
|
|
+ }
|
|
+ __leave;
|
|
+ }
|
|
+ }
|
|
+
|
|
/* Default technique creating a symlink. */
|
|
buf = tp.t_get ();
|
|
cp = stpcpy (buf, SYMLINK_COOKIE);
|