Remove some #if __cplusplus wrt inlining. (#18891)
[mono-project.git] / mono / eglib / gpath.c
blobe6ec47b05f1eea6ff59be6718e44318d21da1182
1 /*
2 * Portable Utility Functions
4 * Author:
5 * Miguel de Icaza (miguel@novell.com)
7 * (C) 2006 Novell, Inc.
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <config.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <sys/stat.h>
34 #ifdef G_OS_WIN32
35 #include <direct.h>
36 #endif
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
42 gchar *
43 g_build_path (const gchar *separator, const gchar *first_element, ...)
45 const char *elem, *next, *endptr;
46 gboolean trimmed;
47 GString *path;
48 va_list args;
49 size_t slen;
51 g_return_val_if_fail (separator != NULL, NULL);
53 path = g_string_sized_new (48);
54 slen = strlen (separator);
56 va_start (args, first_element);
57 for (elem = first_element; elem != NULL; elem = next) {
58 /* trim any trailing separators from @elem */
59 endptr = elem + strlen (elem);
60 trimmed = FALSE;
62 while (endptr >= elem + slen) {
63 if (strncmp (endptr - slen, separator, slen) != 0)
64 break;
66 endptr -= slen;
67 trimmed = TRUE;
70 /* append elem, not including any trailing separators */
71 if (endptr > elem)
72 g_string_append_len (path, elem, endptr - elem);
74 /* get the next element */
75 do {
76 if (!(next = va_arg (args, char *)))
77 break;
79 /* remove leading separators */
80 while (!strncmp (next, separator, slen))
81 next += slen;
82 } while (*next == '\0');
84 if (next || trimmed)
85 g_string_append_len (path, separator, slen);
87 va_end (args);
89 return g_string_free (path, FALSE);
92 static gchar*
93 strrchr_seperator (const gchar* filename)
95 #ifdef G_OS_WIN32
96 char *p2;
97 #endif
98 char *p;
100 p = (char*)strrchr (filename, G_DIR_SEPARATOR);
101 #ifdef G_OS_WIN32
102 p2 = (char*)strrchr (filename, '/');
103 if (p2 > p)
104 p = p2;
105 #endif
107 return p;
110 gchar *
111 g_path_get_dirname (const gchar *filename)
113 char *p, *r;
114 size_t count;
115 g_return_val_if_fail (filename != NULL, NULL);
117 p = strrchr_seperator (filename);
118 if (p == NULL)
119 return g_strdup (".");
120 if (p == filename)
121 return g_strdup ("/");
122 count = p - filename;
123 r = g_malloc (count + 1);
124 strncpy (r, filename, count);
125 r [count] = 0;
127 return r;
130 gchar *
131 g_path_get_basename (const char *filename)
133 char *r;
134 g_return_val_if_fail (filename != NULL, NULL);
136 /* Empty filename -> . */
137 if (!*filename)
138 return g_strdup (".");
140 /* No separator -> filename */
141 r = strrchr_seperator (filename);
142 if (r == NULL)
143 return g_strdup (filename);
145 /* Trailing slash, remove component */
146 if (r [1] == 0){
147 char *copy = g_strdup (filename);
148 copy [r-filename] = 0;
149 r = strrchr_seperator (copy);
151 if (r == NULL){
152 g_free (copy);
153 return g_strdup ("/");
155 r = g_strdup (&r[1]);
156 g_free (copy);
157 return r;
160 return g_strdup (&r[1]);
163 //wasm does have strtok_r even though autoconf fails to find
164 #if !defined (HAVE_STRTOK_R) && !defined (HOST_WASM)
165 // This is from BSD's strtok_r
167 char *
168 strtok_r(char *s, const char *delim, char **last)
170 char *spanp;
171 int c, sc;
172 char *tok;
174 if (s == NULL && (s = *last) == NULL)
175 return NULL;
178 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
180 cont:
181 c = *s++;
182 for (spanp = (char *)delim; (sc = *spanp++) != 0; ){
183 if (c == sc)
184 goto cont;
187 if (c == 0){ /* no non-delimiter characters */
188 *last = NULL;
189 return NULL;
191 tok = s - 1;
194 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
195 * Note that delim must have one NUL; we stop if we see that, too.
197 for (;;){
198 c = *s++;
199 spanp = (char *)delim;
200 do {
201 if ((sc = *spanp++) == c) {
202 if (c == 0)
203 s = NULL;
204 else {
205 char *w = s - 1;
206 *w = '\0';
208 *last = s;
209 return tok;
212 while (sc != 0);
214 /* NOTREACHED */
216 #endif
218 gchar *
219 g_find_program_in_path (const gchar *program)
221 char *p;
222 char *x, *l;
223 gchar *curdir = NULL;
224 char *save = NULL;
225 #ifdef G_OS_WIN32
226 char *program_exe;
227 static char const * const suffix_list[5] = {".exe",".cmd",".bat",".com",NULL};
228 int listx;
229 gboolean hasSuffix;
230 #endif
232 g_return_val_if_fail (program != NULL, NULL);
233 x = p = g_getenv ("PATH");
235 if (x == NULL || *x == '\0') {
236 curdir = g_get_current_dir ();
237 x = curdir;
240 #ifdef G_OS_WIN32
241 /* see if program already has a suffix */
242 listx = 0;
243 hasSuffix = FALSE;
244 while (!hasSuffix && suffix_list[listx]) {
245 hasSuffix = g_str_has_suffix(program,suffix_list[listx++]);
247 #endif
249 while ((l = strtok_r (x, G_SEARCHPATH_SEPARATOR_S, &save)) != NULL){
250 char *probe_path;
252 x = NULL;
253 probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program, NULL);
254 #ifdef HAVE_ACCESS
255 if (g_access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */
256 g_free (curdir);
257 g_free (p);
258 return probe_path;
260 #endif
261 g_free (probe_path);
263 #ifdef G_OS_WIN32
264 /* check for program with a suffix attached */
265 if (!hasSuffix) {
266 listx = 0;
267 while (suffix_list[listx]) {
268 program_exe = g_strjoin (NULL, program, suffix_list [listx], (const char*)NULL);
269 probe_path = g_build_path (G_DIR_SEPARATOR_S, l, program_exe, (const char*)NULL);
270 #ifdef HAVE_ACCESS
271 if (g_access (probe_path, X_OK) == 0){ /* FIXME: on windows this is just a read permissions test */
272 g_free (curdir);
273 g_free (p);
274 g_free (program_exe);
275 return probe_path;
277 #endif
278 listx++;
279 g_free (probe_path);
280 g_free (program_exe);
283 #endif
285 g_free (curdir);
286 g_free (p);
287 return NULL;
290 static char *name;
292 void
293 g_set_prgname (const gchar *prgname)
295 name = g_strdup (prgname);
298 gchar *
299 g_get_prgname (void)
301 return name;
304 gboolean
305 g_ensure_directory_exists (const gchar *filename)
307 #ifdef G_OS_WIN32
308 gchar *dir_utf8 = g_path_get_dirname (filename);
309 gunichar2 *p;
310 gunichar2 *dir_utf16 = NULL;
311 int retval;
313 if (!dir_utf8 || !dir_utf8 [0])
314 return FALSE;
316 dir_utf16 = g_utf8_to_utf16 (dir_utf8, strlen (dir_utf8), NULL, NULL, NULL);
317 g_free (dir_utf8);
319 if (!dir_utf16)
320 return FALSE;
322 p = dir_utf16;
324 /* make life easy and only use one directory seperator */
325 while (*p != '\0')
327 if (*p == '/')
328 *p = '\\';
329 p++;
332 p = dir_utf16;
334 /* get past C:\ )*/
335 while (*p++ != '\\')
339 while (1) {
340 p = wcschr (p, '\\');
341 if (p)
342 *p = '\0';
343 retval = _wmkdir (dir_utf16);
344 if (retval != 0 && errno != EEXIST) {
345 g_free (dir_utf16);
346 return FALSE;
348 if (!p)
349 break;
350 *p++ = '\\';
353 g_free (dir_utf16);
354 return TRUE;
355 #else
356 char *p;
357 gchar *dir = g_path_get_dirname (filename);
358 int retval;
359 struct stat sbuf;
361 if (!dir || !dir [0]) {
362 g_free (dir);
363 return FALSE;
366 if (stat (dir, &sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
367 g_free (dir);
368 return TRUE;
371 p = dir;
372 while (*p == '/')
373 p++;
375 while (1) {
376 p = strchr (p, '/');
377 if (p)
378 *p = '\0';
379 retval = mkdir (dir, 0777);
380 if (retval != 0 && errno != EEXIST) {
381 g_free (dir);
382 return FALSE;
384 if (!p)
385 break;
386 *p++ = '/';
389 g_free (dir);
390 return TRUE;
391 #endif