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

1.1       root        1: /* dirwrap.c */
                      2: 
                      3: /* Directory-related system-call wrappers */
                      4: 
1.1.1.2 ! root        5: /* $Id: dirwrap.c,v 1.83 2011/09/08 22:22:48 rswindell Exp $ */
1.1       root        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:  *                                                                                                                                                     *
1.1.1.2 ! root       11:  * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html         *
1.1       root       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: 
1.1.1.2 ! root      178:        if(_dos_findfirst((char*)pattern,(flags&GLOB_PERIOD) ? _A_HIDDEN : _A_NORMAL,&ff)!=0)
1.1       root      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) {
1.1.1.2 ! root      239:                if((flags&GLOB_PERIOD || (ff.name[0]!='.' && !(ff.attrib&_A_HIDDEN))) &&
1.1       root      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: 
1.1.1.2 ! root      303: long DLLCALL getdirsize(const char* path, BOOL include_subdirs, BOOL subdir_only)
        !           304: {
        !           305:        char            match[MAX_PATH+1];
        !           306:        glob_t          g;
        !           307:        unsigned        gi;
        !           308:        long            count=0;
        !           309: 
        !           310:        if(!isdir(path))
        !           311:                return -1;
        !           312: 
        !           313:        SAFECOPY(match,path);
        !           314:        backslash(match);
        !           315:        strcat(match,ALLFILES);
        !           316:        glob(match,GLOB_MARK,NULL,&g);
        !           317:        if(include_subdirs && !subdir_only)
        !           318:                count=g.gl_pathc;
        !           319:        else
        !           320:                for(gi=0;gi<g.gl_pathc;gi++) {
        !           321:                        if(*lastchar(g.gl_pathv[gi])=='/') {
        !           322:                                if(!include_subdirs)
        !           323:                                        continue;
        !           324:                        } else
        !           325:                                if(subdir_only)
        !           326:                                        continue;
        !           327:                        count++;
        !           328:                }
        !           329:        globfree(&g);
        !           330:        return(count);
        !           331: }
        !           332: 
1.1       root      333: /****************************************************************************/
                    334: /* POSIX directory operations using Microsoft _findfirst/next API.                     */
                    335: /****************************************************************************/
                    336: #if defined(_MSC_VER) || defined(__DMC__)
                    337: DIR* opendir(const char* dirname)
                    338: {
                    339:        DIR*    dir;
                    340: 
                    341:        if((dir=(DIR*)calloc(1,sizeof(DIR)))==NULL) {
                    342:                errno=ENOMEM;
                    343:                return(NULL);
                    344:        }
                    345:        sprintf(dir->filespec,"%.*s",sizeof(dir->filespec)-5,dirname);
                    346:        if(*dir->filespec && dir->filespec[strlen(dir->filespec)-1]!='\\')
                    347:                strcat(dir->filespec,"\\");
                    348:        strcat(dir->filespec,"*.*");
                    349:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
                    350:        if(dir->handle==-1) {
                    351:                errno=ENOENT;
                    352:                free(dir);
                    353:                return(NULL);
                    354:        }
                    355:        return(dir);
                    356: }
                    357: struct dirent* readdir(DIR* dir)
                    358: {
                    359:        if(dir==NULL)
                    360:                return(NULL);
                    361:        if(dir->end==TRUE)
                    362:                return(NULL);
                    363:        if(dir->handle==-1)
                    364:                return(NULL);
                    365:        sprintf(dir->dirent.d_name,"%.*s",sizeof(struct dirent)-1,dir->finddata.name);
                    366:        if(_findnext(dir->handle,&dir->finddata)!=0)
                    367:                dir->end=TRUE;
                    368:        return(&dir->dirent);
                    369: }
                    370: int closedir (DIR* dir)
                    371: {
                    372:        if(dir==NULL)
                    373:                return(-1);
                    374:        _findclose(dir->handle);
                    375:        free(dir);
                    376:        return(0);
                    377: }
                    378: void rewinddir(DIR* dir)
                    379: {
                    380:        if(dir==NULL)
                    381:                return;
                    382:        _findclose(dir->handle);
                    383:        dir->end=FALSE;
                    384:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
                    385: }
                    386: #endif /* defined(_MSC_VER) */
                    387: 
                    388: /****************************************************************************/
                    389: /* Returns the time/date of the file in 'filename' in time_t (unix) format  */
                    390: /****************************************************************************/
                    391: time_t DLLCALL fdate(const char* filename)
                    392: {
                    393:        struct stat st;
                    394: 
                    395:        if(access(filename,0)==-1)
                    396:                return(-1);
                    397: 
                    398:        if(stat(filename, &st)!=0)
                    399:                return(-1);
                    400: 
                    401:        return(st.st_mtime);
                    402: }
                    403: 
                    404: /****************************************************************************/
                    405: /* Change the access and modification times for specified filename                     */
                    406: /****************************************************************************/
                    407: int DLLCALL setfdate(const char* filename, time_t t)
                    408: {
                    409:        struct utimbuf ut;
                    410: 
                    411:        memset(&ut,0,sizeof(ut));
                    412: 
                    413:        ut.actime=t;
                    414:        ut.modtime=t;
                    415: 
                    416:        return(utime(filename,&ut));
                    417: }
                    418: 
                    419: /****************************************************************************/
                    420: /* Returns the length of the file in 'filename'                             */
1.1.1.2 ! root      421: /* or -1 if the file doesn't exist                                                                                     */
1.1       root      422: /****************************************************************************/
1.1.1.2 ! root      423: off_t DLLCALL flength(const char *filename)
1.1       root      424: {
                    425: #if defined(__BORLANDC__) && !defined(__unix__)        /* stat() doesn't work right */
                    426: 
                    427:        long    handle;
                    428:        struct _finddata_t f;
                    429: 
                    430:        if(access((char*)filename,0)==-1)
1.1.1.2 ! root      431:                return(-1);
1.1       root      432: 
                    433:        if((handle=_findfirst((char*)filename,&f))==-1)
                    434:                return(-1);
                    435: 
                    436:        _findclose(handle);
                    437: 
                    438:        return(f.size);
                    439: 
                    440: #else 
                    441: 
                    442:        struct stat st;
                    443: 
                    444:        if(access(filename,0)==-1)
1.1.1.2 ! root      445:                return(-1);
1.1       root      446: 
                    447:        if(stat(filename, &st)!=0)
1.1.1.2 ! root      448:                return(-1);
1.1       root      449: 
                    450:        return(st.st_size);
                    451: 
                    452: #endif
                    453: }
                    454: 
                    455: 
                    456: /****************************************************************************/
                    457: /* Checks the file system for the existence of one or more files.                      */
                    458: /* Returns TRUE if it exists, FALSE if it doesn't.                          */
                    459: /* 'filespec' may *NOT* contain wildcards!                                                                     */
                    460: /****************************************************************************/
                    461: static BOOL fnameexist(const char *filename)
                    462: {
                    463:        if(access(filename,0)==-1)
                    464:                return(FALSE);
                    465:        if(!isdir(filename))
                    466:                return(TRUE);
                    467:        return(FALSE);
                    468: }
                    469: 
                    470: /****************************************************************************/
                    471: /* Checks the file system for the existence of one or more files.                      */
                    472: /* Returns TRUE if it exists, FALSE if it doesn't.                          */
                    473: /* 'filespec' may contain wildcards!                                                                           */
                    474: /****************************************************************************/
                    475: BOOL DLLCALL fexist(const char *filespec)
                    476: {
                    477: #if defined(_WIN32)
                    478: 
                    479:        long    handle;
                    480:        struct _finddata_t f;
1.1.1.2 ! root      481:        BOOL    found;
1.1       root      482: 
                    483:        if(!strchr(filespec,'*') && !strchr(filespec,'?'))
                    484:                return(fnameexist(filespec));
                    485: 
                    486:        if((handle=_findfirst((char*)filespec,&f))==-1)
                    487:                return(FALSE);
1.1.1.2 ! root      488:        found=TRUE;
        !           489:        while(f.attrib&_A_SUBDIR)
        !           490:                if(_findnext(handle,&f)!=0) {
        !           491:                        found=FALSE;
        !           492:                        break;
        !           493:                }
1.1       root      494: 
                    495:        _findclose(handle);
                    496: 
1.1.1.2 ! root      497:        return(found);
1.1       root      498: 
                    499: #else /* Unix or OS/2 */
                    500:        
                    501:        /* portion by cmartin */
                    502: 
                    503:        glob_t g;
                    504:     int c;
                    505: 
                    506:        if(!strchr(filespec,'*') && !strchr(filespec,'?'))
                    507:                return(fnameexist(filespec));
                    508: 
                    509:     /* start the search */
                    510:     glob(filespec, GLOB_MARK | GLOB_NOSORT, NULL, &g);
                    511: 
                    512:     if (!g.gl_pathc) {
                    513:            /* no results */
                    514:        globfree(&g);
                    515:        return FALSE;
                    516:     }
                    517: 
                    518:     /* make sure it's not a directory */
                    519:        c = g.gl_pathc;
                    520:     while (c--) {
                    521:        if (*lastchar(g.gl_pathv[c]) != '/') {
                    522:                globfree(&g);
                    523:             return TRUE;
                    524:         }
                    525:     }
                    526:         
                    527:     globfree(&g);
                    528:     return FALSE;
                    529: 
                    530: #endif
                    531: }
                    532: 
                    533: /****************************************************************************/
                    534: /* Fixes upper/lowercase filename for Unix file systems                                                */
                    535: /****************************************************************************/
                    536: BOOL DLLCALL fexistcase(char *path)
                    537: {
                    538: #if defined(_WIN32)
                    539: 
                    540:        char*   fname;
                    541:        long    handle;
                    542:        struct _finddata_t f;
                    543: 
                    544:        if(access(path,0)==-1 && !strchr(path,'*') && !strchr(path,'?'))
                    545:                return(FALSE);
                    546: 
                    547:        if((handle=_findfirst((char*)path,&f))==-1)
                    548:                return(FALSE);
                    549: 
                    550:        _findclose(handle);
                    551: 
                    552:        if(f.attrib&_A_SUBDIR)
                    553:                return(FALSE);
                    554: 
                    555:        fname=getfname(path);   /* Find filename in path */
                    556:        strcpy(fname,f.name);   /* Correct filename */
                    557: 
                    558:        return(TRUE);
                    559: 
                    560: #else /* Unix or OS/2 */
                    561: 
                    562:        char globme[MAX_PATH*4+1];
                    563:        char fname[MAX_PATH+1];
                    564:        char tmp[5];
                    565:        char *p;
                    566:        int  i;
                    567:        glob_t  glb;
                    568:        
1.1.1.2 ! root      569:        if(path[0]==0)          /* work around glibc bug 574274 */
        !           570:                return FALSE;
        !           571: 
1.1       root      572:        if(!strchr(path,'*') && !strchr(path,'?') && fnameexist(path))
                    573:                return(TRUE);
                    574: 
                    575:        SAFECOPY(globme,path);
                    576:        p=getfname(globme);
                    577:        SAFECOPY(fname,p);
                    578:        *p=0;
                    579:        for(i=0;fname[i];i++)  {
                    580:                if(isalpha(fname[i]))
                    581:                        sprintf(tmp,"[%c%c]",toupper(fname[i]),tolower(fname[i]));
                    582:                else
                    583:                        sprintf(tmp,"%c",fname[i]);
                    584:                strncat(globme,tmp,MAX_PATH*4);
                    585:        }
                    586: #if 0
                    587:        if(strcspn(path,"?*")!=strlen(path))  {
                    588:                sprintf(path,"%.*s",MAX_PATH,globme);
                    589:                return(fexist(path));
                    590:        }
                    591: #endif
                    592: 
                    593:        if(glob(globme,GLOB_MARK,NULL,&glb) != 0)
                    594:                return(FALSE);
                    595:        
                    596:        if(glb.gl_pathc>0)  {
                    597:                for(i=0;i<glb.gl_pathc;i++)  {
                    598:                        if(*lastchar(glb.gl_pathv[i]) != '/')
                    599:                                break;
                    600:                }
                    601:                if(i<glb.gl_pathc)  {
                    602:                        sprintf(path,"%.*s",MAX_PATH,glb.gl_pathv[i]);
                    603:                        globfree(&glb);
                    604:                        return TRUE;
                    605:                }
                    606:        }
                    607: 
                    608:        globfree(&glb);
                    609:        return FALSE;
                    610:        
                    611: #endif
                    612: }
                    613: 
                    614: #if !defined(S_ISDIR)
                    615:        #define S_ISDIR(x)      ((x)&S_IFDIR)
                    616: #endif
                    617: 
                    618: /****************************************************************************/
                    619: /* Returns TRUE if the filename specified is a directory                                       */
                    620: /****************************************************************************/
                    621: BOOL DLLCALL isdir(const char *filename)
                    622: {
                    623:        char    path[MAX_PATH+1];
                    624:        char*   p;
                    625:        struct stat st;
                    626: 
                    627:        SAFECOPY(path,filename);
                    628: 
                    629:        p=lastchar(path);
                    630:        if(p!=path && IS_PATH_DELIM(*p)) {      /* chop off trailing slash */
                    631: #if !defined(__unix__)
                    632:                if(*(p-1)!=':')         /* Don't change C:\ to C: */
                    633: #endif
                    634:                        *p=0;
                    635:        }
                    636: 
                    637: #if defined(__BORLANDC__) && !defined(__unix__)        /* stat() doesn't work right */
                    638:        if(stat(path, &st)!=0 || strchr(path,'*')!=NULL || strchr(path,'?')!=NULL)
                    639: #else
                    640:        if(stat(path, &st)!=0)
                    641: #endif
                    642:                return(FALSE);
                    643: 
                    644:        return(S_ISDIR(st.st_mode) ? TRUE : FALSE);
                    645: }
                    646: 
                    647: /****************************************************************************/
                    648: /* Returns the attributes (mode) for specified 'filename'                                      */
                    649: /****************************************************************************/
                    650: int DLLCALL getfattr(const char* filename)
                    651: {
                    652: #if defined(_WIN32)
                    653:        long handle;
                    654:        struct _finddata_t      finddata;
                    655: 
                    656:        if((handle=_findfirst((char*)filename,&finddata))==-1) {
                    657:                errno=ENOENT;
                    658:                return(-1);
                    659:        }
                    660:        _findclose(handle);
                    661:        return(finddata.attrib);
                    662: #else
                    663:        struct stat st;
                    664: 
                    665:        if(stat(filename, &st)!=0) {
                    666:                errno=ENOENT;
                    667:                return(-1L);
                    668:        }
                    669: 
                    670:        return(st.st_mode);
                    671: #endif
                    672: }
                    673: 
                    674: #ifdef __unix__
1.1.1.2 ! root      675: int removecase(const char *path)
1.1       root      676: {
                    677:        char inpath[MAX_PATH+1];
                    678:        char fname[MAX_PATH*4+1];
                    679:        char tmp[5];
                    680:        char *p;
                    681:        int  i;
                    682: 
                    683:        if(strchr(path,'?') || strchr(path,'*'))
                    684:                return(-1);
                    685:        SAFECOPY(inpath,path);
                    686:        p=getfname(inpath);
                    687:        fname[0]=0;
                    688:        for(i=0;p[i];i++)  {
                    689:                if(isalpha(p[i]))
                    690:                        sprintf(tmp,"[%c%c]",toupper(p[i]),tolower(p[i]));
                    691:                else
                    692:                        sprintf(tmp,"%c",p[i]);
                    693:                strncat(fname,tmp,MAX_PATH*4);
                    694:        }
                    695:        *p=0;
                    696: 
                    697:        return(delfiles(inpath,fname)?-1:0);
                    698: }
                    699: #endif
                    700: 
                    701: /****************************************************************************/
                    702: /* Deletes all files in dir 'path' that match file spec 'spec'              */
                    703: /****************************************************************************/
1.1.1.2 ! root      704: ulong DLLCALL delfiles(const char *inpath, const char *spec)
1.1       root      705: {
                    706:        char    path[MAX_PATH+1];
                    707:        char    lastch;
                    708:     uint       i,files=0;
                    709:        glob_t  g;
                    710: 
                    711:        lastch=*lastchar(inpath);
                    712:        if(!IS_PATH_DELIM(lastch) && lastch)
                    713:                sprintf(path,"%s%c",inpath,PATH_DELIM);
                    714:        else
                    715:                strcpy(path,inpath);
                    716:        strcat(path,spec);
                    717:        glob(path,0,NULL,&g);
                    718:        for(i=0;i<g.gl_pathc;i++) {
                    719:                if(isdir(g.gl_pathv[i]))
                    720:                        continue;
                    721:                CHMOD(g.gl_pathv[i],S_IWRITE);  /* Incase it's been marked RDONLY */
                    722:                if(remove(g.gl_pathv[i])==0)
                    723:                        files++;
                    724:        }
                    725:        globfree(&g);
                    726:        return(files);
                    727: }
                    728: 
                    729: /****************************************************************************/
                    730: /* Return free disk space in bytes (up to a maximum of 4GB)                                    */
                    731: /****************************************************************************/
                    732: #if defined(_WIN32)
                    733: typedef BOOL(WINAPI * GetDiskFreeSpaceEx_t)
                    734:        (LPCTSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER); 
                    735: 
                    736: static int bit_num(ulong val)
                    737: {
                    738:        int i;
                    739: 
                    740:        for(i=31;i>=0;i--)
                    741:                if(val&(1<<i))
                    742:                        return(i);
                    743: 
                    744:        return(-1);
                    745: }
                    746: #endif
                    747: 
                    748: /* Unit should be a power-of-2 (e.g. 1024 to report kilobytes) or 1 (to report bytes) */
                    749: static ulong getdiskspace(const char* path, ulong unit, BOOL freespace)
                    750: {
                    751: #if defined(_WIN32)
                    752:        char                    root[16];
                    753:        DWORD                   TotalNumberOfClusters;
                    754:        DWORD                   NumberOfFreeClusters;
                    755:        DWORD                   BytesPerSector;
                    756:        DWORD                   SectorsPerCluster;
                    757:        ULARGE_INTEGER  avail;
                    758:        ULARGE_INTEGER  size;
                    759:        static HINSTANCE hK32;
                    760:        GetDiskFreeSpaceEx_t GetDiskFreeSpaceEx;
                    761: 
                    762:        if(hK32 == NULL)
                    763:                hK32 = LoadLibrary("KERNEL32");
                    764:        GetDiskFreeSpaceEx 
                    765:                = (GetDiskFreeSpaceEx_t)GetProcAddress(hK32,"GetDiskFreeSpaceExA");
                    766:  
                    767:        if (GetDiskFreeSpaceEx!=NULL) { /* Windows 95-OSR2 or later */
                    768:                if(!GetDiskFreeSpaceEx(
                    769:                        path,           /* pointer to the directory name */
                    770:                        &avail,         /* receives the number of bytes on disk avail to the caller */
                    771:                        &size,          /* receives the number of bytes on disk */
                    772:                        NULL))          /* receives the free bytes on disk */
                    773:                        return(0);
                    774: 
                    775:                if(freespace)
                    776:                        size=avail;
                    777: 
                    778:                if(unit>1)
                    779:                        size.QuadPart=Int64ShrlMod32(size.QuadPart,bit_num(unit));
                    780: 
                    781: #if defined(_ANONYMOUS_STRUCT)
                    782:                if(size.HighPart)
                    783: #else
                    784:                if(size.u.HighPart)
                    785: #endif
                    786:                        return(0xffffffff);     /* 4GB max */
                    787: 
                    788: #if defined(_ANONYMOUS_STRUCT)
                    789:                return(size.LowPart);
                    790: #else
                    791:                return(size.u.LowPart);
                    792: #endif
                    793:        }
                    794: 
                    795:        /* Windows 95 (old way), limited to 2GB */
                    796:        sprintf(root,"%.3s",path);
                    797:        if(!GetDiskFreeSpace(
                    798:                root,                                   /* pointer to root path */
                    799:                &SectorsPerCluster,             /* pointer to sectors per cluster */
                    800:                &BytesPerSector,                /* pointer to bytes per sector */
                    801:                &NumberOfFreeClusters,  /* pointer to number of free clusters */
                    802:                &TotalNumberOfClusters  /* pointer to total number of clusters */
                    803:                ))
                    804:                return(0);
                    805: 
                    806:        if(freespace)
                    807:                TotalNumberOfClusters = NumberOfFreeClusters;
                    808:        if(unit>1)
                    809:                TotalNumberOfClusters/=unit;
                    810:        return(TotalNumberOfClusters*SectorsPerCluster*BytesPerSector);
                    811: 
                    812: 
                    813: #elif defined(__solaris__) || (defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000 /* NetBSD 3.0 */))
                    814: 
                    815:        struct statvfs fs;
                    816:        unsigned long blocks;
                    817: 
                    818:     if (statvfs(path, &fs) < 0)
                    819:        return 0;
                    820: 
                    821:        if(freespace)
                    822:                blocks=fs.f_bavail;
                    823:        else
                    824:                blocks=fs.f_blocks;
                    825: 
                    826:        if(unit>1)
                    827:                blocks/=unit;
                    828:     return fs.f_bsize * blocks;
                    829:     
                    830: /* statfs is also used under FreeBSD (Though it *supports* statvfs() now too) */
                    831: #elif defined(__GLIBC__) || defined(BSD)
                    832: 
                    833:        struct statfs fs;
                    834:        unsigned long blocks;
                    835: 
                    836:     if (statfs(path, &fs) < 0)
                    837:        return 0;
                    838: 
                    839:        if(freespace)
                    840:                blocks=fs.f_bavail;
                    841:        else
                    842:                blocks=fs.f_blocks;
                    843: 
                    844:        if(unit>1)
                    845:                blocks/=unit;
                    846:     return fs.f_bsize * blocks;
                    847:     
                    848: #else
                    849: 
                    850:        fprintf(stderr,"\n*** !Missing getfreediskspace implementation ***\n");
                    851:        return(0);
                    852: 
                    853: #endif
                    854: }
                    855: 
                    856: ulong DLLCALL getfreediskspace(const char* path, ulong unit)
                    857: {
                    858:        return getdiskspace(path, unit, /* freespace? */TRUE);
                    859: }
                    860: 
                    861: ulong DLLCALL getdisksize(const char* path, ulong unit)
                    862: {
                    863:        return getdiskspace(path, unit, /* freespace? */FALSE);
                    864: }
                    865: 
                    866: /****************************************************************************/
                    867: /* Resolves //, /./, and /../ in a path. Should work indetically to Windows */
                    868: /****************************************************************************/
                    869: #if defined(__unix__)
                    870: char * DLLCALL _fullpath(char *target, const char *path, size_t size)  {
                    871:        char    *out;
                    872:        char    *p;
                    873: 
                    874:        if(target==NULL)  {
                    875:                if((target=malloc(MAX_PATH+1))==NULL) {
                    876:                        return(NULL);
                    877:                }
                    878:        }
                    879:        out=target;
                    880:        *out=0;
                    881: 
                    882:        if(*path != '/')  {
                    883:                if(*path == '~') {
                    884:                        p=getenv("HOME");
                    885:                        if(p==NULL || strlen(p)+strlen(path)>=size)
                    886:                                return(NULL);
                    887:                        strcpy(target,p);
                    888:                        out=strrchr(target,'\0');
                    889:                        path++;
                    890:                }
                    891:                else {
                    892:                        p=getcwd(NULL,size);
                    893:                        if(p==NULL || strlen(p)+strlen(path)>=size)
                    894:                                return(NULL);
                    895:                        strcpy(target,p);
                    896:                        free(p);
                    897:                        out=strrchr(target,'\0');
                    898:                        *(out++)='/';
                    899:                        *out=0;
                    900:                        out--;
                    901:                }
                    902:        }
                    903:        strncat(target,path,size-1);
                    904:        
                    905: /*     if(stat(target,&sb))
                    906:                return(NULL);
                    907:        if(sb.st_mode&S_IFDIR)
                    908:                strcat(target,"/"); */
                    909: 
                    910:        for(;*out;out++)  {
                    911:                while(*out=='/')  {
                    912:                        if(*(out+1)=='/')
                    913:                                memmove(out,out+1,strlen(out));
                    914:                        else if(*(out+1)=='.' && (*(out+2)=='/' || *(out+2)==0))
                    915:                                memmove(out,out+2,strlen(out)-1);
                    916:                        else if(*(out+1)=='.' && *(out+2)=='.' && (*(out+3)=='/' || *(out+3)==0))  {
                    917:                                *out=0;
                    918:                                p=strrchr(target,'/');
                    919:                                if(p==NULL)
                    920:                                        p=target;
                    921:                                memmove(p,out+3,strlen(out+3)+1);
                    922:                                out=p;
                    923:                        }
                    924:                        else  {
                    925:                                out++;
                    926:                        }
                    927:                }
                    928:        }
                    929:        return(target);
                    930: }
                    931: #endif
                    932: 
                    933: /****************************************************************************/
                    934: /* Adds a trailing slash/backslash (path delimiter) on path strings            */
                    935: /****************************************************************************/
                    936: char* DLLCALL backslash(char* path)
                    937: {
                    938:        char* p;
                    939: 
                    940:        p=lastchar(path);
                    941: 
                    942:        if(*p && !IS_PATH_DELIM(*p)) {
                    943: #if defined(__unix__)
                    944:                /* Convert trailing backslash to forwardslash on *nix */
                    945:                if(*p!='\\')
                    946: #endif
                    947:                        p++;
                    948:                *p=PATH_DELIM;
                    949:                *(++p)=0;
                    950:        }
                    951:        return(path);
                    952: }
                    953: 
                    954: /****************************************************************************/
                    955: /* Returns true if the specified filename an aboslute pathname                         */
                    956: /****************************************************************************/
                    957: BOOL DLLCALL isabspath(const char *filename)
                    958: {
                    959:        char path[MAX_PATH+1];
                    960: 
                    961:        return(stricmp(filename,FULLPATH(path,filename,sizeof(path)))==0);
                    962: }
                    963: 
                    964: /****************************************************************************/
                    965: /* Returns true if the specified filename is a full ("rooted") path                    */
                    966: /****************************************************************************/
                    967: BOOL DLLCALL isfullpath(const char* filename)
                    968: {
                    969:        return(filename[0]=='/' 
                    970: #ifdef WIN32
                    971:                || filename[0]=='\\' || filename[1]==':'
                    972: #endif
                    973:                );
                    974: }
                    975: 
                    976: /****************************************************************************/
                    977: /* Matches file name against filespec                                                                          */
                    978: /* Optionally not allowing * to match PATH_DELIM (for paths)                           */
                    979: /****************************************************************************/
1.1.1.2 ! root      980: 
1.1       root      981: BOOL DLLCALL wildmatch(const char *fname, const char *spec, BOOL path)
                    982: {
                    983:        char *specp;
                    984:        char *fnamep;
1.1.1.2 ! root      985:        char *wildend;
1.1       root      986: 
                    987:        specp=(char *)spec;
                    988:        fnamep=(char *)fname;
                    989:        for(;;specp++, fnamep++) {
                    990:                switch(*specp) {
                    991:                        case '?':
                    992:                                if(!(*fnamep))
                    993:                                        return(FALSE);
                    994:                                break;
                    995:                        case 0:
                    996:                                if(!*fnamep)
                    997:                                        return(TRUE);
                    998:                                break;
                    999:                        case '*':
                   1000:                                while(*specp=='*')
                   1001:                                        specp++;
1.1.1.2 ! root     1002:                                if(path) {
        !          1003:                                        for(wildend=fnamep; *wildend; wildend++) {
        !          1004:                                                if(IS_PATH_DELIM(*wildend)) {
        !          1005:                                                        wildend--;
        !          1006:                                                        break;
        !          1007:                                                }
        !          1008:                                        }
        !          1009:                                }
        !          1010:                                else
        !          1011:                                        wildend=strchr(fnamep, 0);
        !          1012:                                for(;wildend >= fnamep;wildend--) {
        !          1013:                                        if(wildmatch(wildend, specp, path))
        !          1014:                                                return(TRUE);
1.1       root     1015:                                }
1.1.1.2 ! root     1016:                                return(FALSE);
1.1       root     1017:                        default:
                   1018:                                if(*specp != *fnamep)
                   1019:                                        return(FALSE);
                   1020:                }
                   1021:                if(!(*specp && *fnamep))
                   1022:                        break;
                   1023:        }
                   1024:        while(*specp=='*')
                   1025:                specp++;
                   1026:        if(*specp==*fnamep)
                   1027:                return(TRUE);
                   1028:        return(FALSE);
                   1029: }
                   1030: 
                   1031: /****************************************************************************/
                   1032: /* Matches file name against filespec, ignoring case                                           */
                   1033: /****************************************************************************/
                   1034: BOOL DLLCALL wildmatchi(const char *fname, const char *spec, BOOL path)
                   1035: {
                   1036:        char* s1;
                   1037:        char* s2;
                   1038:        BOOL result;
                   1039: 
                   1040:        if((s1=strdup(fname))==NULL)
                   1041:                return(FALSE);
                   1042:        if((s2=strdup(spec))==NULL) {
                   1043:                free(s1);
                   1044:                return(FALSE);
                   1045:        }
                   1046:        strupr(s1);
                   1047:        strupr(s2);
                   1048:        result = wildmatch(s1, s2, path);
                   1049:        free(s1);
                   1050:        free(s2);
                   1051:        return(result);
                   1052: }
                   1053: 
                   1054: /****************************************************************************/
                   1055: /* Creates all the necessary directories in the specified path                         */
                   1056: /****************************************************************************/
1.1.1.2 ! root     1057: int DLLCALL mkpath(const char* path)
1.1       root     1058: {
                   1059:        const char*     p=path;
                   1060:        const char*     tp;
                   1061:        const char*     sep=
                   1062: #ifdef _WIN32
                   1063:                "\\"
                   1064: #endif
                   1065:                "/";
                   1066:        char    dir[MAX_PATH+1];
                   1067:        int             result=0;
                   1068: 
                   1069: #ifdef _WIN32
                   1070:        if(p[1]==':')   /* Skip drive letter, if specified */
                   1071:                p+=2;
                   1072: #endif
                   1073: 
                   1074:        while(*p) {
                   1075:                SKIP_CHARSET(p,sep);
                   1076:                if(*p==0)
                   1077:                        break;
                   1078:                tp=p;
                   1079:                FIND_CHARSET(tp,sep);
                   1080:                safe_snprintf(dir,sizeof(dir),"%.*s",tp-path, path);
                   1081:                if(!isdir(dir)) {
                   1082:                        if((result=MKDIR(dir))!=0)
                   1083:                                break;
                   1084:                }
                   1085:                p=tp;
                   1086:        }
                   1087: 
                   1088:        return(result);
                   1089: }

unix.superglobalmegacorp.com

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