1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker *
4*acea8879SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker *
8*acea8879SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker *
10*acea8879SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker */
16*acea8879SAndroid Build Coastguard Worker
17*acea8879SAndroid Build Coastguard Worker #include "updater/install.h"
18*acea8879SAndroid Build Coastguard Worker
19*acea8879SAndroid Build Coastguard Worker #include <ctype.h>
20*acea8879SAndroid Build Coastguard Worker #include <errno.h>
21*acea8879SAndroid Build Coastguard Worker #include <fcntl.h>
22*acea8879SAndroid Build Coastguard Worker #include <ftw.h>
23*acea8879SAndroid Build Coastguard Worker #include <inttypes.h>
24*acea8879SAndroid Build Coastguard Worker #include <stdarg.h>
25*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
26*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
27*acea8879SAndroid Build Coastguard Worker #include <string.h>
28*acea8879SAndroid Build Coastguard Worker #include <sys/capability.h>
29*acea8879SAndroid Build Coastguard Worker #include <sys/mount.h>
30*acea8879SAndroid Build Coastguard Worker #include <sys/stat.h>
31*acea8879SAndroid Build Coastguard Worker #include <sys/types.h>
32*acea8879SAndroid Build Coastguard Worker #include <sys/wait.h>
33*acea8879SAndroid Build Coastguard Worker #include <sys/xattr.h>
34*acea8879SAndroid Build Coastguard Worker #include <time.h>
35*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
36*acea8879SAndroid Build Coastguard Worker #include <utime.h>
37*acea8879SAndroid Build Coastguard Worker
38*acea8879SAndroid Build Coastguard Worker #include <limits>
39*acea8879SAndroid Build Coastguard Worker #include <memory>
40*acea8879SAndroid Build Coastguard Worker #include <string>
41*acea8879SAndroid Build Coastguard Worker #include <vector>
42*acea8879SAndroid Build Coastguard Worker
43*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
44*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
45*acea8879SAndroid Build Coastguard Worker #include <android-base/parsedouble.h>
46*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
47*acea8879SAndroid Build Coastguard Worker #include <android-base/properties.h>
48*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
49*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
50*acea8879SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
51*acea8879SAndroid Build Coastguard Worker #include <applypatch/applypatch.h>
52*acea8879SAndroid Build Coastguard Worker #include <bootloader_message/bootloader_message.h>
53*acea8879SAndroid Build Coastguard Worker #include <ext4_utils/wipe.h>
54*acea8879SAndroid Build Coastguard Worker #include <openssl/sha.h>
55*acea8879SAndroid Build Coastguard Worker #include <selinux/label.h>
56*acea8879SAndroid Build Coastguard Worker #include <selinux/selinux.h>
57*acea8879SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
58*acea8879SAndroid Build Coastguard Worker
59*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
60*acea8879SAndroid Build Coastguard Worker #include "edify/updater_interface.h"
61*acea8879SAndroid Build Coastguard Worker #include "edify/updater_runtime_interface.h"
62*acea8879SAndroid Build Coastguard Worker #include "otautil/dirutil.h"
63*acea8879SAndroid Build Coastguard Worker #include "otautil/error_code.h"
64*acea8879SAndroid Build Coastguard Worker #include "otautil/print_sha1.h"
65*acea8879SAndroid Build Coastguard Worker #include "otautil/sysutil.h"
66*acea8879SAndroid Build Coastguard Worker
67*acea8879SAndroid Build Coastguard Worker #ifndef __ANDROID__
68*acea8879SAndroid Build Coastguard Worker #include <cutils/memory.h> // for strlcpy
69*acea8879SAndroid Build Coastguard Worker #endif
70*acea8879SAndroid Build Coastguard Worker
UpdateBlockDeviceNameForPartition(UpdaterInterface * updater,Partition * partition)71*acea8879SAndroid Build Coastguard Worker static bool UpdateBlockDeviceNameForPartition(UpdaterInterface* updater, Partition* partition) {
72*acea8879SAndroid Build Coastguard Worker CHECK(updater);
73*acea8879SAndroid Build Coastguard Worker std::string name = updater->FindBlockDeviceName(partition->name);
74*acea8879SAndroid Build Coastguard Worker if (name.empty()) {
75*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to find the block device " << partition->name;
76*acea8879SAndroid Build Coastguard Worker return false;
77*acea8879SAndroid Build Coastguard Worker }
78*acea8879SAndroid Build Coastguard Worker
79*acea8879SAndroid Build Coastguard Worker partition->name = std::move(name);
80*acea8879SAndroid Build Coastguard Worker return true;
81*acea8879SAndroid Build Coastguard Worker }
82*acea8879SAndroid Build Coastguard Worker
83*acea8879SAndroid Build Coastguard Worker // This is the updater side handler for ui_print() in edify script. Contents will be sent over to
84*acea8879SAndroid Build Coastguard Worker // the recovery side for on-screen display.
UIPrintFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)85*acea8879SAndroid Build Coastguard Worker Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
86*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
87*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
88*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
89*acea8879SAndroid Build Coastguard Worker }
90*acea8879SAndroid Build Coastguard Worker
91*acea8879SAndroid Build Coastguard Worker std::string buffer = android::base::Join(args, "");
92*acea8879SAndroid Build Coastguard Worker state->updater->UiPrint(buffer);
93*acea8879SAndroid Build Coastguard Worker return StringValue(buffer);
94*acea8879SAndroid Build Coastguard Worker }
95*acea8879SAndroid Build Coastguard Worker
96*acea8879SAndroid Build Coastguard Worker // package_extract_file(package_file[, dest_file])
97*acea8879SAndroid Build Coastguard Worker // Extracts a single package_file from the update package and writes it to dest_file,
98*acea8879SAndroid Build Coastguard Worker // overwriting existing files if necessary. Without the dest_file argument, returns the
99*acea8879SAndroid Build Coastguard Worker // contents of the package file as a binary blob.
PackageExtractFileFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)100*acea8879SAndroid Build Coastguard Worker Value* PackageExtractFileFn(const char* name, State* state,
101*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
102*acea8879SAndroid Build Coastguard Worker if (argv.size() < 1 || argv.size() > 2) {
103*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
104*acea8879SAndroid Build Coastguard Worker argv.size());
105*acea8879SAndroid Build Coastguard Worker }
106*acea8879SAndroid Build Coastguard Worker
107*acea8879SAndroid Build Coastguard Worker if (argv.size() == 2) {
108*acea8879SAndroid Build Coastguard Worker // The two-argument version extracts to a file.
109*acea8879SAndroid Build Coastguard Worker
110*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
111*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
112*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
113*acea8879SAndroid Build Coastguard Worker argv.size());
114*acea8879SAndroid Build Coastguard Worker }
115*acea8879SAndroid Build Coastguard Worker const std::string& zip_path = args[0];
116*acea8879SAndroid Build Coastguard Worker std::string dest_path = args[1];
117*acea8879SAndroid Build Coastguard Worker
118*acea8879SAndroid Build Coastguard Worker ZipArchiveHandle za = state->updater->GetPackageHandle();
119*acea8879SAndroid Build Coastguard Worker ZipEntry64 entry;
120*acea8879SAndroid Build Coastguard Worker if (FindEntry(za, zip_path, &entry) != 0) {
121*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": no " << zip_path << " in package";
122*acea8879SAndroid Build Coastguard Worker return StringValue("");
123*acea8879SAndroid Build Coastguard Worker }
124*acea8879SAndroid Build Coastguard Worker
125*acea8879SAndroid Build Coastguard Worker // Update the destination of package_extract_file if it's a block device. During simulation the
126*acea8879SAndroid Build Coastguard Worker // destination will map to a fake file.
127*acea8879SAndroid Build Coastguard Worker if (std::string block_device_name = state->updater->FindBlockDeviceName(dest_path);
128*acea8879SAndroid Build Coastguard Worker !block_device_name.empty()) {
129*acea8879SAndroid Build Coastguard Worker dest_path = block_device_name;
130*acea8879SAndroid Build Coastguard Worker }
131*acea8879SAndroid Build Coastguard Worker
132*acea8879SAndroid Build Coastguard Worker android::base::unique_fd fd(TEMP_FAILURE_RETRY(
133*acea8879SAndroid Build Coastguard Worker open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
134*acea8879SAndroid Build Coastguard Worker if (fd == -1) {
135*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
136*acea8879SAndroid Build Coastguard Worker return StringValue("");
137*acea8879SAndroid Build Coastguard Worker }
138*acea8879SAndroid Build Coastguard Worker
139*acea8879SAndroid Build Coastguard Worker bool success = true;
140*acea8879SAndroid Build Coastguard Worker int32_t ret = ExtractEntryToFile(za, &entry, fd);
141*acea8879SAndroid Build Coastguard Worker if (ret != 0) {
142*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
143*acea8879SAndroid Build Coastguard Worker << entry.uncompressed_length << " bytes) to \"" << dest_path
144*acea8879SAndroid Build Coastguard Worker << "\": " << ErrorCodeString(ret);
145*acea8879SAndroid Build Coastguard Worker success = false;
146*acea8879SAndroid Build Coastguard Worker }
147*acea8879SAndroid Build Coastguard Worker if (fsync(fd) == -1) {
148*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
149*acea8879SAndroid Build Coastguard Worker success = false;
150*acea8879SAndroid Build Coastguard Worker }
151*acea8879SAndroid Build Coastguard Worker
152*acea8879SAndroid Build Coastguard Worker if (close(fd.release()) != 0) {
153*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
154*acea8879SAndroid Build Coastguard Worker success = false;
155*acea8879SAndroid Build Coastguard Worker }
156*acea8879SAndroid Build Coastguard Worker
157*acea8879SAndroid Build Coastguard Worker return StringValue(success ? "t" : "");
158*acea8879SAndroid Build Coastguard Worker } else {
159*acea8879SAndroid Build Coastguard Worker // The one-argument version returns the contents of the file as the result.
160*acea8879SAndroid Build Coastguard Worker
161*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
162*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
163*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
164*acea8879SAndroid Build Coastguard Worker argv.size());
165*acea8879SAndroid Build Coastguard Worker }
166*acea8879SAndroid Build Coastguard Worker const std::string& zip_path = args[0];
167*acea8879SAndroid Build Coastguard Worker
168*acea8879SAndroid Build Coastguard Worker ZipArchiveHandle za = state->updater->GetPackageHandle();
169*acea8879SAndroid Build Coastguard Worker ZipEntry64 entry;
170*acea8879SAndroid Build Coastguard Worker if (FindEntry(za, zip_path, &entry) != 0) {
171*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
172*acea8879SAndroid Build Coastguard Worker zip_path.c_str());
173*acea8879SAndroid Build Coastguard Worker }
174*acea8879SAndroid Build Coastguard Worker
175*acea8879SAndroid Build Coastguard Worker std::string buffer;
176*acea8879SAndroid Build Coastguard Worker if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
177*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kPackageExtractFileFailure,
178*acea8879SAndroid Build Coastguard Worker "%s(): Entry `%s` Uncompressed size exceeds size of address space.", name,
179*acea8879SAndroid Build Coastguard Worker zip_path.c_str());
180*acea8879SAndroid Build Coastguard Worker }
181*acea8879SAndroid Build Coastguard Worker buffer.resize(entry.uncompressed_length);
182*acea8879SAndroid Build Coastguard Worker
183*acea8879SAndroid Build Coastguard Worker int32_t ret =
184*acea8879SAndroid Build Coastguard Worker ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
185*acea8879SAndroid Build Coastguard Worker if (ret != 0) {
186*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kPackageExtractFileFailure,
187*acea8879SAndroid Build Coastguard Worker "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
188*acea8879SAndroid Build Coastguard Worker zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
189*acea8879SAndroid Build Coastguard Worker }
190*acea8879SAndroid Build Coastguard Worker
191*acea8879SAndroid Build Coastguard Worker return new Value(Value::Type::BLOB, buffer);
192*acea8879SAndroid Build Coastguard Worker }
193*acea8879SAndroid Build Coastguard Worker }
194*acea8879SAndroid Build Coastguard Worker
195*acea8879SAndroid Build Coastguard Worker // patch_partition_check(target_partition, source_partition)
196*acea8879SAndroid Build Coastguard Worker // Checks if the target and source partitions have the desired checksums to be patched. It returns
197*acea8879SAndroid Build Coastguard Worker // directly, if the target partition already has the expected checksum. Otherwise it in turn
198*acea8879SAndroid Build Coastguard Worker // checks the integrity of the source partition and the backup file on /cache.
199*acea8879SAndroid Build Coastguard Worker //
200*acea8879SAndroid Build Coastguard Worker // For example, patch_partition_check(
201*acea8879SAndroid Build Coastguard Worker // "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
202*acea8879SAndroid Build Coastguard Worker // "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4")
PatchPartitionCheckFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)203*acea8879SAndroid Build Coastguard Worker Value* PatchPartitionCheckFn(const char* name, State* state,
204*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
205*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
206*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure,
207*acea8879SAndroid Build Coastguard Worker "%s(): Invalid number of args (expected 2, got %zu)", name, argv.size());
208*acea8879SAndroid Build Coastguard Worker }
209*acea8879SAndroid Build Coastguard Worker
210*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
211*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args, 0, 2)) {
212*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
213*acea8879SAndroid Build Coastguard Worker }
214*acea8879SAndroid Build Coastguard Worker
215*acea8879SAndroid Build Coastguard Worker std::string err;
216*acea8879SAndroid Build Coastguard Worker auto target = Partition::Parse(args[0], &err);
217*acea8879SAndroid Build Coastguard Worker if (!target) {
218*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
219*acea8879SAndroid Build Coastguard Worker args[0].c_str(), err.c_str());
220*acea8879SAndroid Build Coastguard Worker }
221*acea8879SAndroid Build Coastguard Worker
222*acea8879SAndroid Build Coastguard Worker auto source = Partition::Parse(args[1], &err);
223*acea8879SAndroid Build Coastguard Worker if (!source) {
224*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
225*acea8879SAndroid Build Coastguard Worker args[1].c_str(), err.c_str());
226*acea8879SAndroid Build Coastguard Worker }
227*acea8879SAndroid Build Coastguard Worker
228*acea8879SAndroid Build Coastguard Worker if (!UpdateBlockDeviceNameForPartition(state->updater, &source) ||
229*acea8879SAndroid Build Coastguard Worker !UpdateBlockDeviceNameForPartition(state->updater, &target)) {
230*acea8879SAndroid Build Coastguard Worker return StringValue("");
231*acea8879SAndroid Build Coastguard Worker }
232*acea8879SAndroid Build Coastguard Worker
233*acea8879SAndroid Build Coastguard Worker bool result = PatchPartitionCheck(target, source);
234*acea8879SAndroid Build Coastguard Worker return StringValue(result ? "t" : "");
235*acea8879SAndroid Build Coastguard Worker }
236*acea8879SAndroid Build Coastguard Worker
237*acea8879SAndroid Build Coastguard Worker // patch_partition(target, source, patch)
238*acea8879SAndroid Build Coastguard Worker // Applies the given patch to the source partition, and writes the result to the target partition.
239*acea8879SAndroid Build Coastguard Worker //
240*acea8879SAndroid Build Coastguard Worker // For example, patch_partition(
241*acea8879SAndroid Build Coastguard Worker // "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
242*acea8879SAndroid Build Coastguard Worker // "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4",
243*acea8879SAndroid Build Coastguard Worker // package_extract_file("boot.img.p"))
PatchPartitionFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)244*acea8879SAndroid Build Coastguard Worker Value* PatchPartitionFn(const char* name, State* state,
245*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
246*acea8879SAndroid Build Coastguard Worker if (argv.size() != 3) {
247*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure,
248*acea8879SAndroid Build Coastguard Worker "%s(): Invalid number of args (expected 3, got %zu)", name, argv.size());
249*acea8879SAndroid Build Coastguard Worker }
250*acea8879SAndroid Build Coastguard Worker
251*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
252*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args, 0, 2)) {
253*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
254*acea8879SAndroid Build Coastguard Worker }
255*acea8879SAndroid Build Coastguard Worker
256*acea8879SAndroid Build Coastguard Worker std::string err;
257*acea8879SAndroid Build Coastguard Worker auto target = Partition::Parse(args[0], &err);
258*acea8879SAndroid Build Coastguard Worker if (!target) {
259*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
260*acea8879SAndroid Build Coastguard Worker args[0].c_str(), err.c_str());
261*acea8879SAndroid Build Coastguard Worker }
262*acea8879SAndroid Build Coastguard Worker
263*acea8879SAndroid Build Coastguard Worker auto source = Partition::Parse(args[1], &err);
264*acea8879SAndroid Build Coastguard Worker if (!source) {
265*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
266*acea8879SAndroid Build Coastguard Worker args[1].c_str(), err.c_str());
267*acea8879SAndroid Build Coastguard Worker }
268*acea8879SAndroid Build Coastguard Worker
269*acea8879SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Value>> values;
270*acea8879SAndroid Build Coastguard Worker if (!ReadValueArgs(state, argv, &values, 2, 1) || values[0]->type != Value::Type::BLOB) {
271*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Invalid patch arg", name);
272*acea8879SAndroid Build Coastguard Worker }
273*acea8879SAndroid Build Coastguard Worker
274*acea8879SAndroid Build Coastguard Worker if (!UpdateBlockDeviceNameForPartition(state->updater, &source) ||
275*acea8879SAndroid Build Coastguard Worker !UpdateBlockDeviceNameForPartition(state->updater, &target)) {
276*acea8879SAndroid Build Coastguard Worker return StringValue("");
277*acea8879SAndroid Build Coastguard Worker }
278*acea8879SAndroid Build Coastguard Worker
279*acea8879SAndroid Build Coastguard Worker bool result = PatchPartition(target, source, *values[0], nullptr, true);
280*acea8879SAndroid Build Coastguard Worker return StringValue(result ? "t" : "");
281*acea8879SAndroid Build Coastguard Worker }
282*acea8879SAndroid Build Coastguard Worker
283*acea8879SAndroid Build Coastguard Worker // mount(fs_type, partition_type, location, mount_point)
284*acea8879SAndroid Build Coastguard Worker // mount(fs_type, partition_type, location, mount_point, mount_options)
285*acea8879SAndroid Build Coastguard Worker
286*acea8879SAndroid Build Coastguard Worker // fs_type="ext4" partition_type="EMMC" location=device
MountFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)287*acea8879SAndroid Build Coastguard Worker Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
288*acea8879SAndroid Build Coastguard Worker if (argv.size() != 4 && argv.size() != 5) {
289*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name,
290*acea8879SAndroid Build Coastguard Worker argv.size());
291*acea8879SAndroid Build Coastguard Worker }
292*acea8879SAndroid Build Coastguard Worker
293*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
294*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
295*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
296*acea8879SAndroid Build Coastguard Worker }
297*acea8879SAndroid Build Coastguard Worker const std::string& fs_type = args[0];
298*acea8879SAndroid Build Coastguard Worker const std::string& partition_type = args[1];
299*acea8879SAndroid Build Coastguard Worker const std::string& location = args[2];
300*acea8879SAndroid Build Coastguard Worker const std::string& mount_point = args[3];
301*acea8879SAndroid Build Coastguard Worker std::string mount_options;
302*acea8879SAndroid Build Coastguard Worker
303*acea8879SAndroid Build Coastguard Worker if (argv.size() == 5) {
304*acea8879SAndroid Build Coastguard Worker mount_options = args[4];
305*acea8879SAndroid Build Coastguard Worker }
306*acea8879SAndroid Build Coastguard Worker
307*acea8879SAndroid Build Coastguard Worker if (fs_type.empty()) {
308*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
309*acea8879SAndroid Build Coastguard Worker }
310*acea8879SAndroid Build Coastguard Worker if (partition_type.empty()) {
311*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
312*acea8879SAndroid Build Coastguard Worker name);
313*acea8879SAndroid Build Coastguard Worker }
314*acea8879SAndroid Build Coastguard Worker if (location.empty()) {
315*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
316*acea8879SAndroid Build Coastguard Worker }
317*acea8879SAndroid Build Coastguard Worker if (mount_point.empty()) {
318*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
319*acea8879SAndroid Build Coastguard Worker name);
320*acea8879SAndroid Build Coastguard Worker }
321*acea8879SAndroid Build Coastguard Worker
322*acea8879SAndroid Build Coastguard Worker auto updater = state->updater;
323*acea8879SAndroid Build Coastguard Worker if (updater->GetRuntime()->Mount(location, mount_point, fs_type, mount_options) != 0) {
324*acea8879SAndroid Build Coastguard Worker updater->UiPrint(android::base::StringPrintf("%s: Failed to mount %s at %s: %s", name,
325*acea8879SAndroid Build Coastguard Worker location.c_str(), mount_point.c_str(),
326*acea8879SAndroid Build Coastguard Worker strerror(errno)));
327*acea8879SAndroid Build Coastguard Worker return StringValue("");
328*acea8879SAndroid Build Coastguard Worker }
329*acea8879SAndroid Build Coastguard Worker
330*acea8879SAndroid Build Coastguard Worker return StringValue(mount_point);
331*acea8879SAndroid Build Coastguard Worker }
332*acea8879SAndroid Build Coastguard Worker
333*acea8879SAndroid Build Coastguard Worker // is_mounted(mount_point)
IsMountedFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)334*acea8879SAndroid Build Coastguard Worker Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
335*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
336*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
337*acea8879SAndroid Build Coastguard Worker }
338*acea8879SAndroid Build Coastguard Worker
339*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
340*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
341*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
342*acea8879SAndroid Build Coastguard Worker }
343*acea8879SAndroid Build Coastguard Worker const std::string& mount_point = args[0];
344*acea8879SAndroid Build Coastguard Worker if (mount_point.empty()) {
345*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure,
346*acea8879SAndroid Build Coastguard Worker "mount_point argument to unmount() can't be empty");
347*acea8879SAndroid Build Coastguard Worker }
348*acea8879SAndroid Build Coastguard Worker
349*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
350*acea8879SAndroid Build Coastguard Worker if (!updater_runtime->IsMounted(mount_point)) {
351*acea8879SAndroid Build Coastguard Worker return StringValue("");
352*acea8879SAndroid Build Coastguard Worker }
353*acea8879SAndroid Build Coastguard Worker
354*acea8879SAndroid Build Coastguard Worker return StringValue(mount_point);
355*acea8879SAndroid Build Coastguard Worker }
356*acea8879SAndroid Build Coastguard Worker
UnmountFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)357*acea8879SAndroid Build Coastguard Worker Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
358*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
359*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
360*acea8879SAndroid Build Coastguard Worker }
361*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
362*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
363*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
364*acea8879SAndroid Build Coastguard Worker }
365*acea8879SAndroid Build Coastguard Worker const std::string& mount_point = args[0];
366*acea8879SAndroid Build Coastguard Worker if (mount_point.empty()) {
367*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure,
368*acea8879SAndroid Build Coastguard Worker "mount_point argument to unmount() can't be empty");
369*acea8879SAndroid Build Coastguard Worker }
370*acea8879SAndroid Build Coastguard Worker
371*acea8879SAndroid Build Coastguard Worker auto updater = state->updater;
372*acea8879SAndroid Build Coastguard Worker auto [mounted, result] = updater->GetRuntime()->Unmount(mount_point);
373*acea8879SAndroid Build Coastguard Worker if (!mounted) {
374*acea8879SAndroid Build Coastguard Worker updater->UiPrint(
375*acea8879SAndroid Build Coastguard Worker android::base::StringPrintf("Failed to unmount %s: No such volume", mount_point.c_str()));
376*acea8879SAndroid Build Coastguard Worker return nullptr;
377*acea8879SAndroid Build Coastguard Worker } else if (result != 0) {
378*acea8879SAndroid Build Coastguard Worker updater->UiPrint(android::base::StringPrintf("Failed to unmount %s: %s", mount_point.c_str(),
379*acea8879SAndroid Build Coastguard Worker strerror(errno)));
380*acea8879SAndroid Build Coastguard Worker }
381*acea8879SAndroid Build Coastguard Worker
382*acea8879SAndroid Build Coastguard Worker return StringValue(mount_point);
383*acea8879SAndroid Build Coastguard Worker }
384*acea8879SAndroid Build Coastguard Worker
385*acea8879SAndroid Build Coastguard Worker // format(fs_type, partition_type, location, fs_size, mount_point)
386*acea8879SAndroid Build Coastguard Worker //
387*acea8879SAndroid Build Coastguard Worker // fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
388*acea8879SAndroid Build Coastguard Worker // fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
389*acea8879SAndroid Build Coastguard Worker // if fs_size == 0, then make fs uses the entire partition.
390*acea8879SAndroid Build Coastguard Worker // if fs_size > 0, that is the size to use
391*acea8879SAndroid Build Coastguard Worker // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
FormatFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)392*acea8879SAndroid Build Coastguard Worker Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
393*acea8879SAndroid Build Coastguard Worker if (argv.size() != 5) {
394*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name,
395*acea8879SAndroid Build Coastguard Worker argv.size());
396*acea8879SAndroid Build Coastguard Worker }
397*acea8879SAndroid Build Coastguard Worker
398*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
399*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
400*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
401*acea8879SAndroid Build Coastguard Worker }
402*acea8879SAndroid Build Coastguard Worker const std::string& fs_type = args[0];
403*acea8879SAndroid Build Coastguard Worker const std::string& partition_type = args[1];
404*acea8879SAndroid Build Coastguard Worker const std::string& location = args[2];
405*acea8879SAndroid Build Coastguard Worker const std::string& fs_size = args[3];
406*acea8879SAndroid Build Coastguard Worker const std::string& mount_point = args[4];
407*acea8879SAndroid Build Coastguard Worker
408*acea8879SAndroid Build Coastguard Worker if (fs_type.empty()) {
409*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
410*acea8879SAndroid Build Coastguard Worker }
411*acea8879SAndroid Build Coastguard Worker if (partition_type.empty()) {
412*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
413*acea8879SAndroid Build Coastguard Worker name);
414*acea8879SAndroid Build Coastguard Worker }
415*acea8879SAndroid Build Coastguard Worker if (location.empty()) {
416*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
417*acea8879SAndroid Build Coastguard Worker }
418*acea8879SAndroid Build Coastguard Worker if (mount_point.empty()) {
419*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
420*acea8879SAndroid Build Coastguard Worker name);
421*acea8879SAndroid Build Coastguard Worker }
422*acea8879SAndroid Build Coastguard Worker
423*acea8879SAndroid Build Coastguard Worker int64_t size;
424*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(fs_size, &size)) {
425*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
426*acea8879SAndroid Build Coastguard Worker fs_size.c_str());
427*acea8879SAndroid Build Coastguard Worker }
428*acea8879SAndroid Build Coastguard Worker
429*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
430*acea8879SAndroid Build Coastguard Worker if (fs_type == "ext4") {
431*acea8879SAndroid Build Coastguard Worker std::vector<std::string> mke2fs_args = {
432*acea8879SAndroid Build Coastguard Worker "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", location
433*acea8879SAndroid Build Coastguard Worker };
434*acea8879SAndroid Build Coastguard Worker if (size != 0) {
435*acea8879SAndroid Build Coastguard Worker mke2fs_args.push_back(std::to_string(size / 4096LL));
436*acea8879SAndroid Build Coastguard Worker }
437*acea8879SAndroid Build Coastguard Worker
438*acea8879SAndroid Build Coastguard Worker if (auto status = updater_runtime->RunProgram(mke2fs_args, true); status != 0) {
439*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location;
440*acea8879SAndroid Build Coastguard Worker return StringValue("");
441*acea8879SAndroid Build Coastguard Worker }
442*acea8879SAndroid Build Coastguard Worker
443*acea8879SAndroid Build Coastguard Worker if (auto status = updater_runtime->RunProgram(
444*acea8879SAndroid Build Coastguard Worker { "/system/bin/e2fsdroid", "-e", "-a", mount_point, location }, true);
445*acea8879SAndroid Build Coastguard Worker status != 0) {
446*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location;
447*acea8879SAndroid Build Coastguard Worker return StringValue("");
448*acea8879SAndroid Build Coastguard Worker }
449*acea8879SAndroid Build Coastguard Worker return StringValue(location);
450*acea8879SAndroid Build Coastguard Worker }
451*acea8879SAndroid Build Coastguard Worker
452*acea8879SAndroid Build Coastguard Worker if (fs_type == "f2fs") {
453*acea8879SAndroid Build Coastguard Worker if (size < 0) {
454*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
455*acea8879SAndroid Build Coastguard Worker return StringValue("");
456*acea8879SAndroid Build Coastguard Worker }
457*acea8879SAndroid Build Coastguard Worker std::vector<std::string> f2fs_args = {
458*acea8879SAndroid Build Coastguard Worker "/system/bin/make_f2fs", "-g", "android", "-w", "512", location
459*acea8879SAndroid Build Coastguard Worker };
460*acea8879SAndroid Build Coastguard Worker if (size >= 512) {
461*acea8879SAndroid Build Coastguard Worker f2fs_args.push_back(std::to_string(size / 512));
462*acea8879SAndroid Build Coastguard Worker }
463*acea8879SAndroid Build Coastguard Worker if (auto status = updater_runtime->RunProgram(f2fs_args, true); status != 0) {
464*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": make_f2fs failed (" << status << ") on " << location;
465*acea8879SAndroid Build Coastguard Worker return StringValue("");
466*acea8879SAndroid Build Coastguard Worker }
467*acea8879SAndroid Build Coastguard Worker
468*acea8879SAndroid Build Coastguard Worker if (auto status = updater_runtime->RunProgram(
469*acea8879SAndroid Build Coastguard Worker { "/system/bin/sload_f2fs", "-t", mount_point, location }, true);
470*acea8879SAndroid Build Coastguard Worker status != 0) {
471*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": sload_f2fs failed (" << status << ") on " << location;
472*acea8879SAndroid Build Coastguard Worker return StringValue("");
473*acea8879SAndroid Build Coastguard Worker }
474*acea8879SAndroid Build Coastguard Worker
475*acea8879SAndroid Build Coastguard Worker return StringValue(location);
476*acea8879SAndroid Build Coastguard Worker }
477*acea8879SAndroid Build Coastguard Worker
478*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
479*acea8879SAndroid Build Coastguard Worker << partition_type << "\"";
480*acea8879SAndroid Build Coastguard Worker return nullptr;
481*acea8879SAndroid Build Coastguard Worker }
482*acea8879SAndroid Build Coastguard Worker
ShowProgressFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)483*acea8879SAndroid Build Coastguard Worker Value* ShowProgressFn(const char* name, State* state,
484*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
485*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
486*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
487*acea8879SAndroid Build Coastguard Worker argv.size());
488*acea8879SAndroid Build Coastguard Worker }
489*acea8879SAndroid Build Coastguard Worker
490*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
491*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
492*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
493*acea8879SAndroid Build Coastguard Worker }
494*acea8879SAndroid Build Coastguard Worker const std::string& frac_str = args[0];
495*acea8879SAndroid Build Coastguard Worker const std::string& sec_str = args[1];
496*acea8879SAndroid Build Coastguard Worker
497*acea8879SAndroid Build Coastguard Worker double frac;
498*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
499*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
500*acea8879SAndroid Build Coastguard Worker frac_str.c_str());
501*acea8879SAndroid Build Coastguard Worker }
502*acea8879SAndroid Build Coastguard Worker int sec;
503*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
504*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
505*acea8879SAndroid Build Coastguard Worker sec_str.c_str());
506*acea8879SAndroid Build Coastguard Worker }
507*acea8879SAndroid Build Coastguard Worker
508*acea8879SAndroid Build Coastguard Worker state->updater->WriteToCommandPipe(android::base::StringPrintf("progress %f %d", frac, sec));
509*acea8879SAndroid Build Coastguard Worker
510*acea8879SAndroid Build Coastguard Worker return StringValue(frac_str);
511*acea8879SAndroid Build Coastguard Worker }
512*acea8879SAndroid Build Coastguard Worker
SetProgressFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)513*acea8879SAndroid Build Coastguard Worker Value* SetProgressFn(const char* name, State* state,
514*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
515*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
516*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
517*acea8879SAndroid Build Coastguard Worker }
518*acea8879SAndroid Build Coastguard Worker
519*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
520*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
521*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
522*acea8879SAndroid Build Coastguard Worker }
523*acea8879SAndroid Build Coastguard Worker const std::string& frac_str = args[0];
524*acea8879SAndroid Build Coastguard Worker
525*acea8879SAndroid Build Coastguard Worker double frac;
526*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
527*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
528*acea8879SAndroid Build Coastguard Worker frac_str.c_str());
529*acea8879SAndroid Build Coastguard Worker }
530*acea8879SAndroid Build Coastguard Worker
531*acea8879SAndroid Build Coastguard Worker state->updater->WriteToCommandPipe(android::base::StringPrintf("set_progress %f", frac));
532*acea8879SAndroid Build Coastguard Worker
533*acea8879SAndroid Build Coastguard Worker return StringValue(frac_str);
534*acea8879SAndroid Build Coastguard Worker }
535*acea8879SAndroid Build Coastguard Worker
GetPropFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)536*acea8879SAndroid Build Coastguard Worker Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
537*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
538*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
539*acea8879SAndroid Build Coastguard Worker }
540*acea8879SAndroid Build Coastguard Worker std::string key;
541*acea8879SAndroid Build Coastguard Worker if (!Evaluate(state, argv[0], &key)) {
542*acea8879SAndroid Build Coastguard Worker return nullptr;
543*acea8879SAndroid Build Coastguard Worker }
544*acea8879SAndroid Build Coastguard Worker
545*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
546*acea8879SAndroid Build Coastguard Worker std::string value = updater_runtime->GetProperty(key, "");
547*acea8879SAndroid Build Coastguard Worker
548*acea8879SAndroid Build Coastguard Worker return StringValue(value);
549*acea8879SAndroid Build Coastguard Worker }
550*acea8879SAndroid Build Coastguard Worker
551*acea8879SAndroid Build Coastguard Worker // file_getprop(file, key)
552*acea8879SAndroid Build Coastguard Worker //
553*acea8879SAndroid Build Coastguard Worker // interprets 'file' as a getprop-style file (key=value pairs, one
554*acea8879SAndroid Build Coastguard Worker // per line. # comment lines, blank lines, lines without '=' ignored),
555*acea8879SAndroid Build Coastguard Worker // and returns the value for 'key' (or "" if it isn't defined).
FileGetPropFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)556*acea8879SAndroid Build Coastguard Worker Value* FileGetPropFn(const char* name, State* state,
557*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
558*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
559*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
560*acea8879SAndroid Build Coastguard Worker argv.size());
561*acea8879SAndroid Build Coastguard Worker }
562*acea8879SAndroid Build Coastguard Worker
563*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
564*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
565*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
566*acea8879SAndroid Build Coastguard Worker }
567*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
568*acea8879SAndroid Build Coastguard Worker const std::string& key = args[1];
569*acea8879SAndroid Build Coastguard Worker
570*acea8879SAndroid Build Coastguard Worker std::string buffer;
571*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
572*acea8879SAndroid Build Coastguard Worker if (!updater_runtime->ReadFileToString(filename, &buffer)) {
573*acea8879SAndroid Build Coastguard Worker ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
574*acea8879SAndroid Build Coastguard Worker return nullptr;
575*acea8879SAndroid Build Coastguard Worker }
576*acea8879SAndroid Build Coastguard Worker
577*acea8879SAndroid Build Coastguard Worker std::vector<std::string> lines = android::base::Split(buffer, "\n");
578*acea8879SAndroid Build Coastguard Worker for (size_t i = 0; i < lines.size(); i++) {
579*acea8879SAndroid Build Coastguard Worker std::string line = android::base::Trim(lines[i]);
580*acea8879SAndroid Build Coastguard Worker
581*acea8879SAndroid Build Coastguard Worker // comment or blank line: skip to next line
582*acea8879SAndroid Build Coastguard Worker if (line.empty() || line[0] == '#') {
583*acea8879SAndroid Build Coastguard Worker continue;
584*acea8879SAndroid Build Coastguard Worker }
585*acea8879SAndroid Build Coastguard Worker size_t equal_pos = line.find('=');
586*acea8879SAndroid Build Coastguard Worker if (equal_pos == std::string::npos) {
587*acea8879SAndroid Build Coastguard Worker continue;
588*acea8879SAndroid Build Coastguard Worker }
589*acea8879SAndroid Build Coastguard Worker
590*acea8879SAndroid Build Coastguard Worker // trim whitespace between key and '='
591*acea8879SAndroid Build Coastguard Worker std::string str = android::base::Trim(line.substr(0, equal_pos));
592*acea8879SAndroid Build Coastguard Worker
593*acea8879SAndroid Build Coastguard Worker // not the key we're looking for
594*acea8879SAndroid Build Coastguard Worker if (key != str) continue;
595*acea8879SAndroid Build Coastguard Worker
596*acea8879SAndroid Build Coastguard Worker return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
597*acea8879SAndroid Build Coastguard Worker }
598*acea8879SAndroid Build Coastguard Worker
599*acea8879SAndroid Build Coastguard Worker return StringValue("");
600*acea8879SAndroid Build Coastguard Worker }
601*acea8879SAndroid Build Coastguard Worker
602*acea8879SAndroid Build Coastguard Worker // apply_patch_space(bytes)
ApplyPatchSpaceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)603*acea8879SAndroid Build Coastguard Worker Value* ApplyPatchSpaceFn(const char* name, State* state,
604*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
605*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
606*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name,
607*acea8879SAndroid Build Coastguard Worker argv.size());
608*acea8879SAndroid Build Coastguard Worker }
609*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
610*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
611*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
612*acea8879SAndroid Build Coastguard Worker }
613*acea8879SAndroid Build Coastguard Worker const std::string& bytes_str = args[0];
614*acea8879SAndroid Build Coastguard Worker
615*acea8879SAndroid Build Coastguard Worker size_t bytes;
616*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
617*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name,
618*acea8879SAndroid Build Coastguard Worker bytes_str.c_str());
619*acea8879SAndroid Build Coastguard Worker }
620*acea8879SAndroid Build Coastguard Worker
621*acea8879SAndroid Build Coastguard Worker // Skip the cache size check if the update is a retry.
622*acea8879SAndroid Build Coastguard Worker if (state->is_retry || CheckAndFreeSpaceOnCache(bytes)) {
623*acea8879SAndroid Build Coastguard Worker return StringValue("t");
624*acea8879SAndroid Build Coastguard Worker }
625*acea8879SAndroid Build Coastguard Worker return StringValue("");
626*acea8879SAndroid Build Coastguard Worker }
627*acea8879SAndroid Build Coastguard Worker
WipeCacheFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)628*acea8879SAndroid Build Coastguard Worker Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
629*acea8879SAndroid Build Coastguard Worker if (!argv.empty()) {
630*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
631*acea8879SAndroid Build Coastguard Worker argv.size());
632*acea8879SAndroid Build Coastguard Worker }
633*acea8879SAndroid Build Coastguard Worker
634*acea8879SAndroid Build Coastguard Worker state->updater->WriteToCommandPipe("wipe_cache");
635*acea8879SAndroid Build Coastguard Worker return StringValue("t");
636*acea8879SAndroid Build Coastguard Worker }
637*acea8879SAndroid Build Coastguard Worker
RunProgramFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)638*acea8879SAndroid Build Coastguard Worker Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
639*acea8879SAndroid Build Coastguard Worker if (argv.size() < 1) {
640*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
641*acea8879SAndroid Build Coastguard Worker }
642*acea8879SAndroid Build Coastguard Worker
643*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
644*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
645*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
646*acea8879SAndroid Build Coastguard Worker }
647*acea8879SAndroid Build Coastguard Worker
648*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
649*acea8879SAndroid Build Coastguard Worker auto status = updater_runtime->RunProgram(args, false);
650*acea8879SAndroid Build Coastguard Worker return StringValue(std::to_string(status));
651*acea8879SAndroid Build Coastguard Worker }
652*acea8879SAndroid Build Coastguard Worker
653*acea8879SAndroid Build Coastguard Worker // read_file(filename)
654*acea8879SAndroid Build Coastguard Worker // Reads a local file 'filename' and returns its contents as a string Value.
ReadFileFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)655*acea8879SAndroid Build Coastguard Worker Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
656*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
657*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
658*acea8879SAndroid Build Coastguard Worker }
659*acea8879SAndroid Build Coastguard Worker
660*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
661*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
662*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
663*acea8879SAndroid Build Coastguard Worker }
664*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
665*acea8879SAndroid Build Coastguard Worker
666*acea8879SAndroid Build Coastguard Worker std::string contents;
667*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
668*acea8879SAndroid Build Coastguard Worker if (updater_runtime->ReadFileToString(filename, &contents)) {
669*acea8879SAndroid Build Coastguard Worker return new Value(Value::Type::STRING, std::move(contents));
670*acea8879SAndroid Build Coastguard Worker }
671*acea8879SAndroid Build Coastguard Worker
672*acea8879SAndroid Build Coastguard Worker // Leave it to caller to handle the failure.
673*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << name << ": Failed to read " << filename;
674*acea8879SAndroid Build Coastguard Worker return StringValue("");
675*acea8879SAndroid Build Coastguard Worker }
676*acea8879SAndroid Build Coastguard Worker
677*acea8879SAndroid Build Coastguard Worker // write_value(value, filename)
678*acea8879SAndroid Build Coastguard Worker // Writes 'value' to 'filename'.
679*acea8879SAndroid Build Coastguard Worker // Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
WriteValueFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)680*acea8879SAndroid Build Coastguard Worker Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
681*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
682*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
683*acea8879SAndroid Build Coastguard Worker argv.size());
684*acea8879SAndroid Build Coastguard Worker }
685*acea8879SAndroid Build Coastguard Worker
686*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
687*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
688*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
689*acea8879SAndroid Build Coastguard Worker }
690*acea8879SAndroid Build Coastguard Worker
691*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[1];
692*acea8879SAndroid Build Coastguard Worker if (filename.empty()) {
693*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
694*acea8879SAndroid Build Coastguard Worker }
695*acea8879SAndroid Build Coastguard Worker
696*acea8879SAndroid Build Coastguard Worker const std::string& value = args[0];
697*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
698*acea8879SAndroid Build Coastguard Worker if (!updater_runtime->WriteStringToFile(value, filename)) {
699*acea8879SAndroid Build Coastguard Worker PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
700*acea8879SAndroid Build Coastguard Worker return StringValue("");
701*acea8879SAndroid Build Coastguard Worker }
702*acea8879SAndroid Build Coastguard Worker return StringValue("t");
703*acea8879SAndroid Build Coastguard Worker }
704*acea8879SAndroid Build Coastguard Worker
705*acea8879SAndroid Build Coastguard Worker // Immediately reboot the device. Recovery is not finished normally,
706*acea8879SAndroid Build Coastguard Worker // so if you reboot into recovery it will re-start applying the
707*acea8879SAndroid Build Coastguard Worker // current package (because nothing has cleared the copy of the
708*acea8879SAndroid Build Coastguard Worker // arguments stored in the BCB).
709*acea8879SAndroid Build Coastguard Worker //
710*acea8879SAndroid Build Coastguard Worker // The argument is the partition name passed to the android reboot
711*acea8879SAndroid Build Coastguard Worker // property. It can be "recovery" to boot from the recovery
712*acea8879SAndroid Build Coastguard Worker // partition, or "" (empty string) to boot from the regular boot
713*acea8879SAndroid Build Coastguard Worker // partition.
RebootNowFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)714*acea8879SAndroid Build Coastguard Worker Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
715*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
716*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
717*acea8879SAndroid Build Coastguard Worker argv.size());
718*acea8879SAndroid Build Coastguard Worker }
719*acea8879SAndroid Build Coastguard Worker
720*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
721*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
722*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
723*acea8879SAndroid Build Coastguard Worker }
724*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
725*acea8879SAndroid Build Coastguard Worker const std::string& property = args[1];
726*acea8879SAndroid Build Coastguard Worker
727*acea8879SAndroid Build Coastguard Worker // Zero out the 'command' field of the bootloader message. Leave the rest intact.
728*acea8879SAndroid Build Coastguard Worker bootloader_message boot;
729*acea8879SAndroid Build Coastguard Worker std::string err;
730*acea8879SAndroid Build Coastguard Worker if (!read_bootloader_message_from(&boot, filename, &err)) {
731*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
732*acea8879SAndroid Build Coastguard Worker return StringValue("");
733*acea8879SAndroid Build Coastguard Worker }
734*acea8879SAndroid Build Coastguard Worker memset(boot.command, 0, sizeof(boot.command));
735*acea8879SAndroid Build Coastguard Worker if (!write_bootloader_message_to(boot, filename, &err)) {
736*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
737*acea8879SAndroid Build Coastguard Worker return StringValue("");
738*acea8879SAndroid Build Coastguard Worker }
739*acea8879SAndroid Build Coastguard Worker
740*acea8879SAndroid Build Coastguard Worker Reboot(property);
741*acea8879SAndroid Build Coastguard Worker
742*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
743*acea8879SAndroid Build Coastguard Worker }
744*acea8879SAndroid Build Coastguard Worker
745*acea8879SAndroid Build Coastguard Worker // Store a string value somewhere that future invocations of recovery
746*acea8879SAndroid Build Coastguard Worker // can access it. This value is called the "stage" and can be used to
747*acea8879SAndroid Build Coastguard Worker // drive packages that need to do reboots in the middle of
748*acea8879SAndroid Build Coastguard Worker // installation and keep track of where they are in the multi-stage
749*acea8879SAndroid Build Coastguard Worker // install.
750*acea8879SAndroid Build Coastguard Worker //
751*acea8879SAndroid Build Coastguard Worker // The first argument is the block device for the misc partition
752*acea8879SAndroid Build Coastguard Worker // ("/misc" in the fstab), which is where this value is stored. The
753*acea8879SAndroid Build Coastguard Worker // second argument is the string to store; it should not exceed 31
754*acea8879SAndroid Build Coastguard Worker // bytes.
SetStageFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)755*acea8879SAndroid Build Coastguard Worker Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
756*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
757*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
758*acea8879SAndroid Build Coastguard Worker argv.size());
759*acea8879SAndroid Build Coastguard Worker }
760*acea8879SAndroid Build Coastguard Worker
761*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
762*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
763*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
764*acea8879SAndroid Build Coastguard Worker }
765*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
766*acea8879SAndroid Build Coastguard Worker const std::string& stagestr = args[1];
767*acea8879SAndroid Build Coastguard Worker
768*acea8879SAndroid Build Coastguard Worker // Store this value in the misc partition, immediately after the
769*acea8879SAndroid Build Coastguard Worker // bootloader message that the main recovery uses to save its
770*acea8879SAndroid Build Coastguard Worker // arguments in case of the device restarting midway through
771*acea8879SAndroid Build Coastguard Worker // package installation.
772*acea8879SAndroid Build Coastguard Worker bootloader_message boot;
773*acea8879SAndroid Build Coastguard Worker std::string err;
774*acea8879SAndroid Build Coastguard Worker if (!read_bootloader_message_from(&boot, filename, &err)) {
775*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
776*acea8879SAndroid Build Coastguard Worker return StringValue("");
777*acea8879SAndroid Build Coastguard Worker }
778*acea8879SAndroid Build Coastguard Worker strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
779*acea8879SAndroid Build Coastguard Worker if (!write_bootloader_message_to(boot, filename, &err)) {
780*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
781*acea8879SAndroid Build Coastguard Worker return StringValue("");
782*acea8879SAndroid Build Coastguard Worker }
783*acea8879SAndroid Build Coastguard Worker
784*acea8879SAndroid Build Coastguard Worker return StringValue(filename);
785*acea8879SAndroid Build Coastguard Worker }
786*acea8879SAndroid Build Coastguard Worker
787*acea8879SAndroid Build Coastguard Worker // Return the value most recently saved with SetStageFn. The argument
788*acea8879SAndroid Build Coastguard Worker // is the block device for the misc partition.
GetStageFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)789*acea8879SAndroid Build Coastguard Worker Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
790*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
791*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
792*acea8879SAndroid Build Coastguard Worker }
793*acea8879SAndroid Build Coastguard Worker
794*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
795*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
796*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
797*acea8879SAndroid Build Coastguard Worker }
798*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
799*acea8879SAndroid Build Coastguard Worker
800*acea8879SAndroid Build Coastguard Worker bootloader_message boot;
801*acea8879SAndroid Build Coastguard Worker std::string err;
802*acea8879SAndroid Build Coastguard Worker if (!read_bootloader_message_from(&boot, filename, &err)) {
803*acea8879SAndroid Build Coastguard Worker LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
804*acea8879SAndroid Build Coastguard Worker return StringValue("");
805*acea8879SAndroid Build Coastguard Worker }
806*acea8879SAndroid Build Coastguard Worker
807*acea8879SAndroid Build Coastguard Worker return StringValue(boot.stage);
808*acea8879SAndroid Build Coastguard Worker }
809*acea8879SAndroid Build Coastguard Worker
WipeBlockDeviceFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)810*acea8879SAndroid Build Coastguard Worker Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
811*acea8879SAndroid Build Coastguard Worker if (argv.size() != 2) {
812*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
813*acea8879SAndroid Build Coastguard Worker argv.size());
814*acea8879SAndroid Build Coastguard Worker }
815*acea8879SAndroid Build Coastguard Worker
816*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
817*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
818*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
819*acea8879SAndroid Build Coastguard Worker }
820*acea8879SAndroid Build Coastguard Worker const std::string& filename = args[0];
821*acea8879SAndroid Build Coastguard Worker const std::string& len_str = args[1];
822*acea8879SAndroid Build Coastguard Worker
823*acea8879SAndroid Build Coastguard Worker size_t len;
824*acea8879SAndroid Build Coastguard Worker if (!android::base::ParseUint(len_str.c_str(), &len)) {
825*acea8879SAndroid Build Coastguard Worker return nullptr;
826*acea8879SAndroid Build Coastguard Worker }
827*acea8879SAndroid Build Coastguard Worker
828*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
829*acea8879SAndroid Build Coastguard Worker int status = updater_runtime->WipeBlockDevice(filename, len);
830*acea8879SAndroid Build Coastguard Worker return StringValue(status == 0 ? "t" : "");
831*acea8879SAndroid Build Coastguard Worker }
832*acea8879SAndroid Build Coastguard Worker
EnableRebootFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)833*acea8879SAndroid Build Coastguard Worker Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
834*acea8879SAndroid Build Coastguard Worker if (!argv.empty()) {
835*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
836*acea8879SAndroid Build Coastguard Worker argv.size());
837*acea8879SAndroid Build Coastguard Worker }
838*acea8879SAndroid Build Coastguard Worker state->updater->WriteToCommandPipe("enable_reboot");
839*acea8879SAndroid Build Coastguard Worker return StringValue("t");
840*acea8879SAndroid Build Coastguard Worker }
841*acea8879SAndroid Build Coastguard Worker
Tune2FsFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)842*acea8879SAndroid Build Coastguard Worker Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
843*acea8879SAndroid Build Coastguard Worker if (argv.empty()) {
844*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size());
845*acea8879SAndroid Build Coastguard Worker }
846*acea8879SAndroid Build Coastguard Worker
847*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
848*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
849*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
850*acea8879SAndroid Build Coastguard Worker }
851*acea8879SAndroid Build Coastguard Worker
852*acea8879SAndroid Build Coastguard Worker // tune2fs expects the program name as its first arg.
853*acea8879SAndroid Build Coastguard Worker args.insert(args.begin(), "tune2fs");
854*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
855*acea8879SAndroid Build Coastguard Worker if (auto result = updater_runtime->Tune2Fs(args); result != 0) {
856*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
857*acea8879SAndroid Build Coastguard Worker }
858*acea8879SAndroid Build Coastguard Worker return StringValue("t");
859*acea8879SAndroid Build Coastguard Worker }
860*acea8879SAndroid Build Coastguard Worker
AddSlotSuffixFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)861*acea8879SAndroid Build Coastguard Worker Value* AddSlotSuffixFn(const char* name, State* state,
862*acea8879SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Expr>>& argv) {
863*acea8879SAndroid Build Coastguard Worker if (argv.size() != 1) {
864*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
865*acea8879SAndroid Build Coastguard Worker }
866*acea8879SAndroid Build Coastguard Worker std::vector<std::string> args;
867*acea8879SAndroid Build Coastguard Worker if (!ReadArgs(state, argv, &args)) {
868*acea8879SAndroid Build Coastguard Worker return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
869*acea8879SAndroid Build Coastguard Worker }
870*acea8879SAndroid Build Coastguard Worker const std::string& arg = args[0];
871*acea8879SAndroid Build Coastguard Worker auto updater_runtime = state->updater->GetRuntime();
872*acea8879SAndroid Build Coastguard Worker return StringValue(updater_runtime->AddSlotSuffix(arg));
873*acea8879SAndroid Build Coastguard Worker }
874*acea8879SAndroid Build Coastguard Worker
RegisterInstallFunctions()875*acea8879SAndroid Build Coastguard Worker void RegisterInstallFunctions() {
876*acea8879SAndroid Build Coastguard Worker RegisterFunction("mount", MountFn);
877*acea8879SAndroid Build Coastguard Worker RegisterFunction("is_mounted", IsMountedFn);
878*acea8879SAndroid Build Coastguard Worker RegisterFunction("unmount", UnmountFn);
879*acea8879SAndroid Build Coastguard Worker RegisterFunction("format", FormatFn);
880*acea8879SAndroid Build Coastguard Worker RegisterFunction("show_progress", ShowProgressFn);
881*acea8879SAndroid Build Coastguard Worker RegisterFunction("set_progress", SetProgressFn);
882*acea8879SAndroid Build Coastguard Worker RegisterFunction("package_extract_file", PackageExtractFileFn);
883*acea8879SAndroid Build Coastguard Worker
884*acea8879SAndroid Build Coastguard Worker RegisterFunction("getprop", GetPropFn);
885*acea8879SAndroid Build Coastguard Worker RegisterFunction("file_getprop", FileGetPropFn);
886*acea8879SAndroid Build Coastguard Worker
887*acea8879SAndroid Build Coastguard Worker RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
888*acea8879SAndroid Build Coastguard Worker RegisterFunction("patch_partition", PatchPartitionFn);
889*acea8879SAndroid Build Coastguard Worker RegisterFunction("patch_partition_check", PatchPartitionCheckFn);
890*acea8879SAndroid Build Coastguard Worker
891*acea8879SAndroid Build Coastguard Worker RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
892*acea8879SAndroid Build Coastguard Worker
893*acea8879SAndroid Build Coastguard Worker RegisterFunction("read_file", ReadFileFn);
894*acea8879SAndroid Build Coastguard Worker RegisterFunction("write_value", WriteValueFn);
895*acea8879SAndroid Build Coastguard Worker
896*acea8879SAndroid Build Coastguard Worker RegisterFunction("wipe_cache", WipeCacheFn);
897*acea8879SAndroid Build Coastguard Worker
898*acea8879SAndroid Build Coastguard Worker RegisterFunction("ui_print", UIPrintFn);
899*acea8879SAndroid Build Coastguard Worker
900*acea8879SAndroid Build Coastguard Worker RegisterFunction("run_program", RunProgramFn);
901*acea8879SAndroid Build Coastguard Worker
902*acea8879SAndroid Build Coastguard Worker RegisterFunction("reboot_now", RebootNowFn);
903*acea8879SAndroid Build Coastguard Worker RegisterFunction("get_stage", GetStageFn);
904*acea8879SAndroid Build Coastguard Worker RegisterFunction("set_stage", SetStageFn);
905*acea8879SAndroid Build Coastguard Worker
906*acea8879SAndroid Build Coastguard Worker RegisterFunction("enable_reboot", EnableRebootFn);
907*acea8879SAndroid Build Coastguard Worker RegisterFunction("tune2fs", Tune2FsFn);
908*acea8879SAndroid Build Coastguard Worker
909*acea8879SAndroid Build Coastguard Worker RegisterFunction("add_slot_suffix", AddSlotSuffixFn);
910*acea8879SAndroid Build Coastguard Worker }
911