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