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