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; }
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; }