|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.