1339 lines
44 KiB
Diff
1339 lines
44 KiB
Diff
From a31d0894a73d39935efa830e88ef8bb9dce9785b Mon Sep 17 00:00:00 2001
|
|
From: Alexpux <alexey.pawlow@gmail.com>
|
|
Date: Tue, 16 Sep 2014 22:01:33 +0400
|
|
Subject: [PATCH] Replace old MSYS1 path's convert procedure with newly writed.
|
|
|
|
---
|
|
winsup/cygwin/Makefile.in | 4 +-
|
|
winsup/cygwin/msys2_path_conv.cc | 607 +++++++++++++++++++++++++++++++++++++++
|
|
winsup/cygwin/msys2_path_conv.h | 146 ++++++++++
|
|
winsup/cygwin/path.cc | 492 ++------------------------------
|
|
4 files changed, 780 insertions(+), 465 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 5567e8e..6d22635 100644
|
|
--- a/winsup/cygwin/Makefile.in
|
|
+++ b/winsup/cygwin/Makefile.in
|
|
@@ -169,8 +169,8 @@ DLL_OFILES:=advapi32.o arc4random.o assert.o autoload.o base64.o bsdlib.o ctype.
|
|
glob_pattern_p.o globals.o grp.o heap.o hookapi.o inet_addr.o \
|
|
inet_network.o init.o ioctl.o ipc.o kernel32.o ldap.o libstdcxx_wrapper.o \
|
|
localtime.o lsearch.o malloc_wrapper.o minires-os-if.o minires.o \
|
|
- miscfuncs.o mktemp.o mmap.o msg.o mount.o net.o netdb.o nfs.o nftw.o \
|
|
- nlsfuncs.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o posix_ipc.o \
|
|
+ miscfuncs.o mktemp.o mmap.o msg.o msys2_path_conv.o mount.o net.o netdb.o nfs.o \
|
|
+ nftw.o nlsfuncs.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o posix_ipc.o \
|
|
pseudo-reloc.o pthread.o random.o regcomp.o regerror.o regexec.o regfree.o \
|
|
registry.o resource.o rexec.o rcmd.o scandir.o sched.o sec_acl.o \
|
|
sec_auth.o sec_helper.o security.o select.o sem.o setlsapwd.o shared.o \
|
|
diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc
|
|
new file mode 100644
|
|
index 0000000..549a42e
|
|
--- /dev/null
|
|
+++ b/winsup/cygwin/msys2_path_conv.cc
|
|
@@ -0,0 +1,614 @@
|
|
+/*
|
|
+ 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>
|
|
+
|
|
+*/
|
|
+
|
|
+#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** to, int* in_string) {
|
|
+ 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(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 == '"' || *it == '\'') {
|
|
+ need_convert = false;
|
|
+ break;
|
|
+ }
|
|
+ if (*it == '\\' || *it == '/') {
|
|
+ need_convert = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ char* dstit = dst;
|
|
+ char* dstend = dst + dstlen;
|
|
+ if (!need_convert) {
|
|
+ copy_to_dst(src, NULL, &dstit, dstend);
|
|
+ *dstit = '\0';
|
|
+ return dst;
|
|
+ }
|
|
+
|
|
+ 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;
|
|
+ }*/
|
|
+ }
|
|
+
|
|
+ sub_convert(&srcbeg, &srcit, &dstit, dstend, &in_string);
|
|
+
|
|
+ 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 (!isalpha(*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) == '/')) {
|
|
+ return RELATIVE_PATH;
|
|
+ }
|
|
+
|
|
+ if (*it == '/') {
|
|
+ it += 1;
|
|
+
|
|
+ if (isalpha(*it) && *(it + 1) == ':') {
|
|
+ return ESCAPE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if (*it == '.' && *(it + 1) == '.') {
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ int double_slashed = 0;
|
|
+ if (*it == '/') {
|
|
+ double_slashed = 1;
|
|
+ it += 1;
|
|
+ }
|
|
+
|
|
+ if (double_slashed && *it == ':') {
|
|
+ return URL;
|
|
+ }
|
|
+
|
|
+ if (double_slashed && *it == '/') {
|
|
+ return ESCAPE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ for (; *it != '\0' && it != end; ++it) {
|
|
+ switch(*it) {
|
|
+ case ':': {char ch = *(it + 1); if (ch == '/' || ch == ':' || ch == '.') return POSIX_PATH_LIST;}
|
|
+ case '/': result = (double_slashed) ? UNC : ROOTED_PATH; break;
|
|
+ case ';': return WINDOWS_PATH_LIST;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (result != NONE) {
|
|
+ return result;
|
|
+ }
|
|
+
|
|
+ return (double_slashed) ? ESCAPED_PATH : ROOTED_PATH;
|
|
+ }
|
|
+
|
|
+ int starts_with_minus = (*it == '-');
|
|
+
|
|
+ if (starts_with_minus) {
|
|
+ char n1 = *(it + 1);
|
|
+ char n2 = n1 ? *(it + 2) : '\0';
|
|
+ char n3 = n2 ? *(it + 3) : '\0';
|
|
+ char n4 = n3 ? *(it + 4) : '\0';
|
|
+ char n5 = n4 ? *(it + 5) : '\0';
|
|
+
|
|
+ if (isalpha(n1) && n2 == '/') {
|
|
+ it += 2;
|
|
+ result = ROOTED_PATH;
|
|
+ } else if ((n2 == '\'' || n2 == '"') && n3 == '/') {
|
|
+ it += 3;
|
|
+ result = ROOTED_PATH;
|
|
+ }
|
|
+
|
|
+ if (isalpha(n2) && n3 == ':' && n4 == '/') {
|
|
+ *src = it + 2;
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+
|
|
+ if ((n2 == '\'' || n2 == '"') && isalpha(n3) && n4 == ':' && n5 == '/') {
|
|
+ *src = it + 3;
|
|
+ return SIMPLE_WINDOWS_PATH;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (const char* it2 = it; *it2 != '\0' && it2 != end; ++it2) {
|
|
+ char ch = *it2;
|
|
+ if (ch == '=') {
|
|
+ *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;
|
|
+ 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 (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 = 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* 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) == '/') {
|
|
+ is_url = 1;
|
|
+ continue;
|
|
+ }
|
|
+ prev_was_simc = 1;
|
|
+ subp_convert(&beg, it, is_url, dst, dstend);
|
|
+ is_url = 0;
|
|
+
|
|
+ **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..e1e5e87
|
|
--- /dev/null
|
|
+++ b/winsup/cygwin/msys2_path_conv.h
|
|
@@ -0,0 +1,146 @@
|
|
+/*
|
|
+ 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>
|
|
+
|
|
+*/
|
|
+
|
|
+#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 be08707..fd635cf 100644
|
|
--- a/winsup/cygwin/path.cc
|
|
+++ b/winsup/cygwin/path.cc
|
|
@@ -65,6 +65,7 @@
|
|
#include "cygtls.h"
|
|
#include "tls_pbuf.h"
|
|
#include "environ.h"
|
|
+#include "msys2_path_conv.h"
|
|
#include <assert.h>
|
|
#include <ntdll.h>
|
|
#include <wchar.h>
|
|
@@ -3398,84 +3399,26 @@ fchdir (int fd)
|
|
return res;
|
|
}
|
|
|
|
-static bool
|
|
-isabswinpath (const char * path)
|
|
-{
|
|
- int plen = strlen (path);
|
|
- bool p0alpha = isalpha (path[0]) != 0;
|
|
- bool p1colon = (plen > 1 && path[1] == ':');
|
|
- bool rval =
|
|
- ( ((plen == 2) && p0alpha && p1colon)
|
|
- || ( (plen > 2)
|
|
- && p0alpha
|
|
- && p1colon
|
|
- && (strchr (&path[2], ':') == (char *)NULL)
|
|
- )
|
|
- || ( plen > 3
|
|
- && path[0] == '\\'
|
|
- && path[1] == '\\'
|
|
- && path[3] == '\\'
|
|
- )
|
|
- );
|
|
- return rval;
|
|
-}
|
|
-
|
|
-static char *
|
|
-ScrubRetpath (char * const retpath)
|
|
-{
|
|
- char * sspath = (char *)retpath;
|
|
- //
|
|
- // Check for null path because Win32 doesn't like them.
|
|
- // I.E.: Path lists of c:/foo;;c:/bar need changed to
|
|
- // c:/foo;c:/bar.
|
|
- //
|
|
- // This need be executed only if we actually converted the path.
|
|
- //
|
|
- while (*sspath)
|
|
- {
|
|
- if (*sspath == ';' && sspath[1] == ';')
|
|
- for (char *i = sspath; *i; i++)
|
|
- *i = *(i + 1);
|
|
- else
|
|
- sspath++;
|
|
- }
|
|
- if (*(sspath - 1) == ';')
|
|
- *(sspath - 1) = '\0';
|
|
-
|
|
- //
|
|
- // If we modified the path then convert all / to \ if we have a path list
|
|
- // else convert all \ to /.
|
|
- //
|
|
- if ((strchr (retpath, ';')))
|
|
- {
|
|
- backslashify (retpath, retpath, 0);
|
|
- } else
|
|
- {
|
|
- slashify (retpath, retpath, 0);
|
|
- }
|
|
- debug_printf("returning: %s", retpath);
|
|
- return retpath;
|
|
-}
|
|
-
|
|
//
|
|
-// The returned pointer should be freed with free unless,
|
|
-// as it turns out, it is equal to the input pointer.
|
|
+// 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;
|
|
|
|
- int arglen = (arg ? strlen (arg): 0);
|
|
+ // Must return something ..
|
|
+ size_t arglen = (arg ? strlen (arg): 0);
|
|
|
|
- if (arglen == 0)
|
|
+ if (arglen == 0 || !arg)
|
|
{
|
|
- char *retpath = (char *)malloc (sizeof (char));
|
|
- memset (retpath, 0, sizeof (char));
|
|
- return retpath;
|
|
+ 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)
|
|
{
|
|
if ( strstr (arg, exclusions) == arg )
|
|
@@ -3483,408 +3426,31 @@ arg_heuristic_with_exclusions (char const * const arg, char const * exclusions,
|
|
exclusions += strlen (exclusions) + 1;
|
|
}
|
|
|
|
- //
|
|
- // copy of the path string that we can overwrite
|
|
- //
|
|
- char *spath = (char *)alloca (arglen + 1);
|
|
- memcpy (spath, arg, arglen + 1);
|
|
-
|
|
- char * sspath;
|
|
-
|
|
- //
|
|
- // retpath contains the converted path string to be returned
|
|
- //
|
|
- char *retpath = (char *)malloc(((MAX_PATH - arglen) > 0) ?
|
|
- MAX_PATH : arglen + MAX_PATH);
|
|
- memset (retpath, 0, MAX_PATH);
|
|
- int retpath_len = 0;
|
|
- int retpath_buflen = MAX_PATH;
|
|
-
|
|
-#define retpathcat(retstr) \
|
|
- retpath_len += strlen(retstr); \
|
|
- if (retpath_buflen <= retpath_len) \
|
|
- { \
|
|
- retpath_buflen = ((retpath_buflen * 2 <= retpath_len) ? \
|
|
- retpath_len + 1 : retpath_buflen * 2); \
|
|
- retpath = (char *)realloc (retpath, retpath_buflen); \
|
|
- } \
|
|
- strcat (retpath, retstr);
|
|
-
|
|
-#define retpathcpy(retstr) \
|
|
- retpath_len = strlen (retstr); \
|
|
- *retpath = '\0'; \
|
|
- if (retpath_buflen <= retpath_len ) \
|
|
- { \
|
|
- retpath_buflen = ((retpath_buflen * 2 <= retpath_len) ? \
|
|
- retpath_len + 1 : retpath_buflen * 2); \
|
|
- retpath = (char *)realloc (retpath, retpath_buflen); \
|
|
- } \
|
|
- strcpy (retpath, retstr);
|
|
-
|
|
- //
|
|
- // Just return win32 paths and path lists.
|
|
- //
|
|
- if (isabswinpath (arg)
|
|
- || (strchr (arg, ';') > 0)
|
|
- )
|
|
- {
|
|
- debug_printf("returning Win32 absolute path: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- //
|
|
- // Multiple forward slashes are treated special,
|
|
- // Remove one and return for the form of //foo or ///bar
|
|
- // but just return for the form of //server/share.
|
|
- //
|
|
- else if (arg[0] == '/' && arg[1] == '/')
|
|
+ size_t stack_len = arglen + MAX_PATH;
|
|
+ char * stack_path = (char *)malloc (stack_len);
|
|
+ memset (stack_path, 0, MAX_PATH);
|
|
+ if (!stack_len)
|
|
{
|
|
- int tidx = 2;
|
|
- while (spath[tidx] && spath[tidx] == '/')
|
|
- tidx++;
|
|
- if (strchr (&spath[tidx], '/'))
|
|
- {
|
|
- retpathcpy (spath);
|
|
- }
|
|
- else
|
|
- {
|
|
- retpathcpy (&spath[1]);
|
|
- }
|
|
- return ScrubRetpath (retpath);
|
|
+ debug_printf ("out of stack space?");
|
|
+ return (char *)arg;
|
|
}
|
|
- //
|
|
- // special case confusion elimination
|
|
- // Translate a path that looks similar to /c: to c:/.
|
|
- //
|
|
- else if (arg[0] == '/' && isabswinpath (arg + 1))
|
|
+ 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))
|
|
{
|
|
- retpathcpy (&arg[1]);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- //
|
|
- // Check for variable set.
|
|
- //
|
|
- else if ((sspath = strchr(spath, '=')) && isalpha (spath[0]))
|
|
- {
|
|
- if (isabswinpath (sspath + 1)) {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- char *swin32_path = arg_heuristic(sspath + 1);
|
|
- if (swin32_path == (sspath + 1)) {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- *sspath = '\0';
|
|
- retpathcpy (spath);
|
|
- retpathcat ("=");
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- //
|
|
- // Check for paths after commas, if string begins with a '-' character.
|
|
- //
|
|
- else if ((sspath = strchr(spath, ',')) && spath[0] == '-')
|
|
- {
|
|
- if (isabswinpath (sspath + 1)) {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- char *swin32_path = arg_heuristic(sspath + 1);
|
|
- if (swin32_path == (sspath + 1)) {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- *sspath = '\0';
|
|
- retpathcpy (spath);
|
|
- retpathcat (",");
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- //
|
|
- // Check for POSIX path lists.
|
|
- // But we have to allow processing of quoted strings and switches first
|
|
- // which uses recursion so this code will be seen again.
|
|
- //
|
|
- else
|
|
- {
|
|
- sspath = strchr (spath, ':');
|
|
- //
|
|
- // Prevent http://some.string/ from being modified.
|
|
- //
|
|
- if ((sspath > 0 && strlen (sspath) > 2)
|
|
- && (sspath[1] == '/')
|
|
- && (sspath[2] == '/')
|
|
- )
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- else
|
|
- if ((sspath > 0)
|
|
- && (strchr (spath, '/') > 0)
|
|
- //
|
|
- // Prevent strings beginning with -, ", ', or @ from being processed,
|
|
- // remember that this is a recursive routine.
|
|
- //
|
|
- && (strchr ("-\"\'@", spath[0]) == 0)
|
|
- //
|
|
- // Prevent ``foo:echo /bar/baz'' from being considered a path list.
|
|
- //
|
|
- && (strlen (sspath) > 1 && strchr (":./", sspath[1]) > 0)
|
|
- )
|
|
- {
|
|
- //
|
|
- // Yes, convert to Win32 path list.
|
|
- //
|
|
- while (sspath)
|
|
- {
|
|
- *sspath = '\0';
|
|
- char *swin32_path = arg_heuristic (spath);
|
|
- //
|
|
- // Just ignore sret; swin32_path has the value we need.
|
|
- //
|
|
- retpathcat (swin32_path);
|
|
- if (swin32_path != spath)
|
|
- free (swin32_path);
|
|
- spath = sspath + 1;
|
|
- sspath = strchr (spath, ':');
|
|
- retpathcat (";");
|
|
- //
|
|
- // Handle the last path in the list.
|
|
- //
|
|
- if (!sspath)
|
|
- {
|
|
- char *swin32_path = arg_heuristic (spath);
|
|
- retpathcat (swin32_path);
|
|
- if (swin32_path != spath)
|
|
- free (swin32_path);
|
|
- }
|
|
- }
|
|
- return ScrubRetpath (retpath);
|
|
+ return ((char *)arg);
|
|
}
|
|
- else
|
|
+ arg_result = (char *)malloc (strlen (stack_path)+1);
|
|
+ strcpy (arg_result, stack_path);
|
|
+ // Windows doesn't like empty entries in PATH env. variables (;;)
|
|
+ char* semisemi = strstr(arg_result, ";;");
|
|
+ while (semisemi)
|
|
{
|
|
- switch (spath[0])
|
|
- {
|
|
- case '/':
|
|
- //
|
|
- // Just a normal POSIX path.
|
|
- //
|
|
- {
|
|
- //
|
|
- // Convert only up to a ".." path component, and
|
|
- // keep all what follows as is.
|
|
- //
|
|
- sspath = strstr (spath, "/..");
|
|
- if (sspath)
|
|
- {
|
|
- *sspath = '\0';
|
|
- char *swin32_path = arg_heuristic (spath);
|
|
- if (swin32_path == spath)
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcpy (swin32_path);
|
|
- retpathcat ("/");
|
|
- retpathcat (sspath+1);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- if (strcmp(spath, "/dev/null") == 0)
|
|
- {
|
|
- retpathcpy("nul");
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- path_conv p (spath, 0);
|
|
- if (p.error)
|
|
- {
|
|
- set_errno(p.error);
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcpy (p.get_win32 ());
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- case '-':
|
|
- //
|
|
- // here we check for POSIX paths as attributes to a POSIX switch.
|
|
- //
|
|
- sspath = strchr (spath, '=');
|
|
- if (sspath)
|
|
- {
|
|
- //
|
|
- // just use recursion if we find a set variable token.
|
|
- //
|
|
- *sspath = '\0';
|
|
- if (isabswinpath (sspath + 1)) {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- char *swin32_path = arg_heuristic(sspath + 1);
|
|
- if (swin32_path == sspath + 1)
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcpy (spath);
|
|
- retpathcat ("=");
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- else
|
|
- {
|
|
- //
|
|
- // Check for single letter option with a
|
|
- // path argument attached, eg -I/include */
|
|
- //
|
|
- if (spath[1] && spath[2] == '/')
|
|
- {
|
|
- debug_printf("spath = %s", spath);
|
|
- sspath = spath + 2;
|
|
- char *swin32_path = arg_heuristic (sspath);
|
|
- if (swin32_path == sspath)
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- sspath = (char *)spath;
|
|
- sspath++;
|
|
- sspath++;
|
|
- *sspath = '\0';
|
|
- retpathcpy (spath);
|
|
- *sspath = '/';
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- else
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- }
|
|
- break;
|
|
- case '@':
|
|
- //
|
|
- // here we check for POSIX paths as attributes to a response
|
|
- // file argument (@file). This is specifically to support
|
|
- // MinGW binutils and gcc.
|
|
- //
|
|
- sspath = spath + 1;
|
|
- if (isabswinpath (sspath))
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return (char *)arg;
|
|
- }
|
|
- if (spath[1] == '/')
|
|
- {
|
|
- debug_printf("spath = %s", spath);
|
|
- char *swin32_path = arg_heuristic (sspath);
|
|
- if (swin32_path == sspath)
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- sspath = (char *)spath;
|
|
- sspath++;
|
|
- *sspath = '\0';
|
|
- retpathcpy (spath);
|
|
- *sspath = '/';
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- else
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- break;
|
|
- case '"':
|
|
- //
|
|
- // Handle a double quote case.
|
|
- //
|
|
- debug_printf ("spath: %s", spath);
|
|
- if (spath[1] == '/')
|
|
- {
|
|
- retpathcpy ("\"");
|
|
- char *tpath = strchr(&spath[1], '"');
|
|
- if (tpath)
|
|
- *tpath = (char)NULL;
|
|
- char *swin32_path = arg_heuristic (&spath[1]);
|
|
- if (swin32_path == &spath[1])
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- if (tpath)
|
|
- retpathcat ("\"");
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- case '\'':
|
|
- //
|
|
- // Handle a single quote case.
|
|
- //
|
|
- debug_printf ("spath: %s", spath);
|
|
- if (spath[1] == '/')
|
|
- {
|
|
- retpathcpy ("'");
|
|
- char *tpath = strchr(&spath[1], '\'');
|
|
- if (tpath)
|
|
- *tpath = (char)NULL;
|
|
- char *swin32_path = arg_heuristic (&spath[1]);
|
|
- if (swin32_path == &spath[1])
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- if (tpath)
|
|
- retpathcat ("'");
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- default:
|
|
- //
|
|
- // This takes care of variable_foo=/bar/baz
|
|
- //
|
|
- if ((sspath = strchr(spath, '=')) && (sspath[1] == '/'))
|
|
- {
|
|
- sspath[1] = '\0';
|
|
- retpathcpy (spath);
|
|
- sspath[1] = '/';
|
|
- char *swin32_path = arg_heuristic (&sspath[1]);
|
|
- if (swin32_path == &sspath[1])
|
|
- {
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- retpathcat (swin32_path);
|
|
- free (swin32_path);
|
|
- return ScrubRetpath (retpath);
|
|
- }
|
|
- //
|
|
- // Oh well, nothing special found, set win32_path same as path.
|
|
- //
|
|
- debug_printf("returning: %s", arg);
|
|
- return ((char *)arg);
|
|
- }
|
|
- }
|
|
+ memmove(semisemi, semisemi+1, strlen(semisemi));
|
|
+ semisemi = strstr(semisemi, ";;");
|
|
}
|
|
- // I should not get to this point.
|
|
- assert (false);
|
|
- debug_printf("returning: %s", arg);
|
|
- return ScrubRetpath (retpath);
|
|
+ return arg_result;
|
|
}
|
|
|
|
extern "C" char *
|
|
--
|
|
2.0.3
|
|
|