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

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   common file access
                      5: */
                      6: 
                      7: #include <sys/types.h>
                      8: #include <sys/stat.h>
                      9: #include <fcntl.h>
                     10: 
                     11: #include "main.h"
                     12: #include "dialog.h"
                     13: #include "file.h"
                     14: #include "floppy.h"
                     15: #include "createBlankImage.h"
                     16: #include "memAlloc.h"
                     17: #include "misc.h"
                     18: 
                     19: 
1.1.1.3 ! root       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: 
1.1       root       32: 
                     33: /*-----------------------------------------------------------------------*/
                     34: /*
1.1.1.3 ! root       35:   Alphabetic order comparison routine for those who want it.
1.1       root       36: */
1.1.1.3 ! root       37: int alphasort(const void *d1, const void *d2)
1.1       root       38: {
1.1.1.3 ! root       39:   return(strcmp((*(struct dirent **)d1)->d_name, (*(struct dirent **)d2)->d_name));
        !            40: }
1.1       root       41: 
                     42: 
1.1.1.3 ! root       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;
1.1       root       54: 
1.1.1.3 ! root       55:   if ((dirp = opendir(dirname)) == NULL)
        !            56:     return(-1);
1.1       root       57: 
1.1.1.3 ! root       58:   if (fstat(dirp->fd, &stb) < 0)
        !            59:     return(-1);
1.1       root       60: 
1.1.1.3 ! root       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);
1.1       root       66: 
1.1.1.3 ! root       67:   names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
        !            68:   if (names == NULL)
        !            69:     return(-1);
1.1       root       70: 
1.1.1.3 ! root       71:   nitems = 0;
1.1       root       72: 
1.1.1.3 ! root       73:   while ((d = readdir(dirp)) != NULL) {
1.1       root       74: 
1.1.1.3 ! root       75:      if (select != NULL && !(*select)(d))
        !            76:        continue;       /* just selected names */
1.1       root       77: 
1.1.1.3 ! root       78:      /*
        !            79:       * Make a minimum size copy of the data
        !            80:       */
1.1       root       81: 
1.1.1.3 ! root       82:      p = (struct dirent *)malloc(DIRSIZ(d));
        !            83:      if (p == NULL)
        !            84:        return(-1);
1.1       root       85: 
1.1.1.3 ! root       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);
1.1       root       90: 
1.1.1.3 ! root       91:      /*
        !            92:       * Check to make sure the array has space left and
        !            93:       * realloc the maximum size.
        !            94:       */
1.1       root       95: 
1.1.1.3 ! root       96:      if (++nitems >= arraysz) {
1.1       root       97: 
1.1.1.3 ! root       98:        if (fstat(dirp->fd, &stb) < 0)
        !            99:          return(-1);     /* just might have grown */
1.1       root      100: 
1.1.1.3 ! root      101:        arraysz = stb.st_size / 12;
1.1       root      102: 
1.1.1.3 ! root      103:        names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
        !           104:        if (names == NULL)
        !           105:          return(-1);
        !           106:      }
1.1       root      107: 
1.1.1.3 ! root      108:      names[nitems-1] = p;
        !           109:    }
1.1       root      110: 
1.1.1.3 ! root      111:    closedir(dirp);
1.1       root      112: 
1.1.1.3 ! root      113:    if (nitems && dcomp != NULL)
        !           114:      qsort(names, nitems, sizeof(struct dirent *), dcomp);
1.1       root      115: 
1.1.1.3 ! root      116:    *namelist = names;
        !           117: 
        !           118:    return(nitems);
1.1       root      119: }
                    120: 
                    121: 
1.1.1.3 ! root      122: #endif /* __BEOS__ */
        !           123: 
1.1       root      124: 
1.1.1.2   root      125: 
                    126: /*-----------------------------------------------------------------------*/
1.1       root      127: /*
                    128:   Remove any '/'s from end of filenames, but keeps / intact
                    129: */
                    130: void File_CleanFileName(char *pszFileName)
                    131: {
1.1.1.3 ! root      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:   }
1.1       root      142: 
1.1.1.2   root      143:   /* Remove end slash from filename! But / remains! Doh! */
1.1.1.3 ! root      144:   if( len>2 && pszFileName[len-1]=='/' )
        !           145:     pszFileName[len-1] = 0;
1.1       root      146: }
                    147: 
1.1.1.2   root      148: 
                    149: /*-----------------------------------------------------------------------*/
