This corresponds to https://github.com/msys2/msys2-runtime/pull/71. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1101 lines
40 KiB
Diff
1101 lines
40 KiB
Diff
From 35991fee287d1c40bc50857e943f6eb1b6ed9372 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 04/N] Add functionality for converting UNIX paths in
|
|
arguments and environment variables to Windows form for native Win32
|
|
applications.
|
|
|
|
---
|
|
winsup/cygwin/Makefile.am | 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 | 42 +-
|
|
winsup/cygwin/winf.h | 4 +
|
|
10 files changed, 932 insertions(+), 6 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.am b/winsup/cygwin/Makefile.am
|
|
index 6a53049..f10b1b5 100644
|
|
--- a/winsup/cygwin/Makefile.am
|
|
+++ b/winsup/cygwin/Makefile.am
|
|
@@ -283,6 +283,7 @@ DLL_FILES= \
|
|
mmap.cc \
|
|
mmap_alloc.cc \
|
|
msg.cc \
|
|
+ msys2_path_conv.cc \
|
|
mount.cc \
|
|
net.cc \
|
|
netdb.cc \
|
|
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
|
|
index 03f8277..8ad1026 100644
|
|
--- a/winsup/cygwin/environ.cc
|
|
+++ b/winsup/cygwin/environ.cc
|
|
@@ -1058,7 +1058,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;
|
|
@@ -1151,6 +1151,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)))
|
|
@@ -1271,6 +1284,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 74413a8..6adf620 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..f9dcda5
|
|
--- /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;} return WINDOWS_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 baf04ce..5a3aa9b 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[] =
|
|
@@ -3768,6 +3769,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 e160fa3..63c5d24 100644
|
|
--- a/winsup/cygwin/spawn.cc
|
|
+++ b/winsup/cygwin/spawn.cc
|
|
@@ -295,6 +295,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);
|
|
@@ -404,9 +425,23 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
|
moreinfo->argc = newargv.argc;
|
|
moreinfo->argv = newargv;
|
|
}
|
|
+ else
|
|
+ {
|
|
+ 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 ()))
|
|
+ && !cmd.fromargv (newargv, real_path.get_win32 (),
|
|
+ real_path.iscygexec ()))
|
|
{
|
|
res = -1;
|
|
__leave;
|
|
@@ -540,7 +575,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.33.0
|
|
|