Example #1
0
/**
 * 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;
}
Example #2
0
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;
}
Example #4
0
/**
 * 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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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);
}
Example #8
0
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;
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
0
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;
}
Example #12
0
/* 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;
}
Example #13
0
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_);
}
Example #14
0
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
}
Example #15
0
/**
 * 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;
}
Example #16
0
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
}
Example #17
0
 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);
   }
 }
Example #18
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;
}