Example #1
0
bool MDFNFILE::Open(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose, const bool suppress_notfound_pe)
{
 void *t;
 unzFile tz;

 local_errno = 0;
 error_code = MDFNFILE_EC_OTHER;	// Set to 0 at the end if the function succeeds.

 //f_data = (uint8 *)0xDEADBEEF;

 // Try opening it as a zip file first
 if((tz = unzOpen(path)))
 {
  char tempu[1024];
  int errcode;

  if((errcode = unzGoToFirstFile(tz)) != UNZ_OK)
  {
   MDFN_PrintError(_("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode));
   unzClose(tz);

   return(NULL);
  }

  if(known_ext)
  {
   bool FileFound = FALSE;
   while(!FileFound)
   {
    size_t tempu_strlen;
    const FileExtensionSpecStruct *ext_search = known_ext;

    if((errcode = unzGetCurrentFileInfo(tz, 0, tempu, 1024, 0, 0, 0, 0)) != UNZ_OK)
    {
     MDFN_PrintError(_("Could not get file information in ZIP archive: %s"), unzErrorString(errcode));
     unzClose(tz);

     return(NULL);
    }

    tempu[1023] = 0;
    tempu_strlen = strlen(tempu);

    while(ext_search->extension && !FileFound)
    {
     size_t ttmeow = strlen(ext_search->extension);
     if(tempu_strlen >= ttmeow)
     {
      if(!strcasecmp(tempu + tempu_strlen - ttmeow, ext_search->extension))
       FileFound = TRUE;
     }
     ext_search++;
    }

    if(FileFound)
     break;

    if((errcode = unzGoToNextFile(tz)) != UNZ_OK)
    { 
     if(errcode != UNZ_END_OF_LIST_OF_FILE)
     {
      MDFN_PrintError(_("Error seeking to next file in ZIP archive: %s"), unzErrorString(errcode));
      unzClose(tz);
      return(NULL);
     }

     if((errcode = unzGoToFirstFile(tz)) != UNZ_OK)
     {
      MDFN_PrintError(_("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode));
      unzClose(tz);
      return(NULL);
     }
     break;     
    }

   } // end to while(!FileFound)
  } // end to if(ext)

  if((errcode = unzOpenCurrentFile(tz)) != UNZ_OK)
  {
   MDFN_PrintError(_("Could not open file in ZIP archive: %s"), unzErrorString(errcode));
   unzClose(tz);
   return(NULL);
  }

  if(!MakeMemWrap(tz, MDFN_FILETYPE_ZIP))
   return(0);

  char *ld = strrchr(tempu, '.');

  f_ext = strdup(ld ? ld + 1 : "");
 }
 else // If it's not a zip file, handle it as...another type of file!
 {
  if(!(t = fopen(path,"rb")))
  {
   ErrnoHolder ene(errno);
   local_errno = ene.Errno();

   if(ene.Errno() == ENOENT)
   {
    local_errno = ene.Errno();
    error_code = MDFNFILE_EC_NOTFOUND;
   }
   
   if(ene.Errno() != ENOENT || !suppress_notfound_pe)
    MDFN_PrintError(_("Error opening \"%s\": %s"), path, ene.StrError());

   return(0);
  }

  uint32 gzmagic;

  gzmagic = ::fgetc((FILE *)t);
  gzmagic |= ::fgetc((FILE *)t)<<8;
  gzmagic |= ::fgetc((FILE *)t)<<16;

  if(gzmagic!=0x088b1f)   /* Not gzip... */
  {
   ::fseek((FILE *)t,0,SEEK_SET);

   if(!MakeMemWrap(t, 0))
    return(0);

   const char *ld = strrchr(path, '.');
   f_ext = strdup(ld ? ld + 1 : "");
  }
  else                  /* Probably gzip */
  {
   int fd;

   //fd = dup(fileno( (FILE *)t));
   lseek(fd, 0, SEEK_SET);

   if(!(t=gzdopen(fd, "rb")))
   {
    close(fd);
    return(0);
   }

   if(!MakeMemWrap(t, 1))
   {
    gzclose(t);
    return(0);
   }

   char *tmp_path = strdup(path);
   char *ld = strrchr(tmp_path, '.');

   if(ld && ld > tmp_path)
   {
    char *last_ld = ld;
    *ld = 0;
    ld = strrchr(tmp_path, '.');
    if(!ld) { *last_ld = '.'; ld = last_ld; }
   }
   f_ext = strdup(ld ? ld + 1 : "");
   free(tmp_path);
  } // End gzip handling
 } // End normal and gzip file handling else to zip

 // FIXME:  Handle extension fixing for cases where loaded filename is like "moo.moo/lalala"

 error_code = 0;

 return(TRUE);
}
Example #2
0
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
{
 FILE *ipsfile=0;
 FCEUFILE *fceufp;
 void *t;

 if(strchr(mode,'r'))
  ipsfile=FCEUD_UTF8fopen(ipsfn,"rb");

 fceufp=(FCEUFILE *)malloc(sizeof(FCEUFILE));

 {
  unzFile tz;
  if((tz=unzOpen(path)))  // If it's not a zip file, use regular file handlers.
			  // Assuming file type by extension usually works,
			  // but I don't like it. :)
  {
   if(unzGoToFirstFile(tz)==UNZ_OK)
   {
    for(;;)
    {
     char tempu[512];	// Longer filenames might be possible, but I don't
		 	// think people would name files that long in zip files...
     unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
     tempu[511]=0;
     if(strlen(tempu)>=4)
     {
      char *za=tempu+strlen(tempu)-4;

      if(!ext)
      {
       if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
          !strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
          !strcasecmp(za,".nez"))
        break;
      }
      else if(!strcasecmp(za,ext)) 
       break;
     }
     if(strlen(tempu)>=5)
     {
      if(!strcasecmp(tempu+strlen(tempu)-5,".unif"))
       break;
     }
     if(unzGoToNextFile(tz)!=UNZ_OK)
     { 
      if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
      break;     
     }
    }
    if(unzOpenCurrentFile(tz)!=UNZ_OK)
     goto zpfail;       
   }
   else
   {
    zpfail:
    free(fceufp);
    unzClose(tz);
    return 0;
   }
   if(!(fceufp->fp=MakeMemWrap(tz,2)))
   {
    free(fceufp);
    return(0);
   }
   fceufp->type=2;
   if(ipsfile)
    ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
   return(fceufp);
  }
 }

 if((t=FCEUD_UTF8fopen(path,"rb")))
 {
  uint32 magic;

  magic=fgetc((FILE *)t);
  magic|=fgetc((FILE *)t)<<8;
  magic|=fgetc((FILE *)t)<<16;

  if(magic!=0x088b1f)   /* Not gzip... */
   fclose((FILE *)t);
  else                  /* Probably gzip */
  {
   int fd;

   fd = dup(fileno( (FILE *)t));

   fclose(t);

   lseek(fd, 0, SEEK_SET);

   if((t=gzdopen(fd,mode)))
   {
    fceufp->type=1;
    fceufp->fp=t;
    if(ipsfile)
    {
     fceufp->fp=MakeMemWrap(t,1);
     gzclose(t);

     if(fceufp->fp)
     {
      free(fceufp);
      return(0);
     }

     fceufp->type=3;
     ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
    }
    return(fceufp);
   }
   close(fd);
  }

 }

  if((t=FCEUD_UTF8fopen(path,mode)))
  {
   fseek((FILE *)t,0,SEEK_SET);
   fceufp->type=0;
   fceufp->fp=t;
   if(ipsfile)
   {
    if(!(fceufp->fp=MakeMemWrap(t,0)))
    {
     free(fceufp);
     return(0);
    }
    fceufp->type=3;
    ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
   }
   return(fceufp);
  }

 free(fceufp);
 return 0;
}