示例#1
0
ZipEntry *ZipEntry::Create(const wxString &path) {
  wxFile file(path);

  int error;
  auto zipFile = zip_fdopen(file.fd(), ZIP_RDONLY, &error);
  file.Detach();
  if (zipFile == nullptr) {
    throw error;
  }
  auto mutex = new wxMutex();
  ZipEntry *root = new ZipEntry(zipFile, mutex, "");

  std::vector<wxString> innerPaths;

  int num_entries = zip_get_num_entries(zipFile, ZIP_FL_UNCHANGED);
  for (int i = 0; i < num_entries; i++) {
    auto path = wxString(zip_get_name(zipFile, i, ZIP_FL_UNCHANGED));
    innerPaths.push_back(path);
  }

  std::sort(innerPaths.begin(), innerPaths.end());
  std::map<wxString, ZipEntry *> entryMap;

  entryMap[""] = root;
  for (auto &path : innerPaths) {
    AddChildrenFromPath(zipFile, mutex, entryMap, path);
  }

  return root;
}
示例#2
0
archive_t arch_zip_read(const char* name,int buf){
    archive_t arch=(archive_t)HREmalloc(NULL,sizeof(struct archive_s));
    arch_init(arch);
    int err;
    arch->archive=zip_open(name,ZIP_CHECKCONS,&err);
    if (arch->archive==NULL){
        char errstr[1024];
        zip_error_to_str(errstr, sizeof(errstr), err, errno);
        Abort("cannot open zip archive `%s': %s\n",name , errstr);
    }
    arch->stream_index=SIcreate();
#ifdef LIBZIP_VERSION
    int count=zip_get_num_entries(arch->archive,0);
#else
    int count=zip_get_num_files(arch->archive);
#endif
    for(int i=0;i<count;i++){
        struct zip_stat sb;
        int res=zip_stat_index(arch->archive,i,0,&sb);
        if (res<0) {
            Abort("cannot stat zip archive: %s\n",zip_strerror(arch->archive));
        }
        SIputAt(arch->stream_index,sb.name,i);
        Print(infoShort,"stream %d is %s",i,sb.name);
    }
    arch->procs.contains=zip_contains;
    arch->procs.read=hre_zip_read;
    arch->procs.read_raw=hre_zip_read_raw;
    arch->procs.enumerator=zip_enum;
    arch->procs.close=hre_zip_close;
    arch->buf=buf;
    return arch;
}
示例#3
0
文件: jar_file.cpp 项目: Dthird/CBMC
bool get_jar_index(
  const std::string &jar_file,
  std::vector<std::string> &entries)
{
  #ifdef HAVE_LIBZIP
  int zip_error;
  struct zip *zip=zip_open(jar_file.c_str(), 0, &zip_error);

  if(zip==NULL)
    return true;
  
  std::size_t number_of_files=zip_get_num_entries(zip, 0);
  
  for(std::size_t index=0; index<number_of_files; index++)
  {
    std::string file_name=zip_get_name(zip, index, 0);
    entries.push_back(file_name);
  }
  
  zip_close(zip);
  
  return false;
  #else
  return true;
  #endif
}
示例#4
0
文件: jar_file.cpp 项目: lihaol/cbmc
void jar_filet::open(const std::string &filename)
{
  #ifdef HAVE_LIBZIP
  if(zip!=nullptr)
    zip_close(static_cast<struct zip *>(zip));

  int zip_error;
  zip=zip_open(filename.c_str(), 0, &zip_error);

  if(zip!=nullptr)
  {
    std::size_t number_of_files=
      zip_get_num_entries(static_cast<struct zip *>(zip), 0);

    index.reserve(number_of_files);

    for(std::size_t i=0; i<number_of_files; i++)
    {
      std::string file_name=
        zip_get_name(static_cast<struct zip *>(zip), i, 0);
      index.push_back(file_name);
    }
  }
  #else
  zip=nullptr;
  #endif
}
示例#5
0
static void vfs_zipfile_init_pathmap(VFSNode *node) {
	VFSZipFileData *zdata = node->data1;
	VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true);
	zip_int64_t num = zip_get_num_entries(tls->zip, 0);

	ht_create(&zdata->pathmap);

	for(zip_int64_t i = 0; i < num; ++i) {
		const char *original = zip_get_name(tls->zip, i, 0);
		char normalized[strlen(original) + 1];

		vfs_path_normalize(original, normalized);

		if(*normalized) {
			char *c = strchr(normalized, 0) - 1;
			if(*c == '/') {
				*c = 0;
			}
		}

		if(strcmp(original, normalized)) {
			ht_set(&zdata->pathmap, normalized, i);
		}
	}
}
示例#6
0
size_t Unzip(const char *dst_path_, const char *archive, const UnzipFileHandler& handler)
{
    struct zip *za;
    struct zip_file *zf;
    struct zip_stat sb;
    char buf[1024];
    size_t ret = 0;
    std::string dst_path = dst_path_;

    int err;
    if ((za = zip_open(archive, 0, &err)) == nullptr) {
        zip_error_to_str(buf, sizeof(buf), err, errno);
        return false;
    }

    for (int i = 0; i < zip_get_num_entries(za, 0); ++i) {
        if (zip_stat_index(za, i, 0, &sb) == 0) {
            std::string dstpath = dst_path + '/' + sb.name;

            if (dstpath.back() == '/') {
                std::experimental::filesystem::create_directories(dstpath.c_str());
            }
            else {
                zf = zip_fopen_index(za, i, 0);
                if (!zf) {
                    goto bail_out;
                }

                FILE *of = fopen(dstpath.c_str(), "wb");
                if (of == nullptr) {
                    goto bail_out;
                }

                size_t sum = 0;
                while (sum != sb.size) {
                    size_t len = (size_t)zip_fread(zf, buf, sizeof(buf));
                    if (len < 0) {
                        fclose(of);
                        goto bail_out;
                    }
                    fwrite(buf, 1, len, of);
                    sum += len;
                }
                fclose(of);
                zip_fclose(zf);
                if (handler) { handler(dstpath.c_str()); }
                ++ret;
            }
        }
    }

    if (zip_close(za) == -1) {
        return false;
    }
    return ret;

bail_out:
    zip_close(za);
    return ret;
}
示例#7
0
QStringList KaraokePlayable_ZIP::enumerate()
{
    QStringList filelist;

    // http://www.nih.at/libzip/zip_get_num_entries.html
    int files = zip_get_num_entries( m_zip, ZIP_FL_UNCHANGED );

    if ( files == 0 )
    {
        m_errorMsg = "archive has no files";
        return filelist;
    }

    for ( int i = 0; i < files; i++ )
    {
        // Retrieve the file size
        struct zip_stat fileinfo;

        // http://www.nih.at/libzip/zip_stat_index.html
        if ( zip_stat_index( m_zip, i, 0, &fileinfo) != 0 )
        {
            m_errorMsg = "file info not found";
            return QStringList();
        }

        filelist.push_back( decodeFilename( fileinfo.name ) );
    }

    return filelist;
}
示例#8
0
void ZipReader::readFileInfo()
{
	zip_int64_t count = zip_get_num_entries(m_archive, 0);
	for (zip_int64_t i = 0; i < count; ++i) {
		QString name = QString::fromUtf8(zip_get_name(m_archive, i, 0));
		m_files.insert(name, i);
	}
}
bool Upgrader::unzipper(int targetfile)
{
    bfs::path target = path(DATA) / "upgrade";
    if (!verifyPath(target.c_str(), true)) {return false;}

    const char *targetzip = (target / targetswitch(targetfile)).string().c_str();

    struct zip *archive;
    struct zip_file *zipfile;
    struct zip_stat filestat;
    char buffer[1024*1024];
    FILE *file;
    int bufferlength, err;
    unsigned long long sum;

    printf("Extracting %s\n", targetzip);

    if ((archive = zip_open(targetzip, 0, &err)) == NULL) {
        printf("Failed to open archive %s\n", targetzip);
        return false;
    }
 
    for (unsigned int i = 0; i < zip_get_num_entries(archive, 0); i++) 
    {
        if (zip_stat_index(archive, i, 0, &filestat) == 0)
        {
            verifyPath((target / filestat.name).parent_path(), true);
            if (!is_directory(target / filestat.name))
            {
                zipfile = zip_fopen_index(archive, i, 0);
                if (!zipfile) {
                    printf("Could not open %s in archive\n", filestat.name);
                    continue;
                }

                file = fopen((target / filestat.name).string().c_str(), "w");
 
                sum = 0;
                while (sum != filestat.size) {
                    bufferlength = zip_fread(zipfile, buffer, 1024*1024);
                    fwrite(buffer, sizeof(char), bufferlength, file);
                    sum += bufferlength;
                }
                printf("Finished extracting %s\n", filestat.name);
                fclose(file);
                zip_fclose(zipfile);
            }
        }
    }
    if (zip_close(archive) == -1) 
    {
        printf("Can't close zip archive %s\n", targetzip);
        return false;
    }

    bfs::remove(target / targetswitch(targetfile));
    return true;
}
示例#10
0
	COpcPackageReader::COpcPackageReader(_In_ PImportStream pImportStream)
	{
		if (pImportStream.get() == nullptr)
			throw CNMRException(NMR_ERROR_INVALIDPARAM);

		m_ZIPError.str = nullptr;
		m_ZIPError.sys_err = 0;
		m_ZIPError.zip_err = 0;
		m_ZIParchive = nullptr;
		m_ZIPsource = nullptr;

		try {
			// determine stream size
			nfUint64 nStreamSize = pImportStream->retrieveSize();
			pImportStream->seekPosition(0, true);

			if (nStreamSize == 0)
				throw CNMRException(NMR_ERROR_COULDNOTGETSTREAMPOSITION);

			// read ZIP into memory
			m_Buffer.resize ((size_t) nStreamSize);
			pImportStream->readBuffer(&m_Buffer[0], nStreamSize, true);

			// create ZIP objects
			zip_error_init(&m_ZIPError);
			m_ZIPsource = zip_source_buffer_create(&m_Buffer[0], (size_t) nStreamSize, 0, &m_ZIPError);
			if (m_ZIPsource == nullptr)
				throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE);

			m_ZIParchive = zip_open_from_source(m_ZIPsource, ZIP_RDONLY | ZIP_CHECKCONS, &m_ZIPError);
			if (m_ZIParchive == nullptr)
				throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE);

			// Get ZIP Content
			nfInt64 nEntryCount = zip_get_num_entries(m_ZIParchive, ZIP_FL_UNCHANGED);
			if (nEntryCount < 0)
				throw CNMRException(NMR_ERROR_COULDNOTREADZIPFILE);

			// List Entries
			nfInt64 nIndex;
			for (nIndex = 0; nIndex < nEntryCount; nIndex++) {
				const char * pszName = zip_get_name(m_ZIParchive, (nfUint64) nIndex, ZIP_FL_ENC_GUESS);
				std::string sUTF8Name(pszName);
				std::wstring sUTF16Name = fnUTF8toUTF16(sUTF8Name);
				m_ZIPEntries.insert(std::make_pair(sUTF16Name, nIndex));
			}

			readContentTypes();
			readRootRelationships();

		}
		catch (...)
		{
			releaseZIP();
			throw;
		}
	}
