/** * Append data to an existing session file. * * The session file must have been created with sr_session_save_init() * or sr_session_save() beforehand. * * @param filename The name of the filename to append to. Must not be NULL. * @param buf The data to be appended. * @param unitsize The number of bytes per sample. * @param units The number of samples. * * @retval SR_OK Success * @retval SR_ERR_ARG Invalid arguments * @retval SR_ERR Other errors * * @since 0.3.0 */ SR_API int sr_session_append(const char *filename, unsigned char *buf, int unitsize, int units) { struct zip *archive; struct zip_source *logicsrc; zip_int64_t num_files; struct zip_file *zf; struct zip_stat zs; struct zip_source *metasrc; GKeyFile *kf; GError *error; gsize len; int chunk_num, next_chunk_num, tmpfile, ret, i; const char *entry_name; char *metafile, tmpname[32], chunkname[16]; if ((ret = sr_sessionfile_check(filename)) != SR_OK) return ret; if (!(archive = zip_open(filename, 0, &ret))) return SR_ERR; if (zip_stat(archive, "metadata", 0, &zs) == -1) return SR_ERR; metafile = g_malloc(zs.size); zf = zip_fopen_index(archive, zs.index, 0); zip_fread(zf, metafile, zs.size); zip_fclose(zf); /* * If the file was only initialized but doesn't yet have any * data it in, it won't have a unitsize field in metadata yet. */ error = NULL; kf = g_key_file_new(); if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, &error)) { sr_err("Failed to parse metadata: %s.", error->message); return SR_ERR; } g_free(metafile); tmpname[0] = '\0'; if (!g_key_file_has_key(kf, "device 1", "unitsize", &error)) { if (error && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) { sr_err("Failed to check unitsize key: %s", error ? error->message : "?"); return SR_ERR; } /* Add unitsize field. */ g_key_file_set_integer(kf, "device 1", "unitsize", unitsize); metafile = g_key_file_to_data(kf, &len, &error); strcpy(tmpname, "sigrok-meta-XXXXXX"); if ((tmpfile = g_mkstemp(tmpname)) == -1) return SR_ERR; if (write(tmpfile, metafile, len) < 0) { sr_dbg("Failed to create new metadata: %s", strerror(errno)); g_free(metafile); unlink(tmpname); return SR_ERR; } close(tmpfile); if (!(metasrc = zip_source_file(archive, tmpname, 0, -1))) { sr_err("Failed to create zip source for metadata."); g_free(metafile); unlink(tmpname); return SR_ERR; } if (zip_replace(archive, zs.index, metasrc) == -1) { sr_err("Failed to replace metadata file."); g_free(metafile); unlink(tmpname); return SR_ERR; } g_free(metafile); } g_key_file_free(kf); next_chunk_num = 1; num_files = zip_get_num_entries(archive, 0); for (i = 0; i < num_files; i++) { entry_name = zip_get_name(archive, i, 0); if (strncmp(entry_name, "logic-1", 7)) continue; if (strlen(entry_name) == 7) { /* This file has no extra chunks, just a single "logic-1". * Rename it to "logic-1-1" * and continue with chunk 2. */ if (zip_rename(archive, i, "logic-1-1") == -1) { sr_err("Failed to rename 'logic-1' to 'logic-1-1'."); unlink(tmpname); return SR_ERR; } next_chunk_num = 2; break; } else if (strlen(entry_name) > 8 && entry_name[7] == '-') { chunk_num = strtoull(entry_name + 8, NULL, 10); if (chunk_num >= next_chunk_num) next_chunk_num = chunk_num + 1; } } snprintf(chunkname, 15, "logic-1-%d", next_chunk_num); if (!(logicsrc = zip_source_buffer(archive, buf, units * unitsize, FALSE))) { unlink(tmpname); return SR_ERR; } if (zip_add(archive, chunkname, logicsrc) == -1) { unlink(tmpname); return SR_ERR; } if ((ret = zip_close(archive)) == -1) { sr_info("error saving session file: %s", zip_strerror(archive)); unlink(tmpname); return SR_ERR; } unlink(tmpname); return SR_OK; }
PHPZIPAPI struct zip_source * zip_source_zip(struct zip *za, struct zip *srcza, int srcidx, int flags, off_t start, off_t len) { struct zip_error error; struct zip_source *zs; struct read_zip *p; if (za == NULL) return NULL; if (srcza == NULL || start < 0 || len < -1 || srcidx < 0 || srcidx >= srcza->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx)) { _zip_error_set(&za->error, ZIP_ER_CHANGED, 0); return NULL; } if (len == 0) len = -1; if (start == 0 && len == -1) flags |= ZIP_FL_COMPRESSED; else flags &= ~ZIP_FL_COMPRESSED; if ((p=(struct read_zip *)malloc(sizeof(*p))) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } _zip_error_copy(&error, &srcza->error); if (zip_stat_index(srcza, srcidx, flags, &p->st) < 0 || (p->zf=zip_fopen_index(srcza, srcidx, flags)) == NULL) { free(p); _zip_error_copy(&za->error, &srcza->error); _zip_error_copy(&srcza->error, &error); return NULL; } p->off = start; p->len = len; if ((flags & ZIP_FL_COMPRESSED) == 0) { p->st.size = p->st.comp_size = len; p->st.comp_method = ZIP_CM_STORE; p->st.crc = 0; } if ((zs=zip_source_function(za, read_zip, p)) == NULL) { free(p); return NULL; } return zs; }
static VALUE zipruby_archive_update(int argc, VALUE *argv, VALUE self) { struct zipruby_archive *p_archive, *p_srcarchive; VALUE srcarchive, flags; int i, num_files, i_flags = 0; rb_scan_args(argc, argv, "11", &srcarchive, &flags); if (!rb_obj_is_instance_of(srcarchive, Archive)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected ZipRuby::Archive)", rb_class2name(CLASS_OF(srcarchive))); } if (!NIL_P(flags)) { i_flags = NUM2INT(flags); } Data_Get_Struct(self, struct zipruby_archive, p_archive); Check_Archive(p_archive); Data_Get_Struct(srcarchive, struct zipruby_archive, p_srcarchive); Check_Archive(p_srcarchive); num_files = zip_get_num_files(p_srcarchive->archive); for (i = 0; i < num_files; i++) { struct zip_source *zsource; struct zip_file *fzip; struct zip_stat sb; char *buf; const char *name; int index, error; zip_stat_init(&sb); if (zip_stat_index(p_srcarchive->archive, i, 0, &sb)) { zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive)); } if ((buf = malloc(sb.size)) == NULL) { zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(rb_eRuntimeError, "Update archive failed: Cannot allocate memory"); } fzip = zip_fopen_index(p_srcarchive->archive, i, 0); if (fzip == NULL) { free(buf); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive)); } if (zip_fread(fzip, buf, sb.size) == -1) { free(buf); zip_fclose(fzip); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_file_strerror(fzip)); } if ((error = zip_fclose(fzip)) != 0) { char errstr[ERRSTR_BUFSIZE]; free(buf); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); zip_error_to_str(errstr, ERRSTR_BUFSIZE, error, errno); rb_raise(Error, "Update archive failed: %s", errstr); } if ((zsource = zip_source_buffer(p_archive->archive, buf, sb.size, 1)) == NULL) { free(buf); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive)); } if ((name = zip_get_name(p_srcarchive->archive, i, 0)) == NULL) { zip_source_free(zsource); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_srcarchive->archive)); } index = zip_name_locate(p_archive->archive, name, i_flags); if (index >= 0) { if (zip_replace(p_archive->archive, i, zsource) == -1) { zip_source_free(zsource); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive)); } } else { if (zip_add(p_archive->archive, name, zsource) == -1) { zip_source_free(zsource); zip_unchange_all(p_archive->archive); zip_unchange_archive(p_archive->archive); rb_raise(Error, "Update archive failed: %s", zip_strerror(p_archive->archive)); } } } return Qnil; }
/** * Load the session from the specified filename. * * @param filename The name of the session file to load. Must not be NULL. * * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, * SR_ERR_MALLOC upon memory allocation errors, or SR_ERR upon * other errors. */ SR_API int sr_session_load(const char *filename) { GKeyFile *kf; GPtrArray *capturefiles; struct zip *archive; struct zip_file *zf; struct zip_stat zs; struct sr_dev_inst *sdi; struct sr_channel *probe; int ret, devcnt, i, j, k; uint16_t probenum; uint64_t tmp_u64, total_probes, enabled_probes; uint16_t p; char **sections, **keys, *metafile, *val, s[11]; char probename[SR_MAX_PROBENAME_LEN + 1]; int mode = LOGIC; int channel_type = SR_CHANNEL_LOGIC; double tmp_double; if (!filename) { sr_err("%s: filename was NULL", __func__); return SR_ERR_ARG; } if (!(archive = zip_open(filename, 0, &ret))) { sr_dbg("Failed to open session file: zip error %d", ret); return SR_ERR; } /* read "metadata" */ if (zip_stat(archive, "header", 0, &zs) == -1) { sr_dbg("Not a valid DSView data file."); return SR_ERR; } if (!(metafile = g_try_malloc(zs.size))) { sr_err("%s: metafile malloc failed", __func__); return SR_ERR_MALLOC; } zf = zip_fopen_index(archive, zs.index, 0); zip_fread(zf, metafile, zs.size); zip_fclose(zf); kf = g_key_file_new(); if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) { sr_dbg("Failed to parse metadata."); return SR_ERR; } sr_session_new(); devcnt = 0; capturefiles = g_ptr_array_new_with_free_func(g_free); sections = g_key_file_get_groups(kf, NULL); for (i = 0; sections[i]; i++) { if (!strcmp(sections[i], "version")) /* nothing really interesting in here yet */ continue; if (!strncmp(sections[i], "header", 6)) { /* device section */ sdi = NULL; enabled_probes = total_probes = 0; keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); for (j = 0; keys[j]; j++) { val = g_key_file_get_string(kf, sections[i], keys[j], NULL); if (!strcmp(keys[j], "device mode")) { mode = strtoull(val, NULL, 10); } else if (!strcmp(keys[j], "capturefile")) { sdi = sr_dev_inst_new(mode, devcnt, SR_ST_ACTIVE, NULL, NULL, NULL); sdi->driver = &session_driver; if (devcnt == 0) /* first device, init the driver */ sdi->driver->init(NULL); sr_dev_open(sdi); sr_session_dev_add(sdi); sdi->driver->config_set(SR_CONF_SESSIONFILE, g_variant_new_bytestring(filename), sdi, NULL, NULL); sdi->driver->config_set(SR_CONF_CAPTUREFILE, g_variant_new_bytestring(val), sdi, NULL, NULL); g_ptr_array_add(capturefiles, val); } else if (!strcmp(keys[j], "samplerate")) { sr_parse_sizestring(val, &tmp_u64); sdi->driver->config_set(SR_CONF_SAMPLERATE, g_variant_new_uint64(tmp_u64), sdi, NULL, NULL); } else if (!strcmp(keys[j], "unitsize")) { tmp_u64 = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_CAPTURE_UNITSIZE, g_variant_new_uint64(tmp_u64), sdi, NULL, NULL); } else if (!strcmp(keys[j], "total samples")) { tmp_u64 = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_LIMIT_SAMPLES, g_variant_new_uint64(tmp_u64), sdi, NULL, NULL); } else if (!strcmp(keys[j], "hDiv")) { tmp_u64 = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_TIMEBASE, g_variant_new_uint64(tmp_u64), sdi, NULL, NULL); } else if (!strcmp(keys[j], "total probes")) { total_probes = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_CAPTURE_NUM_PROBES, g_variant_new_uint64(total_probes), sdi, NULL, NULL); channel_type = (mode == DSO) ? SR_CHANNEL_DSO : (mode == ANALOG) ? SR_CHANNEL_ANALOG : SR_CHANNEL_LOGIC; for (p = 0; p < total_probes; p++) { snprintf(probename, SR_MAX_PROBENAME_LEN, "%" PRIu64, p); if (!(probe = sr_channel_new(p, channel_type, FALSE, probename))) return SR_ERR; sdi->channels = g_slist_append(sdi->channels, probe); } } else if (!strncmp(keys[j], "probe", 5)) { if (!sdi) continue; enabled_probes++; tmp_u64 = strtoul(keys[j]+5, NULL, 10); /* sr_session_save() */ sr_dev_probe_name_set(sdi, tmp_u64, val); sr_dev_probe_enable(sdi, tmp_u64, TRUE); } else if (!strncmp(keys[j], "trigger", 7)) { probenum = strtoul(keys[j]+7, NULL, 10); sr_dev_trigger_set(sdi, probenum, val); } else if (!strncmp(keys[j], "enable", 6)) { probenum = strtoul(keys[j]+6, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_EN_CH, g_variant_new_boolean(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "coupling", 8)) { probenum = strtoul(keys[j]+8, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_COUPLING, g_variant_new_byte(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "vDiv", 4)) { probenum = strtoul(keys[j]+4, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_VDIV, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "vFactor", 7)) { probenum = strtoul(keys[j]+7, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_FACTOR, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "vPos", 4)) { probenum = strtoul(keys[j]+4, NULL, 10); tmp_double = strtod(val, NULL); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_VPOS, g_variant_new_double(tmp_double), sdi, probe, NULL); } } else if (!strncmp(keys[j], "period", 6)) { probenum = strtoul(keys[j]+6, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_STATUS_PERIOD, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "pcnt", 4)) { probenum = strtoul(keys[j]+4, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_STATUS_PCNT, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "max", 3)) { probenum = strtoul(keys[j]+3, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_STATUS_MAX, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } else if (!strncmp(keys[j], "min", 3)) { probenum = strtoul(keys[j]+3, NULL, 10); tmp_u64 = strtoull(val, NULL, 10); if (probenum < g_slist_length(sdi->channels)) { probe = g_slist_nth(sdi->channels, probenum)->data; sdi->driver->config_set(SR_CONF_STATUS_MIN, g_variant_new_uint64(tmp_u64), sdi, probe, NULL); } } } g_strfreev(keys); } devcnt++; } g_strfreev(sections); g_key_file_free(kf); return SR_OK; }
File * APKFile::CreateFromAssets(const FilePath &filePath, uint32 attributes) { LockGuard<Mutex> guard(mutex); FileSystem * fileSystem = FileSystem::Instance(); for (List<FileSystem::ResourceArchiveItem>::iterator ai = fileSystem->resourceArchiveList.begin(); ai != fileSystem->resourceArchiveList.end(); ++ai) { FileSystem::ResourceArchiveItem & item = *ai; String filenamecpp = filePath.GetAbsolutePathname(); String::size_type pos = filenamecpp.find(item.attachPath); if (0 == pos) { String relfilename = filenamecpp.substr(item.attachPath.length()); int32 size = item.archive->LoadResource(relfilename, 0); if (-1 == size) { return 0; } uint8 * buffer = new uint8[size]; item.archive->LoadResource(relfilename, buffer); APKFile *fileInstance = CreateFromData(relfilename, buffer, size, attributes); SafeDeleteArray(buffer); return fileInstance; } } bool isDirectory = FileSystem::Instance()->IsDirectory(filePath); if(isDirectory) { Logger::Error("[APKFile::CreateFromAssets] Can't create file because of it is directory (%s)", filePath.GetAbsolutePathname().c_str()); return NULL; } AssetsManager* assetsManager = AssetsManager::Instance(); DVASSERT_MSG(assetsManager, "[APKFile::CreateFromAssets] Need to create AssetsManager before loading files"); zip* package = assetsManager->GetApplicationPackage(); if (NULL == package) { DVASSERT_MSG(false, "[APKFile::CreateFromAssets] Package file should be initialized."); return NULL; } String assetFileStr = filePath.GetAbsolutePathname(); int index = zip_name_locate(package, assetFileStr.c_str(), 0); if (-1 == index) { Logger::Error("[APKFile::CreateFromAssets] Can't locate file in the archive: %s", assetFileStr.c_str()); return NULL; } struct zip_stat stat; int32 error = zip_stat_index(package, index, 0, &stat); if (-1 == error) { Logger::Error("[APKFile::CreateFromAssets] Can't get file info: %s", assetFileStr.c_str()); return NULL; } zip_file* file = zip_fopen_index(package, index, 0); if (NULL == file) { Logger::Error("[APKFile::CreateFromAssets] Can't open file in the archive: %s", assetFileStr.c_str()); return NULL; } DVASSERT(stat.size >= 0); uint8 *data = new uint8[stat.size]; if (zip_fread(file, data, stat.size) != stat.size) { Logger::Error("[APKFile::CreateFromAssets] Error reading file: %s", assetFileStr.c_str()); SafeDeleteArray(data); zip_fclose(file); return NULL; } APKFile *fileInstance = CreateFromData(filePath, data, stat.size, attributes); DVASSERT_MSG(fileInstance, "[APKFile::CreateFromAssets] Can't create dynamic file from memory"); SafeDeleteArray(data); zip_fclose(file); return fileInstance; }
bool extractMap(const std::string& file) { int err = 0; zip* zipFile = zip_open(file.c_str(), 0, &err); if(!zipFile) { std::cout << "[ERROR]: Failed to open archive file: " << file << ".\n"; return false; } auto fileNumber = zip_get_num_entries(zipFile, 0); std::string folderName = file.substr(0, file.find_last_of('.')) + "/"; // cut off file extension, add dir char stripWebChars(folderName); if(!makeFolder(folderName)) return false; for(auto i = 0u; i < fileNumber; i++) { zip_file* zipped = zip_fopen_index(zipFile, i, 0); struct zip_stat fileInfo; zip_stat_init(&fileInfo); zip_stat_index(zipFile, i, 0, &fileInfo); if(fileInfo.valid & ZIP_STAT_NAME && fileInfo.valid & ZIP_STAT_SIZE && fileInfo.valid & ZIP_STAT_COMP_SIZE) { std::string fileStr = fileInfo.name; if(fileStr.find('.') == std::string::npos) // if we don't have a dot, this is a folder { continue; // skip this folder } if(fileStr.find('/') != std::string::npos) // if we have any dir chars in the string, strip out dirs { fileStr = fileStr.substr(fileStr.find_last_of('/') + 1); } #ifndef __linux__ #pragma warning(push) #pragma warning(disable: 4244) #endif std::vector<bbyte> bytes(fileInfo.size); // just gotta deal with this conversion #ifndef __linux__ #pragma warning(pop) #endif zip_fread(zipped, bytes.data(), fileInfo.size); std::ofstream fout; fout.open(folderName + fileStr, std::ofstream::binary); if(fout.bad()) { std::cout << "[ERROR]: Unable to extract file: " << fileInfo.name << '\n'; return false; } fout.write(bytes.data(), bytes.size()); fout.close(); } else { std::cout << "[ERROR]: Bad file data for file in archive: " << file << '\n'; return false; } zip_fclose(zipped); } zip_close(zipFile); // delete the zip file, it's no longer needed #ifdef __linux__ // TBD #else DeleteFile(file.c_str()); #endif return true; }
static YogVal decompress(YogEnv* env, YogVal self, YogVal pkg, YogVal args, YogVal kw, YogVal block) { SAVE_ARGS5(env, self, pkg, args, kw, block); YogVal zip = YUNDEF; YogVal dest = YNIL; YogVal s = YUNDEF; PUSH_LOCALS3(env, zip, dest, s); YogCArg params[] = { { "zip", &zip }, { "|", NULL }, { "dest", &dest }, { NULL, NULL } }; YogGetArgs_parse_args(env, "decompress", params, args, kw); if (!IS_PTR(zip) || (BASIC_OBJ_TYPE(zip) != TYPE_STRING)) { YogError_raise_TypeError(env, "zip must be String"); } if (!IS_NIL(dest) && (!IS_PTR(dest) || (BASIC_OBJ_TYPE(dest) != TYPE_STRING))) { YogError_raise_TypeError(env, "dest must be nil or String"); } struct zip* archive = open_zip(env, pkg, zip, 0); int n = zip_get_num_files(archive); YogHandle* h = VAL2HDL(env, dest); int i; for (i = 0; i < n; i++) { const char* name = zip_get_name(archive, i, 0); if (name == NULL) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } YogVal bin = YogString_to_bin_in_default_encoding(env, h); char* path = (char*)YogSysdeps_alloca(strlen(BINARY_CSTR(bin)) + strlen(name) + 2); strcpy(path, BINARY_CSTR(bin)); strcat(path, "/"); strcat(path, name); char* dir = (char*)YogSysdeps_alloca(strlen(path) + 1); strcpy(dir, path); dirname(dir); make_dirs(env, dir); struct zip_file* file = zip_fopen_index(archive, i, 0); if (file == NULL) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } FILE* fp = fopen(path, "wb"); if (fp == NULL) { zip_fclose(file); close_zip(env, pkg, archive); s = YogString_from_string(env, path); YogError_raise_sys_err(env, errno, s); } while (1) { char buf[1024]; int len = zip_fread(file, buf, array_sizeof(buf)); if (len < 0) { zip_fclose(file); close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } else if (len == 0) { break; } fwrite(buf, sizeof(char), len, fp); if (ferror(fp)) { zip_fclose(file); close_zip(env, pkg, archive); YogError_raise_IOError(env, name); } } fclose(fp); if (zip_fclose(file) != 0) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } } close_zip(env, pkg, archive); RETURN(env, YNIL); }
bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) { if (installInProgress_) { ERROR_LOG(HLE, "Cannot have two installs in progress at the same time"); return false; } installInProgress_ = true; std::string pspGame = GetSysDirectory(DIRECTORY_GAME); INFO_LOG(HLE, "Installing %s into %s", zipfile.c_str(), pspGame.c_str()); if (!File::Exists(zipfile)) { ERROR_LOG(HLE, "ZIP file %s doesn't exist", zipfile.c_str()); return false; } int error; #ifdef _WIN32 struct zip *z = zip_open(ConvertUTF8ToWString(zipfile).c_str(), 0, &error); #elif defined(__SYMBIAN32__) // If zipfile is non-ascii, this may not function correctly. Other options? struct zip *z = zip_open(std::wstring(zipfile.begin(), zipfile.end()).c_str(), 0, &error); #else struct zip *z = zip_open(zipfile.c_str(), 0, &error); #endif if (!z) { ERROR_LOG(HLE, "Failed to open ZIP file %s, error code=%i", zipfile.c_str(), error); return false; } int numFiles = zip_get_num_files(z); // First, find all the directories, and precreate them before we fill in with files. // Also, verify that this is a PSP zip file with the correct layout. bool isPSP = false; int stripChars = 0; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); std::string zippedName = fn; if (zippedName.find("EBOOT.PBP") != std::string::npos) { int slashCount = 0; int lastSlashLocation = -1; int slashLocation = -1; for (size_t i = 0; i < zippedName.size(); i++) { if (zippedName[i] == '/') { slashCount++; slashLocation = lastSlashLocation; lastSlashLocation = i; } } if (slashCount >= 1 && (!isPSP || slashLocation < stripChars + 1)) { stripChars = slashLocation + 1; isPSP = true; } else { INFO_LOG(HLE, "Wrong number of slashes (%i) in %s", slashCount, zippedName.c_str()); } } } if (!isPSP) { ERROR_LOG(HLE, "File not a PSP game, no EBOOT.PBP found."); return false; } size_t allBytes = 0, bytesCopied = 0; // Create all the directories in one pass std::set<std::string> createdDirs; for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); std::string zippedName = fn; std::string outFilename = pspGame + zippedName.substr(stripChars); bool isDir = *outFilename.rbegin() == '/'; if (!isDir && outFilename.find("/") != std::string::npos) { outFilename = outFilename.substr(0, outFilename.rfind('/')); } if (createdDirs.find(outFilename) == createdDirs.end()) { File::CreateFullPath(outFilename.c_str()); createdDirs.insert(outFilename); } if (!isDir) { struct zip_stat zstat; if (zip_stat_index(z, i, 0, &zstat) >= 0) { allBytes += zstat.size; } } } // Now, loop through again in a second pass, writing files. for (int i = 0; i < numFiles; i++) { const char *fn = zip_get_name(z, i, 0); // Note that we do NOT write files that are not in a directory, to avoid random // README files etc. if (strstr(fn, "/") != 0) { struct zip_stat zstat; zip_stat_index(z, i, 0, &zstat); size_t size = zstat.size; fn += stripChars; std::string outFilename = pspGame + fn; bool isDir = *outFilename.rbegin() == '/'; if (isDir) continue; if (i < 10) { INFO_LOG(HLE, "Writing %i bytes to %s", (int)size, outFilename.c_str()); } zip_file *zf = zip_fopen_index(z, i, 0); FILE *f = fopen(outFilename.c_str(), "wb"); if (f) { size_t pos = 0; const size_t blockSize = 1024 * 128; u8 *buffer = new u8[blockSize]; while (pos < size) { size_t bs = std::min(blockSize, pos - size); zip_fread(zf, buffer, bs); size_t written = fwrite(buffer, 1, bs, f); if (written != bs) { ERROR_LOG(HLE, "Wrote %i bytes out of %i - Disk full?", (int)written, (int)bs); // TODO: What do we do? } pos += bs; bytesCopied += bs; installProgress_ = (float)bytesCopied / (float)allBytes; // printf("Progress: %f\n", installProgress_); } zip_fclose(zf); fclose(f); delete [] buffer; } else { ERROR_LOG(HLE, "Failed to open file for writing"); } } } INFO_LOG(HLE, "Extracted %i files (%i bytes).", numFiles, (int)bytesCopied); zip_close(z); installProgress_ = 1.0f; installInProgress_ = false; if (deleteAfter) { deleteFile(zipfile.c_str()); } InstallDone(); return true; }
int vfs_zip_seek (DB_FILE *f, int64_t offset, int whence) { ddb_zip_file_t *zf = (ddb_zip_file_t *)f; // printf ("seek: %lld (%d)\n", offset, whence); if (whence == SEEK_CUR) { offset = zf->offset + offset; } else if (whence == SEEK_END) { offset = zf->size + offset; } #if ENABLE_CACHE int64_t offs = offset - zf->offset; if ((offs < 0 && -offs <= zf->buffer_pos) || (offs >= 0 && offs < zf->buffer_remaining)) { if (offs != 0) { //printf ("cache success\n"); //printf ("[before] absoffs: %lld, offs: %lld, rem: %d, pos: %d\n", offset, offs, zf->buffer_remaining, zf->buffer_pos); // test cases: // fail: offs = -3, pos = 0, rem = 100 // fail: offs = 10, pos = 95, rem = 5 // succ: offs = -3, pos = 3, rem = 97 ----> pos = 0, rem=100 // succ: offs = 10, pos = 0, rem = 100 ---> pos = 10, rem = 90 zf->buffer_pos += offs; zf->buffer_remaining -= offs; //printf ("[after] offs: %lld, rem: %d, pos: %d\n", offs, zf->buffer_remaining, zf->buffer_pos); zf->offset = offset; assert (zf->buffer_pos < ZIP_BUFFER_SIZE); return 0; } else { // printf ("cache double success\n"); return 0; } } // else { // printf ("cache miss: abs_offs: %lld, offs: %lld, rem: %d, pos: %d\n", offset, offs, zf->buffer_remaining, zf->buffer_pos); // } zf->offset += zf->buffer_remaining; #endif if (offset < zf->offset) { // reopen zip_fclose (zf->zf); zf->zf = zip_fopen_index (zf->z, zf->index, 0); if (!zf->zf) { return -1; } zf->offset = 0; } #if ENABLE_CACHE zf->buffer_pos = 0; zf->buffer_remaining = 0; #endif char buf[4096]; int64_t n = offset - zf->offset; while (n > 0) { int sz = min (n, sizeof (buf)); ssize_t rb = zip_fread (zf->zf, buf, sz); n -= rb; assert (n >= 0); zf->offset += rb; if (rb != sz) { break; } } if (n > 0) { return -1; } return 0; }
// fname must have form of zip://full_filepath.zip:full_filepath_in_zip DB_FILE* vfs_zip_open (const char *fname) { trace ("vfs_zip: open %s\n", fname); if (strncasecmp (fname, "zip://", 6)) { return NULL; } fname += 6; struct zip *z = NULL; struct zip_stat st; const char *colon = fname; for (;;) { colon = strchr (colon, ':'); if (!colon) { break; } char zipname[colon-fname+1]; memcpy (zipname, fname, colon-fname); zipname[colon-fname] = 0; colon = colon+1; z = zip_open (zipname, 0, NULL); if (!z) { continue; } memset (&st, 0, sizeof (st)); int res = zip_stat(z, colon, 0, &st); if (res != 0) { zip_close (z); return NULL; } break; } if (!z) { return NULL; } fname = colon; struct zip_file *zf = zip_fopen_index (z, st.index, 0); if (!zf) { zip_close (z); return NULL; } ddb_zip_file_t *f = malloc (sizeof (ddb_zip_file_t)); memset (f, 0, sizeof (ddb_zip_file_t)); f->file.vfs = &plugin; f->z = z; f->zf = zf; f->index = st.index; f->size = st.size; trace ("vfs_zip: end open %s\n", fname); return (DB_FILE*)f; }
int sr_session_load(const char *filename) { GKeyFile *kf; GPtrArray *capturefiles; struct zip *archive; struct zip_file *zf; struct zip_stat zs; struct sr_session *session; struct sr_device *device; struct sr_probe *probe; int ret, err, probenum, devcnt, i, j; uint64_t tmp_u64, total_probes, enabled_probes, p; char **sections, **keys, *metafile, *val, c; if (!(archive = zip_open(filename, 0, &err))) { sr_dbg("Failed to open session file: zip error %d", err); return SR_ERR; } /* check "version" */ if (!(zf = zip_fopen(archive, "version", 0))) { sr_dbg("Not a sigrok session file."); return SR_ERR; } ret = zip_fread(zf, &c, 1); if (ret != 1 || c != '1') { sr_dbg("Not a valid sigrok session file."); return SR_ERR; } zip_fclose(zf); /* read "metadata" */ if (zip_stat(archive, "metadata", 0, &zs) == -1) { sr_dbg("Not a valid sigrok session file."); return SR_ERR; } if (!(metafile = g_try_malloc(zs.size))) { sr_err("session file: %s: metafile malloc failed", __func__); return SR_ERR_MALLOC; } zf = zip_fopen_index(archive, zs.index, 0); zip_fread(zf, metafile, zs.size); zip_fclose(zf); kf = g_key_file_new(); if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) { sr_dbg("Failed to parse metadata."); return SR_ERR; } session = sr_session_new(); devcnt = 0; capturefiles = g_ptr_array_new_with_free_func(g_free); sections = g_key_file_get_groups(kf, NULL); for (i = 0; sections[i]; i++) { if (!strcmp(sections[i], "global")) /* nothing really interesting in here yet */ continue; if (!strncmp(sections[i], "device ", 7)) { /* device section */ device = NULL; enabled_probes = 0; keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); for (j = 0; keys[j]; j++) { val = g_key_file_get_string(kf, sections[i], keys[j], NULL); if (!strcmp(keys[j], "capturefile")) { device = sr_device_new(&session_driver, devcnt, 0); if (devcnt == 0) /* first device, init the plugin */ device->plugin->init((char *)filename); sr_session_device_add(device); device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTUREFILE, val); g_ptr_array_add(capturefiles, val); } else if (!strcmp(keys[j], "samplerate")) { tmp_u64 = sr_parse_sizestring(val); device->plugin->set_configuration(devcnt, SR_HWCAP_SAMPLERATE, &tmp_u64); } else if (!strcmp(keys[j], "unitsize")) { tmp_u64 = strtoull(val, NULL, 10); device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTURE_UNITSIZE, &tmp_u64); } else if (!strcmp(keys[j], "total probes")) { total_probes = strtoull(val, NULL, 10); device->plugin->set_configuration(devcnt, SR_HWCAP_CAPTURE_NUM_PROBES, &total_probes); for (p = 1; p <= total_probes; p++) sr_device_probe_add(device, NULL); } else if (!strncmp(keys[j], "probe", 5)) { if (!device) continue; enabled_probes++; tmp_u64 = strtoul(keys[j]+5, NULL, 10); sr_device_probe_name(device, tmp_u64, val); } else if (!strncmp(keys[j], "trigger", 7)) { probenum = strtoul(keys[j]+7, NULL, 10); sr_device_trigger_set(device, probenum, val); } } g_strfreev(keys); for (p = enabled_probes; p < total_probes; p++) { probe = g_slist_nth_data(device->probes, p); probe->enabled = FALSE; } } } g_strfreev(sections); g_key_file_free(kf); return SR_OK; }
/* read (extract) 'zipfile' in current directory */ int zread(const char *zipfile, unsigned long long maxsize) { struct filedesc *fdesc; int err, fd; size_t len; struct zip *zip; zip_int64_t z64; zip_uint64_t uz64; unsigned int count, index; struct zip_file *zfile; struct zip_stat zstat; char buffer[32768]; ssize_t sizr, sizw; size_t esize; /* open the zip file */ zip = zip_open(zipfile, ZIP_CHECKCONS, &err); if (!zip) { ERROR("Can't connect to file %s", zipfile); return -1; } z64 = zip_get_num_entries(zip, 0); if (z64 < 0 || z64 > UINT_MAX) { ERROR("too many entries in %s", zipfile); goto error; } count = (unsigned int)z64; /* records the files */ file_reset(); esize = 0; for (index = 0 ; index < count ; index++) { err = zip_stat_index(zip, index, ZIP_FL_ENC_GUESS, &zstat); /* check the file name */ if (!is_valid_filename(zstat.name)) { ERROR("invalid entry %s found in %s", zstat.name, zipfile); goto error; } if (zstat.name[0] == '/') { ERROR("absolute entry %s found in %s", zstat.name, zipfile); goto error; } len = strlen(zstat.name); if (len == 0) { ERROR("empty entry found in %s", zipfile); goto error; } if (zstat.name[len - 1] == '/') /* record */ fdesc = file_add_directory(zstat.name); else { /* get the size */ esize += zstat.size; /* record */ fdesc = file_add_file(zstat.name); } if (!fdesc) goto error; fdesc->zindex = index; } /* check the size */ if (maxsize && esize > maxsize) { ERROR("extracted size %zu greater than allowed size %llu", esize, maxsize); goto error; } /* unpack the recorded files */ assert(count == file_count()); for (index = 0 ; index < count ; index++) { fdesc = file_of_index(index); assert(fdesc != NULL); err = zip_stat_index(zip, fdesc->zindex, ZIP_FL_ENC_GUESS, &zstat); assert(zstat.name[0] != '/'); len = strlen(zstat.name); assert(len > 0); if (zstat.name[len - 1] == '/') { /* directory name */ err = create_directory((char*)zstat.name, MODE_OF_DIRECTORY_CREATION); if (err && errno != EEXIST) goto error; } else { /* file name */ zfile = zip_fopen_index(zip, fdesc->zindex, 0); if (!zfile) { ERROR("Can't open %s in %s", zstat.name, zipfile); goto error; } fd = create_file((char*)zstat.name, MODE_OF_FILE_CREATION, MODE_OF_DIRECTORY_CREATION); if (fd < 0) goto errorz; /* extract */ uz64 = zstat.size; while (uz64) { sizr = zip_fread(zfile, buffer, sizeof buffer); if (sizr < 0) { ERROR("error while reading %s in %s", zstat.name, zipfile); goto errorzf; } sizw = write(fd, buffer, (size_t)sizr); if (sizw < 0) { ERROR("error while writing %s", zstat.name); goto errorzf; } uz64 -= (size_t)sizw; } close(fd); zip_fclose(zfile); } } zip_close(zip); return 0; errorzf: close(fd); errorz: zip_fclose(zfile); error: zip_close(zip); return -1; }
Handle<Value> ZipFile::readFileSync(const Arguments& args) { HandleScope scope; if (args.Length() != 1 || !args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("first argument must be a file name inside the zip"))); std::string name = TOSTR(args[0]); // TODO - enforce valid index ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); struct zip_file *zf_ptr; int idx = -1; std::vector<std::string>::iterator it = std::find(zf->names.begin(), zf->names.end(), name); if (it!=zf->names.end()) { idx = distance(zf->names.begin(), it); } if (idx == -1) { std::stringstream s; s << "No file found by the name of: '" << name << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } if ((zf_ptr=zip_fopen_index(zf->archive, idx, 0)) == NULL) { zip_fclose(zf_ptr); std::stringstream s; s << "cannot open file #" << idx << " in " << name << ": archive error: " << zip_strerror(zf->archive) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } struct zip_stat st; zip_stat_index(zf->archive, idx, 0, &st); std::vector<unsigned char> data; data.clear(); data.resize( st.size ); int result = 0; result = (int)zip_fread( zf_ptr, reinterpret_cast<void*> (&data[0]), data.size() ); if (result < 0) { zip_fclose(zf_ptr); std::stringstream s; s << "error reading file #" << idx << " in " << name << ": archive error: " << zip_file_strerror(zf_ptr) << "\n"; return ThrowException(Exception::Error(String::New(s.str().c_str()))); } #if NODE_VERSION_AT_LEAST(0,3,0) node::Buffer *retbuf = Buffer::New((char *)&data[0],data.size()); #else node::Buffer *retbuf = Buffer::New(data.size()); std::memcpy(retbuf->data(), (char *)&data[0], data.size()); #endif zip_fclose(zf_ptr); return scope.Close(retbuf->handle_); }
bool GetCompressedFiles(std::string ZipName, std::vector<std::string>* pFileNames, std::vector<std::vector<char> >* data, std::string* pError) { #ifdef WIN32 HZIP hz = OpenZip(ZipName.c_str(),0); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} ZIPENTRY ze; if (GetZipItem(hz, -1, &ze) != ZR_OK) {if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} int NumFiles = ze.index; //set up returns for data... data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ if (GetZipItem(hz,i,&ze) != ZR_OK) {if(pError) *pError += "Error loading ZIP file information. Aborting.\n"; return false;} int NumDesiredFiles = pFileNames->size(); for (int j=0; j<NumDesiredFiles; j++){ if ((*pFileNames)[j].compare(ze.name)==0){ //if this is one of the file's we're looking for int size = ze.unc_size; (*data)[j].resize(size+1); //or clear... if (UnzipItem(hz, i, &((*data)[j].front()), size) != ZR_OK) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[j][size] = '\0'; } } } if (CloseZip(hz) != ZR_OK) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #else //Mac/Linux Zip read code int err; struct zip * hz = zip_open(ZipName.c_str(), ZIP_CHECKCONS, &err); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} int NumFiles = zip_get_num_entries(hz,0); if (NumFiles < 0) { if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} //set up returns for data... data->resize(NumFiles); for (uint i=0; i<NumFiles; i++){ struct zip_file * zfile = zip_fopen_index(hz, i, 0); int NumDesiredFiles = pFileNames->size(); const char * entryname = zip_get_name(hz, i, 0); struct zip_stat stat; err = zip_stat_index(hz, i, 0, &stat); for (int j=0; j<NumDesiredFiles; j++){ if ((*pFileNames)[j].compare(entryname)==0){ //if this is one of the file's we're looking for int size = stat.size; (*data)[j].resize(size+1); //or clear... if (zip_fread(zfile, &((*data)[j].front()), size) != size) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[j][size] = '\0'; } } zip_fclose(zfile); } if (zip_close(hz) != 0) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #endif }
/** * Load the session from the specified filename. * * @param ctx The context in which to load the session. * @param filename The name of the session file to load. * @param session The session to load the file into. * * @retval SR_OK Success * @retval SR_ERR_MALLOC Memory allocation error * @retval SR_ERR_DATA Malformed session file * @retval SR_ERR This is not a session file */ SR_API int sr_session_load(struct sr_context *ctx, const char *filename, struct sr_session **session) { GKeyFile *kf; GPtrArray *capturefiles; struct zip *archive; struct zip_file *zf; struct zip_stat zs; struct sr_dev_inst *sdi; struct sr_channel *ch; int ret, i, j; uint64_t tmp_u64, total_channels, p; char **sections, **keys, *metafile, *val; char channelname[SR_MAX_CHANNELNAME_LEN + 1]; if ((ret = sr_sessionfile_check(filename)) != SR_OK) return ret; if (!(archive = zip_open(filename, 0, &ret))) return SR_ERR; if (zip_stat(archive, "metadata", 0, &zs) == -1) return SR_ERR; if (!(metafile = g_try_malloc(zs.size))) { sr_err("%s: metafile malloc failed", __func__); return SR_ERR_MALLOC; } zf = zip_fopen_index(archive, zs.index, 0); zip_fread(zf, metafile, zs.size); zip_fclose(zf); kf = g_key_file_new(); if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) { sr_dbg("Failed to parse metadata."); return SR_ERR; } if ((ret = sr_session_new(ctx, session)) != SR_OK) return ret; ret = SR_OK; capturefiles = g_ptr_array_new_with_free_func(g_free); sections = g_key_file_get_groups(kf, NULL); for (i = 0; sections[i] && ret == SR_OK; i++) { if (!strcmp(sections[i], "global")) /* nothing really interesting in here yet */ continue; if (!strncmp(sections[i], "device ", 7)) { /* device section */ sdi = NULL; keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); for (j = 0; keys[j]; j++) { val = g_key_file_get_string(kf, sections[i], keys[j], NULL); if (!strcmp(keys[j], "capturefile")) { sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->driver = &session_driver; sdi->status = SR_ST_ACTIVE; if (!session_driver_initialized) { /* first device, init the driver */ session_driver_initialized = 1; sdi->driver->init(sdi->driver, NULL); } sr_dev_open(sdi); sr_session_dev_add(*session, sdi); (*session)->owned_devs = g_slist_append( (*session)->owned_devs, sdi); sdi->driver->config_set(SR_CONF_SESSIONFILE, g_variant_new_string(filename), sdi, NULL); sdi->driver->config_set(SR_CONF_CAPTUREFILE, g_variant_new_string(val), sdi, NULL); g_ptr_array_add(capturefiles, val); } else if (!strcmp(keys[j], "samplerate")) { if (!sdi) { ret = SR_ERR_DATA; break; } sr_parse_sizestring(val, &tmp_u64); sdi->driver->config_set(SR_CONF_SAMPLERATE, g_variant_new_uint64(tmp_u64), sdi, NULL); } else if (!strcmp(keys[j], "unitsize")) { if (!sdi) { ret = SR_ERR_DATA; break; } tmp_u64 = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_CAPTURE_UNITSIZE, g_variant_new_uint64(tmp_u64), sdi, NULL); } else if (!strcmp(keys[j], "total probes")) { if (!sdi) { ret = SR_ERR_DATA; break; } total_channels = strtoull(val, NULL, 10); sdi->driver->config_set(SR_CONF_NUM_LOGIC_CHANNELS, g_variant_new_uint64(total_channels), sdi, NULL); for (p = 0; p < total_channels; p++) { snprintf(channelname, SR_MAX_CHANNELNAME_LEN, "%" PRIu64, p); sr_channel_new(sdi, p, SR_CHANNEL_LOGIC, FALSE, channelname); } } else if (!strncmp(keys[j], "probe", 5)) { if (!sdi) { ret = SR_ERR_DATA; break; } tmp_u64 = strtoul(keys[j]+5, NULL, 10) - 1; ch = g_slist_nth_data(sdi->channels, tmp_u64); /* sr_session_save() */ sr_dev_channel_name_set(ch, val); sr_dev_channel_enable(ch, TRUE); } } g_strfreev(keys); } } g_strfreev(sections); g_key_file_free(kf); return ret; }
bool UncompressAllFiles(std::string ZipName, std::vector<std::string>* pFileNames, std::vector<std::vector<char> >* data, std::string* pError) { #ifdef WIN32 HZIP hz = OpenZip(ZipName.c_str(),0); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} ZIPENTRY ze; if (GetZipItem(hz, -1, &ze) != ZR_OK) {if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} int NumFiles = ze.index; //set up returns for the number of files... pFileNames->resize(NumFiles); data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ if (GetZipItem(hz,i,&ze) != ZR_OK) {if(pError) *pError += "Error loading ZIP file information. Aborting.\n"; return false;} int size = ze.unc_size; (*data)[i].resize(size+1); if (UnzipItem(hz, i, &((*data)[i].front()), size) != ZR_OK) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[i][size] = '\0'; (*pFileNames)[i] = ze.name; } if (CloseZip(hz) != ZR_OK) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #else //Mac/Linux Zip read code int err; struct zip * hz = zip_open(ZipName.c_str(), ZIP_CHECKCONS, &err); if (!hz){if(pError) *pError += ("Unable to open ZIP archive. Aborting.\n"); return false;} int NumFiles = zip_get_num_entries(hz,0); if (NumFiles < 0) { if(pError) *pError += ("Unable to return information about ZIP archive. Aborting.\n"); return false;} //set up returns for the number of files... pFileNames->resize(NumFiles); data->resize(NumFiles); for (int i=0; i<NumFiles; i++){ struct zip_stat stat; err = zip_stat_index(hz, i, 0, &stat); int size = stat.size; (*data)[i].resize(size+1); struct zip_file * zfile = zip_fopen_index(hz, i, 0); if (zip_fread(zfile, &((*data)[i].front()), size) != size) {if(pError) *pError += "Could not unzip sub-file. Aborting.\n"; return false;} (*data)[i][size] = '\0'; (*pFileNames)[i] = zip_get_name(hz, i, 0); } if (zip_close(hz) != 0) {if(pError) *pError += "Error closing ZIP file.\n"; return false;} return true; #endif }
ZipEntry(zip* z, int index) : m_zipFile(nullptr) { if (zip_stat_index(z, index, 0, &m_zipStat) == 0) { m_zipFile = zip_fopen_index(z, index, 0); } }
int ipsw_extract_to_file(const char* ipsw, const char* infile, const char* outfile) { ipsw_archive* archive = ipsw_open(ipsw); if (archive == NULL || archive->zip == NULL) { error("ERROR: Invalid archive\n"); return -1; } int zindex = zip_name_locate(archive->zip, infile, 0); if (zindex < 0) { error("ERROR: zip_name_locate: %s\n", infile); return -1; } struct zip_stat zstat; zip_stat_init(&zstat); if (zip_stat_index(archive->zip, zindex, 0, &zstat) != 0) { error("ERROR: zip_stat_index: %s\n", infile); return -1; } char* buffer = (char*) malloc(BUFSIZE); if (buffer == NULL) { error("ERROR: Unable to allocate memory\n"); return -1; } struct zip_file* zfile = zip_fopen_index(archive->zip, zindex, 0); if (zfile == NULL) { error("ERROR: zip_fopen_index: %s\n", infile); return -1; } FILE* fd = fopen(outfile, "wb"); if (fd == NULL) { error("ERROR: Unable to open output file: %s\n", outfile); zip_fclose(zfile); return -1; } int i = 0; int size = 0; int bytes = 0; int count = 0; double progress = 0; for(i = zstat.size; i > 0; i -= count) { if (i < BUFSIZE) size = i; else size = BUFSIZE; count = zip_fread(zfile, buffer, size); if (count < 0) { error("ERROR: zip_fread: %s\n", infile); zip_fclose(zfile); free(buffer); return -1; } fwrite(buffer, 1, count, fd); bytes += size; progress = ((double) bytes/ (double) zstat.size) * 100.0; print_progress_bar(progress); } fclose(fd); zip_fclose(zfile); ipsw_close(archive); free(buffer); return 0; }
int main(int argc, char **argv) { idevice_t phone = NULL; lockdownd_client_t client = NULL; instproxy_client_t ipc = NULL; instproxy_error_t err; np_client_t np = NULL; afc_client_t afc = NULL; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 lockdownd_service_descriptor_t service = NULL; #else uint16_t service = 0; #endif int res = 0; char *bundleidentifier = NULL; parse_opts(argc, argv); argc -= optind; argv += optind; if (IDEVICE_E_SUCCESS != idevice_new(&phone, udid)) { fprintf(stderr, "No iOS device found, is it plugged in?\n"); return -1; } if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } if ((lockdownd_start_service (client, "com.apple.mobile.notification_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.notification_proxy!\n"); goto leave_cleanup; } np_error_t nperr = np_client_new(phone, service, &np); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (nperr != NP_E_SUCCESS) { fprintf(stderr, "Could not connect to notification_proxy!\n"); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 np_set_notify_callback(np, notifier, NULL); #else np_set_notify_callback(np, notifier); #endif const char *noties[3] = { NP_APP_INSTALLED, NP_APP_UNINSTALLED, NULL }; np_observe_notifications(np, noties); run_again: #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.mobile.installation_proxy", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.mobile.installation_proxy!\n"); goto leave_cleanup; } err = instproxy_client_new(phone, service, &ipc); #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to installation_proxy!\n"); goto leave_cleanup; } setbuf(stdout, NULL); if (last_status) { free(last_status); last_status = NULL; } notification_expected = 0; if (cmd == CMD_LIST_APPS) { int xml_mode = 0; plist_t client_opts = instproxy_client_options_new(); instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); plist_t apps = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "list_system")) { if (!client_opts) { client_opts = instproxy_client_options_new(); } instproxy_client_options_add(client_opts, "ApplicationType", "System", NULL); } else if (!strcmp(elem, "list_all")) { instproxy_client_options_free(client_opts); client_opts = NULL; } else if (!strcmp(elem, "list_user")) { /* do nothing, we're already set */ } else if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } free(opts); } err = instproxy_browse(ipc, client_opts, &apps); instproxy_client_options_free(client_opts); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: instproxy_browse returned %d\n", err); goto leave_cleanup; } if (!apps || (plist_get_node_type(apps) != PLIST_ARRAY)) { fprintf(stderr, "ERROR: instproxy_browse returnd an invalid plist!\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(apps, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(apps); goto leave_cleanup; } printf("Total: %d apps\n", plist_array_get_size(apps)); uint32_t i = 0; for (i = 0; i < plist_array_get_size(apps); i++) { plist_t app = plist_array_get_item(apps, i); plist_t p_appid = plist_dict_get_item(app, "CFBundleIdentifier"); char *s_appid = NULL; char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(app, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(app, "CFBundleVersion"); if (p_appid) { plist_get_string_val(p_appid, &s_appid); } if (!s_appid) { fprintf(stderr, "ERROR: Failed to get APPID!\n"); break; } if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(s_appid); } if (s_version) { printf("%s - %s %s\n", s_appid, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", s_appid, s_dispName); } free(s_dispName); free(s_appid); } plist_free(apps); } else if (cmd == CMD_INSTALL || cmd == CMD_UPGRADE) { plist_t sinf = NULL; plist_t meta = NULL; char *pkgname = NULL; struct stat fst; uint64_t af = 0; char buf[8192]; #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } if (stat(appid, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", appid, strerror(errno)); goto leave_cleanup; } char **strs = NULL; if (afc_get_file_info(afc, PKG_PATH, &strs) != AFC_E_SUCCESS) { if (afc_make_directory(afc, PKG_PATH) != AFC_E_SUCCESS) { fprintf(stderr, "WARNING: Could not create directory '%s' on device!\n", PKG_PATH); } } if (strs) { int i = 0; while (strs[i]) { free(strs[i]); i++; } free(strs); } plist_t client_opts = instproxy_client_options_new(); /* open install package */ int errp = 0; struct zip *zf = NULL; if ((strlen(appid) > 5) && (strcmp(&appid[strlen(appid)-5], ".ipcc") == 0)) { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } char* ipcc = strdup(appid); if ((asprintf(&pkgname, "%s/%s", PKG_PATH, basename(ipcc)) > 0) && pkgname) { afc_make_directory(afc, pkgname); } printf("Uploading %s package contents... ", basename(ipcc)); /* extract the contents of the .ipcc file to PublicStaging/<name>.ipcc directory */ zip_uint64_t numzf = zip_get_num_entries(zf, 0); zip_uint64_t i = 0; for (i = 0; numzf > 0 && i < numzf; i++) { const char* zname = zip_get_name(zf, i, 0); char* dstpath = NULL; if (!zname) continue; if (zname[strlen(zname)-1] == '/') { // directory if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) > 0) && dstpath) { afc_make_directory(afc, dstpath); } free(dstpath); dstpath = NULL; } else { // file struct zip_file* zfile = zip_fopen_index(zf, i, 0); if (!zfile) continue; if ((asprintf(&dstpath, "%s/%s/%s", PKG_PATH, basename(ipcc), zname) <= 0) || !dstpath || (afc_file_open(afc, dstpath, AFC_FOPEN_WRONLY, &af) != AFC_E_SUCCESS)) { fprintf(stderr, "ERROR: can't open afc://%s for writing\n", dstpath); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } struct zip_stat zs; zip_stat_init(&zs); if (zip_stat_index(zf, i, 0, &zs) != 0) { fprintf(stderr, "ERROR: zip_stat_index %" PRIu64 " failed!\n", i); free(dstpath); dstpath = NULL; zip_fclose(zfile); continue; } free(dstpath); dstpath = NULL; zip_uint64_t zfsize = 0; while (zfsize < zs.size) { zip_int64_t amount = zip_fread(zfile, buf, sizeof(buf)); if (amount == 0) { break; } if (amount > 0) { uint32_t written, total = 0; while (total < amount) { written = 0; if (afc_file_write(afc, af, buf, amount, &written) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Write error!\n"); break; } total += written; } if (total != amount) { fprintf(stderr, "Error: wrote only %d of %" PRIi64 "\n", total, amount); afc_file_close(afc, af); zip_fclose(zfile); free(dstpath); goto leave_cleanup; } } zfsize += amount; } afc_file_close(afc, af); af = 0; zip_fclose(zfile); } } free(ipcc); printf("DONE.\n"); instproxy_client_options_add(client_opts, "PackageType", "CarrierBundle", NULL); } else if (S_ISDIR(fst.st_mode)) { /* upload developer app directory */ instproxy_client_options_add(client_opts, "PackageType", "Developer", NULL); if (asprintf(&pkgname, "%s/%s", PKG_PATH, basename(appid)) < 0) { fprintf(stderr, "ERROR: Out of memory allocating pkgname!?\n"); goto leave_cleanup; } printf("Uploading %s package contents... ", basename(appid)); afc_upload_dir(afc, appid, pkgname); printf("DONE.\n"); } else { zf = zip_open(appid, 0, &errp); if (!zf) { fprintf(stderr, "ERROR: zip_open: %s: %d\n", appid, errp); goto leave_cleanup; } /* extract iTunesMetadata.plist from package */ char *zbuf = NULL; uint32_t len = 0; plist_t meta_dict = NULL; if (zip_get_contents(zf, ITUNES_METADATA_PLIST_FILENAME, 0, &zbuf, &len) == 0) { meta = plist_new_data(zbuf, len); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &meta_dict); } else { plist_from_xml(zbuf, len, &meta_dict); } } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", ITUNES_METADATA_PLIST_FILENAME); } if (zbuf) { free(zbuf); } /* determine .app directory in archive */ zbuf = NULL; len = 0; plist_t info = NULL; char* filename = NULL; char* app_directory_name = NULL; if (zip_get_app_directory(zf, &app_directory_name)) { fprintf(stderr, "Unable to locate app directory in archive!\n"); goto leave_cleanup; } /* construct full filename to Info.plist */ filename = (char*)malloc(strlen(app_directory_name)+10+1); strcpy(filename, app_directory_name); free(app_directory_name); app_directory_name = NULL; strcat(filename, "Info.plist"); if (zip_get_contents(zf, filename, 0, &zbuf, &len) < 0) { fprintf(stderr, "WARNING: could not locate %s in archive!\n", filename); free(filename); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } free(filename); if (memcmp(zbuf, "bplist00", 8) == 0) { plist_from_bin(zbuf, len, &info); } else { plist_from_xml(zbuf, len, &info); } free(zbuf); if (!info) { fprintf(stderr, "Could not parse Info.plist!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *bundleexecutable = NULL; plist_t bname = plist_dict_get_item(info, "CFBundleExecutable"); if (bname) { plist_get_string_val(bname, &bundleexecutable); } bname = plist_dict_get_item(info, "CFBundleIdentifier"); if (bname) { plist_get_string_val(bname, &bundleidentifier); } plist_free(info); info = NULL; if (!bundleexecutable) { fprintf(stderr, "Could not determine value for CFBundleExecutable!\n"); zip_unchange_all(zf); zip_close(zf); goto leave_cleanup; } char *sinfname = NULL; if (asprintf(&sinfname, "Payload/%s.app/SC_Info/%s.sinf", bundleexecutable, bundleexecutable) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(bundleexecutable); /* extract .sinf from package */ zbuf = NULL; len = 0; if (zip_get_contents(zf, sinfname, 0, &zbuf, &len) == 0) { sinf = plist_new_data(zbuf, len); } else { fprintf(stderr, "WARNING: could not locate %s in archive!\n", sinfname); } free(sinfname); if (zbuf) { free(zbuf); } /* copy archive to device */ pkgname = NULL; if (asprintf(&pkgname, "%s/%s", PKG_PATH, bundleidentifier) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } printf("Copying '%s' to device... ", appid); if (afc_upload_file(afc, appid, pkgname) < 0) { free(pkgname); goto leave_cleanup; } printf("DONE.\n"); if (bundleidentifier) { instproxy_client_options_add(client_opts, "CFBundleIdentifier", bundleidentifier, NULL); } if (sinf) { instproxy_client_options_add(client_opts, "ApplicationSINF", sinf, NULL); } if (meta) { instproxy_client_options_add(client_opts, "iTunesMetadata", meta, NULL); } } if (zf) { zip_unchange_all(zf); zip_close(zf); } /* perform installation or upgrade */ if (cmd == CMD_INSTALL) { printf("Installing '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_install(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_install(ipc, pkgname, client_opts, status_cb); #endif } else { printf("Upgrading '%s'\n", bundleidentifier); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_upgrade(ipc, pkgname, client_opts, status_cb, NULL); #else instproxy_upgrade(ipc, pkgname, client_opts, status_cb); #endif } instproxy_client_options_free(client_opts); free(pkgname); wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_UNINSTALL) { printf("Uninstalling '%s'\n", appid); #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_uninstall(ipc, appid, NULL, status_cb, NULL); #else instproxy_uninstall(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 0; } else if (cmd == CMD_LIST_ARCHIVES) { int xml_mode = 0; plist_t dict = NULL; plist_t lres = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "xml")) { xml_mode = 1; } elem = strtok(NULL, ","); } } err = instproxy_lookup_archives(ipc, NULL, &dict); if (err != INSTPROXY_E_SUCCESS) { fprintf(stderr, "ERROR: lookup_archives returned %d\n", err); goto leave_cleanup; } if (!dict) { fprintf(stderr, "ERROR: lookup_archives did not return a plist!?\n"); goto leave_cleanup; } lres = plist_dict_get_item(dict, "LookupResult"); if (!lres || (plist_get_node_type(lres) != PLIST_DICT)) { plist_free(dict); fprintf(stderr, "ERROR: Could not get dict 'LookupResult'\n"); goto leave_cleanup; } if (xml_mode) { char *xml = NULL; uint32_t len = 0; plist_to_xml(lres, &xml, &len); if (xml) { puts(xml); free(xml); } plist_free(dict); goto leave_cleanup; } plist_dict_iter iter = NULL; plist_t node = NULL; char *key = NULL; printf("Total: %d archived apps\n", plist_dict_get_size(lres)); plist_dict_new_iter(lres, &iter); if (!iter) { plist_free(dict); fprintf(stderr, "ERROR: Could not create plist_dict_iter!\n"); goto leave_cleanup; } do { key = NULL; node = NULL; plist_dict_next_item(lres, iter, &key, &node); if (key && (plist_get_node_type(node) == PLIST_DICT)) { char *s_dispName = NULL; char *s_version = NULL; plist_t dispName = plist_dict_get_item(node, "CFBundleDisplayName"); plist_t version = plist_dict_get_item(node, "CFBundleVersion"); if (dispName) { plist_get_string_val(dispName, &s_dispName); } if (version) { plist_get_string_val(version, &s_version); } if (!s_dispName) { s_dispName = strdup(key); } if (s_version) { printf("%s - %s %s\n", key, s_dispName, s_version); free(s_version); } else { printf("%s - %s\n", key, s_dispName); } free(s_dispName); free(key); } } while (node); plist_free(dict); } else if (cmd == CMD_ARCHIVE) { char *copy_path = NULL; int remove_after_copy = 0; int skip_uninstall = 1; int app_only = 0; int docs_only = 0; plist_t client_opts = NULL; /* look for options */ if (options) { char *opts = strdup(options); char *elem = strtok(opts, ","); while (elem) { if (!strcmp(elem, "uninstall")) { skip_uninstall = 0; } else if (!strcmp(elem, "app_only")) { app_only = 1; docs_only = 0; } else if (!strcmp(elem, "docs_only")) { docs_only = 1; app_only = 0; } else if ((strlen(elem) > 5) && !strncmp(elem, "copy=", 5)) { copy_path = strdup(elem+5); } else if (!strcmp(elem, "remove")) { remove_after_copy = 1; } elem = strtok(NULL, ","); } } if (skip_uninstall || app_only || docs_only) { client_opts = instproxy_client_options_new(); if (skip_uninstall) { instproxy_client_options_add(client_opts, "SkipUninstall", 1, NULL); } if (app_only) { instproxy_client_options_add(client_opts, "ArchiveType", "ApplicationOnly", NULL); } else if (docs_only) { instproxy_client_options_add(client_opts, "ArchiveType", "DocumentsOnly", NULL); } } if (copy_path) { struct stat fst; if (stat(copy_path, &fst) != 0) { fprintf(stderr, "ERROR: stat: %s: %s\n", copy_path, strerror(errno)); free(copy_path); goto leave_cleanup; } if (!S_ISDIR(fst.st_mode)) { fprintf(stderr, "ERROR: '%s' is not a directory as expected.\n", copy_path); free(copy_path); goto leave_cleanup; } #ifdef HAVE_LIBIMOBILEDEVICE_1_1_5 if (service) { lockdownd_service_descriptor_free(service); } service = NULL; #else service = 0; #endif if ((lockdownd_start_service(client, "com.apple.afc", &service) != LOCKDOWN_E_SUCCESS) || !service) { fprintf(stderr, "Could not start com.apple.afc!\n"); free(copy_path); goto leave_cleanup; } lockdownd_client_free(client); client = NULL; if (afc_client_new(phone, service, &afc) != INSTPROXY_E_SUCCESS) { fprintf(stderr, "Could not connect to AFC!\n"); goto leave_cleanup; } } #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_archive(ipc, appid, client_opts, status_cb, NULL); #else instproxy_archive(ipc, appid, client_opts, status_cb); #endif instproxy_client_options_free(client_opts); wait_for_op_complete = 1; if (skip_uninstall) { notification_expected = 0; } else { notification_expected = 1; } idevice_wait_for_operation_to_complete(); if (copy_path) { if (err_occured) { afc_client_free(afc); afc = NULL; goto leave_cleanup; } FILE *f = NULL; uint64_t af = 0; /* local filename */ char *localfile = NULL; if (asprintf(&localfile, "%s/%s.ipa", copy_path, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } free(copy_path); f = fopen(localfile, "wb"); if (!f) { fprintf(stderr, "ERROR: fopen: %s: %s\n", localfile, strerror(errno)); free(localfile); goto leave_cleanup; } /* remote filename */ char *remotefile = NULL; if (asprintf(&remotefile, "%s/%s.zip", APPARCH_PATH, appid) < 0) { fprintf(stderr, "Out of memory!?\n"); goto leave_cleanup; } uint32_t fsize = 0; char **fileinfo = NULL; if ((afc_get_file_info(afc, remotefile, &fileinfo) != AFC_E_SUCCESS) || !fileinfo) { fprintf(stderr, "ERROR getting AFC file info for '%s' on device!\n", remotefile); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } int i; for (i = 0; fileinfo[i]; i+=2) { if (!strcmp(fileinfo[i], "st_size")) { fsize = atoi(fileinfo[i+1]); break; } } i = 0; while (fileinfo[i]) { free(fileinfo[i]); i++; } free(fileinfo); if (fsize == 0) { fprintf(stderr, "Hm... remote file length could not be determined. Cannot copy.\n"); fclose(f); free(remotefile); free(localfile); goto leave_cleanup; } if ((afc_file_open(afc, remotefile, AFC_FOPEN_RDONLY, &af) != AFC_E_SUCCESS) || !af) { fclose(f); fprintf(stderr, "ERROR: could not open '%s' on device for reading!\n", remotefile); free(remotefile); free(localfile); goto leave_cleanup; } /* copy file over */ printf("Copying '%s' --> '%s'... ", remotefile, localfile); free(remotefile); free(localfile); uint32_t amount = 0; uint32_t total = 0; char buf[8192]; do { if (afc_file_read(afc, af, buf, sizeof(buf), &amount) != AFC_E_SUCCESS) { fprintf(stderr, "AFC Read error!\n"); break; } if (amount > 0) { size_t written = fwrite(buf, 1, amount, f); if (written != amount) { fprintf(stderr, "Error when writing %d bytes to local file!\n", amount); break; } total += written; } } while (amount > 0); afc_file_close(afc, af); fclose(f); printf("DONE.\n"); if (total != fsize) { fprintf(stderr, "WARNING: remote and local file sizes don't match (%d != %d)\n", fsize, total); if (remove_after_copy) { fprintf(stderr, "NOTE: archive file will NOT be removed from device\n"); remove_after_copy = 0; } } if (remove_after_copy) { /* remove archive if requested */ printf("Removing '%s'\n", appid); cmd = CMD_REMOVE_ARCHIVE; free(options); options = NULL; if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(phone, &client, "ideviceinstaller")) { fprintf(stderr, "Could not connect to lockdownd. Exiting.\n"); goto leave_cleanup; } goto run_again; } } goto leave_cleanup; } else if (cmd == CMD_RESTORE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_restore(ipc, appid, NULL, status_cb, NULL); #else instproxy_restore(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; notification_expected = 1; } else if (cmd == CMD_REMOVE_ARCHIVE) { #ifdef HAVE_LIBIMOBILEDEVICE_1_1 instproxy_remove_archive(ipc, appid, NULL, status_cb, NULL); #else instproxy_remove_archive(ipc, appid, NULL, status_cb); #endif wait_for_op_complete = 1; } else { printf ("ERROR: no operation selected?! This should not be reached!\n"); res = -2; goto leave_cleanup; } if (client) { /* not needed anymore */ lockdownd_client_free(client); client = NULL; } idevice_wait_for_operation_to_complete(); leave_cleanup: if (bundleidentifier) { free(bundleidentifier); } if (np) { np_client_free(np); } if (ipc) { instproxy_client_free(ipc); } if (afc) { afc_client_free(afc); } if (client) { lockdownd_client_free(client); } idevice_free(phone); if (udid) { free(udid); } if (appid) { free(appid); } if (options) { free(options); } return res; }