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

1.1     ! root        1: /* dirwrap.c */
        !             2: 
        !             3: /* Directory-related system-call wrappers */
        !             4: 
        !             5: /* $Id: dirwrap.c,v 1.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.