示例#11
0
struct VDirEntry* _vdzListNext(struct VDir* vd) {
	struct VDirZip* vdz = (struct VDirZip*) vd;
	zip_int64_t maxIndex = zip_get_num_entries(vdz->z, 0);
	if (maxIndex <= vdz->dirent.index + 1) {
		return 0;
	}
	++vdz->dirent.index;
	return &vdz->dirent.d;
}
示例#12
0
int
main(int argc, char *argv[])
{
    const char *archive;
    struct zip *za;
    char buf[100];
    int err;
    int i;

    prg = argv[0];

    if (argc != 2) {
	fprintf(stderr, "usage: %s archive\n", prg);
	return 1;
    }

    archive = argv[1];
    
    if ((za=zip_open(archive, 0, &err)) == NULL) {
	zip_error_to_str(buf, sizeof(buf), err, errno);
	fprintf(stderr, "%s: can't open zip archive `%s': %s\n", prg,
		archive, buf);
	return 1;
    }

    if (zip_set_archive_comment(za, new_archive_comment,
				(zip_uint16_t)strlen(new_archive_comment)) < 0) {
	zip_error_to_str(buf, sizeof(buf), err, errno);
	fprintf(stderr, "%s: zip_set_archive_comment failed: %s\n",
		prg, buf);
    }

    for (i=0; i<zip_get_num_entries(za, 0); i++) {
	snprintf(buf, sizeof(buf), "File comment no %d", i);
	if (zip_file_set_comment(za, i, buf, (zip_uint16_t)strlen(buf), 0) < 0) {
	    zip_error_to_str(buf, sizeof(buf), err, errno);
	    fprintf(stderr, "%s: zip_set_file_comment on file %d failed: %s\n",
		    prg, i, buf);
	}
    }

    if (zip_unchange_all(za) == -1) {
	fprintf(stderr, "%s: can't revert changes to archive `%s'\n",
		prg, archive);
	return 1;
    }

    if (zip_close(za) == -1) {
	fprintf(stderr, "%s: can't close zip archive `%s': %s\n", prg, archive, zip_strerror(za));
	return 1;
    }

    return 0;
}
示例#13
0
static const char* vfs_zipfile_iter(VFSNode *node, void **opaque) {
	VFSZipFileData *zdata = node->data1;
	VFSZipFileIterData *idata = *opaque;
	VFSZipFileTLS *tls = vfs_zipfile_get_tls(node, true);

	if(!idata) {
		*opaque = idata = calloc(1, sizeof(VFSZipFileIterData));
		idata->num = zip_get_num_entries(tls->zip, 0);
	}

	return vfs_zipfile_iter_shared(node, zdata, idata, tls);
}
示例#14
0
文件: Zip.hpp 项目: det/RapidTools
	void iterateFiles(FunctorT Functor)
	{
		struct zip_stat Stat;
		auto NumEntries = zip_get_num_entries(mZip, 0);
		for (zip_uint64_t I = 0; I != NumEntries; ++I)
		{
			auto Error = zip_stat_index(mZip, I, 0, &Stat);
			if (Error != 0) throw std::runtime_error{"Error reading zip"};
			auto Length = std::char_traits<char>::length(Stat.name);
			if (Length == 0 || Stat.name[Length - 1] == '/') continue;
			auto File = ZipFileT{Stat.name, zip_fopen_index(mZip, I, 0)};
			Functor(File);
		}
	}
