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 (17 years, 2 months ago) by berlac
Branch: MAIN
CVS Tags: HEAD
Log Message:
Initial revision.

File Contents

# Content
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