• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "host/commands/launch/data_image.h"
2 
3 #include <glog/logging.h>
4 
5 #include "common/libs/utils/files.h"
6 #include "common/libs/utils/subprocess.h"
7 
8 namespace {
9 const std::string kDataPolicyUseExisting = "use_existing";
10 const std::string kDataPolicyCreateIfMissing = "create_if_missing";
11 const std::string kDataPolicyAlwaysCreate = "always_create";
12 const std::string kDataPolicyResizeUpTo= "resize_up_to";
13 
14 const int FSCK_ERROR_CORRECTED = 1;
15 const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2;
16 
ForceFsckImage(const char * data_image)17 bool ForceFsckImage(const char* data_image) {
18   int fsck_status = cvd::execute({"/sbin/e2fsck", "-y", "-f", data_image});
19   if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) {
20     LOG(ERROR) << "`e2fsck -y -f " << data_image << "` failed with code "
21                << fsck_status;
22     return false;
23   }
24   return true;
25 }
26 
ResizeImage(const char * data_image,int data_image_mb)27 bool 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     }
49     int resize_status = cvd::execute({"/sbin/resize2fs", data_image});
50     if (resize_status != 0) {
51       LOG(ERROR) << "`resize2fs " << data_image << "` failed with code "
52                  << 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 
CreateBlankImage(const std::string & image,int image_mb,const std::string & image_fmt)64 void CreateBlankImage(
65     const std::string& image, int image_mb, const std::string& image_fmt) {
66   LOG(INFO) << "Creating " << image;
67   std::string of = "of=";
68   of += image;
69   std::string count = "count=";
70   count += std::to_string(image_mb);
71   cvd::execute({"/bin/dd", "if=/dev/zero", of, "bs=1M", count});
72   if (image_fmt != "none") {
73     cvd::execute({"/sbin/mkfs", "-t", image_fmt, image}, {"PATH=/sbin"});
74   }
75 }
76 
ApplyDataImagePolicy(const vsoc::CuttlefishConfig & config)77 bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config) {
78   std::string data_image = config.data_image_path();
79   bool data_exists = cvd::FileHasContent(data_image.c_str());
80   bool remove{};
81   bool create{};
82   bool resize{};
83 
84   if (config.data_policy() == kDataPolicyUseExisting) {
85     if (!data_exists) {
86       LOG(ERROR) << "Specified data image file does not exists: " << data_image;
87       return false;
88     }
89     if (config.blank_data_image_mb() > 0) {
90       LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy="
91                  << kDataPolicyUseExisting;
92       return false;
93     }
94     create = false;
95     remove = false;
96     resize = false;
97   } else if (config.data_policy() == kDataPolicyAlwaysCreate) {
98     remove = data_exists;
99     create = true;
100     resize = false;
101   } else if (config.data_policy() == kDataPolicyCreateIfMissing) {
102     create = !data_exists;
103     remove = false;
104     resize = false;
105   } else if (config.data_policy() == kDataPolicyResizeUpTo) {
106     create = false;
107     remove = false;
108     resize = true;
109   } else {
110     LOG(ERROR) << "Invalid data_policy: " << config.data_policy();
111     return false;
112   }
113 
114   if (remove) {
115     cvd::RemoveFile(data_image.c_str());
116   }
117 
118   if (create) {
119     if (config.blank_data_image_mb() <= 0) {
120       LOG(ERROR) << "-blank_data_image_mb is required to create data image";
121       return false;
122     }
123     CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(),
124                      config.blank_data_image_fmt());
125   } else if (resize) {
126     if (!data_exists) {
127       LOG(ERROR) << data_image << " does not exist, but resizing was requested";
128       return false;
129     }
130     return ResizeImage(data_image.c_str(), config.blank_data_image_mb());
131   } else {
132     LOG(INFO) << data_image << " exists. Not creating it.";
133   }
134 
135   return true;
136 }
137