1 |
#include <string.h> |
2 |
#include <malloc.h> |
3 |
#include <stdio.h> |
4 |
#include <ctype.h> |
5 |
|
6 |
#include "ospath.h" |
7 |
|
8 |
// to test this code, 'gcc -DTEST ospath.c && ./a' |
9 |
|
10 |
#if defined(WIN32) || defined(__WIN32) || defined(_MSC_VER) |
11 |
# ifndef __WIN32__ |
12 |
# define __WIN32__ |
13 |
# endif |
14 |
#endif |
15 |
|
16 |
#define VERBOSE |
17 |
|
18 |
#if !defined(TEST) && !defined(VERBOSE) |
19 |
# define NDEBUG |
20 |
#endif |
21 |
|
22 |
//#define TRY_GETPWUID |
23 |
|
24 |
#define DO_FIXSLASHES |
25 |
|
26 |
#ifndef NDEBUG |
27 |
# include <assert.h> |
28 |
# define M(MSG) fprintf(stderr,"%s:%d: (%s) %s\n",__FILE__,__LINE__,__FUNCTION__,MSG) |
29 |
# define X(VAR) fprintf(stderr,"%s:%d: (%s) %s=%s\n",__FILE__,__LINE__,__FUNCTION__,#VAR,VAR) |
30 |
# define V(VAR) fprintf(stderr,"%s:%d: (%s) %s=%d\n",__FILE__,__LINE__,__FUNCTION__,#VAR,(VAR)) |
31 |
# define D(VAR) fprintf(stderr,"%s:%d: (%s) %s=",__FILE__,__LINE__,__FUNCTION__,#VAR);ospath_debug(VAR) |
32 |
#else |
33 |
# include <assert.h> |
34 |
# define M(MSG) ((void)0) |
35 |
# define X(VAR) ((void)0) |
36 |
# define V(VAR) ((void)0) |
37 |
# define D(VAR) ((void)0) |
38 |
#endif |
39 |
|
40 |
#if defined(__WIN32__) && !defined(__MINGW32__) |
41 |
# include <direct.h> |
42 |
# include <stdlib.h> |
43 |
# define STRCPY strcpy |
44 |
# define STRNCPY(dest,src,n) strncpy_s(dest,n,src,n) |
45 |
# define STRCAT strcat |
46 |
# define STRNCAT strncat |
47 |
# define STRTOK(STR,PAT,VAR) strtok_s(STR,PAT,&VAR) |
48 |
# define STRTOKVAR(VAR) char *VAR |
49 |
# define GETCWD getcwd |
50 |
# define GETENV(VAR) getenv(VAR) |
51 |
#else |
52 |
# define STRCPY strcpy |
53 |
# define STRNCPY(dest,src,n) strncpy(dest,src,n) |
54 |
# define STRCAT strcat |
55 |
# define STRNCAT strncat |
56 |
# define STRTOK(STR,PAT,VAR) strtok(STR,PAT) |
57 |
# define STRTOKVAR(VAR) ((void)0) |
58 |
# define GETCWD getcwd |
59 |
# define GETENV(VAR) getenv(VAR) |
60 |
#endif |
61 |
|
62 |
// PATH_MAX is in ospath.h |
63 |
#define DRIVEMAX 3 |
64 |
#define LISTMAX 256 |
65 |
|
66 |
#ifdef __WIN32__ /* && !defined(__MINGW32__) */ |
67 |
# define WINPATHS |
68 |
#endif |
69 |
|
70 |
struct FilePath{ |
71 |
char path[PATH_MAX]; /// the string version of the represented POSIX path |
72 |
|
73 |
#ifdef WINPATHS |
74 |
char drive[DRIVEMAX]; /// the drive the path resides on (field is absent in POSIX systems) |
75 |
#endif |
76 |
}; |
77 |
|
78 |
#include <string.h> |
79 |
|
80 |
#define MALLOC malloc |
81 |
#define FREE free |
82 |
#define CALLOC calloc |
83 |
|
84 |
#define E(MSG) fprintf(stderr,"%s:%d: (%s) ERROR: %s\n",__FILE__,__LINE__,__FUNCTION__,MSG) |
85 |
|
86 |
#ifdef DO_FIXSLASHES |
87 |
void ospath_fixslash(char *path); |
88 |
#endif |
89 |
|
90 |
struct FilePath *ospath_getcwd(); |
91 |
|
92 |
/** |
93 |
This function cleans up the path string used to construct the FilePath object: |
94 |
1. Get rid of multiple / 's one after the other... |
95 |
|
96 |
ie. "///usr/bin///hello/////there// --> "/usr/bin/hello/there/" |
97 |
|
98 |
2. Resolve a leading tilde (~) to the current user's HOME path |
99 |
|
100 |
3. Remove redundant /./ in middle of path |
101 |
|
102 |
4. Remove reduncant dir/.. in path |
103 |
|
104 |
5. Environment substitution?? |
105 |
|
106 |
6. On windows, drive reference if not specified |
107 |
|
108 |
7. What about \\server\path and URLs, gnomefs, etc? |
109 |
*/ |
110 |
void ospath_cleanup(struct FilePath *); |
111 |
|
112 |
void ospath_copy(struct FilePath *dest, struct FilePath *src); |
113 |
|
114 |
|
115 |
#ifdef WINPATHS |
116 |
/** |
117 |
This function splits out the drive letter in the path string, thus completing |
118 |
the correct construction of a FilePath object under Win32. |
119 |
*/ |
120 |
void ospath_extractdriveletter(struct FilePath *); |
121 |
#endif |
122 |
|
123 |
#ifdef WINPATHS |
124 |
# define PATH_SEPARATOR_STR "\\" |
125 |
# define PATH_SEPARATOR_CHAR '\\' |
126 |
# define PATH_LISTSEP_CHAR ';' |
127 |
# define PATH_LISTSEP_STR ";" |
128 |
# define PATH_WRONGSLASH_CHAR '/' |
129 |
# define PATH_WRONGSLASH_STR "/" |
130 |
#else |
131 |
# define PATH_SEPARATOR_STR "/" |
132 |
# define PATH_SEPARATOR_CHAR '/' |
133 |
# define PATH_LISTSEP_CHAR ':' |
134 |
# define PATH_LISTSEP_STR ":" |
135 |
# define PATH_WRONGSLASH_CHAR '\\' |
136 |
# define PATH_WRONGSLASH_STR "\\" |
137 |
#endif |
138 |
|
139 |
/** |
140 |
Create a new path structure from a string |
141 |
*/ |
142 |
struct FilePath *ospath_new(const char *path){ |
143 |
struct FilePath *fp; |
144 |
fp = MALLOC(sizeof(struct FilePath)); |
145 |
STRNCPY(fp->path, path, PATH_MAX); |
146 |
//X(fp->path); |
147 |
//X(path); |
148 |
assert(strcmp(fp->path,path)==0); |
149 |
#ifdef WINPATHS |
150 |
//X(fp->drive); |
151 |
ospath_extractdriveletter(fp); |
152 |
#endif |
153 |
|
154 |
//X(fp->drive); |
155 |
|
156 |
#ifdef DO_FIXSLASHES |
157 |
ospath_fixslash(fp->path); |
158 |
#endif |
159 |
|
160 |
ospath_cleanup(fp); |
161 |
|
162 |
//D(fp); |
163 |
|
164 |
return fp; |
165 |
} |
166 |
|
167 |
void ospath_free(struct FilePath *fp){ |
168 |
FREE(fp); |
169 |
} |
170 |
|
171 |
/** |
172 |
This function will serve to allow #include-style file paths |
173 |
to be specified with platform-independent forward slashes then |
174 |
translated into the local filesystem format for subsequent use. |
175 |
|
176 |
This method should be identical to ospath_new on posix, right? |
177 |
|
178 |
@NOTE: on windows, we also want: |
179 |
C:dir/file --> c:$PWD\dir\file |
180 |
e:/hello --> e:\hello |
181 |
here/i/am --> here\i\am |
182 |
|
183 |
@NOTE: |
184 |
A path-search function should create full file paths by |
185 |
appending relative file to each component of the search path |
186 |
then performing a callback on each one to determine if the |
187 |
match is OK or not. |
188 |
*/ |
189 |
struct FilePath *ospath_new_from_posix(const char *posixpath){ |
190 |
struct FilePath *fp = MALLOC(sizeof(struct FilePath)); |
191 |
STRNCPY(fp->path,posixpath,PATH_MAX); |
192 |
#ifdef WINPATHS |
193 |
X(fp->path); |
194 |
ospath_extractdriveletter(fp); |
195 |
#endif |
196 |
|
197 |
#ifdef DO_FIXSLASHES |
198 |
ospath_fixslash(fp->path); |
199 |
#endif |
200 |
|
201 |
//X(fp->path); |
202 |
|
203 |
ospath_cleanup(fp); |
204 |
|
205 |
return fp; |
206 |
} |
207 |
|
208 |
#ifdef DO_FIXSLASHES |
209 |
void ospath_fixslash(char *path){ |
210 |
|
211 |
char *p; |
212 |
char temp[PATH_MAX]; |
213 |
int startslash; |
214 |
int endslash; |
215 |
STRTOKVAR(nexttok); |
216 |
|
217 |
STRNCPY(temp,path,PATH_MAX); |
218 |
|
219 |
//X(path); |
220 |
|
221 |
startslash = (strlen(temp) > 0 && temp[0] == PATH_WRONGSLASH_CHAR); |
222 |
endslash = (strlen(temp) > 1 && temp[strlen(temp) - 1] == PATH_WRONGSLASH_CHAR); |
223 |
|
224 |
//V(startslash); |
225 |
//V(endslash); |
226 |
|
227 |
// reset fp->path as required. |
228 |
STRNCPY(path, (startslash ? PATH_SEPARATOR_STR : ""), PATH_MAX); |
229 |
|
230 |
//M("STARTING STRTOK"); |
231 |
for(p = STRTOK(temp, PATH_WRONGSLASH_STR,nexttok); |
232 |
p!=NULL; |
233 |
p = STRTOK(NULL,PATH_WRONGSLASH_STR,nexttok) |
234 |
){ |
235 |
// add a separator if we've already got some stuff |
236 |
if( |
237 |
strlen(path) > 0 |
238 |
&& path[strlen(path) - 1] != PATH_SEPARATOR_CHAR |
239 |
){ |
240 |
STRCAT(path,PATH_SEPARATOR_STR); |
241 |
} |
242 |
|
243 |
STRCAT(path,p); |
244 |
} |
245 |
//M("FINISHED STRTOK"); |
246 |
|
247 |
// put / on end as required, according to what the starting path had |
248 |
if(endslash && (strlen(path) > 0 ? (path[strlen(path) - 1] != PATH_SEPARATOR_CHAR) : 1)) |
249 |
{ |
250 |
//M("adding endslash!"); |
251 |
|
252 |
STRCAT(path, PATH_SEPARATOR_STR); |
253 |
} |
254 |
|
255 |
//X(path); |
256 |
} |
257 |
#endif |
258 |
|
259 |
|
260 |
/// Create but with no 'cleanup' call |
261 |
struct FilePath *ospath_new_noclean(const char *path){ |
262 |
struct FilePath *fp = MALLOC(sizeof(struct FilePath)); |
263 |
STRNCPY(fp->path,path,PATH_MAX); |
264 |
|
265 |
#ifdef WINPATHS |
266 |
//X(fp->path); |
267 |
ospath_extractdriveletter(fp); |
268 |
#endif |
269 |
|
270 |
//D(fp); |
271 |
|
272 |
/* |
273 |
#ifdef DO_FIXSLASHES |
274 |
ospath_fixslash(fp->path); |
275 |
D(fp); |
276 |
#endif |
277 |
*/ |
278 |
return fp; |
279 |
} |
280 |
|
281 |
struct FilePath *ospath_getcwd(void){ |
282 |
struct FilePath *fp = MALLOC(sizeof(struct FilePath)); |
283 |
char *cwd; |
284 |
|
285 |
// get current working directory |
286 |
cwd = (char *)GETCWD(NULL, 0); |
287 |
|
288 |
// create new path with resolved working directory |
289 |
fp = ospath_new_noclean(cwd != NULL ? cwd : "."); |
290 |
|
291 |
D(fp); |
292 |
|
293 |
return fp; |
294 |
} |
295 |
|
296 |
/** |
297 |
Use getenv() function to retrieve HOME path, or if not set, use |
298 |
the password database and try to retrieve it that way (???) |
299 |
*/ |
300 |
struct FilePath *ospath_gethomepath(void){ |
301 |
|
302 |
const char *pfx = (const char *)getenv("HOME"); |
303 |
struct FilePath *fp; |
304 |
|
305 |
#ifndef __WIN32__ |
306 |
# ifdef TRY_GETPWUID |
307 |
struct passwd *pw; |
308 |
|
309 |
if(pfx==NULL){ |
310 |
pw = (struct passwd*)getpwuid(getuid()); |
311 |
|
312 |
if(pw){ |
313 |
pfx = pw->pw_dir; |
314 |
} |
315 |
} |
316 |
# endif |
317 |
#endif |
318 |
|
319 |
// create path object from HOME, but don't compress it |
320 |
// (because that would lead to an infinite loop) |
321 |
fp = ospath_new_noclean(pfx ? pfx : ""); |
322 |
|
323 |
#ifdef DO_FIXSLASHES |
324 |
ospath_fixslash(fp->path); |
325 |
#endif |
326 |
|
327 |
return fp; |
328 |
} |
329 |
|
330 |
#ifdef WINPATHS |
331 |
void ospath_extractdriveletter(struct FilePath *fp) |
332 |
{ |
333 |
char *p; |
334 |
//M("SOURCE"); |
335 |
//X(fp->path); |
336 |
//fprintf(stderr,"CHAR 1 = %c\n",fp->path[1]); |
337 |
|
338 |
// extract the drive the path resides on... |
339 |
if(strlen(fp->path) >= 2 && fp->path[1] == ':') |
340 |
{ |
341 |
STRNCPY(fp->drive,fp->path,2); |
342 |
fp->drive[2]='\0'; |
343 |
for(p=fp->path+2; *p!='\0'; ++p){ |
344 |
*(p-2)=*p; |
345 |
} |
346 |
*(p-2)='\0'; |
347 |
}else{ |
348 |
STRNCPY(fp->drive,"",DRIVEMAX); |
349 |
} |
350 |
//M("RESULT"); |
351 |
//X(fp->path); |
352 |
//X(fp->drive); |
353 |
} |
354 |
#endif |
355 |
|
356 |
void ospath_cleanup(struct FilePath *fp){ |
357 |
char path[PATH_MAX]; |
358 |
char *p; |
359 |
struct FilePath *home; |
360 |
struct FilePath *working; |
361 |
struct FilePath *parent; |
362 |
STRTOKVAR(nexttok); |
363 |
|
364 |
// compress the path, and resolve ~ |
365 |
int startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR); |
366 |
int endslash = (strlen(fp->path) > 1 && fp->path[strlen(fp->path) - 1] == PATH_SEPARATOR_CHAR); |
367 |
|
368 |
//fprintf(stderr,"FS ON START = %d\n",startslash); |
369 |
//fprintf(stderr,"FS ON END = %d\n",endslash); |
370 |
//fprintf(stderr,"FIRST CHAR = %c\n",fp->path[0]); |
371 |
|
372 |
home = ospath_gethomepath(); |
373 |
|
374 |
// create a copy of fp->path. |
375 |
STRCPY(path, fp->path); |
376 |
|
377 |
// reset fp->path as required. |
378 |
STRCPY(fp->path, (startslash ? PATH_SEPARATOR_STR : "")); |
379 |
|
380 |
X(path); |
381 |
|
382 |
// split path into it tokens, using STRTOK which is NOT reentrant |
383 |
// so be careful! |
384 |
|
385 |
//M("STARTING STRTOK"); |
386 |
for(p = STRTOK(path, PATH_SEPARATOR_STR,nexttok); |
387 |
p!=NULL; |
388 |
p = STRTOK(NULL,PATH_SEPARATOR_STR,nexttok) |
389 |
){ |
390 |
//M("NEXT TOKEN"); |
391 |
//X(p); |
392 |
//X(path+strlen(p)+1); |
393 |
if(strcmp(p, "~")==0){ |
394 |
|
395 |
if(p == path){ // check that the ~ is the first character in the path |
396 |
if(ospath_isvalid(home)){ |
397 |
ospath_copy(fp,home); |
398 |
continue; |
399 |
}else{ |
400 |
E("HOME does not resolve to valid path"); |
401 |
} |
402 |
}else{ |
403 |
E("A tilde (~) present as a component in a file path must be at the start!"); |
404 |
} |
405 |
}else if(strcmp(p, ".") == 0){ |
406 |
|
407 |
if(p==path){// start of path: |
408 |
M("EXPANDING LEADING '.' IN PATH"); |
409 |
X(path); |
410 |
|
411 |
working = ospath_getcwd(); |
412 |
|
413 |
D(working); |
414 |
#ifdef WINPATHS |
415 |
X(working->drive); |
416 |
#endif |
417 |
X(p); |
418 |
X(path); |
419 |
|
420 |
ospath_copy(fp,working); |
421 |
|
422 |
|
423 |
D(fp); |
424 |
X(p); |
425 |
//X(path+strlen(p)+1); |
426 |
|
427 |
//ospath_free(working); |
428 |
continue; |
429 |
}else{// later in the path: just skip it |
430 |
M("SKIPPING '.' IN PATH"); |
431 |
continue; |
432 |
} |
433 |
|
434 |
}else if(strcmp(p, "..") == 0){ |
435 |
M("GOING TO PARENT"); |
436 |
parent = ospath_getparent(fp); |
437 |
if(ospath_isvalid(parent)){ |
438 |
ospath_copy(fp,parent); |
439 |
} |
440 |
//ospath_free(parent); |
441 |
continue; |
442 |
} |
443 |
|
444 |
// add a separator if we've already got some stuff |
445 |
if( |
446 |
strlen(fp->path) > 0 |
447 |
&& fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR |
448 |
){ |
449 |
STRCAT(fp->path,PATH_SEPARATOR_STR); |
450 |
} |
451 |
|
452 |
// add the present path component |
453 |
STRCAT(fp->path, p); |
454 |
} |
455 |
//M("FINISHED STRTOK"); |
456 |
|
457 |
// put / on end as required, according to what the starting path had |
458 |
if(endslash && (strlen(fp->path) > 0 ? (fp->path[strlen(fp->path) - 1] != PATH_SEPARATOR_CHAR) : 1)) |
459 |
{ |
460 |
STRCAT(fp->path, PATH_SEPARATOR_STR); |
461 |
} |
462 |
} |
463 |
|
464 |
|
465 |
int ospath_isvalid(struct FilePath *fp){ |
466 |
//if(fp==NULL) return 0; |
467 |
return strlen(fp->path) > 0 ? 1 : 0; |
468 |
} |
469 |
|
470 |
|
471 |
char *ospath_str(struct FilePath *fp){ |
472 |
char *s; |
473 |
#ifdef WINPATHS |
474 |
s = CALLOC(strlen(fp->drive)+strlen(fp->path),sizeof(char)); |
475 |
STRCPY(s,fp->drive); |
476 |
STRCAT(s,fp->path); |
477 |
#else |
478 |
s = CALLOC(strlen(fp->path),sizeof(char)); |
479 |
STRCPY(s,fp->path); |
480 |
#endif |
481 |
return s; |
482 |
} |
483 |
|
484 |
void ospath_strcpy(struct FilePath *fp, char *dest, int destsize){ |
485 |
#ifdef WINPATHS |
486 |
STRNCPY(dest,fp->drive,destsize); |
487 |
STRNCAT(dest,fp->path,destsize-strlen(dest)); |
488 |
#else |
489 |
STRNCPY(dest,fp->path,destsize); |
490 |
#endif |
491 |
} |
492 |
|
493 |
void ospath_fwrite(struct FilePath *fp, FILE *dest){ |
494 |
#ifdef WINPATHS |
495 |
fprintf(dest,"%s%s",fp->drive,fp->path); |
496 |
#else |
497 |
fprintf(dest,"%s",fp->path); |
498 |
#endif |
499 |
} |
500 |
|
501 |
unsigned ospath_length(struct FilePath *fp){ |
502 |
#ifdef WINPATHS |
503 |
// we've already validated this path, so it's on to just add it up |
504 |
// (unless someone has been tinkering with the internal structure here) |
505 |
return (unsigned) (strlen(fp->drive) + strlen(fp->path)); |
506 |
#else |
507 |
return (unsigned) (strlen(fp->path)); |
508 |
#endif |
509 |
} |
510 |
|
511 |
struct FilePath *ospath_getparent(struct FilePath *fp) |
512 |
{ |
513 |
int length; |
514 |
int offset; |
515 |
char *pos; |
516 |
int len1; |
517 |
char sub[PATH_MAX]; |
518 |
struct FilePath *fp1; |
519 |
|
520 |
D(fp); |
521 |
|
522 |
if(strlen(fp->path) == 0 || ospath_isroot(fp)) |
523 |
{ |
524 |
// return empty path. |
525 |
return ospath_new(""); |
526 |
} |
527 |
|
528 |
// reverse find a / ignoring the end / if it exists. |
529 |
/// FIXME |
530 |
length = strlen(fp->path); |
531 |
offset = ( |
532 |
fp->path[length - 1] == PATH_SEPARATOR_CHAR // last char is slash? |
533 |
&& length > 1 // and more than just leading slash... |
534 |
) ? length - 1 : length; // then remove last char |
535 |
|
536 |
for(pos = fp->path + offset - 1; *pos!=PATH_SEPARATOR_CHAR && pos>=fp->path; --pos){ |
537 |
//fprintf(stderr,"CURRENT CHAR: %c\n",*pos); |
538 |
} |
539 |
|
540 |
len1 = (int)pos - (int)fp->path; |
541 |
//fprintf(stderr,"POS = %d\n",len1); |
542 |
|
543 |
if(*pos==PATH_SEPARATOR_CHAR){ |
544 |
#ifdef WINPATHS |
545 |
STRCPY(sub,fp->drive); |
546 |
STRNCAT(sub,fp->path,len1); |
547 |
#else |
548 |
STRNCPY(sub,fp->path,len1); |
549 |
sub[len1]='\0'; |
550 |
#endif |
551 |
X(sub); |
552 |
if(strcmp(sub,"")==0){ |
553 |
M("DIRECTORY IS EMPTY"); |
554 |
STRCAT(sub,PATH_SEPARATOR_STR); |
555 |
} |
556 |
}else{ |
557 |
E("NO PARENT DIR"); |
558 |
return ospath_new_noclean(fp->path); |
559 |
} |
560 |
|
561 |
fp1 = ospath_new_noclean(sub); |
562 |
D(fp1); |
563 |
return fp1; |
564 |
} |
565 |
|
566 |
struct FilePath *ospath_getparentatdepthn(struct FilePath *fp, unsigned depth) |
567 |
{ |
568 |
int startslash; |
569 |
char path[PATH_MAX]; |
570 |
char *temp; |
571 |
char *p; |
572 |
STRTOKVAR(nexttok); |
573 |
#ifdef WINPATHS |
574 |
char temp2[PATH_MAX]; |
575 |
#endif |
576 |
|
577 |
if( |
578 |
!ospath_isvalid(fp) |
579 |
|| depth >= ospath_depth(fp) |
580 |
){ |
581 |
return fp; |
582 |
} |
583 |
|
584 |
// create FilePath object to parent object at depth N relative to this |
585 |
// path object. |
586 |
startslash = (strlen(fp->path) > 0 && fp->path[0] == PATH_SEPARATOR_CHAR); |
587 |
|
588 |
// create a copy of fp->path. |
589 |
STRCPY(path, fp->path); |
590 |
|
591 |
// reset fp->path as required. |
592 |
temp = startslash ? PATH_SEPARATOR_STR : ""; |
593 |
|
594 |
// split path into it tokens. |
595 |
//M("STARTING STRTOK"); |
596 |
p = STRTOK(path, PATH_SEPARATOR_STR, nexttok); |
597 |
|
598 |
while(p && depth > 0) |
599 |
{ |
600 |
if(strlen(temp) > 0 && temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR) |
601 |
{ |
602 |
strcat(temp,PATH_SEPARATOR_STR); |
603 |
} |
604 |
|
605 |
STRCAT(temp,p); |
606 |
--depth; |
607 |
|
608 |
p = STRTOK(NULL, PATH_SEPARATOR_STR, nexttok); |
609 |
} |
610 |
//M("FINISHED STRTOK"); |
611 |
|
612 |
// put / on end as required |
613 |
if(strlen(temp) > 0 ? (temp[strlen(temp) - 1] != PATH_SEPARATOR_CHAR) : 1) |
614 |
{ |
615 |
strcat(temp,PATH_SEPARATOR_STR); |
616 |
} |
617 |
|
618 |
#ifdef WINPATHS |
619 |
STRCPY(temp2,fp->drive); |
620 |
STRCAT(temp2,temp); |
621 |
return ospath_new_noclean(temp2); |
622 |
#else |
623 |
return ospath_new_noclean(temp); |
624 |
#endif |
625 |
} |
626 |
|
627 |
char *ospath_getbasefilename(struct FilePath *fp){ |
628 |
char *temp; |
629 |
unsigned length, offset; |
630 |
char *pos; |
631 |
|
632 |
if(strlen(fp->path) == 0){ |
633 |
// return empty name. |
634 |
return ""; |
635 |
} |
636 |
|
637 |
if(fp->path[strlen(fp->path)-1]==PATH_SEPARATOR_CHAR){ |
638 |
return NULL; |
639 |
} |
640 |
|
641 |
// reverse find '/' but DON'T ignore a trailing slash |
642 |
// (this is changed from the original implementation) |
643 |
length = strlen(fp->path); |
644 |
offset = length; |
645 |
|
646 |
pos = strrchr(fp->path, PATH_SEPARATOR_CHAR); /* OFFSET! */ |
647 |
|
648 |
// extract filename given position of find / and return it. |
649 |
if(pos != NULL){ |
650 |
unsigned length1 = length - ((pos - fp->path) + 1); |
651 |
temp = CALLOC(length1,sizeof(char)); |
652 |
|
653 |
V(length1); |
654 |
STRNCPY(temp, pos + 1, length1); |
655 |
return temp; |
656 |
}else{ |
657 |
temp = CALLOC(length,sizeof(char)); |
658 |
STRNCPY(temp, fp->path, length); |
659 |
return temp; |
660 |
} |
661 |
} |
662 |
|
663 |
char *ospath_getfilestem(struct FilePath *fp){ |
664 |
char *temp; |
665 |
char *pos; |
666 |
|
667 |
if(!ospath_isvalid(fp)){ |
668 |
return NULL; |
669 |
} |
670 |
|
671 |
temp = ospath_getbasefilename(fp); |
672 |
if(temp==NULL){ |
673 |
// it's a directory |
674 |
return NULL; |
675 |
} |
676 |
|
677 |
pos = strrchr(temp,'.'); |
678 |
|
679 |
if(pos==NULL || pos==temp){ |
680 |
// no extension, or a filename starting with '.' |
681 |
// -- return the whole filename |
682 |
return temp; |
683 |
} |
684 |
|
685 |
// remove extension. |
686 |
*pos = '\0'; |
687 |
|
688 |
return temp; |
689 |
} |
690 |
|
691 |
char *ospath_getfileext(struct FilePath *fp){ |
692 |
char *temp, *temp2, *pos; |
693 |
int len1; |
694 |
|
695 |
if(!ospath_isvalid(fp)){ |
696 |
return NULL; |
697 |
} |
698 |
|
699 |
temp = ospath_getbasefilename(fp); |
700 |
if(temp==NULL){ |
701 |
// it's a directory |
702 |
return NULL; |
703 |
} |
704 |
|
705 |
// make sure there is no / on the end. |
706 |
/// FIXME: is this good policy, removing a trailing slash? |
707 |
if(temp[strlen(temp) - 1] == PATH_SEPARATOR_CHAR){ |
708 |
temp[strlen(temp)-1] = '\0'; |
709 |
} |
710 |
|
711 |
pos = strrchr(temp,'.'); |
712 |
|
713 |
if(pos != NULL && pos!=temp){ |
714 |
// extract extension. |
715 |
len1 = temp + strlen(temp) - pos; |
716 |
temp2 = CALLOC(len1, sizeof(char)); |
717 |
STRNCPY(temp2, pos, len1); |
718 |
}else{ |
719 |
// no extension |
720 |
temp2 = NULL; |
721 |
} |
722 |
FREE(temp); |
723 |
return temp2; |
724 |
} |
725 |
|
726 |
int ospath_isroot(struct FilePath *fp) |
727 |
{ |
728 |
if(!ospath_isvalid(fp)) |
729 |
{ |
730 |
return 0; |
731 |
} |
732 |
|
733 |
return fp->path == PATH_SEPARATOR_STR ? 1 : 0; |
734 |
} |
735 |
|
736 |
unsigned ospath_depth(struct FilePath *fp){ |
737 |
unsigned length; |
738 |
unsigned depth; |
739 |
unsigned i; |
740 |
|
741 |
length = strlen(fp->path); |
742 |
depth = 0; |
743 |
|
744 |
for(i = 0; i < length; i++){ |
745 |
if(fp->path[i] == PATH_SEPARATOR_CHAR){ |
746 |
++depth; |
747 |
} |
748 |
} |
749 |
|
750 |
if( |
751 |
depth > 0 |
752 |
&& length > 0 |
753 |
&& fp->path[length - 1] == PATH_SEPARATOR_CHAR |
754 |
){ |
755 |
// PATH_SEPARATOR_CHAR on the end, reduce count by 1 |
756 |
--depth; |
757 |
} |
758 |
|
759 |
return depth; |
760 |
} |
761 |
|
762 |
struct FilePath *ospath_root(struct FilePath *fp){ |
763 |
#ifdef WINPATHS |
764 |
//M("WIN ROOT"); |
765 |
char *temp; |
766 |
struct FilePath *r; |
767 |
|
768 |
if(strlen(fp->drive)){ |
769 |
temp = CALLOC(strlen(fp->drive)+1, sizeof(char)); |
770 |
STRCPY(temp,fp->drive); |
771 |
STRCAT(temp,PATH_SEPARATOR_STR); |
772 |
X(temp); |
773 |
r = ospath_new(temp); |
774 |
FREE(temp); |
775 |
}else{ |
776 |
r = ospath_new(fp->path); |
777 |
} |
778 |
return r; |
779 |
#else |
780 |
//M("JUST RETURNING PATH SEP"); |
781 |
return ospath_new(PATH_SEPARATOR_STR); |
782 |
#endif |
783 |
} |
784 |
|
785 |
struct FilePath *ospath_getdir(struct FilePath *fp){ |
786 |
char *pos; |
787 |
char s[PATH_MAX]; |
788 |
|
789 |
pos = strrchr(fp->path,PATH_SEPARATOR_CHAR); |
790 |
if(pos==NULL){ |
791 |
return ospath_new("."); |
792 |
} |
793 |
#ifdef WINPATHS |
794 |
strncpy(s,fp->drive,PATH_MAX); |
795 |
strncat(s,fp->path,pos - fp->path); |
796 |
#else |
797 |
strncpy(s,fp->path,pos - fp->path); |
798 |
#endif |
799 |
return ospath_new(s); |
800 |
} |
801 |
|
802 |
int ospath_cmp(struct FilePath *fp1, struct FilePath *fp2){ |
803 |
char temp[2][PATH_MAX]; |
804 |
#ifdef WINPATHS |
805 |
char *p; |
806 |
#endif |
807 |
|
808 |
if(!ospath_isvalid(fp1)){ |
809 |
if(!ospath_isvalid(fp2)){ |
810 |
return 0; |
811 |
}else{ |
812 |
return -1; |
813 |
} |
814 |
}else if(!ospath_isvalid(fp2)){ |
815 |
return 1; |
816 |
} |
817 |
|
818 |
// now, both are valid... |
819 |
//M("BOTH ARE VALID"); |
820 |
|
821 |
#ifdef WINPATHS |
822 |
//X(fp1->drive); |
823 |
STRCPY(temp[0],fp1->drive); |
824 |
//X(temp[0]); |
825 |
//X(fp1->path); |
826 |
STRCAT(temp[0],fp1->path); |
827 |
//X(temp[0]); |
828 |
STRCPY(temp[1],fp2->drive); |
829 |
STRCAT(temp[1],fp2->path); |
830 |
#else |
831 |
STRCPY(temp[0], fp1->path); |
832 |
STRCPY(temp[1], fp2->path); |
833 |
#endif |
834 |
|
835 |
#ifdef WINPATHS |
836 |
for(p=temp[0];*p!='\0';++p){ |
837 |
*p=tolower(*p); |
838 |
} |
839 |
for(p=temp[1];*p!='\0';++p){ |
840 |
*p=tolower(*p); |
841 |
} |
842 |
X(temp[0]); |
843 |
X(temp[1]); |
844 |
#endif |
845 |
|
846 |
// we will count two paths that different only in a trailing slash to be the *same* |
847 |
// so we add trailing slashes to both now: |
848 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR){ |
849 |
STRCAT(temp[0],PATH_SEPARATOR_STR); |
850 |
} |
851 |
|
852 |
if(temp[1][strlen(temp[1]) - 1] != PATH_SEPARATOR_CHAR){ |
853 |
STRCAT(temp[1],PATH_SEPARATOR_STR); |
854 |
} |
855 |
|
856 |
//X(temp[0]); |
857 |
//X(temp[1]); |
858 |
|
859 |
return strcmp(temp[0],temp[1]); |
860 |
} |
861 |
|
862 |
struct FilePath *ospath_concat(struct FilePath *fp1, struct FilePath *fp2){ |
863 |
|
864 |
struct FilePath *fp; |
865 |
char temp[2][PATH_MAX]; |
866 |
char temp2[PATH_MAX]; |
867 |
struct FilePath *r; |
868 |
|
869 |
fp = MALLOC(sizeof(struct FilePath)); |
870 |
|
871 |
D(fp1); |
872 |
D(fp2); |
873 |
|
874 |
if(!ospath_isvalid(fp1)){ |
875 |
if(ospath_isvalid(fp2)){ |
876 |
ospath_copy(fp,fp2); |
877 |
}else{ |
878 |
// both invalid |
879 |
ospath_copy(fp,fp1); |
880 |
} |
881 |
return fp; |
882 |
} |
883 |
|
884 |
if(!ospath_isvalid(fp2)){ |
885 |
ospath_copy(fp,fp1); |
886 |
return fp; |
887 |
} |
888 |
|
889 |
// not just a copy of one or the other... |
890 |
ospath_free(fp); |
891 |
|
892 |
// now, both paths are valid... |
893 |
|
894 |
#ifdef WINPATHS |
895 |
STRNCPY(temp[0],fp1->drive,PATH_MAX); |
896 |
STRNCAT(temp[0],fp1->path,PATH_MAX-strlen(temp[0])); |
897 |
#else |
898 |
STRNCPY(temp[0], fp1->path,PATH_MAX); |
899 |
#endif |
900 |
|
901 |
STRNCPY(temp[1], fp2->path,PATH_MAX); |
902 |
|
903 |
// make sure temp has a / on the end. |
904 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR) |
905 |
{ |
906 |
STRNCAT(temp[0],PATH_SEPARATOR_STR,PATH_MAX-strlen(temp[0])); |
907 |
} |
908 |
|
909 |
#ifdef DO_FIXSLASHES |
910 |
ospath_fixslash(temp[0]); |
911 |
ospath_fixslash(temp[1]); |
912 |
#endif |
913 |
|
914 |
//V(strlen(temp[0])); |
915 |
//X(temp[0]); |
916 |
//V(strlen(temp[1])); |
917 |
//X(temp[1]); |
918 |
|
919 |
// make sure rhs path has NOT got a / at the start. |
920 |
if(temp[1][0] == PATH_SEPARATOR_CHAR){ |
921 |
return NULL; |
922 |
} |
923 |
|
924 |
// create a new path object with the two path strings appended together. |
925 |
STRNCPY(temp2,temp[0],PATH_MAX); |
926 |
STRNCAT(temp2,temp[1],PATH_MAX-strlen(temp2)); |
927 |
//V(strlen(temp2)); |
928 |
//X(temp2); |
929 |
r = ospath_new_noclean(temp2); |
930 |
D(r); |
931 |
/* ospath_cleanup(r);*/ |
932 |
return r; |
933 |
} |
934 |
|
935 |
void ospath_append(struct FilePath *fp, struct FilePath *fp1){ |
936 |
char *p; |
937 |
char *temp[2]; |
938 |
struct FilePath fp2; |
939 |
|
940 |
ospath_copy(&fp2,fp1); |
941 |
#ifdef DO_FIXSLASHES |
942 |
ospath_fixslash(fp2.path); |
943 |
#endif |
944 |
|
945 |
if(!ospath_isvalid(&fp2)){ |
946 |
M("fp1 invalid"); |
947 |
return; |
948 |
} |
949 |
|
950 |
if(!ospath_isvalid(fp) && ospath_isvalid(&fp2)){ |
951 |
// set this object to be the same as the rhs |
952 |
M("fp invalid"); |
953 |
ospath_copy(fp,&fp2); |
954 |
#ifdef DO_FIXSLASHES |
955 |
ospath_fixslash(fp->path); |
956 |
#endif |
957 |
return; |
958 |
} |
959 |
|
960 |
//X(fp->path); |
961 |
//X(fp2.path); |
962 |
|
963 |
// both paths are valid... |
964 |
temp[0] = CALLOC(1+strlen(fp->path), sizeof(char)); |
965 |
STRCPY(temp[0], fp->path); |
966 |
temp[1] = CALLOC(strlen(fp2.path), sizeof(char)); |
967 |
STRCPY(temp[1], fp2.path); |
968 |
|
969 |
//X(temp[0]); |
970 |
//X(temp[1]); |
971 |
|
972 |
// make sure temp has a / on the end. |
973 |
if(temp[0][strlen(temp[0]) - 1] != PATH_SEPARATOR_CHAR) |
974 |
{ |
975 |
STRCAT(temp[0],PATH_SEPARATOR_STR); |
976 |
} |
977 |
|
978 |
// make sure rhs path has NOT got a / at the start. |
979 |
if(temp[1][0] == PATH_SEPARATOR_CHAR){ |
980 |
for(p=temp[1]+1; *p != '\0'; ++p){ |
981 |
*(p-1)=*p; |
982 |
} |
983 |
*(p-1)='\0'; |
984 |
} |
985 |
|
986 |
//X(temp[0]); |
987 |
//X(temp[1]); |
988 |
|
989 |
// create new path string. |
990 |
STRCPY(fp->path,temp[0]); |
991 |
STRCAT(fp->path,temp[1]); |
992 |
|
993 |
FREE(temp[0]); |
994 |
FREE(temp[1]); |
995 |
|
996 |
X(fp); |
997 |
ospath_cleanup(fp); |
998 |
} |
999 |
|
1000 |
void ospath_copy(struct FilePath *dest, struct FilePath *src){ |
1001 |
STRCPY(dest->path,src->path); |
1002 |
#ifdef WINPATHS |
1003 |
STRCPY(dest->drive,src->drive); |
1004 |
#endif |
1005 |
} |
1006 |
|
1007 |
void ospath_debug(struct FilePath *fp){ |
1008 |
#ifdef WINPATHS |
1009 |
fprintf(stderr,"{\"%s\",\"%s\"}\n",fp->drive,fp->path); |
1010 |
#else |
1011 |
fprintf(stderr,"{\"%s\"}\n",fp->path); |
1012 |
#endif |
1013 |
} |
1014 |
|
1015 |
FILE *ospath_fopen(struct FilePath *fp, const char *mode){ |
1016 |
char s[PATH_MAX]; |
1017 |
if(!ospath_isvalid(fp)){ |
1018 |
E("Invalid path"); |
1019 |
return NULL; |
1020 |
} |
1021 |
ospath_strcpy(fp,s,PATH_MAX); |
1022 |
FILE *f = fopen(s,mode); |
1023 |
return f; |
1024 |
} |
1025 |
|
1026 |
//------------------------ |
1027 |
// SEARCH PATH FUNCTIONS |
1028 |
|
1029 |
struct FilePath **ospath_searchpath_new(const char *path){ |
1030 |
char *p; |
1031 |
char *list[LISTMAX]; |
1032 |
unsigned n=0; |
1033 |
char *c; |
1034 |
unsigned i; |
1035 |
struct FilePath **pp; |
1036 |
STRTOKVAR(nexttok); |
1037 |
|
1038 |
char path1[PATH_MAX]; |
1039 |
strncpy(path1,path,PATH_MAX); |
1040 |
|
1041 |
X(path1); |
1042 |
X(PATH_LISTSEP_STR); |
1043 |
|
1044 |
V(strlen(path1)); |
1045 |
V(strlen(PATH_LISTSEP_STR)); |
1046 |
|
1047 |
/* |
1048 |
c = strstr(path,PATH_LISTSEP_CHAR); |
1049 |
if(c==NULL){ |
1050 |
E("NO TOKEN FOUND"); |
1051 |
} |
1052 |
*/ |
1053 |
|
1054 |
p=STRTOK(path1,PATH_LISTSEP_STR,nexttok); |
1055 |
X(p); |
1056 |
for(; p!= NULL; p=STRTOK(NULL,PATH_LISTSEP_STR,nexttok)){ |
1057 |
c = CALLOC(strlen(p),sizeof(char)); |
1058 |
X(p); |
1059 |
STRCPY(c,p); |
1060 |
if(n>=LISTMAX){ |
1061 |
E("IGNORING SOME PATH COMPONENTS"); |
1062 |
break; |
1063 |
} |
1064 |
list[n++]=c; |
1065 |
} |
1066 |
|
1067 |
/* |
1068 |
for(i=0;i<n;++i){ |
1069 |
X(list[i]); |
1070 |
} |
1071 |
V(n); |
1072 |
*/ |
1073 |
|
1074 |
pp = CALLOC(n+1,sizeof(struct FilePath*)); |
1075 |
for(i=0; i<n; ++i){ |
1076 |
//V(i); |
1077 |
//X(list[i]); |
1078 |
pp[i] = ospath_new_noclean(list[i]); |
1079 |
//D(pp[i]); |
1080 |
} |
1081 |
pp[n] = NULL; |
1082 |
|
1083 |
for(i=0;i<n;++i){ |
1084 |
#ifdef DO_FIXSLASHES |
1085 |
ospath_fixslash(pp[i]->path); |
1086 |
#endif |
1087 |
D(pp[i]); |
1088 |
} |
1089 |
|
1090 |
return pp; |
1091 |
} |
1092 |
|
1093 |
void ospath_searchpath_free(struct FilePath **searchpath){ |
1094 |
struct FilePath **p; |
1095 |
for(p=searchpath; *p!=NULL; ++p){ |
1096 |
ospath_free(*p); |
1097 |
} |
1098 |
FREE(searchpath); |
1099 |
} |
1100 |
|
1101 |
struct FilePath *ospath_searchpath_iterate( |
1102 |
struct FilePath **searchpath |
1103 |
, FilePathTestFn *testfn |
1104 |
, void *searchdata |
1105 |
){ |
1106 |
struct FilePath **p; |
1107 |
|
1108 |
p = searchpath; |
1109 |
|
1110 |
M("SEARCHING IN..."); |
1111 |
for(p=searchpath; *p!=NULL; ++p){ |
1112 |
D(*p); |
1113 |
} |
1114 |
|
1115 |
for(p=searchpath; *p!=NULL; ++p){ |
1116 |
D(*p); |
1117 |
if((*testfn)(*p,searchdata)){ |
1118 |
return *p; |
1119 |
} |
1120 |
} |
1121 |
return NULL; |
1122 |
} |
1123 |
|
1124 |
|
1125 |
/*-------------------------------- |
1126 |
some simple test routines... |
1127 |
*/ |
1128 |
#ifdef TEST |
1129 |
|
1130 |
FilePathTestFn ospath_searchpath_testexists; |
1131 |
|
1132 |
/** |
1133 |
Return 1 if the file exists relative inside path |
1134 |
*/ |
1135 |
int ospath_searchpath_testexists(struct FilePath *path,void *file){ |
1136 |
struct FilePath *fp, *fp1, *fp2; |
1137 |
fp = (struct FilePath *)file; |
1138 |
D(fp); |
1139 |
fp1 = ospath_concat(path,fp); |
1140 |
D(fp1); |
1141 |
|
1142 |
fp2 = ospath_new("\\GTK\\bin\\johnpye\\extfn"); |
1143 |
if(ospath_cmp(fp1,fp2)==0){ |
1144 |
return 1; |
1145 |
} |
1146 |
return 0; |
1147 |
} |
1148 |
|
1149 |
#include <assert.h> |
1150 |
|
1151 |
int main(void){ |
1152 |
struct FilePath *fp1, *fp2, *fp3, *fp4; |
1153 |
char *s1, *s2; |
1154 |
struct FilePath **pp, **p1;// will be returned null-terminated |
1155 |
#ifdef WINPATHS |
1156 |
char pathtext[]="c:\\Program Files\\GnuWin32\\bin;c:\\GTK\\bin;e:\\ascend\\;..\\..\\pygtk"; |
1157 |
char pathtext2[]="c:\\Program Files\\ASCEND\\models"; |
1158 |
#else |
1159 |
char pathtext[]="\\Program Files\\GnuWin32\\bin:\\GTK\\bin:\\ascend\\:..\\..\\pygtk"; |
1160 |
char pathtext2[]="/usr/local/ascend/models"; |
1161 |
#endif |
1162 |
|
1163 |
//------------------------ |
1164 |
|
1165 |
fp1 = ospath_new_from_posix("/usr/local/hello/"); |
1166 |
fp2 = ospath_getparent(fp1); |
1167 |
fp3 = ospath_new_from_posix("/usr/local"); |
1168 |
|
1169 |
D(fp1); |
1170 |
D(fp2); |
1171 |
D(fp3); |
1172 |
assert(ospath_cmp(fp2,fp3)==0); |
1173 |
M("Passed 'getparent' test\n"); |
1174 |
|
1175 |
ospath_free(fp1); ospath_free(fp2); ospath_free(fp3); |
1176 |
|
1177 |
//------------------------ |
1178 |
|
1179 |
fp1 = ospath_new_from_posix("models/johnpye/extfn/extfntest"); |
1180 |
D(fp1); |
1181 |
fp2 = ospath_new("models\\johnpye\\extfn\\extfntest"); |
1182 |
D(fp2); |
1183 |
D(fp1); |
1184 |
assert(ospath_cmp(fp1,fp2)==0); |
1185 |
M("Passed 'new_from_posix' test\n"); |
1186 |
|
1187 |
ospath_free(fp1); |
1188 |
ospath_free(fp2); |
1189 |
|
1190 |
//------------------------ |
1191 |
fp1 = ospath_new(".\\src/.\\images\\..\\\\movies\\"); |
1192 |
fp2 = ospath_new(".\\src\\movies"); |
1193 |
|
1194 |
D(fp1); |
1195 |
D(fp2); |
1196 |
|
1197 |
assert(ospath_cmp(fp1,fp2)==0); |
1198 |
M("Passed mid-path '..' cleanup test\n"); |
1199 |
|
1200 |
ospath_free(fp2); |
1201 |
|
1202 |
fp2 = ospath_new("./src/movies\\kubrick"); |
1203 |
fp3 = ospath_getparent(fp2); |
1204 |
|
1205 |
D(fp2); |
1206 |
D(fp3); |
1207 |
|
1208 |
assert(ospath_cmp(fp1,fp3)==0); |
1209 |
M("Passed 'second cleanup' test\n"); |
1210 |
|
1211 |
//------------------------ |
1212 |
|
1213 |
fp2 = ospath_new("\\home\\john"); |
1214 |
fp3 = ospath_new("where\\mojo"); |
1215 |
|
1216 |
D(fp2); |
1217 |
D(fp3); |
1218 |
|
1219 |
ospath_append(fp2,fp3); |
1220 |
|
1221 |
D(fp2); |
1222 |
|
1223 |
fp4 = ospath_new("\\home\\john\\where\\mojo\\"); |
1224 |
|
1225 |
D(fp2); |
1226 |
assert(ospath_cmp(fp2,fp4)==0); |
1227 |
M("Passed 'append' test\n"); |
1228 |
|
1229 |
ospath_free(fp3); |
1230 |
ospath_free(fp2); |
1231 |
|
1232 |
//--------------------------- |
1233 |
|
1234 |
fp3 = ospath_new_noclean("../.."); |
1235 |
D(fp3); |
1236 |
|
1237 |
// test with appending ../.. to an existing path |
1238 |
fp2 = ospath_new("\\home\\john"); |
1239 |
M("ORIGINAL PATH"); |
1240 |
D(fp2); |
1241 |
ospath_append(fp2,fp3); |
1242 |
M("AFTER APPENDING ../.."); |
1243 |
D(fp2); |
1244 |
|
1245 |
M("GETTING ROOT"); |
1246 |
fp4 = ospath_root(fp2); |
1247 |
M("ROOT FOUND:"); |
1248 |
D(fp4); |
1249 |
|
1250 |
assert(ospath_cmp(fp2,fp4)==0); |
1251 |
M("Passed 'append ../..' test\n"); |
1252 |
|
1253 |
ospath_free(fp2); |
1254 |
ospath_free(fp3); |
1255 |
ospath_free(fp4); |
1256 |
|
1257 |
//------------------------- |
1258 |
|
1259 |
fp1 = ospath_new("~\\somewhere\\.."); |
1260 |
fp2 = ospath_new("~/."); |
1261 |
|
1262 |
assert(ospath_cmp(fp1,fp2)==0); |
1263 |
|
1264 |
D(fp2); |
1265 |
|
1266 |
ospath_free(fp1); |
1267 |
ospath_free(fp2); |
1268 |
|
1269 |
fp1 = ospath_new("/usr/local/include"); |
1270 |
fp2 = ospath_new("/usr/include/../local/include"); |
1271 |
|
1272 |
D(fp1); |
1273 |
D(fp2); |
1274 |
|
1275 |
assert(ospath_cmp(fp1,fp2)==0); |
1276 |
M("Passed another mid-path '..' test\n"); |
1277 |
|
1278 |
ospath_free(fp1); |
1279 |
ospath_free(fp2); |
1280 |
|
1281 |
//--------------------------- |
1282 |
|
1283 |
fp1 = ospath_new("/home"); |
1284 |
fp2 = ospath_new("john"); |
1285 |
fp3 = ospath_concat(fp1, fp2); |
1286 |
|
1287 |
fp4 = ospath_new("/home/john"); |
1288 |
|
1289 |
assert(ospath_cmp(fp3,fp4)==0); |
1290 |
M("Passed 'ospath_concat' test\n"); |
1291 |
|
1292 |
ospath_free(fp1); ospath_free(fp2); ospath_free(fp3); ospath_free(fp4); |
1293 |
|
1294 |
//--------------------------- |
1295 |
|
1296 |
fp1 = ospath_new("c:/Program Files"); |
1297 |
fp2 = ospath_new("GnuWin32\\bin"); |
1298 |
fp3 = ospath_concat(fp1, fp2); |
1299 |
|
1300 |
fp4 = ospath_new("c:/Program Files/GnuWin32/bin"); |
1301 |
|
1302 |
assert(ospath_cmp(fp3,fp4)==0); |
1303 |
M("Passed 'ospath_concat' test\n"); |
1304 |
|
1305 |
ospath_free(fp1); ospath_free(fp2); ospath_free(fp3); ospath_free(fp4); |
1306 |
|
1307 |
//--------------------------- |
1308 |
|
1309 |
fp1 = ospath_new("c:/Program Files/"); |
1310 |
fp2 = ospath_new("GnuWin32\\bin"); |
1311 |
fp3 = ospath_concat(fp1, fp2); |
1312 |
|
1313 |
fp4 = ospath_new("c:/Program Files/GnuWin32/bin"); |
1314 |
|
1315 |
assert(ospath_cmp(fp3,fp4)==0); |
1316 |
M("Passed trailing-slash 'ospath_concat' test\n"); |
1317 |
|
1318 |
ospath_free(fp1); ospath_free(fp2); ospath_free(fp3); ospath_free(fp4); |
1319 |
|
1320 |
//--------------------------- |
1321 |
|
1322 |
fp1 = ospath_new("c:/Program Files/GnuWin32/bin"); |
1323 |
fp2 = ospath_new("johnpye/extfn"); |
1324 |
fp3 = ospath_concat(fp1, fp2); |
1325 |
|
1326 |
fp4 = ospath_new("c:/Program Files/GnuWin32/bin/johnpye/extfn"); |
1327 |
|
1328 |
assert(ospath_cmp(fp3,fp4)==0); |
1329 |
M("Passed trailing-slash 'ospath_concat' test\n"); |
1330 |
|
1331 |
ospath_free(fp1); ospath_free(fp2); ospath_free(fp3); ospath_free(fp4); |
1332 |
|
1333 |
//--------------------------- |
1334 |
|
1335 |
pp = ospath_searchpath_new(pathtext); |
1336 |
|
1337 |
for(p1=pp; *p1!=NULL; ++p1){ |
1338 |
D(*p1); |
1339 |
} |
1340 |
|
1341 |
#ifdef WINPATHS |
1342 |
fp1 = ospath_new("c:\\program files\\GnuWin32\\bin"); |
1343 |
#else |
1344 |
fp1 = ospath_new("\\Program Files\\GnuWin32\\bin"); |
1345 |
#endif |
1346 |
|
1347 |
D(fp1); |
1348 |
D(pp[0]); |
1349 |
|
1350 |
assert(ospath_cmp(pp[0],fp1)==0); |
1351 |
|
1352 |
fp2 = ospath_new_noclean("johnpye/extfn"); |
1353 |
|
1354 |
fp3 = ospath_searchpath_iterate(pp,&ospath_searchpath_testexists,(void*)fp2); |
1355 |
|
1356 |
assert(ospath_cmp(fp3,pp[1])==0); |
1357 |
M("Passed path-search test\n"); |
1358 |
|
1359 |
ospath_free(fp1); |
1360 |
ospath_free(fp2); |
1361 |
ospath_searchpath_free(pp); |
1362 |
|
1363 |
//------------------------------- |
1364 |
|
1365 |
pp = ospath_searchpath_new(pathtext2); |
1366 |
|
1367 |
for (p1=pp; *p1!=NULL; ++p1){ |
1368 |
D(*p1); |
1369 |
} |
1370 |
|
1371 |
fp2 = ospath_new_noclean("johnpye/extfn/extfntest"); |
1372 |
fp3 = ospath_searchpath_iterate(pp,&ospath_searchpath_testexists,(void*)fp2); |
1373 |
|
1374 |
D(fp2); |
1375 |
D(fp3); |
1376 |
|
1377 |
assert(fp3==NULL); |
1378 |
M("Passed path-search test 2\n"); |
1379 |
|
1380 |
ospath_free(fp2); |
1381 |
ospath_free(fp3); |
1382 |
ospath_searchpath_free(pp); |
1383 |
|
1384 |
//------------------------------- |
1385 |
|
1386 |
fp1 = ospath_new("/usr/share/data/ascend/models/johnpye/extfn/extfntest.a4c"); |
1387 |
D(fp1); |
1388 |
s1 = ospath_getbasefilename(fp1); |
1389 |
X(s1); |
1390 |
assert(strcmp(s1,"extfntest.a4c")==0); |
1391 |
M("Passed getbasefilename test\n"); |
1392 |
|
1393 |
ospath_free(fp1); |
1394 |
FREE(s1); |
1395 |
|
1396 |
//------------------------------- |
1397 |
|
1398 |
fp1 = ospath_new("extfntest.a4c"); |
1399 |
D(fp1); |
1400 |
s1 = ospath_getbasefilename(fp1); |
1401 |
X(s1); |
1402 |
assert(strcmp(s1,"extfntest.a4c")==0); |
1403 |
M("Passed getbasefilename test 2\n"); |
1404 |
|
1405 |
ospath_free(fp1); |
1406 |
FREE(s1); |
1407 |
|
1408 |
|
1409 |
//------------------------------- |
1410 |
|
1411 |
fp1 = ospath_new("/here/is/my/path.dir/"); |
1412 |
D(fp1); |
1413 |
s1 = ospath_getbasefilename(fp1); |
1414 |
X(s1); |
1415 |
assert(NULL==s1); |
1416 |
M("Passed getbasefilename test 3\n"); |
1417 |
|
1418 |
ospath_free(fp1); |
1419 |
FREE(s1); |
1420 |
|
1421 |
//------------------------------- |
1422 |
|
1423 |
#ifdef WINPATHS |
1424 |
fp1 = ospath_new("c:extfntest.a4c"); |
1425 |
D(fp1); |
1426 |
s1 = ospath_getbasefilename(fp1); |
1427 |
X(s1); |
1428 |
assert(strcmp(s1,"extfntest.a4c")==0); |
1429 |
M("Passed getbasefilename test WINPATHS\n"); |
1430 |
|
1431 |
ospath_free(fp1); |
1432 |
FREE(s1); |
1433 |
#endif |
1434 |
|
1435 |
//------------------------------- |
1436 |
|
1437 |
fp1 = ospath_new("/usr/share/data/ascend/models/johnpye/extfn/extfntest.a4c"); |
1438 |
D(fp1); |
1439 |
s1 = ospath_getfilestem(fp1); |
1440 |
X(s1); |
1441 |
assert(strcmp(s1,"extfntest")==0); |
1442 |
M("Passed getfilestem test\n"); |
1443 |
|
1444 |
ospath_free(fp1); |
1445 |
FREE(s1); |
1446 |
|
1447 |
//------------------------------- |
1448 |
|
1449 |
fp1 = ospath_new("/usr/share/data/ascend/models/johnpye/extfn/extfntest"); |
1450 |
D(fp1); |
1451 |
s1 = ospath_getfilestem(fp1); |
1452 |
X(s1); |
1453 |
assert(strcmp(s1,"extfntest")==0); |
1454 |
M("Passed getfilestem test 2\n"); |
1455 |
|
1456 |
ospath_free(fp1); |
1457 |
FREE(s1); |
1458 |
|
1459 |
//------------------------------- |
1460 |
|
1461 |
fp1 = ospath_new("/usr/share/data/ascend/.ascend.ini"); |
1462 |
D(fp1); |
1463 |
s1 = ospath_getfilestem(fp1); |
1464 |
X(s1); |
1465 |
assert(strcmp(s1,".ascend")==0); |
1466 |
M("Passed getfilestem test 3\n"); |
1467 |
|
1468 |
ospath_free(fp1); |
1469 |
FREE(s1); |
1470 |
|
1471 |
//------------------------------- |
1472 |
|
1473 |
fp1 = ospath_new("~/.vimrc"); |
1474 |
D(fp1); |
1475 |
s1 = ospath_getfilestem(fp1); |
1476 |
X(s1); |
1477 |
assert(strcmp(s1,".vimrc")==0); |
1478 |
M("Passed getfilestem test 3\n"); |
1479 |
|
1480 |
ospath_free(fp1); |
1481 |
FREE(s1); |
1482 |
|
1483 |
//------------------------------- |
1484 |
|
1485 |
fp1 = ospath_new("~/src/ascend-0.9.5-1.jdpipe.src.rpm"); |
1486 |
D(fp1); |
1487 |
s1 = ospath_getfilestem(fp1); |
1488 |
X(s1); |
1489 |
assert(strcmp(s1,"ascend-0.9.5-1.jdpipe.src")==0); |
1490 |
M("Passed getfilestem test 4\n"); |
1491 |
|
1492 |
ospath_free(fp1); |
1493 |
FREE(s1); |
1494 |
|
1495 |
//------------------------------- |
1496 |
|
1497 |
fp1 = ospath_new("~/dir1/dir2/"); |
1498 |
D(fp1); |
1499 |
s1 = ospath_getfilestem(fp1); |
1500 |
X(s1); |
1501 |
assert(NULL==s1); |
1502 |
M("Passed getfilestem test 5\n"); |
1503 |
|
1504 |
ospath_free(fp1); |
1505 |
FREE(s1); |
1506 |
|
1507 |
//------------------------------- |
1508 |
|
1509 |
fp1 = ospath_new("~/src/ascend-0.9.5-1.jdpipe.src.rpm"); |
1510 |
D(fp1); |
1511 |
s1 = ospath_getfileext(fp1); |
1512 |
X(s1); |
1513 |
assert(strcmp(s1,".rpm")==0); |
1514 |
M("Passed getbasefileext test\n"); |
1515 |
|
1516 |
ospath_free(fp1); |
1517 |
FREE(s1); |
1518 |
|
1519 |
//------------------------------- |
1520 |
|
1521 |
fp1 = ospath_new("~/.vimrc"); |
1522 |
D(fp1); |
1523 |
s1 = ospath_getfileext(fp1); |
1524 |
X(s1); |
1525 |
assert(s1==NULL); |
1526 |
M("Passed getbasefileext test 2\n"); |
1527 |
|
1528 |
ospath_free(fp1); |
1529 |
FREE(s1); |
1530 |
|
1531 |
//------------------------------- |
1532 |
|
1533 |
fp1 = ospath_new("./ascend4"); |
1534 |
D(fp1); |
1535 |
s1 = ospath_getfileext(fp1); |
1536 |
X(s1); |
1537 |
assert(s1==NULL); |
1538 |
M("Passed getbasefileext test 3\n"); |
1539 |
|
1540 |
ospath_free(fp1); |
1541 |
FREE(s1); |
1542 |
|
1543 |
//------------------------------- |
1544 |
|
1545 |
fp1 = ospath_new("/home/myfile"); |
1546 |
fp2 = ospath_getdir(fp1); |
1547 |
fp3 = ospath_new("/home"); |
1548 |
assert(ospath_cmp(fp2,fp3)==0); |
1549 |
M("Passed ospath_getdir test\n"); |
1550 |
|
1551 |
ospath_free(fp1); |
1552 |
ospath_free(fp2); |
1553 |
ospath_free(fp3); |
1554 |
|
1555 |
//------------------------------- |
1556 |
|
1557 |
fp1 = ospath_new("/home/myfile.ext"); |
1558 |
fp2 = ospath_getdir(fp1); |
1559 |
fp3 = ospath_new("/home"); |
1560 |
assert(ospath_cmp(fp2,fp3)==0); |
1561 |
M("Passed ospath_getdir test 2\n"); |
1562 |
|
1563 |
ospath_free(fp1); |
1564 |
ospath_free(fp2); |
1565 |
ospath_free(fp3); |
1566 |
|
1567 |
//------------------------------- |
1568 |
|
1569 |
fp1 = ospath_new("/home/mydir/"); |
1570 |
fp2 = ospath_getdir(fp1); |
1571 |
fp3 = ospath_new("/home/mydir"); |
1572 |
assert(ospath_cmp(fp2,fp3)==0); |
1573 |
M("Passed ospath_getdir test 3\n"); |
1574 |
|
1575 |
ospath_free(fp1); |
1576 |
ospath_free(fp2); |
1577 |
ospath_free(fp3); |
1578 |
|
1579 |
//--------------------------------- |
1580 |
M("ALL TESTS PASSED"); |
1581 |
} |
1582 |
|
1583 |
#endif |