beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / gutils / fsys.c
blobba846e2c571c39ea67cd08b5dfa471a279149cb5
1 /* Copyright (C) 2000-2004 by George Williams */
2 /*
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.
28 #include "basics.h"
29 #include "ustring.h"
30 #include "gfile.h"
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/stat.h> /* for mkdir */
34 #include <unistd.h>
36 #ifdef _WIN32
37 #define MKDIR(A,B) mkdir(A)
38 #else
39 #define MKDIR(A,B) mkdir(A,B)
40 #endif
42 static char dirname_[1024];
44 char *GFileGetAbsoluteName(char *name, char *result, int rsiz) {
45 /* result may be the same as name */
46 char buffer[1000];
48 if ( *name!='/' ) {
49 char *pt, *spt, *rpt, *bpt;
51 if ( dirname_[0]=='\0' ) {
52 if (getcwd(dirname_,sizeof(dirname_)) == NULL)
53 return(result);
55 strcpy(buffer,dirname_);
56 if ( buffer[strlen(buffer)-1]!='/' )
57 strcat(buffer,"/");
58 strcat(buffer,name);
60 /* Normalize out any .. */
61 spt = rpt = buffer;
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 */
68 strcpy(spt,pt);
69 else if ( pt==spt+2 && spt[0]=='.' && spt[1]=='.' ) {
70 for ( bpt=spt-2 ; bpt>rpt && *bpt!='/'; --bpt );
71 if ( bpt>=rpt && *bpt=='/' ) {
72 strcpy(bpt,pt);
73 spt = bpt;
74 } else {
75 rpt = pt;
76 spt = pt;
78 } else
79 spt = pt;
81 name = buffer;
82 if ( rsiz>sizeof(buffer)) rsiz = sizeof(buffer); /* Else valgrind gets unhappy */
84 if (result!=name) {
85 strncpy(result,name,rsiz);
86 result[rsiz-1]='\0';
88 return(result);
91 char *GFileMakeAbsoluteName(char *name) {
92 char buffer[1025];
94 GFileGetAbsoluteName(name,buffer,sizeof(buffer));
95 return( copy(buffer));
98 char *GFileBuildName(char *dir,char *fname,char *buffer,int size) {
99 int len;
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);
104 else {
105 strncpy(buffer,fname,size-1);
106 buffer[size-1]='\0';
108 } else {
109 if ( buffer!=dir ) {
110 if ( strlen( dir )<size-3 )
111 strcpy(buffer,dir);
112 else {
113 strncpy(buffer,dir,size-3);
114 buffer[size-3]='\0';
117 len = strlen(buffer);
118 if ( buffer[len-1]!='/' )
119 buffer[len++] = '/';
120 if ( strlen( fname )<size-1 )
121 strcpy(buffer+len,fname);
122 else {
123 strncpy(buffer+len,fname,size-len-1);
124 buffer[size-1]='\0';
127 return( buffer );
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) {
133 int len;
134 char *dirend;
136 dirend = strrchr(oldname,'/');
137 if ( dirend == NULL ) {
138 strncpy(buffer,fname,size-1);
139 buffer[size-1]='\0';
140 } else {
141 *dirend = '\0';
142 if ( buffer!=oldname ) {
143 strncpy(buffer,oldname,size-3);
144 buffer[size-3]='\0';
146 len = strlen(buffer);
147 *dirend = '/';
148 buffer[len++] = '/';
149 strncpy(buffer+len,fname,size-len-1);
150 buffer[size-1]='\0';
152 return( buffer );
155 char *GFileNameTail(const char *oldname) {
156 char *pt;
158 pt = strrchr(oldname,'/');
159 if ( pt !=NULL )
160 return( pt+1);
161 else
162 return( (char *)oldname );
165 char *GFileAppendFile(char *dir,char *name,int isdir) {
166 char *ret, *pt;
168 ret = xmalloc((strlen(dir)+strlen(name)+3));
169 strcpy(ret,dir);
170 pt = ret+strlen(ret);
171 if ( pt>ret && pt[-1]!='/' )
172 *pt++ = '/';
173 strcpy(pt,name);
174 if ( isdir ) {
175 pt += strlen(pt);
176 if ( pt>ret && pt[-1]!='/' ) {
177 *pt++ = '/';
178 *pt = '\0';
181 return(ret);
184 int GFileIsAbsolute(const char *file) {
185 if ( *file=='/' )
186 return( true );
187 if ( strstr(file,"://")!=NULL )
188 return( true );
190 return( false );
193 int GFileIsDir(const char *file) {
194 #ifdef _WIN32
195 struct stat info;
196 if (stat(file, &info))
197 return 0;
198 else
199 return ((info.st_mode&_S_IFDIR));
200 #else
201 char buffer[1000];
202 sprintf(buffer,"%s/.",file);
203 return( access(buffer,0)==0 );
204 #endif
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;
218 strcpy(buffer,file);
219 pt = strrchr(buffer,'/');
220 if ( pt==NULL )
221 strcpy(buffer,".");
222 else
223 *pt='\0';
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) {
236 return(rmdir(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;
245 char filename[2000];
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);
256 break;
258 path = pt+1;
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 )
267 return( NULL );
268 GFileGetAbsoluteName(program_dir,filename,sizeof(filename));
269 gfree(program_dir);
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];
278 if ( *name!='/' ) {
279 unichar_t *pt, *spt, *rpt, *bpt;
281 if ( dirname_[0]=='\0' ) {
282 if (getcwd(dirname_,sizeof(dirname_)) == NULL)
283 return(result);
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 .. */
291 spt = rpt = buffer;
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 */
298 u_strcpy(spt,pt);
299 else if ( pt==spt+2 && spt[0]=='.' && spt[1]=='.' ) {
300 for ( bpt=spt-2 ; bpt>rpt && *bpt!='/'; --bpt );
301 if ( bpt>=rpt && *bpt=='/' ) {
302 u_strcpy(bpt,pt);
303 spt = bpt;
304 } else {
305 rpt = pt;
306 spt = pt;
308 } else
309 spt = pt;
311 name = buffer;
313 if (result!=name) {
314 u_strncpy(result,name,rsiz);
315 result[rsiz-1]='\0';
317 return(result);
320 unichar_t *u_GFileBuildName(unichar_t *dir,unichar_t *fname,unichar_t *buffer,int size) {
321 int len;
323 if ( dir==NULL || *dir=='\0' ) {
324 u_strncpy(buffer,fname,size-1);
325 buffer[size-1]='\0';
326 } else {
327 if ( buffer!=dir ) {
328 u_strncpy(buffer,dir,size-3);
329 buffer[size-3]='\0';
331 len = u_strlen(buffer);
332 if ( buffer[len-1]!='/' )
333 buffer[len++] = '/';
334 u_strncpy(buffer+len,fname,size-len-1);
335 buffer[size-1]='\0';
337 return( buffer );
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) {
343 int len;
344 unichar_t *dirend;
346 dirend = u_strrchr(oldname,'/');
347 if ( dirend == NULL ) {
348 u_strncpy(buffer,fname,size-1);
349 buffer[size-1]='\0';
350 } else {
351 *dirend = '\0';
352 if ( buffer!=oldname ) {
353 u_strncpy(buffer,oldname,size-3);
354 buffer[size-3]='\0';
356 len = u_strlen(buffer);
357 *dirend = '/';
358 buffer[len++] = '/';
359 u_strncpy(buffer+len,fname,size-len-1);
360 buffer[size-1]='\0';
362 return( buffer );
365 unichar_t *u_GFileNameTail(const unichar_t *oldname) {
366 unichar_t *pt;
368 pt = u_strrchr(oldname,'/');
369 if ( pt !=NULL )
370 return( pt+1);
371 else
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,'/');
380 if ( base==NULL )
381 return( name );
382 ++base;
383 } else if ( *name=='/' )
384 base = name+1;
385 else
386 base = name;
387 for ( pt=base; *pt!='\0'; ) {
388 if ( *pt=='/' )
389 u_strcpy(pt,pt+1);
390 else if ( uc_strncmp(pt,"./",2)==0 )
391 u_strcpy(pt,pt+2);
392 else if ( uc_strncmp(pt,"../",2)==0 ) {
393 for ( ppt=pt-2; ppt>=base && *ppt!='/'; --ppt );
394 ++ppt;
395 if ( ppt>=base ) {
396 u_strcpy(ppt,pt+3);
397 pt = ppt;
398 } else
399 pt += 3;
400 } else {
401 while ( *pt!='/' && *pt!='\0' ) ++pt;
402 if ( *pt == '/' ) ++pt;
405 return( name );
408 unichar_t *u_GFileAppendFile(unichar_t *dir,unichar_t *name,int isdir) {
409 unichar_t *ret, *pt;
411 ret = xmalloc((u_strlen(dir)+u_strlen(name)+3)*sizeof(unichar_t));
412 u_strcpy(ret,dir);
413 pt = ret+u_strlen(ret);
414 if ( pt>ret && pt[-1]!='/' )
415 *pt++ = '/';
416 u_strcpy(pt,name);
417 if ( isdir ) {
418 pt += u_strlen(pt);
419 if ( pt>ret && pt[-1]!='/' ) {
420 *pt++ = '/';
421 *pt = '\0';
424 return(ret);
427 int u_GFileIsAbsolute(const unichar_t *file) {
428 if ( *file=='/' )
429 return( true );
430 if ( uc_strstr(file,"://")!=NULL )
431 return( true );
433 return( false );
436 int u_GFileIsDir(const unichar_t *file) {
437 char buffer[1024];
438 cu_strcpy(buffer,file);
439 strcat(buffer,"/.");
440 return( access(buffer,0)==0 );
443 int u_GFileExists(const unichar_t *file) {
444 char buffer[1024];
445 cu_strcpy(buffer,file);
446 return( access(buffer,0)==0 );
449 int u_GFileModifyable(const unichar_t *file) {
450 char buffer[1024];
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,'/');
460 if ( pt==NULL )
461 strcpy(buffer,".");
462 else
463 *pt='\0';
464 return( GFileModifyable(buffer));
467 int u_GFileReadable(unichar_t *file) {
468 char buffer[1024];
469 cu_strcpy(buffer,file);
470 return( access(buffer,04)==0 );
473 int u_GFileMkDir(unichar_t *name) {
474 char buffer[1024];
475 cu_strcpy(buffer,name);
476 return( MKDIR(buffer,0755));
479 int u_GFileRmDir(unichar_t *name) {
480 char buffer[1024];
481 cu_strcpy(buffer,name);
482 return(rmdir(buffer));
485 int u_GFileUnlink(unichar_t *name) {
486 char buffer[1024];
487 cu_strcpy(buffer,name);
488 return(unlink(buffer));