blob: d86fc496cfca529ef9b6d28f043844f316873cd6 [file] [log] [blame]
Doug Zongker9931f7f2009-06-10 14:11:53 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tao Bao0c7839a2016-10-10 15:48:37 -070017#include "updater/install.h"
18
Doug Zongkerfbf3c102009-06-24 09:36:20 -070019#include <ctype.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070020#include <errno.h>
Tao Bao361342c2016-02-08 11:15:50 -080021#include <fcntl.h>
22#include <ftw.h>
23#include <inttypes.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070024#include <stdarg.h>
Doug Zongkerfbf3c102009-06-24 09:36:20 -070025#include <stdio.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070026#include <stdlib.h>
27#include <string.h>
Tao Bao361342c2016-02-08 11:15:50 -080028#include <sys/capability.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070029#include <sys/mount.h>
30#include <sys/stat.h>
31#include <sys/types.h>
Doug Zongkera3f89ea2009-09-10 14:10:48 -070032#include <sys/wait.h>
Nick Kralevich5dbdef02013-09-07 14:41:06 -070033#include <sys/xattr.h>
Tao Bao361342c2016-02-08 11:15:50 -080034#include <time.h>
35#include <unistd.h>
Tianjie Xu8cf5c8f2016-09-08 20:10:11 -070036#include <utime.h>
Doug Zongker9931f7f2009-06-10 14:11:53 -070037
Yabin Cui64be2132016-02-03 18:16:02 -080038#include <memory>
Tao Bao361342c2016-02-08 11:15:50 -080039#include <string>
Yabin Cui64be2132016-02-03 18:16:02 -080040#include <vector>
41
Tao Baod0f30882016-11-03 23:52:01 -070042#include <android-base/file.h>
Tao Bao039f2da2016-11-22 16:29:50 -080043#include <android-base/logging.h>
Tianjie Xu5fe280a2016-10-17 18:15:20 -070044#include <android-base/parsedouble.h>
Tao Baod0f30882016-11-03 23:52:01 -070045#include <android-base/parseint.h>
Elliott Hughescb220402016-09-23 15:30:55 -070046#include <android-base/properties.h>
Elliott Hughes4b166f02015-12-04 15:30:20 -080047#include <android-base/stringprintf.h>
Tao Baod0f30882016-11-03 23:52:01 -070048#include <android-base/strings.h>
Tianjie Xu22f11202018-08-27 10:50:31 -070049#include <android-base/unique_fd.h>
Tao Bao0d3f84f2016-12-28 15:09:20 -080050#include <applypatch/applypatch.h>
Dan Pasanend10b00b2015-01-13 21:25:26 -060051#include <blkid/blkid.h>
Tao Bao0d3f84f2016-12-28 15:09:20 -080052#include <bootloader_message/bootloader_message.h>
Tao Baode40ba52016-10-05 23:17:01 -070053#include <ext4_utils/wipe.h>
Tao Bao361342c2016-02-08 11:15:50 -080054#include <openssl/sha.h>
Elliott Hughes4bbd5bf2016-04-01 18:24:39 -070055#include <selinux/label.h>
56#include <selinux/selinux.h>
Tao Bao09e468f2017-09-29 14:39:33 -070057#include <tune2fs.h>
Tianjie Xu8cf5c8f2016-09-08 20:10:11 -070058#include <ziparchive/zip_archive.h>
Tao Bao1107d962015-09-09 17:16:55 -070059
Doug Zongker9931f7f2009-06-10 14:11:53 -070060#include "edify/expr.h"
Tao Bao17054c02018-05-03 22:41:23 -070061#include "otautil/dirutil.h"
Tao Bao1fc5bf32017-10-06 07:43:41 -070062#include "otautil/error_code.h"
Tao Bao9a319f02018-01-04 13:19:11 -080063#include "otautil/mounts.h"
Tao Bao09e468f2017-09-29 14:39:33 -070064#include "otautil/print_sha1.h"
Tao Bao2c526392018-05-03 23:01:13 -070065#include "otautil/sysutil.h"
Michael Bestas847c0652019-09-19 21:42:12 +030066#include "otautil/ziputil.h"
67#include "tune2fs.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070068#include "updater/updater.h"
Doug Zongker8edb00c2009-06-11 17:21:44 -070069
Tao Bao1107d962015-09-09 17:16:55 -070070// Send over the buffer to recovery though the command pipe.
71static void uiPrint(State* state, const std::string& buffer) {
Tao Bao039f2da2016-11-22 16:29:50 -080072 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
Tao Baob6918c72015-05-19 17:02:16 -070073
Tao Bao039f2da2016-11-22 16:29:50 -080074 // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
75 // So skip sending empty strings to UI.
76 std::vector<std::string> lines = android::base::Split(buffer, "\n");
77 for (auto& line : lines) {
78 if (!line.empty()) {
79 fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
Tao Bao1107d962015-09-09 17:16:55 -070080 }
Tao Bao039f2da2016-11-22 16:29:50 -080081 }
Tao Bao1107d962015-09-09 17:16:55 -070082
Tao Bao039f2da2016-11-22 16:29:50 -080083 // On the updater side, we need to dump the contents to stderr (which has
84 // been redirected to the log file). Because the recovery will only print
85 // the contents to screen when processing pipe command ui_print.
86 LOG(INFO) << buffer;
Michael Runged4a63422014-10-22 19:48:41 -070087}
88
Elliott Hughes83ce7552016-06-30 09:28:42 -070089void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) {
Tao Bao039f2da2016-11-22 16:29:50 -080090 std::string error_msg;
Tao Bao1107d962015-09-09 17:16:55 -070091
Tao Bao039f2da2016-11-22 16:29:50 -080092 va_list ap;
93 va_start(ap, format);
94 android::base::StringAppendV(&error_msg, format, ap);
95 va_end(ap);
Tao Bao1107d962015-09-09 17:16:55 -070096
Tao Bao039f2da2016-11-22 16:29:50 -080097 uiPrint(state, error_msg);
Michael Runged4a63422014-10-22 19:48:41 -070098}
99
Michael Bestas847c0652019-09-19 21:42:12 +0300100static bool is_dir(const std::string& dirpath) {
101 struct stat st;
102 return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
103}
104
105// Create all parent directories of name, if necessary.
106static bool make_parents(const std::string& name) {
107 size_t prev_end = 0;
108 while (prev_end < name.size()) {
109 size_t next_end = name.find('/', prev_end + 1);
110 if (next_end == std::string::npos) {
111 break;
112 }
113 std::string dir_path = name.substr(0, next_end);
114 if (!is_dir(dir_path)) {
115 int result = mkdir(dir_path.c_str(), 0700);
116 if (result != 0) {
117 PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name;
118 return false;
119 }
120
121 LOG(INFO) << "created [" << dir_path << "]";
122 }
123 prev_end = next_end;
124 }
125 return true;
126}
127
Tianjie Xu5419ad32018-02-02 16:49:15 -0800128// This is the updater side handler for ui_print() in edify script. Contents will be sent over to
129// the recovery side for on-screen display.
130Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
131 std::vector<std::string> args;
132 if (!ReadArgs(state, argv, &args)) {
133 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
134 }
135
136 std::string buffer = android::base::Join(args, "");
137 uiPrint(state, buffer);
138 return StringValue(buffer);
139}
140
Michael Bestas847c0652019-09-19 21:42:12 +0300141// package_extract_dir(package_dir, dest_dir)
142// Extracts all files from the package underneath package_dir and writes them to the
143// corresponding tree beneath dest_dir. Any existing files are overwritten.
144// Example: package_extract_dir("system", "/system")
145//
146// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
147Value* PackageExtractDirFn(const char* name, State* state,
148 const std::vector<std::unique_ptr<Expr>>& argv) {
149 if (argv.size() != 2) {
150 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
151 argv.size());
152 }
153
154 std::vector<std::string> args;
155 if (!ReadArgs(state, argv, &args)) {
156 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
157 }
158 const std::string& zip_path = args[0];
159 const std::string& dest_path = args[1];
160
161 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
162
163 // To create a consistent system image, never use the clock for timestamps.
164 constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
165
166 bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
167
168 return StringValue(success ? "t" : "");
169}
170
Tianjie Xu5419ad32018-02-02 16:49:15 -0800171// package_extract_file(package_file[, dest_file])
172// Extracts a single package_file from the update package and writes it to dest_file,
173// overwriting existing files if necessary. Without the dest_file argument, returns the
174// contents of the package file as a binary blob.
175Value* PackageExtractFileFn(const char* name, State* state,
176 const std::vector<std::unique_ptr<Expr>>& argv) {
177 if (argv.size() < 1 || argv.size() > 2) {
178 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
179 argv.size());
180 }
181
182 if (argv.size() == 2) {
183 // The two-argument version extracts to a file.
184
185 std::vector<std::string> args;
186 if (!ReadArgs(state, argv, &args)) {
187 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
188 argv.size());
189 }
190 const std::string& zip_path = args[0];
191 const std::string& dest_path = args[1];
192
193 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
194 ZipString zip_string_path(zip_path.c_str());
195 ZipEntry entry;
196 if (FindEntry(za, zip_string_path, &entry) != 0) {
197 LOG(ERROR) << name << ": no " << zip_path << " in package";
198 return StringValue("");
199 }
200
Tianjie Xu22f11202018-08-27 10:50:31 -0700201 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
202 open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
Tianjie Xu5419ad32018-02-02 16:49:15 -0800203 if (fd == -1) {
204 PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
205 return StringValue("");
206 }
207
208 bool success = true;
209 int32_t ret = ExtractEntryToFile(za, &entry, fd);
210 if (ret != 0) {
211 LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
212 << entry.uncompressed_length << " bytes) to \"" << dest_path
213 << "\": " << ErrorCodeString(ret);
214 success = false;
215 }
Tianjie Xu22f11202018-08-27 10:50:31 -0700216 if (fsync(fd) == -1) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800217 PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
218 success = false;
219 }
Tianjie Xu22f11202018-08-27 10:50:31 -0700220
221 if (close(fd.release()) != 0) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800222 PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
223 success = false;
224 }
225
226 return StringValue(success ? "t" : "");
227 } else {
228 // The one-argument version returns the contents of the file as the result.
229
230 std::vector<std::string> args;
231 if (!ReadArgs(state, argv, &args)) {
232 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
233 argv.size());
234 }
235 const std::string& zip_path = args[0];
236
237 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
238 ZipString zip_string_path(zip_path.c_str());
239 ZipEntry entry;
240 if (FindEntry(za, zip_string_path, &entry) != 0) {
241 return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
242 zip_path.c_str());
243 }
244
245 std::string buffer;
246 buffer.resize(entry.uncompressed_length);
247
248 int32_t ret =
249 ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
250 if (ret != 0) {
251 return ErrorAbort(state, kPackageExtractFileFailure,
252 "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
253 zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
254 }
255
Tao Bao511d7592018-06-19 15:56:49 -0700256 return new Value(Value::Type::BLOB, buffer);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800257 }
258}
259
Tao Bao5609bc82018-06-20 00:30:48 -0700260// patch_partition_check(target_partition, source_partition)
261// Checks if the target and source partitions have the desired checksums to be patched. It returns
262// directly, if the target partition already has the expected checksum. Otherwise it in turn
263// checks the integrity of the source partition and the backup file on /cache.
Tianjie Xu5419ad32018-02-02 16:49:15 -0800264//
Tao Bao5609bc82018-06-20 00:30:48 -0700265// For example, patch_partition_check(
266// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
267// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4")
268Value* PatchPartitionCheckFn(const char* name, State* state,
269 const std::vector<std::unique_ptr<Expr>>& argv) {
270 if (argv.size() != 2) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800271 return ErrorAbort(state, kArgsParsingFailure,
Tao Bao5609bc82018-06-20 00:30:48 -0700272 "%s(): Invalid number of args (expected 2, got %zu)", name, argv.size());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800273 }
274
275 std::vector<std::string> args;
Tao Bao5609bc82018-06-20 00:30:48 -0700276 if (!ReadArgs(state, argv, &args, 0, 2)) {
277 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800278 }
279
Tao Bao5609bc82018-06-20 00:30:48 -0700280 std::string err;
281 auto target = Partition::Parse(args[0], &err);
282 if (!target) {
283 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
284 args[0].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800285 }
286
Tao Bao5609bc82018-06-20 00:30:48 -0700287 auto source = Partition::Parse(args[1], &err);
288 if (!source) {
289 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
290 args[1].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800291 }
292
Tao Bao5609bc82018-06-20 00:30:48 -0700293 bool result = PatchPartitionCheck(target, source);
294 return StringValue(result ? "t" : "");
Tianjie Xu5419ad32018-02-02 16:49:15 -0800295}
296
Tao Bao5609bc82018-06-20 00:30:48 -0700297// patch_partition(target, source, patch)
298// Applies the given patch to the source partition, and writes the result to the target partition.
299//
300// For example, patch_partition(
301// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
302// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4",
303// package_extract_file("boot.img.p"))
304Value* PatchPartitionFn(const char* name, State* state,
305 const std::vector<std::unique_ptr<Expr>>& argv) {
306 if (argv.size() != 3) {
307 return ErrorAbort(state, kArgsParsingFailure,
308 "%s(): Invalid number of args (expected 3, got %zu)", name, argv.size());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800309 }
310
311 std::vector<std::string> args;
Tao Bao5609bc82018-06-20 00:30:48 -0700312 if (!ReadArgs(state, argv, &args, 0, 2)) {
313 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800314 }
Tianjie Xu5419ad32018-02-02 16:49:15 -0800315
Tao Bao5609bc82018-06-20 00:30:48 -0700316 std::string err;
317 auto target = Partition::Parse(args[0], &err);
318 if (!target) {
319 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
320 args[0].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800321 }
Tianjie Xu5419ad32018-02-02 16:49:15 -0800322
Tao Bao5609bc82018-06-20 00:30:48 -0700323 auto source = Partition::Parse(args[1], &err);
324 if (!source) {
325 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
326 args[1].c_str(), err.c_str());
327 }
328
329 std::vector<std::unique_ptr<Value>> values;
330 if (!ReadValueArgs(state, argv, &values, 2, 1) || values[0]->type != Value::Type::BLOB) {
331 return ErrorAbort(state, kArgsParsingFailure, "%s(): Invalid patch arg", name);
332 }
333
334 bool result = PatchPartition(target, source, *values[0], nullptr);
335 return StringValue(result ? "t" : "");
Tianjie Xu5419ad32018-02-02 16:49:15 -0800336}
337
Doug Zongker3d177d02010-07-01 09:18:44 -0700338// mount(fs_type, partition_type, location, mount_point)
Tao Bao0831d0b2016-11-03 23:25:04 -0700339// mount(fs_type, partition_type, location, mount_point, mount_options)
Tianjie Xuc4447322017-03-06 14:44:59 -0800340
Doug Zongker3d177d02010-07-01 09:18:44 -0700341// fs_type="ext4" partition_type="EMMC" location=device
Tianjie Xuc4447322017-03-06 14:44:59 -0800342Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
343 if (argv.size() != 4 && argv.size() != 5) {
344 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name,
345 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800346 }
347
348 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800349 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800350 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
351 }
Dan Pasanend10b00b2015-01-13 21:25:26 -0600352 std::string fs_type = args[0];
Tao Bao039f2da2016-11-22 16:29:50 -0800353 const std::string& partition_type = args[1];
354 const std::string& location = args[2];
355 const std::string& mount_point = args[3];
356 std::string mount_options;
357
Tianjie Xuc4447322017-03-06 14:44:59 -0800358 if (argv.size() == 5) {
Tao Bao039f2da2016-11-22 16:29:50 -0800359 mount_options = args[4];
360 }
361
362 if (fs_type.empty()) {
363 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
364 }
365 if (partition_type.empty()) {
366 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
367 name);
368 }
369 if (location.empty()) {
370 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
371 }
372 if (mount_point.empty()) {
373 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
374 name);
375 }
376
377 {
378 char* secontext = nullptr;
379
380 if (sehandle) {
381 selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755);
382 setfscreatecon(secontext);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700383 }
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700384
Tao Bao039f2da2016-11-22 16:29:50 -0800385 mkdir(mount_point.c_str(), 0755);
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700386
Tao Bao039f2da2016-11-22 16:29:50 -0800387 if (secontext) {
388 freecon(secontext);
389 setfscreatecon(nullptr);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700390 }
Tao Bao039f2da2016-11-22 16:29:50 -0800391 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700392
Dan Pasanend10b00b2015-01-13 21:25:26 -0600393 char* detected_fs_type = blkid_get_tag_value(NULL, "TYPE", location.c_str());
394 if (detected_fs_type) {
395 uiPrintf(state, "detected filesystem %s for %s\n", detected_fs_type, location.c_str());
396 fs_type = detected_fs_type;
397 free(detected_fs_type);
398 } else {
399 uiPrintf(state, "could not detect filesystem for %s, assuming %s\n", location.c_str(),
400 fs_type.c_str());
401 }
402
Tao Bao039f2da2016-11-22 16:29:50 -0800403 if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(),
404 MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700405 uiPrintf(state, "%s: Failed to mount %s at %s: %s", name, location.c_str(), mount_point.c_str(),
406 strerror(errno));
Tao Bao039f2da2016-11-22 16:29:50 -0800407 return StringValue("");
408 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700409
Tao Bao039f2da2016-11-22 16:29:50 -0800410 return StringValue(mount_point);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700411}
412
Doug Zongker8edb00c2009-06-11 17:21:44 -0700413// is_mounted(mount_point)
Tianjie Xuc4447322017-03-06 14:44:59 -0800414Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
415 if (argv.size() != 1) {
416 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800417 }
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700418
Tao Bao039f2da2016-11-22 16:29:50 -0800419 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800420 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800421 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
422 }
423 const std::string& mount_point = args[0];
424 if (mount_point.empty()) {
425 return ErrorAbort(state, kArgsParsingFailure,
426 "mount_point argument to unmount() can't be empty");
427 }
Doug Zongker8edb00c2009-06-11 17:21:44 -0700428
Tao Bao039f2da2016-11-22 16:29:50 -0800429 scan_mounted_volumes();
430 MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
431 if (vol == nullptr) {
432 return StringValue("");
433 }
Doug Zongker8edb00c2009-06-11 17:21:44 -0700434
Tao Bao039f2da2016-11-22 16:29:50 -0800435 return StringValue(mount_point);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700436}
437
Tianjie Xuc4447322017-03-06 14:44:59 -0800438Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
439 if (argv.size() != 1) {
440 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800441 }
442 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800443 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800444 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
445 }
446 const std::string& mount_point = args[0];
447 if (mount_point.empty()) {
448 return ErrorAbort(state, kArgsParsingFailure,
449 "mount_point argument to unmount() can't be empty");
450 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700451
Tao Bao039f2da2016-11-22 16:29:50 -0800452 scan_mounted_volumes();
453 MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
454 if (vol == nullptr) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700455 uiPrintf(state, "Failed to unmount %s: No such volume", mount_point.c_str());
Tao Bao039f2da2016-11-22 16:29:50 -0800456 return nullptr;
457 } else {
458 int ret = unmount_mounted_volume(vol);
459 if (ret != 0) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700460 uiPrintf(state, "Failed to unmount %s: %s", mount_point.c_str(), strerror(errno));
Doug Zongker9931f7f2009-06-10 14:11:53 -0700461 }
Tao Bao039f2da2016-11-22 16:29:50 -0800462 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700463
Tao Bao039f2da2016-11-22 16:29:50 -0800464 return StringValue(mount_point);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700465}
Doug Zongker8edb00c2009-06-11 17:21:44 -0700466
Tao Bao3d69f0d2018-12-20 09:44:06 -0800467static int exec_cmd(const std::vector<std::string>& args) {
468 CHECK(!args.empty());
469 auto argv = StringVectorToNullTerminatedArray(args);
470
Tao Bao039f2da2016-11-22 16:29:50 -0800471 pid_t child;
472 if ((child = vfork()) == 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800473 execv(argv[0], argv.data());
Tao Bao3da88012017-02-03 13:09:23 -0800474 _exit(EXIT_FAILURE);
Tao Bao039f2da2016-11-22 16:29:50 -0800475 }
476
477 int status;
478 waitpid(child, &status, 0);
479 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800480 LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status);
Tao Bao039f2da2016-11-22 16:29:50 -0800481 }
482 return WEXITSTATUS(status);
JP Abgrall37aedb32014-06-16 19:07:39 -0700483}
484
Stephen Smalley779701d2012-02-09 14:13:23 -0500485// format(fs_type, partition_type, location, fs_size, mount_point)
Doug Zongker9931f7f2009-06-10 14:11:53 -0700486//
Tao Bao039f2da2016-11-22 16:29:50 -0800487// fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
488// fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
JP Abgrall37aedb32014-06-16 19:07:39 -0700489// if fs_size == 0, then make fs uses the entire partition.
Ken Sumrall8f132ed2011-01-14 18:55:05 -0800490// if fs_size > 0, that is the size to use
JP Abgrall37aedb32014-06-16 19:07:39 -0700491// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
Tianjie Xuc4447322017-03-06 14:44:59 -0800492Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
493 if (argv.size() != 5) {
494 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name,
495 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800496 }
Stephen Smalley779701d2012-02-09 14:13:23 -0500497
Tao Bao039f2da2016-11-22 16:29:50 -0800498 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800499 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800500 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
501 }
502 const std::string& fs_type = args[0];
503 const std::string& partition_type = args[1];
504 const std::string& location = args[2];
505 const std::string& fs_size = args[3];
506 const std::string& mount_point = args[4];
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700507
Tao Bao039f2da2016-11-22 16:29:50 -0800508 if (fs_type.empty()) {
509 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
510 }
511 if (partition_type.empty()) {
512 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
513 name);
514 }
515 if (location.empty()) {
516 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
517 }
518 if (mount_point.empty()) {
519 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
520 name);
521 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700522
Tao Bao039f2da2016-11-22 16:29:50 -0800523 int64_t size;
524 if (!android::base::ParseInt(fs_size, &size)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800525 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800526 fs_size.c_str());
527 }
528
529 if (fs_type == "ext4") {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800530 std::vector<std::string> mke2fs_args = {
531 "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", location
532 };
Jin Qianded2dac2017-04-21 14:36:12 -0700533 if (size != 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800534 mke2fs_args.push_back(std::to_string(size / 4096LL));
Jin Qianded2dac2017-04-21 14:36:12 -0700535 }
536
Tao Bao3d69f0d2018-12-20 09:44:06 -0800537 if (auto status = exec_cmd(mke2fs_args); status != 0) {
Jin Qian502fd1c2017-11-02 11:58:12 -0700538 LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location;
539 return StringValue("");
Jin Qianded2dac2017-04-21 14:36:12 -0700540 }
541
Tao Bao3d69f0d2018-12-20 09:44:06 -0800542 if (auto status = exec_cmd({ "/system/bin/e2fsdroid", "-e", "-a", mount_point, location });
543 status != 0) {
Jin Qianded2dac2017-04-21 14:36:12 -0700544 LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location;
Tao Bao039f2da2016-11-22 16:29:50 -0800545 return StringValue("");
Doug Zongker9931f7f2009-06-10 14:11:53 -0700546 }
Tao Bao039f2da2016-11-22 16:29:50 -0800547 return StringValue(location);
Tao Bao3d69f0d2018-12-20 09:44:06 -0800548 }
549
550 if (fs_type == "f2fs") {
Tao Bao039f2da2016-11-22 16:29:50 -0800551 if (size < 0) {
552 LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
553 return StringValue("");
Doug Zongker9931f7f2009-06-10 14:11:53 -0700554 }
Tao Bao3d69f0d2018-12-20 09:44:06 -0800555 std::vector<std::string> f2fs_args = {
Tao Baoc674dfb2018-12-20 14:25:15 -0800556 "/system/bin/make_f2fs", "-g", "android", "-w", "512", location
Tao Bao3d69f0d2018-12-20 09:44:06 -0800557 };
558 if (size >= 512) {
559 f2fs_args.push_back(std::to_string(size / 512));
560 }
561 if (auto status = exec_cmd(f2fs_args); status != 0) {
Tao Baoc674dfb2018-12-20 14:25:15 -0800562 LOG(ERROR) << name << ": make_f2fs failed (" << status << ") on " << location;
Tao Bao039f2da2016-11-22 16:29:50 -0800563 return StringValue("");
564 }
Jaegeuk Kimc1c73112017-11-28 19:48:05 -0800565
Tao Baoc674dfb2018-12-20 14:25:15 -0800566 if (auto status = exec_cmd({ "/system/bin/sload_f2fs", "-t", mount_point, location });
567 status != 0) {
568 LOG(ERROR) << name << ": sload_f2fs failed (" << status << ") on " << location;
Jaegeuk Kimc1c73112017-11-28 19:48:05 -0800569 return StringValue("");
570 }
571
Tao Bao039f2da2016-11-22 16:29:50 -0800572 return StringValue(location);
Tao Bao039f2da2016-11-22 16:29:50 -0800573 }
574
Tao Bao3d69f0d2018-12-20 09:44:06 -0800575 LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
576 << partition_type << "\"";
Tao Bao039f2da2016-11-22 16:29:50 -0800577 return nullptr;
Doug Zongker9931f7f2009-06-10 14:11:53 -0700578}
579
Michael Bestas847c0652019-09-19 21:42:12 +0300580// rename(src_name, dst_name)
581// Renames src_name to dst_name. It automatically creates the necessary directories for dst_name.
582// Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk")
583Value* RenameFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
584 if (argv.size() != 2) {
585 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
586 argv.size());
587 }
588
589 std::vector<std::string> args;
590 if (!ReadArgs(state, argv, &args)) {
591 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
592 }
593 const std::string& src_name = args[0];
594 const std::string& dst_name = args[1];
595
596 if (src_name.empty()) {
597 return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
598 }
599 if (dst_name.empty()) {
600 return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
601 }
602 if (!make_parents(dst_name)) {
603 return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s",
604 dst_name.c_str(), strerror(errno));
605 } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) {
606 // File was already moved
607 return StringValue(dst_name);
608 } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) {
609 return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
610 src_name.c_str(), dst_name.c_str(), strerror(errno));
611 }
612
613 return StringValue(dst_name);
614}
615
616// delete([filename, ...])
617// Deletes all the filenames listed. Returns the number of files successfully deleted.
618//
619// delete_recursive([dirname, ...])
620// Recursively deletes dirnames and all their contents. Returns the number of directories
621// successfully deleted.
622Value* DeleteFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
623 std::vector<std::string> paths;
624 if (!ReadArgs(state, argv, &paths)) {
625 return nullptr;
626 }
627
628 bool recursive = (strcmp(name, "delete_recursive") == 0);
629
630 int success = 0;
631 for (const auto& path : paths) {
632 if ((recursive ? dirUnlinkHierarchy(path.c_str()) : unlink(path.c_str())) == 0) {
633 ++success;
634 }
635 }
636
637 return StringValue(std::to_string(success));
638}
639
Tianjie Xuc4447322017-03-06 14:44:59 -0800640Value* ShowProgressFn(const char* name, State* state,
641 const std::vector<std::unique_ptr<Expr>>& argv) {
642 if (argv.size() != 2) {
643 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
644 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800645 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700646
Tao Bao039f2da2016-11-22 16:29:50 -0800647 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800648 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800649 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
650 }
651 const std::string& frac_str = args[0];
652 const std::string& sec_str = args[1];
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700653
Tao Bao039f2da2016-11-22 16:29:50 -0800654 double frac;
655 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800656 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800657 frac_str.c_str());
658 }
659 int sec;
660 if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800661 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800662 sec_str.c_str());
663 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700664
Tao Bao039f2da2016-11-22 16:29:50 -0800665 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
666 fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700667
Tao Bao039f2da2016-11-22 16:29:50 -0800668 return StringValue(frac_str);
Doug Zongkerfbf3c102009-06-24 09:36:20 -0700669}
670
Tianjie Xu5419ad32018-02-02 16:49:15 -0800671Value* SetProgressFn(const char* name, State* state,
672 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800673 if (argv.size() != 1) {
674 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800675 }
Doug Zongkerfbf3c102009-06-24 09:36:20 -0700676
Tao Bao039f2da2016-11-22 16:29:50 -0800677 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800678 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800679 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
680 }
681 const std::string& frac_str = args[0];
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700682
Tao Bao039f2da2016-11-22 16:29:50 -0800683 double frac;
684 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800685 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800686 frac_str.c_str());
687 }
Doug Zongkerfbf3c102009-06-24 09:36:20 -0700688
Tao Bao039f2da2016-11-22 16:29:50 -0800689 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
690 fprintf(ui->cmd_pipe, "set_progress %f\n", frac);
Doug Zongkerfbf3c102009-06-24 09:36:20 -0700691
Tao Bao039f2da2016-11-22 16:29:50 -0800692 return StringValue(frac_str);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700693}
694
Michael Bestas847c0652019-09-19 21:42:12 +0300695// symlink(target, [src1, src2, ...])
696// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc
697// before creating symlinks.
698Value* SymlinkFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
699 if (argv.size() == 0) {
700 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %zu", name,
701 argv.size());
702 }
703
704 std::vector<std::string> args;
705 if (!ReadArgs(state, argv, &args)) {
706 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
707 }
708
709 const auto& target = args[0];
710 if (target.empty()) {
711 return ErrorAbort(state, kArgsParsingFailure, "%s() target argument can't be empty", name);
712 }
713
714 size_t bad = 0;
715 for (size_t i = 1; i < args.size(); ++i) {
716 const auto& src = args[i];
717 if (unlink(src.c_str()) == -1 && errno != ENOENT) {
718 PLOG(ERROR) << name << ": failed to remove " << src;
719 ++bad;
720 } else if (!make_parents(src)) {
721 LOG(ERROR) << name << ": failed to symlink " << src << " to " << target
722 << ": making parents failed";
723 ++bad;
724 } else if (symlink(target.c_str(), src.c_str()) == -1) {
725 PLOG(ERROR) << name << ": failed to symlink " << src << " to " << target;
726 ++bad;
727 }
728 }
729 if (bad != 0) {
730 return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad);
731 }
732 return StringValue("t");
733}
734
735struct perm_parsed_args {
736 bool has_uid;
737 uid_t uid;
738 bool has_gid;
739 gid_t gid;
740 bool has_mode;
741 mode_t mode;
742 bool has_fmode;
743 mode_t fmode;
744 bool has_dmode;
745 mode_t dmode;
746 bool has_selabel;
747 const char* selabel;
748 bool has_capabilities;
749 uint64_t capabilities;
750};
751
752static struct perm_parsed_args ParsePermArgs(State* state, const std::vector<std::string>& args) {
753 struct perm_parsed_args parsed;
754 int bad = 0;
755 static int max_warnings = 20;
756
757 memset(&parsed, 0, sizeof(parsed));
758
759 for (size_t i = 1; i < args.size(); i += 2) {
760 if (args[i] == "uid") {
761 int64_t uid;
762 if (sscanf(args[i + 1].c_str(), "%" SCNd64, &uid) == 1) {
763 parsed.uid = uid;
764 parsed.has_uid = true;
765 } else {
766 uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str());
767 bad++;
768 }
769 continue;
770 }
771 if (args[i] == "gid") {
772 int64_t gid;
773 if (sscanf(args[i + 1].c_str(), "%" SCNd64, &gid) == 1) {
774 parsed.gid = gid;
775 parsed.has_gid = true;
776 } else {
777 uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str());
778 bad++;
779 }
780 continue;
781 }
782 if (args[i] == "mode") {
783 int32_t mode;
784 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
785 parsed.mode = mode;
786 parsed.has_mode = true;
787 } else {
788 uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str());
789 bad++;
790 }
791 continue;
792 }
793 if (args[i] == "dmode") {
794 int32_t mode;
795 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
796 parsed.dmode = mode;
797 parsed.has_dmode = true;
798 } else {
799 uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str());
800 bad++;
801 }
802 continue;
803 }
804 if (args[i] == "fmode") {
805 int32_t mode;
806 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
807 parsed.fmode = mode;
808 parsed.has_fmode = true;
809 } else {
810 uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str());
811 bad++;
812 }
813 continue;
814 }
815 if (args[i] == "capabilities") {
816 int64_t capabilities;
817 if (sscanf(args[i + 1].c_str(), "%" SCNi64, &capabilities) == 1) {
818 parsed.capabilities = capabilities;
819 parsed.has_capabilities = true;
820 } else {
821 uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str());
822 bad++;
823 }
824 continue;
825 }
826 if (args[i] == "selabel") {
827 if (!args[i + 1].empty()) {
828 parsed.selabel = args[i + 1].c_str();
829 parsed.has_selabel = true;
830 } else {
831 uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str());
832 bad++;
833 }
834 continue;
835 }
836 if (max_warnings != 0) {
837 printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str());
838 max_warnings--;
839 if (max_warnings == 0) {
840 LOG(INFO) << "ParsedPermArgs: suppressing further warnings";
841 }
842 }
843 }
844 return parsed;
845}
846
847static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr,
848 struct perm_parsed_args parsed) {
849 int bad = 0;
850
851 if (parsed.has_selabel) {
852 if (lsetfilecon(filename, parsed.selabel) != 0) {
853 uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", filename,
854 parsed.selabel, strerror(errno));
855 bad++;
856 }
857 }
858
859 /* ignore symlinks */
860 if (S_ISLNK(statptr->st_mode)) {
861 return bad;
862 }
863
864 if (parsed.has_uid) {
865 if (chown(filename, parsed.uid, -1) < 0) {
866 uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", filename, parsed.uid,
867 strerror(errno));
868 bad++;
869 }
870 }
871
872 if (parsed.has_gid) {
873 if (chown(filename, -1, parsed.gid) < 0) {
874 uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", filename, parsed.gid,
875 strerror(errno));
876 bad++;
877 }
878 }
879
880 if (parsed.has_mode) {
881 if (chmod(filename, parsed.mode) < 0) {
882 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.mode,
883 strerror(errno));
884 bad++;
885 }
886 }
887
888 if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) {
889 if (chmod(filename, parsed.dmode) < 0) {
890 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.dmode,
891 strerror(errno));
892 bad++;
893 }
894 }
895
896 if (parsed.has_fmode && S_ISREG(statptr->st_mode)) {
897 if (chmod(filename, parsed.fmode) < 0) {
898 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.fmode,
899 strerror(errno));
900 bad++;
901 }
902 }
903
904 if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) {
905 if (parsed.capabilities == 0) {
906 if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) {
907 // Report failure unless it's ENODATA (attribute not set)
908 uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", filename,
909 parsed.capabilities, strerror(errno));
910 bad++;
911 }
912 } else {
913 struct vfs_cap_data cap_data;
914 memset(&cap_data, 0, sizeof(cap_data));
XiNGRZ9de4bbb2019-12-03 14:31:56 +0800915 cap_data.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE;
Michael Bestas847c0652019-09-19 21:42:12 +0300916 cap_data.data[0].permitted = (uint32_t)(parsed.capabilities & 0xffffffff);
917 cap_data.data[0].inheritable = 0;
918 cap_data.data[1].permitted = (uint32_t)(parsed.capabilities >> 32);
919 cap_data.data[1].inheritable = 0;
920 if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
921 uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", filename,
922 parsed.capabilities, strerror(errno));
923 bad++;
924 }
925 }
926 }
927
928 return bad;
929}
930
931// nftw doesn't allow us to pass along context, so we need to use
932// global variables. *sigh*
933static struct perm_parsed_args recursive_parsed_args;
934static State* recursive_state;
935
936static int do_SetMetadataRecursive(const char* filename, const struct stat* statptr,
937 int /*fileflags*/, struct FTW* /*pfwt*/) {
938 return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args);
939}
940
941static Value* SetMetadataFn(const char* name, State* state,
942 const std::vector<std::unique_ptr<Expr>>& argv) {
943 if ((argv.size() % 2) != 1) {
944 return ErrorAbort(state, kArgsParsingFailure,
945 "%s() expects an odd number of arguments, got %zu", name, argv.size());
946 }
947
948 std::vector<std::string> args;
949 if (!ReadArgs(state, argv, &args)) {
950 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
951 }
952
953 struct stat sb;
954 if (lstat(args[0].c_str(), &sb) == -1) {
955 return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", name,
956 args[0].c_str(), strerror(errno));
957 }
958
959 struct perm_parsed_args parsed = ParsePermArgs(state, args);
960 int bad = 0;
961 bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
962
963 if (recursive) {
964 recursive_parsed_args = parsed;
965 recursive_state = state;
966 bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS);
967 memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args));
968 recursive_state = NULL;
969 } else {
970 bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed);
971 }
972
973 if (bad > 0) {
974 return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
975 }
976
977 return StringValue("");
978}
979
Tianjie Xuc4447322017-03-06 14:44:59 -0800980Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
981 if (argv.size() != 1) {
982 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800983 }
984 std::string key;
985 if (!Evaluate(state, argv[0], &key)) {
986 return nullptr;
987 }
988 std::string value = android::base::GetProperty(key, "");
Doug Zongker8edb00c2009-06-11 17:21:44 -0700989
Tao Bao039f2da2016-11-22 16:29:50 -0800990 return StringValue(value);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700991}
992
Doug Zongker47cace92009-06-18 10:11:50 -0700993// file_getprop(file, key)
994//
995// interprets 'file' as a getprop-style file (key=value pairs, one
Tao Bao51d516e2016-11-03 14:49:01 -0700996// per line. # comment lines, blank lines, lines without '=' ignored),
Michael Rungeaa1a31e2014-04-25 18:47:18 -0700997// and returns the value for 'key' (or "" if it isn't defined).
Tianjie Xu5419ad32018-02-02 16:49:15 -0800998Value* FileGetPropFn(const char* name, State* state,
999 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -08001000 if (argv.size() != 2) {
1001 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1002 argv.size());
Tao Bao358c2ec2016-11-28 11:48:43 -08001003 }
1004
1005 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001006 if (!ReadArgs(state, argv, &args)) {
Tao Bao358c2ec2016-11-28 11:48:43 -08001007 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1008 }
1009 const std::string& filename = args[0];
1010 const std::string& key = args[1];
1011
Tianjie Xu22f11202018-08-27 10:50:31 -07001012 std::string buffer;
1013 if (!android::base::ReadFileToString(filename, &buffer)) {
1014 ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
Tao Bao358c2ec2016-11-28 11:48:43 -08001015 return nullptr;
1016 }
1017
Tao Bao358c2ec2016-11-28 11:48:43 -08001018 std::vector<std::string> lines = android::base::Split(buffer, "\n");
1019 for (size_t i = 0; i < lines.size(); i++) {
1020 std::string line = android::base::Trim(lines[i]);
1021
1022 // comment or blank line: skip to next line
1023 if (line.empty() || line[0] == '#') {
1024 continue;
1025 }
1026 size_t equal_pos = line.find('=');
1027 if (equal_pos == std::string::npos) {
1028 continue;
Tao Bao51d516e2016-11-03 14:49:01 -07001029 }
1030
Tao Bao358c2ec2016-11-28 11:48:43 -08001031 // trim whitespace between key and '='
1032 std::string str = android::base::Trim(line.substr(0, equal_pos));
Doug Zongker47cace92009-06-18 10:11:50 -07001033
Tao Bao358c2ec2016-11-28 11:48:43 -08001034 // not the key we're looking for
1035 if (key != str) continue;
Doug Zongker47cace92009-06-18 10:11:50 -07001036
Tao Bao358c2ec2016-11-28 11:48:43 -08001037 return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
1038 }
Doug Zongker47cace92009-06-18 10:11:50 -07001039
Tao Bao358c2ec2016-11-28 11:48:43 -08001040 return StringValue("");
Doug Zongker47cace92009-06-18 10:11:50 -07001041}
1042
Doug Zongker8edb00c2009-06-11 17:21:44 -07001043// apply_patch_space(bytes)
Tianjie Xu5419ad32018-02-02 16:49:15 -08001044Value* ApplyPatchSpaceFn(const char* name, State* state,
1045 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -08001046 if (argv.size() != 1) {
1047 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name,
1048 argv.size());
1049 }
Tao Bao039f2da2016-11-22 16:29:50 -08001050 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001051 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001052 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1053 }
1054 const std::string& bytes_str = args[0];
Doug Zongkerc4351c72010-02-22 14:46:32 -08001055
Tao Bao039f2da2016-11-22 16:29:50 -08001056 size_t bytes;
1057 if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -08001058 return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name,
1059 bytes_str.c_str());
Tao Bao039f2da2016-11-22 16:29:50 -08001060 }
Doug Zongkerc4351c72010-02-22 14:46:32 -08001061
Tianjie Xu99b73be2017-11-28 17:23:06 -08001062 // Skip the cache size check if the update is a retry.
Tao Bao5ee25662018-07-11 15:55:32 -07001063 if (state->is_retry || CheckAndFreeSpaceOnCache(bytes)) {
Tianjie Xu99b73be2017-11-28 17:23:06 -08001064 return StringValue("t");
1065 }
1066 return StringValue("");
Doug Zongkerc4351c72010-02-22 14:46:32 -08001067}
1068
Tianjie Xuc4447322017-03-06 14:44:59 -08001069Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1070 if (!argv.empty()) {
1071 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
1072 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001073 }
1074 fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n");
1075 return StringValue("t");
Doug Zongkerd0181b82011-10-19 10:51:12 -07001076}
1077
Tianjie Xuc4447322017-03-06 14:44:59 -08001078Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1079 if (argv.size() < 1) {
Tao Bao039f2da2016-11-22 16:29:50 -08001080 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1081 }
Tianjie Xu5fe280a2016-10-17 18:15:20 -07001082
Tao Bao039f2da2016-11-22 16:29:50 -08001083 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001084 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001085 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1086 }
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001087
Tao Bao3d69f0d2018-12-20 09:44:06 -08001088 auto exec_args = StringVectorToNullTerminatedArray(args);
1089 LOG(INFO) << "about to run program [" << exec_args[0] << "] with " << argv.size() << " args";
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001090
Tao Bao039f2da2016-11-22 16:29:50 -08001091 pid_t child = fork();
1092 if (child == 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -08001093 execv(exec_args[0], exec_args.data());
Tao Bao039f2da2016-11-22 16:29:50 -08001094 PLOG(ERROR) << "run_program: execv failed";
Tao Bao3da88012017-02-03 13:09:23 -08001095 _exit(EXIT_FAILURE);
Tao Bao039f2da2016-11-22 16:29:50 -08001096 }
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001097
Tao Bao039f2da2016-11-22 16:29:50 -08001098 int status;
1099 waitpid(child, &status, 0);
1100 if (WIFEXITED(status)) {
1101 if (WEXITSTATUS(status) != 0) {
1102 LOG(ERROR) << "run_program: child exited with status " << WEXITSTATUS(status);
1103 }
1104 } else if (WIFSIGNALED(status)) {
1105 LOG(ERROR) << "run_program: child terminated by signal " << WTERMSIG(status);
1106 }
1107
1108 return StringValue(std::to_string(status));
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001109}
1110
Tao Bao511d7592018-06-19 15:56:49 -07001111// read_file(filename)
Tao Baobafd6c72018-07-09 15:08:50 -07001112// Reads a local file 'filename' and returns its contents as a string Value.
Tianjie Xuc4447322017-03-06 14:44:59 -08001113Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1114 if (argv.size() != 1) {
1115 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001116 }
Tianjie Xu5fe280a2016-10-17 18:15:20 -07001117
Tao Bao039f2da2016-11-22 16:29:50 -08001118 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001119 if (!ReadArgs(state, argv, &args)) {
Tao Bao511d7592018-06-19 15:56:49 -07001120 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tao Bao039f2da2016-11-22 16:29:50 -08001121 }
1122 const std::string& filename = args[0];
Doug Zongker512536a2010-02-17 16:11:44 -08001123
Tao Baobafd6c72018-07-09 15:08:50 -07001124 std::string contents;
1125 if (android::base::ReadFileToString(filename, &contents)) {
1126 return new Value(Value::Type::STRING, std::move(contents));
Tao Bao039f2da2016-11-22 16:29:50 -08001127 }
Tao Bao511d7592018-06-19 15:56:49 -07001128
1129 // Leave it to caller to handle the failure.
Tao Baobafd6c72018-07-09 15:08:50 -07001130 PLOG(ERROR) << name << ": Failed to read " << filename;
Tao Bao511d7592018-06-19 15:56:49 -07001131 return StringValue("");
Doug Zongker512536a2010-02-17 16:11:44 -08001132}
Doug Zongker8edb00c2009-06-11 17:21:44 -07001133
Tao Baod0f30882016-11-03 23:52:01 -07001134// write_value(value, filename)
1135// Writes 'value' to 'filename'.
1136// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
Tianjie Xuc4447322017-03-06 14:44:59 -08001137Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1138 if (argv.size() != 2) {
1139 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1140 argv.size());
Tao Baod0f30882016-11-03 23:52:01 -07001141 }
1142
1143 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001144 if (!ReadArgs(state, argv, &args)) {
Tao Baod0f30882016-11-03 23:52:01 -07001145 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
1146 }
1147
1148 const std::string& filename = args[1];
1149 if (filename.empty()) {
1150 return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
1151 }
1152
1153 const std::string& value = args[0];
1154 if (!android::base::WriteStringToFile(value, filename)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001155 PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
Tao Baod0f30882016-11-03 23:52:01 -07001156 return StringValue("");
1157 } else {
1158 return StringValue("t");
1159 }
1160}
1161
Doug Zongkerc87bab12013-11-25 13:53:25 -08001162// Immediately reboot the device. Recovery is not finished normally,
1163// so if you reboot into recovery it will re-start applying the
1164// current package (because nothing has cleared the copy of the
1165// arguments stored in the BCB).
1166//
1167// The argument is the partition name passed to the android reboot
1168// property. It can be "recovery" to boot from the recovery
1169// partition, or "" (empty string) to boot from the regular boot
1170// partition.
Tianjie Xuc4447322017-03-06 14:44:59 -08001171Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1172 if (argv.size() != 2) {
1173 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1174 argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001175 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001176
Tao Baobedf5fc2016-11-18 12:01:26 -08001177 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001178 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001179 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
1180 }
1181 const std::string& filename = args[0];
1182 const std::string& property = args[1];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001183
Tao Baobedf5fc2016-11-18 12:01:26 -08001184 // Zero out the 'command' field of the bootloader message. Leave the rest intact.
1185 bootloader_message boot;
1186 std::string err;
1187 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001188 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001189 return StringValue("");
1190 }
1191 memset(boot.command, 0, sizeof(boot.command));
1192 if (!write_bootloader_message_to(boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001193 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001194 return StringValue("");
1195 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001196
Tao Bao2c526392018-05-03 23:01:13 -07001197 reboot("reboot," + property);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001198
Tao Baobedf5fc2016-11-18 12:01:26 -08001199 sleep(5);
1200 return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001201}
1202
1203// Store a string value somewhere that future invocations of recovery
1204// can access it. This value is called the "stage" and can be used to
1205// drive packages that need to do reboots in the middle of
1206// installation and keep track of where they are in the multi-stage
1207// install.
1208//
1209// The first argument is the block device for the misc partition
1210// ("/misc" in the fstab), which is where this value is stored. The
1211// second argument is the string to store; it should not exceed 31
1212// bytes.
Tianjie Xuc4447322017-03-06 14:44:59 -08001213Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1214 if (argv.size() != 2) {
1215 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1216 argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001217 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001218
Tao Baobedf5fc2016-11-18 12:01:26 -08001219 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001220 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001221 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1222 }
1223 const std::string& filename = args[0];
1224 const std::string& stagestr = args[1];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001225
Tao Baobedf5fc2016-11-18 12:01:26 -08001226 // Store this value in the misc partition, immediately after the
1227 // bootloader message that the main recovery uses to save its
1228 // arguments in case of the device restarting midway through
1229 // package installation.
1230 bootloader_message boot;
1231 std::string err;
1232 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001233 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001234 return StringValue("");
1235 }
1236 strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
1237 if (!write_bootloader_message_to(boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001238 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001239 return StringValue("");
1240 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001241
Tao Baobedf5fc2016-11-18 12:01:26 -08001242 return StringValue(filename);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001243}
1244
1245// Return the value most recently saved with SetStageFn. The argument
1246// is the block device for the misc partition.
Tianjie Xuc4447322017-03-06 14:44:59 -08001247Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1248 if (argv.size() != 1) {
1249 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001250 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001251
Tao Baobedf5fc2016-11-18 12:01:26 -08001252 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001253 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001254 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1255 }
1256 const std::string& filename = args[0];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001257
Tao Baobedf5fc2016-11-18 12:01:26 -08001258 bootloader_message boot;
1259 std::string err;
1260 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001261 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001262 return StringValue("");
1263 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001264
Tao Baobedf5fc2016-11-18 12:01:26 -08001265 return StringValue(boot.stage);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001266}
1267
Tianjie Xuc4447322017-03-06 14:44:59 -08001268Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1269 if (argv.size() != 2) {
1270 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1271 argv.size());
Tao Bao358c2ec2016-11-28 11:48:43 -08001272 }
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001273
Tao Bao358c2ec2016-11-28 11:48:43 -08001274 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001275 if (!ReadArgs(state, argv, &args)) {
Tao Bao358c2ec2016-11-28 11:48:43 -08001276 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1277 }
1278 const std::string& filename = args[0];
1279 const std::string& len_str = args[1];
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001280
Tao Bao358c2ec2016-11-28 11:48:43 -08001281 size_t len;
1282 if (!android::base::ParseUint(len_str.c_str(), &len)) {
1283 return nullptr;
1284 }
Tianjie Xu22f11202018-08-27 10:50:31 -07001285 android::base::unique_fd fd(open(filename.c_str(), O_WRONLY));
1286 if (fd == -1) {
1287 PLOG(ERROR) << "Failed to open " << filename;
1288 return StringValue("");
1289 }
1290
Tao Bao358c2ec2016-11-28 11:48:43 -08001291 // The wipe_block_device function in ext4_utils returns 0 on success and 1
1292 // for failure.
1293 int status = wipe_block_device(fd, len);
1294 return StringValue((status == 0) ? "t" : "");
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001295}
1296
Tianjie Xuc4447322017-03-06 14:44:59 -08001297Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1298 if (!argv.empty()) {
1299 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
1300 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001301 }
1302 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
1303 fprintf(ui->cmd_pipe, "enable_reboot\n");
1304 return StringValue("t");
Doug Zongkerc704e062014-05-23 08:40:35 -07001305}
1306
Tianjie Xuc4447322017-03-06 14:44:59 -08001307Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1308 if (argv.empty()) {
1309 return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001310 }
Michael Rungeacf47db2014-11-21 00:12:28 -08001311
Tao Bao039f2da2016-11-22 16:29:50 -08001312 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001313 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001314 return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
1315 }
Michael Rungeacf47db2014-11-21 00:12:28 -08001316
Tao Bao3d69f0d2018-12-20 09:44:06 -08001317 // tune2fs expects the program name as its first arg.
1318 args.insert(args.begin(), "tune2fs");
1319 auto tune2fs_args = StringVectorToNullTerminatedArray(args);
Michael Rungeacf47db2014-11-21 00:12:28 -08001320
Tao Bao3d69f0d2018-12-20 09:44:06 -08001321 // tune2fs changes the filesystem parameters on an ext2 filesystem; it returns 0 on success.
1322 if (auto result = tune2fs_main(tune2fs_args.size() - 1, tune2fs_args.data()); result != 0) {
Tao Bao039f2da2016-11-22 16:29:50 -08001323 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
1324 }
1325 return StringValue("t");
Michael Rungeacf47db2014-11-21 00:12:28 -08001326}
1327
Doug Zongker9931f7f2009-06-10 14:11:53 -07001328void RegisterInstallFunctions() {
Tao Bao039f2da2016-11-22 16:29:50 -08001329 RegisterFunction("mount", MountFn);
1330 RegisterFunction("is_mounted", IsMountedFn);
1331 RegisterFunction("unmount", UnmountFn);
1332 RegisterFunction("format", FormatFn);
1333 RegisterFunction("show_progress", ShowProgressFn);
1334 RegisterFunction("set_progress", SetProgressFn);
Michael Bestas847c0652019-09-19 21:42:12 +03001335 RegisterFunction("delete", DeleteFn);
1336 RegisterFunction("delete_recursive", DeleteFn);
1337 RegisterFunction("package_extract_dir", PackageExtractDirFn);
Tao Bao039f2da2016-11-22 16:29:50 -08001338 RegisterFunction("package_extract_file", PackageExtractFileFn);
Michael Bestas847c0652019-09-19 21:42:12 +03001339 RegisterFunction("symlink", SymlinkFn);
1340
1341 // Usage:
1342 // set_metadata("filename", "key1", "value1", "key2", "value2", ...)
1343 // Example:
1344 // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel",
1345 // "u:object_r:system_file:s0", "capabilities", 0x0);
1346 RegisterFunction("set_metadata", SetMetadataFn);
1347
1348 // Usage:
1349 // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
1350 // Example:
1351 // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755,
1352 // "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
1353 RegisterFunction("set_metadata_recursive", SetMetadataFn);
Nick Kralevich5dbdef02013-09-07 14:41:06 -07001354
Tao Bao039f2da2016-11-22 16:29:50 -08001355 RegisterFunction("getprop", GetPropFn);
1356 RegisterFunction("file_getprop", FileGetPropFn);
Doug Zongker8edb00c2009-06-11 17:21:44 -07001357
Tao Bao039f2da2016-11-22 16:29:50 -08001358 RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
Tao Bao5609bc82018-06-20 00:30:48 -07001359 RegisterFunction("patch_partition", PatchPartitionFn);
1360 RegisterFunction("patch_partition_check", PatchPartitionCheckFn);
Doug Zongkerd9c9d102009-06-12 12:24:39 -07001361
Tao Bao039f2da2016-11-22 16:29:50 -08001362 RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
Doug Zongker52b40362014-02-10 15:30:30 -08001363
Tao Bao039f2da2016-11-22 16:29:50 -08001364 RegisterFunction("read_file", ReadFileFn);
Michael Bestas847c0652019-09-19 21:42:12 +03001365 RegisterFunction("rename", RenameFn);
Tao Bao039f2da2016-11-22 16:29:50 -08001366 RegisterFunction("write_value", WriteValueFn);
Doug Zongker512536a2010-02-17 16:11:44 -08001367
Tao Bao039f2da2016-11-22 16:29:50 -08001368 RegisterFunction("wipe_cache", WipeCacheFn);
Doug Zongkerd0181b82011-10-19 10:51:12 -07001369
Tao Bao039f2da2016-11-22 16:29:50 -08001370 RegisterFunction("ui_print", UIPrintFn);
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001371
Tao Bao039f2da2016-11-22 16:29:50 -08001372 RegisterFunction("run_program", RunProgramFn);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001373
Tao Bao039f2da2016-11-22 16:29:50 -08001374 RegisterFunction("reboot_now", RebootNowFn);
1375 RegisterFunction("get_stage", GetStageFn);
1376 RegisterFunction("set_stage", SetStageFn);
Doug Zongkerc704e062014-05-23 08:40:35 -07001377
Tao Bao039f2da2016-11-22 16:29:50 -08001378 RegisterFunction("enable_reboot", EnableRebootFn);
1379 RegisterFunction("tune2fs", Tune2FsFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -07001380}