Annotation of sbbs/src/xpdev/dirwrap.c, revision 1.1

1.1     ! root        1: /* dirwrap.c */
        !             2: 
        !             3: /* Directory-related system-call wrappers */
        !             4: 
        !             5: /* $Id: dirwrap.c,v 1.70 2006/08/24 00:20:48 deuce Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This library is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU Lesser General Public License          *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
        !            18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: #include <string.h>    /* strrchr */
        !            39: 
        !            40: #if defined(_WIN32)
        !            41: 
        !            42:        #include <windows.h>    /* WINAPI, etc */
        !            43:        #include <io.h>                 /* _findfirst */
        !            44: 
        !            45: #elif defined __unix__
        !            46: 
        !            47:        #include <unistd.h>             /* usleep */
        !            48:        #include <fcntl.h>              /* O_NOCCTY */
        !            49:        #include <ctype.h>              /* toupper */
        !            50:        #include <sys/param.h>
        !            51: 
        !            52:        #if defined(BSD)
        !            53:                #include <sys/mount.h>
        !            54:        #endif
        !            55:        #if defined(__FreeBSD__)
        !            56:                #include <sys/kbio.h>
        !            57:        #endif
        !            58:        #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000 /* NetBSD 3.0 */)
        !            59:                #include <sys/statvfs.h>
        !            60:        #endif
        !            61: 
        !            62:        #include <sys/ioctl.h>  /* ioctl */
        !            63: 
        !            64:        #if defined(__GLIBC__)          /* actually, BSD, but will work for now */
        !            65:                #include <sys/vfs.h>    /* statfs() */
        !            66:        #endif
        !            67: 
        !            68:        #if defined(__solaris__)
        !            69:                #include <sys/statvfs.h>
        !            70:        #endif
        !            71: 
        !            72: #endif /* __unix__ */
        !            73: 
        !            74: #if defined(__WATCOMC__)
        !            75:        #include <dos.h>
        !            76: #endif
        !            77:        
        !            78: #include <sys/types.h> /* _dev_t */
        !            79: #include <sys/stat.h>  /* struct stat */
        !            80: 
        !            81: #include <stdio.h>             /* sprintf */
        !            82: #include <stdlib.h>            /* rand */
        !            83: #include <errno.h>             /* ENOENT definitions */
        !            84: 
        !            85: #include "genwrap.h"   /* strupr/strlwr */
        !            86: #include "dirwrap.h"   /* DLLCALL */
        !            87: 
        !            88: /****************************************************************************/
        !            89: /* Return the filename portion of a full pathname                                                      */
        !            90: /****************************************************************************/
        !            91: char* DLLCALL getfname(const char* path)
        !            92: {
        !            93:        const char* fname;
        !            94:        const char* bslash;
        !            95: 
        !            96:        fname=strrchr(path,'/');
        !            97:        bslash=strrchr(path,'\\');
        !            98:        if(bslash>fname)
        !            99:                fname=bslash;
        !           100:        if(fname!=NULL) 
        !           101:                fname++;
        !           102:        else 
        !           103:                fname=(char*)path;
        !           104:        return((char*)fname);
        !           105: }
        !           106: 
        !           107: /****************************************************************************/
        !           108: /* Return a pointer to a file's extesion (beginning with '.')                          */
        !           109: /****************************************************************************/
        !           110: char* DLLCALL getfext(const char* path)
        !           111: {
        !           112:        char *fname;
        !           113:        char *fext;
        !           114: 
        !           115:        fname=getfname(path);
        !           116:        fext=strrchr(fname,'.');
        !           117:        if(fext==NULL || fext==fname) 
        !           118:                return(NULL);
        !           119:        return(fext);
        !           120: }
        !           121: 
        !           122: /****************************************************************************/
        !           123: /* Break a path name into components.                                                                          */
        !           124: /****************************************************************************/
        !           125: #if defined(__unix__)
        !           126: void DLLCALL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
        !           127: {
        !           128:        char*   p;
        !           129: 
        !           130:        ext[0]=0;
        !           131:        drive[0]=0;                     /* no drive letters on Unix */
        !           132: 
        !           133:        strcpy(dir,path);       /* Optional directory path, including trailing slash. */
        !           134:        p=getfname(dir);
        !           135:        strcpy(fname,p);        /* Base filename (no extension) */
        !           136:        if(p==dir)
        !           137:                dir[0]=0;               /* no directory specified in path */
        !           138:        else
        !           139:                *p=0;                   /* truncate dir at filename */
        !           140:        p=getfext(fname);
        !           141:        if(p!=NULL) {
        !           142:                strcpy(ext,p);  /* Optional filename extension, including leading period (.) */
        !           143:                *p=0;
        !           144:        }
        !           145: }
        !           146: #endif
        !           147: 
        !           148: /****************************************************************************/
        !           149: /* Win32 (minimal) implementation of POSIX.2 glob() function                           */
        !           150: /* This code _may_ work on other DOS-based platforms (e.g. OS/2)                       */
        !           151: /****************************************************************************/
        !           152: #if !defined(__unix__)
        !           153: static int _cdecl glob_compare( const void *arg1, const void *arg2 )
        !           154: {
        !           155:    /* Compare all of both strings: */
        !           156:    return stricmp( * ( char** ) arg1, * ( char** ) arg2 );
        !           157: }
        !           158: 
        !           159: #if defined(__BORLANDC__)
        !           160:        #pragma argsused
        !           161: #endif
        !           162: 
        !           163: #if defined(__WATCOMC__)
        !           164: 
        !           165: int    DLLCALL glob(const char *pattern, int flags, void* unused, glob_t* glob)
        !           166: {
        !           167:     struct     find_t ff;
        !           168:        size_t  found=0;
        !           169:        char    path[MAX_PATH+1];
        !           170:        char*   p;
        !           171:        char**  new_pathv;
        !           172: 
        !           173:        if(!(flags&GLOB_APPEND)) {
        !           174:                glob->gl_pathc=0;
        !           175:                glob->gl_pathv=NULL;
        !           176:        }
        !           177: 
        !           178:        if(_dos_findfirst((char*)pattern,_A_NORMAL,&ff)!=0)
        !           179:                return(GLOB_NOMATCH);
        !           180: 
        !           181:        do {
        !           182:                if((flags&GLOB_PERIOD || ff.name[0]!='.') &&
        !           183:                        (!(flags&GLOB_ONLYDIR) || ff.attrib&_A_SUBDIR)) {
        !           184:                        if((new_pathv=realloc(glob->gl_pathv
        !           185:                                ,(glob->gl_pathc+1)*sizeof(char*)))==NULL) {
        !           186:                                globfree(glob);
        !           187:                                return(GLOB_NOSPACE);
        !           188:                        }
        !           189:                        glob->gl_pathv=new_pathv;
        !           190: 
        !           191:                        /* build the full pathname */
        !           192:                        SAFECOPY(path,pattern);
        !           193:                        p=getfname(path);
        !           194:                        *p=0;
        !           195:                        strcat(path,ff.name);
        !           196: 
        !           197:                        if((glob->gl_pathv[glob->gl_pathc]=malloc(strlen(path)+2))==NULL) {
        !           198:                                globfree(glob);
        !           199:                                return(GLOB_NOSPACE);
        !           200:                        }
        !           201:                        strcpy(glob->gl_pathv[glob->gl_pathc],path);
        !           202:                        if(flags&GLOB_MARK && ff.attrib&_A_SUBDIR)
        !           203:                                strcat(glob->gl_pathv[glob->gl_pathc],"/");
        !           204: 
        !           205:                        glob->gl_pathc++;
        !           206:                        found++;
        !           207:                }
        !           208:        } while(_dos_findnext(&ff)==0);
        !           209:        _dos_findclose(&ff);
        !           210: 
        !           211:        if(found==0)
        !           212:                return(GLOB_NOMATCH);
        !           213: 
        !           214:        if(!(flags&GLOB_NOSORT)) {
        !           215:                qsort(glob->gl_pathv,found,sizeof(char*),glob_compare);
        !           216:        }
        !           217: 
        !           218:        return(0);      /* success */
        !           219: }
        !           220: 
        !           221: #else
        !           222: 
        !           223: int    DLLCALL glob(const char *pattern, int flags, void* unused, glob_t* glob)
        !           224: {
        !           225:     struct     _finddata_t ff;
        !           226:        long    ff_handle;
        !           227:        size_t  found=0;
        !           228:        char    path[MAX_PATH+1];
        !           229:        char*   p;
        !           230:        char**  new_pathv;
        !           231: 
        !           232:        if(!(flags&GLOB_APPEND)) {
        !           233:                glob->gl_pathc=0;
        !           234:                glob->gl_pathv=NULL;
        !           235:        }
        !           236: 
        !           237:        ff_handle=_findfirst((char*)pattern,&ff);
        !           238:        while(ff_handle!=-1) {
        !           239:                if((flags&GLOB_PERIOD || ff.name[0]!='.') &&
        !           240:                        (!(flags&GLOB_ONLYDIR) || ff.attrib&_A_SUBDIR)) {
        !           241:                        if((new_pathv=(char**)realloc(glob->gl_pathv
        !           242:                                ,(glob->gl_pathc+1)*sizeof(char*)))==NULL) {
        !           243:                                globfree(glob);
        !           244:                                return(GLOB_NOSPACE);
        !           245:                        }
        !           246:                        glob->gl_pathv=new_pathv;
        !           247: 
        !           248:                        /* build the full pathname */
        !           249:                        SAFECOPY(path,pattern);
        !           250:                        p=getfname(path);
        !           251:                        *p=0;
        !           252:                        strcat(path,ff.name);
        !           253: 
        !           254:                        if((glob->gl_pathv[glob->gl_pathc]=(char*)malloc(strlen(path)+2))==NULL) {
        !           255:                                globfree(glob);
        !           256:                                return(GLOB_NOSPACE);
        !           257:                        }
        !           258:                        strcpy(glob->gl_pathv[glob->gl_pathc],path);
        !           259:                        if(flags&GLOB_MARK && ff.attrib&_A_SUBDIR)
        !           260:                                strcat(glob->gl_pathv[glob->gl_pathc],"/");
        !           261: 
        !           262:                        glob->gl_pathc++;
        !           263:                        found++;
        !           264:                }
        !           265:                if(_findnext(ff_handle, &ff)!=0) {
        !           266:                        _findclose(ff_handle);
        !           267:                        ff_handle=-1; 
        !           268:                } 
        !           269:        }
        !           270: 
        !           271:        if(found==0)
        !           272:                return(GLOB_NOMATCH);
        !           273: 
        !           274:        if(!(flags&GLOB_NOSORT)) {
        !           275:                qsort(glob->gl_pathv,found,sizeof(char*),glob_compare);
        !           276:        }
        !           277: 
        !           278:        return(0);      /* success */
        !           279: }
        !           280: 
        !           281: #endif
        !           282: 
        !           283: void DLLCALL globfree(glob_t* glob)
        !           284: {
        !           285:        size_t i;
        !           286: 
        !           287:        if(glob==NULL)
        !           288:                return;
        !           289: 
        !           290:        if(glob->gl_pathv!=NULL) {
        !           291:                for(i=0;i<glob->gl_pathc;i++)
        !           292:                        if(glob->gl_pathv[i]!=NULL)
        !           293:                                free(glob->gl_pathv[i]);
        !           294: 
        !           295:                free(glob->gl_pathv);
        !           296:                glob->gl_pathv=NULL;
        !           297:        }
        !           298:        glob->gl_pathc=0;
        !           299: }
        !           300: 
        !           301: #endif /* !defined(__unix__) */
        !           302: 
        !           303: /****************************************************************************/
        !           304: /* POSIX directory operations using Microsoft _findfirst/next API.                     */
        !           305: /****************************************************************************/
        !           306: #if defined(_MSC_VER) || defined(__DMC__)
        !           307: DIR* opendir(const char* dirname)
        !           308: {
        !           309:        DIR*    dir;
        !           310: 
        !           311:        if((dir=(DIR*)calloc(1,sizeof(DIR)))==NULL) {
        !           312:                errno=ENOMEM;
        !           313:                return(NULL);
        !           314:        }
        !           315:        sprintf(dir->filespec,"%.*s",sizeof(dir->filespec)-5,dirname);
        !           316:        if(*dir->filespec && dir->filespec[strlen(dir->filespec)-1]!='\\')
        !           317:                strcat(dir->filespec,"\\");
        !           318:        strcat(dir->filespec,"*.*");
        !           319:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
        !           320:        if(dir->handle==-1) {
        !           321:                errno=ENOENT;
        !           322:                free(dir);
        !           323:                return(NULL);
        !           324:        }
        !           325:        return(dir);
        !           326: }
        !           327: struct dirent* readdir(DIR* dir)
        !           328: {
        !           329:        if(dir==NULL)
        !           330:                return(NULL);
        !           331:        if(dir->end==TRUE)
        !           332:                return(NULL);
        !           333:        if(dir->handle==-1)
        !           334:                return(NULL);
        !           335:        sprintf(dir->dirent.d_name,"%.*s",sizeof(struct dirent)-1,dir->finddata.name);
        !           336:        if(_findnext(dir->handle,&dir->finddata)!=0)
        !           337:                dir->end=TRUE;
        !           338:        return(&dir->dirent);
        !           339: }
        !           340: int closedir (DIR* dir)
        !           341: {
        !           342:        if(dir==NULL)
        !           343:                return(-1);
        !           344:        _findclose(dir->handle);
        !           345:        free(dir);
        !           346:        return(0);
        !           347: }
        !           348: void rewinddir(DIR* dir)
        !           349: {
        !           350:        if(dir==NULL)
        !           351:                return;
        !           352:        _findclose(dir->handle);
        !           353:        dir->end=FALSE;
        !           354:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
        !           355: }
        !           356: #endif /* defined(_MSC_VER) */
        !           357: 
        !           358: /****************************************************************************/
        !           359: /* Returns the time/date of the file in 'filename' in time_t (unix) format  */
        !           360: /****************************************************************************/
        !           361: time_t DLLCALL fdate(const char* filename)
        !           362: {
        !           363:        struct stat st;
        !           364: 
        !           365:        if(access(filename,0)==-1)
        !           366:                return(-1);
        !           367: 
        !           368:        if(stat(filename, &st)!=0)
        !           369:                return(-1);
        !           370: 
        !           371:        return(st.st_mtime);
        !           372: }
        !           373: 
        !           374: /****************************************************************************/
        !           375: /* Change the access and modification times for specified filename                     */
        !           376: /****************************************************************************/
        !           377: int DLLCALL setfdate(const char* filename, time_t t)
        !           378: {
        !           379:        struct utimbuf ut;
        !           380: 
        !           381:        memset(&ut,0,sizeof(ut));
        !           382: 
        !           383:        ut.actime=t;
        !           384:        ut.modtime=t;
        !           385: 
        !           386:        return(utime(filename,&ut));
        !           387: }
        !           388: 
        !           389: /****************************************************************************/
        !           390: /* Returns the length of the file in 'filename'                             */
        !           391: /****************************************************************************/
        !           392: long DLLCALL flength(const char *filename)
        !           393: {
        !           394: #if defined(__BORLANDC__) && !defined(__unix__)        /* stat() doesn't work right */
        !           395: 
        !           396:        long    handle;
        !           397:        struct _finddata_t f;
        !           398: 
        !           399:        if(access((char*)filename,0)==-1)
        !           400:                return(-1L);
        !           401: 
        !           402:        if((handle=_findfirst((char*)filename,&f))==-1)
        !           403:                return(-1);
        !           404: 
        !           405:        _findclose(handle);
        !           406: 
        !           407:        return(f.size);
        !           408: 
        !           409: #else 
        !           410: 
        !           411:        struct stat st;
        !           412: 
        !           413:        if(access(filename,0)==-1)
        !           414:                return(-1L);
        !           415: 
        !           416:        if(stat(filename, &st)!=0)
        !           417:                return(-1L);
        !           418: 
        !           419:        return(st.st_size);
        !           420: 
        !           421: #endif
        !           422: }
        !           423: 
        !           424: 
        !           425: /****************************************************************************/
        !           426: /* Checks the file system for the existence of one or more files.                      */
        !           427: /* Returns TRUE if it exists, FALSE if it doesn't.                          */
        !           428: /* 'filespec' may *NOT* contain wildcards!                                                                     */
        !           429: /****************************************************************************/
        !           430: static BOOL fnameexist(const char *filename)
        !           431: {
        !           432:        if(access(filename,0)==-1)
        !           433:                return(FALSE);
        !           434:        if(!isdir(filename))
        !           435:                return(TRUE);
        !           436:        return(FALSE);
        !           437: }
        !           438: 
        !           439: /****************************************************************************/
        !           440: /* Checks the file system for the existence of one or more files.                      */
        !           441: /* Returns TRUE if it exists, FALSE if it doesn't.                          */
        !           442: /* 'filespec' may contain wildcards!                                                                           */
        !           443: /****************************************************************************/
        !           444: BOOL DLLCALL fexist(const char *filespec)
        !           445: {
        !           446: #if defined(_WIN32)
        !           447: 
        !           448:        long    handle;
        !           449:        struct _finddata_t f;
        !           450: 
        !           451:        if(!strchr(filespec,'*') && !strchr(filespec,'?'))
        !           452:                return(fnameexist(filespec));
        !           453: 
        !           454:        if((handle=_findfirst((char*)filespec,&f))==-1)
        !           455:                return(FALSE);
        !           456: 
        !           457:        _findclose(handle);
        !           458: 
        !           459:        if(f.attrib&_A_SUBDIR)
        !           460:                return(FALSE);
        !           461: 
        !           462:        return(TRUE);
        !           463: 
        !           464: #else /* Unix or OS/2 */
        !           465:        
        !           466:        /* portion by cmartin */
        !           467: 
        !           468:        glob_t g;
        !           469:     int c;
        !           470: 
        !           471:        if(!strchr(filespec,'*') && !strchr(filespec,'?'))
        !           472:                return(fnameexist(filespec));
        !           473: 
        !           474:     /* start the search */
        !           475:     glob(filespec, GLOB_MARK | GLOB_NOSORT, NULL, &g);
        !           476: 
        !           477:     if (!g.gl_pathc) {
        !           478:            /* no results */
        !           479:        globfree(&g);
        !           480:        return FALSE;
        !           481:     }
        !           482: 
        !           483:     /* make sure it's not a directory */
        !           484:        c = g.gl_pathc;
        !           485:     while (c--) {
        !           486:        if (*lastchar(g.gl_pathv[c]) != '/') {
        !           487:                globfree(&g);
        !           488:             return TRUE;
        !           489:         }
        !           490:     }
        !           491:         
        !           492:     globfree(&g);
        !           493:     return FALSE;
        !           494: 
        !           495: #endif
        !           496: }
        !           497: 
        !           498: /****************************************************************************/
        !           499: /* Fixes upper/lowercase filename for Unix file systems                                                */
        !           500: /****************************************************************************/
        !           501: BOOL DLLCALL fexistcase(char *path)
        !           502: {
        !           503: #if defined(_WIN32)
        !           504: 
        !           505:        char*   fname;
        !           506:        long    handle;
        !           507:        struct _finddata_t f;
        !           508: 
        !           509:        if(access(path,0)==-1 && !strchr(path,'*') && !strchr(path,'?'))
        !           510:                return(FALSE);
        !           511: 
        !           512:        if((handle=_findfirst((char*)path,&f))==-1)
        !           513:                return(FALSE);
        !           514: 
        !           515:        _findclose(handle);
        !           516: 
        !           517:        if(f.attrib&_A_SUBDIR)
        !           518:                return(FALSE);
        !           519: 
        !           520:        fname=getfname(path);   /* Find filename in path */
        !           521:        strcpy(fname,f.name);   /* Correct filename */
        !           522: 
        !           523:        return(TRUE);
        !           524: 
        !           525: #else /* Unix or OS/2 */
        !           526: 
        !           527:        char globme[MAX_PATH*4+1];
        !           528:        char fname[MAX_PATH+1];
        !           529:        char tmp[5];
        !           530:        char *p;
        !           531:        int  i;
        !           532:        glob_t  glb;
        !           533:        
        !           534:        if(!strchr(path,'*') && !strchr(path,'?') && fnameexist(path))
        !           535:                return(TRUE);
        !           536: 
        !           537:        SAFECOPY(globme,path);
        !           538:        p=getfname(globme);
        !           539:        SAFECOPY(fname,p);
        !           540:        *p=0;
        !           541:        for(i=0;fname[i];i++)  {
        !           542:                if(isalpha(fname[i]))
        !           543:                        sprintf(tmp,"[%c%c]",toupper(fname[i]),tolower(fname[i]));
        !           544:                else
        !           545:                        sprintf(tmp,"%c",fname[i]);
        !           546:                strncat(globme,tmp,MAX_PATH*4);
        !           547:        }
        !           548: #if 0
        !           549:        if(strcspn(path,"?*")!=strlen(path))  {
        !           550:                sprintf(path,"%.*s",MAX_PATH,globme);
        !           551:                return(fexist(path));
        !           552:        }
        !           553: #endif
        !           554: 
        !           555:        if(glob(globme,GLOB_MARK,NULL,&glb) != 0)
        !           556:                return(FALSE);
        !           557:        
        !           558:        if(glb.gl_pathc>0)  {
        !           559:                for(i=0;i<glb.gl_pathc;i++)  {
        !           560:                        if(*lastchar(glb.gl_pathv[i]) != '/')
        !           561:                                break;
        !           562:                }
        !           563:                if(i<glb.gl_pathc)  {
        !           564:                        sprintf(path,"%.*s",MAX_PATH,glb.gl_pathv[i]);
        !           565:                        globfree(&glb);
        !           566:                        return TRUE;
        !           567:                }
        !           568:        }
        !           569: 
        !           570:        globfree(&glb);
        !           571:        return FALSE;
        !           572:        
        !           573: #endif
        !           574: }
        !           575: 
        !           576: #if !defined(S_ISDIR)
        !           577:        #define S_ISDIR(x)      ((x)&S_IFDIR)
        !           578: #endif
        !           579: 
        !           580: /****************************************************************************/
        !           581: /* Returns TRUE if the filename specified is a directory                                       */
        !           582: /****************************************************************************/
        !           583: BOOL DLLCALL isdir(const char *filename)
        !           584: {
        !           585:        char    path[MAX_PATH+1];
        !           586:        char*   p;
        !           587:        struct stat st;
        !           588: 
        !           589:        SAFECOPY(path,filename);
        !           590: 
        !           591:        p=lastchar(path);
        !           592:        if(p!=path && IS_PATH_DELIM(*p)) {      /* chop off trailing slash */
        !           593: #if !defined(__unix__)
        !           594:                if(*(p-1)!=':')         /* Don't change C:\ to C: */
        !           595: #endif
        !           596:                        *p=0;
        !           597:        }
        !           598: 
        !           599: #if defined(__BORLANDC__) && !defined(__unix__)        /* stat() doesn't work right */
        !           600:        if(stat(path, &st)!=0 || strchr(path,'*')!=NULL || strchr(path,'?')!=NULL)
        !           601: #else
        !           602:        if(stat(path, &st)!=0)
        !           603: #endif
        !           604:                return(FALSE);
        !           605: 
        !           606:        return(S_ISDIR(st.st_mode) ? TRUE : FALSE);
        !           607: }
        !           608: 
        !           609: /****************************************************************************/
        !           610: /* Returns the attributes (mode) for specified 'filename'                                      */
        !           611: /****************************************************************************/
        !           612: int DLLCALL getfattr(const char* filename)
        !           613: {
        !           614: #if defined(_WIN32)
        !           615:        long handle;
        !           616:        struct _finddata_t      finddata;
        !           617: 
        !           618:        if((handle=_findfirst((char*)filename,&finddata))==-1) {
        !           619:                errno=ENOENT;
        !           620:                return(-1);
        !           621:        }
        !           622:        _findclose(handle);
        !           623:        return(finddata.attrib);
        !           624: #else
        !           625:        struct stat st;
        !           626: 
        !           627:        if(stat(filename, &st)!=0) {
        !           628:                errno=ENOENT;
        !           629:                return(-1L);
        !           630:        }
        !           631: 
        !           632:        return(st.st_mode);
        !           633: #endif
        !           634: }
        !           635: 
        !           636: #ifdef __unix__
        !           637: int removecase(char *path)
        !           638: {
        !           639:        char inpath[MAX_PATH+1];
        !           640:        char fname[MAX_PATH*4+1];
        !           641:        char tmp[5];
        !           642:        char *p;
        !           643:        int  i;
        !           644: 
        !           645:        if(strchr(path,'?') || strchr(path,'*'))
        !           646:                return(-1);
        !           647:        SAFECOPY(inpath,path);
        !           648:        p=getfname(inpath);
        !           649:        fname[0]=0;
        !           650:        for(i=0;p[i];i++)  {
        !           651:                if(isalpha(p[i]))
        !           652:                        sprintf(tmp,"[%c%c]",toupper(p[i]),tolower(p[i]));
        !           653:                else
        !           654:                        sprintf(tmp,"%c",p[i]);
        !           655:                strncat(fname,tmp,MAX_PATH*4);
        !           656:        }
        !           657:        *p=0;
        !           658: 
        !           659:        return(delfiles(inpath,fname)?-1:0);
        !           660: }
        !           661: #endif
        !           662: 
        !           663: /****************************************************************************/
        !           664: /* Deletes all files in dir 'path' that match file spec 'spec'              */
        !           665: /****************************************************************************/
        !           666: ulong DLLCALL delfiles(char *inpath, char *spec)
        !           667: {
        !           668:        char    path[MAX_PATH+1];
        !           669:        char    lastch;
        !           670:     uint       i,files=0;
        !           671:        glob_t  g;
        !           672: 
        !           673:        lastch=*lastchar(inpath);
        !           674:        if(!IS_PATH_DELIM(lastch) && lastch)
        !           675:                sprintf(path,"%s%c",inpath,PATH_DELIM);
        !           676:        else
        !           677:                strcpy(path,inpath);
        !           678:        strcat(path,spec);
        !           679:        glob(path,0,NULL,&g);
        !           680:        for(i=0;i<g.gl_pathc;i++) {
        !           681:                if(isdir(g.gl_pathv[i]))
        !           682:                        continue;
        !           683:                CHMOD(g.gl_pathv[i],S_IWRITE);  /* Incase it's been marked RDONLY */
        !           684:                if(remove(g.gl_pathv[i])==0)
        !           685:                        files++;
        !           686:        }
        !           687:        globfree(&g);
        !           688:        return(files);
        !           689: }
        !           690: 
        !           691: /****************************************************************************/
        !           692: /* Return free disk space in bytes (up to a maximum of 4GB)                                    */
        !           693: /****************************************************************************/
        !           694: #if defined(_WIN32)
        !           695: typedef BOOL(WINAPI * GetDiskFreeSpaceEx_t)
        !           696:        (LPCTSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER); 
        !           697: 
        !           698: static int bit_num(ulong val)
        !           699: {
        !           700:        int i;
        !           701: 
        !           702:        for(i=31;i>=0;i--)
        !           703:                if(val&(1<<i))
        !           704:                        return(i);
        !           705: 
        !           706:        return(-1);
        !           707: }
        !           708: #endif
        !           709: 
        !           710: /* Unit should be a power-of-2 (e.g. 1024 to report kilobytes) or 1 (to report bytes) */
        !           711: static ulong getdiskspace(const char* path, ulong unit, BOOL freespace)
        !           712: {
        !           713: #if defined(_WIN32)
        !           714:        char                    root[16];
        !           715:        DWORD                   TotalNumberOfClusters;
        !           716:        DWORD                   NumberOfFreeClusters;
        !           717:        DWORD                   BytesPerSector;
        !           718:        DWORD                   SectorsPerCluster;
        !           719:        ULARGE_INTEGER  avail;
        !           720:        ULARGE_INTEGER  size;
        !           721:        static HINSTANCE hK32;
        !           722:        GetDiskFreeSpaceEx_t GetDiskFreeSpaceEx;
        !           723: 
        !           724:        if(hK32 == NULL)
        !           725:                hK32 = LoadLibrary("KERNEL32");
        !           726:        GetDiskFreeSpaceEx 
        !           727:                = (GetDiskFreeSpaceEx_t)GetProcAddress(hK32,"GetDiskFreeSpaceExA");
        !           728:  
        !           729:        if (GetDiskFreeSpaceEx!=NULL) { /* Windows 95-OSR2 or later */
        !           730:                if(!GetDiskFreeSpaceEx(
        !           731:                        path,           /* pointer to the directory name */
        !           732:                        &avail,         /* receives the number of bytes on disk avail to the caller */
        !           733:                        &size,          /* receives the number of bytes on disk */
        !           734:                        NULL))          /* receives the free bytes on disk */
        !           735:                        return(0);
        !           736: 
        !           737:                if(freespace)
        !           738:                        size=avail;
        !           739: 
        !           740:                if(unit>1)
        !           741:                        size.QuadPart=Int64ShrlMod32(size.QuadPart,bit_num(unit));
        !           742: 
        !           743: #if defined(_ANONYMOUS_STRUCT)
        !           744:                if(size.HighPart)
        !           745: #else
        !           746:                if(size.u.HighPart)
        !           747: #endif
        !           748:                        return(0xffffffff);     /* 4GB max */
        !           749: 
        !           750: #if defined(_ANONYMOUS_STRUCT)
        !           751:                return(size.LowPart);
        !           752: #else
        !           753:                return(size.u.LowPart);
        !           754: #endif
        !           755:        }
        !           756: 
        !           757:        /* Windows 95 (old way), limited to 2GB */
        !           758:        sprintf(root,"%.3s",path);
        !           759:        if(!GetDiskFreeSpace(
        !           760:                root,                                   /* pointer to root path */
        !           761:                &SectorsPerCluster,             /* pointer to sectors per cluster */
        !           762:                &BytesPerSector,                /* pointer to bytes per sector */
        !           763:                &NumberOfFreeClusters,  /* pointer to number of free clusters */
        !           764:                &TotalNumberOfClusters  /* pointer to total number of clusters */
        !           765:                ))
        !           766:                return(0);
        !           767: 
        !           768:        if(freespace)
        !           769:                TotalNumberOfClusters = NumberOfFreeClusters;
        !           770:        if(unit>1)
        !           771:                TotalNumberOfClusters/=unit;
        !           772:        return(TotalNumberOfClusters*SectorsPerCluster*BytesPerSector);
        !           773: 
        !           774: 
        !           775: #elif defined(__solaris__) || (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000 /* NetBSD 3.0 */))
        !           776: 
        !           777:        struct statvfs fs;
        !           778:        unsigned long blocks;
        !           779: 
        !           780:     if (statvfs(path, &fs) < 0)
        !           781:        return 0;
        !           782: 
        !           783:        if(freespace)
        !           784:                blocks=fs.f_bavail;
        !           785:        else
        !           786:                blocks=fs.f_blocks;
        !           787: 
        !           788:        if(unit>1)
        !           789:                blocks/=unit;
        !           790:     return fs.f_bsize * blocks;
        !           791:     
        !           792: /* statfs is also used under FreeBSD (Though it *supports* statvfs() now too) */
        !           793: #elif defined(__GLIBC__) || defined(BSD)
        !           794: 
        !           795:        struct statfs fs;
        !           796:        unsigned long blocks;
        !           797: 
        !           798:     if (statfs(path, &fs) < 0)
        !           799:        return 0;
        !           800: 
        !           801:        if(freespace)
        !           802:                blocks=fs.f_bavail;
        !           803:        else
        !           804:                blocks=fs.f_blocks;
        !           805: 
        !           806:        if(unit>1)
        !           807:                blocks/=unit;
        !           808:     return fs.f_bsize * blocks;
        !           809:     
        !           810: #else
        !           811: 
        !           812:        fprintf(stderr,"\n*** !Missing getfreediskspace implementation ***\n");
        !           813:        return(0);
        !           814: 
        !           815: #endif
        !           816: }
        !           817: 
        !           818: ulong DLLCALL getfreediskspace(const char* path, ulong unit)
        !           819: {
        !           820:        return getdiskspace(path, unit, /* freespace? */TRUE);
        !           821: }
        !           822: 
        !           823: ulong DLLCALL getdisksize(const char* path, ulong unit)
        !           824: {
        !           825:        return getdiskspace(path, unit, /* freespace? */FALSE);
        !           826: }
        !           827: 
        !           828: /****************************************************************************/
        !           829: /* Resolves //, /./, and /../ in a path. Should work indetically to Windows */
        !           830: /****************************************************************************/
        !           831: #if defined(__unix__)
        !           832: char * DLLCALL _fullpath(char *target, const char *path, size_t size)  {
        !           833:        char    *out;
        !           834:        char    *p;
        !           835: 
        !           836:        if(target==NULL)  {
        !           837:                if((target=malloc(MAX_PATH+1))==NULL) {
        !           838:                        return(NULL);
        !           839:                }
        !           840:        }
        !           841:        out=target;
        !           842:        *out=0;
        !           843: 
        !           844:        if(*path != '/')  {
        !           845:                if(*path == '~') {
        !           846:                        p=getenv("HOME");
        !           847:                        if(p==NULL || strlen(p)+strlen(path)>=size)
        !           848:                                return(NULL);
        !           849:                        strcpy(target,p);
        !           850:                        out=strrchr(target,'\0');
        !           851:                        path++;
        !           852:                }
        !           853:                else {
        !           854:                        p=getcwd(NULL,size);
        !           855:                        if(p==NULL || strlen(p)+strlen(path)>=size)
        !           856:                                return(NULL);
        !           857:                        strcpy(target,p);
        !           858:                        free(p);
        !           859:                        out=strrchr(target,'\0');
        !           860:                        *(out++)='/';
        !           861:                        *out=0;
        !           862:                        out--;
        !           863:                }
        !           864:        }
        !           865:        strncat(target,path,size-1);
        !           866:        
        !           867: /*     if(stat(target,&sb))
        !           868:                return(NULL);
        !           869:        if(sb.st_mode&S_IFDIR)
        !           870:                strcat(target,"/"); */
        !           871: 
        !           872:        for(;*out;out++)  {
        !           873:                while(*out=='/')  {
        !           874:                        if(*(out+1)=='/')
        !           875:                                memmove(out,out+1,strlen(out));
        !           876:                        else if(*(out+1)=='.' && (*(out+2)=='/' || *(out+2)==0))
        !           877:                                memmove(out,out+2,strlen(out)-1);
        !           878:                        else if(*(out+1)=='.' && *(out+2)=='.' && (*(out+3)=='/' || *(out+3)==0))  {
        !           879:                                *out=0;
        !           880:                                p=strrchr(target,'/');
        !           881:                                if(p==NULL)
        !           882:                                        p=target;
        !           883:                                memmove(p,out+3,strlen(out+3)+1);
        !           884:                                out=p;
        !           885:                        }
        !           886:                        else  {
        !           887:                                out++;
        !           888:                        }
        !           889:                }
        !           890:        }
        !           891:        return(target);
        !           892: }
        !           893: #endif
        !           894: 
        !           895: /****************************************************************************/
        !           896: /* Adds a trailing slash/backslash (path delimiter) on path strings            */
        !           897: /****************************************************************************/
        !           898: char* DLLCALL backslash(char* path)
        !           899: {
        !           900:        char* p;
        !           901: 
        !           902:        p=lastchar(path);
        !           903: 
        !           904:        if(*p && !IS_PATH_DELIM(*p)) {
        !           905: #if defined(__unix__)
        !           906:                /* Convert trailing backslash to forwardslash on *nix */
        !           907:                if(*p!='\\')
        !           908: #endif
        !           909:                        p++;
        !           910:                *p=PATH_DELIM;
        !           911:                *(++p)=0;
        !           912:        }
        !           913:        return(path);
        !           914: }
        !           915: 
        !           916: /****************************************************************************/
        !           917: /* Returns true if the specified filename an aboslute pathname                         */
        !           918: /****************************************************************************/
        !           919: BOOL DLLCALL isabspath(const char *filename)
        !           920: {
        !           921:        char path[MAX_PATH+1];
        !           922: 
        !           923:        return(stricmp(filename,FULLPATH(path,filename,sizeof(path)))==0);
        !           924: }
        !           925: 
        !           926: /****************************************************************************/
        !           927: /* Returns true if the specified filename is a full ("rooted") path                    */
        !           928: /****************************************************************************/
        !           929: BOOL DLLCALL isfullpath(const char* filename)
        !           930: {
        !           931:        return(filename[0]=='/' 
        !           932: #ifdef WIN32
        !           933:                || filename[0]=='\\' || filename[1]==':'
        !           934: #endif
        !           935:                );
        !           936: }
        !           937: 
        !           938: /****************************************************************************/
        !           939: /* Matches file name against filespec                                                                          */
        !           940: /* Optionally not allowing * to match PATH_DELIM (for paths)                           */
        !           941: /****************************************************************************/
        !           942: BOOL DLLCALL wildmatch(const char *fname, const char *spec, BOOL path)
        !           943: {
        !           944:        char *specp;
        !           945:        char *fnamep;
        !           946: 
        !           947:        specp=(char *)spec;
        !           948:        fnamep=(char *)fname;
        !           949:        for(;;specp++, fnamep++) {
        !           950:                switch(*specp) {
        !           951:                        case '?':
        !           952:                                if(!(*fnamep))
        !           953:                                        return(FALSE);
        !           954:                                break;
        !           955:                        case 0:
        !           956:                                if(!*fnamep)
        !           957:                                        return(TRUE);
        !           958:                                break;
        !           959:                        case '*':
        !           960:                                while(*specp=='*')
        !           961:                                        specp++;
        !           962:                                for(;*fnamep!=*specp && *fnamep;fnamep++) {
        !           963:                                        if(path && IS_PATH_DELIM(*fnamep))
        !           964:                                                return(FALSE);
        !           965:                                }
        !           966:                        default:
        !           967:                                if(*specp != *fnamep)
        !           968:                                        return(FALSE);
        !           969:                }
        !           970:                if(!(*specp && *fnamep))
        !           971:                        break;
        !           972:        }
        !           973:        while(*specp=='*')
        !           974:                specp++;
        !           975:        if(*specp==*fnamep)
        !           976:                return(TRUE);
        !           977:        return(FALSE);
        !           978: }
        !           979: 
        !           980: /****************************************************************************/
        !           981: /* Matches file name against filespec, ignoring case                                           */
        !           982: /****************************************************************************/
        !           983: BOOL DLLCALL wildmatchi(const char *fname, const char *spec, BOOL path)
        !           984: {
        !           985:        char* s1;
        !           986:        char* s2;
        !           987:        BOOL result;
        !           988: 
        !           989:        if((s1=strdup(fname))==NULL)
        !           990:                return(FALSE);
        !           991:        if((s2=strdup(spec))==NULL) {
        !           992:                free(s1);
        !           993:                return(FALSE);
        !           994:        }
        !           995:        strupr(s1);
        !           996:        strupr(s2);
        !           997:        result = wildmatch(s1, s2, path);
        !           998:        free(s1);
        !           999:        free(s2);
        !          1000:        return(result);
        !          1001: }
        !          1002: 
        !          1003: /****************************************************************************/
        !          1004: /* Creates all the necessary directories in the specified path                         */
        !          1005: /****************************************************************************/
        !          1006: int DLLCALL mkdirs(const char* path)
        !          1007: {
        !          1008:        const char*     p=path;
        !          1009:        const char*     tp;
        !          1010:        const char*     sep=
        !          1011: #ifdef _WIN32
        !          1012:                "\\"
        !          1013: #endif
        !          1014:                "/";
        !          1015:        char    dir[MAX_PATH+1];
        !          1016:        int             result=0;
        !          1017: 
        !          1018: #ifdef _WIN32
        !          1019:        if(p[1]==':')   /* Skip drive letter, if specified */
        !          1020:                p+=2;
        !          1021: #endif
        !          1022: 
        !          1023:        while(*p) {
        !          1024:                SKIP_CHARSET(p,sep);
        !          1025:                if(*p==0)
        !          1026:                        break;
        !          1027:                tp=p;
        !          1028:                FIND_CHARSET(tp,sep);
        !          1029:                safe_snprintf(dir,sizeof(dir),"%.*s",tp-path, path);
        !          1030:                if(!isdir(dir)) {
        !          1031:                        if((result=MKDIR(dir))!=0)
        !          1032:                                break;
        !          1033:                }
        !          1034:                p=tp;
        !          1035:        }
        !          1036: 
        !          1037:        return(result);
        !          1038: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.