|
|
1.1 ! root 1: /* ! 2: Hatari ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: common file access ! 8: */ ! 9: ! 10: #include <sys/types.h> ! 11: #include <sys/stat.h> ! 12: #include <fcntl.h> ! 13: ! 14: #include "main.h" ! 15: #include "file.h" ! 16: #include "memAlloc.h" ! 17: #include "misc.h" ! 18: ! 19: ! 20: ! 21: #ifdef __BEOS__ ! 22: /* The scandir() and alphasort() functions aren't available on BeOS, */ ! 23: /* so let's declare them here... */ ! 24: #include <dirent.h> ! 25: ! 26: #undef DIRSIZ ! 27: ! 28: #define DIRSIZ(dp) \ ! 29: ((sizeof(struct dirent) - sizeof(dp)->d_name) + \ ! 30: (((dp)->d_reclen + 1 + 3) &~ 3)) ! 31: ! 32: ! 33: /*-----------------------------------------------------------------------*/ ! 34: /* ! 35: Alphabetic order comparison routine for those who want it. ! 36: */ ! 37: int alphasort(const void *d1, const void *d2) ! 38: { ! 39: return(strcmp((*(struct dirent **)d1)->d_name, (*(struct dirent **)d2)->d_name)); ! 40: } ! 41: ! 42: ! 43: /*-----------------------------------------------------------------------*/ ! 44: /* ! 45: Scan a directory for all its entries ! 46: */ ! 47: int scandir(const char *dirname,struct dirent ***namelist, int(*select) __P((struct dirent *)), int (*dcomp) __P((const void *, const void *))) ! 48: { ! 49: register struct dirent *d, *p, **names; ! 50: register size_t nitems; ! 51: struct stat stb; ! 52: long arraysz; ! 53: DIR *dirp; ! 54: ! 55: if ((dirp = opendir(dirname)) == NULL) ! 56: return(-1); ! 57: ! 58: if (fstat(dirp->fd, &stb) < 0) ! 59: return(-1); ! 60: ! 61: /* ! 62: * estimate the array size by taking the size of the directory file ! 63: * and dividing it by a multiple of the minimum size entry. ! 64: */ ! 65: arraysz = (stb.st_size / 24); ! 66: ! 67: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); ! 68: if (names == NULL) ! 69: return(-1); ! 70: ! 71: nitems = 0; ! 72: ! 73: while ((d = readdir(dirp)) != NULL) { ! 74: ! 75: if (select != NULL && !(*select)(d)) ! 76: continue; /* just selected names */ ! 77: ! 78: /* ! 79: * Make a minimum size copy of the data ! 80: */ ! 81: ! 82: p = (struct dirent *)malloc(DIRSIZ(d)); ! 83: if (p == NULL) ! 84: return(-1); ! 85: ! 86: p->d_ino = d->d_ino; ! 87: p->d_reclen = d->d_reclen; ! 88: /*p->d_namlen = d->d_namlen;*/ ! 89: bcopy(d->d_name, p->d_name, p->d_reclen + 1); ! 90: ! 91: /* ! 92: * Check to make sure the array has space left and ! 93: * realloc the maximum size. ! 94: */ ! 95: ! 96: if (++nitems >= arraysz) { ! 97: ! 98: if (fstat(dirp->fd, &stb) < 0) ! 99: return(-1); /* just might have grown */ ! 100: ! 101: arraysz = stb.st_size / 12; ! 102: ! 103: names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *)); ! 104: if (names == NULL) ! 105: return(-1); ! 106: } ! 107: ! 108: names[nitems-1] = p; ! 109: } ! 110: ! 111: closedir(dirp); ! 112: ! 113: if (nitems && dcomp != NULL) ! 114: qsort(names, nitems, sizeof(struct dirent *), dcomp); ! 115: ! 116: *namelist = names; ! 117: ! 118: return(nitems); ! 119: } ! 120: ! 121: ! 122: #endif /* __BEOS__ */ ! 123: ! 124: ! 125: ! 126: /*-----------------------------------------------------------------------*/ ! 127: /* ! 128: Remove any '/'s from end of filenames, but keeps / intact ! 129: */ ! 130: void File_CleanFileName(char *pszFileName) ! 131: { ! 132: int len; ! 133: ! 134: len = strlen(pszFileName); ! 135: ! 136: /* Security length check: */ ! 137: if( len>MAX_FILENAME_LENGTH ) ! 138: { ! 139: pszFileName[MAX_FILENAME_LENGTH-1] = 0; ! 140: len = MAX_FILENAME_LENGTH; ! 141: } ! 142: ! 143: /* Remove end slash from filename! But / remains! Doh! */ ! 144: if( len>2 && pszFileName[len-1]=='/' ) ! 145: pszFileName[len-1] = 0; ! 146: } ! 147: ! 148: ! 149: /*-----------------------------------------------------------------------*/ ! 150: /* ! 151: Add '/' to end of filename ! 152: */ ! 153: void File_AddSlashToEndFileName(char *pszFileName) ! 154: { ! 155: /* Check dir/filenames */ ! 156: if (strlen(pszFileName)!=0) { ! 157: if (pszFileName[strlen(pszFileName)-1]!='/') ! 158: strcat(pszFileName,"/"); /* Must use end slash */ ! 159: } ! 160: } ! 161: ! 162: ! 163: /*-----------------------------------------------------------------------*/ ! 164: /* ! 165: Does filename extension match? If so, return TRUE ! 166: */ ! 167: BOOL File_DoesFileExtensionMatch(char *pszFileName, char *pszExtension) ! 168: { ! 169: if ( strlen(pszFileName) < strlen(pszExtension) ) ! 170: return(FALSE); ! 171: /* Is matching extension? */ ! 172: if ( !strcasecmp(&pszFileName[strlen(pszFileName)-strlen(pszExtension)], pszExtension) ) ! 173: return(TRUE); ! 174: ! 175: /* No */ ! 176: return(FALSE); ! 177: } ! 178: ! 179: ! 180: /*-----------------------------------------------------------------------*/ ! 181: /* ! 182: Check if filename is from root ! 183: ! 184: Return TRUE if filename is '/', else give FALSE ! 185: */ ! 186: BOOL File_IsRootFileName(char *pszFileName) ! 187: { ! 188: if (pszFileName[0]=='\0') /* If NULL string return! */ ! 189: return(FALSE); ! 190: ! 191: if (pszFileName[0]=='/') ! 192: return(TRUE); ! 193: ! 194: return(FALSE); ! 195: } ! 196: ! 197: ! 198: /*-----------------------------------------------------------------------*/ ! 199: /* ! 200: Return string, to remove 'C:' part of filename ! 201: */ ! 202: char *File_RemoveFileNameDrive(char *pszFileName) ! 203: { ! 204: if ( (pszFileName[0]!='\0') && (pszFileName[1]==':') ) ! 205: return(&pszFileName[2]); ! 206: else ! 207: return(pszFileName); ! 208: } ! 209: ! 210: ! 211: /*-----------------------------------------------------------------------*/ ! 212: /* ! 213: Check if filename end with a '/' ! 214: ! 215: Return TRUE if filename ends with '/' ! 216: */ ! 217: BOOL File_DoesFileNameEndWithSlash(char *pszFileName) ! 218: { ! 219: if (pszFileName[0]=='\0') /* If NULL string return! */ ! 220: return(FALSE); ! 221: ! 222: /* Does string end in a '/'? */ ! 223: if (pszFileName[strlen(pszFileName)-1]=='/') ! 224: return(TRUE); ! 225: ! 226: return(FALSE); ! 227: } ! 228: ! 229: ! 230: /*-----------------------------------------------------------------------*/ ! 231: /* ! 232: Remove any double '/'s from end of filenames. So just the one ! 233: */ ! 234: void File_RemoveFileNameTrailingSlashes(char *pszFileName) ! 235: { ! 236: int Length; ! 237: ! 238: /* Do have slash at end of filename? */ ! 239: Length = strlen(pszFileName); ! 240: if (Length>=3) { ! 241: if (pszFileName[Length-1]=='/') { /* Yes, have one previous? */ ! 242: if (pszFileName[Length-2]=='/') ! 243: pszFileName[Length-1] = '\0'; /* then remove it! */ ! 244: } ! 245: } ! 246: } ! 247: ! 248: ! 249: /*-----------------------------------------------------------------------*/ ! 250: /* ! 251: Does filename end with a .ST.GZ extension? If so, return TRUE ! 252: */ ! 253: BOOL File_FileNameIsSTGZ(char *pszFileName) ! 254: { ! 255: return(File_DoesFileExtensionMatch(pszFileName,".st.gz")); ! 256: } ! 257: ! 258: ! 259: /*-----------------------------------------------------------------------*/ ! 260: /* ! 261: Does filename end with a .MSA.GZ extension? If so, return TRUE ! 262: */ ! 263: BOOL File_FileNameIsMSAGZ(char *pszFileName) ! 264: { ! 265: return(File_DoesFileExtensionMatch(pszFileName,".msa.gz")); ! 266: } ! 267: ! 268: ! 269: /*-----------------------------------------------------------------------*/ ! 270: /* ! 271: Does filename end with a .ZIP extension? If so, return TRUE ! 272: */ ! 273: BOOL File_FileNameIsZIP(char *pszFileName) ! 274: { ! 275: return(File_DoesFileExtensionMatch(pszFileName,".zip")); ! 276: } ! 277: ! 278: ! 279: /*-----------------------------------------------------------------------*/ ! 280: /* ! 281: Does filename end with a .MSA extension? If so, return TRUE ! 282: */ ! 283: BOOL File_FileNameIsMSA(char *pszFileName) ! 284: { ! 285: return(File_DoesFileExtensionMatch(pszFileName,".msa")); ! 286: } ! 287: ! 288: ! 289: /*-----------------------------------------------------------------------*/ ! 290: /* ! 291: Does filename end with a .ST extension? If so, return TRUE ! 292: */ ! 293: BOOL File_FileNameIsST(char *pszFileName) ! 294: { ! 295: return(File_DoesFileExtensionMatch(pszFileName,".st")); ! 296: } ! 297: ! 298: ! 299: /*-----------------------------------------------------------------------*/ ! 300: /* ! 301: Read file from PC into memory, allocate memory for it if need to (pass Address as NULL) ! 302: Also may pass 'unsigned long' if want to find size of file read (may pass as NULL) ! 303: */ ! 304: void *File_Read(char *pszFileName, void *pAddress, long *pFileSize, char *ppszExts[]) ! 305: { ! 306: FILE *DiscFile; ! 307: void *pFile=NULL; ! 308: long FileSize=0; ! 309: ! 310: /* Does the file exist? If not, see if can scan for other extensions and try these */ ! 311: if (!File_Exists(pszFileName) && ppszExts) { ! 312: /* Try other extensions, if suceeds correct filename is now in 'pszFileName' */ ! 313: File_FindPossibleExtFileName(pszFileName,ppszExts); ! 314: } ! 315: ! 316: /* Open our file */ ! 317: DiscFile = fopen(pszFileName, "rb"); ! 318: if (DiscFile!=NULL) { ! 319: /* Find size of TOS image - 192k or 256k */ ! 320: fseek(DiscFile, 0, SEEK_END); ! 321: FileSize = ftell(DiscFile); ! 322: fseek(DiscFile, 0, SEEK_SET); ! 323: /* Find pointer to where to load, allocate memory if pass NULL */ ! 324: if (pAddress) ! 325: pFile = pAddress; ! 326: else ! 327: pFile = Memory_Alloc(FileSize); ! 328: /* Read in... */ ! 329: if (pFile) ! 330: fread((char *)pFile, 1, FileSize, DiscFile); ! 331: ! 332: fclose(DiscFile); ! 333: } ! 334: /* Store size of file we read in (or 0 if failed) */ ! 335: if (pFileSize) ! 336: *pFileSize = FileSize; ! 337: ! 338: return(pFile); /* Return to where read in/allocated */ ! 339: } ! 340: ! 341: ! 342: /*-----------------------------------------------------------------------*/ ! 343: /* ! 344: Save file to PC, return FALSE if errors ! 345: */ ! 346: BOOL File_Save(char *pszFileName, void *pAddress,long Size,BOOL bQueryOverwrite) ! 347: { ! 348: FILE *DiscFile; ! 349: BOOL bRet=FALSE; ! 350: ! 351: /* Check if need to ask user if to overwrite */ ! 352: if (bQueryOverwrite) { ! 353: /* If file exists, ask if OK to overwrite */ ! 354: if (!File_QueryOverwrite(pszFileName)) ! 355: return(FALSE); ! 356: } ! 357: ! 358: /* Create our file */ ! 359: DiscFile = fopen(pszFileName, "wb"); ! 360: if (DiscFile!=NULL) { ! 361: /* Write data, set success flag */ ! 362: if ( fwrite(pAddress, 1, Size, DiscFile)==Size ) ! 363: bRet = TRUE; ! 364: ! 365: fclose(DiscFile); ! 366: } ! 367: ! 368: return(bRet); ! 369: } ! 370: ! 371: ! 372: /*-----------------------------------------------------------------------*/ ! 373: /* ! 374: Return size of file, -1 if error ! 375: */ ! 376: int File_Length(char *pszFileName) ! 377: { ! 378: FILE *DiscFile; ! 379: int FileSize; ! 380: DiscFile = fopen(pszFileName, "rb"); ! 381: if (DiscFile!=NULL) { ! 382: fseek(DiscFile, 0, SEEK_END); ! 383: FileSize = ftell(DiscFile); ! 384: fseek(DiscFile, 0, SEEK_SET); ! 385: fclose(DiscFile); ! 386: return(FileSize); ! 387: } ! 388: ! 389: return(-1); ! 390: } ! 391: ! 392: ! 393: /*-----------------------------------------------------------------------*/ ! 394: /* ! 395: Return TRUE if file exists ! 396: */ ! 397: BOOL File_Exists(char *pszFileName) ! 398: { ! 399: FILE *DiscFile; ! 400: ! 401: /* Attempt to open file */ ! 402: DiscFile = fopen(pszFileName, "rb"); ! 403: if (DiscFile!=NULL) { ! 404: fclose(DiscFile); ! 405: return(TRUE); ! 406: } ! 407: return(FALSE); ! 408: } ! 409: ! 410: ! 411: /*-----------------------------------------------------------------------*/ ! 412: /* ! 413: Delete file, return TRUE if OK ! 414: */ ! 415: BOOL File_Delete(char *pszFileName) ! 416: { ! 417: /* Delete the file (must be closed first) */ ! 418: return( remove(pszFileName) ); ! 419: } ! 420: ! 421: ! 422: /*-----------------------------------------------------------------------*/ ! 423: /* ! 424: Find if file exists, and if so ask user if OK to overwrite ! 425: */ ! 426: BOOL File_QueryOverwrite(char *pszFileName) ! 427: { ! 428: ! 429: char szString[MAX_FILENAME_LENGTH]; ! 430: ! 431: /* Try and find if file exists */ ! 432: if (File_Exists(pszFileName)) { ! 433: /* File does exist, are we OK to overwrite? */ ! 434: sprintf(szString,"File '%s' exists, overwrite?",pszFileName); ! 435: /* FIXME: */ ! 436: // if (MessageBox(hWnd,szString,PROG_NAME,MB_YESNO | MB_DEFBUTTON2 | MB_ICONSTOP)==IDNO) ! 437: // return(FALSE); ! 438: } ! 439: ! 440: return(TRUE); ! 441: } ! 442: ! 443: ! 444: /*-----------------------------------------------------------------------*/ ! 445: /* ! 446: Try filename with various extensions and check if file exists - if so return correct name ! 447: */ ! 448: BOOL File_FindPossibleExtFileName(char *pszFileName, char *ppszExts[]) ! 449: { ! 450: char szSrcDir[256], szSrcName[128], szSrcExt[32]; ! 451: char szTempFileName[MAX_FILENAME_LENGTH]; ! 452: int i=0; ! 453: ! 454: /* Split filename into parts */ ! 455: File_splitpath(pszFileName, szSrcDir, szSrcName, szSrcExt); ! 456: ! 457: /* Scan possible extensions */ ! 458: while(ppszExts[i]) { ! 459: /* Re-build with new file extension */ ! 460: File_makepath(szTempFileName, szSrcDir, szSrcName, ppszExts[i]); ! 461: /* Does this file exist? */ ! 462: if (File_Exists(szTempFileName)) { ! 463: /* Copy name for return */ ! 464: strcpy(pszFileName,szTempFileName); ! 465: return(TRUE); ! 466: } ! 467: ! 468: /* Next one */ ! 469: i++; ! 470: } ! 471: ! 472: /* No, none of the files exist */ ! 473: return(FALSE); ! 474: } ! 475: ! 476: ! 477: /*-----------------------------------------------------------------------*/ ! 478: /* ! 479: Split a complete filename into path, filename and extension. ! 480: If pExt is NULL, don't split the extension from the file name! ! 481: */ ! 482: void File_splitpath(char *pSrcFileName, char *pDir, char *pName, char *pExt) ! 483: { ! 484: char *ptr1, *ptr2; ! 485: ! 486: /* Build pathname: */ ! 487: ptr1 = strrchr(pSrcFileName, '/'); ! 488: if( ptr1 ) ! 489: { ! 490: strcpy(pDir, pSrcFileName); ! 491: strcpy(pName, ptr1+1); ! 492: pDir[ptr1-pSrcFileName+1] = 0; ! 493: } ! 494: else ! 495: { ! 496: strcpy(pDir, "./"); ! 497: strcpy(pName, pSrcFileName); ! 498: } ! 499: ! 500: /* Build the raw filename: */ ! 501: if( pExt!=NULL ) ! 502: { ! 503: ptr2 = strrchr(pName+1, '.'); ! 504: if( ptr2 ) ! 505: { ! 506: pName[ptr2-pName] = 0; ! 507: /* Copy the file extension: */ ! 508: strcpy(pExt, ptr2+1); ! 509: } ! 510: else ! 511: pExt[0] = 0; ! 512: } ! 513: } ! 514: ! 515: ! 516: /*-----------------------------------------------------------------------*/ ! 517: /* ! 518: Build a complete filename from path, filename and extension. ! 519: pExt can also be NULL. ! 520: */ ! 521: void File_makepath(char *pDestFileName, char *pDir, char *pName, char *pExt) ! 522: { ! 523: strcpy(pDestFileName, pDir); ! 524: if( strlen(pDestFileName)==0 ) ! 525: strcpy(pDestFileName, "./"); ! 526: if( pDestFileName[strlen(pDestFileName)-1]!='/' ) ! 527: strcat(pDestFileName, "/"); ! 528: ! 529: strcat(pDestFileName, pName); ! 530: ! 531: if( pExt!=NULL ) ! 532: { ! 533: if( strlen(pExt)>0 && pExt[0]!='.' ) ! 534: strcat(pDestFileName, "."); ! 535: strcat(pDestFileName, pExt); ! 536: } ! 537: } ! 538: ! 539: ! 540: /*-----------------------------------------------------------------------*/ ! 541: /* ! 542: Shrink a file name to a certain length and insert some dots if we cut ! 543: something away (usefull for showing file names in a dialog). ! 544: */ ! 545: void File_ShrinkName(char *pDestFileName, char *pSrcFileName, int maxlen) ! 546: { ! 547: int srclen = strlen(pSrcFileName); ! 548: if( srclen<maxlen ) ! 549: strcpy(pDestFileName, pSrcFileName); /* It fits! */ ! 550: else ! 551: { ! 552: strncpy(pDestFileName, pSrcFileName, maxlen/2); ! 553: if(maxlen&1) /* even or uneven? */ ! 554: pDestFileName[maxlen/2-1] = 0; ! 555: else ! 556: pDestFileName[maxlen/2-2] = 0; ! 557: strcat(pDestFileName, "..."); ! 558: strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]); ! 559: } ! 560: } ! 561:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.