bool FileUtils::mzExtractFile(unzFile uf,
                              const std::string &directory)
{
    unz_file_info64 fi;
    std::string filename;

    if (!mzGetInfo(uf, &fi, &filename)) {
        return false;
    }

    std::string fullPath(directory);
    fullPath += "/";
    fullPath += filename;

    std::string parentPath = io::dirName(fullPath);
    if (!io::createDirectories(parentPath)) {
        FLOGW("%s: Failed to create directory: %s",
              parentPath.c_str(), io::lastErrorString().c_str());
    }

    io::File file;
    if (!file.open(fullPath, io::File::OpenWrite)) {
        FLOGE("%s: Failed to open for writing: %s",
              fullPath.c_str(), file.errorString().c_str());
        return false;
    }

    int ret = unzOpenCurrentFile(uf);
    if (ret != UNZ_OK) {
        FLOGE("miniunz: Failed to open inner file: %s",
              mzUnzErrorString(ret).c_str());
        return false;
    }

    int n;
    char buf[32768];
    uint64_t bytesWritten;

    while ((n = unzReadCurrentFile(uf, buf, sizeof(buf))) > 0) {
        if (!file.write(buf, n, &bytesWritten)) {
            FLOGE("%s: Failed to write file: %s",
                  fullPath.c_str(), file.errorString().c_str());
            unzCloseCurrentFile(uf);
            return false;
        }
    }
    if (n != 0) {
        FLOGE("miniunz: Finished before reaching inner file's EOF: %s",
              mzUnzErrorString(n).c_str());
    }

    ret = unzCloseCurrentFile(uf);
    if (ret != UNZ_OK) {
        FLOGE("miniunz: Failed to close inner file: %s",
              mzUnzErrorString(ret).c_str());
        return false;
    }

    return n == 0;
}
Exemple #2
0
PatcherError FileUtils::mzArchiveStats(const std::string &path,
                                       FileUtils::ArchiveStats *stats,
                                       std::vector<std::string> ignore)
{
    assert(stats != nullptr);

    unzFile uf = mzOpenInputFile(path);

    if (!uf) {
        FLOGE("minizip: Failed to open for reading: {}", path);
        return PatcherError::createArchiveError(
                ErrorCode::ArchiveReadOpenError, path);
    }

    uint64_t count = 0;
    uint64_t totalSize = 0;
    std::string name;
    unz_file_info64 fi;
    memset(&fi, 0, sizeof(fi));

    int ret = unzGoToFirstFile(uf);
    if (ret != UNZ_OK) {
        mzCloseInputFile(uf);
        return PatcherError::createArchiveError(
                ErrorCode::ArchiveReadHeaderError, std::string());
    }

    do {
        if (!mzGetInfo(uf, &fi, &name)) {
            mzCloseInputFile(uf);
            return PatcherError::createArchiveError(
                    ErrorCode::ArchiveReadHeaderError, std::string());
        }

        if (std::find(ignore.begin(), ignore.end(), name) == ignore.end()) {
            ++count;
            totalSize += fi.uncompressed_size;
        }
    } while ((ret = unzGoToNextFile(uf)) == UNZ_OK);

    if (ret != UNZ_END_OF_LIST_OF_FILE) {
        mzCloseInputFile(uf);
        return PatcherError::createArchiveError(
                ErrorCode::ArchiveReadHeaderError, std::string());
    }

    mzCloseInputFile(uf);

    stats->files = count;
    stats->totalSize = totalSize;

    return PatcherError();
}
ErrorCode FileUtils::mzArchiveStats(const std::string &path,
                                    FileUtils::ArchiveStats *stats,
                                    std::vector<std::string> ignore)
{
    assert(stats != nullptr);

    MzUnzCtx *ctx = mzOpenInputFile(path);

    if (!ctx) {
        FLOGE("miniunz: Failed to open for reading: %s", path.c_str());
        return ErrorCode::ArchiveReadOpenError;
    }

    uint64_t count = 0;
    uint64_t totalSize = 0;
    std::string name;
    unz_file_info64 fi;
    memset(&fi, 0, sizeof(fi));

    int ret = unzGoToFirstFile(ctx->uf);
    if (ret != UNZ_OK) {
        FLOGE("miniunz: Failed to move to first file: %s",
              mzUnzErrorString(ret).c_str());
        mzCloseInputFile(ctx);
        return ErrorCode::ArchiveReadHeaderError;
    }

    do {
        if (!mzGetInfo(ctx->uf, &fi, &name)) {
            mzCloseInputFile(ctx);
            return ErrorCode::ArchiveReadHeaderError;
        }

        if (std::find(ignore.begin(), ignore.end(), name) == ignore.end()) {
            ++count;
            totalSize += fi.uncompressed_size;
        }
    } while ((ret = unzGoToNextFile(ctx->uf)) == UNZ_OK);

    if (ret != UNZ_END_OF_LIST_OF_FILE) {
        FLOGE("miniunz: Finished before EOF: %s",
              mzUnzErrorString(ret).c_str());
        mzCloseInputFile(ctx);
        return ErrorCode::ArchiveReadHeaderError;
    }

    mzCloseInputFile(ctx);

    stats->files = count;
    stats->totalSize = totalSize;

    return ErrorCode::NoError;
}
bool FileUtils::mzReadToMemory(unzFile uf,
                               std::vector<unsigned char> *output,
                               void (*cb)(uint64_t bytes, void *), void *userData)
{
    unz_file_info64 fi;

    if (!mzGetInfo(uf, &fi, nullptr)) {
        return false;
    }

    std::vector<unsigned char> data;
    data.reserve(fi.uncompressed_size);

    int ret = unzOpenCurrentFile(uf);
    if (ret != UNZ_OK) {
        FLOGE("miniunz: Failed to open inner file: %s",
              mzUnzErrorString(ret).c_str());
        return false;
    }

    int n;
    char buf[32768];

    while ((n = unzReadCurrentFile(uf, buf, sizeof(buf))) > 0) {
        if (cb) {
            cb(data.size() + n, userData);
        }

        data.insert(data.end(), buf, buf + n);
    }
    if (n != 0) {
        FLOGE("miniunz: Finished before reaching inner file's EOF: %s",
              mzUnzErrorString(n).c_str());
    }

    ret = unzCloseCurrentFile(uf);
    if (ret != UNZ_OK) {
        FLOGE("miniunz: Failed to close inner file: %s",
              mzUnzErrorString(ret).c_str());
        return false;
    }

    if (n != 0) {
        return false;
    }

    data.swap(*output);
    return true;
}
Exemple #5
0
bool FileUtils::mzExtractFile(unzFile uf,
                              const std::string &directory)
{
    unz_file_info64 fi;
    std::string filename;

    if (!mzGetInfo(uf, &fi, &filename)) {
        return false;
    }

    std::string fullPath(directory);
    fullPath += "/";
    fullPath += filename;

    boost::filesystem::path path(fullPath);
    boost::filesystem::create_directories(path.parent_path());

    std::ofstream file(fullPath, std::ios::binary);
    if (file.fail()) {
        return false;
    }

    int ret = unzOpenCurrentFile(uf);
    if (ret != UNZ_OK) {
        return false;
    }

    int n;
    char buf[32768];

    while ((n = unzReadCurrentFile(uf, buf, sizeof(buf))) > 0) {
        file.write(buf, n);
    }

    unzCloseCurrentFile(uf);

    return n == 0;
}
Exemple #6
0
bool FileUtils::mzReadToMemory(unzFile uf,
                               std::vector<unsigned char> *output,
                               void (*cb)(uint64_t bytes, void *), void *userData)
{
    unz_file_info64 fi;

    if (!mzGetInfo(uf, &fi, nullptr)) {
        return false;
    }

    std::vector<unsigned char> data;
    data.reserve(fi.uncompressed_size);

    int ret = unzOpenCurrentFile(uf);
    if (ret != UNZ_OK) {
        return false;
    }

    int n;
    char buf[32768];

    while ((n = unzReadCurrentFile(uf, buf, sizeof(buf))) > 0) {
        if (cb) {
            cb(data.size() + n, userData);
        }

        data.insert(data.end(), buf, buf + n);
    }

    unzCloseCurrentFile(uf);

    if (n != 0) {
        return false;
    }

    data.swap(*output);
    return true;
}
Exemple #7
0
bool FileUtils::mzCopyFileRaw(unzFile uf,
                              zipFile zf,
                              const std::string &name,
                              void (*cb)(uint64_t bytes, void *), void *userData)
{
    unz_file_info64 ufi;

    if (!mzGetInfo(uf, &ufi, nullptr)) {
        return false;
    }

    bool zip64 = ufi.uncompressed_size >= ((1ull << 32) - 1);

    zip_fileinfo zfi;
    memset(&zfi, 0, sizeof(zfi));

    zfi.dosDate = ufi.dosDate;
    zfi.tmz_date.tm_sec = ufi.tmu_date.tm_sec;
    zfi.tmz_date.tm_min = ufi.tmu_date.tm_min;
    zfi.tmz_date.tm_hour = ufi.tmu_date.tm_hour;
    zfi.tmz_date.tm_mday = ufi.tmu_date.tm_mday;
    zfi.tmz_date.tm_mon = ufi.tmu_date.tm_mon;
    zfi.tmz_date.tm_year = ufi.tmu_date.tm_year;
    zfi.internal_fa = ufi.internal_fa;
    zfi.external_fa = ufi.external_fa;

    int method;
    int level;

    // Open raw file in input zip
    int ret = unzOpenCurrentFile2(
        uf,                     // file
        &method,                // method
        &level,                 // level
        1                       // raw
    );
    if (ret != UNZ_OK) {
        return false;
    }

    // Open raw file in output zip
    ret = zipOpenNewFileInZip2_64(
        zf,             // file
        name.c_str(),   // filename
        &zfi,           // zip_fileinfo
        nullptr,        // extrafield_local
        0,              // size_extrafield_local
        nullptr,        // extrafield_global
        0,              // size_extrafield_global
        nullptr,        // comment
        method,         // method
        level,          // level
        1,              // raw
        zip64           // zip64
    );
    if (ret != ZIP_OK) {
        unzCloseCurrentFile(uf);
        return false;
    }

    uint64_t bytes = 0;

    // Exceeds Android's default stack size, unfortunately, so allocate
    // on the heap
    std::vector<unsigned char> buf(1024 * 1024); // 1MiB
    int bytes_read;
    double ratio;

    while ((bytes_read = unzReadCurrentFile(uf, buf.data(), buf.size())) > 0) {
        bytes += bytes_read;
        if (cb) {
            // Scale this to the uncompressed size for the purposes of a
            // progress bar
            ratio = (double) bytes / ufi.compressed_size;
            cb(ratio * ufi.uncompressed_size, userData);
        }

        ret = zipWriteInFileInZip(zf, buf.data(), bytes_read);
        if (ret != ZIP_OK) {
            unzCloseCurrentFile(uf);
            zipCloseFileInZip(zf);
            return false;
        }
    }

    unzCloseCurrentFile(uf);
    zipCloseFileInZipRaw64(zf, ufi.uncompressed_size, ufi.crc);

    return bytes_read == 0;
}