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); }
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; }