blob: 1943a66430b614cc4b40452549342787ad4bcba0 [file] [log] [blame]
Kelvin Zhang83b594b2023-05-25 13:43:06 -07001//
2// Copyright (C) 2023 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "android-base/stringprintf.h"
18#include "android-base/unique_fd.h"
19#include "common/utils.h"
20#include "update_engine/payload_generator/ext2_filesystem.h"
21#include "update_engine/payload_generator/erofs_filesystem.h"
22#include "update_engine/payload_generator/filesystem_interface.h"
23
24namespace chromeos_update_engine {
25
26int WriteBlockMap(const char* img,
27 const FilesystemInterface* fs,
28 const char* output_file) {
29 std::vector<FilesystemInterface::File> files;
30 if (!fs->GetFiles(&files)) {
31 LOG(ERROR) << "Failed to parse file info in " << img;
32 return -2;
33 }
34 android::base::unique_fd fd(
35 open(output_file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644));
36 if (fd < 0) {
37 PLOG(ERROR) << "Failed to open " << output_file;
38 return -errno;
39 }
40 for (const auto& file : files) {
41 if (file.extents.empty()) {
42 continue;
43 }
44 std::string output_line;
45 output_line.append(file.name);
46 for (const auto& extent : file.extents) {
47 if (extent.num_blocks() <= 0) {
48 continue;
49 }
50 output_line.append(" ");
51 if (extent.num_blocks() == 1) {
52 output_line.append(std::to_string(extent.start_block()));
53 continue;
54 }
55 const auto extent_str = android::base::StringPrintf(
56 "%lu-%lu",
57 extent.start_block(),
58 extent.start_block() + extent.num_blocks() - 1);
59 output_line.append(extent_str);
60 }
61 output_line.append("\n");
62 if (!utils::WriteAll(fd.get(), output_line.data(), output_line.size())) {
63 PLOG(ERROR) << "Failed to write to " << output_file;
64 return -errno;
65 }
66 }
67 return 0;
68}
69
70int Main(int argc, const char* argv[]) {
71 const char* img = argv[1];
72 const char* output_file = argv[2];
73 std::unique_ptr<FilesystemInterface> fs;
74 fs = ErofsFilesystem::CreateFromFile(img);
75 if (fs != nullptr) {
76 return WriteBlockMap(img, fs.get(), output_file);
77 }
78 fs = Ext2Filesystem::CreateFromFile(img);
79 if (fs != nullptr) {
80 return WriteBlockMap(img, fs.get(), output_file);
81 }
82 LOG(ERROR) << "Failed to parse " << img;
83 return -1;
84}
85} // namespace chromeos_update_engine
86
87int main(int argc, const char* argv[]) {
88 return chromeos_update_engine::Main(argc, argv);
89}