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

unix.superglobalmegacorp.com

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