Annotation of frontvm/hardware/file.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

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