void KeyValue::modify_zip_file_test() throw (KeyValueException) { if (is_zip_file()) { throw KeyValueException("A packaged file can't be modified."); } }
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; }
file_error zippath_fopen(const char *filename, UINT32 openflags, core_file *&file, std::string &revised_path) { file_error filerr = FILERR_NOT_FOUND; zip_error ziperr; zip_file *zip = NULL; const zip_file_header *header; osd_dir_entry_type entry_type; char *alloc_fullpath = NULL; int len; /* first, set up the two types of paths */ std::string mainpath(filename); std::string subpath; file = NULL; /* loop through */ while((file == NULL) && (mainpath.length() > 0) && ((openflags == OPEN_FLAG_READ) || (subpath.length() == 0))) { /* is the mainpath a ZIP path? */ if (is_zip_file(mainpath.c_str())) { /* this file might be a zip file - lets take a look */ ziperr = zip_file_open(mainpath.c_str(), &zip); if (ziperr == ZIPERR_NONE) { /* it is a zip file - error if we're not opening for reading */ if (openflags != OPEN_FLAG_READ) { filerr = FILERR_ACCESS_DENIED; goto done; } if (subpath.length() > 0) header = zippath_find_sub_path(zip, subpath.c_str(), &entry_type); else header = zip_file_first_file(zip); if (header == NULL) { filerr = FILERR_NOT_FOUND; goto done; } /* attempt to read the file */ filerr = create_core_file_from_zip(zip, header, file); if (filerr != FILERR_NONE) goto done; /* update subpath, if appropriate */ if (subpath.length() == 0) subpath.assign(header->filename); /* we're done */ goto done; } } else if (is_7z_file(mainpath.c_str())) { filerr = FILERR_INVALID_DATA; goto done; } if (subpath.length() == 0) filerr = core_fopen(filename, openflags, &file); else filerr = FILERR_NOT_FOUND; /* if we errored, then go up a directory */ if (filerr != FILERR_NONE) { /* go up a directory */ std::string temp; zippath_parent(temp, mainpath.c_str()); /* append to the sub path */ if (subpath.length() > 0) { std::string temp2; mainpath = mainpath.substr(temp.length()); temp2.assign(mainpath).append(PATH_SEPARATOR).append(subpath); subpath.assign(temp2); } else { mainpath = mainpath.substr(temp.length()); subpath.assign(mainpath); } /* get the new main path, truncating path separators */ len = temp.length(); while (len > 0 && is_zip_file_separator(temp[len - 1])) len--; temp = temp.substr(0, len); mainpath.assign(temp); } } done: /* store the revised path */ revised_path.clear(); if (filerr == FILERR_NONE) { /* cannonicalize mainpath */ filerr = osd_get_full_path(&alloc_fullpath, mainpath.c_str()); if (filerr == FILERR_NONE) { if (subpath.length() > 0) revised_path.assign(alloc_fullpath).append(PATH_SEPARATOR).append(subpath); else revised_path.assign(alloc_fullpath); } } if (zip != NULL) zip_file_close(zip); if (alloc_fullpath != NULL) osd_free(alloc_fullpath); return filerr; }
static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath) { file_error err; osd_directory_entry *current_entry = NULL; osd_dir_entry_type current_entry_type; int went_up = FALSE; int i; newpath.clear(); /* be conservative */ entry_type = ENTTYPE_NONE; zipfile = NULL; std::string apath(path); std::string apath_trimmed; do { /* trim the path of trailing path separators */ i = apath.length(); while (i > 1 && is_path_separator(apath[i - 1])) i--; apath = apath.substr(0, i); apath_trimmed.assign(apath); /* stat the path */ current_entry = osd_stat(apath_trimmed.c_str()); /* did we find anything? */ if (current_entry != NULL) { /* get the entry type and free the stat entry */ current_entry_type = current_entry->type; osd_free(current_entry); current_entry = NULL; } else { /* if we have not found the file or directory, go up */ current_entry_type = ENTTYPE_NONE; went_up = TRUE; std::string parent; apath.assign(zippath_parent(parent, apath.c_str())); } } while (current_entry_type == ENTTYPE_NONE && !is_root(apath.c_str())); /* if we did not find anything, then error out */ if (current_entry_type == ENTTYPE_NONE) { err = FILERR_NOT_FOUND; goto done; } /* is this file a ZIP file? */ if ((current_entry_type == ENTTYPE_FILE) && is_zip_file(apath_trimmed.c_str()) && (zip_file_open(apath_trimmed.c_str(), &zipfile) == ZIPERR_NONE)) { i = strlen(path + apath.length()); while (i > 0 && is_zip_path_separator(path[apath.length() + i - 1])) i--; newpath.assign(path + apath.length(), i); /* this was a true ZIP path - attempt to identify the type of path */ zippath_find_sub_path(zipfile, newpath.c_str(), ¤t_entry_type); if (current_entry_type == ENTTYPE_NONE) { err = FILERR_NOT_FOUND; goto done; } } else { /* this was a normal path */ if (went_up) { err = FILERR_NOT_FOUND; goto done; } newpath.assign(path); } /* success! */ entry_type = current_entry_type; err = FILERR_NONE; done: return err; }
struct input_file *read_file_list (int argc, char **argv, int *nf_r, char *errstr) { struct input_file *list = (struct input_file *) NULL; FILE *fp = (FILE *) NULL; char line[16384], *av, *p, *s; int a, f, nf = 0; #ifndef _WIN32 glob_t gbuf; int rv, op; /* Init */ gbuf.gl_pathv = (char **) NULL; #endif int is_zip; #ifdef ZIPSUPPORT zip_t *z = (zip_t *) NULL; zip_error_t ze; struct zip_stat sb; int zerrno; int ent, nent; const char *name; int namelen; zip_uint8_t opsys; zip_uint32_t extattr; #endif /* Loop over arguments */ for(a = 0; a < argc; a++) { av = argv[a]; if(*av == '@') { /* @list form */ av++; /* skip past the @ */ is_zip = is_zip_file(av, errstr); if(is_zip < 0) goto error; if(is_zip) { #ifdef ZIPSUPPORT z = zip_open(av, 0, &zerrno); if(!z) { zip_error_init_with_code(&ze, zerrno); report_err(errstr, "zip_open: %s: %s", av, zip_error_strerror(&ze)); zip_error_fini(&ze); goto error; } nent = zip_get_num_entries(z, 0); if(nent < 0) { report_err(errstr, "zip_get_num_entries: %s", zip_strerror(z)); goto error; } for(ent = 0; ent < nent; ent++) { if(zip_stat_index(z, ent, 0, &sb)) { report_err(errstr, "zip_stat_index(%d): %s\n", ent, zip_strerror(z)); goto error; } if(zip_file_get_external_attributes(z, ent, 0, &opsys, &extattr)) { report_err(errstr, "zip_get_external_attributes(%d): %s\n", ent, zip_strerror(z)); goto error; } name = sb.name; namelen = strlen(name); if((opsys != ZIP_OPSYS_AMIGA && extattr & 0x10) || (namelen > 0 && name[namelen-1] == '/')) /* Is directory */ continue; /* Otherwise, add to list */ list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(name); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = ent; list[nf].iarg = a; list[nf].arg = av; nf++; } if(zip_close(z)) { report_err(errstr, "zip_close: %s", zip_strerror(z)); goto error; } z = (zip_t *) NULL; #else report_err(errstr, "not compiled with zip support"); goto error; #endif } else { fp = fopen(av, "r"); if(!fp) { report_syserr(errstr, "open: %s", av); goto error; } while(fgets(line, sizeof(line), fp)) { p = sstrip(line); if(*p) { list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(p); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = -1; list[nf].iarg = a; list[nf].arg = av; nf++; } } if(ferror(fp)) { report_syserr(errstr, "read: %s", av); goto error; } fclose(fp); fp = (FILE *) NULL; } } else { /* glob or single filename */ #ifndef _WIN32 rv = glob(av, 0, NULL, &gbuf); if(rv == 0) { /* succeeded */ /* Allocate block */ list = (struct input_file *) realloc(list, (nf+gbuf.gl_pathc) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } /* Zero out the new pointers */ memset(list+nf, 0, gbuf.gl_pathc * sizeof(struct input_file)); /* Record so we know to free them */ op = nf; nf += gbuf.gl_pathc; for(f = 0; f < gbuf.gl_pathc; f++) { s = strdup(gbuf.gl_pathv[f]); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[op].filename = s; list[op].ient = -1; list[op].iarg = a; list[op].arg = av; op++; } globfree(&gbuf); gbuf.gl_pathv = (char **) NULL; } else if(rv == GLOB_NOMATCH) { /* no match */ #endif /* _WIN32 */ /* Assume it's a single entry. */ list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file)); if(!list) { report_syserr(errstr, "realloc"); goto error; } s = strdup(av); if(!s) { report_syserr(errstr, "strdup"); goto error; } list[nf].filename = s; list[nf].ient = -1; list[nf].iarg = a; list[nf].arg = av; nf++; #ifndef _WIN32 } else { report_err(errstr, "glob error: %s", av); goto error; } #endif } } *nf_r = nf; return(list); error: if(fp) fclose(fp); #ifndef _WIN32 if(gbuf.gl_pathv) globfree(&gbuf); #endif #ifdef ZIPSUPPORT if(z) { zip_close(z); z = (zip_t *) NULL; } #endif if(list) { for(f = 0; f < nf; f++) if(list[f].filename) free((void *) list[f].filename); free((void *) list); } return((struct input_file *) NULL); }