1 /* Copyright (C) 2000-2004 by George Williams */
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/stat.h> /* for mkdir */
37 #define MKDIR(A,B) mkdir(A)
39 #define MKDIR(A,B) mkdir(A,B)
42 static char dirname_
[1024];
44 char *GFileGetAbsoluteName(char *name
, char *result
, int rsiz
) {
45 /* result may be the same as name */
49 char *pt
, *spt
, *rpt
, *bpt
;
51 if ( dirname_
[0]=='\0' ) {
52 if (getcwd(dirname_
,sizeof(dirname_
)) == NULL
)
55 strcpy(buffer
,dirname_
);
56 if ( buffer
[strlen(buffer
)-1]!='/' )
60 /* Normalize out any .. */
62 while ( *spt
!='\0' ) {
63 if ( *spt
=='/' ) ++spt
;
64 for ( pt
= spt
; *pt
!='\0' && *pt
!='/'; ++pt
);
65 if ( pt
==spt
) /* Found // in a path spec, reduce to / (we've*/
66 strcpy(spt
,pt
); /* skipped past the :// of the machine name) */
67 else if ( pt
==spt
+1 && spt
[0]=='.' ) /* Noop */
69 else if ( pt
==spt
+2 && spt
[0]=='.' && spt
[1]=='.' ) {
70 for ( bpt
=spt
-2 ; bpt
>rpt
&& *bpt
!='/'; --bpt
);
71 if ( bpt
>=rpt
&& *bpt
=='/' ) {
82 if ( rsiz
>sizeof(buffer
)) rsiz
= sizeof(buffer
); /* Else valgrind gets unhappy */
85 strncpy(result
,name
,rsiz
);
91 char *GFileMakeAbsoluteName(char *name
) {
94 GFileGetAbsoluteName(name
,buffer
,sizeof(buffer
));
95 return( copy(buffer
));
98 char *GFileBuildName(char *dir
,char *fname
,char *buffer
,int size
) {
101 if ( dir
==NULL
|| *dir
=='\0' ) {
102 if ( strlen( fname
)<size
-1 ) /* valgrind didn't like my strncpies but this complication makes it happy */
103 strcpy(buffer
,fname
);
105 strncpy(buffer
,fname
,size
-1);
110 if ( strlen( dir
)<size
-3 )
113 strncpy(buffer
,dir
,size
-3);
117 len
= strlen(buffer
);
118 if ( buffer
[len
-1]!='/' )
120 if ( strlen( fname
)<size
-1 )
121 strcpy(buffer
+len
,fname
);
123 strncpy(buffer
+len
,fname
,size
-len
-1);
130 /* Given a filename in a directory, pick the directory out of it, and */
131 /* create a new filename using that directory and the given nametail */
132 char *GFileReplaceName(char *oldname
,char *fname
,char *buffer
,int size
) {
136 dirend
= strrchr(oldname
,'/');
137 if ( dirend
== NULL
) {
138 strncpy(buffer
,fname
,size
-1);
142 if ( buffer
!=oldname
) {
143 strncpy(buffer
,oldname
,size
-3);
146 len
= strlen(buffer
);
149 strncpy(buffer
+len
,fname
,size
-len
-1);
155 char *GFileNameTail(const char *oldname
) {
158 pt
= strrchr(oldname
,'/');
162 return( (char *)oldname
);
165 char *GFileAppendFile(char *dir
,char *name
,int isdir
) {
168 ret
= xmalloc((strlen(dir
)+strlen(name
)+3));
170 pt
= ret
+strlen(ret
);
171 if ( pt
>ret
&& pt
[-1]!='/' )
176 if ( pt
>ret
&& pt
[-1]!='/' ) {
184 int GFileIsAbsolute(const char *file
) {
187 if ( strstr(file
,"://")!=NULL
)
193 int GFileIsDir(const char *file
) {
196 if (stat(file
, &info
))
199 return ((info
.st_mode
&_S_IFDIR
));
202 sprintf(buffer
,"%s/.",file
);
203 return( access(buffer
,0)==0 );
207 int GFileExists(const char *file
) {
208 return( access(file
,0)==0 );
211 int GFileModifyable(const char *file
) {
212 return( access(file
,02)==0 );
215 int GFileModifyableDir(const char *file
) {
216 char buffer
[1024], *pt
;
219 pt
= strrchr(buffer
,'/');
224 return( GFileModifyable(buffer
));
227 int GFileReadable(char *file
) {
228 return( access(file
,04)==0 );
231 int GFileMkDir(char *name
) {
232 return( MKDIR(name
,0755));
235 int GFileRmDir(char *name
) {
239 int GFileUnlink(char *name
) {
240 return(unlink(name
));
243 char *_GFile_find_program_dir(char *prog
) {
244 char *pt
, *path
, *program_dir
=NULL
;
247 if ( (pt
= strrchr(prog
,'/'))!=NULL
)
248 program_dir
= copyn(prog
,pt
-prog
);
249 else if ( (path
= getenv("PATH"))!=NULL
) {
250 while ((pt
= strchr(path
,':'))!=NULL
) {
251 sprintf(filename
,"%.*s/%s", (int)(pt
-path
), path
, prog
);
252 /* Under cygwin, applying access to "potrace" will find "potrace.exe" */
253 /* no need for special check to add ".exe" */
254 if ( access(filename
,1)!= -1 ) {
255 program_dir
= copyn(path
,pt
-path
);
260 if ( program_dir
==NULL
) {
261 sprintf(filename
,"%s/%s", path
, prog
);
262 if ( access(filename
,1)!= -1 )
263 program_dir
= copy(path
);
266 if ( program_dir
==NULL
)
268 GFileGetAbsoluteName(program_dir
,filename
,sizeof(filename
));
270 program_dir
= copy(filename
);
271 return( program_dir
);
274 unichar_t
*u_GFileGetAbsoluteName(unichar_t
*name
, unichar_t
*result
, int rsiz
) {
275 /* result may be the same as name */
276 unichar_t buffer
[1000];
279 unichar_t
*pt
, *spt
, *rpt
, *bpt
;
281 if ( dirname_
[0]=='\0' ) {
282 if (getcwd(dirname_
,sizeof(dirname_
)) == NULL
)
285 uc_strcpy(buffer
,dirname_
);
286 if ( buffer
[u_strlen(buffer
)-1]!='/' )
287 uc_strcat(buffer
,"/");
288 u_strcat(buffer
,name
);
290 /* Normalize out any .. */
292 while ( *spt
!='\0' ) {
293 if ( *spt
=='/' ) ++spt
;
294 for ( pt
= spt
; *pt
!='\0' && *pt
!='/'; ++pt
);
295 if ( pt
==spt
) /* Found // in a path spec, reduce to / (we've*/
296 u_strcpy(spt
,pt
); /* skipped past the :// of the machine name) */
297 else if ( pt
==spt
+1 && spt
[0]=='.' ) /* Noop */
299 else if ( pt
==spt
+2 && spt
[0]=='.' && spt
[1]=='.' ) {
300 for ( bpt
=spt
-2 ; bpt
>rpt
&& *bpt
!='/'; --bpt
);
301 if ( bpt
>=rpt
&& *bpt
=='/' ) {
314 u_strncpy(result
,name
,rsiz
);
320 unichar_t
*u_GFileBuildName(unichar_t
*dir
,unichar_t
*fname
,unichar_t
*buffer
,int size
) {
323 if ( dir
==NULL
|| *dir
=='\0' ) {
324 u_strncpy(buffer
,fname
,size
-1);
328 u_strncpy(buffer
,dir
,size
-3);
331 len
= u_strlen(buffer
);
332 if ( buffer
[len
-1]!='/' )
334 u_strncpy(buffer
+len
,fname
,size
-len
-1);
340 /* Given a filename in a directory, pick the directory out of it, and */
341 /* create a new filename using that directory and the given nametail */
342 unichar_t
*u_GFileReplaceName(unichar_t
*oldname
,unichar_t
*fname
,unichar_t
*buffer
,int size
) {
346 dirend
= u_strrchr(oldname
,'/');
347 if ( dirend
== NULL
) {
348 u_strncpy(buffer
,fname
,size
-1);
352 if ( buffer
!=oldname
) {
353 u_strncpy(buffer
,oldname
,size
-3);
356 len
= u_strlen(buffer
);
359 u_strncpy(buffer
+len
,fname
,size
-len
-1);
365 unichar_t
*u_GFileNameTail(const unichar_t
*oldname
) {
368 pt
= u_strrchr(oldname
,'/');
372 return( (unichar_t
*)oldname
);
375 unichar_t
*u_GFileNormalize(unichar_t
*name
) {
376 unichar_t
*pt
, *base
, *ppt
;
378 if ( (pt
= uc_strstr(name
,"://"))!=NULL
) {
379 base
= u_strchr(pt
+3,'/');
383 } else if ( *name
=='/' )
387 for ( pt
=base
; *pt
!='\0'; ) {
390 else if ( uc_strncmp(pt
,"./",2)==0 )
392 else if ( uc_strncmp(pt
,"../",2)==0 ) {
393 for ( ppt
=pt
-2; ppt
>=base
&& *ppt
!='/'; --ppt
);
401 while ( *pt
!='/' && *pt
!='\0' ) ++pt
;
402 if ( *pt
== '/' ) ++pt
;
408 unichar_t
*u_GFileAppendFile(unichar_t
*dir
,unichar_t
*name
,int isdir
) {
411 ret
= xmalloc((u_strlen(dir
)+u_strlen(name
)+3)*sizeof(unichar_t
));
413 pt
= ret
+u_strlen(ret
);
414 if ( pt
>ret
&& pt
[-1]!='/' )
419 if ( pt
>ret
&& pt
[-1]!='/' ) {
427 int u_GFileIsAbsolute(const unichar_t
*file
) {
430 if ( uc_strstr(file
,"://")!=NULL
)
436 int u_GFileIsDir(const unichar_t
*file
) {
438 cu_strcpy(buffer
,file
);
440 return( access(buffer
,0)==0 );
443 int u_GFileExists(const unichar_t
*file
) {
445 cu_strcpy(buffer
,file
);
446 return( access(buffer
,0)==0 );
449 int u_GFileModifyable(const unichar_t
*file
) {
451 cu_strcpy(buffer
,file
);
452 return( access(buffer
,02)==0 );
455 int u_GFileModifyableDir(const unichar_t
*file
) {
456 char buffer
[1024], *pt
;
458 cu_strcpy(buffer
,file
);
459 pt
= strrchr(buffer
,'/');
464 return( GFileModifyable(buffer
));
467 int u_GFileReadable(unichar_t
*file
) {
469 cu_strcpy(buffer
,file
);
470 return( access(buffer
,04)==0 );
473 int u_GFileMkDir(unichar_t
*name
) {
475 cu_strcpy(buffer
,name
);
476 return( MKDIR(buffer
,0755));
479 int u_GFileRmDir(unichar_t
*name
) {
481 cu_strcpy(buffer
,name
);
482 return(rmdir(buffer
));
485 int u_GFileUnlink(unichar_t
*name
) {
487 cu_strcpy(buffer
,name
);
488 return(unlink(buffer
));