|
|
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: {
1.1.1.4 ! root 369: FILE *DiscFile;
1.1 root 370:
1.1.1.2 root 371: /* Attempt to open file */
1.1.1.4 ! root 372: DiscFile = fopen(pszFileName, "rb");
! 373: if (DiscFile!=NULL) {
! 374: fclose(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.