ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/file.cpp
Revision: 1.1
Committed: 2007-01-28T17:01:07Z (16 years ago) by berlac
Branch: MAIN
CVS Tags: HEAD
Log Message:
Initial revision.

File Contents

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