1.1       root      150: /*
                    151:   Add '/' to end of filename
                    152: */
                    153: void File_AddSlashToEndFileName(char *pszFileName)
                    154: {
1.1.1.2   root      155:   /* Check dir/filenames */
1.1       root      156:   if (strlen(pszFileName)!=0) {
                    157:     if (pszFileName[strlen(pszFileName)-1]!='/')
1.1.1.2   root      158:       strcat(pszFileName,"/");  /* Must use end slash */
1.1       root      159:   }
                    160: }
                    161: 
1.1.1.3 ! root      162: 
1.1       root      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: 
1.1.1.2   root      179: 
                    180: /*-----------------------------------------------------------------------*/
1.1       root      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: 
1.1.1.2   root      197: 
                    198: /*-----------------------------------------------------------------------*/
1.1       root      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: 
1.1.1.2   root      211: /*-----------------------------------------------------------------------*/
1.1       root      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: 
1.1.1.3 ! root      222:   /* Does string end in a '/'? */
1.1       root      223:   if (pszFileName[strlen(pszFileName)-1]=='/')
                    224:     return(TRUE);
                    225: 
                    226:   return(FALSE);
                    227: }
                    228: 
1.1.1.2   root      229: 
                    230: /*-----------------------------------------------------------------------*/
1.1       root      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: 
1.1.1.2   root      249: /*-----------------------------------------------------------------------*/
1.1       root      250: /*
                    251:   Does filename end with a .MSA extension? If so, return TRUE
                    252: */
                    253: BOOL File_FileNameIsMSA(char *pszFileName)
                    254: {
                    255:   return(File_DoesFileExtensionMatch(pszFileName,".msa"));
                    256: }
                    257: 
1.1.1.2   root      258: 
                    259: /*-----------------------------------------------------------------------*/
1.1       root      260: /*
                    261:   Does filename end with a .ST extension? If so, return TRUE
                    262: */
                    263: BOOL File_FileNameIsST(char *pszFileName)
                    264: {
                    265:   return(File_DoesFileExtensionMatch(pszFileName,".st"));
                    266: }
                    267: 
                    268: 
1.1.1.2   root      269: /*-----------------------------------------------------------------------*/
1.1       root      270: /*
1.1.1.2   root      271:   Read file from PC into memory, allocate memory for it if need to (pass Address as NULL)
                    272:   Also may pass 'unsigned long' if want to find size of file read (may pass as NULL)
1.1       root      273: */
                    274: void *File_Read(char *pszFileName, void *pAddress, long *pFileSize, char *ppszExts[])
                    275: {
1.1.1.2   root      276:   FILE *DiscFile;
1.1       root      277:   void *pFile=NULL;
                    278:   long FileSize=0;
                    279: 
                    280:   /* Does the file exist? If not, see if can scan for other extensions and try these */
                    281:   if (!File_Exists(pszFileName) && ppszExts) {
                    282:     /* Try other extensions, if suceeds correct filename is now in 'pszFileName' */
                    283:     File_FindPossibleExtFileName(pszFileName,ppszExts);
                    284:   }
                    285: 
                    286:   /* Open our file */
1.1.1.2   root      287:   DiscFile = fopen(pszFileName, "rb");
                    288:   if (DiscFile!=NULL) {
1.1       root      289:     /* Find size of TOS image - 192k or 256k */
1.1.1.2   root      290:     fseek(DiscFile, 0, SEEK_END);
                    291:     FileSize = ftell(DiscFile);
                    292:     fseek(DiscFile, 0, SEEK_SET);
1.1       root      293:     /* Find pointer to where to load, allocate memory if pass NULL */
                    294:     if (pAddress)
                    295:       pFile = pAddress;
                    296:     else
                    297:       pFile = Memory_Alloc(FileSize);
                    298:     /* Read in... */
                    299:     if (pFile)
1.1.1.2   root      300:       fread((char *)pFile, 1, FileSize, DiscFile);
1.1       root      301: 
1.1.1.2   root      302:     fclose(DiscFile);
1.1       root      303:   }
1.1.1.2   root      304:   /* Store size of file we read in (or 0 if failed) */
1.1       root      305:   if (pFileSize)
                    306:     *pFileSize = FileSize;
                    307: 
                    308:   return(pFile);        /* Return to where read in/allocated */
                    309: }
                    310: 
1.1.1.2   root      311: 
                    312: /*-----------------------------------------------------------------------*/
