|
|
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.