blob: c84cb33ba3f41f4a7c66408dff1da393f0459439 [file] [log] [blame]
Cody Schuffelen147b88e2019-09-09 16:00:11 -07001#include "host/commands/assemble_cvd/data_image.h"
Cody Schuffelen35289082019-01-28 22:25:30 -08002
3#include <glog/logging.h>
4
5#include "common/libs/utils/files.h"
6#include "common/libs/utils/subprocess.h"
7
8namespace {
9const std::string kDataPolicyUseExisting = "use_existing";
10const std::string kDataPolicyCreateIfMissing = "create_if_missing";
11const std::string kDataPolicyAlwaysCreate = "always_create";
12const std::string kDataPolicyResizeUpTo= "resize_up_to";
13
Cody Schuffelen35289082019-01-28 22:25:30 -080014const int FSCK_ERROR_CORRECTED = 1;
15const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2;
16
17bool ForceFsckImage(const char* data_image) {
Cody Schuffelenbdca7b82019-12-04 20:09:22 +000018 int fsck_status = cvd::execute({"/sbin/e2fsck", "-y", "-f", data_image});
Cody Schuffelen35289082019-01-28 22:25:30 -080019 if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) {
Cody Schuffelenbdca7b82019-12-04 20:09:22 +000020 LOG(ERROR) << "`e2fsck -y -f " << data_image << "` failed with code "
Cody Schuffelen35289082019-01-28 22:25:30 -080021 << fsck_status;
22 return false;
23 }
24 return true;
25}
26
27bool ResizeImage(const char* data_image, int data_image_mb) {
28 auto file_mb = cvd::FileSize(data_image) >> 20;
29 if (file_mb > data_image_mb) {
30 LOG(ERROR) << data_image << " is already " << file_mb << " MB, will not "
31 << "resize down.";
32 return false;
33 } else if (file_mb == data_image_mb) {
34 LOG(INFO) << data_image << " is already the right size";
35 return true;
36 } else {
37 off_t raw_target = static_cast<off_t>(data_image_mb) << 20;
38 int truncate_status =
39 cvd::SharedFD::Open(data_image, O_RDWR)->Truncate(raw_target);
40 if (truncate_status != 0) {
41 LOG(ERROR) << "`truncate --size=" << data_image_mb << "M "
42 << data_image << "` failed with code " << truncate_status;
43 return false;
44 }
45 bool fsck_success = ForceFsckImage(data_image);
46 if (!fsck_success) {
47 return false;
48 }
Cody Schuffelenbdca7b82019-12-04 20:09:22 +000049 int resize_status = cvd::execute({"/sbin/resize2fs", data_image});
Cody Schuffelen35289082019-01-28 22:25:30 -080050 if (resize_status != 0) {
Cody Schuffelenbdca7b82019-12-04 20:09:22 +000051 LOG(ERROR) << "`resize2fs " << data_image << "` failed with code "
Cody Schuffelen35289082019-01-28 22:25:30 -080052 << resize_status;
53 return false;
54 }
55 fsck_success = ForceFsckImage(data_image);
56 if (!fsck_success) {
57 return false;
58 }
59 }
60 return true;
61}
62} // namespace
63
Paul Trautrimba8f8e92019-03-12 17:55:48 +090064void CreateBlankImage(
Kenny Root1f50ee62020-01-24 12:06:19 -080065 const std::string& image, int block_count, const std::string& image_fmt,
66 const std::string& block_size) {
Paul Trautrimba8f8e92019-03-12 17:55:48 +090067 LOG(INFO) << "Creating " << image;
68 std::string of = "of=";
69 of += image;
70 std::string count = "count=";
Kenny Root1f50ee62020-01-24 12:06:19 -080071 count += std::to_string(block_count);
72 std::string bs = "bs=" + block_size;
73 cvd::execute({"/bin/dd", "if=/dev/zero", of, bs, count});
Paul Trautrimba8f8e92019-03-12 17:55:48 +090074 if (image_fmt != "none") {
75 cvd::execute({"/sbin/mkfs", "-t", image_fmt, image}, {"PATH=/sbin"});
76 }
77}
78
Cody Schuffelen3c99f5b2019-06-14 17:26:01 -070079bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config,
80 const std::string& data_image) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080081 bool data_exists = cvd::FileHasContent(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -080082 bool remove{};
83 bool create{};
84 bool resize{};
85
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080086 if (config.data_policy() == kDataPolicyUseExisting) {
Cody Schuffelen35289082019-01-28 22:25:30 -080087 if (!data_exists) {
88 LOG(ERROR) << "Specified data image file does not exists: " << data_image;
89 return false;
90 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080091 if (config.blank_data_image_mb() > 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -080092 LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy="
93 << kDataPolicyUseExisting;
94 return false;
95 }
96 create = false;
97 remove = false;
98 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080099 } else if (config.data_policy() == kDataPolicyAlwaysCreate) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800100 remove = data_exists;
101 create = true;
102 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800103 } else if (config.data_policy() == kDataPolicyCreateIfMissing) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800104 create = !data_exists;
105 remove = false;
106 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800107 } else if (config.data_policy() == kDataPolicyResizeUpTo) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800108 create = false;
109 remove = false;
110 resize = true;
111 } else {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800112 LOG(ERROR) << "Invalid data_policy: " << config.data_policy();
Cody Schuffelen35289082019-01-28 22:25:30 -0800113 return false;
114 }
115
116 if (remove) {
Jorge E. Moreira7b0059a2019-03-22 17:38:14 -0700117 cvd::RemoveFile(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -0800118 }
119
120 if (create) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800121 if (config.blank_data_image_mb() <= 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800122 LOG(ERROR) << "-blank_data_image_mb is required to create data image";
123 return false;
124 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800125 CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(),
126 config.blank_data_image_fmt());
Cody Schuffelen35289082019-01-28 22:25:30 -0800127 } else if (resize) {
128 if (!data_exists) {
129 LOG(ERROR) << data_image << " does not exist, but resizing was requested";
130 return false;
131 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800132 return ResizeImage(data_image.c_str(), config.blank_data_image_mb());
Cody Schuffelen35289082019-01-28 22:25:30 -0800133 } else {
134 LOG(INFO) << data_image << " exists. Not creating it.";
135 }
136
137 return true;
138}
Yifan Hong19d713e2019-05-01 14:12:07 -0700139
140bool InitializeMiscImage(const std::string& misc_image) {
141 bool misc_exists = cvd::FileHasContent(misc_image.c_str());
142
143 if (misc_exists) {
144 LOG(INFO) << "misc partition image: use existing";
145 return true;
146 }
147
148 LOG(INFO) << "misc partition image: creating empty";
149 CreateBlankImage(misc_image, 1 /* mb */, "none");
150 return true;
151}