1.1       root      313: /*
                    314:   Save file to PC, return FALSE if errors
                    315: */
                    316: BOOL File_Save(char *pszFileName, void *pAddress,long Size,BOOL bQueryOverwrite)
                    317: {
1.1.1.2   root      318:   FILE *DiscFile;
1.1       root      319:   BOOL bRet=FALSE;
                    320: 
                    321:   /* Check if need to ask user if to overwrite */
                    322:   if (bQueryOverwrite) {
                    323:     /* If file exists, ask if OK to overwrite */
                    324:     if (!File_QueryOverwrite(pszFileName))
                    325:       return(FALSE);
                    326:   }
                    327: 
                    328:   /* Create our file */
1.1.1.2   root      329:   DiscFile = fopen(pszFileName, "wb");
                    330:   if (DiscFile!=NULL) {
1.1       root      331:     /* Write data, set success flag */
1.1.1.2   root      332:     if ( fwrite(pAddress, 1, Size, DiscFile)==Size )
1.1       root      333:       bRet = TRUE;
                    334: 
1.1.1.2   root      335:     fclose(DiscFile);
1.1       root      336:   }
                    337: 
                    338:   return(bRet);
                    339: }
                    340: 
1.1.1.2   root      341: 
                    342: /*-----------------------------------------------------------------------*/
1.1       root      343: /*
                    344:   Return size of file, -1 if error
                    345: */
                    346: int File_Length(char *pszFileName)
                    347: {
1.1.1.3 ! root      348:   FILE *DiscFile;
1.1       root      349:   int FileSize;
1.1.1.3 ! root      350:   DiscFile = fopen(pszFileName, "rb");
        !           351:   if (DiscFile!=NULL) {
        !           352:     fseek(DiscFile, 0, SEEK_END);
        !           353:     FileSize = ftell(DiscFile);
        !           354:     fseek(DiscFile, 0, SEEK_SET);
        !           355:     fclose(DiscFile);
1.1       root      356:     return(FileSize);
                    357:   }
                    358: 
                    359:   return(-1);
                    360: }
                    361: 
1.1.1.2   root      362: 
                    363: /*-----------------------------------------------------------------------*/
1.1       root      364: /*
                    365:   Return TRUE if file exists
                    366: */
                    367: BOOL File_Exists(char *pszFileName)
                    368: {
                    369:   int DiscFile;
                    370: 
1.1.1.2   root      371:   /* Attempt to open file */
1.1       root      372:   DiscFile = open(pszFileName, O_RDONLY);
1.1.1.2   root      373:   if (DiscFile!=-1) {
                    374:     close(DiscFile);
1.1       root      375:     return(TRUE);
1.1.1.2   root      376:   }
1.1       root      377:   return(FALSE);
                    378: }
                    379: 
1.1.1.2   root      380: 
                    381: /*-----------------------------------------------------------------------*/
1.1       root      382: /*
                    383:   Delete file, return TRUE if OK
                    384: */
                    385: BOOL File_Delete(char *pszFileName)
                    386: {
1.1.1.2   root      387:   /* Delete the file (must be closed first) */
1.1       root      388:   return( remove(pszFileName) );
                    389: }
                    390: 
1.1.1.2   root      391: 
                    392: /*-----------------------------------------------------------------------*/
1.1       root      393: /*
                    394:   Find if file exists, and if so ask user if OK to overwrite
                    395: */
1.1.1.2   root      396: BOOL File_QueryOverwrite(char *pszFileName)
1.1       root      397: {
                    398: 
                    399:   char szString[MAX_FILENAME_LENGTH];
                    400: 
1.1.1.2   root      401:   /* Try and find if file exists */
1.1       root      402:   if (File_Exists(pszFileName)) {
1.1.1.2   root      403:     /* File does exist, are we OK to overwrite? */
1.1       root      404:     sprintf(szString,"File '%s' exists, overwrite?",pszFileName);
                    405: /* FIXME: */
                    406: //    if (MessageBox(hWnd,szString,PROG_NAME,MB_YESNO | MB_DEFBUTTON2 | MB_ICONSTOP)==IDNO)
                    407: //      return(FALSE);
                    408:   }
                    409: 
                    410:   return(TRUE);
                    411: }
                    412: 
1.1.1.2   root      413: 
                    414: /*-----------------------------------------------------------------------*/
1.1       root      415: /*
                    416:   Try filename with various extensions and check if file exists - if so return correct name
                    417: */