示例#15
0
static arch_enum_t zip_enum(archive_t archive,char *regex){
    if (regex!=NULL) Abort("regex not supported");
    arch_enum_t e=(arch_enum_t)HREmalloc(NULL,sizeof(struct arch_enum));
    e->procs.enumerate=zip_enumerate;
    e->procs.free=zip_enum_free;
    e->archive=archive;
    e->next=0;
#ifdef LIBZIP_VERSION
    e->count=zip_get_num_entries(archive->archive,0);
#else
    e->count=zip_get_num_files(archive->archive);
#endif
    return e;
}
示例#16
0
void ZipByteReader::Register(const std::map<std::string, size_t>& sequences)
{
    auto zipFile = m_zips.pop_or_create([this]() { return OpenZip(); });
    zip_stat_t stat;
    zip_stat_init(&stat);

    size_t numberOfEntries = 0;
    size_t numEntries = zip_get_num_entries(zipFile.get(), 0);
    for (size_t i = 0; i < numEntries; ++i) {
        int err = zip_stat_index(zipFile.get(), i, 0, &stat);
        if (ZIP_ER_OK != err)
            RuntimeError("Failed to get file info for index %d, zip library error: %s", (int)i, GetZipError(err).c_str());

        auto sequenceId = sequences.find(std::string(stat.name));
        if (sequenceId == sequences.end())
        {
            continue;
        }
        else
        {
            m_seqIdToIndex[sequenceId->second] = std::make_pair(stat.index, stat.size);
            numberOfEntries++;
        }
    }
    m_zips.push(std::move(zipFile));

    if (numberOfEntries != sequences.size())
    {
        // Not all sequences have been found. Let's print them out and throw.
        for (const auto& s : sequences)
        {
            auto index = m_seqIdToIndex.find(s.second);
            if (index == m_seqIdToIndex.end())
            {
                fprintf(stderr, "Sequence %s is not found in container %s.\n", s.first.c_str(), m_zipPath.c_str());
            }
        }

        RuntimeError("Cannot retrieve image data for some sequences. For more detail, please see the log file.");
    }
}
示例#17
0
static int fs_cd_file_zip(struct directory *parent, const char *filename)
{
    int isdirexist = 0;
    char buf[NAME_MAX];
    int len;
    zip_int64_t nentries, i;
    struct directory dir;

    if (strcmp(filename, "..") == 0) {
        sf_list_pop(&fs.directories);
        return SF_OK;
    }

    get_zip_cwd(buf, NAME_MAX);
    strcat(buf, filename);
    len = strlen(buf);
    buf[len++] = '/';
    buf[len] = '\0';

    nentries = zip_get_num_entries(parent->zip, 0);
    for (i = 0; i < nentries; ++i) {
        if (strncmp(zip_get_name(parent->zip, i, 0), buf, len) == 0) {
            isdirexist = 1;
            break;
        }
    }

    if (isdirexist) {
        strncpy(dir.name, filename, NAME_MAX);
        dir.iszip = 1;
        dir.isopened = 1;
        dir.zip = parent->zip;
        dir.nopens = parent->nopens + 1;
        sf_list_push(&fs.directories, &dir);
        return SF_OK;
    } else {
        sf_log(SF_LOG_ERR, "not a directory: %s", filename);
        return SF_ERR;
    }
}
示例#18
0
static int fs_file_walker_zip(struct directory *d,
                              int (*func)(int type, const char *filename,
                                          void *arg),
                              void *arg)
{
    char buf[PATH_MAX];
    size_t len;
    int ret = SF_OK;
    zip_int64_t nentries = zip_get_num_entries(d->zip, 0);
    zip_int64_t i;

    get_zip_cwd(buf, PATH_MAX);
    len = strlen(buf);

    for (i = 0; i < nentries; ++i) {
        const char *filename = zip_get_name(d->zip, i, 0);
        char *ptr;
        if (strncmp(filename, buf, len) == 0) {
            filename += len;
            if (*filename == '\0') {
                continue;
            }
            if ((ptr = strchr(filename, '/')) == NULL) {
                if ((ret = func(FS_FILE, filename, arg)) != SF_OK) {
                    break;
                }
            } else if (ptr == filename + strlen(filename) - 1) {
                char tmp[NAME_MAX];
                strncpy(tmp, filename, strlen(filename) - 1);
                tmp[strlen(filename) - 1] = '\0';
                if ((ret = func(FS_DIR, tmp, arg)) != SF_OK) {
                    break;
                }
            }
        }
    }
    return ret;
}
示例#19
0
文件: cnpy.cpp 项目: allebacco/cnpy
cnpy::NpArrayDict cnpy::npz_load(const std::string& fname)
{
    Handler<struct zip> zip = zip_open(fname.c_str(), ZIP_CHECKCONS, nullptr);
    if(zip.handle()==nullptr)
        throw std::runtime_error("Error opening npz file "+fname);

    NpArrayDict arrays;
    zip_uint64_t numFiles = zip_get_num_entries(zip.handle(), 0);
    for(zip_uint64_t fid=0; fid<numFiles; ++fid)
    {
        const char* arrName = zip_get_name(zip.handle(), fid, 0);
        if(arrName==nullptr)
            continue;

        Handler<struct zip_file> zipFile = zip_fopen_index(zip.handle(), fid, 0);

        std::string name = arrName;
        name.erase(name.size()-4);
        arrays.insert(NpArrayDictItem(name, load_the_npy_file(zipFile)));
    }

    return arrays;
}
示例#20
0
static jstatus_t __stdcall find(
	struct judgefs *fs,
	/* out */ const char **path,
	const char *prefix,
	/* in out */ void **context)
{
	struct zipfs *zipfs = (struct zipfs *)fs;
	uintptr_t *index = (uintptr_t *)context;
	zip_uint64_t num_entries;
	int zep;

	EnterCriticalSection(&zipfs->zip_cs);
	num_entries = zip_get_num_entries(zipfs->zip, ZIP_FL_NOCASE);

	while (1) {
		if (*index < num_entries) {
			const char *name = zip_get_name(zipfs->zip, *index, ZIP_FL_NOCASE);
			if (!name) {
				zip_error_get(zipfs->zip, &zep, NULL);
				LeaveCriticalSection(&zipfs->zip_cs);
				return zep_to_jstatus(zep);
			}
			++*index;
			if (strncmp(name, prefix, strlen(prefix)) == 0) {
				LeaveCriticalSection(&zipfs->zip_cs);
				*path = name;
				return JSTATUS_SUCCESS;
			}
		} else {
			LeaveCriticalSection(&zipfs->zip_cs);
			*path = NULL;
			*index = 0;
			return JSTATUS_SUCCESS;
		}
	}
}
示例#21
0
int
_unzip(char const* path, char const* outpath)
{
    int err;
    int i, len;
    int filelen;
    struct zip* archive;
    struct zip_file* file;
    struct zip_stat stat;
    int fd;
    size_t sum;
    char buf[4096];
    int outlen;
    char tmp[FILENAME_MAX];

    archive = zip_open(path, 0, &err);
    if (!archive) { return 1; }

    outlen = strlen(outpath);
    len = zip_get_num_entries(archive, 0);
    for (i = 0; i < len; i++)
    {
        if (zip_stat_index(archive, i, 0, &stat))
        {
            goto error;
        }

        filelen = strlen(stat.name);
        memcpy(tmp, outpath, outlen);
        memcpy(tmp + outlen, "/", 1);
        memcpy(tmp + outlen + 1, stat.name, filelen);
        tmp[outlen + filelen + 1] = '\0';

        if (tmp[outlen + filelen + 1 - 1] == '/')
        {
            if (mkdir(tmp, 0755))
            {
                fprintf(stderr, "Error: Creating directory: %s\n", tmp);
                goto error;
            }
        }
        else
        {
            file = zip_fopen_index(archive, i, 0);
            if (!file)
            {
                fprintf(stderr, "Error: Opening zip content: %s", tmp);
                goto error;
            }

            fd = open(tmp, O_RDWR | O_TRUNC | O_CREAT | BINARY, 0644);
            if (fd < 0)
            {
                fprintf(stderr, "Error: Opening file: %s\n", tmp);
                zip_fclose(file);
                goto error;
            }

            sum = 0;
            while (sum != stat.size)
            {
                filelen = zip_fread(file, buf, 4096);
                if (len < 0)
                {
                    fprintf(stderr, "Error: Reading file: %s\n", tmp);
                    close(fd);
                    zip_fclose(file);
                    goto error;
                }

                write(fd, buf, filelen);
                sum += filelen;
            }

            close(fd);
            zip_fclose(file);
        }
    }

    zip_close(archive);
    return 0;

error:
    zip_close(archive);
    return 1;
}
示例#22
0
文件: unzip.cpp 项目: Ayu222/android
int extract_to_cache(const char *archive, const char *cache_path)
{
  struct zip *ziparchive;
  struct zip_file *zipfile;
  struct zip_stat zipstat;
  char buf[4096];
  int err;
  int i, len;
  int fd;
  int dirname_len;
  long long sum;
  char *full_path;
  char *dir_name;
  Stat localfile;
  utimbuf modified;
  android_printf("unzip: Preparing to cache. This could take a while...");

  if ((ziparchive = zip_open(archive, 0, &err)) == NULL)
  {
    zip_error_to_str(buf, sizeof(buf), err, errno);
    android_printf("unzip error: can't open archive %s/n",archive);
    return 1;
  }

  mkpath(cache_path);

  for (i = 0; i < zip_get_num_entries(ziparchive, 0); i++)
  {
    if (zip_stat_index(ziparchive, i, 0, &zipstat) != 0)
    {
      android_printf("unzip error: can't open entry: %i/n",i);
      continue;
    }

    if(strncmp (zipstat.name,"assets/",7) != 0)
      continue;

    modified.modtime = modified.actime = zipstat.mtime;

    full_path = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + strlen(zipstat.name) + 1));
    sprintf(full_path, "%s/%s",cache_path,zipstat.name);

    if (zipstat.name[strlen(zipstat.name) - 1] == '/')
    {
      mkpath(full_path);
      free(full_path);
      continue;
    }

    zipfile = zip_fopen_index(ziparchive, i, 0);
    if (!zipfile)
    {
      android_printf("unzip error: can't open index");
      free(full_path);
      continue;
    }

    if (stat(full_path, &localfile) != 0)
    {
      dirname_len = strrchr(zipstat.name,'/') - zipstat.name;
      dir_name = (char*)malloc( sizeof(char*) * (strlen(cache_path) + 1 + dirname_len + 1));
      strncpy(dir_name, full_path, strlen(cache_path) + dirname_len + 1);
      dir_name[strlen(cache_path) + dirname_len + 1] = '\0';
      mkpath(dir_name);
      free(dir_name);
    }
    else if (localfile.st_mtime == zipstat.mtime)
    {
      free(full_path);
      continue;
    }

    fd = open(full_path, O_RDWR | O_TRUNC | O_CREAT, 0644);
    if(fd < 0)
    {
      android_printf("unzip error: could not open %s",full_path);
      free(full_path);
      continue;
    }

    sum = 0;
    while (sum != zipstat.size)
    {
      len = zip_fread(zipfile, buf, 4096);
      if (len < 0)
      {
        android_printf("unzip error: no data in %s",full_path);
        free(full_path);
        continue;
      }
      write(fd, buf, len);
      sum += len;
    }
    close(fd);
    zip_fclose(zipfile);

    if (stat(full_path, &localfile) == 0)
    {
      // save the zip time. this way we know for certain if we need to refresh.
      utime(full_path, &modified);
    }
    else
    {
      android_printf("unzip error: failed to extract %s",full_path);
    }

    free(full_path);
  }

  if (zip_close(ziparchive) == -1)
    android_printf("unzip error: can't close zip archive `%s'/n", archive);

  return 0;
}
示例#23
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
}
示例#24
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;
}
示例#25
0
static int zip_append(const struct sr_output *o, unsigned char *buf,
		int unitsize, int length)
{
	struct out_context *outc;
	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];

	outc = o->priv;
	if (!(archive = zip_open(outc->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, length, 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;
}
示例#26
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
}
示例#27
0
struct input_file *read_file_list (int argc, char **argv,
                                   int *nf_r, char *errstr) {
  struct input_file *list = (struct input_file *) NULL;

  FILE *fp = (FILE *) NULL;
  char line[16384], *av, *p, *s;

  int a, f, nf = 0;

#ifndef _WIN32
  glob_t gbuf;
  int rv, op;

  /* Init */
  gbuf.gl_pathv = (char **) NULL;
#endif

  int is_zip;

#ifdef ZIPSUPPORT
  zip_t *z = (zip_t *) NULL;
  zip_error_t ze;
  struct zip_stat sb;

  int zerrno;
  int ent, nent;
  const char *name;
  int namelen;

  zip_uint8_t opsys;
  zip_uint32_t extattr;
#endif

  /* Loop over arguments */
  for(a = 0; a < argc; a++) {
    av = argv[a];

    if(*av == '@') {  /* @list form */
      av++;  /* skip past the @ */

      is_zip = is_zip_file(av, errstr);
      if(is_zip < 0)
        goto error;

      if(is_zip) {
#ifdef ZIPSUPPORT
        z = zip_open(av, 0, &zerrno);
        if(!z) {
          zip_error_init_with_code(&ze, zerrno);
          report_err(errstr, "zip_open: %s: %s",
                     av, zip_error_strerror(&ze));
          zip_error_fini(&ze);
          goto error;
        }
        
        nent = zip_get_num_entries(z, 0);
        if(nent < 0) {
          report_err(errstr, "zip_get_num_entries: %s",
                     zip_strerror(z));
          goto error;
        }
        
        for(ent = 0; ent < nent; ent++) {
          if(zip_stat_index(z, ent, 0, &sb)) {
            report_err(errstr, "zip_stat_index(%d): %s\n",
                       ent, zip_strerror(z));
            goto error;
          }
          
          if(zip_file_get_external_attributes(z, ent, 0, &opsys, &extattr)) {
            report_err(errstr, "zip_get_external_attributes(%d): %s\n",
                       ent, zip_strerror(z));
            goto error;
          }
          
          name = sb.name;
          namelen = strlen(name);
          
          if((opsys != ZIP_OPSYS_AMIGA && extattr & 0x10) ||
             (namelen > 0 && name[namelen-1] == '/'))
            /* Is directory */
            continue;
          
          /* Otherwise, add to list */
          list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file));
          if(!list) {
            report_syserr(errstr, "realloc");
            goto error;
          }
          
          s = strdup(name);
          if(!s) {
            report_syserr(errstr, "strdup");
            goto error;
          }
          
          list[nf].filename = s;
          list[nf].ient = ent;
          list[nf].iarg = a;
          list[nf].arg = av;
          nf++;
        }
        
        if(zip_close(z)) {
          report_err(errstr, "zip_close: %s",
                     zip_strerror(z));
          goto error;
        }

        z = (zip_t *) NULL;
#else
        report_err(errstr, "not compiled with zip support");
        goto error;
#endif
      }
      else {
        fp = fopen(av, "r");
        if(!fp) {
          report_syserr(errstr, "open: %s", av);
          goto error;
        }
        
        while(fgets(line, sizeof(line), fp)) {
          p = sstrip(line);
          
          if(*p) {
            list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file));
            if(!list) {
              report_syserr(errstr, "realloc");
              goto error;
            }
            
            s = strdup(p);
            if(!s) {
              report_syserr(errstr, "strdup");
              goto error;
            }
            
            list[nf].filename = s;
            list[nf].ient = -1;
            list[nf].iarg = a;
            list[nf].arg = av;
            nf++;
          }
        }
        
        if(ferror(fp)) {
          report_syserr(errstr, "read: %s", av);
          goto error;
        }
        
        fclose(fp);
        fp = (FILE *) NULL;
      }
    }
    else {  /* glob or single filename */
#ifndef _WIN32
      rv = glob(av, 0, NULL, &gbuf);
      if(rv == 0) {  /* succeeded */
        /* Allocate block */
        list = (struct input_file *) realloc(list,
                                             (nf+gbuf.gl_pathc) * sizeof(struct input_file));
        if(!list) {
          report_syserr(errstr, "realloc");
          goto error;
        }

        /* Zero out the new pointers */
        memset(list+nf, 0, gbuf.gl_pathc * sizeof(struct input_file));

        /* Record so we know to free them */
        op = nf;

        nf += gbuf.gl_pathc;
        
        for(f = 0; f < gbuf.gl_pathc; f++) {
          s = strdup(gbuf.gl_pathv[f]);
          if(!s) {
            report_syserr(errstr, "strdup");
            goto error;
          }

          list[op].filename = s;
          list[op].ient = -1;
          list[op].iarg = a;
          list[op].arg = av;
          op++;
        }

        globfree(&gbuf);
        gbuf.gl_pathv = (char **) NULL;
      }
      else if(rv == GLOB_NOMATCH) {  /* no match */
#endif  /* _WIN32 */

        /* Assume it's a single entry. */
        list = (struct input_file *) realloc(list, (nf+1) * sizeof(struct input_file));
        if(!list) {
          report_syserr(errstr, "realloc");
          goto error;
        }
        
        s = strdup(av);
        if(!s) {
          report_syserr(errstr, "strdup");
          goto error;
        }
        
        list[nf].filename = s;
        list[nf].ient = -1;
        list[nf].iarg = a;
        list[nf].arg = av;
        nf++;
#ifndef _WIN32
      }
      else {
        report_err(errstr, "glob error: %s", av);
        goto error;
      }
#endif
    }
  }

  *nf_r = nf;

  return(list);

 error:
  if(fp)
    fclose(fp);

#ifndef _WIN32
  if(gbuf.gl_pathv)
    globfree(&gbuf);
#endif

#ifdef ZIPSUPPORT
  if(z) {
    zip_close(z);
    z = (zip_t *) NULL;
  }
#endif

  if(list) {
    for(f = 0; f < nf; f++)
      if(list[f].filename)
        free((void *) list[f].filename);

    free((void *) list);
  }

  return((struct input_file *) NULL);
}
示例#28
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;
}
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;
}