static const zip_file_header *zip_file_seek_file(zip_file *zip, const char *filename) { const zip_file_header *header; char *new_filename; int i; // we need to change filename; allocate a copy new_filename = (char*)malloc(strlen(filename) + 1); if (!new_filename) return NULL; // change all backslashes to forward slashes for (i = 0; filename[i]; i++) new_filename[i] = (filename[i] != '\\') ? filename[i] : '/'; new_filename[i] = '\0'; // find the entry header = zip_file_first_file(zip); while(header && mame_stricmp(header->filename, new_filename)) { header = zip_file_next_file(zip); } free(new_filename); return header; }
static BOOL SoftwarePicker_InternalAddFile(HWND hwndPicker, LPCSTR pszFilename, BOOL bForce) { LPCSTR s; BOOL rc = TRUE; zip_error ziperr; zip_file *pZip; const zip_file_header *pZipEnt; s = strrchr(pszFilename, '.'); if (s && !mame_stricmp(s, ".zip")) { ziperr = zip_file_open(pszFilename, &pZip); if (ziperr == ZIPERR_NONE) { pZipEnt = zip_file_first_file(pZip); while(rc && pZipEnt) { rc = SoftwarePicker_AddZipEntFile(hwndPicker, pszFilename, bForce, pZip, pZipEnt); pZipEnt = zip_file_next_file(pZip); } zip_file_close(pZip); } } else { rc = SoftwarePicker_AddFileEntry(hwndPicker, pszFilename, 0, 0, bForce); } return rc; }
static imgtool_stream *stream_open_zip(const char *zipname, const char *subname, int read_or_write) { imgtool_stream *imgfile = NULL; // zip_error ziperr; zip_file *z = NULL; const zip_file_header *zipent; FILE *f; if (read_or_write) goto error; /* check to see if the file exists */ f = fopen(zipname, "r"); if (!f) goto error; fclose(f); imgfile = (imgtool_stream *)malloc(sizeof(imgtool_stream)); if (!imgfile) goto error; memset(imgfile, 0, sizeof(*imgfile)); imgfile->imgtype = IMG_MEM; imgfile->write_protect = 1; imgfile->position = 0; // ziperr = zip_file_open(zipname, &z); if (!z) goto error; zipent = zip_file_first_file(z); while(zipent && subname && strcmp(subname, zipent->filename)) zipent = zip_file_next_file(z); if (!zipent) goto error; imgfile->filesize = zipent->uncompressed_length; imgfile->u.buffer = (UINT8*)malloc(zipent->uncompressed_length); if (!imgfile->u.buffer) goto error; if (zip_file_decompress(z, imgfile->u.buffer, zipent->uncompressed_length)) goto error; zip_file_close(z); return imgfile; error: if (z) zip_file_close(z); if (imgfile) { if (imgfile->u.buffer) free(imgfile->u.buffer); free(imgfile); } return NULL; }
static void romident(const char *filename, romident_status *status) { osd_directory *directory; /* reset the status */ memset(status, 0, sizeof(*status)); /* first try to open as a directory */ directory = osd_opendir(filename); if (directory != NULL) { const osd_directory_entry *entry; /* iterate over all files in the directory */ while ((entry = osd_readdir(directory)) != NULL) if (entry->type == ENTTYPE_FILE) { astring *curfile = astring_assemble_3(astring_alloc(), filename, PATH_SEPARATOR, entry->name); identify_file(astring_c(curfile), status); astring_free(curfile); } osd_closedir(directory); } /* if that failed, and the filename ends with .zip, identify as a ZIP file */ else if (core_filename_ends_with(filename, ".zip")) { /* first attempt to examine it as a valid ZIP file */ zip_file *zip = NULL; zip_error ziperr = zip_file_open(filename, &zip); if (ziperr == ZIPERR_NONE && zip != NULL) { const zip_file_header *entry; /* loop over entries in the ZIP, skipping empty files and directories */ for (entry = zip_file_first_file(zip); entry; entry = zip_file_next_file(zip)) if (entry->uncompressed_length != 0) { UINT8 *data = (UINT8 *)malloc(entry->uncompressed_length); if (data != NULL) { /* decompress data into RAM and identify it */ ziperr = zip_file_decompress(zip, data, entry->uncompressed_length); if (ziperr == ZIPERR_NONE) identify_data(entry->filename, data, entry->uncompressed_length, status); free(data); } } /* close up */ zip_file_close(zip); } } /* otherwise, identify as a raw file */ else identify_file(filename, status); }
static const zip_file_header *find_file(zip_file *zip, const char *filename) { const zip_file_header *header; for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip)) { if (!core_stricmp(header->filename, filename)) return header; } return NULL; }
static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const char *subpath, osd_dir_entry_type *type) { int i, j; char c1, c2, last_char; const zip_file_header *header; for (header = zip_file_first_file(zipfile); header != NULL; header = zip_file_next_file(zipfile)) { /* special case */ if (subpath == NULL) { if (type != NULL) *type = ENTTYPE_FILE; return header; } i = 0; j = 0; last_char = '/'; while(((c1 = next_path_char(header->filename, &i)) == (c2 = next_path_char(subpath, &j))) && ( c1 != '\0' && c2 != '\0' )) last_char = c2; if (c2 == '\0') { if (c1 == '\0') { if (type != NULL) *type = ENTTYPE_FILE; return header; } else if ((last_char == '/') || (c1 == '/')) { if (type != NULL) *type = ENTTYPE_DIR; return header; } } } if (type != NULL) *type = ENTTYPE_NONE; return NULL; }
static const zip_file_header *find_file_crc(zip_file *zip, const char *filename, UINT32 crc) { const zip_file_header *header; for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip)) { // if the CRC and name both match, we're good // if the CRC matches and the name doesn't, we're still good if ((!core_stricmp(header->filename, filename)) && (header->crc == crc)) { return header; } else if (header->crc == crc) { return header; } } return NULL; }
static imgtool_stream *stream_open_zip(const char *zipname, const char *subname, int read_or_write) { if (read_or_write) return nullptr; /* check to see if the file exists */ FILE *f = fopen(zipname, "r"); if (!f) return nullptr; fclose(f); imgtool_stream::ptr imgfile(new imgtool_stream(true)); imgfile->imgtype = IMG_MEM; zip_file *z = nullptr; const zip_file_header *zipent = nullptr; zip_file_open(zipname, &z); if (!z) goto error; zipent = zip_file_first_file(z); while (zipent && subname && strcmp(subname, zipent->filename)) zipent = zip_file_next_file(z); if (!zipent) goto error; imgfile->filesize = zipent->uncompressed_length; imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(zipent->uncompressed_length)); if (!imgfile->buffer) goto error; if (zip_file_decompress(z, imgfile->buffer, zipent->uncompressed_length)) goto error; zip_file_close(z); return imgfile.release(); error: if (z) zip_file_close(z); return nullptr; }
file_error emu_file::attempt_zipped() { astring filename; // loop over directory parts up to the start of filename while (1) { // find the final path separator int dirsep = m_fullpath.rchr(0, PATH_SEPARATOR[0]); if (dirsep == -1) return FILERR_NOT_FOUND; // insert the part from the right of the separator into the head of the filename if (filename.len() > 0) filename.ins(0, "/"); filename.inssubstr(0, m_fullpath, dirsep + 1, -1); // remove this part of the filename and append a .zip extension m_fullpath.substr(0, dirsep).cat(".zip"); // attempt to open the ZIP file zip_file *zip; zip_error ziperr = zip_file_open(m_fullpath, &zip); // chop the .zip back off the filename before continuing m_fullpath.substr(0, dirsep); // if we failed to open this file, continue scanning if (ziperr != ZIPERR_NONE) continue; // see if we can find a file with the right name and (if available) crc const zip_file_header *header; for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip)) if (zip_filename_match(*header, filename) && (!(m_openflags & OPEN_FLAG_HAS_CRC) || header->crc == m_crc)) break; // if that failed, look for a file with the right crc, but the wrong filename if (header == NULL && (m_openflags & OPEN_FLAG_HAS_CRC)) for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip)) if (header->crc == m_crc && !zip_header_is_path(*header)) break; // if that failed, look for a file with the right name; reporting a bad checksum // is more helpful and less confusing than reporting "rom not found" if (header == NULL) for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip)) if (zip_filename_match(*header, filename)) break; // if we got it, read the data if (header != NULL) { m_zipfile = zip; m_ziplength = header->uncompressed_length; // build a hash with just the CRC m_hashes.reset(); m_hashes.add_crc(header->crc); return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? FILERR_NONE : load_zipped_file(); } // close up the ZIP file and try the next level zip_file_close(zip); } }
const osd_directory_entry *zippath_readdir(zippath_directory *directory) { const osd_directory_entry *result = NULL; const zip_file_header *header; const char *relpath; const char *separator; const char *s; zippath_returned_directory *rdent; if (!directory->returned_parent) { /* first thing's first - return parent directory */ directory->returned_parent = true; memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = ".."; directory->returned_entry.type = ENTTYPE_DIR; result = &directory->returned_entry; } else if (directory->directory != NULL) { /* a normal directory read */ do { result = osd_readdir(directory->directory); } while((result != NULL) && (!strcmp(result->name, ".") || !strcmp(result->name, ".."))); /* special case - is this entry a ZIP file? if so we need to return it as a "directory" */ if ((result != NULL) && is_zip_file(result->name)) { /* copy; but change the entry type */ directory->returned_entry = *result; directory->returned_entry.type = ENTTYPE_DIR; result = &directory->returned_entry; } } else if (directory->zipfile != NULL) { do { /* a zip file read */ do { if (!directory->called_zip_first) header = zip_file_first_file(directory->zipfile); else header = zip_file_next_file(directory->zipfile); directory->called_zip_first = true; relpath = NULL; } while((header != NULL) && ((relpath = get_relative_path(directory, header)) == NULL)); if (relpath != NULL) { /* we've found a ZIP entry; but this may be an entry deep within the target directory */ for (s = relpath; *s && !is_zip_file_separator(*s); s++) ; separator = *s ? s : NULL; if (separator != NULL) { /* a nested entry; loop through returned_dirlist to see if we've returned the parent directory */ for (rdent = directory->returned_dirlist; rdent != NULL; rdent = rdent->next) { if (!core_strnicmp(rdent->name.c_str(), relpath, separator - relpath)) break; } if (rdent == NULL) { /* we've found a new directory; add this to returned_dirlist */ rdent = new zippath_returned_directory; rdent->next = directory->returned_dirlist; rdent->name.assign(relpath, separator - relpath); directory->returned_dirlist = rdent; /* ...and return it */ memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = rdent->name.c_str(); directory->returned_entry.type = ENTTYPE_DIR; result = &directory->returned_entry; } } else { /* a real file */ memset(&directory->returned_entry, 0, sizeof(directory->returned_entry)); directory->returned_entry.name = relpath; directory->returned_entry.type = ENTTYPE_FILE; directory->returned_entry.size = header->uncompressed_length; result = &directory->returned_entry; } } } while((relpath != NULL) && (result == NULL)); } return result; }
static image_error_t load_zip_path(mess_image *image, const char *path) { image_error_t err = IMAGE_ERROR_FILENOTFOUND; zip_file *zip = NULL; zip_error ziperr; const zip_file_header *header; const char *zip_extension = ".zip"; char *path_copy; const char *zip_entry; void *ptr; int pos; /* create our own copy of the path */ path_copy = mame_strdup(path); if (!path_copy) { err = IMAGE_ERROR_OUTOFMEMORY; goto done; } /* loop through the path and try opening zip files */ ziperr = ZIPERR_FILE_ERROR; zip_entry = NULL; pos = strlen(path_copy); while(pos > strlen(zip_extension)) { /* is this a potential zip path? */ if ((path_copy[pos] == '\0') || !strncmp(&path_copy[pos], PATH_SEPARATOR, strlen(PATH_SEPARATOR))) { /* parse out the zip path */ if (path_copy[pos] == '\0') { /* no zip path */ zip_entry = NULL; } else { /* we are at a zip path */ path_copy[pos] = '\0'; zip_entry = &path_copy[pos + strlen(PATH_SEPARATOR)]; } /* try to open the zip file */ ziperr = zip_file_open(path_copy, &zip); if (ziperr != ZIPERR_FILE_ERROR) break; /* restore the path if we changed */ if (zip_entry) path_copy[pos] = PATH_SEPARATOR[0]; } pos--; } /* did we succeed in opening up a zip file? */ if (ziperr == ZIPERR_NONE) { /* iterate through the zip file */ header = zip_file_first_file(zip); /* if we specified a zip partial path, find it */ if (zip_entry) { while(header) { if (!mame_stricmp(header->filename, zip_entry)) break; header = zip_file_next_file(zip); } } /* were we successful? */ if (header) { /* if no zip path was specified, we have to change the name */ if (!zip_entry) { /* use the first entry; tough part is we have to change the name */ err = set_image_filename(image, image->name, header->filename); if (err) goto done; } /* allocate space for this zip file */ ptr = image_malloc(image, header->uncompressed_length); if (!ptr) { err = IMAGE_ERROR_OUTOFMEMORY; goto done; } ziperr = zip_file_decompress(zip, ptr, header->uncompressed_length); if (ziperr == ZIPERR_NONE) { /* success! */ err = IMAGE_ERROR_SUCCESS; image->ptr = ptr; image->length = header->uncompressed_length; } } } done: if (path_copy) free(path_copy); if (zip) zip_file_close(zip); return err; }
const zip_file_header *zip_file_first_file(zip_file *zip) { /* reset the position and go from there */ zip->cd_pos = 0; return zip_file_next_file(zip); }