Merge changes Ib7509508,I7e256e8d into main
* changes: snapuserd: Add an extractor tool. inspect_cow: Add an --extract-to argument.
This commit is contained in:
commit
310e7ae496
5 changed files with 280 additions and 3 deletions
|
|
@ -22,6 +22,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <gflags/gflags.h>
|
||||
|
|
@ -38,11 +39,13 @@ DEFINE_bool(show_merged, false,
|
|||
DEFINE_bool(verify_merge_sequence, false, "Verify merge order sequencing");
|
||||
DEFINE_bool(show_merge_sequence, false, "Show merge order sequence");
|
||||
DEFINE_bool(show_raw_ops, false, "Show raw ops directly from the underlying parser");
|
||||
DEFINE_string(extract_to, "", "Extract the COW contents to the given file");
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
using android::base::borrowed_fd;
|
||||
using android::base::unique_fd;
|
||||
|
||||
void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
|
||||
unsigned int, const char* message) {
|
||||
|
|
@ -53,7 +56,7 @@ void MyLogger(android::base::LogId, android::base::LogSeverity severity, const c
|
|||
}
|
||||
}
|
||||
|
||||
static void ShowBad(CowReader& reader, const struct CowOperation* op) {
|
||||
static void ShowBad(CowReader& reader, const CowOperation* op) {
|
||||
size_t count;
|
||||
auto buffer = std::make_unique<uint8_t[]>(op->data_length);
|
||||
|
||||
|
|
@ -104,12 +107,21 @@ static bool ShowRawOpStream(borrowed_fd fd) {
|
|||
}
|
||||
|
||||
static bool Inspect(const std::string& path) {
|
||||
android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
|
||||
unique_fd fd(open(path.c_str(), O_RDONLY));
|
||||
if (fd < 0) {
|
||||
PLOG(ERROR) << "open failed: " << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
unique_fd extract_to;
|
||||
if (!FLAGS_extract_to.empty()) {
|
||||
extract_to.reset(open(FLAGS_extract_to.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0664));
|
||||
if (extract_to < 0) {
|
||||
PLOG(ERROR) << "could not open " << FLAGS_extract_to << " for writing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CowReader reader;
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
|
|
@ -186,12 +198,23 @@ static bool Inspect(const std::string& path) {
|
|||
|
||||
if (!FLAGS_silent && FLAGS_show_ops) std::cout << *op << "\n";
|
||||
|
||||
if (FLAGS_decompress && op->type == kCowReplaceOp && op->compression != kCowCompressNone) {
|
||||
if ((FLAGS_decompress || extract_to >= 0) && op->type == kCowReplaceOp) {
|
||||
if (reader.ReadData(op, buffer.data(), buffer.size()) < 0) {
|
||||
std::cerr << "Failed to decompress for :" << *op << "\n";
|
||||
success = false;
|
||||
if (FLAGS_show_bad_data) ShowBad(reader, op);
|
||||
}
|
||||
if (extract_to >= 0) {
|
||||
off_t offset = uint64_t(op->new_block) * header.block_size;
|
||||
if (!android::base::WriteFullyAtOffset(extract_to, buffer.data(), buffer.size(),
|
||||
offset)) {
|
||||
PLOG(ERROR) << "failed to write block " << op->new_block;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (extract_to >= 0 && !IsMetadataOp(*op) && op->type != kCowZeroOp) {
|
||||
PLOG(ERROR) << "Cannot extract op yet: " << *op;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (op->type == kCowSequenceOp && FLAGS_show_merge_sequence) {
|
||||
|
|
|
|||
|
|
@ -293,3 +293,48 @@ cc_test {
|
|||
"vts",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "snapuserd_extractor",
|
||||
defaults: [
|
||||
"fs_mgr_defaults",
|
||||
"libsnapshot_cow_defaults",
|
||||
],
|
||||
srcs: [
|
||||
"testing/dm_user_harness.cpp",
|
||||
"testing/harness.cpp",
|
||||
"testing/host_harness.cpp",
|
||||
"user-space-merge/extractor.cpp",
|
||||
"snapuserd_extractor.cpp",
|
||||
],
|
||||
cflags: [
|
||||
"-D_FILE_OFFSET_BITS=64",
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
],
|
||||
static_libs: [
|
||||
"libbrotli",
|
||||
"libcutils_sockets",
|
||||
"libdm",
|
||||
"libext2_uuid",
|
||||
"libext4_utils",
|
||||
"libfs_mgr_file_wait",
|
||||
"libgflags",
|
||||
"libsnapshot_cow",
|
||||
"libsnapuserd",
|
||||
"liburing",
|
||||
"libz",
|
||||
],
|
||||
include_dirs: [
|
||||
"bionic/libc/kernel",
|
||||
".",
|
||||
],
|
||||
header_libs: [
|
||||
"libstorage_literals_headers",
|
||||
"libfiemap_headers",
|
||||
],
|
||||
}
|
||||
|
|
|
|||
68
fs_mgr/libsnapshot/snapuserd/snapuserd_extractor.cpp
Normal file
68
fs_mgr/libsnapshot/snapuserd/snapuserd_extractor.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (C) 2023 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 <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <gflags/gflags.h>
|
||||
#include "user-space-merge/extractor.h"
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
DEFINE_string(base, "", "Base device/image");
|
||||
DEFINE_string(cow, "", "COW device/image");
|
||||
DEFINE_string(out, "", "Output path");
|
||||
DEFINE_int32(num_sectors, 0, "Number of sectors to read");
|
||||
|
||||
int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv) {
|
||||
android::base::InitLogging(argv);
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (FLAGS_out.empty()) {
|
||||
LOG(ERROR) << "Missing -out argument.";
|
||||
return 1;
|
||||
}
|
||||
if (FLAGS_base.empty()) {
|
||||
LOG(ERROR) << "Missing -base argument.";
|
||||
return 1;
|
||||
}
|
||||
if (FLAGS_cow.empty()) {
|
||||
LOG(ERROR) << "missing -out argument.";
|
||||
return 1;
|
||||
}
|
||||
if (!FLAGS_num_sectors) {
|
||||
LOG(ERROR) << "missing -num_sectors argument.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
android::snapshot::Extractor extractor(FLAGS_base, FLAGS_cow);
|
||||
if (!extractor.Init()) {
|
||||
return 1;
|
||||
}
|
||||
if (!extractor.Extract(FLAGS_num_sectors, FLAGS_out)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
90
fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
Normal file
90
fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (C) 2023 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 "extractor.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
using android::base::unique_fd;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
Extractor::Extractor(const std::string& base_path, const std::string& cow_path)
|
||||
: base_path_(base_path), cow_path_(cow_path), control_name_("test") {}
|
||||
|
||||
bool Extractor::Init() {
|
||||
auto opener = factory_.CreateTestOpener(control_name_);
|
||||
handler_ = std::make_shared<SnapshotHandler>(control_name_, cow_path_, base_path_, base_path_,
|
||||
opener, 1, false, false);
|
||||
if (!handler_->InitCowDevice()) {
|
||||
return false;
|
||||
}
|
||||
if (!handler_->InitializeWorkers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
read_worker_ = std::make_unique<ReadWorker>(cow_path_, base_path_, control_name_, base_path_,
|
||||
handler_->GetSharedPtr(), opener);
|
||||
if (!read_worker_->Init()) {
|
||||
return false;
|
||||
}
|
||||
block_server_ = static_cast<TestBlockServer*>(read_worker_->block_server());
|
||||
|
||||
handler_thread_ = std::async(std::launch::async, &SnapshotHandler::Start, handler_.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
Extractor::~Extractor() {
|
||||
factory_.DeleteQueue(control_name_);
|
||||
}
|
||||
|
||||
bool Extractor::Extract(off_t num_sectors, const std::string& out_path) {
|
||||
unique_fd out_fd(open(out_path.c_str(), O_RDWR | O_CLOEXEC | O_TRUNC | O_CREAT, 0664));
|
||||
if (out_fd < 0) {
|
||||
PLOG(ERROR) << "Could not open for writing: " << out_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (off_t i = 0; i < num_sectors; i++) {
|
||||
if (!read_worker_->RequestSectors(i, 512)) {
|
||||
LOG(ERROR) << "Read sector " << i << " failed.";
|
||||
return false;
|
||||
}
|
||||
std::string result = std::move(block_server_->sent_io());
|
||||
off_t offset = i * 512;
|
||||
if (!android::base::WriteFullyAtOffset(out_fd, result.data(), result.size(), offset)) {
|
||||
PLOG(ERROR) << "write failed";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
51
fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h
Normal file
51
fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (C) 2023 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include "merge_worker.h"
|
||||
#include "read_worker.h"
|
||||
#include "snapuserd_core.h"
|
||||
#include "testing/host_harness.h"
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
class Extractor final {
|
||||
public:
|
||||
Extractor(const std::string& base_path, const std::string& cow_path);
|
||||
~Extractor();
|
||||
|
||||
bool Init();
|
||||
bool Extract(off_t num_sectors, const std::string& out_path);
|
||||
|
||||
private:
|
||||
std::string base_path_;
|
||||
std::string cow_path_;
|
||||
|
||||
TestBlockServerFactory factory_;
|
||||
HostTestHarness harness_;
|
||||
std::string control_name_;
|
||||
std::shared_ptr<SnapshotHandler> handler_;
|
||||
std::unique_ptr<ReadWorker> read_worker_;
|
||||
std::future<bool> handler_thread_;
|
||||
TestBlockServer* block_server_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
Loading…
Add table
Reference in a new issue