blob: 9b0ca12b24ee023affef2ef7d259506514b89af0 [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) {
A. Cody Schuffelen64cb1452020-03-04 15:34:57 -080018 auto fsck_path = vsoc::DefaultHostArtifactsPath("bin/fsck.f2fs");
19 int fsck_status = cvd::execute({fsck_path, "-y", "-f", data_image});
Cody Schuffelen35289082019-01-28 22:25:30 -080020 if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) {
Alistair Delva4c70e262019-10-15 14:33:59 -070021 LOG(ERROR) << "`fsck.f2fs -y -f " << data_image << "` failed with code "
Cody Schuffelen35289082019-01-28 22:25:30 -080022 << fsck_status;
23 return false;
24 }
25 return true;
26}
27
28bool ResizeImage(const char* data_image, int data_image_mb) {
29 auto file_mb = cvd::FileSize(data_image) >> 20;
30 if (file_mb > data_image_mb) {
31 LOG(ERROR) << data_image << " is already " << file_mb << " MB, will not "
32 << "resize down.";
33 return false;
34 } else if (file_mb == data_image_mb) {
35 LOG(INFO) << data_image << " is already the right size";
36 return true;
37 } else {
38 off_t raw_target = static_cast<off_t>(data_image_mb) << 20;
39 int truncate_status =
40 cvd::SharedFD::Open(data_image, O_RDWR)->Truncate(raw_target);
41 if (truncate_status != 0) {
42 LOG(ERROR) << "`truncate --size=" << data_image_mb << "M "
43 << data_image << "` failed with code " << truncate_status;
44 return false;
45 }
46 bool fsck_success = ForceFsckImage(data_image);
47 if (!fsck_success) {
48 return false;
49 }
A. Cody Schuffelen64cb1452020-03-04 15:34:57 -080050 auto resize_path = vsoc::DefaultHostArtifactsPath("bin/resize.f2fs");
51 int resize_status = cvd::execute({resize_path, data_image});
Cody Schuffelen35289082019-01-28 22:25:30 -080052 if (resize_status != 0) {
Alistair Delva4c70e262019-10-15 14:33:59 -070053 LOG(ERROR) << "`resize.f2fs " << data_image << "` failed with code "
Cody Schuffelen35289082019-01-28 22:25:30 -080054 << resize_status;
55 return false;
56 }
57 fsck_success = ForceFsckImage(data_image);
58 if (!fsck_success) {
59 return false;
60 }
61 }
62 return true;
63}
64} // namespace
65
Paul Trautrimba8f8e92019-03-12 17:55:48 +090066void CreateBlankImage(
Kenny Root1f50ee62020-01-24 12:06:19 -080067 const std::string& image, int block_count, const std::string& image_fmt,
68 const std::string& block_size) {
Paul Trautrimba8f8e92019-03-12 17:55:48 +090069 LOG(INFO) << "Creating " << image;
70 std::string of = "of=";
71 of += image;
72 std::string count = "count=";
Kenny Root1f50ee62020-01-24 12:06:19 -080073 count += std::to_string(block_count);
74 std::string bs = "bs=" + block_size;
75 cvd::execute({"/bin/dd", "if=/dev/zero", of, bs, count});
A. Cody Schuffelend77ae132020-03-04 18:47:31 -080076 if (image_fmt == "ext4") {
77 cvd::execute({"/sbin/mkfs.ext4", image});
78 } else if (image_fmt != "none") {
A. Cody Schuffelen64cb1452020-03-04 15:34:57 -080079 auto make_f2fs_path = vsoc::DefaultHostArtifactsPath("bin/make_f2fs");
80 cvd::execute({make_f2fs_path, "-t", image_fmt, image, "-g", "android"});
Paul Trautrimba8f8e92019-03-12 17:55:48 +090081 }
82}
83
Cody Schuffelen3c99f5b2019-06-14 17:26:01 -070084bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config,
85 const std::string& data_image) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080086 bool data_exists = cvd::FileHasContent(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -080087 bool remove{};
88 bool create{};
89 bool resize{};
90
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080091 if (config.data_policy() == kDataPolicyUseExisting) {
Cody Schuffelen35289082019-01-28 22:25:30 -080092 if (!data_exists) {
93 LOG(ERROR) << "Specified data image file does not exists: " << data_image;
94 return false;
95 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080096 if (config.blank_data_image_mb() > 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -080097 LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy="
98 << kDataPolicyUseExisting;
99 return false;
100 }
101 create = false;
102 remove = false;
103 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800104 } else if (config.data_policy() == kDataPolicyAlwaysCreate) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800105 remove = data_exists;
106 create = true;
107 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800108 } else if (config.data_policy() == kDataPolicyCreateIfMissing) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800109 create = !data_exists;
110 remove = false;
111 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800112 } else if (config.data_policy() == kDataPolicyResizeUpTo) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800113 create = false;
114 remove = false;
115 resize = true;
116 } else {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800117 LOG(ERROR) << "Invalid data_policy: " << config.data_policy();
Cody Schuffelen35289082019-01-28 22:25:30 -0800118 return false;
119 }
120
121 if (remove) {
Jorge E. Moreira7b0059a2019-03-22 17:38:14 -0700122 cvd::RemoveFile(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -0800123 }
124
125 if (create) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800126 if (config.blank_data_image_mb() <= 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800127 LOG(ERROR) << "-blank_data_image_mb is required to create data image";
128 return false;
129 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800130 CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(),
131 config.blank_data_image_fmt());
Cody Schuffelen35289082019-01-28 22:25:30 -0800132 } else if (resize) {
133 if (!data_exists) {
134 LOG(ERROR) << data_image << " does not exist, but resizing was requested";
135 return false;
136 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800137 return ResizeImage(data_image.c_str(), config.blank_data_image_mb());
Cody Schuffelen35289082019-01-28 22:25:30 -0800138 } else {
139 LOG(INFO) << data_image << " exists. Not creating it.";
140 }
141
142 return true;
143}
Yifan Hong19d713e2019-05-01 14:12:07 -0700144
145bool InitializeMiscImage(const std::string& misc_image) {
146 bool misc_exists = cvd::FileHasContent(misc_image.c_str());
147
148 if (misc_exists) {
149 LOG(INFO) << "misc partition image: use existing";
150 return true;
151 }
152
153 LOG(INFO) << "misc partition image: creating empty";
154 CreateBlankImage(misc_image, 1 /* mb */, "none");
155 return true;
156}