Files
MSYS2-packages/msys2-runtime/0003-Add-msys2_path_conv.patch

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