Beispiel #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);
}
Beispiel #2
0
void MDFNFILE::Open(const char *path, const FileExtensionSpecStruct *known_ext, const char *purpose)
{
    unzFile tz = NULL;

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

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

            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)
                    {
                        throw MDFN_Error(0, _("Could not get file information in ZIP archive: %s"), unzErrorString(errcode));
                    }

                    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)
                        {
                            throw MDFN_Error(0, _("Error seeking to next file in ZIP archive: %s"), unzErrorString(errcode));
                        }

                        if((errcode = unzGoToFirstFile(tz)) != UNZ_OK)
                        {
                            throw MDFN_Error(0, _("Could not seek to first file in ZIP archive: %s"), unzErrorString(errcode));
                        }
                        break;
                    }
                } // end to while(!FileFound)
            } // end to if(ext)

            if((errcode = unzOpenCurrentFile(tz)) != UNZ_OK)
            {
                throw MDFN_Error(0, _("Could not open file in ZIP archive: %s"), unzErrorString(errcode));
            }

            {
                unz_file_info ufo;
                unzGetCurrentFileInfo((unzFile)tz, &ufo, 0, 0, 0, 0, 0, 0);

                if(ufo.uncompressed_size > MaxROMImageSize)
                    throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize);

                str.reset(new MemoryStream(ufo.uncompressed_size, true));

                unzReadCurrentFile((unzFile)tz, str->map(), str->size());
            }

            // Don't use MDFN_GetFilePathComponents() here.
            {
                char* ld = strrchr(tempu, '.');

                f_ext = std::string(ld ? ld : "");
                f_fbase = std::string(tempu, ld ? (ld - tempu) : strlen(tempu));
            }
        }
        else // If it's not a zip file, handle it as...another type of file!
        {
            std::unique_ptr<Stream> tfp(new FileStream(path, FileStream::MODE_READ));

            // We'll clean up f_ext to remove the leading period, and convert to lowercase, after
            // the plain vs gzip file handling code below(since gzip handling path will want to strip off an extra extension).
            MDFN_GetFilePathComponents(path, NULL, &f_fbase, &f_ext);

            uint8 gzmagic[3] = { 0 };

            if(tfp->read(gzmagic, 3, false) != 3 || gzmagic[0] != 0x1F || gzmagic[1] != 0x8b || gzmagic[2] != 0x08)
            {
                tfp->seek(0, SEEK_SET);

                if(tfp->size() > MaxROMImageSize)
                    throw MDFN_Error(0, _("ROM image is too large; maximum size allowed is %llu bytes."), (unsigned long long)MaxROMImageSize);

                str = std::move(tfp);
            }
            else                  /* Probably gzip */
            {
                delete tfp.release();

                str.reset(new MemoryStream(new GZFileStream(path, GZFileStream::MODE::READ), MaxROMImageSize));

                MDFN_GetFilePathComponents(f_fbase, NULL, &f_fbase, &f_ext);
            } // End gzip handling
        } // End normal and gzip file handling else to zip

        // Remove leading period in file extension.
        if(f_ext.size() > 0 && f_ext[0] == '.')
            f_ext = f_ext.substr(1);

        // Convert file extension A-Z chars to lowercase, a-z
        for(auto& c : f_ext)
            if(c >= 'A' && c <= 'Z')
                c = 'a' + (c - 'A');

        //printf("|%s| --- |%s|\n", f_fbase.c_str(), f_ext.c_str());
    }
    catch(...)
    {
        if(tz != NULL)
        {
            unzCloseCurrentFile(tz);
            unzClose(tz);
        }

        Close();
        throw;
    }

    if(tz != NULL)
    {
        unzCloseCurrentFile(tz);
        unzClose(tz);
    }
}