Annotation of hatari/src/file.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.