annotate gcc/d/dmd/root/filename.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 /* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 * http://www.digitalmars.com
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 * Distributed under the Boost Software License, Version 1.0.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/filename.c
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 #include "dsystem.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 #include "filename.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 #include "outbuffer.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 #include "array.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 #include "file.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 #include "rmem.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 #include <windows.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 #include <utime.h>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 /****************************** FileName ********************************/
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 FileName::FileName(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 : str(mem.xstrdup(str))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 const char *FileName::combine(const char *path, const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 { char *f;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 size_t pathlen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 size_t namelen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 if (!path || !*path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 return name;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 pathlen = strlen(path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 namelen = strlen(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 f = (char *)mem.xmalloc(pathlen + 1 + namelen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 memcpy(f, path, pathlen);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 if (path[pathlen - 1] != '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 { f[pathlen] = '/';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 pathlen++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 #elif _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 if (path[pathlen - 1] != '\\' &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 path[pathlen - 1] != '/' &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 path[pathlen - 1] != ':')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 { f[pathlen] = '\\';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 pathlen++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 memcpy(f + pathlen, name, namelen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 return f;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62 // Split a path into an Array of paths
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 Strings *FileName::splitPath(const char *path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 char c = 0; // unnecessary initializer is for VC /W4
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 const char *p;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 OutBuffer buf;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 Strings *array;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 array = new Strings();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 if (path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 p = path;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 do
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 { char instring = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 while (isspace((utf8_t)*p)) // skip leading whitespace
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 p++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 buf.reserve(strlen(p) + 1); // guess size of path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 for (; ; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 c = *p;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 switch (c)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 case '"':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 instring ^= 1; // toggle inside/outside of string
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 #if MACINTOSH
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 case ',':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 case ';':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 case ':':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 p++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 break; // note that ; cannot appear as part
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 // of a path, quotes won't protect it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 case 0x1A: // ^Z means end of file
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 case 0:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 case '\r':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 continue; // ignore carriage returns
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 case '~':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 char *home = getenv("HOME");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 // Expand ~ only if it is prefixing the rest of the path.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 if (!buf.offset && p[1] == '/' && home)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 buf.writestring(home);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 buf.writestring("~");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 buf.writeByte(c);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 if (buf.offset) // if path is not empty
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 array->push(buf.extractString());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 } while (c);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 return array;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 int FileName::compare(RootObject *obj)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 return compare(str, ((FileName *)obj)->str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 int FileName::compare(const char *name1, const char *name2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 return stricmp(name1, name2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 return strcmp(name1, name2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 bool FileName::equals(RootObject *obj)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 return compare(obj) == 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 bool FileName::equals(const char *name1, const char *name2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 return compare(name1, name2) == 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 /************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 * Return !=0 if absolute path name.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 bool FileName::absolute(const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 return (*name == '\\') ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 (*name == '/') ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 (*name && name[1] == ':');
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 #elif POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 return (*name == '/');
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 /********************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 * Return filename extension (read-only).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 * Points past '.' of extension.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 * If there isn't one, return NULL.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 const char *FileName::ext(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 size_t len = strlen(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 const char *e = str + len;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 for (;;)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 switch (*e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 { case '.':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 return e + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 case '/':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 case '\\':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 case ':':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 case '/':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 if (e == str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207 e--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214 const char *FileName::ext()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 return ext(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 /********************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 * Return mem.xmalloc'd filename with extension removed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 const char *FileName::removeExt(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 const char *e = ext(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 if (e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 { size_t len = (e - str) - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 char *n = (char *)mem.xmalloc(len + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229 memcpy(n, str, len);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 n[len] = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 return n;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 return mem.xstrdup(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 /********************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 * Return filename name excluding path (read-only).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 const char *FileName::name(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 size_t len = strlen(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 const char *e = str + len;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 for (;;)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 switch (*e)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250 case '/':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 return e + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 case '/':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 case '\\':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 return e + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 case ':':
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 /* The ':' is a drive letter only if it is the second
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 * character or the last character,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 * otherwise it is an ADS (Alternate Data Stream) separator.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 * Consider ADS separators as part of the file name.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 if (e == str + 1 || e == str + len - 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 return e + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 /* falls through */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 if (e == str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 e--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 return e;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 const char *FileName::name()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 return name(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 /**************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 * Return path portion of str.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 * Path will does not include trailing path separator.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 const char *FileName::path(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289 const char *n = name(str);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 size_t pathlen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 if (n > str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 if (n[-1] == '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 n--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 #elif _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 if (n[-1] == '\\' || n[-1] == '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 n--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304 pathlen = n - str;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 char *path = (char *)mem.xmalloc(pathlen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 memcpy(path, str, pathlen);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 path[pathlen] = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308 return path;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 /**************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 * Replace filename portion of path.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 const char *FileName::replaceName(const char *path, const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 size_t pathlen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 size_t namelen;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 if (absolute(name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 return name;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 const char *n = FileName::name(path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 if (n == path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 return name;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 pathlen = n - path;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 namelen = strlen(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 char *f = (char *)mem.xmalloc(pathlen + 1 + namelen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 memcpy(f, path, pathlen);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 if (path[pathlen - 1] != '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 { f[pathlen] = '/';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 pathlen++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 #elif _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 if (path[pathlen - 1] != '\\' &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 path[pathlen - 1] != '/' &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 path[pathlen - 1] != ':')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 { f[pathlen] = '\\';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340 pathlen++;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 memcpy(f + pathlen, name, namelen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346 return f;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 /***************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 * Free returned value with FileName::free()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 const char *FileName::defaultExt(const char *name, const char *ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 const char *e = FileName::ext(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 if (e) // if already has an extension
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 return mem.xstrdup(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 size_t len = strlen(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 size_t extlen = strlen(ext);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 char *s = (char *)mem.xmalloc(len + 1 + extlen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 memcpy(s,name,len);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 s[len] = '.';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 memcpy(s + len + 1, ext, extlen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 return s;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 /***************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 * Free returned value with FileName::free()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 const char *FileName::forceExt(const char *name, const char *ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 const char *e = FileName::ext(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 if (e) // if already has an extension
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377 size_t len = e - name;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 size_t extlen = strlen(ext);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 char *s = (char *)mem.xmalloc(len + extlen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381 memcpy(s,name,len);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 memcpy(s + len, ext, extlen + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383 return s;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 return defaultExt(name, ext); // doesn't have one
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 /******************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 * Return !=0 if extensions match.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 bool FileName::equalsExt(const char *ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395 return equalsExt(str, ext);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 bool FileName::equalsExt(const char *name, const char *ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400 const char *e = FileName::ext(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 if (!e && !ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 if (!e || !ext)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 return FileName::compare(e, ext) == 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 /*************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409 * Search Path for file.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 * Input:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 * cwd if true, search current directory before searching path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 const char *FileName::searchPath(Strings *path, const char *name, bool cwd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 if (absolute(name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 return exists(name) ? name : NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 if (cwd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 if (exists(name))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 return name;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 if (path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 for (size_t i = 0; i < path->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 const char *p = (*path)[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 const char *n = combine(p, name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433 if (exists(n))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 return n;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 /*************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 * Search Path for file in a safe manner.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 *
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445 * ('Path Traversal') attacks.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 * http://cwe.mitre.org/data/definitions/22.html
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 * More info:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 * https://www.securecoding.cert.org/confluence/display/c/FIO02-C.+Canonicalize+path+names+originating+from+tainted+sources
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 * Returns:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450 * NULL file not found
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 * !=NULL mem.xmalloc'd file name
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 const char *FileName::safeSearchPath(Strings *path, const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 // don't allow leading / because it might be an absolute
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 // path or UNC path or something we'd prefer to just not deal with
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459 if (*name == '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 /* Disallow % \ : and .. in name characters
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 * We allow / for compatibility with subdirectories which is allowed
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 * on dmd/posix. With the leading / blocked above and the rest of these
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 * conservative restrictions, we should be OK.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 for (const char *p = name; *p; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470 char c = *p;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471 if (c == '\\' || c == ':' || c == '%' || (c == '.' && p[1] == '.'))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477 return FileName::searchPath(path, name, false);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 #elif POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 /* Even with realpath(), we must check for // and disallow it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 for (const char *p = name; *p; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 char c = *p;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 if (c == '/' && p[1] == '/')
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 if (path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 /* Each path is converted to a cannonical name and then a check is done to see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 * that the searched name is really a child one of the the paths searched.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 for (size_t i = 0; i < path->dim; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 const char *cname = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 const char *cpath = canonicalName((*path)[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499 //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 // name, (char *)path->data[i], cpath);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 if (cpath == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 goto cont;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 cname = canonicalName(combine(cpath, name));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 //printf("FileName::safeSearchPath(): cname=%s\n", cname);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 if (cname == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 goto cont;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 //printf("FileName::safeSearchPath(): exists=%i "
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 // "strncmp(cpath, cname, %i)=%i\n", exists(cname),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509 // strlen(cpath), strncmp(cpath, cname, strlen(cpath)));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 // exists and name is *really* a "child" of path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511 if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 ::free(const_cast<char *>(cpath));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 const char *p = mem.xstrdup(cname);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515 ::free(const_cast<char *>(cname));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 return p;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518 cont:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 if (cpath)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520 ::free(const_cast<char *>(cpath));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 if (cname)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 ::free(const_cast<char *>(cname));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 int FileName::exists(const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535 struct stat st;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 if (stat(name, &st) < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 if (S_ISDIR(st.st_mode))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540 return 2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 return 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 #elif _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 DWORD dw;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544 int result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 dw = GetFileAttributesA(name);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 if (dw == INVALID_FILE_ATTRIBUTES)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 result = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 else if (dw & FILE_ATTRIBUTE_DIRECTORY)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550 result = 2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 result = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559 bool FileName::ensurePathExists(const char *path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 if (path && *path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 if (!exists(path))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 const char *p = FileName::path(path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567 if (*p)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 size_t len = strlen(path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571 if ((len > 2 && p[-1] == ':' && strcmp(path + 2, p) == 0) ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 len == strlen(p))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573 { mem.xfree(const_cast<char *>(p));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 bool r = ensurePathExists(p);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 mem.xfree(const_cast<char *>(p));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 if (r)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580 return r;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 char sep = '\\';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 #elif POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585 char sep = '/';
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 if (path[strlen(path) - 1] != sep)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 //printf("mkdir(%s)\n", path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 #if _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 int r = _mkdir(path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 int r = mkdir(path, (7 << 6) | (7 << 3) | 7);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596 if (r)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598 /* Don't error out if another instance of dmd just created
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 * this directory
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601 if (errno != EEXIST)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 /******************************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 * Return canonical version of name in a malloc'd buffer.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612 * This code is high risk.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614 const char *FileName::canonicalName(const char *name)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 #if POSIX
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 // NULL destination buffer is allowed and preferred
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 return realpath(name, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 #elif _WIN32
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 /* Apparently, there is no good way to do this on Windows.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621 * GetFullPathName isn't it, but use it anyway.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623 DWORD result = GetFullPathNameA(name, 0, NULL, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 if (result)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626 char *buf = (char *)mem.xmalloc(result);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 result = GetFullPathNameA(name, result, buf, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628 if (result == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630 ::free(buf);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633 return buf;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636 #else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 assert(0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 #endif
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 /********************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 * Free memory allocated by FileName routines
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 void FileName::free(const char *str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 if (str)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 { assert(str[0] != (char)0xAB);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 memset(const_cast<char *>(str), 0xAB, strlen(str) + 1); // stomp
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 mem.xfree(const_cast<char *>(str));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 const char *FileName::toChars() const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 return str;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 }