From 37304f3cc920804c97d52df929b9871c057c55e0 Mon Sep 17 00:00:00 2001 From: xunchang Date: Tue, 12 Mar 2019 12:40:14 -0700 Subject: Implement FilePackage class This is another implementation of the Package class. And we will later need it when reading the package from FUSE. Bug: 127071893 Test: unit tests pass, sideload a file package on sailfish Change-Id: I3de5d5ef60b29c8b73517d6de3498459d7d95975 --- package.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 3 deletions(-) (limited to 'package.cpp') diff --git a/package.cpp b/package.cpp index d40427859..6c7289f3f 100644 --- a/package.cpp +++ b/package.cpp @@ -17,10 +17,12 @@ #include "package.h" #include +#include +#include #include #include -#include +#include #include "otautil/error_code.h" #include "otautil/sysutil.h" @@ -67,14 +69,38 @@ class MemoryPackage : public Package { ZipArchiveHandle zip_handle_; }; -// TODO(xunchang) Implement the PackageFromFd. - void Package::SetProgress(float progress) { if (set_progress_) { set_progress_(progress); } } +class FilePackage : public Package { + public: + FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path, + const std::function& set_progress); + + ~FilePackage() override; + + uint64_t GetPackageSize() const override { + return package_size_; + } + + bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override; + + ZipArchiveHandle GetZipArchiveHandle() override; + + bool UpdateHashAtOffset(const std::vector& hashers, uint64_t start, + uint64_t length) override; + + private: + android::base::unique_fd fd_; // The underlying fd to the open package. + uint64_t package_size_; + std::string path_; // The physical path to the package. + + ZipArchiveHandle zip_handle_; +}; + std::unique_ptr Package::CreateMemoryPackage( const std::string& path, const std::function& set_progress) { std::unique_ptr mmap = std::make_unique(); @@ -86,6 +112,23 @@ std::unique_ptr Package::CreateMemoryPackage( return std::make_unique(path, std::move(mmap), set_progress); } +std::unique_ptr Package::CreateFilePackage( + const std::string& path, const std::function& set_progress) { + android::base::unique_fd fd(open(path.c_str(), O_RDONLY)); + if (fd == -1) { + PLOG(ERROR) << "Failed to open " << path; + return nullptr; + } + + off64_t file_size = lseek64(fd.get(), 0, SEEK_END); + if (file_size == -1) { + PLOG(ERROR) << "Failed to get the package size"; + return nullptr; + } + + return std::make_unique(std::move(fd), file_size, path, set_progress); +} + std::unique_ptr Package::CreateMemoryPackage( std::vector content, const std::function& set_progress) { return std::make_unique(std::move(content), set_progress); @@ -152,3 +195,68 @@ ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() { return zip_handle_; } + +FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path, + const std::function& set_progress) + : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) { + set_progress_ = set_progress; +} + +FilePackage::~FilePackage() { + if (zip_handle_) { + CloseArchive(zip_handle_); + } +} + +bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) { + if (byte_count > package_size_ || offset > package_size_ - byte_count) { + LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count + << ", total package_size: " << package_size_; + return false; + } + + if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) { + PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset; + return false; + } + + return true; +} + +bool FilePackage::UpdateHashAtOffset(const std::vector& hashers, + uint64_t start, uint64_t length) { + if (length > package_size_ || start > package_size_ - length) { + LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length + << ", total package_size: " << package_size_; + return false; + } + + uint64_t so_far = 0; + while (so_far < length) { + uint64_t read_size = std::min(length - so_far, 16 * MiB); + std::vector buffer(read_size); + if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) { + return false; + } + + for (const auto& hasher : hashers) { + hasher(buffer.data(), read_size); + } + so_far += read_size; + } + + return true; +} + +ZipArchiveHandle FilePackage::GetZipArchiveHandle() { + if (zip_handle_) { + return zip_handle_; + } + + if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) { + LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err); + return nullptr; + } + + return zip_handle_; +} -- cgit v1.2.3