예제 #1
0
bool OdinPatcher::Impl::patchTar()
{
#ifdef __ANDROID__
    static const char *prefix = "/proc/self/fd/";
    fd = -1;
    if (StringUtils::starts_with(info->inputPath(), prefix)) {
        std::string fdStr = info->inputPath().substr(strlen(prefix));
        if (!convertToInt(fdStr.c_str(), &fd)) {
            LOGE("Invalid fd: %s", fdStr.c_str());
            error = ErrorCode::FileOpenError;
            return false;
        }
        LOGD("Input path '%s' is a file descriptor: %d",
             info->inputPath().c_str(), fd);
    }
#endif

    // Get file size for progress information
#ifdef __ANDROID__
    if (fd > 0) {
        off64_t offset = lseek64(fd, 0, SEEK_END);
        if (offset < 0 || lseek64(fd, 0, SEEK_SET) < 0) {
            LOGE("%s: Failed to seek fd: %s", info->inputPath().c_str(),
                 strerror(errno));
            error = ErrorCode::FileSeekError;
            return false;
        }
        maxBytes = offset;
    } else {
#endif

    io::File file;
    if (!file.open(info->inputPath(), io::File::OpenRead)) {
        LOGE("%s: Failed to open: %s", info->inputPath().c_str(),
             file.errorString().c_str());
        error = ErrorCode::FileOpenError;
        return false;
    }
    if (!file.seek(0, io::File::SeekEnd)) {
        LOGE("%s: Failed to seek: %s", info->inputPath().c_str(),
             file.errorString().c_str());
        error = ErrorCode::FileReadError;
        return false;
    }
    if (!file.tell(&maxBytes)) {
        LOGE("%s: Failed to get position: %s", info->inputPath().c_str(),
             file.errorString().c_str());
        error = ErrorCode::FileReadError;
        return false;
    }
    file.close();

#ifdef __ANDROID__
    }
#endif

    updateProgress(bytes, maxBytes);

    if (!openInputArchive()) {
        return false;
    }
    if (!openOutputArchive()) {
        return false;
    }

    if (cancelled) return false;

    if (!processContents()) {
        return false;
    }

    std::vector<CopySpec> toCopy{
        {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/odinupdater",
            "META-INF/com/google/android/update-binary.orig"
        }, {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/odinupdater.sig",
            "META-INF/com/google/android/update-binary.orig.sig"
        }, {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/fuse-sparse",
            "fuse-sparse"
        }, {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/fuse-sparse.sig",
            "fuse-sparse.sig"
        }, {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/mbtool_recovery",
            "META-INF/com/google/android/update-binary"
        }, {
            pc->dataDirectory() + "/binaries/android/"
                    + mb_device_architecture(info->device())
                    + "/mbtool_recovery.sig",
            "META-INF/com/google/android/update-binary.sig"
        }, {
            pc->dataDirectory() + "/scripts/bb-wrapper.sh",
            "multiboot/bb-wrapper.sh"
        }, {
            pc->dataDirectory() + "/scripts/bb-wrapper.sh.sig",
            "multiboot/bb-wrapper.sh.sig"
        }
    };

    zipFile zf = MinizipUtils::ctxGetZipFile(zOutput);

    ErrorCode result;

    for (const CopySpec &spec : toCopy) {
        if (cancelled) return false;

        updateDetails(spec.target);

        result = MinizipUtils::addFile(zf, spec.target, spec.source);
        if (result != ErrorCode::NoError) {
            error = result;
            return false;
        }
    }

    if (cancelled) return false;

    updateDetails("multiboot/info.prop");

    const std::string infoProp =
            MultiBootPatcher::createInfoProp(pc, info->romId());
    result = MinizipUtils::addFile(
            zf, "multiboot/info.prop",
            std::vector<unsigned char>(infoProp.begin(), infoProp.end()));
    if (result != ErrorCode::NoError) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateDetails("block_devs.prop");

    std::string blockDevsProp;
    blockDevsProp += "system=";
    blockDevsProp += mb_device_system_block_devs(info->device())[0];
    blockDevsProp += "\n";
    blockDevsProp += "boot=";
    blockDevsProp += mb_device_boot_block_devs(info->device())[0];
    blockDevsProp += "\n";
    result = MinizipUtils::addFile(
            zf, "block_devs.prop", std::vector<unsigned char>(
                    blockDevsProp.begin(), blockDevsProp.end()));
    if (result != ErrorCode::NoError) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateDetails("multiboot/device.json");

    char *json = mb_device_to_json(info->device());
    if (!json) {
        error = ErrorCode::MemoryAllocationError;
        return false;
    }

    result = MinizipUtils::addFile(
            zf, "multiboot/device.json",
            std::vector<unsigned char>(json, json + strlen(json)));
    free(json);

    if (result != ErrorCode::NoError) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    return true;
}
예제 #2
0
bool MultiBootPatcher::Impl::patchZip()
{
    std::unordered_set<std::string> excludeFromPass1;

    for (auto const &item : info->patchInfo()->autoPatchers()) {
        auto args = info->patchInfo()->autoPatcherArgs(item);

        auto *ap = pc->createAutoPatcher(item, info, args);
        if (!ap) {
            error = PatcherError::createPatcherCreationError(
                    ErrorCode::AutoPatcherCreateError, item);
            return false;
        }

        // TODO: AutoPatcher::newFiles() is not supported yet

        std::vector<std::string> existingFiles = ap->existingFiles();
        if (existingFiles.empty()) {
            pc->destroyAutoPatcher(ap);
            continue;
        }

        autoPatchers.push_back(ap);

        // AutoPatcher files should be excluded from the first pass
        for (auto const &file : existingFiles) {
            excludeFromPass1.insert(file);
        }
    }

    // Unlike the old patcher, we'll write directly to the new file
    if (!openOutputArchive()) {
        return false;
    }

    if (cancelled) return false;

    FileUtils::ArchiveStats stats;
    auto result = FileUtils::mzArchiveStats(info->filename(), &stats,
                                            std::vector<std::string>());
    if (!result) {
        error = result;
        return false;
    }

    maxBytes = stats.totalSize;

    if (cancelled) return false;

    // +1 for mbtool_recovery (update-binary)
    // +1 for bb-wrapper.sh
    // +1 for info.prop
    maxFiles = stats.files + 3;
    updateFiles(files, maxFiles);

    if (!openInputArchive()) {
        return false;
    }

    // Create temporary dir for extracted files for autopatchers
    std::string tempDir = FileUtils::createTemporaryDir(pc->tempDirectory());

    if (!pass1(zOutput, tempDir, excludeFromPass1)) {
        boost::filesystem::remove_all(tempDir);
        return false;
    }

    if (cancelled) return false;

    // On the second pass, run the autopatchers on the rest of the files

    if (!pass2(zOutput, tempDir, excludeFromPass1)) {
        boost::filesystem::remove_all(tempDir);
        return false;
    }

    boost::filesystem::remove_all(tempDir);

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("META-INF/com/google/android/update-binary");

    // Add mbtool_recovery
    result = FileUtils::mzAddFile(
            zOutput, "META-INF/com/google/android/update-binary",
            pc->dataDirectory() + "/binaries/android/"
                    + info->device()->architecture() + "/mbtool_recovery");
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("multiboot/bb-wrapper.sh");

    // Add bb-wrapper.sh
    result = FileUtils::mzAddFile(
        zOutput, "multiboot/bb-wrapper.sh",
        pc->dataDirectory() + "/scripts/bb-wrapper.sh");
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    updateFiles(++files, maxFiles);
    updateDetails("multiboot/info.prop");

    const std::string infoProp = createInfoProp();
    result = FileUtils::mzAddFile(
            zOutput, "multiboot/info.prop",
            std::vector<unsigned char>(infoProp.begin(), infoProp.end()));
    if (!result) {
        error = result;
        return false;
    }

    if (cancelled) return false;

    return true;
}