|
|
1.1 root 1: /*
1.1.1.6 root 2: Hatari - file.c
1.1 root 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.1.6 root 7: Common file access functions.
1.1 root 8: */
1.1.1.8 ! root 9: char File_rcsid[] = "Hatari $Id: file.c,v 1.23 2005/06/01 13:44:39 thothy Exp $";
1.1 root 10:
11: #include <sys/types.h>
12: #include <sys/stat.h>
13: #include <fcntl.h>
1.1.1.6 root 14: #include <unistd.h>
15:
16: #include <zlib.h>
1.1 root 17:
18: #include "main.h"
1.1.1.7 root 19: #include "dialog.h"
1.1 root 20: #include "file.h"
21: #include "createBlankImage.h"
22:
1.1.1.3 root 23:
1.1.1.6 root 24: #if defined(__BEOS__) || (defined(__sun) && defined(__SVR4))
25: /* The scandir() and alphasort() functions aren't available on
26: * BeOS and Solaris, so let's declare them here... */
1.1.1.3 root 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.1.6 root 35: #if defined(__sun) && defined(__SVR4)
1.1.1.7 root 36: # define dirfd(d) ((d)->dd_fd)
37: #elif defined(__BEOS__)
38: # define dirfd(d) ((d)->fd)
1.1.1.6 root 39: #endif
40:
1.1 root 41:
42: /*-----------------------------------------------------------------------*/
43: /*
1.1.1.3 root 44: Alphabetic order comparison routine for those who want it.
1.1 root 45: */
1.1.1.3 root 46: int alphasort(const void *d1, const void *d2)
1.1 root 47: {
1.1.1.8 ! root 48: return strcmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
1.1.1.3 root 49: }
1.1 root 50:
51:
1.1.1.3 root 52: /*-----------------------------------------------------------------------*/
53: /*
54: Scan a directory for all its entries
55: */
1.1.1.8 ! root 56: int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
1.1.1.3 root 57: {
1.1.1.8 ! root 58: struct dirent *d, *p, **names;
1.1.1.3 root 59: struct stat stb;
1.1.1.8 ! root 60: size_t nitems;
! 61: size_t arraysz;
1.1.1.3 root 62: DIR *dirp;
1.1 root 63:
1.1.1.3 root 64: if ((dirp = opendir(dirname)) == NULL)
65: return(-1);
1.1 root 66:
1.1.1.7 root 67: if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.3 root 68: return(-1);
1.1 root 69:
1.1.1.3 root 70: /*
71: * estimate the array size by taking the size of the directory file
72: * and dividing it by a multiple of the minimum size entry.
73: */
74: arraysz = (stb.st_size / 24);
1.1 root 75:
1.1.1.3 root 76: names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
77: if (names == NULL)
78: return(-1);
1.1 root 79:
1.1.1.3 root 80: nitems = 0;
1.1 root 81:
1.1.1.3 root 82: while ((d = readdir(dirp)) != NULL) {
1.1 root 83:
1.1.1.8 ! root 84: if (sdfilter != NULL && !(*sdfilter)(d))
1.1.1.3 root 85: continue; /* just selected names */
1.1 root 86:
1.1.1.3 root 87: /*
88: * Make a minimum size copy of the data
89: */
1.1 root 90:
1.1.1.3 root 91: p = (struct dirent *)malloc(DIRSIZ(d));
92: if (p == NULL)
93: return(-1);
1.1 root 94:
1.1.1.3 root 95: p->d_ino = d->d_ino;
96: p->d_reclen = d->d_reclen;
97: /*p->d_namlen = d->d_namlen;*/
1.1.1.7 root 98: memcpy(p->d_name, d->d_name, p->d_reclen + 1);
1.1 root 99:
1.1.1.3 root 100: /*
101: * Check to make sure the array has space left and
102: * realloc the maximum size.
103: */
1.1 root 104:
1.1.1.3 root 105: if (++nitems >= arraysz) {
1.1 root 106:
1.1.1.7 root 107: if (fstat(dirfd(dirp), &stb) < 0)
1.1.1.3 root 108: return(-1); /* just might have grown */
1.1 root 109:
1.1.1.3 root 110: arraysz = stb.st_size / 12;
1.1 root 111:
1.1.1.3 root 112: names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
113: if (names == NULL)
114: return(-1);
115: }
1.1 root 116:
1.1.1.3 root 117: names[nitems-1] = p;
118: }
1.1 root 119:
1.1.1.3 root 120: closedir(dirp);
1.1 root 121:
1.1.1.3 root 122: if (nitems && dcomp != NULL)
123: qsort(names, nitems, sizeof(struct dirent *), dcomp);
1.1 root 124:
1.1.1.3 root 125: *namelist = names;
126:
1.1.1.8 ! root 127: return nitems;
1.1 root 128: }
129:
130:
1.1.1.3 root 131: #endif /* __BEOS__ */
132:
1.1 root 133:
1.1.1.2 root 134:
135: /*-----------------------------------------------------------------------*/
1.1 root 136: /*
137: Remove any '/'s from end of filenames, but keeps / intact
138: */
139: void File_CleanFileName(char *pszFileName)
140: {
1.1.1.3 root 141: int len;
142:
143: len = strlen(pszFileName);
144:
145: /* Security length check: */
1.1.1.6 root 146: if (len > FILENAME_MAX)
1.1.1.3 root 147: {
1.1.1.6 root 148: pszFileName[FILENAME_MAX-1] = 0;
149: len = FILENAME_MAX;
1.1.1.3 root 150: }
1.1 root 151:
1.1.1.2 root 152: /* Remove end slash from filename! But / remains! Doh! */
1.1.1.3 root 153: if( len>2 && pszFileName[len-1]=='/' )
154: pszFileName[len-1] = 0;
1.1 root 155: }
156:
1.1.1.2 root 157:
158: /*-----------------------------------------------------------------------*/
1.1 root 159: /*
160: Add '/' to end of filename
161: */
162: void File_AddSlashToEndFileName(char *pszFileName)
163: {
1.1.1.2 root 164: /* Check dir/filenames */
1.1.1.8 ! root 165: if (strlen(pszFileName)!=0)
! 166: {
1.1 root 167: if (pszFileName[strlen(pszFileName)-1]!='/')
1.1.1.2 root 168: strcat(pszFileName,"/"); /* Must use end slash */
1.1 root 169: }
170: }
171:
1.1.1.3 root 172:
1.1 root 173: /*-----------------------------------------------------------------------*/
174: /*
175: Does filename extension match? If so, return TRUE
176: */
1.1.1.8 ! root 177: BOOL File_DoesFileExtensionMatch(const char *pszFileName, const char *pszExtension)
1.1 root 178: {
179: if ( strlen(pszFileName) < strlen(pszExtension) )
180: return(FALSE);
181: /* Is matching extension? */
182: if ( !strcasecmp(&pszFileName[strlen(pszFileName)-strlen(pszExtension)], pszExtension) )
183: return(TRUE);
184:
185: /* No */
186: return(FALSE);
187: }
188:
1.1.1.2 root 189:
190: /*-----------------------------------------------------------------------*/
1.1 root 191: /*
192: Check if filename is from root
193:
194: Return TRUE if filename is '/', else give FALSE
195: */
196: BOOL File_IsRootFileName(char *pszFileName)
197: {
198: if (pszFileName[0]=='\0') /* If NULL string return! */
199: return(FALSE);
200:
201: if (pszFileName[0]=='/')
202: return(TRUE);
203:
204: return(FALSE);
205: }
206:
1.1.1.2 root 207:
208: /*-----------------------------------------------------------------------*/
1.1 root 209: /*
210: Return string, to remove 'C:' part of filename
211: */
1.1.1.8 ! root 212: const char *File_RemoveFileNameDrive(const char *pszFileName)
1.1 root 213: {
214: if ( (pszFileName[0]!='\0') && (pszFileName[1]==':') )
215: return(&pszFileName[2]);
216: else
217: return(pszFileName);
218: }
219:
220:
1.1.1.2 root 221: /*-----------------------------------------------------------------------*/
1.1 root 222: /*
223: Check if filename end with a '/'
224:
225: Return TRUE if filename ends with '/'
226: */
227: BOOL File_DoesFileNameEndWithSlash(char *pszFileName)
228: {
229: if (pszFileName[0]=='\0') /* If NULL string return! */
230: return(FALSE);
231:
1.1.1.3 root 232: /* Does string end in a '/'? */
1.1 root 233: if (pszFileName[strlen(pszFileName)-1]=='/')
234: return(TRUE);
235:
236: return(FALSE);
237: }
238:
1.1.1.2 root 239:
240: /*-----------------------------------------------------------------------*/
1.1 root 241: /*
242: Remove any double '/'s from end of filenames. So just the one
243: */
244: void File_RemoveFileNameTrailingSlashes(char *pszFileName)
245: {
246: int Length;
247:
248: /* Do have slash at end of filename? */
249: Length = strlen(pszFileName);
1.1.1.8 ! root 250: if (Length>=3)
! 251: {
! 252: if (pszFileName[Length-1]=='/') /* Yes, have one previous? */
! 253: {
1.1 root 254: if (pszFileName[Length-2]=='/')
255: pszFileName[Length-1] = '\0'; /* then remove it! */
256: }
257: }
258: }
259:
260:
1.1.1.2 root 261: /*-----------------------------------------------------------------------*/
1.1 root 262: /*
1.1.1.6 root 263: Read file from disc into memory, allocate memory for it if need to (pass
264: Address as NULL).
1.1 root 265: */
1.1.1.8 ! root 266: void *File_Read(char *pszFileName, void *pAddress, long *pFileSize, const char *ppszExts[])
1.1 root 267: {
1.1.1.6 root 268: void *pFile = NULL;
269: long FileSize = 0;
1.1 root 270:
271: /* Does the file exist? If not, see if can scan for other extensions and try these */
1.1.1.6 root 272: if (!File_Exists(pszFileName) && ppszExts)
273: {
1.1 root 274: /* Try other extensions, if suceeds correct filename is now in 'pszFileName' */
1.1.1.6 root 275: File_FindPossibleExtFileName(pszFileName, ppszExts);
1.1 root 276: }
277:
1.1.1.6 root 278: /* Normal file or gzipped file? */
279: if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
280: {
281: gzFile hGzFile;
282: /* Open and read gzipped file */
283: hGzFile = gzopen(pszFileName, "rb");
284: if (hGzFile != NULL)
285: {
286: /* Find size of file: */
287: do
288: {
289: /* Seek through the file until we hit the end... */
290: gzseek(hGzFile, 1024, SEEK_CUR);
291: }
292: while (!gzeof(hGzFile));
293: FileSize = gztell(hGzFile);
294: gzrewind(hGzFile);
295: /* Find pointer to where to load, allocate memory if pass NULL */
296: if (pAddress)
297: pFile = pAddress;
298: else
299: pFile = malloc(FileSize);
300: /* Read in... */
301: if (pFile)
302: gzread(hGzFile, pFile, FileSize);
1.1 root 303:
1.1.1.6 root 304: gzclose(hGzFile);
305: }
306: }
307: else
308: {
309: FILE *hDiscFile;
310: /* Open and read normal file */
311: hDiscFile = fopen(pszFileName, "rb");
312: if (hDiscFile != NULL)
313: {
314: /* Find size of file: */
315: fseek(hDiscFile, 0, SEEK_END);
316: FileSize = ftell(hDiscFile);
317: fseek(hDiscFile, 0, SEEK_SET);
318: /* Find pointer to where to load, allocate memory if pass NULL */
319: if (pAddress)
320: pFile = pAddress;
321: else
322: pFile = malloc(FileSize);
323: /* Read in... */
324: if (pFile)
325: fread(pFile, 1, FileSize, hDiscFile);
326:
327: fclose(hDiscFile);
328: }
1.1 root 329: }
1.1.1.6 root 330:
1.1.1.2 root 331: /* Store size of file we read in (or 0 if failed) */
1.1 root 332: if (pFileSize)
333: *pFileSize = FileSize;
334:
335: return(pFile); /* Return to where read in/allocated */
336: }
337:
1.1.1.2 root 338:
339: /*-----------------------------------------------------------------------*/
1.1 root 340: /*
1.1.1.6 root 341: Save file to disc, return FALSE if errors
1.1 root 342: */
1.1.1.6 root 343: BOOL File_Save(char *pszFileName, void *pAddress, size_t Size, BOOL bQueryOverwrite)
1.1 root 344: {
1.1.1.6 root 345: BOOL bRet = FALSE;
1.1 root 346:
347: /* Check if need to ask user if to overwrite */
1.1.1.6 root 348: if (bQueryOverwrite)
349: {
1.1 root 350: /* If file exists, ask if OK to overwrite */
351: if (!File_QueryOverwrite(pszFileName))
352: return(FALSE);
353: }
354:
1.1.1.6 root 355: /* Normal file or gzipped file? */
356: if (File_DoesFileExtensionMatch(pszFileName, ".gz"))
357: {
358: gzFile *hGzFile;
359: /* Create a gzipped file: */
360: hGzFile = gzopen(pszFileName, "wb");
361: if (hGzFile != NULL)
362: {
363: /* Write data, set success flag */
1.1.1.8 ! root 364: if (gzwrite(hGzFile, pAddress, Size) == (int)Size)
1.1.1.6 root 365: bRet = TRUE;
1.1 root 366:
1.1.1.6 root 367: gzclose(hGzFile);
368: }
369: }
370: else
371: {
372: FILE *hDiscFile;
373: /* Create a normal file: */
374: hDiscFile = fopen(pszFileName, "wb");
375: if (hDiscFile != NULL)
376: {
377: /* Write data, set success flag */
378: if (fwrite(pAddress, 1, Size, hDiscFile) == Size)
379: bRet = TRUE;
380:
381: fclose(hDiscFile);
382: }
1.1 root 383: }
384:
385: return(bRet);
386: }
387:
1.1.1.2 root 388:
389: /*-----------------------------------------------------------------------*/
1.1 root 390: /*
391: Return size of file, -1 if error
392: */
1.1.1.8 ! root 393: int File_Length(const char *pszFileName)
1.1 root 394: {
1.1.1.3 root 395: FILE *DiscFile;
1.1 root 396: int FileSize;
1.1.1.3 root 397: DiscFile = fopen(pszFileName, "rb");
1.1.1.8 ! root 398: if (DiscFile!=NULL)
! 399: {
1.1.1.3 root 400: fseek(DiscFile, 0, SEEK_END);
401: FileSize = ftell(DiscFile);
402: fseek(DiscFile, 0, SEEK_SET);
403: fclose(DiscFile);
1.1 root 404: return(FileSize);
405: }
406:
407: return(-1);
408: }
409:
1.1.1.2 root 410:
411: /*-----------------------------------------------------------------------*/
1.1 root 412: /*
413: Return TRUE if file exists
414: */
1.1.1.8 ! root 415: BOOL File_Exists(const char *pszFileName)
1.1 root 416: {
1.1.1.4 root 417: FILE *DiscFile;
1.1 root 418:
1.1.1.2 root 419: /* Attempt to open file */
1.1.1.4 root 420: DiscFile = fopen(pszFileName, "rb");
1.1.1.8 ! root 421: if (DiscFile!=NULL)
! 422: {
1.1.1.4 root 423: fclose(DiscFile);
1.1 root 424: return(TRUE);
1.1.1.2 root 425: }
1.1 root 426: return(FALSE);
427: }
428:
1.1.1.2 root 429:
430: /*-----------------------------------------------------------------------*/
1.1 root 431: /*
432: Find if file exists, and if so ask user if OK to overwrite
433: */
1.1.1.8 ! root 434: BOOL File_QueryOverwrite(const char *pszFileName)
1.1 root 435: {
1.1.1.7 root 436: char szString[FILENAME_MAX + 26];
1.1 root 437:
1.1.1.2 root 438: /* Try and find if file exists */
1.1.1.6 root 439: if (File_Exists(pszFileName))
440: {
1.1.1.2 root 441: /* File does exist, are we OK to overwrite? */
1.1.1.7 root 442: snprintf(szString, sizeof(szString), "File '%s' exists, overwrite?", pszFileName);
443: fprintf(stderr, "%s\n", szString);
444: return DlgAlert_Query(szString);
1.1 root 445: }
446:
447: return(TRUE);
448: }
449:
1.1.1.2 root 450:
451: /*-----------------------------------------------------------------------*/
1.1 root 452: /*
453: Try filename with various extensions and check if file exists - if so return correct name
454: */
1.1.1.8 ! root 455: BOOL File_FindPossibleExtFileName(char *pszFileName, const char *ppszExts[])
1.1 root 456: {
1.1.1.8 ! root 457: char *szSrcDir, *szSrcName, *szSrcExt;
! 458: char *szTempFileName;
! 459: int i = 0;
! 460: BOOL bFileExists = FALSE;
! 461:
! 462: /* Allocate temporary memory for strings: */
! 463: szTempFileName = malloc(4 * FILENAME_MAX);
! 464: if (!szTempFileName)
! 465: {
! 466: perror("File_FindPossibleExtFileName");
! 467: return FALSE;
! 468: }
! 469: szSrcDir = szTempFileName + FILENAME_MAX;
! 470: szSrcName = szSrcDir + FILENAME_MAX;
! 471: szSrcExt = szSrcName + FILENAME_MAX;
1.1 root 472:
1.1.1.3 root 473: /* Split filename into parts */
474: File_splitpath(pszFileName, szSrcDir, szSrcName, szSrcExt);
1.1 root 475:
1.1.1.3 root 476: /* Scan possible extensions */
1.1.1.8 ! root 477: while(ppszExts[i] && !bFileExists)
! 478: {
1.1.1.3 root 479: /* Re-build with new file extension */
480: File_makepath(szTempFileName, szSrcDir, szSrcName, ppszExts[i]);
481: /* Does this file exist? */
1.1.1.8 ! root 482: if (File_Exists(szTempFileName))
! 483: {
1.1.1.3 root 484: /* Copy name for return */
1.1.1.8 ! root 485: strcpy(pszFileName, szTempFileName);
! 486: bFileExists = TRUE;
1.1 root 487: }
488:
1.1.1.3 root 489: /* Next one */
1.1 root 490: i++;
491: }
1.1.1.3 root 492:
1.1.1.8 ! root 493: free(szTempFileName);
! 494:
! 495: return bFileExists;
1.1 root 496: }
1.1.1.3 root 497:
498:
499: /*-----------------------------------------------------------------------*/
500: /*
501: Split a complete filename into path, filename and extension.
502: If pExt is NULL, don't split the extension from the file name!
503: */
1.1.1.8 ! root 504: void File_splitpath(const char *pSrcFileName, char *pDir, char *pName, char *pExt)
1.1.1.3 root 505: {
506: char *ptr1, *ptr2;
507:
508: /* Build pathname: */
509: ptr1 = strrchr(pSrcFileName, '/');
510: if( ptr1 )
511: {
512: strcpy(pDir, pSrcFileName);
513: strcpy(pName, ptr1+1);
514: pDir[ptr1-pSrcFileName+1] = 0;
515: }
516: else
517: {
518: strcpy(pDir, "./");
519: strcpy(pName, pSrcFileName);
520: }
521:
522: /* Build the raw filename: */
523: if( pExt!=NULL )
524: {
525: ptr2 = strrchr(pName+1, '.');
526: if( ptr2 )
527: {
528: pName[ptr2-pName] = 0;
529: /* Copy the file extension: */
530: strcpy(pExt, ptr2+1);
531: }
532: else
533: pExt[0] = 0;
534: }
535: }
536:
537:
538: /*-----------------------------------------------------------------------*/
539: /*
540: Build a complete filename from path, filename and extension.
541: pExt can also be NULL.
542: */
1.1.1.8 ! root 543: void File_makepath(char *pDestFileName, const char *pDir, const char *pName, const char *pExt)
1.1.1.3 root 544: {
545: strcpy(pDestFileName, pDir);
546: if( strlen(pDestFileName)==0 )
547: strcpy(pDestFileName, "./");
548: if( pDestFileName[strlen(pDestFileName)-1]!='/' )
549: strcat(pDestFileName, "/");
550:
551: strcat(pDestFileName, pName);
552:
553: if( pExt!=NULL )
554: {
555: if( strlen(pExt)>0 && pExt[0]!='.' )
556: strcat(pDestFileName, ".");
557: strcat(pDestFileName, pExt);
558: }
559: }
560:
561:
562: /*-----------------------------------------------------------------------*/
563: /*
564: Shrink a file name to a certain length and insert some dots if we cut
565: something away (usefull for showing file names in a dialog).
566: */
567: void File_ShrinkName(char *pDestFileName, char *pSrcFileName, int maxlen)
568: {
569: int srclen = strlen(pSrcFileName);
570: if( srclen<maxlen )
571: strcpy(pDestFileName, pSrcFileName); /* It fits! */
572: else
573: {
574: strncpy(pDestFileName, pSrcFileName, maxlen/2);
575: if(maxlen&1) /* even or uneven? */
576: pDestFileName[maxlen/2-1] = 0;
577: else
578: pDestFileName[maxlen/2-2] = 0;
579: strcat(pDestFileName, "...");
580: strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]);
581: }
582: }
583:
1.1.1.6 root 584:
585: /*-----------------------------------------------------------------------*/
586: /*
587: Create a clean absolute file name from a (possibly) relative file name.
588: I.e. filter out all occurancies of "./" and "../".
589: pFileName needs to point to a buffer of at least FILENAME_MAX bytes.
590: */
591: void File_MakeAbsoluteName(char *pFileName)
592: {
1.1.1.8 ! root 593: char *pTempName;
1.1.1.6 root 594: int inpos, outpos;
595:
596: inpos = 0;
1.1.1.8 ! root 597: pTempName = malloc(FILENAME_MAX);
! 598: if (!pTempName)
! 599: {
! 600: perror("File_MakeAbsoluteName - malloc");
! 601: return;
! 602: }
1.1.1.6 root 603:
604: /* Is it already an absolute name? */
605: if(pFileName[0] == '/')
606: {
607: outpos = 0;
608: }
609: else
610: {
1.1.1.8 ! root 611: if (!getcwd(pTempName, FILENAME_MAX))
! 612: {
! 613: perror("File_MakeAbsoluteName - getcwd");
! 614: free(pTempName);
! 615: return;
! 616: }
1.1.1.6 root 617: File_AddSlashToEndFileName(pTempName);
618: outpos = strlen(pTempName);
619: }
620:
621: /* Now filter out the relative paths "./" and "../" */
622: while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
623: {
624: if (pFileName[inpos] == '.' && pFileName[inpos+1] == '/')
625: {
626: /* Ignore "./" */
627: inpos += 2;
628: }
629: else if (pFileName[inpos] == '.' && pFileName[inpos+1] == '.' && pFileName[inpos+2] == '/')
630: {
631: /* Handle "../" */
632: char *pSlashPos;
633: inpos += 3;
634: pTempName[outpos - 1] = 0;
635: pSlashPos = strrchr(pTempName, '/');
636: if (pSlashPos)
637: {
638: *(pSlashPos + 1) = 0;
639: outpos = strlen(pTempName);
640: }
641: else
642: {
643: pTempName[0] = '/';
644: outpos = 1;
645: }
646: }
647: else
648: {
649: /* Copy until next slash or end of input string */
650: while (pFileName[inpos] != 0 && outpos < FILENAME_MAX)
651: {
652: pTempName[outpos++] = pFileName[inpos++];
653: if (pFileName[inpos - 1] == '/') break;
654: }
655: }
656: }
657:
658: pTempName[outpos] = 0;
659:
660: strcpy(pFileName, pTempName); /* Copy back */
1.1.1.8 ! root 661: free(pTempName);
! 662: }
! 663:
! 664:
! 665: /*-----------------------------------------------------------------------*/
! 666: /*
! 667: Create a valid path name from a possibly invalid name by erasing invalid
! 668: path parts at the end of the string.
! 669: pPathName needs to point to a buffer of at least FILENAME_MAX bytes.
! 670: */
! 671: void File_MakeValidPathName(char *pPathName)
! 672: {
! 673: struct stat dirstat;
! 674: char *pLastSlash;
! 675:
! 676: do
! 677: {
! 678: /* Check for a valid path */
! 679: if (stat(pPathName, &dirstat) == 0 && S_ISDIR(dirstat.st_mode))
! 680: {
! 681: break;
! 682: }
! 683:
! 684: pLastSlash = strrchr(pPathName, '/');
! 685: if (pLastSlash)
! 686: {
! 687: /* Erase the (probably invalid) part after the last slash */
! 688: *pLastSlash = 0;
! 689: }
! 690: else
! 691: {
! 692: /* Path name seems to be completely invalid -> set to root directory */
! 693: strcpy(pPathName, "/");
! 694: }
! 695: }
! 696: while (pLastSlash);
1.1.1.6 root 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.