/* Copyright (C) 2000-2004 by George Williams */ /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include "ustring.h" #include "fileutil.h" #include "gfile.h" #include #include /* for mkdir */ #include #ifdef _WIN32 #define MKDIR(A,B) mkdir(A) #else #define MKDIR(A,B) mkdir(A,B) #endif static char dirname_[1024]; char *GFileGetAbsoluteName(char *name, char *result, int rsiz) { /* result may be the same as name */ char buffer[1000]; if ( *name!='/' ) { char *pt, *spt, *rpt, *bpt; if ( dirname_[0]=='\0' ) { getcwd(dirname_,sizeof(dirname_)); } strcpy(buffer,dirname_); if ( buffer[strlen(buffer)-1]!='/' ) strcat(buffer,"/"); strcat(buffer,name); /* Normalize out any .. */ spt = rpt = buffer; while ( *spt!='\0' ) { if ( *spt=='/' ) ++spt; for ( pt = spt; *pt!='\0' && *pt!='/'; ++pt ); if ( pt==spt ) /* Found // in a path spec, reduce to / (we've*/ strcpy(spt,pt); /* skipped past the :// of the machine name) */ else if ( pt==spt+1 && spt[0]=='.' ) /* Noop */ strcpy(spt,pt); else if ( pt==spt+2 && spt[0]=='.' && spt[1]=='.' ) { for ( bpt=spt-2 ; bpt>rpt && *bpt!='/'; --bpt ); if ( bpt>=rpt && *bpt=='/' ) { strcpy(bpt,pt); spt = bpt; } else { rpt = pt; spt = pt; } } else spt = pt; } name = buffer; if ( rsiz>sizeof(buffer)) rsiz = sizeof(buffer); /* Else valgrind gets unhappy */ } if (result!=name) { strncpy(result,name,rsiz); result[rsiz-1]='\0'; } return(result); } char *GFileMakeAbsoluteName(char *name) { char buffer[1025]; GFileGetAbsoluteName(name,buffer,sizeof(buffer)); return( copy(buffer)); } char *GFileBuildName(char *dir,char *fname,char *buffer,int size) { int len; if ( dir==NULL || *dir=='\0' ) { if ( strlen( fname )ret && pt[-1]!='/' ) *pt++ = '/'; strcpy(pt,name); if ( isdir ) { pt += strlen(pt); if ( pt>ret && pt[-1]!='/' ) { *pt++ = '/'; *pt = '\0'; } } return(ret); } int GFileIsAbsolute(const char *file) { if ( *file=='/' ) return( true ); if ( strstr(file,"://")!=NULL ) return( true ); return( false ); } int GFileIsDir(const char *file) { #ifdef _WIN32 struct stat info; if (stat(file, &info)) return 0; else return ((info.st_mode&_S_IFDIR)); #else char buffer[1000]; sprintf(buffer,"%s/.",file); return( access(buffer,0)==0 ); #endif } int GFileExists(const char *file) { return( access(file,0)==0 ); } int GFileModifyable(const char *file) { return( access(file,02)==0 ); } int GFileModifyableDir(const char *file) { char buffer[1024], *pt; strcpy(buffer,file); pt = strrchr(buffer,'/'); if ( pt==NULL ) strcpy(buffer,"."); else *pt='\0'; return( GFileModifyable(buffer)); } int GFileReadable(char *file) { return( access(file,04)==0 ); } int GFileMkDir(char *name) { return( MKDIR(name,0755)); } int GFileRmDir(char *name) { return(rmdir(name)); } int GFileUnlink(char *name) { return(unlink(name)); } char *_GFile_find_program_dir(char *prog) { char *pt, *path, *program_dir=NULL; char filename[2000]; if ( (pt = strrchr(prog,'/'))!=NULL ) program_dir = copyn(prog,pt-prog); else if ( (path = getenv("PATH"))!=NULL ) { while ((pt = strchr(path,':'))!=NULL ) { sprintf(filename,"%.*s/%s", (int)(pt-path), path, prog); /* Under cygwin, applying access to "potrace" will find "potrace.exe" */ /* no need for special check to add ".exe" */ if ( access(filename,1)!= -1 ) { program_dir = copyn(path,pt-path); break; } path = pt+1; } if ( program_dir==NULL ) { sprintf(filename,"%s/%s", path, prog); if ( access(filename,1)!= -1 ) program_dir = copy(path); } } if ( program_dir==NULL ) return( NULL ); GFileGetAbsoluteName(program_dir,filename,sizeof(filename)); gfree(program_dir); program_dir = copy(filename); return( program_dir ); } unichar_t *u_GFileGetAbsoluteName(unichar_t *name, unichar_t *result, int rsiz) { /* result may be the same as name */ unichar_t buffer[1000]; if ( *name!='/' ) { unichar_t *pt, *spt, *rpt, *bpt; if ( dirname_[0]=='\0' ) { getcwd(dirname_,sizeof(dirname_)); } uc_strcpy(buffer,dirname_); if ( buffer[u_strlen(buffer)-1]!='/' ) uc_strcat(buffer,"/"); u_strcat(buffer,name); /* Normalize out any .. */ spt = rpt = buffer; while ( *spt!='\0' ) { if ( *spt=='/' ) ++spt; for ( pt = spt; *pt!='\0' && *pt!='/'; ++pt ); if ( pt==spt ) /* Found // in a path spec, reduce to / (we've*/ u_strcpy(spt,pt); /* skipped past the :// of the machine name) */ else if ( pt==spt+1 && spt[0]=='.' ) /* Noop */ u_strcpy(spt,pt); else if ( pt==spt+2 && spt[0]=='.' && spt[1]=='.' ) { for ( bpt=spt-2 ; bpt>rpt && *bpt!='/'; --bpt ); if ( bpt>=rpt && *bpt=='/' ) { u_strcpy(bpt,pt); spt = bpt; } else { rpt = pt; spt = pt; } } else spt = pt; } name = buffer; } if (result!=name) { u_strncpy(result,name,rsiz); result[rsiz-1]='\0'; } return(result); } unichar_t *u_GFileBuildName(unichar_t *dir,unichar_t *fname,unichar_t *buffer,int size) { int len; if ( dir==NULL || *dir=='\0' ) { u_strncpy(buffer,fname,size-1); buffer[size-1]='\0'; } else { if ( buffer!=dir ) { u_strncpy(buffer,dir,size-3); buffer[size-3]='\0'; } len = u_strlen(buffer); if ( buffer[len-1]!='/' ) buffer[len++] = '/'; u_strncpy(buffer+len,fname,size-len-1); buffer[size-1]='\0'; } return( buffer ); } /* Given a filename in a directory, pick the directory out of it, and */ /* create a new filename using that directory and the given nametail */ unichar_t *u_GFileReplaceName(unichar_t *oldname,unichar_t *fname,unichar_t *buffer,int size) { int len; unichar_t *dirend; dirend = u_strrchr(oldname,'/'); if ( dirend == NULL ) { u_strncpy(buffer,fname,size-1); buffer[size-1]='\0'; } else { *dirend = '\0'; if ( buffer!=oldname ) { u_strncpy(buffer,oldname,size-3); buffer[size-3]='\0'; } len = u_strlen(buffer); *dirend = '/'; buffer[len++] = '/'; u_strncpy(buffer+len,fname,size-len-1); buffer[size-1]='\0'; } return( buffer ); } unichar_t *u_GFileNameTail(const unichar_t *oldname) { unichar_t *pt; pt = u_strrchr(oldname,'/'); if ( pt !=NULL ) return( pt+1); else return( (unichar_t *)oldname ); } unichar_t *u_GFileNormalize(unichar_t *name) { unichar_t *pt, *base, *ppt; if ( (pt = uc_strstr(name,"://"))!=NULL ) { base = u_strchr(pt+3,'/'); if ( base==NULL ) return( name ); ++base; } else if ( *name=='/' ) base = name+1; else base = name; for ( pt=base; *pt!='\0'; ) { if ( *pt=='/' ) u_strcpy(pt,pt+1); else if ( uc_strncmp(pt,"./",2)==0 ) u_strcpy(pt,pt+2); else if ( uc_strncmp(pt,"../",2)==0 ) { for ( ppt=pt-2; ppt>=base && *ppt!='/'; --ppt ); ++ppt; if ( ppt>=base ) { u_strcpy(ppt,pt+3); pt = ppt; } else pt += 3; } else { while ( *pt!='/' && *pt!='\0' ) ++pt; if ( *pt == '/' ) ++pt; } } return( name ); } unichar_t *u_GFileAppendFile(unichar_t *dir,unichar_t *name,int isdir) { unichar_t *ret, *pt; ret = galloc((u_strlen(dir)+u_strlen(name)+3)*sizeof(unichar_t)); u_strcpy(ret,dir); pt = ret+u_strlen(ret); if ( pt>ret && pt[-1]!='/' ) *pt++ = '/'; u_strcpy(pt,name); if ( isdir ) { pt += u_strlen(pt); if ( pt>ret && pt[-1]!='/' ) { *pt++ = '/'; *pt = '\0'; } } return(ret); } int u_GFileIsAbsolute(const unichar_t *file) { if ( *file=='/' ) return( true ); if ( uc_strstr(file,"://")!=NULL ) return( true ); return( false ); } int u_GFileIsDir(const unichar_t *file) { char buffer[1024]; cu_strcpy(buffer,file); strcat(buffer,"/."); return( access(buffer,0)==0 ); } int u_GFileExists(const unichar_t *file) { char buffer[1024]; cu_strcpy(buffer,file); return( access(buffer,0)==0 ); } int u_GFileModifyable(const unichar_t *file) { char buffer[1024]; cu_strcpy(buffer,file); return( access(buffer,02)==0 ); } int u_GFileModifyableDir(const unichar_t *file) { char buffer[1024], *pt; cu_strcpy(buffer,file); pt = strrchr(buffer,'/'); if ( pt==NULL ) strcpy(buffer,"."); else *pt='\0'; return( GFileModifyable(buffer)); } int u_GFileReadable(unichar_t *file) { char buffer[1024]; cu_strcpy(buffer,file); return( access(buffer,04)==0 ); } int u_GFileMkDir(unichar_t *name) { char buffer[1024]; cu_strcpy(buffer,name); return( MKDIR(buffer,0755)); } int u_GFileRmDir(unichar_t *name) { char buffer[1024]; cu_strcpy(buffer,name); return(rmdir(buffer)); } int u_GFileUnlink(unichar_t *name) { char buffer[1024]; cu_strcpy(buffer,name); return(unlink(buffer)); }