1.1.1.3 ! root      418: BOOL File_FindPossibleExtFileName(char *pszFileName, char *ppszExts[])
1.1       root      419: {
1.1.1.3 ! root      420:   char szSrcDir[256], szSrcName[128], szSrcExt[32];
1.1       root      421:   char szTempFileName[MAX_FILENAME_LENGTH];
                    422:   int i=0;
                    423: 
1.1.1.3 ! root      424:   /* Split filename into parts */
        !           425:   File_splitpath(pszFileName, szSrcDir, szSrcName, szSrcExt);
1.1       root      426: 
1.1.1.3 ! root      427:   /* Scan possible extensions */
1.1       root      428:   while(ppszExts[i]) {
1.1.1.3 ! root      429:     /* Re-build with new file extension */
        !           430:     File_makepath(szTempFileName, szSrcDir, szSrcName, ppszExts[i]);
        !           431:     /* Does this file exist? */
1.1       root      432:     if (File_Exists(szTempFileName)) {
1.1.1.3 ! root      433:       /* Copy name for return */
1.1       root      434:       strcpy(pszFileName,szTempFileName);
                    435:       return(TRUE);
                    436:     }
                    437: 
1.1.1.3 ! root      438:     /* Next one */
1.1       root      439:     i++;
                    440:   }
1.1.1.3 ! root      441: 
1.1.1.2   root      442:   /* No, none of the files exist */
1.1       root      443:   return(FALSE);
                    444: }
1.1.1.3 ! root      445: 
        !           446: 
        !           447: /*-----------------------------------------------------------------------*/
        !           448: /*
        !           449:   Split a complete filename into path, filename and extension.
        !           450:   If pExt is NULL, don't split the extension from the file name!
        !           451: */
        !           452: void File_splitpath(char *pSrcFileName, char *pDir, char *pName, char *pExt)
        !           453: {
        !           454:   char *ptr1, *ptr2;
        !           455: 
        !           456:   /* Build pathname: */
        !           457:   ptr1 = strrchr(pSrcFileName, '/');
        !           458:   if( ptr1 )
        !           459:   {
        !           460:     strcpy(pDir, pSrcFileName);
        !           461:     strcpy(pName, ptr1+1);
        !           462:     pDir[ptr1-pSrcFileName+1] = 0;
        !           463:   }
        !           464:   else
        !           465:   {
        !           466:     strcpy(pDir, "./");
        !           467:     strcpy(pName, pSrcFileName);
        !           468:   }
        !           469: 
        !           470:   /* Build the raw filename: */
        !           471:   if( pExt!=NULL )
        !           472:   {
        !           473:     ptr2 = strrchr(pName+1, '.');
        !           474:     if( ptr2 )
        !           475:     {
        !           476:       pName[ptr2-pName] = 0;
        !           477:       /* Copy the file extension: */
        !           478:       strcpy(pExt, ptr2+1);
        !           479:     }
        !           480:     else
        !           481:       pExt[0] = 0;
        !           482:    }
        !           483: }
        !           484: 
        !           485: 
        !           486: /*-----------------------------------------------------------------------*/
        !           487: /*
        !           488:   Build a complete filename from path, filename and extension.
        !           489:   pExt can also be NULL.
        !           490: */
        !           491: void File_makepath(char *pDestFileName, char *pDir, char *pName, char *pExt)
        !           492: {
        !           493:   strcpy(pDestFileName, pDir);
        !           494:   if( strlen(pDestFileName)==0 )
        !           495:     strcpy(pDestFileName, "./");
        !           496:   if( pDestFileName[strlen(pDestFileName)-1]!='/' )
        !           497:     strcat(pDestFileName, "/");
        !           498: 
        !           499:   strcat(pDestFileName, pName);
        !           500: 
        !           501:   if( pExt!=NULL )
        !           502:   {
        !           503:     if( strlen(pExt)>0 && pExt[0]!='.' )
        !           504:       strcat(pDestFileName, ".");
        !           505:     strcat(pDestFileName, pExt);
        !           506:   }
        !           507: }
        !           508: 
        !           509: 
        !           510: /*-----------------------------------------------------------------------*/
        !           511: /*
        !           512:   Shrink a file name to a certain length and insert some dots if we cut
        !           513:   something away (usefull for showing file names in a dialog).
        !           514: */
        !           515: void File_ShrinkName(char *pDestFileName, char *pSrcFileName, int maxlen)
        !           516: {
        !           517:   int srclen = strlen(pSrcFileName);
        !           518:   if( srclen<maxlen )
        !           519:     strcpy(pDestFileName, pSrcFileName);  /* It fits! */
        !           520:   else
        !           521:   {
        !           522:     strncpy(pDestFileName, pSrcFileName, maxlen/2);
        !           523:     if(maxlen&1)  /* even or uneven? */
        !           524:       pDestFileName[maxlen/2-1] = 0;
        !           525:     else
        !           526:       pDestFileName[maxlen/2-2] = 0;
        !           527:     strcat(pDestFileName, "...");
        !           528:     strcat(pDestFileName, &pSrcFileName[strlen(pSrcFileName)-maxlen/2+1]);
        !           529:   }
        !           530: }
        !           531: 

unix.superglobalmegacorp.com

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