1 |
/* ASCEND modelling environment |
2 |
Copyright (C) 2006 Carnegie Mellon University |
3 |
|
4 |
This program is free software; you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation; either version 2, or (at your option) |
7 |
any later version. |
8 |
|
9 |
This program is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with this program; if not, write to the Free Software |
16 |
Foundation, Inc., 59 Temple Place - Suite 330, |
17 |
Boston, MA 02111-1307, USA. |
18 |
*//** |
19 |
@file |
20 |
Platform-agnostic filesystem path manipulation functions. |
21 |
By John Pye. |
22 |
*/ |
23 |
|
24 |
#if defined(WIN32) || defined(__WIN32) || defined(_MSC_VER) |
25 |
# ifndef __WIN32__ |
26 |
# define __WIN32__ |
27 |
# endif |
28 |
#endif |
29 |
|
30 |
#include <string.h> |
31 |
#include <stdlib.h> |
32 |
#include <stddef.h> |
33 |
#include <stdio.h> |
34 |
#include <ctype.h> |
35 |
|
36 |
#ifndef __WIN32__ |
37 |
# include <unistd.h> |
38 |
#endif |
39 |
|
40 |
#include "ospath.h" |
41 |
|
42 |
/* to test this code, 'gcc -DTEST ospath.c && ./a' */ |
43 |
|
44 |
#ifndef __GNUC__ |
45 |
# ifndef __FUNCTION__ |
46 |
# define __FUNCTION__ "<ospath>" |
47 |
# endif |
48 |
#endif |
49 |
|
50 |
|
51 |
/* #define VERBOSE */ |
52 |
|
53 |
#if !defined(TEST) && !defined(VERBOSE) |
54 |
#ifndef NDEBUG |
55 |
# define NDEBUG |
56 |
#endif |
57 |
#endif |
58 |
|
59 |
#ifdef _MSC_VER |
60 |
# define STAT _stat |
61 |
#else |
62 |
# define STAT stat |
63 |
#endif |
64 |
|
65 |
//#define TRY_GETPWUID |
66 |
|
67 |
#define DO_FIXSLASHES |
68 |
|
69 |
#ifndef NDEBUG |
70 |
# include <assert.h> |
71 |
# define M(MSG) fprintf(stderr,"%s:%d: (%s) %s\n",__FILE__,__LINE__,__FUNCTION__,MSG);fflush(stderr);fflush(stderr) |
72 |
# define MC(CLR,MSG) fprintf(stderr,"%c[%sm%s:%d: (%s) %s%c[0m\n",27,CLR,__FILE__,__LINE__,__FUNCTION__,MSG,27);fflush(stderr) |
73 |
# define MM(MSG) MC("34",MSG) |
74 |
# define X(VAR) fprintf(stderr,"%s:%d: (%s) %s=%s\n",__FILE__,__LINE__,__FUNCTION__,#VAR,VAR);fflush(stderr) |
75 |
# define C(VAR) fprintf(stderr,"%s:%d: (%s) %s=%c\n",__FILE__,__LINE__,__FUNCTION__,#VAR,VAR);fflush(stderr) |
76 |
# define V(VAR) fprintf(stderr,"%s:%d: (%s) %s=%d\n",__FILE__,__LINE__,__FUNCTION__,#VAR,(VAR));fflush(stderr) |
77 |
# define P(VAR) fprintf(stderr,"%s:%d: (%s) %s=%p\n",__FILE__,__LINE__,__FUNCTION__,#VAR,(VAR));fflush(stderr) |
78 |
# define D(VAR) fprintf(stderr,"%s:%d: (%s) %s=",__FILE__,__LINE__,__FUNCTION__,#VAR);ospath_debug(VAR);fflush(stderr) |
79 |
# define DD(VAR) fprintf(stderr,"%c[34;1m%s:%d: (%s)%c[0m %s=",27,__FILE__,__LINE__,__FUNCTION__,27,#VAR);ospath_debug(VAR);fflush(stderr) |
80 |
#else |
81 |
# include <assert.h> |
82 |
# define M(MSG) ((void)0) |
83 |
# define MC(CLR,MSG) ((void)0) |
84 |
# define X(VAR) ((void)0) |
85 |
# define C(VAR) ((void)0) |
86 |
# define V(VAR) ((void)0) |
87 |
# define D(VAR) ((void)0) |
88 |
# define P(VAR) ((void)0) |
89 |
# define DD(VAR) ((void)0) |
90 |
# define MM(VAR) ((void)0) |
91 |
#endif |
92 |
|
93 |
#if defined(__WIN32__) && !defined(__MINGW32__) |
94 |
# define STRCPY strcpy |
95 |
# define STRNCPY(dest,src,n) strncpy_s(dest,n,src,n) |
96 |
# define STRCAT strcat |
97 |
# define STRNCAT strncat |
98 |
# define STRTOK(STR,PAT,VAR) strtok_s(STR,PAT,&VAR) |
99 |
# define STRTOKVAR(VAR) char *VAR |
100 |
# define GETCWD _getcwd |
101 |
# define GETENV(VAR) getenv(VAR) |
102 |
#else |
103 |
# define STRCPY strcpy |
104 |
# define STRNCPY(dest,src,n) strncpy(dest,src,n) |
105 |
# define STRCAT strcat |
106 |
# define STRNCAT strncat |
107 |
# define STRTOK(STR,PAT,VAR) strtok(STR,PAT) |
108 |
# define STRTOKVAR(VAR) ((void)0) |
109 |
# define GETCWD getcwd |
110 |
# define GETENV(VAR) getenv(VAR) |
111 |
#endif |
112 |
|
113 |
/* PATH_MAX is in ospath.h */ |
114 |
#define DRIVEMAX 3 |
115 |
#define LISTMAX 256 |
116 |
|
117 |
#ifdef __WIN32__ /* && !defined(__MINGW32__) */ |
118 |
# define WINPATHS |
119 |
#endif |
120 |
|
121 |
struct FilePath{ |
122 |
char path[PATH_MAX]; /** the string version of the represented POSIX path */ |
123 |
|
124 |
#ifdef WINPATHS |
125 |
char drive[DRIVEMAX]; /** the drive the path resides on (field is absent in POSIX systems) */ |
126 |
#endif |
127 |
}; |
128 |
|
129 |
#include <string.h> |
130 |
|
131 |
#if !defined(MALLOC) && !defined(FREE) |
132 |
# define MALLOC malloc |
133 |
# define FREE free |
134 |
#endif |
135 |
|
136 |
#define E(MSG) fprintf(stderr,"%s:%d: (%s) ERROR: %s\n",__FILE__,__LINE__,__FUNCTION__,MSG) |
137 |
|
138 |
#ifdef DO_FIXSLASHES |
139 |
void ospath_fixslash(char *path); |
140 |
#endif |
141 |
|
142 |
struct FilePath *ospath_getcwd(); |
143 |
|
144 |
void ospath_copy(struct FilePath *dest, struct FilePath *src); |
145 |
|
146 |
|
147 |
#ifdef WINPATHS |
148 |
/** |
149 |
This function splits out the drive letter in the path string, thus completing |
150 |
the correct construction of a FilePath object under Win32. |
151 |
*/ |
152 |
void ospath_extractdriveletter(struct FilePath *); |
153 |
#endif |
154 |
|
155 |
#ifdef WINPATHS |
156 |
# define PATH_SEPARATOR_STR "\\" |
157 |
# define PATH_SEPARATOR_CHAR '\\' |
158 |
# define PATH_LISTSEP_CHAR ';' |
159 |
# define PATH_LISTSEP_STR ";" |
160 |
# define PATH_WRONGSLASH_CHAR '/' |
161 |
# define PATH_WRONGSLASH_STR "/" |
162 |
#else |
163 |
# define PATH_SEPARATOR_STR "/" |
164 |
# define PATH_SEPARATOR_CHAR '/' |
165 |
# define PATH_LISTSEP_CHAR ':' |
166 |
# define PATH_LISTSEP_STR ":" |
167 |
# define PATH_WRONGSLASH_CHAR '\\' |
168 |
# define PATH_WRONGSLASH_STR "\\" |
169 |
#endif |
170 |
|
171 |
/** |
172 |
Create a new path structure from a string |
173 |
*/ |
174 |
struct FilePath *ospath_new(const char *path){ |
175 |
struct FilePath *fp; |
176 |
fp = ospath_new_noclean(path); |
177 |
|
178 |
#ifdef DO_FIXSLASHES |
179 |
ospath_fixslash(fp->path); |
180 |
#endif |
181 |
|
182 |
ospath_cleanup(fp); |
183 |
|
184 |
#if 0 |
185 |
D(fp); |
186 |
#endif |
187 |
|
188 |
return fp; |
189 |
} |
190 |
|
191 |
|
192 |
|
193 |
/** Create but with no 'cleanup', and no fixing of / vs \. */ |
194 |
struct FilePath *ospath_new_noclean(const char *path){ |
195 |
struct FilePath *fp = (struct FilePath *)MALLOC(sizeof(struct FilePath)); |
196 |
P(fp); |
197 |
X(path); |
198 |
STRNCPY(fp->path,path,PATH_MAX); |
199 |
assert(strcmp(fp->path,path)==0); |
200 |
#ifdef WINPATHS |
201 |
#if 0 |
202 |
X(fp->path); |
203 |
#endif |
204 |
ospath_extractdriveletter(fp); |
205 |
#endif |
206 |
|
207 |
return fp; |
208 |
} |
209 |
|
210 |
struct FilePath *ospath_new_expand_env(const char *path, GetEnvFn *getenvptr){ |
211 |
struct FilePath *fp; |
212 |
|
213 |
char *pathnew = env_subst(path,getenvptr); |
214 |
fp = ospath_new(pathnew); |
215 |
FREE(pathnew); |
216 |
|
217 |
return fp; |
218 |
} |
219 |
|
220 |
struct FilePath *ospath_new_copy(struct FilePath *fp){ |
221 |
struct FilePath *fp1 = (struct FilePath *)MALLOC(sizeof(struct FilePath)); |
222 |
ospath_copy(fp1,fp); |
223 |
return fp1; |
224 |
} |
225 |
|
226 |
/** |
227 |
This function will serve to allow #include-style file paths |
228 |
to be specified with platform-independent forward slashes then |
229 |
translated into the local filesystem format for subsequent use. |
230 |
|
231 |
This method should be identical to ospath_new on posix, right? |
232 |
|
233 |
@NOTE: on windows, we also want: |
234 |
C:dir/file --> c:$PWD\dir\file |
235 |
e:/hello --> e:\hello |
236 |
here/i/am --> here\i\am |
237 |
|
238 |
@NOTE: |
239 |
A path-search function should create full file paths by |
240 |
appending relative file to each component of the search path |
241 |
then performing a callback on each one to determine if the |
242 |
match is OK or not. |
243 |
*/ |
244 |
struct FilePath *ospath_new_from_posix(const char *posixpath){ |
245 |
struct FilePath *fp; |
246 |
fp = ospath_new_noclean(posixpath); |
247 |
|
248 |
#ifdef DO_FIXSLASHES |
249 |
ospath_fixslash(fp->path); |
250 |
#endif |
251 |
|
252 |
#if 0 |
253 |
X(fp->path); |
254 |
#endif |
255 |
|
256 |
ospath_cleanup(fp); |
257 |
|
258 |
return fp; |
259 |
} |
260 |
|
261 |
void ospath_free(struct FilePath *fp){ |
262 |
if(fp!=NULL){ |
263 |
P(fp); |
264 |
FREE(fp); |
265 |
} |
266 |
fp=NULL; |
267 |
} |
268 |
|
269 |
void ospath_free_str(char *str){ |
270 |
FREE(str); |
271 |
} |
272 |
|
273 |
|
274 |
#ifdef DO_FIXSLASHES |
275 |
void ospath_fixslash(char *path){ |
276 |
|
277 |
char *p; |
278 |
char temp[PATH_MAX]; |
279 |
int startslash; |
280 |
int endslash; |
281 |
STRTOKVAR(nexttok); |
282 |
|
283 |
STRNCPY(temp,path,PATH_MAX); |
284 |
|
285 |
#if 0 |
286 |
X(path); |
287 |
#endif |
288 |
|
289 |
startslash = (strlen(temp) > 0 && temp[0] == PATH_WRONGSLASH_CHAR); |
290 |
endslash = (strlen(temp) > 1 && temp[strlen(temp) - 1] == PATH_WRONGSLASH_CHAR); |
291 |
|
292 |
#if 0 |
293 |
V(startslash); |
294 |
V(endslash); |
295 |
|
296 |
#endif |
297 |
/* reset fp->path as required. */ |
298 |
STRNCPY(path, (startslash ? PATH_SEPARATOR_STR : ""), PATH_MAX); |
299 |
|
300 |
#if 0 |
301 |
M("STARTING STRTOK"); |
302 |
#endif |
303 |
for(p = STRTOK(temp, PATH_WRONGSLASH_STR,nexttok); |
304 |
p!=NULL; |
305 |
p = STRTOK(NULL,PATH_WRONGSLASH_STR,nexttok) |
306 |
){ |
307 |
/* add a separator if we've already got some stuff */ |
308 |
if( |
309 |
strlen(path) > 0 |
310 |
&& path[strlen(path) - 1] != PATH_SEPARATOR_CHAR |
311 |
){ |
312 |
STRCAT(path,PATH_SEPARATOR_STR); |
313 |
} |
314 |
|
315 |
STRCAT(path,p); |
316 |
} |
317 |
#if 0 |
318 |
M("FINISHED STRTOK"); |
319 |
#endif |
320 |
|
321 |
/* put / on end as required, according to what the starting path had */ |
322 |
if(endslash && (strlen(path) > 0 ? (path[strlen(path) - 1] != PATH_SEPARATOR_CHAR) : 1)) |
323 |
{ |
324 |
#if 0 |
325 |
M("adding endslash!"); |
326 |
#endif |
327 |
|
328 |
STRCAT(path, PATH_SEPARATOR_STR); |
329 |
} |
330 |
|
331 |
#if 0 |
332 |
X(path); |
333 |
#endif |
334 |
} |
335 |
#endif |
336 |
|
337 |
struct FilePath *ospath_getcwd(void){ |
338 |
struct FilePath *fp; |
339 |
char *cwd; |
340 |
|
341 |
/* get current working directory */ |
342 |
cwd = (char *)GETCWD(NULL, 0); |
343 |
|
344 |
/* create new path with resolved working directory */ |
345 |
fp = ospath_new_noclean(cwd != NULL ? cwd : "."); |
346 |
|
347 |
D(fp); |
348 |
|
349 |
return fp; |
350 |
} |
351 |
|
352 |
/** |
353 |
Use getenv() function to retrieve HOME path, or if not set, use |
354 |
the password database and try to retrieve it that way (???) |
355 |
*/ |
356 |
struct FilePath *ospath_gethomepath(void){ |
357 |
|
358 |
const char *pfx = (const char *)getenv("HOME"); |
359 |
struct FilePath *fp; |
360 |
|
361 |
#ifndef __WIN32__ |
362 |
# ifdef TRY_GETPWUID |
363 |
struct passwd *pw; |
364 |
|
365 |
if(pfx==NULL){ |
366 |
pw = (struct passwd*)getpwuid(getuid()); |
367 |
|
368 |
if(pw){ |
369 |
pfx = pw->pw_dir; |
370 |
} |
371 |
} |
372 |
# endif |
373 |
#endif |
374 |
|
375 |
/* create path object from HOME, but don't compress it |
376 |
(because that would lead to an infinite loop) */ |
377 |
fp = ospath_new_noclean(pfx ? pfx : ""); |
378 |
|
379 |
#ifdef DO_FIXSLASHES |
380 |
ospath_fixslash(fp->path); |
381 |
#endif |
382 |
|
383 |
return fp; |
384 |
} |
385 |
|
386 |
#ifdef WINPATHS |
387 |
void ospath_extractdriveletter(struct FilePath *fp) |
388 |
{ |
389 |
char *p; |
390 |
#if 0 |
391 |
M("SOURCE"); |
392 |
X(fp->path); |
393 |
fprintf(stderr,"CHAR 1 = %c\n",fp->path[1]); |
394 |
#endif |
395 |
|
396 |
/* extract the drive the path resides on... */ |
397 |
if(strlen(fp->path) >= 2 && fp->path[1] == ':') |
398 |
{ |
399 |
STRNCPY(fp->drive,fp->path,2); |
400 |
fp->drive[2]='\0'; |
401 |
for(p=fp->path+2; *p!='\0'; ++p){ |
402 |
*(p-2)=*p; |
403 |
} |
404 |
*(p-2)='\0'; |
405 |
}else{ |
406 |
STRNCPY(fp->drive,"",DRIVEMAX); |
407 |
} |
408 |
#if 0 |
409 |
M("RESULT"); |
410 |
X(fp->path); |
411 |
X(fp->drive); |
412 |
#endif |
413 |
} |
414 |
#endif |
415 |
|
416 |
void ospath_cleanup(struct FilePath *fp){ |
417 |
char path[PATH_MAX]; |
418 |
char *p; |
419 |
struct FilePath *home; |
420 |
struct FilePath *working; |
421 |
struct FilePath *parent; |
422 |
int startslash, endslash; |
423 |
STRTOKVAR(nexttok); |
424 |
|
425 |
/* compress the path, and resolve ~ */ |
426 |
startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR); |
427 |
endslash = (strlen(fp->path) > 1 && fp->path[strlen(fp->path) - 1] == PATH_SEPARATOR_CHAR); |
428 |
|
429 |
#if 0 |
430 |
fprintf(stderr,"FS ON START = %d\n",startslash); |
431 |
fprintf(stderr,"FS ON END = %d\n",endslash); |
432 |
fprintf(stderr,"FIRST CHAR = %c\n",fp->path[0]); |
433 |
#endif |
434 |
|
435 |
home = ospath_gethomepath(); |
436 |
|
437 |
/* create a copy of fp->path. */ |
438 |
STRCPY(path, fp->path); |
439 |
|
440 |
/* reset fp->path as required. */ |
441 |
STRCPY(fp->path, (startslash ? PATH_SEPARATOR_STR : "")); |
442 |
|
443 |
D(fp); |
444 |
X(path); |
445 |
|
446 |
/* split path into it tokens, using STRTOK which is NOT reentrant |
447 |
so be careful! */ |
448 |
|
449 |
/*M("STARTING STRTOK"); */ |
450 |
for(p = STRTOK(path, PATH_SEPARATOR_STR,nexttok); |
451 |
p!=NULL; |
452 |
p = STRTOK(NULL,PATH_SEPARATOR_STR,nexttok) |
453 |
){ |
454 |
#if 0 |
455 |
M("NEXT TOKEN"); |
456 |
X(p); |
457 |
X(path+strlen(p)+1); |
458 |
#endif |
459 |
if(strcmp(p, "~")==0){ |
460 |
|
461 |
if(p == path){ /* check that the ~ is the first character in the path */ |
462 |
if(ospath_isvalid(home)){ |
463 |
ospath_copy(fp,home); |
464 |
continue; |
465 |
}else{ |
466 |
E("HOME does not resolve to valid path"); |
467 |
} |
468 |
}else{ |
469 |
E("A tilde (~) present as a component in a file path must be at the start!"); |
470 |
} |
471 |
}else if(strcmp(p, ".") == 0){ |
472 |
|
473 |
if(p==path){/* start of path: */ |
474 |
M("EXPANDING LEADING '.' IN PATH"); |
475 |
X(path); |
476 |
|
477 |
working = ospath_getcwd(); |
478 |
|
479 |
D(working); |
480 |
#ifdef WINPATHS |
481 |
X(working->drive); |
482 |
#endif |
483 |
X(p); |
484 |
X(path); |
485 |
|
486 |
ospath_copy(fp,working); |
487 |
|
488 |
|
489 |
D(fp); |
490 |
X(p); |
491 |
X(path+strlen(p)+1); |
492 |
|
493 |
ospath_free(working); |
494 |
continue; |
495 |
}else{/* later in the path: just skip it */ |
496 |
M("SKIPPING '.' IN PATH"); |
497 |
continue; |
498 |
} |
499 |
|
500 |
}else if(strcmp(p, "..") == 0){ |
501 |
M("GOING TO PARENT"); |
502 |
parent = ospath_getparent(fp); |
503 |
if(ospath_isvalid(parent)){ |
504 |
ospath_copy(fp,parent); |
505 |
} |
506 |
ospath_free(parent); |
507 |
continue; |
508 |
} |
509 |
|
510 |
/* add a separator if we've already got some stuff */ |
511 |
if( |
512 |
strlen(fp->path) > 0 |
513 |
&& fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR |
514 |
){ |
515 |
STRCAT(fp->path,PATH_SEPARATOR_STR); |
516 |
} |
517 |
|
518 |
/* add the present path component */ |
519 |
STRCAT(fp->path, p); |
520 |
} |
521 |
#if 0 |
522 |
M("FINISHED STRTOK"); |
523 |
#endif |
524 |
|
525 |
ospath_free(home); |
526 |
|
527 |
// put / on end as required, according to what the starting path had |
528 |
if(endslash && (strlen(fp->path) > 0 ? (fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR) : 1)) |
529 |
{ |
530 |
STRCAT(fp->path, PATH_SEPARATOR_STR); |
531 |
} |
532 |
} |
533 |
|
534 |
|
535 |
int ospath_isvalid(struct FilePath *fp){ |
536 |
/*if(fp==NULL) return 0; */ |
537 |
return strlen(fp->path) > 0 ? 1 : 0; |
538 |
} |
539 |
|
540 |
|
541 |
char *ospath_str(const struct FilePath *fp){ |
542 |
char *s; |
543 |
#ifdef WINPATHS |
544 |
s = (char *)MALLOC(sizeof(char)*(strlen(fp->drive)+strlen(fp->path) +1) ); |
545 |
STRCPY(s,fp->drive); |
546 |
STRCAT(s,fp->path); |
547 |
#else |
548 |
s = MALLOC(sizeof(char)*(strlen(fp->path)+1)); |
549 |
STRCPY(s,fp->path); |
550 |
#endif |
551 |
return s; |
552 |
} |
553 |
|
554 |
void ospath_strncpy(struct FilePath *fp, char *dest, int destsize){ |
555 |
#ifdef WINPATHS |
556 |
STRNCPY(dest,fp->drive,destsize); |
557 |
STRNCAT(dest,fp->path,destsize-strlen(dest)); |
558 |
#else |
559 |
STRNCPY(dest,fp->path,destsize); |
560 |
#endif |
561 |
} |
562 |
|
563 |
void ospath_strcat(struct FilePath *fp, char *dest, int destsize){ |
564 |
int remaining = destsize - strlen(dest); |
565 |
V(remaining); |
566 |
#ifdef WINPATHS |
567 |
STRNCAT(dest,fp->drive,remaining); |
568 |
STRNCAT(dest,fp->path,remaining-strlen(dest)); |
569 |
#else |
570 |
STRNCAT(dest,fp->path,remaining); |
571 |
#endif |
572 |
D(fp); |
573 |
} |
574 |
|
575 |
void ospath_fwrite(struct FilePath *fp, FILE *dest){ |
576 |
#ifdef WINPATHS |
577 |
fprintf(dest,"%s%s",fp->drive,fp->path); |
578 |
#else |
579 |
fprintf(dest,"%s",fp->path); |
580 |
#endif |
581 |
} |
582 |
|
583 |
unsigned ospath_length(struct FilePath *fp){ |
584 |
#ifdef WINPATHS |
585 |
/* we've already validated this path, so it's on to just add it up |
586 |
(unless someone has been tinkering with the internal structure here)*/ |
587 |
return (unsigned) (strlen(fp->drive) + strlen(fp->path)); |
588 |
#else |
589 |
return (unsigned) (strlen(fp->path)); |
590 |
#endif |
591 |
} |
592 |
|
593 |
struct FilePath *ospath_getparent(struct FilePath *fp) |
594 |
{ |
595 |
int length; |
596 |
int offset; |
597 |
char *pos; |
598 |
ptrdiff_t len1; |
599 |
int len2; |
600 |
char sub[PATH_MAX]; |
601 |
struct FilePath *fp1, *fp2; |
602 |
|
603 |
D(fp); |
604 |
|
605 |
if(strlen(fp->path) == 0){ |
606 |
fp1 = ospath_getcwd(); |
607 |
fp2 = ospath_getparent(fp1); |
608 |
ospath_free(fp1); |
609 |
return fp2; |
610 |
}else if(ospath_isroot(fp)){ |
611 |
/* stay at root */ |
612 |
return ospath_new("/"); |
613 |
} |
614 |
|
615 |
/* reverse find a / ignoring the end / if it exists. |
616 |
/// FIXME */ |
617 |
length = strlen(fp->path); |
618 |
offset = ( |
619 |
fp->path[length - 1] == PATH_SEPARATOR_CHAR /* last char is slash?*/ |
620 |
&& length > 1 /* and more than just leading slash... */ |
621 |
) ? length - 1 : length; /* then remove last char */ |
622 |
|
623 |
for(pos = fp->path + offset - 1; *pos!=PATH_SEPARATOR_CHAR && pos>=fp->path; --pos){ |
624 |
#if 0 |
625 |
fprintf(stderr,"CURRENT CHAR: %c\n",*pos); |
626 |
#endif |
627 |
} |
628 |
|
629 |
len1 = pos - (fp->path); len2 = (int)len1; |
630 |
V(len2); |
631 |
/*fprintf(stderr,"POS = %d\n",len2);*/ |
632 |
|
633 |
if(*pos==PATH_SEPARATOR_CHAR){ |
634 |
#ifdef WINPATHS |
635 |
STRCPY(sub,fp->drive); |
636 |
STRNCAT(sub,fp->path,len1); |
637 |
#else |
638 |
STRNCPY(sub,fp->path,len1); |
639 |
sub[len1]='\0'; |
640 |
#endif |
641 |
X(sub); |
642 |
if(strcmp(sub,"")==0){ |
643 |
M("DIRECTORY IS EMPTY"); |
644 |
STRCAT(sub,PATH_SEPARATOR_STR); |
645 |
} |
646 |
}else{ |
647 |
/* ie pos<fp->path */ |
648 |
M("NO PARENT DIR"); |
649 |
if(fp->path[0]==PATH_SEPARATOR_CHAR){ |
650 |
E("NO PARENT DIR"); |
651 |
return ospath_new_noclean(fp->path); |
652 |
}else{ |
653 |
M("RETURNING '.'"); |
654 |
#ifdef WINPATHS |
655 |
/* eg 'c:bin' --> 'c:' */ |
656 |
STRCPY(sub,fp->drive); |
657 |
return ospath_new_noclean(sub); |
658 |
#else |
659 |
/* eg 'bin' --> '.' */ |
660 |
return ospath_new_noclean("."); |
661 |
#endif |
662 |
} |
663 |
} |
664 |
|
665 |
M("Creating 'sub'"); |
666 |
fp1 = ospath_new_noclean(sub); |
667 |
M("... 'sub'"); |
668 |
D(fp1); |
669 |
return fp1; |
670 |
} |
671 |
|
672 |
struct FilePath *ospath_getparentatdepthn(struct FilePath *fp, unsigned depth) |
673 |
{ |
674 |
int startslash; |
675 |
char path[PATH_MAX]; |
676 |
char *temp; |
677 |
char *p; |
678 |
STRTOKVAR(nexttok); |
679 |
#ifdef WINPATHS |
680 |
char temp2[PATH_MAX]; |
681 |
#endif |
682 |
|
683 |
if( |
684 |
!ospath_isvalid(fp) |
685 |
|| depth >= ospath_depth(fp) |
686 |
){ |
687 |
return fp; |
688 |
} |
689 |
|
690 |
/* create FilePath object to parent object at depth N relative to this |
691 |
path object.*/ |
692 |
startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR); |
693 |
|
694 |
/* create a copy of fp->path.*/ |
695 |
STRCPY(path, fp->path); |
696 |
|
697 |
/* reset fp->path as required.*/ |
698 |
temp = startslash ? PATH_SEPARATOR_STR : ""; |
699 |
|
700 |
/* split path into it tokens. |
701 |
M("STARTING STRTOK");*/ |
702 |
p = STRTOK(path, PATH_SEPARATOR_STR, nexttok); |
703 |
|
704 |
while(p && depth > 0) |
705 |
{ |
706 |
if(strlen(temp) > 0 && temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR) |
707 |
{ |
708 |
strcat(temp,PATH_SEPARATOR_STR); |
709 |
} |
710 |
|
711 |
STRCAT(temp,p); |
712 |
--depth; |
713 |
|
714 |
p = STRTOK(NULL, PATH_SEPARATOR_STR, nexttok); |
715 |
} |
716 |
#if 0 |
717 |
M("FINISHED STRTOK"); |
718 |
#endif |
719 |
|
720 |
/* put / on end as required*/ |
721 |
if(strlen(temp) > 0 ? (temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR) : 1) |
722 |
{ |
723 |
strcat(temp,PATH_SEPARATOR_STR); |
724 |
} |
725 |
|
726 |
#ifdef WINPATHS |
727 |
STRCPY(temp2,fp->drive); |
728 |
STRCAT(temp2,temp); |
729 |
return ospath_new_noclean(temp2); |
730 |
#else |
731 |
return ospath_new_noclean(temp); |
732 |
#endif |
733 |
} |
734 |
|
735 |
char *ospath_getbasefilename(struct FilePath *fp){ |
736 |
char *temp; |
737 |
unsigned length, offset; |
738 |
char *pos; |
739 |
|
740 |
if(fp==NULL)return NULL; |
741 |
|
742 |
if(strlen(fp->path) == 0){ |
743 |
/* return empty name.*/ |
744 |
return ""; |
745 |
} |
746 |
|
747 |
if(fp->path[strlen(fp->path)-1]==PATH_SEPARATOR_CHAR){ |
748 |
return NULL; |
749 |
} |
750 |
|
751 |
/* reverse find '/' but DON'T ignore a trailing slash*/ |
752 |
/* (this is changed from the original implementation)*/ |
753 |
length = strlen(fp->path); |
754 |
offset = length; |
755 |
|
756 |
pos = strrchr(fp->path, PATH_SEPARATOR_CHAR); /* OFFSET! */ |
757 |
|
758 |
/* extract filename given position of find / and return it.*/ |
759 |
if(pos != NULL){ |
760 |
unsigned length1 = length - ((pos - fp->path)); |
761 |
temp = (char *)MALLOC(sizeof(char)*(length1+1)); |
762 |
|
763 |
V(length1); |
764 |
STRNCPY(temp, pos + 1, length1); |
765 |
*(temp + length1)='\0'; |
766 |
return temp; |
767 |
}else{ |
768 |
temp = (char *)MALLOC(sizeof(char)*(length+1)); |
769 |
STRNCPY(temp, fp->path, length); |
770 |
*(temp+length)='\0'; |
771 |
return temp; |
772 |
} |
773 |
} |
774 |
|
775 |
char *ospath_getfilestem(struct FilePath *fp){ |
776 |
char *temp; |
777 |
char *pos; |
778 |
|
779 |
if(!ospath_isvalid(fp)){ |
780 |
return NULL; |
781 |
} |
782 |
|
783 |
temp = ospath_getbasefilename(fp); |
784 |
if(temp==NULL){ |
785 |
/* it's a directory*/ |
786 |
return NULL; |
787 |
} |
788 |
|
789 |
pos = strrchr(temp,'.'); |
790 |
|
791 |
if(pos==NULL || pos==temp){ |
792 |
/* no extension, or a filename starting with '.' |
793 |
-- return the whole filename*/ |
794 |
return temp; |
795 |
} |
796 |
|
797 |
/* remove extension.*/ |
798 |
*pos = '\0'; |
799 |
|
800 |
return temp; |
801 |
} |
802 |
|
803 |
char *ospath_getfileext(struct FilePath *fp){ |
804 |
char *temp, *temp2, *pos; |
805 |
int len1; |
806 |
|
807 |
if(!ospath_isvalid(fp)){ |
808 |
return NULL; |
809 |
} |
810 |
|
811 |
temp = ospath_getbasefilename(fp); |
812 |
if(temp==NULL){ |
813 |
/* it's a directory*/ |
814 |
return NULL; |
815 |
} |
816 |
|
817 |
/* make sure there is no / on the end. |
818 |
FIXME: is this good policy, removing a trailing slash?*/ |
819 |
if(temp[strlen(temp) - 1] == PATH_SEPARATOR_CHAR){ |
820 |
temp[strlen(temp)-1] = '\0'; |
821 |
} |
822 |
|
823 |
pos = strrchr(temp,'.'); |
824 |
|
825 |
if(pos != NULL && pos!=temp){ |
826 |
/* extract extension.*/ |
827 |
len1 = temp + strlen(temp) - pos + 1; |
828 |
temp2 = (char *)MALLOC(sizeof(char)*len1); |
829 |
STRNCPY(temp2, pos, len1); |
830 |
}else{ |
831 |
/* no extension*/ |
832 |
temp2 = NULL; |
833 |
} |
834 |
FREE(temp); |
835 |
return temp2; |
836 |
} |
837 |
|
838 |
int ospath_isroot(struct FilePath *fp) |
839 |
{ |
840 |
if(!ospath_isvalid(fp)) |
841 |
{ |
842 |
return 0; |
843 |
} |
844 |
|
845 |
return fp->path == PATH_SEPARATOR_STR ? 1 : 0; |
846 |
} |
847 |
|
848 |
unsigned ospath_depth(struct FilePath *fp){ |
849 |
unsigned length; |
850 |
unsigned depth; |
851 |
unsigned i; |
852 |
|
853 |
length = strlen(fp->path); |
854 |
depth = 0; |
855 |
|
856 |
for(i = 0; i < length; i++){ |
857 |
if(fp->path[i] == PATH_SEPARATOR_CHAR){ |
858 |
++depth; |
859 |
} |
860 |
} |
861 |
|
862 |
if( |
863 |
depth > 0 |
864 |
&& length > 0 |
865 |
&& fp->path[length - 1] == PATH_SEPARATOR_CHAR |
866 |
){ |
867 |
/* PATH_SEPARATOR_CHAR on the end, reduce count by 1*/ |
868 |
--depth; |
869 |
} |
870 |
|
871 |
return depth; |
872 |
} |
873 |
|
874 |
struct FilePath *ospath_root(struct FilePath *fp){ |
875 |
#ifdef WINPATHS |
876 |
#if 0 |
877 |
M("WIN ROOT"); |
878 |
#endif |
879 |
char *temp; |
880 |
struct FilePath *r; |
881 |
|
882 |
if(strlen(fp->drive)){ |
883 |
temp = (char *)MALLOC(sizeof(char)*strlen(fp->drive)+1); |
884 |
STRCPY(temp,fp->drive); |
885 |
STRCAT(temp,PATH_SEPARATOR_STR); |
886 |
X(temp); |
887 |
r = ospath_new(temp); |
888 |
FREE(temp); |
889 |
}else{ |
890 |
r = ospath_new(fp->path); |
891 |
} |
892 |
return r; |
893 |
#else |
894 |
(void)fp; |
895 |
#if 0 |
896 |
M("JUST RETURNING PATH SEP"); |
897 |
#endif |
898 |
return ospath_new(PATH_SEPARATOR_STR); |
899 |
#endif |
900 |
} |
901 |
|
902 |
struct FilePath *ospath_getdir(struct FilePath *fp){ |
903 |
char *pos; |
904 |
char s[PATH_MAX]; |
905 |
#ifdef WINPATHS |
906 |
int e; |
907 |
#endif |
908 |
|
909 |
pos = strrchr(fp->path,PATH_SEPARATOR_CHAR); |
910 |
if(pos==NULL){ |
911 |
return ospath_new_noclean(""); |
912 |
} |
913 |
#ifdef WINPATHS |
914 |
strncpy(s,fp->drive,PATH_MAX); |
915 |
e = strlen(s); |
916 |
strncat(s,fp->path,pos - fp->path); |
917 |
s[e+pos-fp->path]='\0'; |
918 |
#else |
919 |
strncpy(s,fp->path,pos - fp->path); |
920 |
s[pos-fp->path]='\0'; |
921 |
/* CONSOLE_DEBUG("DIRECTORY: '%s'",s); */ |
922 |
#endif |
923 |
return ospath_new(s); |
924 |
} |
925 |
|
926 |
ASC_DLLSPEC struct FilePath *ospath_getabs(struct FilePath *fp){ |
927 |
struct FilePath *fp1, *fp2; |
928 |
if(fp->path[0]==PATH_SEPARATOR_CHAR){ |
929 |
fp1 = ospath_new_copy(fp); |
930 |
}else{ |
931 |
fp2 = ospath_new("."); |
932 |
fp1 = ospath_concat(fp2,fp); |
933 |
ospath_free(fp2); |
934 |
} |
935 |
return fp1; |
936 |
} |
937 |
|
938 |
int ospath_cmp(struct FilePath *fp1, struct FilePath *fp2){ |
939 |
char temp[2][PATH_MAX]; |
940 |
#ifdef WINPATHS |
941 |
char *p; |
942 |
struct FilePath *fp; |
943 |
#endif |
944 |
|
945 |
if(!ospath_isvalid(fp1)){ |
946 |
if(!ospath_isvalid(fp2)){ |
947 |
return 0; |
948 |
}else{ |
949 |
return -1; |
950 |
} |
951 |
}else if(!ospath_isvalid(fp2)){ |
952 |
return 1; |
953 |
} |
954 |
|
955 |
#if 0 |
956 |
/ now, both are valid... |
957 |
M("BOTH ARE VALID"); |
958 |
|
959 |
/Check that paths both have drives, if applic. |
960 |
#endif |
961 |
#ifdef WINPATHS |
962 |
if(strcmp(fp1->drive,"")==0){ |
963 |
M("PATH IS MISSING DRIVE LETTER"); |
964 |
D(fp1); |
965 |
fp = ospath_getcwd(); |
966 |
assert(strlen(fp->drive)!=0); |
967 |
X(fp->drive); |
968 |
STRCPY(temp[0],fp->drive); |
969 |
ospath_free(fp); |
970 |
}else{ |
971 |
STRCPY(temp[0],fp1->drive); |
972 |
} |
973 |
|
974 |
if(strcmp(fp2->drive,"")==0){ |
975 |
M("PATH IS MISSING DRIVE LETTER"); |
976 |
D(fp2); |
977 |
fp = ospath_getcwd(); |
978 |
assert(strlen(fp->drive)!=0); |
979 |
X(fp->drive); |
980 |
STRCPY(temp[1],fp->drive); |
981 |
ospath_free(fp); |
982 |
}else{ |
983 |
STRCPY(temp[1],fp2->drive); |
984 |
} |
985 |
|
986 |
STRCAT(temp[0],fp1->path); |
987 |
STRCAT(temp[1],fp2->path); |
988 |
#else |
989 |
STRCPY(temp[0], fp1->path); |
990 |
STRCPY(temp[1], fp2->path); |
991 |
#endif |
992 |
|
993 |
#ifdef WINPATHS |
994 |
X(temp[0]); |
995 |
for(p=temp[0];*p!='\0';++p){ |
996 |
*p=tolower(*p); |
997 |
#if 0 |
998 |
C(*p); |
999 |
#endif |
1000 |
} |
1001 |
X(temp[1]); |
1002 |
for(p=temp[1];*p!='\0';++p){ |
1003 |
*p=tolower(*p); |
1004 |
#if 0 |
1005 |
C(*p); |
1006 |
#endif |
1007 |
} |
1008 |
X(temp[0]); |
1009 |
X(temp[1]); |
1010 |
#endif |
1011 |
|
1012 |
/* we will count two paths that different only in a trailing slash to be the *same* |
1013 |
so we add trailing slashes to both now: */ |
1014 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR){ |
1015 |
STRCAT(temp[0],PATH_SEPARATOR_STR); |
1016 |
} |
1017 |
|
1018 |
if(temp[1][strlen(temp[1]) - 1] != PATH_SEPARATOR_CHAR){ |
1019 |
STRCAT(temp[1],PATH_SEPARATOR_STR); |
1020 |
} |
1021 |
|
1022 |
#if 0 |
1023 |
X(temp[0]); |
1024 |
X(temp[1]); |
1025 |
#endif |
1026 |
|
1027 |
return strcmp(temp[0],temp[1]); |
1028 |
} |
1029 |
|
1030 |
struct FilePath *ospath_concat(struct FilePath *fp1, struct FilePath *fp2){ |
1031 |
|
1032 |
struct FilePath *fp; |
1033 |
char temp[2][PATH_MAX]; |
1034 |
char temp2[PATH_MAX]; |
1035 |
struct FilePath *r; |
1036 |
|
1037 |
fp = (struct FilePath *)MALLOC(sizeof(struct FilePath)); |
1038 |
|
1039 |
if(!ospath_isvalid(fp1)){ |
1040 |
if(ospath_isvalid(fp2)){ |
1041 |
ospath_copy(fp,fp2); |
1042 |
}else{ |
1043 |
/* both invalid*/ |
1044 |
ospath_copy(fp,fp1); |
1045 |
} |
1046 |
return fp; |
1047 |
} |
1048 |
|
1049 |
if(!ospath_isvalid(fp2)){ |
1050 |
ospath_copy(fp,fp1); |
1051 |
return fp; |
1052 |
} |
1053 |
|
1054 |
/* not just a copy of one or the other...*/ |
1055 |
ospath_free(fp); |
1056 |
|
1057 |
/* now, both paths are valid...*/ |
1058 |
|
1059 |
#ifdef WINPATHS |
1060 |
STRNCPY(temp[0],fp1->drive,PATH_MAX); |
1061 |
STRNCAT(temp[0],fp1->path,PATH_MAX-strlen(temp[0])); |
1062 |
#else |
1063 |
STRNCPY(temp[0], fp1->path,PATH_MAX); |
1064 |
#endif |
1065 |
|
1066 |
STRNCPY(temp[1], fp2->path,PATH_MAX); |
1067 |
|
1068 |
/* make sure temp has a / on the end. */ |
1069 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR) |
1070 |
{ |
1071 |
STRNCAT(temp[0],PATH_SEPARATOR_STR,PATH_MAX-strlen(temp[0])); |
1072 |
} |
1073 |
|
1074 |
#ifdef DO_FIXSLASHES |
1075 |
ospath_fixslash(temp[0]); |
1076 |
ospath_fixslash(temp[1]); |
1077 |
#endif |
1078 |
|
1079 |
#if 0 |
1080 |
V(strlen(temp[0])); |
1081 |
X(temp[0]); |
1082 |
V(strlen(temp[1])); |
1083 |
X(temp[1]); |
1084 |
#endif |
1085 |
|
1086 |
/* make sure rhs path has NOT got a / at the start. */ |
1087 |
if(temp[1][0] == PATH_SEPARATOR_CHAR){ |
1088 |
return NULL; |
1089 |
} |
1090 |
|
1091 |
/* create a new path object with the two path strings appended together.*/ |
1092 |
STRNCPY(temp2,temp[0],PATH_MAX); |
1093 |
STRNCAT(temp2,temp[1],PATH_MAX-strlen(temp2)); |
1094 |
#if 0 |
1095 |
V(strlen(temp2)); |
1096 |
X(temp2); |
1097 |
#endif |
1098 |
r = ospath_new_noclean(temp2); |
1099 |
D(r); |
1100 |
|
1101 |
/* ospath_cleanup(r);*/ |
1102 |
return r; |
1103 |
} |
1104 |
|
1105 |
void ospath_append(struct FilePath *fp, struct FilePath *fp1){ |
1106 |
char *p; |
1107 |
char temp[2][PATH_MAX]; |
1108 |
struct FilePath fp2; |
1109 |
|
1110 |
ospath_copy(&fp2,fp1); |
1111 |
#ifdef DO_FIXSLASHES |
1112 |
ospath_fixslash(fp2.path); |
1113 |
#endif |
1114 |
|
1115 |
if(!ospath_isvalid(&fp2)){ |
1116 |
M("fp1 invalid"); |
1117 |
return; |
1118 |
} |
1119 |
|
1120 |
if(!ospath_isvalid(fp) && ospath_isvalid(&fp2)){ |
1121 |
/* set this object to be the same as the rhs */ |
1122 |
M("fp invalid"); |
1123 |
ospath_copy(fp,&fp2); |
1124 |
#ifdef DO_FIXSLASHES |
1125 |
ospath_fixslash(fp->path); |
1126 |
#endif |
1127 |
return; |
1128 |
} |
1129 |
|
1130 |
X(fp->path); |
1131 |
X(fp2.path); |
1132 |
|
1133 |
/* both paths are valid...*/ |
1134 |
#if 0 |
1135 |
temp[0] = CALLOC(1+strlen(fp->path), sizeof(char)); |
1136 |
#endif |
1137 |
STRNCPY(temp[0], fp->path, PATH_MAX); |
1138 |
#if 0 |
1139 |
temp[1] = CALLOC(strlen(fp2.path), sizeof(char)); |
1140 |
#endif |
1141 |
STRNCPY(temp[1], fp2.path, PATH_MAX); |
1142 |
|
1143 |
X(temp[0]); |
1144 |
X(temp[1]); |
1145 |
|
1146 |
/* make sure temp has a / on the end. */ |
1147 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR) |
1148 |
{ |
1149 |
STRCAT(temp[0],PATH_SEPARATOR_STR); |
1150 |
} |
1151 |
|
1152 |
/* make sure rhs path has NOT got a / at the start. */ |
1153 |
if(temp[1][0] == PATH_SEPARATOR_CHAR){ |
1154 |
for(p=temp[1]+1; *p != '\0'; ++p){ |
1155 |
*(p-1)=*p; |
1156 |
} |
1157 |
*(p-1)='\0'; |
1158 |
} |
1159 |
|
1160 |
X(temp[0]); |
1161 |
X(temp[1]); |
1162 |
|
1163 |
/*create new path string.*/ |
1164 |
STRNCPY(fp->path,temp[0], PATH_MAX); |
1165 |
STRNCAT(fp->path,temp[1], PATH_MAX-strlen(fp->path)); |
1166 |
|
1167 |
X(fp->path); |
1168 |
|
1169 |
#if 0 |
1170 |
FREE(temp[0]); |
1171 |
M("Freed temp[0]"); |
1172 |
FREE(temp[1]); |
1173 |
M("Freed temp[1]"); |
1174 |
#endif |
1175 |
|
1176 |
D(fp); |
1177 |
ospath_cleanup(fp); |
1178 |
} |
1179 |
|
1180 |
void ospath_copy(struct FilePath *dest, struct FilePath *src){ |
1181 |
STRCPY(dest->path,src->path); |
1182 |
#ifdef WINPATHS |
1183 |
STRCPY(dest->drive,src->drive); |
1184 |
#endif |
1185 |
} |
1186 |
|
1187 |
void ospath_debug(struct FilePath *fp){ |
1188 |
#ifdef WINPATHS |
1189 |
fprintf(stderr,"{\"%s\",\"%s\"}\n",fp->drive,fp->path); |
1190 |
#else |
1191 |
fprintf(stderr,"{\"%s\"}\n",fp->path); |
1192 |
#endif |
1193 |
} |
1194 |
|
1195 |
FILE *ospath_fopen(struct FilePath *fp, const char *mode){ |
1196 |
char s[PATH_MAX]; |
1197 |
FILE *f; |
1198 |
|
1199 |
if(!ospath_isvalid(fp)){ |
1200 |
E("Invalid path"); |
1201 |
return NULL; |
1202 |
} |
1203 |
ospath_strncpy(fp,s,PATH_MAX); |
1204 |
f = fopen(s,mode); |
1205 |
return f; |
1206 |
} |
1207 |
|
1208 |
int ospath_stat(struct FilePath *fp,ospath_stat_t *buf){ |
1209 |
char s[PATH_MAX]; |
1210 |
|
1211 |
if(!ospath_isvalid(fp)){ |
1212 |
E("Invalid path"); |
1213 |
return -1; |
1214 |
} |
1215 |
ospath_strncpy(fp,s,PATH_MAX); |
1216 |
return STAT(s,buf); |
1217 |
} |
1218 |
|
1219 |
/*------------------------ |
1220 |
SEARCH PATH FUNCTIONS |
1221 |
*/ |
1222 |
|
1223 |
struct FilePath **ospath_searchpath_new(const char *path){ |
1224 |
char *p; |
1225 |
char *list[LISTMAX]; |
1226 |
unsigned n=0; |
1227 |
char *c; |
1228 |
unsigned i; |
1229 |
struct FilePath **pp; |
1230 |
char path1[PATH_MAX]; |
1231 |
|
1232 |
STRTOKVAR(nexttok); |
1233 |
|
1234 |
strncpy(path1,path,PATH_MAX); |
1235 |
|
1236 |
X(path1); |
1237 |
X(PATH_LISTSEP_STR); |
1238 |
|
1239 |
V(strlen(path1)); |
1240 |
V(strlen(PATH_LISTSEP_STR)); |
1241 |
|
1242 |
/* |
1243 |
c = strstr(path,PATH_LISTSEP_CHAR); |
1244 |
if(c==NULL){ |
1245 |
E("NO TOKEN FOUND"); |
1246 |
} |
1247 |
*/ |
1248 |
|
1249 |
p=STRTOK(path1,PATH_LISTSEP_STR,nexttok); |
1250 |
X(p); |
1251 |
for(; p!= NULL; p=STRTOK(NULL,PATH_LISTSEP_STR,nexttok)){ |
1252 |
c = (char *)MALLOC(sizeof(char)*(strlen(p)+1)); |
1253 |
X(p); |
1254 |
STRCPY(c,p); |
1255 |
if(n>=LISTMAX){ |
1256 |
E("IGNORING SOME PATH COMPONENTS"); |
1257 |
break; |
1258 |
} |
1259 |
list[n++]=c; |
1260 |
} |
1261 |
|
1262 |
|
1263 |
for(i=0;i<n;++i){ |
1264 |
X(list[i]); |
1265 |
} |
1266 |
V(n); |
1267 |
|
1268 |
|
1269 |
pp = (struct FilePath **)MALLOC(sizeof(struct FilePath*)*(n+1)); |
1270 |
for(i=0; i<n; ++i){ |
1271 |
#if 0 |
1272 |
V(i); |
1273 |
X(list[i]); |
1274 |
#endif |
1275 |
pp[i] = ospath_new_noclean(list[i]); |
1276 |
#if 0 |
1277 |
D(pp[i]); |
1278 |
#endif |
1279 |
FREE(list[i]); |
1280 |
} |
1281 |
pp[n] = NULL; |
1282 |
|
1283 |
for(i=0;i<n;++i){ |
1284 |
#ifdef DO_FIXSLASHES |
1285 |
ospath_fixslash(pp[i]->path); |
1286 |
#endif |
1287 |
D(pp[i]); |
1288 |
} |
1289 |
|
1290 |
return pp; |
1291 |
} |
1292 |
|
1293 |
void ospath_searchpath_free(struct FilePath **searchpath){ |
1294 |
struct FilePath **p; |
1295 |
for(p=searchpath; *p!=NULL; ++p){ |
1296 |
ospath_free(*p); |
1297 |
} |
1298 |
FREE(searchpath); |
1299 |
} |
1300 |
|
1301 |
int ospath_searchpath_length(struct FilePath **searchpath){ |
1302 |
int i=0; |
1303 |
struct FilePath **p; |
1304 |
for(p=searchpath; *p!=NULL; ++p){ |
1305 |
++i; |
1306 |
} |
1307 |
return i; |
1308 |
} |
1309 |
|
1310 |
struct FilePath *ospath_searchpath_iterate( |
1311 |
struct FilePath **searchpath |
1312 |
, FilePathTestFn *testfn |
1313 |
, void *searchdata |
1314 |
){ |
1315 |
struct FilePath **p; |
1316 |
|
1317 |
p = searchpath; |
1318 |
|
1319 |
M("SEARCHING IN..."); |
1320 |
for(p=searchpath; *p!=NULL; ++p){ |
1321 |
D(*p); |
1322 |
} |
1323 |
|
1324 |
for(p=searchpath; *p!=NULL; ++p){ |
1325 |
D(*p); |
1326 |
assert(*p!=NULL); |
1327 |
if((*testfn)(*p,searchdata)){ |
1328 |
return *p; |
1329 |
} |
1330 |
} |
1331 |
return NULL; |
1332 |
} |