/[ascend]/trunk/ascend/general/ospath.c
ViewVC logotype

Contents of /trunk/ascend/general/ospath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2551 - (show annotations) (download) (as text)
Thu Feb 2 20:14:50 2012 UTC (6 years, 10 months ago) by jpye
File MIME type: text/x-csrc
File size: 27772 byte(s)
Merge 'ospath_chdir' and 'ospath_getcwd' into trunk (from Leon).
Add detection of Ubuntu 11.10 in Sundials, since extra linkage to 'lapack' is required.
Disable defaultall output for the moment.

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

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22