VirtualBox

source: kBuild/trunk/src/kmk/w32/pathstuff.c@ 2454

Last change on this file since 2454 was 2454, checked in by bird, 14 years ago

kmk: Applied r1.13 to w32/pathstuff.c, fixing crash if PATH ends with a quote. Fixes #93.

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1/* Path conversion for Windows pathnames.
2Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
32007, 2009 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify it under the
7terms of the GNU General Public License as published by the Free Software
8Foundation; either version 3 of the License, or (at your option) any later
9version.
10
11GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#include <Windows.h> /* bird */
19#include <stdio.h> /* bird */
20#include <string.h>
21#include <stdlib.h>
22#include "make.h"
23#include "pathstuff.h"
24
25/*
26 * Convert delimiter separated vpath to Canonical format.
27 */
28char *
29convert_vpath_to_windows32(char *Path, char to_delim)
30{
31 char *etok; /* token separator for old Path */
32
33 /*
34 * Convert all spaces to delimiters. Note that pathnames which
35 * contain blanks get trounced here. Use 8.3 format as a workaround.
36 */
37 for (etok = Path; etok && *etok; etok++)
38 if (isblank ((unsigned char) *etok))
39 *etok = to_delim;
40
41 return (convert_Path_to_windows32(Path, to_delim));
42}
43
44/*
45 * Convert delimiter separated path to Canonical format.
46 */
47char *
48convert_Path_to_windows32(char *Path, char to_delim)
49{
50 char *etok; /* token separator for old Path */
51 char *p; /* points to element of old Path */
52
53 /* is this a multi-element Path ? */
54 /* FIXME: Perhaps use ":;\"" in strpbrk to convert all quotes to
55 delimiters as well, as a way to handle quoted directories in
56 PATH? */
57 for (p = Path, etok = strpbrk(p, ":;");
58 etok;
59 etok = strpbrk(p, ":;"))
60 if ((etok - p) == 1) {
61 if (*(etok - 1) == ';' ||
62 *(etok - 1) == ':') {
63 etok[-1] = to_delim;
64 etok[0] = to_delim;
65 p = ++etok;
66 continue; /* ignore empty bucket */
67 } else if (!isalpha ((unsigned char) *p)) {
68 /* found one to count, handle things like '.' */
69 *etok = to_delim;
70 p = ++etok;
71 } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) {
72 /* found one to count, handle drive letter */
73 *etok = to_delim;
74 p = ++etok;
75 } else
76 /* all finished, force abort */
77 p += strlen(p);
78 } else if (*p == '"') { /* a quoted directory */
79 for (p++; *p && *p != '"'; p++) /* skip quoted part */
80 ;
81 etok = strpbrk(p, ":;"); /* find next delimiter */
82 if (etok) {
83 *etok = to_delim;
84 p = ++etok;
85 } else
86 p += strlen(p);
87 } else {
88 /* found another one, no drive letter */
89 *etok = to_delim;
90 p = ++etok;
91 }
92
93 return Path;
94}
95
96#if 1 /* bird */
97extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
98#endif
99
100/*
101 * Convert to forward slashes. Resolve to full pathname optionally
102 */
103char *
104w32ify(const char *filename, int resolve)
105{
106 static char w32_path[FILENAME_MAX];
107 char *p;
108
109#if 1 /* bird */
110 if (resolve) {
111 nt_fullpath(filename, w32_path, sizeof(w32_path));
112 } else {
113 w32_path[0] = '\0';
114 strncat(w32_path, filename, sizeof(w32_path));
115 }
116#else /* !bird */
117 if (resolve) {
118 _fullpath(w32_path, filename, sizeof (w32_path));
119 } else
120 strncpy(w32_path, filename, sizeof (w32_path));
121#endif /* !bird */
122
123 for (p = w32_path; p && *p; p++)
124 if (*p == '\\')
125 *p = '/';
126
127 return w32_path;
128}
129
130char *
131getcwd_fs(char* buf, int len)
132{
133 char *p = getcwd(buf, len);
134
135 if (p) {
136 char *q = w32ify(buf, 0);
137#if 1 /* bird */
138 buf[0] = '\0';
139 strncat(buf, q, len);
140#else /* !bird */
141 strncpy(buf, q, len);
142#endif /* !bird */
143 }
144
145 return p;
146}
147
148#undef stat
149/*
150 * Workaround for directory names with trailing slashes.
151 * Added by bird reasons stated.
152 */
153int
154my_stat(const char *path, struct stat *st)
155{
156 int rc = stat(path, st);
157 if ( rc != 0
158 && errno == ENOENT
159 && *path != '\0')
160 {
161 char *slash = strchr(path, '\0') - 1;
162 if (*slash == '/' || *slash == '\\')
163 {
164 size_t len_path = slash - path + 1;
165 char *tmp = alloca(len_path + 4);
166 memcpy(tmp, path, len_path);
167 tmp[len_path] = '.';
168 tmp[len_path + 1] = '\0';
169 errno = 0;
170 rc = stat(tmp, st);
171 if ( rc == 0
172 && !S_ISDIR(st->st_mode))
173 {
174 errno = ENOTDIR;
175 rc = -1;
176 }
177 }
178 }
179#ifdef KMK_PRF
180 {
181 int err = errno;
182 fprintf(stderr, "stat(%s,) -> %d/%d\n", path, rc, errno);
183 errno = err;
184 }
185#endif
186 return rc;
187}
188
189#ifdef unused
190/*
191 * Convert delimiter separated pathnames (e.g. PATH) or single file pathname
192 * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that
193 * _NutPathToNutc() fails to convert, just return the path we were handed
194 * and assume the caller will know what to do with it (It was probably
195 * a mistake to try and convert it anyway due to some of the bizarre things
196 * that might look like pathnames in makefiles).
197 */
198char *
199convert_path_to_nutc(char *path)
200{
201 int count; /* count of path elements */
202 char *nutc_path; /* new NutC path */
203 int nutc_path_len; /* length of buffer to allocate for new path */
204 char *pathp; /* pointer to nutc_path used to build it */
205 char *etok; /* token separator for old path */
206 char *p; /* points to element of old path */
207 char sep; /* what flavor of separator used in old path */
208 char *rval;
209
210 /* is this a multi-element path ? */
211 for (p = path, etok = strpbrk(p, ":;"), count = 0;
212 etok;
213 etok = strpbrk(p, ":;"))
214 if ((etok - p) == 1) {
215 if (*(etok - 1) == ';' ||
216 *(etok - 1) == ':') {
217 p = ++etok;
218 continue; /* ignore empty bucket */
219 } else if (etok = strpbrk(etok+1, ":;"))
220 /* found one to count, handle drive letter */
221 p = ++etok, count++;
222 else
223 /* all finished, force abort */
224 p += strlen(p);
225 } else
226 /* found another one, no drive letter */
227 p = ++etok, count++;
228
229 if (count) {
230 count++; /* x1;x2;x3 <- need to count x3 */
231
232 /*
233 * Hazard a guess on how big the buffer needs to be.
234 * We have to convert things like c:/foo to /c=/foo.
235 */
236 nutc_path_len = strlen(path) + (count*2) + 1;
237 nutc_path = xmalloc(nutc_path_len);
238 pathp = nutc_path;
239 *pathp = '\0';
240
241 /*
242 * Loop through PATH and convert one elemnt of the path at at
243 * a time. Single file pathnames will fail this and fall
244 * to the logic below loop.
245 */
246 for (p = path, etok = strpbrk(p, ":;");
247 etok;
248 etok = strpbrk(p, ":;")) {
249
250 /* don't trip up on device specifiers or empty path slots */
251 if ((etok - p) == 1)
252 if (*(etok - 1) == ';' ||
253 *(etok - 1) == ':') {
254 p = ++etok;
255 continue;
256 } else if ((etok = strpbrk(etok+1, ":;")) == NULL)
257 break; /* thing found was a WINDOWS32 pathname */
258
259 /* save separator */
260 sep = *etok;
261
262 /* terminate the current path element -- temporarily */
263 *etok = '\0';
264
265#ifdef __NUTC__
266 /* convert to NutC format */
267 if (_NutPathToNutc(p, pathp, 0) == FALSE) {
268 free(nutc_path);
269 rval = savestring(path, strlen(path));
270 return rval;
271 }
272#else
273 *pathp++ = '/';
274 *pathp++ = p[0];
275 *pathp++ = '=';
276 *pathp++ = '/';
277 strcpy(pathp, &p[2]);
278#endif
279
280 pathp += strlen(pathp);
281 *pathp++ = ':'; /* use Unix style path separtor for new path */
282 *pathp = '\0'; /* make sure we are null terminaed */
283
284 /* restore path separator */
285 *etok = sep;
286
287 /* point p to first char of next path element */
288 p = ++etok;
289
290 }
291 } else {
292 nutc_path_len = strlen(path) + 3;
293 nutc_path = xmalloc(nutc_path_len);
294 pathp = nutc_path;
295 *pathp = '\0';
296 p = path;
297 }
298
299 /*
300 * OK, here we handle the last element in PATH (e.g. c of a;b;c)
301 * or the path was a single filename and will be converted
302 * here. Note, testing p here assures that we don't trip up
303 * on paths like a;b; which have trailing delimiter followed by
304 * nothing.
305 */
306 if (*p != '\0') {
307#ifdef __NUTC__
308 if (_NutPathToNutc(p, pathp, 0) == FALSE) {
309 free(nutc_path);
310 rval = savestring(path, strlen(path));
311 return rval;
312 }
313#else
314 *pathp++ = '/';
315 *pathp++ = p[0];
316 *pathp++ = '=';
317 *pathp++ = '/';
318 strcpy(pathp, &p[2]);
319#endif
320 } else
321 *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */
322
323 rval = savestring(nutc_path, strlen(nutc_path));
324 free(nutc_path);
325 return rval;
326}
327
328#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette