summaryrefslogtreecommitdiff
path: root/fs_mgr/libsnapshot/snapshot_reader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fs_mgr/libsnapshot/snapshot_reader.cpp')
-rw-r--r--fs_mgr/libsnapshot/snapshot_reader.cpp332
1 files changed, 0 insertions, 332 deletions
diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp
deleted file mode 100644
index 5ee8e25d1..000000000
--- a/fs_mgr/libsnapshot/snapshot_reader.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include "snapshot_reader.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <ext4_utils/ext4_utils.h>
-
-namespace android {
-namespace snapshot {
-
-using android::base::borrowed_fd;
-
-// Not supported.
-bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::Open(const char*, int) {
- errno = EINVAL;
- return false;
-}
-
-ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) {
- errno = EINVAL;
- return false;
-}
-
-bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) {
- errno = EINVAL;
- return false;
-}
-
-ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {}
-
-ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) {
- return read(fd_.get(), buf, count);
-}
-
-off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) {
- return lseek(fd_.get(), offset, whence);
-}
-
-uint64_t ReadFdFileDescriptor::BlockDevSize() {
- return get_block_device_size(fd_.get());
-}
-
-bool ReadFdFileDescriptor::Close() {
- fd_ = {};
- return true;
-}
-
-bool ReadFdFileDescriptor::IsSettingErrno() {
- return true;
-}
-
-bool ReadFdFileDescriptor::IsOpen() {
- return fd_ >= 0;
-}
-
-bool ReadFdFileDescriptor::Flush() {
- return true;
-}
-
-bool CompressedSnapshotReader::SetCow(std::unique_ptr<CowReader>&& cow) {
- cow_ = std::move(cow);
-
- CowHeader header;
- if (!cow_->GetHeader(&header)) {
- return false;
- }
- block_size_ = header.block_size;
-
- // Populate the operation map.
- op_iter_ = cow_->GetOpIter();
- while (!op_iter_->Done()) {
- const CowOperation* op = &op_iter_->Get();
- if (IsMetadataOp(*op)) {
- op_iter_->Next();
- continue;
- }
- if (op->new_block >= ops_.size()) {
- ops_.resize(op->new_block + 1, nullptr);
- }
- ops_[op->new_block] = op;
- op_iter_->Next();
- }
-
- return true;
-}
-
-void CompressedSnapshotReader::SetSourceDevice(const std::string& source_device) {
- source_device_ = {source_device};
-}
-
-void CompressedSnapshotReader::SetBlockDeviceSize(uint64_t block_device_size) {
- block_device_size_ = block_device_size;
-}
-
-borrowed_fd CompressedSnapshotReader::GetSourceFd() {
- if (source_fd_ < 0) {
- if (!source_device_) {
- LOG(ERROR) << "CompressedSnapshotReader needs source device, but none was set";
- errno = EINVAL;
- return {-1};
- }
- source_fd_.reset(open(source_device_->c_str(), O_RDONLY | O_CLOEXEC));
- if (source_fd_ < 0) {
- PLOG(ERROR) << "open " << *source_device_;
- return {-1};
- }
- }
- return source_fd_;
-}
-
-class MemoryByteSink : public IByteSink {
- public:
- MemoryByteSink(void* buf, size_t count) {
- buf_ = reinterpret_cast<uint8_t*>(buf);
- pos_ = buf_;
- end_ = buf_ + count;
- }
-
- void* GetBuffer(size_t requested, size_t* actual) override {
- *actual = std::min(remaining(), requested);
- if (!*actual) {
- return nullptr;
- }
-
- uint8_t* start = pos_;
- pos_ += *actual;
- return start;
- }
-
- bool ReturnData(void*, size_t) override { return true; }
-
- uint8_t* buf() const { return buf_; }
- uint8_t* pos() const { return pos_; }
- size_t remaining() const { return end_ - pos_; }
-
- private:
- uint8_t* buf_;
- uint8_t* pos_;
- uint8_t* end_;
-};
-
-ssize_t CompressedSnapshotReader::Read(void* buf, size_t count) {
- // Find the start and end chunks, inclusive.
- uint64_t start_chunk = offset_ / block_size_;
- uint64_t end_chunk = (offset_ + count - 1) / block_size_;
-
- // Chop off the first N bytes if the position is not block-aligned.
- size_t start_offset = offset_ % block_size_;
-
- MemoryByteSink sink(buf, count);
-
- size_t initial_bytes = std::min(block_size_ - start_offset, sink.remaining());
- ssize_t rv = ReadBlock(start_chunk, &sink, start_offset, initial_bytes);
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
-
- for (uint64_t chunk = start_chunk + 1; chunk < end_chunk; chunk++) {
- ssize_t rv = ReadBlock(chunk, &sink, 0);
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
- }
-
- if (sink.remaining()) {
- ssize_t rv = ReadBlock(end_chunk, &sink, 0, {sink.remaining()});
- if (rv < 0) {
- return -1;
- }
- offset_ += rv;
- }
-
- errno = 0;
-
- DCHECK(sink.pos() - sink.buf() == count);
- return count;
-}
-
-// Discard the first N bytes of a sink request, or any excess bytes.
-class PartialSink : public MemoryByteSink {
- public:
- PartialSink(void* buffer, size_t size, size_t ignore_start)
- : MemoryByteSink(buffer, size), ignore_start_(ignore_start) {}
-
- void* GetBuffer(size_t requested, size_t* actual) override {
- // Throw away the first N bytes if needed.
- if (ignore_start_) {
- *actual = std::min({requested, ignore_start_, sizeof(discard_)});
- ignore_start_ -= *actual;
- return discard_;
- }
- // Throw away any excess bytes if needed.
- if (remaining() == 0) {
- *actual = std::min(requested, sizeof(discard_));
- return discard_;
- }
- return MemoryByteSink::GetBuffer(requested, actual);
- }
-
- private:
- size_t ignore_start_;
- char discard_[4096];
-};
-
-ssize_t CompressedSnapshotReader::ReadBlock(uint64_t chunk, IByteSink* sink, size_t start_offset,
- const std::optional<uint64_t>& max_bytes) {
- size_t bytes_to_read = block_size_;
- if (max_bytes) {
- bytes_to_read = *max_bytes;
- }
-
- // The offset is relative to the chunk; we should be reading no more than
- // one chunk.
- CHECK(start_offset + bytes_to_read <= block_size_);
-
- const CowOperation* op = nullptr;
- if (chunk < ops_.size()) {
- op = ops_[chunk];
- }
-
- size_t actual;
- void* buffer = sink->GetBuffer(bytes_to_read, &actual);
- if (!buffer || actual < bytes_to_read) {
- // This should never happen unless we calculated the read size wrong
- // somewhere. MemoryByteSink always fulfills the entire requested
- // region unless there's not enough buffer remaining.
- LOG(ERROR) << "Asked for buffer of size " << bytes_to_read << ", got " << actual;
- errno = EINVAL;
- return -1;
- }
-
- if (!op || op->type == kCowCopyOp) {
- borrowed_fd fd = GetSourceFd();
- if (fd < 0) {
- // GetSourceFd sets errno.
- return -1;
- }
-
- if (op) {
- chunk = op->source;
- }
-
- off64_t offset = (chunk * block_size_) + start_offset;
- if (!android::base::ReadFullyAtOffset(fd, buffer, bytes_to_read, offset)) {
- PLOG(ERROR) << "read " << *source_device_;
- // ReadFullyAtOffset sets errno.
- return -1;
- }
- } else if (op->type == kCowZeroOp) {
- memset(buffer, 0, bytes_to_read);
- } else if (op->type == kCowReplaceOp) {
- PartialSink partial_sink(buffer, bytes_to_read, start_offset);
- if (!cow_->ReadData(*op, &partial_sink)) {
- LOG(ERROR) << "CompressedSnapshotReader failed to read replace op";
- errno = EIO;
- return -1;
- }
- } else {
- LOG(ERROR) << "CompressedSnapshotReader unknown op type: " << uint32_t(op->type);
- errno = EINVAL;
- return -1;
- }
-
- // MemoryByteSink doesn't do anything in ReturnBuffer, so don't bother calling it.
- return bytes_to_read;
-}
-
-off64_t CompressedSnapshotReader::Seek(off64_t offset, int whence) {
- switch (whence) {
- case SEEK_SET:
- offset_ = offset;
- break;
- case SEEK_END:
- offset_ = static_cast<off64_t>(block_device_size_) + offset;
- break;
- case SEEK_CUR:
- offset_ += offset;
- break;
- default:
- LOG(ERROR) << "Unrecognized seek whence: " << whence;
- errno = EINVAL;
- return -1;
- }
- return offset_;
-}
-
-uint64_t CompressedSnapshotReader::BlockDevSize() {
- return block_device_size_;
-}
-
-bool CompressedSnapshotReader::Close() {
- cow_ = nullptr;
- source_fd_ = {};
- return true;
-}
-
-bool CompressedSnapshotReader::IsSettingErrno() {
- return true;
-}
-
-bool CompressedSnapshotReader::IsOpen() {
- return cow_ != nullptr;
-}
-
-bool CompressedSnapshotReader::Flush() {
- return true;
-}
-
-} // namespace snapshot
-} // namespace android