|
|
1.1 root 1: /*
2: Hatari
3:
4: common file access
5: */
6:
7: #include <sys/types.h>
8: #include <sys/stat.h>
9: #include <fcntl.h>
10:
11: #include "main.h"
12: #include "dialog.h"
13: #include "file.h"
14: #include "floppy.h"
15: #include "createBlankImage.h"
16: #include "memAlloc.h"
17: #include "misc.h"
18:
19:
1.1.1.3 ! root 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:
1.1 root 32:
33: /*-----------------------------------------------------------------------*/
34: /*
1.1.1.3 ! root 35: Alphabetic order comparison routine for those who want it.
1.1 root 36: */
1.1.1.3 ! root 37: int alphasort(const void *d1, const void *d2)
1.1 root 38: {
1.1.1.3 ! root 39: return(strcmp((*(struct dirent **)d1)->d_name, (*(struct dirent **)d2)->d_name));
! 40: }
1.1 root 41:
42:
1.1.1.3 ! root 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;
1.1 root 54:
1.1.1.3 ! root 55: if ((dirp = opendir(dirname)) == NULL)
! 56: return(-1);
1.1 root 57:
1.1.1.3 ! root 58: if (fstat(dirp->fd, &stb) < 0)
! 59: return(-1);
1.1 root 60:
1.1.1.3 ! root 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);
1.1 root 66:
1.1.1.3 ! root 67: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
! 68: if (names == NULL)
! 69: return(-1);
1.1 root 70:
1.1.1.3 ! root 71: nitems = 0;
1.1 root 72:
1.1.1.3 ! root 73: while ((d = readdir(dirp)) != NULL) {
1.1 root 74:
1.1.1.3 ! root 75: if (select != NULL && !(*select)(d))
! 76: continue; /* just selected names */
1.1 root 77:
1.1.1.3 ! root 78: /*
! 79: * Make a minimum size copy of the data
! 80: */
1.1 root 81:
1.1.1.3 ! root 82: p = (struct dirent *)malloc(DIRSIZ(d));
! 83: if (p == NULL)
! 84: return(-1);
1.1 root 85:
1.1.1.3 ! root 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);
1.1 root 90:
1.1.1.3 ! root 91: /*
! 92: * Check to make sure the array has space left and
! 93: * realloc the maximum size.
! 94: */
1.1 root 95:
1.1.1.3 ! root 96: if (++nitems >= arraysz) {
1.1 root 97:
1.1.1.3 ! root 98: if (fstat(dirp->fd, &stb) < 0)
! 99: return(-1); /* just might have grown */
1.1 root 100:
1.1.1.3 ! root 101: arraysz = stb.st_size / 12;
1.1 root 102:
1.1.1.3 ! root 103: names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
! 104: if (names == NULL)
! 105: return(-1);
! 106: }
1.1 root 107:
1.1.1.3 ! root 108: names[nitems-1] = p;
! 109: }
1.1 root 110:
1.1.1.3 ! root 111: closedir(dirp);
1.1 root 112:
1.1.1.3 ! root 113: if (nitems && dcomp != NULL)
! 114: qsort(names, nitems, sizeof(struct dirent *), dcomp);
1.1 root 115:
1.1.1.3 ! root 116: *namelist = names;
! 117:
! 118: return(nitems);
1.1 root 119: }
120:
121:
1.1.1.3 ! root 122: #endif /* __BEOS__ */
! 123:
1.1 root 124:
1.1.1.2 root 125:
126: /*-----------------------------------------------------------------------*/
1.1 root 127: /*
128: Remove any '/'s from end of filenames, but keeps / intact
129: */
130: void File_CleanFileName(char *pszFileName)
131: {
1.1.1.3 ! root 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: }
1.1 root 142:
1.1.1.2 root 143: /* Remove end slash from filename! But / remains! Doh! */
1.1.1.3 ! root 144: if( len>2 && pszFileName[len-1]=='/' )
! 145: pszFileName[len-1] = 0;
1.1 root 146: }
147:
1.1.1.2 root 148:
149: /*-----------------------------------------------------------------------*/
1.1 root 150: /*
151: Add '/' to end of filename
152: */
153: void File_AddSlashToEndFileName(char *pszFileName)
154: {
1.1.1.2 root 155: /* Check dir/filenames */
1.1 root 156: if (strlen(pszFileName)!=0) {
157: if (pszFileName[strlen(pszFileName)-1]!='/')
1.1.1.2 root 158: strcat(pszFileName,"/"); /* Must use end slash */
1.1 root 159: }
160: }
161:
1.1.1.3 ! root 162:
1.1 root 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:
1.1.1.2 root 179:
180: /*-----------------------------------------------------------------------*/
1.1 root 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:
1.1.1.2 root 197:
198: /*-----------------------------------------------------------------------*/
1.1 root 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:
1.1.1.2 root 211: /*-----------------------------------------------------------------------*/
1.1 root 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:
1.1.1.3 ! root 222: /* Does string end in a '/'? */
1.1 root 223: if (pszFileName[strlen(pszFileName)-1]=='/')
224: return(TRUE);
225:
226: return(FALSE);
227: }
228:
1.1.1.2 root 229:
230: /*-----------------------------------------------------------------------*/
1.1 root 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:
1.1.1.2 root 249: /*-----------------------------------------------------------------------*/
1.1 root 250: /*
251: Does filename end with a .MSA extension? If so, return TRUE
252: */
253: BOOL File_FileNameIsMSA(char *pszFileName)
254: {
255: return(File_DoesFileExtensionMatch(pszFileName,".msa"));
256: }
257:
1.1.1.2 root 258:
259: /*-----------------------------------------------------------------------*/
1.1 root 260: /*
261: Does filename end with a .ST extension? If so, return TRUE
262: */
263: BOOL File_FileNameIsST(char *pszFileName)
264: {
265: return(File_DoesFileExtensionMatch(pszFileName,".st"));
266: }
267:
268:
1.1.1.2 root 269: /*-----------------------------------------------------------------------*/
1.1 root 270: /*
1.1.1.2 root 271: Read file from PC into memory, allocate memory for it if need to (pass Address as NULL)
272: Also may pass 'unsigned long' if want to find size of file read (may pass as NULL)
1.1 root 273: */
274: void *File_Read(char *pszFileName, void *pAddress, long *pFileSize, char *ppszExts[])
275: {
1.1.1.2 root 276: FILE *DiscFile;
1.1 root 277: void *pFile=NULL;
278: long FileSize=0;
279:
280: /* Does the file exist? If not, see if can scan for other extensions and try these */
281: if (!File_Exists(pszFileName) && ppszExts) {
282: /* Try other extensions, if suceeds correct filename is now in 'pszFileName' */
283: File_FindPossibleExtFileName(pszFileName,ppszExts);
284: }
285:
286: /* Open our file */
1.1.1.2 root 287: DiscFile = fopen(pszFileName, "rb");
288: if (DiscFile!=NULL) {
1.1 root 289: /* Find size of TOS image - 192k or 256k */
1.1.1.2 root 290: fseek(DiscFile, 0, SEEK_END);
291: FileSize = ftell(DiscFile);
292: fseek(DiscFile, 0, SEEK_SET);
1.1 root 293: /* Find pointer to where to load, allocate memory if pass NULL */
294: if (pAddress)
295: pFile = pAddress;
296: else
297: pFile = Memory_Alloc(FileSize);
298: /* Read in... */
299: if (pFile)
1.1.1.2 root 300: fread((char *)pFile, 1, FileSize, DiscFile);
1.1 root 301:
1.1.1.2 root 302: fclose(DiscFile);
1.1 root 303: }
1.1.1.2 root 304: /* Store size of file we read in (or 0 if failed) */
1.1 root 305: if (pFileSize)
306: *pFileSize = FileSize;
307:
308: return(pFile); /* Return to where read in/allocated */
309: }
310:
1.1.1.2 root 311:
312: /*-----------------------------------------------------------------------*/
1.1 root 313: /*
314: Save file to PC, return FALSE if errors
315: */
316: BOOL File_Save(char *pszFileName, void *pAddress,long Size,BOOL bQueryOverwrite)
317: {
1.1.1.2 root 318: FILE *DiscFile;
1.1 root 319: BOOL bRet=FALSE;
320:
321: /* Check if need to ask user if to overwrite */
322: if (bQueryOverwrite) {
323: /* If file exists, ask if OK to overwrite */
324: if (!File_QueryOverwrite(pszFileName))
325: return(FALSE);
326: }
327:
328: /* Create our file */
1.1.1.2 root 329: DiscFile = fopen(pszFileName, "wb");
330: if (DiscFile!=NULL) {
1.1 root 331: /* Write data, set success flag */
1.1.1.2 root 332: if ( fwrite(pAddress, 1, Size, DiscFile)==Size )
1.1 root 333: bRet = TRUE;
334:
1.1.1.2 root 335: fclose(DiscFile);
1.1 root 336: }
337:
338: return(bRet);
339: }
340:
1.1.1.2 root 341:
342: /*-----------------------------------------------------------------------*/
1.1 root 343: /*
344: Return size of file, -1 if error
345: */
346: int File_Length(char *pszFileName)
347: {
1.1.1.3 ! root 348: FILE *DiscFile;
1.1 root 349: int FileSize;
1.1.1.3 ! root 350: DiscFile = fopen(pszFileName, "rb");
! 351: if (DiscFile!=NULL) {
! 352: fseek(DiscFile, 0, SEEK_END);
! 353: FileSize = ftell(DiscFile);
! 354: fseek(DiscFile, 0, SEEK_SET);
! 355: fclose(DiscFile);
1.1 root 356: return(FileSize);
357: }
358:
359: return(-1);
360: }
361:
1.1.1.2 root 362:
363: /*-----------------------------------------------------------------------*/
1.1 root 364: /*
365: Return TRUE if file exists
366: */
367: BOOL File_Exists(char *pszFileName)
368: {
369: int DiscFile;
370:
1.1.1.2 root 371: /* Attempt to open file */
1.1 root 372: DiscFile = open(pszFileName, O_RDONLY);
1.1.1.2 root 373: if (DiscFile!=-1) {
374: close(DiscFile);
1.1 root 375: return(TRUE);
1.1.1.2 root 376: }
1.1 root 377: return(FALSE);
378: }
379:
1.1.1.2 root 380:
381: /*-----------------------------------------------------------------------*/
1.1 root 382: /*
383: Delete file, return TRUE if OK
384: */
385: BOOL File_Delete(char *pszFileName)
386: {
1.1.1.2 root 387: /* Delete the file (must be closed first) */
1.1 root 388: return( remove(pszFileName) );
389: }
390:
1.1.1.2 root 391:
392: /*-----------------------------------------------------------------------*/
1.1 root 393: /*
394: Find if file exists, and if so ask user if OK to overwrite
395: */
1.1.1.2 root 396: BOOL File_QueryOverwrite(char *pszFileName)
1.1 root 397: {
398:
399: char szString[MAX_FILENAME_LENGTH];
400:
1.1.1.2 root 401: /* Try and find if file exists */
1.1 root 402: if (File_Exists(pszFileName)) {
1.1.1.2 root 403: /* File does exist, are we OK to overwrite? */
1.1 root 404: sprintf(szString,"File '%s' exists, overwrite?",pszFileName);
405: /* FIXME: */
406: // if (MessageBox(hWnd,szString,PROG_NAME,MB_YESNO | MB_DEFBUTTON2 | MB_ICONSTOP)==IDNO)
407: // return(FALSE);
408: }
409:
410: return(TRUE);
411: }
412:
1.1.1.2 root 413:
414: /*-----------------------------------------------------------------------*/
1.1 root 415: /*
416: Try filename with various extensions and check if file exists - if so return correct name
417: */
1.1.1.3 ! root 418: BOOL File_FindPossibleExtFileName(char *pszFileName, char *ppszExts[])
1.1 root 419: {
1.1.1.3 ! root 420: char szSrcDir[256], szSrcName[128], szSrcExt[32];
1.1 root 421: char szTempFileName[MAX_FILENAME_LENGTH];
422: int i=0;
423:
1.1.1.3 ! root 424: /* Split filename into parts */
! 425: File_splitpath(pszFileName, szSrcDir, szSrcName, szSrcExt);
1.1 root 426:
1.1.1.3 ! root 427: /* Scan possible extensions */
1.1 root 428: while(ppszExts[i]) {
1.1.1.3 ! root 429: /* Re-build with new file extension */
! 430: File_makepath(szTempFileName, szSrcDir, szSrcName, ppszExts[i]);
! 431: /* Does this file exist? */
1.1 root 432: if (File_Exists(szTempFileName)) {
1.1.1.3 ! root 433: /* Copy name for return */
1.1 root 434: strcpy(pszFileName,szTempFileName);
435: return(TRUE);
436: }
437:
1.1.1.3 ! root 438: /* Next one */
1.1 root 439: i++;
440: }
1.1.1.3 ! root 441:
1.1.1.2 root 442: /* No, none of the files exist */
1.1 root 443: return(FALSE);
444: }
1.1.1.3 ! root 445:
! 446:
! 447: /*-----------------------------------------------------------------------*/
! 448: /*
! 449: Split a complete filename into path, filename and extension.
! 450: If pExt is NULL, don't split the extension from the file name!
! 451: */
! 452: void File_splitpath(char *pSrcFileName, char *pDir, char *pName, char *pExt)
! 453: {
! 454: char *ptr1, *ptr2;
! 455:
! 456: /* Build pathname: */
! 457: ptr1 = strrchr(pSrcFileName, '/');
! 458: if( ptr1 )
! 459: {
! 460: strcpy(pDir, pSrcFileName);
! 461: strcpy(pName, ptr1+1);
! 462: pDir[ptr1-pSrcFileName+1] = 0;
! 463: }
! 464: else
! 465: {
! 466: strcpy(pDir, "./");
! 467: strcpy(pName, pSrcFileName);
! 468: }
! 469:
! 470: /* Build the raw filename: */
! 471: if( pExt!=NULL )
! 472: {
! 473: ptr2 = strrchr(pName+1, '.');
! 474: if( ptr2 )
! 475: {
! 476: pName[ptr2-pName] = 0;
! 477: /* Copy the file extension: */
! 478: strcpy(pExt, ptr2+1);
! 479: }
! 480: else
! 481: pExt[0] = 0;
! 482: }
! 483: }
! 484:
! 485:
! 486: /*-----------------------------------------------------------------------*/
! 487: /*
! 488: Build a complete filename from path, filename and extension.
! 489: pExt can also be NULL.
! 490: */
! 491: void File_makepath(char *pDestFileName, char *pDir, char *pName, char *pExt)
! 492: {
! 493: strcpy(pDestFileName, pDir);
! 494: if( strlen(pDestFileName)==0 )
! 495: strcpy(pDestFileName, "./");
! 496: if( pDestFileName[strlen(pDestFileName)-1]!='/' )
! 497: strcat(pDestFileName, "/");
! 498:
! 499: strcat(pDestFileName, pName);
! 500:
! 501: if( pExt!=NULL )
! 502: {
! 503: if( strlen(pExt)>0 && pExt[0]!='.' )
! 504: strcat(pDestFileName, ".");
! 505: strcat(pDestFileName, pExt);
! 506: }
! 507: }
! 508:
! 509:
! 510: /*-----------------------------------------------------------------------*/
! 511: /*
! 512: Shrink a file name to a certain length and insert some dots if we cut
! 513: something away (usefull for showing file names in a dialog).
! 514: */
! 515: void File_ShrinkName(char *pDestFileName, char *pSrcFileName, int maxlen)
! 516: {
! 517: int srclen = strlen(pSrcFileName);
! 518: if( srclen<maxlen )
! 519: strcpy(pDestFileName, pSrcFileName); /* It fits! */
! 520: else
! 521: {
! 522: strncpy(pDestFileName, pSrcFileName, maxlen/2);
! 523: if(maxlen&1) /* even or uneven? */
! 524: pDestFileName[maxlen/2-1] = 0;
! 525: else
! 526: pDestFileName[maxlen/2-2] = 0;
! 527: strcat(pDestFileName, "...");
! 528: strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]);
! 529: }
! 530: }
! 531:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.