Annotation of sbbs/xpdev/dirwrap.c, revision 1.1.1.1

1.1       root        1: /* dirwrap.c */
                      2: 
                      3: /* Directory-related system-call wrappers */
                      4: 
                      5: /* $Id: dirwrap.c,v 1.42 2004/10/28 22:00:56 rswindell 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 2004 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:        #if defined(__FreeBSD__)
                     55:                #include <sys/kbio.h>
                     56:        #endif
                     57:        #endif
                     58: 
                     59:        #include <sys/ioctl.h>  /* ioctl */
                     60: 
                     61:        #if defined(__GLIBC__)          /* actually, BSD, but will work for now */
                     62:                #include <sys/vfs.h>    /* statfs() */
                     63:        #endif
                     64: 
                     65:        #if defined(__solaris__)
                     66:                #include <sys/statvfs.h>
                     67:        #endif
                     68: 
                     69: #endif /* __unix__ */
                     70: 
                     71: #if defined(__WATCOMC__)
                     72:        #include <dos.h>
                     73: #endif
                     74:        
                     75: #include <sys/types.h> /* _dev_t */
                     76: #include <sys/stat.h>  /* struct stat */
                     77: 
                     78: #include <stdio.h>             /* sprintf */
                     79: #include <stdlib.h>            /* rand */
                     80: #include <errno.h>             /* ENOENT definitions */
                     81: 
                     82: #include "genwrap.h"   /* strupr/strlwr */
                     83: #include "dirwrap.h"   /* DLLCALL */
                     84: 
                     85: /****************************************************************************/
                     86: /* Return the filename portion of a full pathname                                                      */
                     87: /****************************************************************************/
                     88: char* DLLCALL getfname(const char* path)
                     89: {
                     90:        const char* fname;
                     91:        const char* bslash;
                     92: 
                     93:        fname=strrchr(path,'/');
                     94:        bslash=strrchr(path,'\\');
                     95:        if(bslash>fname)
                     96:                fname=bslash;
                     97:        if(fname!=NULL) 
                     98:                fname++;
                     99:        else 
                    100:                fname=(char*)path;
                    101:        return((char*)fname);
                    102: }
                    103: 
                    104: /****************************************************************************/
                    105: /* Return a pointer to a file's extesion (beginning with '.')                          */
                    106: /****************************************************************************/
                    107: char* DLLCALL getfext(const char* path)
                    108: {
                    109:        char *fname;
                    110:        char *fext;
                    111: 
                    112:        fname=getfname(path);
                    113:        fext=strrchr(fname,'.');
                    114:        if(fext==NULL || fext==fname) 
                    115:                return(NULL);
                    116:        return(fext);
                    117: }
                    118: 
                    119: /****************************************************************************/
                    120: /* Break a path name into components.                                                                          */
                    121: /****************************************************************************/
                    122: #if defined(__unix__)
                    123: void DLLCALL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
                    124: {
                    125:        char*   p;
                    126: 
                    127:        ext[0]=0;
                    128:        drive[0]=0;                     /* no drive letters on Unix */
                    129: 
                    130:        strcpy(dir,path);       /* Optional directory path, including trailing slash. */
                    131:        p=getfname(dir);
                    132:        strcpy(fname,p);        /* Base filename (no extension) */
                    133:        if(p==dir)
                    134:                dir[0]=0;               /* no directory specified in path */
                    135:        else
                    136:                *p=0;                   /* truncate dir at filename */
                    137:        p=getfext(fname);
                    138:        if(p!=NULL) {
                    139:                strcpy(ext,p);  /* Optional filename extension, including leading period (.) */
                    140:                *p=0;
                    141:        }
                    142: }
                    143: #endif
                    144: 
                    145: /****************************************************************************/
                    146: /* Win32 (minimal) implementation of POSIX.2 glob() function                           */
                    147: /* This code _may_ work on other DOS-based platforms (e.g. OS/2)                       */
                    148: /****************************************************************************/
                    149: #if !defined(__unix__)
                    150: static int glob_compare( const void *arg1, const void *arg2 )
                    151: {
                    152:    /* Compare all of both strings: */
                    153:    return stricmp( * ( char** ) arg1, * ( char** ) arg2 );
                    154: }
                    155: 
                    156: #if defined(__BORLANDC__)
                    157:        #pragma argsused
                    158: #endif
                    159: 
                    160: #if defined(__WATCOMC__)
                    161: 
                    162: int    DLLCALL glob(const char *pattern, int flags, void* unused, glob_t* glob)
                    163: {
                    164:     struct     find_t ff;
                    165:        size_t  found=0;
                    166:        char    path[MAX_PATH+1];
                    167:        char*   p;
                    168:        char**  new_pathv;
                    169: 
                    170:        if(!(flags&GLOB_APPEND)) {
                    171:                glob->gl_pathc=0;
                    172:                glob->gl_pathv=NULL;
                    173:        }
                    174: 
                    175:        if(_dos_findfirst((char*)pattern,_A_NORMAL,&ff)!=0)
                    176:                return(GLOB_NOMATCH);
                    177: 
                    178:        do {
                    179:                if((flags&GLOB_PERIOD || ff.name[0]!='.') &&
                    180:                        (!(flags&GLOB_ONLYDIR) || ff.attrib&_A_SUBDIR)) {
                    181:                        if((new_pathv=realloc(glob->gl_pathv
                    182:                                ,(glob->gl_pathc+1)*sizeof(char*)))==NULL) {
                    183:                                globfree(glob);
                    184:                                return(GLOB_NOSPACE);
                    185:                        }
                    186:                        glob->gl_pathv=new_pathv;
                    187: 
                    188:                        /* build the full pathname */
                    189:                        SAFECOPY(path,pattern);
                    190:                        p=getfname(path);
                    191:                        *p=0;
                    192:                        strcat(path,ff.name);
                    193: 
                    194:                        if((glob->gl_pathv[glob->gl_pathc]=malloc(strlen(path)+2))==NULL) {
                    195:                                globfree(glob);
                    196:                                return(GLOB_NOSPACE);
                    197:                        }
                    198:                        strcpy(glob->gl_pathv[glob->gl_pathc],path);
                    199:                        if(flags&GLOB_MARK && ff.attrib&_A_SUBDIR)
                    200:                                strcat(glob->gl_pathv[glob->gl_pathc],"/");
                    201: 
                    202:                        glob->gl_pathc++;
                    203:                        found++;
                    204:                }
                    205:        } while(_dos_findnext(&ff)==0);
                    206:        _dos_findclose(&ff);
                    207: 
                    208:        if(found==0)
                    209:                return(GLOB_NOMATCH);
                    210: 
                    211:        if(!(flags&GLOB_NOSORT)) {
                    212:                qsort(glob->gl_pathv,found,sizeof(char*),glob_compare);
                    213:        }
                    214: 
                    215:        return(0);      /* success */
                    216: }
                    217: 
                    218: #else
                    219: 
                    220: int    DLLCALL glob(const char *pattern, int flags, void* unused, glob_t* glob)
                    221: {
                    222:     struct     _finddata_t ff;
                    223:        long    ff_handle;
                    224:        size_t  found=0;
                    225:        char    path[MAX_PATH+1];
                    226:        char*   p;
                    227:        char**  new_pathv;
                    228: 
                    229:        if(!(flags&GLOB_APPEND)) {
                    230:                glob->gl_pathc=0;
                    231:                glob->gl_pathv=NULL;
                    232:        }
                    233: 
                    234:        ff_handle=_findfirst((char*)pattern,&ff);
                    235:        while(ff_handle!=-1) {
                    236:                if((flags&GLOB_PERIOD || ff.name[0]!='.') &&
                    237:                        (!(flags&GLOB_ONLYDIR) || ff.attrib&_A_SUBDIR)) {
                    238:                        if((new_pathv=(char**)realloc(glob->gl_pathv
                    239:                                ,(glob->gl_pathc+1)*sizeof(char*)))==NULL) {
                    240:                                globfree(glob);
                    241:                                return(GLOB_NOSPACE);
                    242:                        }
                    243:                        glob->gl_pathv=new_pathv;
                    244: 
                    245:                        /* build the full pathname */
                    246:                        SAFECOPY(path,pattern);
                    247:                        p=getfname(path);
                    248:                        *p=0;
                    249:                        strcat(path,ff.name);
                    250: 
                    251:                        if((glob->gl_pathv[glob->gl_pathc]=(char*)malloc(strlen(path)+2))==NULL) {
                    252:                                globfree(glob);
                    253:                                return(GLOB_NOSPACE);
                    254:                        }
                    255:                        strcpy(glob->gl_pathv[glob->gl_pathc],path);
                    256:                        if(flags&GLOB_MARK && ff.attrib&_A_SUBDIR)
                    257:                                strcat(glob->gl_pathv[glob->gl_pathc],"/");
                    258: 
                    259:                        glob->gl_pathc++;
                    260:                        found++;
                    261:                }
                    262:                if(_findnext(ff_handle, &ff)!=0) {
                    263:                        _findclose(ff_handle);
                    264:                        ff_handle=-1; 
                    265:                } 
                    266:        }
                    267: 
                    268:        if(found==0)
                    269:                return(GLOB_NOMATCH);
                    270: 
                    271:        if(!(flags&GLOB_NOSORT)) {
                    272:                qsort(glob->gl_pathv,found,sizeof(char*),glob_compare);
                    273:        }
                    274: 
                    275:        return(0);      /* success */
                    276: }
                    277: 
                    278: #endif
                    279: 
                    280: void DLLCALL globfree(glob_t* glob)
                    281: {
                    282:        size_t i;
                    283: 
                    284:        if(glob==NULL)
                    285:                return;
                    286: 
                    287:        if(glob->gl_pathv!=NULL) {
                    288:                for(i=0;i<glob->gl_pathc;i++)
                    289:                        if(glob->gl_pathv[i]!=NULL)
                    290:                                free(glob->gl_pathv[i]);
                    291: 
                    292:                free(glob->gl_pathv);
                    293:                glob->gl_pathv=NULL;
                    294:        }
                    295:        glob->gl_pathc=0;
                    296: }
                    297: 
                    298: #endif /* !defined(__unix__) */
                    299: 
                    300: /****************************************************************************/
                    301: /* POSIX directory operations using Microsoft _findfirst/next API.                     */
                    302: /****************************************************************************/
                    303: #if defined(_MSC_VER) || defined(__DMC__)
                    304: DIR* opendir(const char* dirname)
                    305: {
                    306:        DIR*    dir;
                    307: 
                    308:        if((dir=(DIR*)calloc(1,sizeof(DIR)))==NULL) {
                    309:                errno=ENOMEM;
                    310:                return(NULL);
                    311:        }
                    312:        sprintf(dir->filespec,"%.*s",sizeof(dir->filespec)-5,dirname);
                    313:        if(*dir->filespec && dir->filespec[strlen(dir->filespec)-1]!='\\')
                    314:                strcat(dir->filespec,"\\");
                    315:        strcat(dir->filespec,"*.*");
                    316:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
                    317:        if(dir->handle==-1) {
                    318:                errno=ENOENT;
                    319:                free(dir);
                    320:                return(NULL);
                    321:        }
                    322:        return(dir);
                    323: }
                    324: struct dirent* readdir(DIR* dir)
                    325: {
                    326:        if(dir==NULL)
                    327:                return(NULL);
                    328:        if(dir->end==TRUE)
                    329:                return(NULL);
                    330:        if(dir->handle==-1)
                    331:                return(NULL);
                    332:        sprintf(dir->dirent.d_name,"%.*s",sizeof(struct dirent)-1,dir->finddata.name);
                    333:        if(_findnext(dir->handle,&dir->finddata)!=0)
                    334:                dir->end=TRUE;
                    335:        return(&dir->dirent);
                    336: }
                    337: int closedir (DIR* dir)
                    338: {
                    339:        if(dir==NULL)
                    340:                return(-1);
                    341:        _findclose(dir->handle);
                    342:        free(dir);
                    343:        return(0);
                    344: }
                    345: void rewinddir(DIR* dir)
                    346: {
                    347:        if(dir==NULL)
                    348:                return;
                    349:        _findclose(dir->handle);
                    350:        dir->end=FALSE;
                    351:        dir->handle=_findfirst(dir->filespec,&dir->finddata);
                    352: }
                    353: #endif /* defined(_MSC_VER) */
                    354: 
                    355: /****************************************************************************/
                    356: /* Returns the time/date of the file in 'filename' in time_t (unix) format  */
                    357: /****************************************************************************/
                    358: time_t DLLCALL fdate(const char* filename)
                    359: {
                    360:        struct stat st;
                    361: 
                    362:        if(access(filename,0)==-1)
                    363:                return(-1);
                    364: 
                    365:        if(stat(filename, &st)!=0)
                    366:                return(-1);
                    367: 
                    368:        return(st.st_mtime);
                    369: }
                    370: 
                    371: /****************************************************************************/
                    372: /* Change the access and modification times for specified filename                     */
                    373: /****************************************************************************/
                    374: int DLLCALL setfdate(const char* filename, time_t t)
                    375: {
                    376:        struct utimbuf ut;
                    377: 
                    378:        memset(&ut,0,sizeof(ut));
                    379: 
                    380:        ut.actime=t;
                    381:        ut.modtime=t;
                    382: 
                    383:        return(utime(filename,&ut));
                    384: }
                    385: 
                    386: /****************************************************************************/
                    387: /* Returns the length of the file in 'filename'                             */
                    388: /****************************************************************************/
                    389: long DLLCALL flength(const char *filename)
                    390: {
                    391: #if defined(__BORLANDC__) && !defined(__unix__)        /* stat() doesn't work right */
                    392: 
                    393:        long    handle;
                    394:        struct _finddata_t f;
                    395: 
                    396:        if(access((char*)filename,0)==-1)
                    397:                return(-1L);
                    398: 
                    399:        if((handle=_findfirst((char*)filename,&f))==-1)
                    400:                return(-1);
                    401: 
                    402:        _findclose(handle);
                    403: 
                    404:        return(f.size);
                    405: 
                    406: #else 
                    407: 
                    408:        struct stat st;
                    409: 
                    410:        if(access(filename,0)==-1)
                    411:                return(-1L);
                    412: 
                    413:        if(stat(filename, &st)!=0)
                    414:                return(-1L);
                    415: 
                    416:        return(st.st_size);
                    417: 
                    418: #endif
                    419: }
                    420: 
                    421: /****************************************************************************/
                    422: /* Checks the file system for the existence of one or more files.                      */
                    423: /* Returns TRUE if it exists, FALSE if it doesn't.                          */
                    424: /* 'filespec' may contain wildcards!                                                                           */
                    425: /****************************************************************************/
                    426: BOOL DLLCALL fexist(const char *filespec)
                    427: {
                    428: #if defined(_WIN32)
                    429: 
                    430:        long    handle;
                    431:        struct _finddata_t f;
                    432: 
                    433:        if(access(filespec,0)==-1 && !strchr(filespec,'*') && !strchr(filespec,'?'))
                    434:                return(FALSE);
                    435: 
                    436:        if((handle=_findfirst((char*)filespec,&f))==-1)
                    437:                return(FALSE);
                    438: 
                    439:        _findclose(handle);
                    440: 
                    441:        if(f.attrib&_A_SUBDIR)
                    442:                return(FALSE);
                    443: 
                    444:        return(TRUE);
                    445: 
                    446: #else /* Unix or OS/2 */
                    447:        
                    448:        /* portion by cmartin */
                    449: 
                    450:        glob_t g;
                    451:     int c;
                    452: 
                    453:        if(access(filespec,0)==-1 && !strchr(filespec,'*') && !strchr(filespec,'?'))
                    454:                return(FALSE);
                    455: 
                    456:     // start the search
                    457:     glob(filespec, GLOB_MARK | GLOB_NOSORT, NULL, &g);
                    458: 
                    459:     if (!g.gl_pathc) {
                    460:            // no results
                    461:        globfree(&g);
                    462:        return FALSE;
                    463:     }
                    464: 
                    465:     // make sure it's not a directory
                    466:        c = g.gl_pathc;
                    467:     while (c--) {
                    468:        if (*lastchar(g.gl_pathv[c]) != '/') {
                    469:                globfree(&g);
                    470:             return TRUE;
                    471:         }
                    472:     }
                    473:         
                    474:     globfree(&g);
                    475:     return FALSE;
                    476: 
                    477: #endif
                    478: }
                    479: 
                    480: /****************************************************************************/
                    481: /* Fixes upper/lowercase filename for Unix file systems                                                */
                    482: /****************************************************************************/
                    483: BOOL DLLCALL fexistcase(char *path)
                    484: {
                    485: #if defined(_WIN32)
                    486: 
                    487:        char*   fname;
                    488:        long    handle;
                    489:        struct _finddata_t f;
                    490: 
                    491:        if(access(path,0)==-1 && !strchr(path,'*') && !strchr(path,'?'))
                    492:                return(FALSE);
                    493: 
                    494:        if((handle=_findfirst((char*)path,&f))==-1)
                    495:                return(FALSE);
                    496: 
                    497:        _findclose(handle);
                    498: 
                    499:        if(f.attrib&_A_SUBDIR)
                    500:                return(FALSE);
                    501: 
                    502:        fname=getfname(path);   /* Find filename in path */
                    503:        strcpy(fname,f.name);   /* Correct filename */
                    504: 
                    505:        return(TRUE);
                    506: 
                    507: #else /* Unix or OS/2 */
                    508: 
                    509:        char globme[MAX_PATH*4+1];
                    510:        char fname[MAX_PATH+1];
                    511:        char tmp[5];
                    512:        char *p;
                    513:        int  i;
                    514:        glob_t  glb;
                    515:        
                    516:        SAFECOPY(globme,path);
                    517:        p=getfname(globme);
                    518:        SAFECOPY(fname,p);
                    519:        *p=0;
                    520:        for(i=0;fname[i];i++)  {
                    521:                if(isalpha(fname[i]))
                    522:                        sprintf(tmp,"[%c%c]",toupper(fname[i]),tolower(fname[i]));
                    523:                else
                    524:                        sprintf(tmp,"%c",fname[i]);
                    525:                strncat(globme,tmp,MAX_PATH*4);
                    526:        }
                    527:        if(strcspn(path,"?*")!=strlen(path))  {
                    528:                sprintf(path,"%.*s",MAX_PATH,globme);
                    529:                return(fexist(path));
                    530:        }
                    531: 
                    532:        if(glob(globme,GLOB_MARK,NULL,&glb) != 0)
                    533:                return(FALSE);
                    534:        
                    535:        if(glb.gl_pathc>0)  {
                    536:                for(i=0;i<glb.gl_pathc;i++)  {
                    537:                        if(*lastchar(glb.gl_pathv[i]) != '/')
                    538:                                break;
                    539:                }
                    540:                if(i<glb.gl_pathc)  {
                    541:                        sprintf(path,"%.*s",MAX_PATH,glb.gl_pathv[i]);
                    542:                        globfree(&glb);
                    543:                        return TRUE;
                    544:                }
                    545:        }
                    546: 
                    547:        globfree(&glb);
                    548:        return FALSE;
                    549:        
                    550: #endif
                    551: }
                    552: 
                    553: #if !defined(S_ISDIR)
                    554:        #define S_ISDIR(x)      ((x)&S_IFDIR)
                    555: #endif
                    556: 
                    557: /****************************************************************************/
                    558: /* Returns TRUE if the filename specified is a directory                                       */
                    559: /****************************************************************************/
                    560: BOOL DLLCALL isdir(const char *filename)
                    561: {
                    562:        char    path[MAX_PATH+1];
                    563:        char*   p;
                    564:        struct stat st;
                    565: 
                    566:        SAFECOPY(path,filename);
                    567: 
                    568:        p=lastchar(path);
                    569:        if(p!=path && IS_PATH_DELIM(*p)) {      /* chop off trailing slash */
                    570: #if !defined(__unix__)
                    571:                if(*(p-1)!=':')         /* Don't change C:\ to C: */
                    572: #endif
                    573:                        *p=0;
                    574:        }
                    575: 
                    576:        if(stat(path, &st)!=0)
                    577:                return(FALSE);
                    578: 
                    579:        return(S_ISDIR(st.st_mode) ? TRUE : FALSE);
                    580: }
                    581: 
                    582: /****************************************************************************/
                    583: /* Returns the attributes (mode) for specified 'filename'                                      */
                    584: /****************************************************************************/
                    585: int DLLCALL getfattr(const char* filename)
                    586: {
                    587: #if defined(_WIN32)
                    588:        long handle;
                    589:        struct _finddata_t      finddata;
                    590: 
                    591:        if((handle=_findfirst((char*)filename,&finddata))==-1) {
                    592:                errno=ENOENT;
                    593:                return(-1);
                    594:        }
                    595:        _findclose(handle);
                    596:        return(finddata.attrib);
                    597: #else
                    598:        struct stat st;
                    599: 
                    600:        if(stat(filename, &st)!=0) {
                    601:                errno=ENOENT;
                    602:                return(-1L);
                    603:        }
                    604: 
                    605:        return(st.st_mode);
                    606: #endif
                    607: }
                    608: 
                    609: /****************************************************************************/
                    610: /* Deletes all files in dir 'path' that match file spec 'spec'              */
                    611: /****************************************************************************/
                    612: ulong DLLCALL delfiles(char *inpath, char *spec)
                    613: {
                    614:        char    path[MAX_PATH+1];
                    615:        char    lastch;
                    616:     uint       i,files=0;
                    617:        glob_t  g;
                    618: 
                    619:        lastch=*lastchar(inpath);
                    620:        if(!IS_PATH_DELIM(lastch))
                    621:                sprintf(path,"%s%c",inpath,PATH_DELIM);
                    622:        else
                    623:                strcpy(path,inpath);
                    624:        strcat(path,spec);
                    625:        glob(path,0,NULL,&g);
                    626:        for(i=0;i<g.gl_pathc;i++) {
                    627:                if(isdir(g.gl_pathv[i]))
                    628:                        continue;
                    629:                CHMOD(g.gl_pathv[i],S_IWRITE);  // Incase it's been marked RDONLY
                    630:                if(remove(g.gl_pathv[i])==0)
                    631:                        files++;
                    632:        }
                    633:        globfree(&g);
                    634:        return(files);
                    635: }
                    636: 
                    637: /****************************************************************************/
                    638: /* Return free disk space in bytes (up to a maximum of 4GB)                                    */
                    639: /****************************************************************************/
                    640: #if defined(_WIN32)
                    641: typedef BOOL(WINAPI * GetDiskFreeSpaceEx_t)
                    642:        (LPCTSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER); 
                    643: 
                    644: static int bit_num(ulong val)
                    645: {
                    646:        int i;
                    647: 
                    648:        for(i=31;i>=0;i--)
                    649:                if(val&(1<<i))
                    650:                        return(i);
                    651: 
                    652:        return(-1);
                    653: }
                    654: #endif
                    655: 
                    656: /* Unit should be a power-of-2 (e.g. 1024 to report kilobytes) */
                    657: ulong DLLCALL getfreediskspace(const char* path, ulong unit)
                    658: {
                    659: #if defined(_WIN32)
                    660:        char                    root[16];
                    661:        DWORD                   TotalNumberOfClusters;
                    662:        DWORD                   NumberOfFreeClusters;
                    663:        DWORD                   BytesPerSector;
                    664:        DWORD                   SectorsPerCluster;
                    665:        ULARGE_INTEGER  avail;
                    666:        ULARGE_INTEGER  size;
                    667:        static HINSTANCE hK32;
                    668:        GetDiskFreeSpaceEx_t GetDiskFreeSpaceEx;
                    669: 
                    670:        if(hK32 == NULL)
                    671:                hK32 = LoadLibrary("KERNEL32");
                    672:        GetDiskFreeSpaceEx 
                    673:                = (GetDiskFreeSpaceEx_t)GetProcAddress(hK32,"GetDiskFreeSpaceExA");
                    674:  
                    675:        if (GetDiskFreeSpaceEx!=NULL) { /* Windows 95-OSR2 or later */
                    676:                if(!GetDiskFreeSpaceEx(
                    677:                        path,           // pointer to the directory name
                    678:                        &avail,         // receives the number of bytes on disk avail to the caller
                    679:                        &size,          // receives the number of bytes on disk
                    680:                        NULL))          // receives the free bytes on disk
                    681:                        return(0);
                    682: 
                    683:                if(unit>1)
                    684:                        avail.QuadPart=Int64ShrlMod32(avail.QuadPart,bit_num(unit));
                    685: 
                    686: #if defined(_ANONYMOUS_STRUCT)
                    687:                if(avail.HighPart)
                    688: #else
                    689:                if(avail.u.HighPart)
                    690: #endif
                    691:                        return(0xffffffff);     /* 4GB max */
                    692: 
                    693: #if defined(_ANONYMOUS_STRUCT)
                    694:                return(avail.LowPart);
                    695: #else
                    696:                return(avail.u.LowPart);
                    697: #endif
                    698:        }
                    699: 
                    700:        /* Windows 95 (old way), limited to 2GB */
                    701:        sprintf(root,"%.3s",path);
                    702:        if(!GetDiskFreeSpace(
                    703:                root,                                   // pointer to root path
                    704:                &SectorsPerCluster,             // pointer to sectors per cluster
                    705:                &BytesPerSector,                // pointer to bytes per sector
                    706:                &NumberOfFreeClusters,  // pointer to number of free clusters
                    707:                &TotalNumberOfClusters  // pointer to total number of clusters
                    708:                ))
                    709:                return(0);
                    710: 
                    711:        if(unit>1)
                    712:                NumberOfFreeClusters/=unit;
                    713:        return(NumberOfFreeClusters*SectorsPerCluster*BytesPerSector);
                    714: 
                    715: 
                    716: /* statfs is also used under FreeBSD */
                    717: #elif defined(__GLIBC__) || defined(BSD)
                    718: 
                    719:        struct statfs fs;
                    720: 
                    721:     if (statfs(path, &fs) < 0)
                    722:        return 0;
                    723: 
                    724:        if(unit>1)
                    725:                fs.f_bavail/=unit;
                    726:     return fs.f_bsize * fs.f_bavail;
                    727:     
                    728: #elif defined(__solaris__)
                    729: 
                    730:        struct statvfs fs;
                    731: 
                    732:     if (statvfs(path, &fs) < 0)
                    733:        return 0;
                    734: 
                    735:        if(unit>1)
                    736:                fs.f_bavail/=unit;
                    737:     return fs.f_bsize * fs.f_bavail;
                    738:     
                    739: #else
                    740: 
                    741:        fprintf(stderr,"\n*** !Missing getfreediskspace implementation ***\n");
                    742:        return(0);
                    743: 
                    744: #endif
                    745: }
                    746: 
                    747: /****************************************************************************/
                    748: /* Resolves //, /./, and /../ in a path. Should work indetically to Windows */
                    749: /****************************************************************************/
                    750: #if defined(__unix__)
                    751: char * DLLCALL _fullpath(char *target, const char *path, size_t size)  {
                    752:        char    *out;
                    753:        char    *p;
                    754:        
                    755:        if(target==NULL)  {
                    756:                if((target=malloc(MAX_PATH+1))==NULL) {
                    757:                        return(NULL);
                    758:                }
                    759:        }
                    760:        out=target;
                    761:        *out=0;
                    762: 
                    763:        if(*path != '/')  {
                    764:                p=getcwd(target,size);
                    765:                if(p==NULL || strlen(p)+strlen(path)>=size)
                    766:                        return(NULL);
                    767:                out=strrchr(target,'\0');
                    768:                *(out++)='/';
                    769:                *out=0;
                    770:                out--;
                    771:        }
                    772:        strncat(target,path,size-1);
                    773:        
                    774: /*     if(stat(target,&sb))
                    775:                return(NULL);
                    776:        if(sb.st_mode&S_IFDIR)
                    777:                strcat(target,"/"); */
                    778: 
                    779:        for(;*out;out++)  {
                    780:                while(*out=='/')  {
                    781:                        if(*(out+1)=='/')
                    782:                                memmove(out,out+1,strlen(out));
                    783:                        else if(*(out+1)=='.' && (*(out+2)=='/' || *(out+2)==0))
                    784:                                memmove(out,out+2,strlen(out)-1);
                    785:                        else if(*(out+1)=='.' && *(out+2)=='.' && (*(out+3)=='/' || *(out+3)==0))  {
                    786:                                *out=0;
                    787:                                p=strrchr(target,'/');
                    788:                                memmove(p,out+3,strlen(out+3)+1);
                    789:                                out=p;
                    790:                        }
                    791:                        else  {
                    792:                                out++;
                    793:                        }
                    794:                }
                    795:        }
                    796:        return(target);
                    797: }
                    798: #endif
                    799: 
                    800: /****************************************************************************/
                    801: /* Adds a trailing slash/backslash (path delimiter) on path strings            */
                    802: /****************************************************************************/
                    803: char* DLLCALL backslash(char* path)
                    804: {
                    805:        char* p;
                    806: 
                    807:        p=lastchar(path);
                    808: 
                    809:        if(*p!='/' && *p!='\\') {
                    810:                *(++p)=PATH_DELIM;
                    811:                *(++p)=0;
                    812:        }
                    813:        return(path);
                    814: }
                    815: 
                    816: /****************************************************************************/
                    817: /* Returns true if the specified filename an aboslute pathname                         */
                    818: /****************************************************************************/
                    819: BOOL DLLCALL isabspath(const char *filename)
                    820: {
                    821:        char path[MAX_PATH+1];
                    822: 
                    823:        return(stricmp(filename,FULLPATH(path,filename,sizeof(path)))==0);
                    824: }
                    825: 
                    826: /****************************************************************************/
                    827: /* Returns true if the specified filename is a full ("rooted") path                    */
                    828: /****************************************************************************/
                    829: BOOL DLLCALL isfullpath(const char* filename)
                    830: {
                    831:        return(filename[0]=='/' 
                    832: #ifdef WIN32
                    833:                || filename[0]=='\\' || filename[1]==':'
                    834: #endif
                    835:                );
                    836: }

unix.superglobalmegacorp.com

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