* msys2-runtime: add a shell script to generate the patches from msys2/Cygwin
The idea is to commit a change incrementing the `pkgver`, then running
this script, and then amending the commit.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
* msys2-runtime: work around Cygwin's source code containing symlinks
It is a bit unfortunate that MSYS2 substitutes symlinks by deep copies,
by default. Git, for example, claims that it cannot do symlinks, but
Cygwin now needs this. Let's make do with that default.
The strategy we use is simple: we override the auto-detected
`core.symlinks` setting. That will result in a dirty worktree, of
course: deep copies are not symlinks, and `git status` will detect it.
But that does not matter, as the build will now work ("deep" copies of
those header files will work just as well as real symlinks would have
done).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
* msys2-runtime: upgrade to v3.1.4
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1107 lines
40 KiB
Diff
1107 lines
40 KiB
Diff
From 1c6ee51365389a6ec56ebf249e5c81272dc6d3fe 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:17:46 +0300
|
|
Subject: [PATCH 03/N] Add functionality for converting UNIX paths in
|
|
arguments and environment variables to Windows form for native Win32
|
|
applications.
|
|
|
|
---
|
|
winsup/cygwin/Makefile.in | 1 +
|
|
winsup/cygwin/environ.cc | 24 +-
|
|
winsup/cygwin/environ.h | 2 +-
|
|
winsup/cygwin/external.cc | 2 +-
|
|
winsup/cygwin/include/sys/cygwin.h | 6 +
|
|
winsup/cygwin/msys2_path_conv.cc | 641 +++++++++++++++++++++++++++++
|
|
winsup/cygwin/msys2_path_conv.h | 147 +++++++
|
|
winsup/cygwin/path.cc | 69 ++++
|
|
winsup/cygwin/spawn.cc | 48 ++-
|
|
winsup/cygwin/winf.h | 4 +
|
|
10 files changed, 935 insertions(+), 9 deletions(-)
|
|
create mode 100644 winsup/cygwin/msys2_path_conv.cc
|
|
create mode 100644 winsup/cygwin/msys2_path_conv.h
|
|
|
|
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
|
|
index 11e0a78..553f66e 100644
|
|
--- a/winsup/cygwin/Makefile.in
|
|
+++ b/winsup/cygwin/Makefile.in
|
|
@@ -345,6 +345,7 @@ DLL_OFILES:= \
|
|
mmap_alloc.o \
|
|
msg.o \
|
|
msgcat.o \
|
|
+ msys2_path_conv.o \
|
|
mount.o \
|
|
net.o \
|
|
netdb.o \
|
|
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
|
|
index 3a03657..73df083 100644
|
|
--- a/winsup/cygwin/environ.cc
|
|
+++ b/winsup/cygwin/environ.cc
|
|
@@ -1056,7 +1056,7 @@ env_compare (const void *key, const void *memb)
|
|
to the child. */
|
|
char ** __reg3
|
|
build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
|
- bool no_envblock, HANDLE new_token)
|
|
+ bool no_envblock, HANDLE new_token, bool keep_posix)
|
|
{
|
|
PWCHAR cwinenv = NULL;
|
|
size_t winnum = 0;
|
|
@@ -1149,6 +1149,19 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
|
for (srcp = envp, dstp = newenv, pass_dstp = pass_env; *srcp; srcp++)
|
|
{
|
|
bool calc_tl = !no_envblock;
|
|
+#ifdef __MSYS__
|
|
+ /* Don't pass timezone environment to non-msys applications */
|
|
+ if (!keep_posix && ascii_strncasematch(*srcp, "TZ=", 3))
|
|
+ {
|
|
+ const char *v = *srcp + 3;
|
|
+ if (*v == ':')
|
|
+ goto next1;
|
|
+ for (; *v; v++)
|
|
+ if (!isalpha(*v) && !isdigit(*v) &&
|
|
+ *v != '-' && *v != '+' && *v != ':')
|
|
+ goto next1;
|
|
+ }
|
|
+#endif
|
|
/* Look for entries that require special attention */
|
|
for (unsigned i = 0; i < SPENVS_SIZE; i++)
|
|
if (!saw_spenv[i] && (*dstp = spenvs[i].retrieve (no_envblock, *srcp)))
|
|
@@ -1269,6 +1282,15 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc,
|
|
saw_PATH = true;
|
|
}
|
|
}
|
|
+#ifdef __MSYS__
|
|
+ else if (!keep_posix) {
|
|
+ char *win_arg = arg_heuristic(*srcp);
|
|
+ debug_printf("WIN32_PATH is %s", win_arg);
|
|
+ p = cstrdup1(win_arg);
|
|
+ if (win_arg != *srcp)
|
|
+ free (win_arg);
|
|
+ }
|
|
+#endif
|
|
else
|
|
p = *srcp; /* Don't worry about it */
|
|
|
|
diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h
|
|
index 269591a..71c3f22 100644
|
|
--- a/winsup/cygwin/environ.h
|
|
+++ b/winsup/cygwin/environ.h
|
|
@@ -43,7 +43,7 @@ extern "C" char **__cygwin_environ, ***main_environ;
|
|
extern "C" char __stdcall **cur_environ ();
|
|
#endif
|
|
char ** __reg3 build_env (const char * const *envp, PWCHAR &envblock,
|
|
- int &envc, bool need_envblock, HANDLE new_token);
|
|
+ int &envc, bool need_envblock, HANDLE new_token, bool keep_posix);
|
|
|
|
char ** __reg2 win32env_to_cygenv (PWCHAR rawenv, bool posify);
|
|
|
|
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
|
|
index 14a1dfb..07aa2fa 100644
|
|
--- a/winsup/cygwin/external.cc
|
|
+++ b/winsup/cygwin/external.cc
|
|
@@ -141,7 +141,7 @@ create_winenv (const char * const *env)
|
|
int unused_envc;
|
|
PWCHAR envblock = NULL;
|
|
char **envp = build_env (env ?: cur_environ (), envblock, unused_envc, false,
|
|
- NULL);
|
|
+ NULL, true);
|
|
PWCHAR p = envblock;
|
|
|
|
if (envp)
|
|
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
|
|
index 805671e..b395e96 100644
|
|
--- a/winsup/cygwin/include/sys/cygwin.h
|
|
+++ b/winsup/cygwin/include/sys/cygwin.h
|
|
@@ -83,6 +83,12 @@ extern ssize_t cygwin_conv_path_list (cygwin_conv_path_t what, const void *from,
|
|
to one of the above values, or to ENOMEM if malloc fails. */
|
|
extern void *cygwin_create_path (cygwin_conv_path_t what, const void *from);
|
|
|
|
+extern char * arg_heuristic_with_exclusions (char const * const arg,
|
|
+ char const * exclusions,
|
|
+ size_t exclusions_count);
|
|
+
|
|
+extern char * arg_heuristic (char const * const);
|
|
+
|
|
extern pid_t cygwin_winpid_to_pid (int);
|
|
extern int cygwin_posix_path_list_p (const char *);
|
|
extern void cygwin_split_path (const char *, char *, char *);
|
|
diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc
|
|
new file mode 100644
|
|
index 0000000..a989734
|
|
--- /dev/null
|
|
+++ b/winsup/cygwin/msys2_path_conv.cc
|
|
@@ -0,0 +1,641 @@
|
|
+/*
|
|
+ The MSYS2 Path conversion source code is licensed under:
|
|
+
|
|
+ CC0 1.0 Universal
|
|
+
|
|
+ Official translations of this legal tool are available
|
|
+
|
|
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
|
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
|
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
+ HEREUNDER.
|
|
+
|
|
+ Statement of Purpose
|
|
+
|
|
+ The laws of most jurisdictions throughout the world automatically
|
|
+ confer exclusive Copyright and Related Rights (defined below) upon the
|
|
+ creator and subsequent owner(s) (each and all, an "owner") of an
|
|
+ original work of authorship and/or a database (each, a "Work").
|
|
+
|
|
+ Certain owners wish to permanently relinquish those rights to a Work
|
|
+ for the purpose of contributing to a commons of creative, cultural and
|
|
+ scientific works ("Commons") that the public can reliably and without
|
|
+ fear of later claims of infringement build upon, modify, incorporate
|
|
+ in other works, reuse and redistribute as freely as possible in any
|
|
+ form whatsoever and for any purposes, including without limitation
|
|
+ commercial purposes. These owners may contribute to the Commons to
|
|
+ promote the ideal of a free culture and the further production of
|
|
+ creative, cultural and scientific works, or to gain reputation or
|
|
+ greater distribution for their Work in part through the use and
|
|
+ efforts of others.
|
|
+
|
|
+ For these and/or other purposes and motivations, and without any
|
|
+ expectation of additional consideration or compensation, the person
|
|
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or
|
|
+ she is an owner of Copyright and Related Rights in the Work,
|
|
+ voluntarily elects to apply CC0 to the Work and publicly distribute
|
|
+ the Work under its terms, with knowledge of his or her Copyright and
|
|
+ Related Rights in the Work and the meaning and intended legal effect
|
|
+ of CC0 on those rights.
|
|
+
|
|
+ 1. Copyright and Related Rights. A Work made available under CC0 may
|
|
+ be protected by copyright and related or neighboring rights
|
|
+ ("Copyright and Related Rights"). Copyright and Related Rights
|
|
+ include, but are not limited to, the following:
|
|
+
|
|
+ the right to reproduce, adapt, distribute, perform, display,
|
|
+ communicate, and translate a Work;
|
|
+ moral rights retained by the original author(s) and/or performer(s);
|
|
+ publicity and privacy rights pertaining to a person's image or
|
|
+ likeness depicted in a Work;
|
|
+ rights protecting against unfair competition in regards to a Work,
|
|
+ subject to the limitations in paragraph 4(a), below;
|
|
+ rights protecting the extraction, dissemination, use and reuse of data
|
|
+ in a Work;
|
|
+ database rights (such as those arising under Directive 96/9/EC of the
|
|
+ European Parliament and of the Council of 11 March 1996 on the legal
|
|
+ protection of databases, and under any national implementation
|
|
+ thereof, including any amended or successor version of such
|
|
+ directive); and
|
|
+ other similar, equivalent or corresponding rights throughout the world
|
|
+ based on applicable law or treaty, and any national implementations
|
|
+ thereof.
|
|
+
|
|
+ 2. Waiver. To the greatest extent permitted by, but not in
|
|
+ contravention of, applicable law, Affirmer hereby overtly, fully,
|
|
+ permanently, irrevocably and unconditionally waives, abandons, and
|
|
+ surrenders all of Affirmer's Copyright and Related Rights and
|
|
+ associated claims and causes of action, whether now known or unknown
|
|
+ (including existing as well as future claims and causes of action), in
|
|
+ the Work (i) in all territories worldwide, (ii) for the maximum
|
|
+ duration provided by applicable law or treaty (including future time
|
|
+ extensions), (iii) in any current or future medium and for any number
|
|
+ of copies, and (iv) for any purpose whatsoever, including without
|
|
+ limitation commercial, advertising or promotional purposes (the
|
|
+ "Waiver"). Affirmer makes the Waiver for the benefit of each member of
|
|
+ the public at large and to the detriment of Affirmer's heirs and
|
|
+ successors, fully intending that such Waiver shall not be subject to
|
|
+ revocation, rescission, cancellation, termination, or any other legal
|
|
+ or equitable action to disrupt the quiet enjoyment of the Work by the
|
|
+ public as contemplated by Affirmer's express Statement of Purpose.
|
|
+
|
|
+ 3. Public License Fallback. Should any part of the Waiver for any
|
|
+ reason be judged legally invalid or ineffective under applicable law,
|
|
+ then the Waiver shall be preserved to the maximum extent permitted
|
|
+ taking into account Affirmer's express Statement of Purpose. In
|
|
+ addition, to the extent the Waiver is so judged Affirmer hereby grants
|
|
+ to each affected person a royalty-free, non transferable, non
|
|
+ sublicensable, non exclusive, irrevocable and unconditional license to
|
|
+ exercise Affirmer's Copyright and Related Rights in the Work (i) in
|
|
+ all territories worldwide, (ii) for the maximum duration provided by
|
|
+ applicable law or treaty (including future time extensions), (iii) in
|
|
+ any current or future medium and for any number of copies, and (iv)
|
|
+ for any purpose whatsoever, including without limitation commercial,
|
|
+ advertising or promotional purposes (the "License"). The License shall
|
|
+ be deemed effective as of the date CC0 was applied by Affirmer to the
|
|
+ Work. Should any part of the License for any reason be judged legally
|
|
+ invalid or ineffective under applicable law, such partial invalidity
|
|
+ or ineffectiveness shall not invalidate the remainder of the License,
|
|
+ and in such case Affirmer hereby affirms that he or she will not (i)
|
|
+ exercise any of his or her remaining Copyright and Related Rights in
|
|
+ the Work or (ii) assert any associated claims and causes of action
|
|
+ with respect to the Work, in either case contrary to Affirmer's
|
|
+ express Statement of Purpose.
|
|
+
|
|
+ 4. Limitations and Disclaimers.
|
|
+
|
|
+ No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
+ surrendered, licensed or otherwise affected by this document.
|
|
+ Affirmer offers the Work as-is and makes no representations or
|
|
+ warranties of any kind concerning the Work, express, implied,
|
|
+ statutory or otherwise, including without limitation warranties of
|
|
+ title, merchantability, fitness for a particular purpose, non
|
|
+ infringement, or the absence of latent or other defects, accuracy, or
|
|
+ the present or absence of errors, whether or not discoverable, all to
|
|
+ the greatest extent permissible under applicable law.
|
|
+ Affirmer disclaims responsibility for clearing rights of other persons
|
|
+ that may apply to the Work or any use thereof, including without
|
|
+ limitation any person's Copyright and Related Rights in the Work.
|
|
+ Further, Affirmer disclaims responsibility for obtaining any necessary
|
|
+ consents, permissions or other rights required for any use of the
|
|
+ Work.
|
|
+ Affirmer understands and acknowledges that Creative Commons is not a
|
|
+ party to this document and has no duty or obligation with respect to
|
|
+ this CC0 or use of the Work.
|
|
+
|
|
+ Contributions thanks to:
|
|
+ niXman <i.nixman@autistici.org>
|
|
+ Ely Arzhannikov <iarzhannikov@gmail.com>
|
|
+ Alexey Pavlov <alexpux@gmail.com>
|
|
+ Ray Donnelly <mingw.android@gmail.com>
|
|
+ Johannes Schindelin <johannes.schindelin@gmx.de>
|
|
+
|
|
+*/
|
|
+
|
|
+#include "winsup.h"
|
|
+#include "miscfuncs.h"
|
|
+#include <ctype.h>
|
|
+#include <winioctl.h>
|
|
+#include <shlobj.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/cygwin.h>
|
|
+#include "cygerrno.h"
|
|
+#include "security.h"
|
|
+#include "path.h"
|
|
+#include "fhandler.h"
|
|
+#include "dtable.h"
|
|
+#include "cygheap.h"
|
|
+#include "shared_info.h"
|
|
+#include "cygtls.h"
|
|
+#include "tls_pbuf.h"
|
|
+#include "environ.h"
|
|
+#include <assert.h>
|
|
+#include <ntdll.h>
|
|
+#include <wchar.h>
|
|
+#include <wctype.h>
|
|
+
|
|
+#include "msys2_path_conv.h"
|
|
+
|
|
+typedef enum PATH_TYPE_E {
|
|
+ NONE = 0,
|
|
+ SIMPLE_WINDOWS_PATH,
|
|
+ ESCAPE_WINDOWS_PATH,
|
|
+ WINDOWS_PATH_LIST,
|
|
+ UNC,
|
|
+ ESCAPED_PATH,
|
|
+ ROOTED_PATH,
|
|
+ POSIX_PATH_LIST,
|
|
+ RELATIVE_PATH,
|
|
+ URL
|
|
+} path_type;
|
|
+
|
|
+int is_special_posix_path(const char* from, const char* to, char** dst, const char* dstend);
|
|
+void posix_to_win32_path(const char* from, const char* to, char** dst, const char* dstend);
|
|
+
|
|
+
|
|
+path_type find_path_start_and_type(const char** src, int recurse, const char* end);
|
|
+void copy_to_dst(const char* from, const char* to, char** dst, const char* dstend);
|
|
+void convert_path(const char** from, const char* to, path_type type, char** dst, const char* dstend);
|
|
+
|
|
+//Transformations
|
|
+//SIMPLE_WINDOWS_PATH converter. Copy as is. Hold C:\Something\like\this
|
|
+void swp_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//ESCAPE_WINDOWS_PATH converter. Turn backslashes to slashes and skip first /. Hold /C:\Somethind\like\this
|
|
+void ewp_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//WINDOWS_PATH_LIST converter. Copy as is. Hold /something/like/this;
|
|
+void wpl_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//UNC convert converter. Copy as is. Hold //somethig/like/this
|
|
+void unc_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//ESCAPED_PATH converter. Turn backslashes to slashes and skip first /. Hold //something\like\this
|
|
+void ep_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//ROOTED_PATH converter. Prepend root dir to front. Hold /something/like/this
|
|
+void rp_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//URL converter. Copy as is.
|
|
+void url_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+//POSIX_PATH_LIST. Hold x::x/y:z
|
|
+void ppl_convert(const char** from, const char* to, char** dst, const char* dstend);
|
|
+
|
|
+
|
|
+void find_end_of_posix_list(const char** to, int* in_string) {
|
|
+ for (; **to != '\0' && (in_string ? (**to != *in_string) : **to != ' '); ++*to) {
|
|
+ }
|
|
+
|
|
+ if (**to == *in_string) {
|
|
+ *in_string = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+void find_end_of_rooted_path(const char** from, const char** to, int* in_string) {
|
|
+ for (const char* it = *from; *it != '\0' && it != *to; ++it)
|
|
+ if (*it == '.' && *(it + 1) == '.' && *(it - 1) == '/') {
|
|
+ *to = it - 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (; **to != '\0'; ++*to) {
|
|
+ if (*in_string == 0 && **to == ' ') {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (**to == *in_string) {
|
|
+ *in_string = 0;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (**to == '/') {
|
|
+ if (*(*to - 1) == ' ') {
|
|
+ *to -= 1;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void sub_convert(const char** from, const char** to, char** dst, const char* dstend, int* in_string) {
|
|
+ const char* copy_from = *from;
|
|
+ path_type type = find_path_start_and_type(from, false, *to);
|
|
+
|
|
+ if (type == POSIX_PATH_LIST) {
|
|
+ find_end_of_posix_list(to, in_string);
|
|
+ }
|
|
+
|
|
+ if (type == ROOTED_PATH) {
|
|
+ find_end_of_rooted_path(from, to, in_string);
|
|
+ }
|
|
+
|
|
+ copy_to_dst(copy_from, *from, dst, dstend);
|
|
+
|
|
+ if (type != NONE) {
|
|
+ convert_path(from, *to, type, dst, dstend);
|
|
+ }
|
|
+
|
|
+ if (*dst != dstend) {
|
|
+ **dst = **to;
|
|
+ *dst += 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+const char* convert(char *dst, size_t dstlen, const char *src) {
|
|
+ if (dst == NULL || dstlen == 0 || src == NULL) {
|
|
+ return dst;
|
|
+ }
|
|
+
|
|
+ int need_convert = false;
|
|
+ for (const char* it = src; *it != '\0'; ++it) {
|
|
+ if (*it == '\\' || *it == '/') {
|
|
+ need_convert = true;
|
|
+ break;
|
|
+ }
|
|
+ if (isspace(*it)) {
|
|
+ need_convert = false;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ char* dstit = dst;
|
|
+ char* dstend = dst + dstlen;
|
|
+ if (!need_convert) {
|
|
+ copy_to_dst(src, NULL, &dstit, dstend);
|
|
+ *dstit = '\0';
|
|
+ return dst;
|
|
+ }
|
|
+ *dstend = '\0';
|
|
+
|
|
+ const char* srcit = src;
|
|
+ const char* srcbeg = src;
|
|
+
|
|
+ int in_string = false;
|
|
+
|
|
+ for (; *srcit != '\0'; ++srcit) {
|
|
+ if (*srcit == '\'' || *srcit == '"') {
|
|
+ if (in_string == *srcit) {
|
|
+ if (*(srcit + 1) != in_string) {
|
|
+ in_string = 0;
|
|
+ }
|
|
+ } else {
|
|
+ in_string = *srcit;
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (isspace(*srcit)) {
|
|
+ //sub_convert(&srcbeg, &srcit, &dstit, dstend, &in_string);
|
|
+ //srcbeg = srcit + 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ sub_convert(&srcbeg, &srcit, &dstit, dstend, &in_string);
|
|
+ if (!*srcit) {
|
|
+ *dstit = '\0';
|
|
+ return dst;
|
|
+ }
|
|
+ srcbeg = srcit + 1;
|
|
+ for (; *srcit != '\0'; ++srcit) {
|
|
+ continue;
|
|
+ }
|
|
+ copy_to_dst(srcbeg, srcit, &dstit, dstend);
|
|
+ *dstit = '\0';
|
|
+
|
|
+ /*if (dstit - dst < 2) {
|
|
+ dstit = dst;
|
|
+ copy_to_dst(src, NULL, &dstit, dstend);
|
|
+ *dstit = '\0';
|
|
+ }*/
|
|
+
|
|
+ return dst;
|
|
+}
|
|
+
|
|
+void copy_to_dst(const char* from, const char* to, char** dst, const char* dstend) {
|
|
+ for (; (*from != '\0') && (from != to) && (*dst != dstend); ++from, ++(*dst)) {
|
|
+ **dst = *from;
|
|
+ }
|
|
+}
|
|
+
|
|
+const char** move(const char** p, int count) {
|
|
+ *p += count;
|
|
+ return p;
|
|
+}
|
|
+
|
|
+path_type find_path_start_and_type(const char** src, int recurse, const char* end) {
|
|
+ const char* it = *src;
|
|
+
|
|
+ if (*it == '\0' || it == end) return NONE;
|
|
+
|
|
+ if (!isalnum(*it) && *it != '/' && *it != '\\' && *it != ':' && *it != '-' && *it != '.') {
|
|
+ return find_path_start_and_type(move(src, 1), true, end);
|
|
+ }
|
|
+
|
|
+ path_type result = NONE;
|
|
+
|
|
+ if (isalpha(*it) && *(it + 1) == ':') {
|
|
+ if (*(it + 2) == '\\') {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if (*(it + 2) == '/' && memchr(it + 2, ':', end - (it + 2)) == NULL) {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if (*(it + 2) == '/' && memchr(it + 2, ';', end - (it + 2))) {
|
|
+ return WINDOWS_PATH_LIST;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (*it == '.' && (*(it + 1) == '.' || *(it + 1) == '/') && memchr(it + 2, ':', end - (it + 2)) == NULL) {
|
|
+ return RELATIVE_PATH;
|
|
+ }
|
|
+
|
|
+ if (*it == '/') {
|
|
+ it += 1;
|
|
+
|
|
+ if (isalpha(*it) && *(it + 1) == ':') {
|
|
+ return ESCAPE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if (*it == '.' && *(it + 1) == '.') {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if (*it == '/') {
|
|
+ it += 1;
|
|
+ switch(*it) {
|
|
+ case ':': return URL;
|
|
+ case '/': return ESCAPED_PATH;
|
|
+ }
|
|
+ if (memchr(it, '/', end - it))
|
|
+ return UNC;
|
|
+ else
|
|
+ return ESCAPED_PATH;
|
|
+ }
|
|
+
|
|
+ for (; *it != '\0' && it != end; ++it) {
|
|
+ switch(*it) {
|
|
+ case ':': {char ch = *(it + 1); if (ch == '/' || ch == ':' || ch == '.') return POSIX_PATH_LIST;}
|
|
+ case ';': return WINDOWS_PATH_LIST;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (result != NONE) {
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ return ROOTED_PATH;
|
|
+ }
|
|
+
|
|
+ int starts_with_minus = 0;
|
|
+ int starts_with_minus_alpha = 0;
|
|
+ if (*it == '-') {
|
|
+ starts_with_minus = 1;
|
|
+ it += 1;
|
|
+ if (isalpha(*it)) {
|
|
+ it += 1;
|
|
+ starts_with_minus_alpha = 1;
|
|
+ if (memchr(it, ';', end - it)) {
|
|
+ return WINDOWS_PATH_LIST;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (const char* it2 = it; *it2 != '\0' && it2 != end; ++it2) {
|
|
+ char ch = *it2;
|
|
+ if (starts_with_minus_alpha) {
|
|
+ if (isalpha(ch) && (*(it2+1) == ':') && (*(it2+2) == '/')) {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+ if (ch == '/'&& memchr(it2, ',', end - it) == NULL) {
|
|
+ *src = it2;
|
|
+ return find_path_start_and_type(src, true, end);
|
|
+ }
|
|
+ starts_with_minus_alpha = 0;
|
|
+ }
|
|
+ if (ch == '\'' || ch == '"')
|
|
+ starts_with_minus = false;
|
|
+ if ((ch == '=') || (ch == ':' && starts_with_minus) || ((ch == '\'' || ch == '"') && result == NONE)) {
|
|
+ *src = it2 + 1;
|
|
+ return find_path_start_and_type(src, true, end);
|
|
+ }
|
|
+
|
|
+ if (ch == ',' && starts_with_minus) {
|
|
+ *src = it2 + 1;
|
|
+ return find_path_start_and_type(src, true, end);
|
|
+ }
|
|
+
|
|
+ if (ch == ':' && it2 + 1 != end) {
|
|
+ it2 += 1;
|
|
+ ch = *it2;
|
|
+ if (ch == '/' || ch == ':' || ch == '.') {
|
|
+ if (ch == '/' && *(it2 + 1) == '/') {
|
|
+ return URL;
|
|
+ } else {
|
|
+ return POSIX_PATH_LIST;
|
|
+ }
|
|
+ } else if (memchr(it2, '=', end - it) == NULL) {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (result != NONE) {
|
|
+ *src = it;
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+}
|
|
+
|
|
+void convert_path(const char** from, const char* to, path_type type, char** dst, const char* dstend) {
|
|
+ switch(type) {
|
|
+ case SIMPLE_WINDOWS_PATH: swp_convert(from, to, dst, dstend); break;
|
|
+ case ESCAPE_WINDOWS_PATH: ewp_convert(from, to, dst, dstend); break;
|
|
+ case WINDOWS_PATH_LIST: wpl_convert(from, to, dst, dstend); break;
|
|
+ case RELATIVE_PATH: swp_convert(from, to, dst, dstend); break;
|
|
+ case UNC: unc_convert(from, to, dst, dstend); break;
|
|
+ case ESCAPED_PATH: ep_convert(from, to, dst, dstend); break;
|
|
+ case ROOTED_PATH: rp_convert(from, to, dst, dstend); break;
|
|
+ case URL: url_convert(from, to, dst, dstend); break;
|
|
+ case POSIX_PATH_LIST: ppl_convert(from, to, dst, dstend); break;
|
|
+ case NONE: // prevent warnings;
|
|
+ default:
|
|
+ return;
|
|
+ }
|
|
+}
|
|
+
|
|
+void swp_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ copy_to_dst(*from, to, dst, dstend);
|
|
+}
|
|
+
|
|
+void ewp_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ *from += 1;
|
|
+ unc_convert(from, to, dst, dstend);
|
|
+}
|
|
+
|
|
+void wpl_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ swp_convert(from, to, dst, dstend);
|
|
+}
|
|
+
|
|
+void unc_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ const char* it = *from;
|
|
+ for (; (*it != '\0' && it != to) && (*dst != dstend); ++it, ++(*dst)) {
|
|
+ if (*it == '\\') {
|
|
+ **dst = '/';
|
|
+ } else {
|
|
+ **dst = *it;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void ep_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ ewp_convert(from, to, dst, dstend);
|
|
+}
|
|
+
|
|
+void rp_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ const char* it = *from;
|
|
+ const char* real_to = to;
|
|
+
|
|
+ if (*real_to == '\0') {
|
|
+ real_to -= 1;
|
|
+ if (*real_to != '\'' && *real_to != '"') {
|
|
+ real_to += 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!is_special_posix_path(*from, real_to, dst, dstend)) {
|
|
+ posix_to_win32_path(it, real_to, dst, dstend);
|
|
+ }
|
|
+
|
|
+ if (*dst != dstend && real_to != to) {
|
|
+ **dst = *real_to;
|
|
+ *dst += 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+void url_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ unc_convert(from, to, dst, dstend);
|
|
+}
|
|
+
|
|
+void subp_convert(const char** from, const char* end, int is_url, char** dst, const char* dstend) {
|
|
+ const char* begin = *from;
|
|
+ path_type type = is_url ? URL : find_path_start_and_type(from, 0, end);
|
|
+ copy_to_dst(begin, *from, dst, dstend);
|
|
+
|
|
+ if (type == NONE) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ char* start = *dst;
|
|
+ convert_path(from, end, type, dst, dstend);
|
|
+
|
|
+ if (!is_url) {
|
|
+ for (; start != *dst; ++start) {
|
|
+ if (*start == '/') {
|
|
+ *start = '\\';
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+void ppl_convert(const char** from, const char* to, char** dst, const char* dstend) {
|
|
+ const char *orig_dst = *dst;
|
|
+ const char* it = *from;
|
|
+ const char* beg = it;
|
|
+ int prev_was_simc = 0;
|
|
+ int is_url = 0;
|
|
+ for (; (*it != '\0' && it != to) && (*dst != dstend); ++it) {
|
|
+ if (*it == ':') {
|
|
+ if (prev_was_simc) {
|
|
+ continue;
|
|
+ }
|
|
+ if (*(it + 1) == '/' && *(it + 2) == '/' && isalpha(*beg)) {
|
|
+ is_url = 1;
|
|
+ /* double-check: protocol must be alnum (or +) */
|
|
+ for (const char *p = beg; p != it; ++p)
|
|
+ if (!isalnum(*p) && *p != '+') {
|
|
+ is_url = 0;
|
|
+ break;
|
|
+ }
|
|
+ if (is_url)
|
|
+ continue;
|
|
+ }
|
|
+ prev_was_simc = 1;
|
|
+ subp_convert(&beg, it, is_url, dst, dstend);
|
|
+ is_url = 0;
|
|
+
|
|
+ if (*dst == dstend) {
|
|
+ system_printf("Path cut off during conversion: %s\n", orig_dst);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ **dst = ';';
|
|
+ *dst += 1;
|
|
+ }
|
|
+
|
|
+ if (*it != ':' && prev_was_simc) {
|
|
+ prev_was_simc = 0;
|
|
+ beg = it;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!prev_was_simc) {
|
|
+ subp_convert(&beg, it, is_url, dst, dstend);
|
|
+ } else {
|
|
+ *dst -= 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+int is_special_posix_path(const char* from, const char* to, char** dst, const char* dstend) {
|
|
+ const char dev_null[] = "/dev/null";
|
|
+
|
|
+ if ((to - from) == (sizeof(dev_null) - 1) && strncmp(from, "/dev/null", to - from) == 0) {
|
|
+ copy_to_dst("nul", NULL, dst, dstend);
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void posix_to_win32_path(const char* from, const char* to, char** dst, const char* dstend) {
|
|
+ if ( from != to ) {
|
|
+ tmp_pathbuf tp;
|
|
+ char *one_path = tp.c_get();
|
|
+ strncpy(one_path, from, to-from);
|
|
+ one_path[to-from] = '\0';
|
|
+
|
|
+ path_conv conv (one_path, 0);
|
|
+ if (conv.error)
|
|
+ {
|
|
+ set_errno(conv.error);
|
|
+ copy_to_dst(one_path, NULL, dst, dstend);
|
|
+ } else {
|
|
+ char* win32_path = tp.c_get();
|
|
+ stpcpy (win32_path, conv.get_win32 ());
|
|
+ for (; (*win32_path != '\0') && (*dst != dstend); ++win32_path, ++(*dst)) {
|
|
+ **dst = (*win32_path == '\\') ? '/' : *win32_path;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
diff --git a/winsup/cygwin/msys2_path_conv.h b/winsup/cygwin/msys2_path_conv.h
|
|
new file mode 100644
|
|
index 0000000..67d85ec
|
|
--- /dev/null
|
|
+++ b/winsup/cygwin/msys2_path_conv.h
|
|
@@ -0,0 +1,147 @@
|
|
+/*
|
|
+ The MSYS2 Path conversion source code is licensed under:
|
|
+
|
|
+ CC0 1.0 Universal
|
|
+
|
|
+ Official translations of this legal tool are available
|
|
+
|
|
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
|
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
|
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
+ HEREUNDER.
|
|
+
|
|
+ Statement of Purpose
|
|
+
|
|
+ The laws of most jurisdictions throughout the world automatically
|
|
+ confer exclusive Copyright and Related Rights (defined below) upon the
|
|
+ creator and subsequent owner(s) (each and all, an "owner") of an
|
|
+ original work of authorship and/or a database (each, a "Work").
|
|
+
|
|
+ Certain owners wish to permanently relinquish those rights to a Work
|
|
+ for the purpose of contributing to a commons of creative, cultural and
|
|
+ scientific works ("Commons") that the public can reliably and without
|
|
+ fear of later claims of infringement build upon, modify, incorporate
|
|
+ in other works, reuse and redistribute as freely as possible in any
|
|
+ form whatsoever and for any purposes, including without limitation
|
|
+ commercial purposes. These owners may contribute to the Commons to
|
|
+ promote the ideal of a free culture and the further production of
|
|
+ creative, cultural and scientific works, or to gain reputation or
|
|
+ greater distribution for their Work in part through the use and
|
|
+ efforts of others.
|
|
+
|
|
+ For these and/or other purposes and motivations, and without any
|
|
+ expectation of additional consideration or compensation, the person
|
|
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or
|
|
+ she is an owner of Copyright and Related Rights in the Work,
|
|
+ voluntarily elects to apply CC0 to the Work and publicly distribute
|
|
+ the Work under its terms, with knowledge of his or her Copyright and
|
|
+ Related Rights in the Work and the meaning and intended legal effect
|
|
+ of CC0 on those rights.
|
|
+
|
|
+ 1. Copyright and Related Rights. A Work made available under CC0 may
|
|
+ be protected by copyright and related or neighboring rights
|
|
+ ("Copyright and Related Rights"). Copyright and Related Rights
|
|
+ include, but are not limited to, the following:
|
|
+
|
|
+ the right to reproduce, adapt, distribute, perform, display,
|
|
+ communicate, and translate a Work;
|
|
+ moral rights retained by the original author(s) and/or performer(s);
|
|
+ publicity and privacy rights pertaining to a person's image or
|
|
+ likeness depicted in a Work;
|
|
+ rights protecting against unfair competition in regards to a Work,
|
|
+ subject to the limitations in paragraph 4(a), below;
|
|
+ rights protecting the extraction, dissemination, use and reuse of data
|
|
+ in a Work;
|
|
+ database rights (such as those arising under Directive 96/9/EC of the
|
|
+ European Parliament and of the Council of 11 March 1996 on the legal
|
|
+ protection of databases, and under any national implementation
|
|
+ thereof, including any amended or successor version of such
|
|
+ directive); and
|
|
+ other similar, equivalent or corresponding rights throughout the world
|
|
+ based on applicable law or treaty, and any national implementations
|
|
+ thereof.
|
|
+
|
|
+ 2. Waiver. To the greatest extent permitted by, but not in
|
|
+ contravention of, applicable law, Affirmer hereby overtly, fully,
|
|
+ permanently, irrevocably and unconditionally waives, abandons, and
|
|
+ surrenders all of Affirmer's Copyright and Related Rights and
|
|
+ associated claims and causes of action, whether now known or unknown
|
|
+ (including existing as well as future claims and causes of action), in
|
|
+ the Work (i) in all territories worldwide, (ii) for the maximum
|
|
+ duration provided by applicable law or treaty (including future time
|
|
+ extensions), (iii) in any current or future medium and for any number
|
|
+ of copies, and (iv) for any purpose whatsoever, including without
|
|
+ limitation commercial, advertising or promotional purposes (the
|
|
+ "Waiver"). Affirmer makes the Waiver for the benefit of each member of
|
|
+ the public at large and to the detriment of Affirmer's heirs and
|
|
+ successors, fully intending that such Waiver shall not be subject to
|
|
+ revocation, rescission, cancellation, termination, or any other legal
|
|
+ or equitable action to disrupt the quiet enjoyment of the Work by the
|
|
+ public as contemplated by Affirmer's express Statement of Purpose.
|
|
+
|
|
+ 3. Public License Fallback. Should any part of the Waiver for any
|
|
+ reason be judged legally invalid or ineffective under applicable law,
|
|
+ then the Waiver shall be preserved to the maximum extent permitted
|
|
+ taking into account Affirmer's express Statement of Purpose. In
|
|
+ addition, to the extent the Waiver is so judged Affirmer hereby grants
|
|
+ to each affected person a royalty-free, non transferable, non
|
|
+ sublicensable, non exclusive, irrevocable and unconditional license to
|
|
+ exercise Affirmer's Copyright and Related Rights in the Work (i) in
|
|
+ all territories worldwide, (ii) for the maximum duration provided by
|
|
+ applicable law or treaty (including future time extensions), (iii) in
|
|
+ any current or future medium and for any number of copies, and (iv)
|
|
+ for any purpose whatsoever, including without limitation commercial,
|
|
+ advertising or promotional purposes (the "License"). The License shall
|
|
+ be deemed effective as of the date CC0 was applied by Affirmer to the
|
|
+ Work. Should any part of the License for any reason be judged legally
|
|
+ invalid or ineffective under applicable law, such partial invalidity
|
|
+ or ineffectiveness shall not invalidate the remainder of the License,
|
|
+ and in such case Affirmer hereby affirms that he or she will not (i)
|
|
+ exercise any of his or her remaining Copyright and Related Rights in
|
|
+ the Work or (ii) assert any associated claims and causes of action
|
|
+ with respect to the Work, in either case contrary to Affirmer's
|
|
+ express Statement of Purpose.
|
|
+
|
|
+ 4. Limitations and Disclaimers.
|
|
+
|
|
+ No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
+ surrendered, licensed or otherwise affected by this document.
|
|
+ Affirmer offers the Work as-is and makes no representations or
|
|
+ warranties of any kind concerning the Work, express, implied,
|
|
+ statutory or otherwise, including without limitation warranties of
|
|
+ title, merchantability, fitness for a particular purpose, non
|
|
+ infringement, or the absence of latent or other defects, accuracy, or
|
|
+ the present or absence of errors, whether or not discoverable, all to
|
|
+ the greatest extent permissible under applicable law.
|
|
+ Affirmer disclaims responsibility for clearing rights of other persons
|
|
+ that may apply to the Work or any use thereof, including without
|
|
+ limitation any person's Copyright and Related Rights in the Work.
|
|
+ Further, Affirmer disclaims responsibility for obtaining any necessary
|
|
+ consents, permissions or other rights required for any use of the
|
|
+ Work.
|
|
+ Affirmer understands and acknowledges that Creative Commons is not a
|
|
+ party to this document and has no duty or obligation with respect to
|
|
+ this CC0 or use of the Work.
|
|
+
|
|
+ Contributions thanks to:
|
|
+ niXman <i.nixman@autistici.org>
|
|
+ Ely Arzhannikov <iarzhannikov@gmail.com>
|
|
+ Alexey Pavlov <alexpux@gmail.com>
|
|
+ Ray Donnelly <mingw.android@gmail.com>
|
|
+ Johannes Schindelin <johannes.schindelin@gmx.de>
|
|
+
|
|
+*/
|
|
+
|
|
+#ifndef PATH_CONV_H_DB4IQBH3
|
|
+#define PATH_CONV_H_DB4IQBH3
|
|
+
|
|
+#include <stdlib.h>
|
|
+
|
|
+const char* convert(char *dst, size_t dstlen, const char *src);
|
|
+
|
|
+#endif /* end of include guard: PATH_CONV_H_DB4IQBH3 */
|
|
+
|
|
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
|
|
index 4da8884..bfc916a 100644
|
|
--- a/winsup/cygwin/path.cc
|
|
+++ b/winsup/cygwin/path.cc
|
|
@@ -66,6 +66,7 @@
|
|
#include "shared_info.h"
|
|
#include "tls_pbuf.h"
|
|
#include "environ.h"
|
|
+#include "msys2_path_conv.h"
|
|
#undef basename
|
|
|
|
suffix_info stat_suffixes[] =
|
|
@@ -3422,6 +3423,74 @@ fchdir (int fd)
|
|
return res;
|
|
}
|
|
|
|
+//
|
|
+// Important: If returned pointer == arg, then this function
|
|
+// did not malloc that pointer; otherwise free it.
|
|
+//
|
|
+extern "C" char *
|
|
+arg_heuristic_with_exclusions (char const * const arg, char const * exclusions, size_t exclusions_count)
|
|
+{
|
|
+ char *arg_result;
|
|
+
|
|
+ // Must return something ..
|
|
+ size_t arglen = (arg ? strlen (arg): 0);
|
|
+
|
|
+ if (arglen == 0 || !arg)
|
|
+ {
|
|
+ arg_result = (char *)malloc (sizeof (char));
|
|
+ arg_result[0] = '\0';
|
|
+ return arg_result;
|
|
+ }
|
|
+
|
|
+ debug_printf("Input value: (%s)", arg);
|
|
+ for (size_t excl = 0; excl < exclusions_count; ++excl)
|
|
+ {
|
|
+ /* Since we've got regex linked we should maybe switch to that, but
|
|
+ running regexes for every argument could be too slow. */
|
|
+ if ( strcmp (exclusions, "*") == 0 || (strlen (exclusions) && strstr (arg, exclusions) == arg) )
|
|
+ return (char*)arg;
|
|
+ exclusions += strlen (exclusions) + 1;
|
|
+ }
|
|
+
|
|
+ // Leave enough room for at least 16 path elements; we might be converting
|
|
+ // a path list.
|
|
+ size_t stack_len = arglen + 16 * MAX_PATH;
|
|
+ char * stack_path = (char *)malloc (stack_len);
|
|
+ if (!stack_path)
|
|
+ {
|
|
+ debug_printf ("out of stack space?");
|
|
+ return (char *)arg;
|
|
+ }
|
|
+ memset (stack_path, 0, MAX_PATH);
|
|
+ convert (stack_path, stack_len - 1, arg);
|
|
+ debug_printf ("convert()'ed: %s (length %d)\n.....->: %s", arg, arglen, stack_path);
|
|
+ // Don't allocate memory if no conversion happened.
|
|
+ if (!strcmp (arg, stack_path))
|
|
+ {
|
|
+ if (arg != stack_path)
|
|
+ {
|
|
+ free (stack_path);
|
|
+ }
|
|
+ return ((char *)arg);
|
|
+ }
|
|
+ arg_result = (char *)realloc (stack_path, strlen (stack_path)+1);
|
|
+ // Windows doesn't like empty entries in PATH env. variables (;;)
|
|
+ char* semisemi = strstr(arg_result, ";;");
|
|
+ while (semisemi)
|
|
+ {
|
|
+ memmove(semisemi, semisemi+1, strlen(semisemi));
|
|
+ semisemi = strstr(semisemi, ";;");
|
|
+ }
|
|
+ return arg_result;
|
|
+}
|
|
+
|
|
+extern "C" char *
|
|
+arg_heuristic (char const * const arg)
|
|
+{
|
|
+ return arg_heuristic_with_exclusions (arg, NULL, 0);
|
|
+}
|
|
+
|
|
+
|
|
/******************** Exported Path Routines *********************/
|
|
|
|
/* Cover functions to the path conversion routines.
|
|
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
|
|
index 3e8c836..cb83a37 100644
|
|
--- a/winsup/cygwin/spawn.cc
|
|
+++ b/winsup/cygwin/spawn.cc
|
|
@@ -277,6 +277,27 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|
}
|
|
}
|
|
|
|
+ /* Environment variable MSYS2_ARG_CONV_EXCL contains a list
|
|
+ of ';' separated argument prefixes to pass un-modified..
|
|
+ It isn't applied to env. variables; only spawn arguments.
|
|
+ A value of * means don't convert any arguments. */
|
|
+ char* msys2_arg_conv_excl_env = getenv("MSYS2_ARG_CONV_EXCL");
|
|
+ char* msys2_arg_conv_excl = NULL;
|
|
+ size_t msys2_arg_conv_excl_count = 0;
|
|
+ if (msys2_arg_conv_excl_env)
|
|
+ {
|
|
+ msys2_arg_conv_excl = (char*)alloca (strlen(msys2_arg_conv_excl_env)+1);
|
|
+ strcpy (msys2_arg_conv_excl, msys2_arg_conv_excl_env);
|
|
+ msys2_arg_conv_excl_count = 1;
|
|
+ msys2_arg_conv_excl_env = strchr ( msys2_arg_conv_excl, ';' );
|
|
+ while (msys2_arg_conv_excl_env)
|
|
+ {
|
|
+ *msys2_arg_conv_excl_env = '\0';
|
|
+ ++msys2_arg_conv_excl_count;
|
|
+ msys2_arg_conv_excl_env = strchr ( msys2_arg_conv_excl_env + 1, ';' );
|
|
+ }
|
|
+ }
|
|
+
|
|
/* Check if we have been called from exec{lv}p or spawn{lv}p and mask
|
|
mode to keep only the spawn mode. */
|
|
bool p_type_exec = !!(mode & _P_PATH_TYPE_EXEC);
|
|
@@ -386,12 +407,26 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|
moreinfo->argc = newargv.argc;
|
|
moreinfo->argv = newargv;
|
|
}
|
|
- if ((wincmdln || !real_path.iscygexec ())
|
|
- && !cmd.fromargv (newargv, real_path.get_win32 (),
|
|
- real_path.iscygexec ()))
|
|
+ else
|
|
{
|
|
- res = -1;
|
|
- __leave;
|
|
+ for (int i = 0; i < newargv.argc; i++)
|
|
+ {
|
|
+ //convert argv to win32
|
|
+ int newargvlen = strlen (newargv[i]);
|
|
+ char *tmpbuf = (char *)malloc (newargvlen + 1);
|
|
+ memcpy (tmpbuf, newargv[i], newargvlen + 1);
|
|
+ tmpbuf = arg_heuristic_with_exclusions(tmpbuf, msys2_arg_conv_excl, msys2_arg_conv_excl_count);
|
|
+ debug_printf("newargv[%d] = %s", i, newargv[i]);
|
|
+ newargv.replace (i, tmpbuf);
|
|
+ free (tmpbuf);
|
|
+ }
|
|
+ if ((wincmdln || !real_path.iscygexec ())
|
|
+ && !cmd.fromargv (newargv, real_path.get_win32 (),
|
|
+ real_path.iscygexec ()))
|
|
+ {
|
|
+ res = -1;
|
|
+ __leave;
|
|
+ }
|
|
}
|
|
|
|
|
|
@@ -515,7 +550,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|
moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
|
|
real_path.iscygexec (),
|
|
switch_user ? ::cygheap->user.primary_token ()
|
|
- : NULL);
|
|
+ : NULL,
|
|
+ real_path.iscygexec ());
|
|
if (!moreinfo->envp || !envblock)
|
|
{
|
|
set_errno (E2BIG);
|
|
diff --git a/winsup/cygwin/winf.h b/winsup/cygwin/winf.h
|
|
index e3a65f8..1aeec8d 100644
|
|
--- a/winsup/cygwin/winf.h
|
|
+++ b/winsup/cygwin/winf.h
|
|
@@ -51,6 +51,10 @@ class av
|
|
calloced = 1;
|
|
}
|
|
}
|
|
+ void replace (int i, const char *arg)
|
|
+ {
|
|
+ argv[i] = cstrdup1 (arg);
|
|
+ }
|
|
void dup_all ()
|
|
{
|
|
for (int i = calloced; i < argc; i++)
|
|
--
|
|
2.26.2
|
|
|