blob: 701eb671e2536a632f45ea8c3149f68232489a91 [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;
A. Cody Schuffelen2271e4d2020-04-27 21:08:29 -070039 auto fd = cvd::SharedFD::Open(data_image, O_RDWR);
40 if (fd->Truncate(raw_target) != 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -080041 LOG(ERROR) << "`truncate --size=" << data_image_mb << "M "
A. Cody Schuffelen2271e4d2020-04-27 21:08:29 -070042 << data_image << "` failed:" << fd->StrError();
Cody Schuffelen35289082019-01-28 22:25:30 -080043 return false;
44 }
45 bool fsck_success = ForceFsckImage(data_image);
46 if (!fsck_success) {
47 return false;
48 }
A. Cody Schuffelen64cb1452020-03-04 15:34:57 -080049 auto resize_path = vsoc::DefaultHostArtifactsPath("bin/resize.f2fs");
50 int resize_status = cvd::execute({resize_path, data_image});
Cody Schuffelen35289082019-01-28 22:25:30 -080051 if (resize_status != 0) {
Alistair Delva4c70e262019-10-15 14:33:59 -070052 LOG(ERROR) << "`resize.f2fs " << data_image << "` failed with code "
Cody Schuffelen35289082019-01-28 22:25:30 -080053 << resize_status;
54 return false;
55 }
56 fsck_success = ForceFsckImage(data_image);
57 if (!fsck_success) {
58 return false;
59 }
60 }
61 return true;
62}
63} // namespace
64
Paul Trautrimba8f8e92019-03-12 17:55:48 +090065void CreateBlankImage(
Kenny Root1f50ee62020-01-24 12:06:19 -080066 const std::string& image, int block_count, const std::string& image_fmt,
67 const std::string& block_size) {
Paul Trautrimba8f8e92019-03-12 17:55:48 +090068 LOG(INFO) << "Creating " << image;
69 std::string of = "of=";
70 of += image;
71 std::string count = "count=";
Kenny Root1f50ee62020-01-24 12:06:19 -080072 count += std::to_string(block_count);
73 std::string bs = "bs=" + block_size;
74 cvd::execute({"/bin/dd", "if=/dev/zero", of, bs, count});
A. Cody Schuffelend77ae132020-03-04 18:47:31 -080075 if (image_fmt == "ext4") {
76 cvd::execute({"/sbin/mkfs.ext4", image});
77 } else if (image_fmt != "none") {
A. Cody Schuffelen64cb1452020-03-04 15:34:57 -080078 auto make_f2fs_path = vsoc::DefaultHostArtifactsPath("bin/make_f2fs");
79 cvd::execute({make_f2fs_path, "-t", image_fmt, image, "-g", "android"});
Paul Trautrimba8f8e92019-03-12 17:55:48 +090080 }
81}
82
Cody Schuffelen3c99f5b2019-06-14 17:26:01 -070083bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config,
84 const std::string& data_image) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080085 bool data_exists = cvd::FileHasContent(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -080086 bool remove{};
87 bool create{};
88 bool resize{};
89
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080090 if (config.data_policy() == kDataPolicyUseExisting) {
Cody Schuffelen35289082019-01-28 22:25:30 -080091 if (!data_exists) {
92 LOG(ERROR) << "Specified data image file does not exists: " << data_image;
93 return false;
94 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -080095 if (config.blank_data_image_mb() > 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -080096 LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy="
97 << kDataPolicyUseExisting;
98 return false;
99 }
100 create = false;
101 remove = false;
102 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800103 } else if (config.data_policy() == kDataPolicyAlwaysCreate) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800104 remove = data_exists;
105 create = true;
106 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800107 } else if (config.data_policy() == kDataPolicyCreateIfMissing) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800108 create = !data_exists;
109 remove = false;
110 resize = false;
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800111 } else if (config.data_policy() == kDataPolicyResizeUpTo) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800112 create = false;
113 remove = false;
114 resize = true;
115 } else {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800116 LOG(ERROR) << "Invalid data_policy: " << config.data_policy();
Cody Schuffelen35289082019-01-28 22:25:30 -0800117 return false;
118 }
119
120 if (remove) {
Jorge E. Moreira7b0059a2019-03-22 17:38:14 -0700121 cvd::RemoveFile(data_image.c_str());
Cody Schuffelen35289082019-01-28 22:25:30 -0800122 }
123
124 if (create) {
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800125 if (config.blank_data_image_mb() <= 0) {
Cody Schuffelen35289082019-01-28 22:25:30 -0800126 LOG(ERROR) << "-blank_data_image_mb is required to create data image";
127 return false;
128 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800129 CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(),
130 config.blank_data_image_fmt());
Cody Schuffelen35289082019-01-28 22:25:30 -0800131 } else if (resize) {
132 if (!data_exists) {
133 LOG(ERROR) << data_image << " does not exist, but resizing was requested";
134 return false;
135 }
Cody Schuffelen2b51bab2019-01-29 18:14:48 -0800136 return ResizeImage(data_image.c_str(), config.blank_data_image_mb());
Cody Schuffelen35289082019-01-28 22:25:30 -0800137 } else {
138 LOG(INFO) << data_image << " exists. Not creating it.";
139 }
140
141 return true;
142}
Yifan Hong19d713e2019-05-01 14:12:07 -0700143
144bool InitializeMiscImage(const std::string& misc_image) {
145 bool misc_exists = cvd::FileHasContent(misc_image.c_str());
146
147 if (misc_exists) {
148 LOG(INFO) << "misc partition image: use existing";
149 return true;
150 }
151
152 LOG(INFO) << "misc partition image: creating empty";
153 CreateBlankImage(misc_image, 1 /* mb */, "none");
154 return true;
155}