blob: 28bfee96887071393569c01ef28ed309ea991606 [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 Bao1bf17722016-11-03 23:52:01 -070039#include <string>
Yabin Cui64be2132016-02-03 18:16:02 -080040#include <vector>
41
Tao Bao1bf17722016-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>
Elliott Hughes4b166f02015-12-04 15:30:20 -080045#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>
51#include <bootloader_message/bootloader_message.h>
Tao Baode40ba52016-10-05 23:17:01 -070052#include <ext4_utils/wipe.h>
Tao Bao361342c2016-02-08 11:15:50 -080053#include <openssl/sha.h>
Elliott Hughes4bbd5bf2016-04-01 18:24:39 -070054#include <selinux/label.h>
55#include <selinux/selinux.h>
Tao Bao09e468f2017-09-29 14:39:33 -070056#include <tune2fs.h>
Tianjie Xu8cf5c8f2016-09-08 20:10:11 -070057#include <ziparchive/zip_archive.h>
Tao Bao1107d962015-09-09 17:16:55 -070058
Doug Zongker9931f7f2009-06-10 14:11:53 -070059#include "edify/expr.h"
bigbiff26d5d5f2020-03-23 09:56:16 -040060<<<<<<< HEAD
Elliott Hughes63a31922016-06-09 17:41:22 -070061#include "mounts.h"
Ethan Yonker8373cfe2017-09-08 06:50:54 -050062
Doug Zongker512536a2010-02-17 16:11:44 -080063#include "applypatch/applypatch.h"
Dees_Troy512376c2013-09-03 19:39:41 +000064#include "flashutils/flashutils.h"
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -080065#include "install.h"
Ethan Yonker7e1b9862015-03-19 14:10:01 -050066#ifdef HAVE_LIBTUNE2FS
Michael Rungeb278c252014-11-21 00:12:28 -080067#include "tune2fs.h"
Ethan Yonker7e1b9862015-03-19 14:10:01 -050068#endif
Doug Zongker8edb00c2009-06-11 17:21:44 -070069
Doug Zongker3d177d02010-07-01 09:18:44 -070070#ifdef USE_EXT4
71#include "make_ext4fs.h"
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -080072#include "wipe.h"
Doug Zongker3d177d02010-07-01 09:18:44 -070073#endif
74
Tom Marshall981118e2017-10-25 20:27:08 +020075#include "otautil/ZipUtil.h"
Tao Baod33b2f82017-09-28 21:29:11 -070076#include "otafault/ota_io.h"
Tianjie Xu8cf5c8f2016-09-08 20:10:11 -070077#include "otautil/DirUtil.h"
bigbiff26d5d5f2020-03-23 09:56:16 -040078=======
Tao Bao17054c02018-05-03 22:41:23 -070079#include "otautil/dirutil.h"
bigbiff26d5d5f2020-03-23 09:56:16 -040080>>>>>>> android-10.0.0_r25
Tao Bao1fc5bf32017-10-06 07:43:41 -070081#include "otautil/error_code.h"
Tao Bao9a319f02018-01-04 13:19:11 -080082#include "otautil/mounts.h"
Tao Bao09e468f2017-09-29 14:39:33 -070083#include "otautil/print_sha1.h"
Tao Bao2c526392018-05-03 23:01:13 -070084#include "otautil/sysutil.h"
Tao Bao0c7839a2016-10-10 15:48:37 -070085#include "updater/updater.h"
Doug Zongker52b40362014-02-10 15:30:30 -080086
Tao Bao1107d962015-09-09 17:16:55 -070087// Send over the buffer to recovery though the command pipe.
88static void uiPrint(State* state, const std::string& buffer) {
Tao Bao039f2da2016-11-22 16:29:50 -080089 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
Tao Baob6918c72015-05-19 17:02:16 -070090
Tao Bao039f2da2016-11-22 16:29:50 -080091 // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
92 // So skip sending empty strings to UI.
93 std::vector<std::string> lines = android::base::Split(buffer, "\n");
94 for (auto& line : lines) {
95 if (!line.empty()) {
96 fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
Michael Runge75480252014-10-22 19:48:41 -070097 }
Tao Bao039f2da2016-11-22 16:29:50 -080098 }
Tao Bao1107d962015-09-09 17:16:55 -070099
Tao Bao039f2da2016-11-22 16:29:50 -0800100 // On the updater side, we need to dump the contents to stderr (which has
101 // been redirected to the log file). Because the recovery will only print
102 // the contents to screen when processing pipe command ui_print.
103 LOG(INFO) << buffer;
Michael Runge75480252014-10-22 19:48:41 -0700104}
105
Simon Shields2e9747f2018-08-09 01:17:21 +1000106static bool is_dir(const std::string& dirpath) {
107 struct stat st;
108 return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
109}
110
111// Create all parent directories of name, if necessary.
112static bool make_parents(const std::string& name) {
113 size_t prev_end = 0;
114 while (prev_end < name.size()) {
115 size_t next_end = name.find('/', prev_end + 1);
116 if (next_end == std::string::npos) {
117 break;
118 }
119 std::string dir_path = name.substr(0, next_end);
120 if (!is_dir(dir_path)) {
121 int result = mkdir(dir_path.c_str(), 0700);
122 if (result != 0) {
123 PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name;
124 return false;
125 }
126
127 LOG(INFO) << "created [" << dir_path << "]";
128 }
129 prev_end = next_end;
130 }
131 return true;
132}
133
Elliott Hughes83ce7552016-06-30 09:28:42 -0700134void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) {
Tao Bao039f2da2016-11-22 16:29:50 -0800135 std::string error_msg;
Tao Bao1107d962015-09-09 17:16:55 -0700136
Tao Bao039f2da2016-11-22 16:29:50 -0800137 va_list ap;
138 va_start(ap, format);
139 android::base::StringAppendV(&error_msg, format, ap);
140 va_end(ap);
Tao Bao1107d962015-09-09 17:16:55 -0700141
Tao Bao039f2da2016-11-22 16:29:50 -0800142 uiPrint(state, error_msg);
Michael Runge75480252014-10-22 19:48:41 -0700143}
144
Tianjie Xu5419ad32018-02-02 16:49:15 -0800145// This is the updater side handler for ui_print() in edify script. Contents will be sent over to
146// the recovery side for on-screen display.
147Value* UIPrintFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
148 std::vector<std::string> args;
149 if (!ReadArgs(state, argv, &args)) {
150 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
151 }
152
153 std::string buffer = android::base::Join(args, "");
154 uiPrint(state, buffer);
155 return StringValue(buffer);
Doug Zongker8edb00c2009-06-11 17:21:44 -0700156}
157
Tianjie Xu5419ad32018-02-02 16:49:15 -0800158// package_extract_file(package_file[, dest_file])
159// Extracts a single package_file from the update package and writes it to dest_file,
160// overwriting existing files if necessary. Without the dest_file argument, returns the
161// contents of the package file as a binary blob.
162Value* PackageExtractFileFn(const char* name, State* state,
163 const std::vector<std::unique_ptr<Expr>>& argv) {
164 if (argv.size() < 1 || argv.size() > 2) {
165 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
166 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800167 }
Tianjie Xu5419ad32018-02-02 16:49:15 -0800168
169 if (argv.size() == 2) {
170 // The two-argument version extracts to a file.
171
172 std::vector<std::string> args;
173 if (!ReadArgs(state, argv, &args)) {
174 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
175 argv.size());
176 }
177 const std::string& zip_path = args[0];
178 const std::string& dest_path = args[1];
179
180 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
181 ZipString zip_string_path(zip_path.c_str());
182 ZipEntry entry;
183 if (FindEntry(za, zip_string_path, &entry) != 0) {
184 LOG(ERROR) << name << ": no " << zip_path << " in package";
185 return StringValue("");
186 }
187
Tianjie Xu22f11202018-08-27 10:50:31 -0700188 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
189 open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
Tianjie Xu5419ad32018-02-02 16:49:15 -0800190 if (fd == -1) {
191 PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
192 return StringValue("");
193 }
194
195 bool success = true;
196 int32_t ret = ExtractEntryToFile(za, &entry, fd);
197 if (ret != 0) {
198 LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
199 << entry.uncompressed_length << " bytes) to \"" << dest_path
200 << "\": " << ErrorCodeString(ret);
201 success = false;
202 }
Tianjie Xu22f11202018-08-27 10:50:31 -0700203 if (fsync(fd) == -1) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800204 PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
205 success = false;
206 }
Tianjie Xu22f11202018-08-27 10:50:31 -0700207
208 if (close(fd.release()) != 0) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800209 PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
210 success = false;
211 }
212
213 return StringValue(success ? "t" : "");
214 } else {
215 // The one-argument version returns the contents of the file as the result.
216
217 std::vector<std::string> args;
218 if (!ReadArgs(state, argv, &args)) {
219 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
220 argv.size());
221 }
222 const std::string& zip_path = args[0];
223
224 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
225 ZipString zip_string_path(zip_path.c_str());
226 ZipEntry entry;
227 if (FindEntry(za, zip_string_path, &entry) != 0) {
228 return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
229 zip_path.c_str());
230 }
231
232 std::string buffer;
233 buffer.resize(entry.uncompressed_length);
234
235 int32_t ret =
236 ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
237 if (ret != 0) {
238 return ErrorAbort(state, kPackageExtractFileFailure,
239 "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
240 zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
241 }
242
Tao Bao511d7592018-06-19 15:56:49 -0700243 return new Value(Value::Type::BLOB, buffer);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800244 }
245}
246
Tao Bao5609bc82018-06-20 00:30:48 -0700247// patch_partition_check(target_partition, source_partition)
248// Checks if the target and source partitions have the desired checksums to be patched. It returns
249// directly, if the target partition already has the expected checksum. Otherwise it in turn
250// checks the integrity of the source partition and the backup file on /cache.
Tianjie Xu5419ad32018-02-02 16:49:15 -0800251//
Tao Bao5609bc82018-06-20 00:30:48 -0700252// For example, patch_partition_check(
253// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
254// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4")
255Value* PatchPartitionCheckFn(const char* name, State* state,
256 const std::vector<std::unique_ptr<Expr>>& argv) {
257 if (argv.size() != 2) {
Tianjie Xu5419ad32018-02-02 16:49:15 -0800258 return ErrorAbort(state, kArgsParsingFailure,
Tao Bao5609bc82018-06-20 00:30:48 -0700259 "%s(): Invalid number of args (expected 2, got %zu)", name, argv.size());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800260 }
261
262 std::vector<std::string> args;
Tao Bao5609bc82018-06-20 00:30:48 -0700263 if (!ReadArgs(state, argv, &args, 0, 2)) {
264 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800265 }
266
Tao Bao5609bc82018-06-20 00:30:48 -0700267 std::string err;
268 auto target = Partition::Parse(args[0], &err);
269 if (!target) {
270 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
271 args[0].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800272 }
273
Tao Bao5609bc82018-06-20 00:30:48 -0700274 auto source = Partition::Parse(args[1], &err);
275 if (!source) {
276 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
277 args[1].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800278 }
279
Tao Bao5609bc82018-06-20 00:30:48 -0700280 bool result = PatchPartitionCheck(target, source);
281 return StringValue(result ? "t" : "");
Tianjie Xu5419ad32018-02-02 16:49:15 -0800282}
283
Tao Bao5609bc82018-06-20 00:30:48 -0700284// patch_partition(target, source, patch)
285// Applies the given patch to the source partition, and writes the result to the target partition.
286//
287// For example, patch_partition(
288// "EMMC:/dev/block/boot:12342568:8aaacf187a6929d0e9c3e9e46ea7ff495b43424d",
289// "EMMC:/dev/block/boot:12363048:06b0b16299dcefc94900efed01e0763ff644ffa4",
290// package_extract_file("boot.img.p"))
291Value* PatchPartitionFn(const char* name, State* state,
292 const std::vector<std::unique_ptr<Expr>>& argv) {
293 if (argv.size() != 3) {
294 return ErrorAbort(state, kArgsParsingFailure,
295 "%s(): Invalid number of args (expected 3, got %zu)", name, argv.size());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800296 }
297
298 std::vector<std::string> args;
Tao Bao5609bc82018-06-20 00:30:48 -0700299 if (!ReadArgs(state, argv, &args, 0, 2)) {
300 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800301 }
302
Tao Bao5609bc82018-06-20 00:30:48 -0700303 std::string err;
304 auto target = Partition::Parse(args[0], &err);
305 if (!target) {
306 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse target \"%s\": %s", name,
307 args[0].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800308 }
309
Tao Bao5609bc82018-06-20 00:30:48 -0700310 auto source = Partition::Parse(args[1], &err);
311 if (!source) {
312 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse source \"%s\": %s", name,
313 args[1].c_str(), err.c_str());
Tianjie Xu5419ad32018-02-02 16:49:15 -0800314 }
315
Tao Bao5609bc82018-06-20 00:30:48 -0700316 std::vector<std::unique_ptr<Value>> values;
317 if (!ReadValueArgs(state, argv, &values, 2, 1) || values[0]->type != Value::Type::BLOB) {
318 return ErrorAbort(state, kArgsParsingFailure, "%s(): Invalid patch arg", name);
Tianjie Xu5419ad32018-02-02 16:49:15 -0800319 }
320
Tao Bao5609bc82018-06-20 00:30:48 -0700321 bool result = PatchPartition(target, source, *values[0], nullptr);
322 return StringValue(result ? "t" : "");
Doug Zongkera23075f2012-08-06 16:19:09 -0700323}
Doug Zongker8edb00c2009-06-11 17:21:44 -0700324
Doug Zongker9931f7f2009-06-10 14:11:53 -0700325// mount(fs_type, partition_type, location, mount_point)
Tao Bao0831d0b2016-11-03 23:25:04 -0700326// mount(fs_type, partition_type, location, mount_point, mount_options)
Doug Zongker9931f7f2009-06-10 14:11:53 -0700327
Doug Zongker9931f7f2009-06-10 14:11:53 -0700328// fs_type="ext4" partition_type="EMMC" location=device
Tianjie Xuc4447322017-03-06 14:44:59 -0800329Value* MountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
330 if (argv.size() != 4 && argv.size() != 5) {
331 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %zu", name,
332 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800333 }
334
335 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800336 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800337 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
338 }
339 const std::string& fs_type = args[0];
340 const std::string& partition_type = args[1];
341 const std::string& location = args[2];
342 const std::string& mount_point = args[3];
343 std::string mount_options;
344
Tianjie Xuc4447322017-03-06 14:44:59 -0800345 if (argv.size() == 5) {
Tao Bao039f2da2016-11-22 16:29:50 -0800346 mount_options = args[4];
347 }
348
349 if (fs_type.empty()) {
350 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
351 }
352 if (partition_type.empty()) {
353 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
354 name);
355 }
356 if (location.empty()) {
357 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
358 }
359 if (mount_point.empty()) {
360 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
361 name);
362 }
363
364 {
365 char* secontext = nullptr;
366
367 if (sehandle) {
368 selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755);
369 setfscreatecon(secontext);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700370 }
371
Tao Bao039f2da2016-11-22 16:29:50 -0800372 mkdir(mount_point.c_str(), 0755);
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700373
Tao Bao039f2da2016-11-22 16:29:50 -0800374 if (secontext) {
375 freecon(secontext);
376 setfscreatecon(nullptr);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700377 }
Tao Bao039f2da2016-11-22 16:29:50 -0800378 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700379
Tao Bao039f2da2016-11-22 16:29:50 -0800380 if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(),
381 MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700382 uiPrintf(state, "%s: Failed to mount %s at %s: %s", name, location.c_str(), mount_point.c_str(),
383 strerror(errno));
Tao Bao039f2da2016-11-22 16:29:50 -0800384 return StringValue("");
385 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700386
Tao Bao039f2da2016-11-22 16:29:50 -0800387 return StringValue(mount_point);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700388}
389
Doug Zongker9931f7f2009-06-10 14:11:53 -0700390// is_mounted(mount_point)
Tianjie Xuc4447322017-03-06 14:44:59 -0800391Value* IsMountedFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
392 if (argv.size() != 1) {
393 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800394 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700395
Tao Bao039f2da2016-11-22 16:29:50 -0800396 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800397 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800398 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
399 }
400 const std::string& mount_point = args[0];
401 if (mount_point.empty()) {
402 return ErrorAbort(state, kArgsParsingFailure,
403 "mount_point argument to unmount() can't be empty");
404 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700405
Tao Bao039f2da2016-11-22 16:29:50 -0800406 scan_mounted_volumes();
407 MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
408 if (vol == nullptr) {
409 return StringValue("");
410 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700411
Tao Bao039f2da2016-11-22 16:29:50 -0800412 return StringValue(mount_point);
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700413}
414
Tianjie Xuc4447322017-03-06 14:44:59 -0800415Value* UnmountFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
416 if (argv.size() != 1) {
417 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800418 }
419 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 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -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) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700432 uiPrintf(state, "Failed to unmount %s: No such volume", mount_point.c_str());
Tao Bao039f2da2016-11-22 16:29:50 -0800433 return nullptr;
434 } else {
435 int ret = unmount_mounted_volume(vol);
436 if (ret != 0) {
Tao Bao0bbc7642017-03-29 23:57:47 -0700437 uiPrintf(state, "Failed to unmount %s: %s", mount_point.c_str(), strerror(errno));
Nick Kralevich6a821fe2014-10-23 20:36:42 -0700438 }
Tao Bao039f2da2016-11-22 16:29:50 -0800439 }
Nick Kralevich6a821fe2014-10-23 20:36:42 -0700440
Tao Bao039f2da2016-11-22 16:29:50 -0800441 return StringValue(mount_point);
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700442}
443
Tao Bao3d69f0d2018-12-20 09:44:06 -0800444static int exec_cmd(const std::vector<std::string>& args) {
445 CHECK(!args.empty());
446 auto argv = StringVectorToNullTerminatedArray(args);
447
Tao Bao039f2da2016-11-22 16:29:50 -0800448 pid_t child;
449 if ((child = vfork()) == 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800450 execv(argv[0], argv.data());
Tao Bao3da88012017-02-03 13:09:23 -0800451 _exit(EXIT_FAILURE);
Tao Bao039f2da2016-11-22 16:29:50 -0800452 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700453
Tao Bao039f2da2016-11-22 16:29:50 -0800454 int status;
455 waitpid(child, &status, 0);
456 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800457 LOG(ERROR) << args[0] << " failed with status " << WEXITSTATUS(status);
Tao Bao039f2da2016-11-22 16:29:50 -0800458 }
459 return WEXITSTATUS(status);
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700460}
461
Doug Zongker9931f7f2009-06-10 14:11:53 -0700462// format(fs_type, partition_type, location, fs_size, mount_point)
463//
Tao Bao039f2da2016-11-22 16:29:50 -0800464// fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
465// fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
JP Abgrall37aedb32014-06-16 19:07:39 -0700466// if fs_size == 0, then make fs uses the entire partition.
Doug Zongker9931f7f2009-06-10 14:11:53 -0700467// if fs_size > 0, that is the size to use
JP Abgrall37aedb32014-06-16 19:07:39 -0700468// 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 -0800469Value* FormatFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
470 if (argv.size() != 5) {
471 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %zu", name,
472 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800473 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700474
Tao Bao039f2da2016-11-22 16:29:50 -0800475 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800476 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800477 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
478 }
479 const std::string& fs_type = args[0];
480 const std::string& partition_type = args[1];
481 const std::string& location = args[2];
482 const std::string& fs_size = args[3];
483 const std::string& mount_point = args[4];
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700484
Tao Bao039f2da2016-11-22 16:29:50 -0800485 if (fs_type.empty()) {
486 return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
487 }
488 if (partition_type.empty()) {
489 return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
490 name);
491 }
492 if (location.empty()) {
493 return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
494 }
495 if (mount_point.empty()) {
496 return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
497 name);
498 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700499
Tao Bao039f2da2016-11-22 16:29:50 -0800500 int64_t size;
501 if (!android::base::ParseInt(fs_size, &size)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800502 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800503 fs_size.c_str());
504 }
505
506 if (fs_type == "ext4") {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800507 std::vector<std::string> mke2fs_args = {
508 "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", location
509 };
Jin Qianac318082017-04-21 14:36:12 -0700510 if (size != 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -0800511 mke2fs_args.push_back(std::to_string(size / 4096LL));
Jin Qianac318082017-04-21 14:36:12 -0700512 }
513
Tao Bao3d69f0d2018-12-20 09:44:06 -0800514 if (auto status = exec_cmd(mke2fs_args); status != 0) {
Jin Qian502fd1c2017-11-02 11:58:12 -0700515 LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location;
516 return StringValue("");
Jin Qianac318082017-04-21 14:36:12 -0700517 }
518
Tao Bao3d69f0d2018-12-20 09:44:06 -0800519 if (auto status = exec_cmd({ "/system/bin/e2fsdroid", "-e", "-a", mount_point, location });
520 status != 0) {
Jin Qianac318082017-04-21 14:36:12 -0700521 LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location;
Tao Bao039f2da2016-11-22 16:29:50 -0800522 return StringValue("");
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700523 }
Tao Bao039f2da2016-11-22 16:29:50 -0800524 return StringValue(location);
Tao Bao3d69f0d2018-12-20 09:44:06 -0800525 }
526
527 if (fs_type == "f2fs") {
Tao Bao039f2da2016-11-22 16:29:50 -0800528 if (size < 0) {
529 LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
530 return StringValue("");
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700531 }
Tao Bao3d69f0d2018-12-20 09:44:06 -0800532 std::vector<std::string> f2fs_args = {
Tao Baoc674dfb2018-12-20 14:25:15 -0800533 "/system/bin/make_f2fs", "-g", "android", "-w", "512", location
Tao Bao3d69f0d2018-12-20 09:44:06 -0800534 };
535 if (size >= 512) {
536 f2fs_args.push_back(std::to_string(size / 512));
537 }
538 if (auto status = exec_cmd(f2fs_args); status != 0) {
Tao Baoc674dfb2018-12-20 14:25:15 -0800539 LOG(ERROR) << name << ": make_f2fs failed (" << status << ") on " << location;
Tao Bao039f2da2016-11-22 16:29:50 -0800540 return StringValue("");
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700541 }
Jaegeuk Kimc1c73112017-11-28 19:48:05 -0800542
Tao Baoc674dfb2018-12-20 14:25:15 -0800543 if (auto status = exec_cmd({ "/system/bin/sload_f2fs", "-t", mount_point, location });
544 status != 0) {
545 LOG(ERROR) << name << ": sload_f2fs failed (" << status << ") on " << location;
Jaegeuk Kimc1c73112017-11-28 19:48:05 -0800546 return StringValue("");
547 }
548
Tao Bao039f2da2016-11-22 16:29:50 -0800549 return StringValue(location);
Tao Bao039f2da2016-11-22 16:29:50 -0800550 }
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700551
Tao Bao3d69f0d2018-12-20 09:44:06 -0800552 LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
553 << partition_type << "\"";
Tao Bao039f2da2016-11-22 16:29:50 -0800554 return nullptr;
Nick Kralevich5dbdef02013-09-07 14:41:06 -0700555}
Doug Zongker8edb00c2009-06-11 17:21:44 -0700556
Tom Marshallbf4f24f2017-08-23 18:14:00 +0000557// rename(src_name, dst_name)
558// Renames src_name to dst_name. It automatically creates the necessary directories for dst_name.
559// Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk")
560Value* RenameFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
561 if (argv.size() != 2) {
562 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
563 argv.size());
564 }
565
566 std::vector<std::string> args;
567 if (!ReadArgs(state, argv, &args)) {
568 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
569 }
570 const std::string& src_name = args[0];
571 const std::string& dst_name = args[1];
572
573 if (src_name.empty()) {
574 return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
575 }
576 if (dst_name.empty()) {
577 return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
578 }
579 if (!make_parents(dst_name)) {
580 return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s",
581 dst_name.c_str(), strerror(errno));
582 } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) {
583 // File was already moved
584 return StringValue(dst_name);
585 } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) {
586 return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
587 src_name.c_str(), dst_name.c_str(), strerror(errno));
588 }
589
590 return StringValue(dst_name);
591}
592
593// delete([filename, ...])
594// Deletes all the filenames listed. Returns the number of files successfully deleted.
595//
596// delete_recursive([dirname, ...])
597// Recursively deletes dirnames and all their contents. Returns the number of directories
598// successfully deleted.
599Value* DeleteFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
600 std::vector<std::string> paths;
601 if (!ReadArgs(state, argv, &paths)) {
602 return nullptr;
603 }
604
605 bool recursive = (strcmp(name, "delete_recursive") == 0);
606
607 int success = 0;
608 for (const auto& path : paths) {
609 if ((recursive ? dirUnlinkHierarchy(path.c_str()) : unlink(path.c_str())) == 0) {
610 ++success;
611 }
612 }
613
614 return StringValue(std::to_string(success));
615}
616
617
Tianjie Xuc4447322017-03-06 14:44:59 -0800618Value* ShowProgressFn(const char* name, State* state,
619 const std::vector<std::unique_ptr<Expr>>& argv) {
620 if (argv.size() != 2) {
621 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
622 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800623 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700624
Tao Bao039f2da2016-11-22 16:29:50 -0800625 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800626 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800627 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
628 }
629 const std::string& frac_str = args[0];
630 const std::string& sec_str = args[1];
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700631
Tao Bao039f2da2016-11-22 16:29:50 -0800632 double frac;
633 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800634 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800635 frac_str.c_str());
636 }
637 int sec;
638 if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800639 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800640 sec_str.c_str());
641 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700642
Tao Bao039f2da2016-11-22 16:29:50 -0800643 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
644 fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700645
Tao Bao039f2da2016-11-22 16:29:50 -0800646 return StringValue(frac_str);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700647}
648
Tianjie Xu5419ad32018-02-02 16:49:15 -0800649Value* SetProgressFn(const char* name, State* state,
650 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -0800651 if (argv.size() != 1) {
652 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -0800653 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700654
Tao Bao039f2da2016-11-22 16:29:50 -0800655 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800656 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -0800657 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
658 }
659 const std::string& frac_str = args[0];
Tianjie Xu5fe280a2016-10-17 18:15:20 -0700660
Tao Bao039f2da2016-11-22 16:29:50 -0800661 double frac;
662 if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -0800663 return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s", name,
Tao Bao039f2da2016-11-22 16:29:50 -0800664 frac_str.c_str());
665 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700666
Tao Bao039f2da2016-11-22 16:29:50 -0800667 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
668 fprintf(ui->cmd_pipe, "set_progress %f\n", frac);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700669
Tao Bao039f2da2016-11-22 16:29:50 -0800670 return StringValue(frac_str);
Doug Zongker9931f7f2009-06-10 14:11:53 -0700671}
672
Tom Marshall981118e2017-10-25 20:27:08 +0200673// package_extract_dir(package_dir, dest_dir)
674// Extracts all files from the package underneath package_dir and writes them to the
675// corresponding tree beneath dest_dir. Any existing files are overwritten.
676// Example: package_extract_dir("system", "/system")
677//
678// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
679Value* PackageExtractDirFn(const char* name, State* state,
680 const std::vector<std::unique_ptr<Expr>>&argv) {
681 if (argv.size() != 2) {
682 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
683 argv.size());
684 }
685
686 std::vector<std::string> args;
687 if (!ReadArgs(state, argv, &args)) {
688 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
689 }
690 const std::string& zip_path = args[0];
691 const std::string& dest_path = args[1];
692
693 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
694
695 // To create a consistent system image, never use the clock for timestamps.
696 constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
697
698 bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
699
700 return StringValue(success ? "t" : "");
701}
702
Tao Baoef0eb3b2016-11-14 21:29:52 -0800703// package_extract_file(package_file[, dest_file])
704// Extracts a single package_file from the update package and writes it to dest_file,
705// overwriting existing files if necessary. Without the dest_file argument, returns the
706// contents of the package file as a binary blob.
Tianjie Xuc4447322017-03-06 14:44:59 -0800707Value* PackageExtractFileFn(const char* name, State* state,
708 const std::vector<std::unique_ptr<Expr>>& argv) {
709 if (argv.size() < 1 || argv.size() > 2) {
710 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %zu", name,
711 argv.size());
Tao Baoef0eb3b2016-11-14 21:29:52 -0800712 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700713
Tianjie Xuc4447322017-03-06 14:44:59 -0800714 if (argv.size() == 2) {
Tao Baoef0eb3b2016-11-14 21:29:52 -0800715 // The two-argument version extracts to a file.
716
717 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800718 if (!ReadArgs(state, argv, &args)) {
719 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
720 argv.size());
Doug Zongker8edb00c2009-06-11 17:21:44 -0700721 }
Tao Baoef0eb3b2016-11-14 21:29:52 -0800722 const std::string& zip_path = args[0];
723 const std::string& dest_path = args[1];
Doug Zongker8edb00c2009-06-11 17:21:44 -0700724
Tao Baoef0eb3b2016-11-14 21:29:52 -0800725 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
726 ZipString zip_string_path(zip_path.c_str());
727 ZipEntry entry;
728 if (FindEntry(za, zip_string_path, &entry) != 0) {
Tao Bao039f2da2016-11-22 16:29:50 -0800729 LOG(ERROR) << name << ": no " << zip_path << " in package";
Tao Baoef0eb3b2016-11-14 21:29:52 -0800730 return StringValue("");
Doug Zongker9931f7f2009-06-10 14:11:53 -0700731 }
Doug Zongker8edb00c2009-06-11 17:21:44 -0700732
Tao Bao358c2ec2016-11-28 11:48:43 -0800733 unique_fd fd(TEMP_FAILURE_RETRY(
734 ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
Tao Baoef0eb3b2016-11-14 21:29:52 -0800735 if (fd == -1) {
Tao Bao039f2da2016-11-22 16:29:50 -0800736 PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
Tao Baoef0eb3b2016-11-14 21:29:52 -0800737 return StringValue("");
738 }
739
740 bool success = true;
741 int32_t ret = ExtractEntryToFile(za, &entry, fd);
742 if (ret != 0) {
Tao Bao039f2da2016-11-22 16:29:50 -0800743 LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
744 << entry.uncompressed_length << " bytes) to \"" << dest_path
745 << "\": " << ErrorCodeString(ret);
Tao Baoef0eb3b2016-11-14 21:29:52 -0800746 success = false;
747 }
748 if (ota_fsync(fd) == -1) {
Tao Bao039f2da2016-11-22 16:29:50 -0800749 PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
Tao Baoef0eb3b2016-11-14 21:29:52 -0800750 success = false;
751 }
752 if (ota_close(fd) == -1) {
Tao Bao039f2da2016-11-22 16:29:50 -0800753 PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
Tao Baoef0eb3b2016-11-14 21:29:52 -0800754 success = false;
755 }
756
757 return StringValue(success ? "t" : "");
758 } else {
759 // The one-argument version returns the contents of the file as the result.
760
761 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -0800762 if (!ReadArgs(state, argv, &args)) {
763 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %zu args", name,
764 argv.size());
Tao Baoef0eb3b2016-11-14 21:29:52 -0800765 }
766 const std::string& zip_path = args[0];
767
768 ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
769 ZipString zip_string_path(zip_path.c_str());
770 ZipEntry entry;
771 if (FindEntry(za, zip_string_path, &entry) != 0) {
772 return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
773 zip_path.c_str());
774 }
775
776 std::string buffer;
777 buffer.resize(entry.uncompressed_length);
778
779 int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
780 if (ret != 0) {
781 return ErrorAbort(state, kPackageExtractFileFailure,
782 "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
783 zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
784 }
785
786 return new Value(VAL_BLOB, buffer);
787 }
Doug Zongker9931f7f2009-06-10 14:11:53 -0700788}
789
Tom Marshallbf4f24f2017-08-23 18:14:00 +0000790// symlink(target, [src1, src2, ...])
791// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc
792// before creating symlinks.
793Value* SymlinkFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
794 if (argv.size() == 0) {
795 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %zu", name, argv.size());
796 }
797 std::string target;
798 if (!Evaluate(state, argv[0], &target)) {
799 return nullptr;
800 }
801
802 std::vector<std::string> srcs;
803 if (!ReadArgs(state, argv, &srcs, 1, argv.size())) {
804 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
805 }
806
807 size_t bad = 0;
808 for (const auto& src : srcs) {
809 if (unlink(src.c_str()) == -1 && errno != ENOENT) {
810 PLOG(ERROR) << name << ": failed to remove " << src;
811 ++bad;
812 } else if (!make_parents(src)) {
813 LOG(ERROR) << name << ": failed to symlink " << src << " to " << target
814 << ": making parents failed";
815 ++bad;
816 } else if (symlink(target.c_str(), src.c_str()) == -1) {
817 PLOG(ERROR) << name << ": failed to symlink " << src << " to " << target;
818 ++bad;
819 }
820 }
821 if (bad != 0) {
822 return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad);
823 }
824 return StringValue("t");
825}
826
827struct perm_parsed_args {
828 bool has_uid;
829 uid_t uid;
830 bool has_gid;
831 gid_t gid;
832 bool has_mode;
833 mode_t mode;
834 bool has_fmode;
835 mode_t fmode;
836 bool has_dmode;
837 mode_t dmode;
838 bool has_selabel;
839 const char* selabel;
840 bool has_capabilities;
841 uint64_t capabilities;
842};
843
844static struct perm_parsed_args ParsePermArgs(State * state,
845 const std::vector<std::string>& args) {
846 struct perm_parsed_args parsed;
847 int bad = 0;
848 static int max_warnings = 20;
849
850 memset(&parsed, 0, sizeof(parsed));
851
852 for (size_t i = 1; i < args.size(); i += 2) {
853 if (args[i] == "uid") {
854 int64_t uid;
855 if (sscanf(args[i + 1].c_str(), "%" SCNd64, &uid) == 1) {
856 parsed.uid = uid;
857 parsed.has_uid = true;
858 } else {
859 uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str());
860 bad++;
861 }
862 continue;
863 }
864 if (args[i] == "gid") {
865 int64_t gid;
866 if (sscanf(args[i + 1].c_str(), "%" SCNd64, &gid) == 1) {
867 parsed.gid = gid;
868 parsed.has_gid = true;
869 } else {
870 uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str());
871 bad++;
872 }
873 continue;
874 }
875 if (args[i] == "mode") {
876 int32_t mode;
877 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
878 parsed.mode = mode;
879 parsed.has_mode = true;
880 } else {
881 uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str());
882 bad++;
883 }
884 continue;
885 }
886 if (args[i] == "dmode") {
887 int32_t mode;
888 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
889 parsed.dmode = mode;
890 parsed.has_dmode = true;
891 } else {
892 uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str());
893 bad++;
894 }
895 continue;
896 }
897 if (args[i] == "fmode") {
898 int32_t mode;
899 if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) {
900 parsed.fmode = mode;
901 parsed.has_fmode = true;
902 } else {
903 uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str());
904 bad++;
905 }
906 continue;
907 }
908 if (args[i] == "capabilities") {
909 int64_t capabilities;
910 if (sscanf(args[i + 1].c_str(), "%" SCNi64, &capabilities) == 1) {
911 parsed.capabilities = capabilities;
912 parsed.has_capabilities = true;
913 } else {
914 uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str());
915 bad++;
916 }
917 continue;
918 }
919 if (args[i] == "selabel") {
920 if (!args[i + 1].empty()) {
921 parsed.selabel = args[i + 1].c_str();
922 parsed.has_selabel = true;
923 } else {
924 uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str());
925 bad++;
926 }
927 continue;
928 }
929 if (max_warnings != 0) {
930 printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str());
931 max_warnings--;
932 if (max_warnings == 0) {
933 LOG(INFO) << "ParsedPermArgs: suppressing further warnings";
934 }
935 }
936 }
937 return parsed;
938}
939
940static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr,
941 struct perm_parsed_args parsed) {
942 int bad = 0;
943
944 if (parsed.has_selabel) {
945 if (lsetfilecon(filename, parsed.selabel) != 0) {
946 uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", filename,
947 parsed.selabel, strerror(errno));
948 bad++;
949 }
950 }
951
952 /* ignore symlinks */
953 if (S_ISLNK(statptr->st_mode)) {
954 return bad;
955 }
956
957 if (parsed.has_uid) {
958 if (chown(filename, parsed.uid, -1) < 0) {
959 uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", filename, parsed.uid,
960 strerror(errno));
961 bad++;
962 }
963 }
964
965 if (parsed.has_gid) {
966 if (chown(filename, -1, parsed.gid) < 0) {
967 uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", filename, parsed.gid,
968 strerror(errno));
969 bad++;
970 }
971 }
972
973 if (parsed.has_mode) {
974 if (chmod(filename, parsed.mode) < 0) {
975 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.mode,
976 strerror(errno));
977 bad++;
978 }
979 }
980
981 if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) {
982 if (chmod(filename, parsed.dmode) < 0) {
983 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.dmode,
984 strerror(errno));
985 bad++;
986 }
987 }
988
989 if (parsed.has_fmode && S_ISREG(statptr->st_mode)) {
990 if (chmod(filename, parsed.fmode) < 0) {
991 uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.fmode,
992 strerror(errno));
993 bad++;
994 }
995 }
996
997 if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) {
998 if (parsed.capabilities == 0) {
999 if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) {
1000 // Report failure unless it's ENODATA (attribute not set)
1001 uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", filename,
1002 parsed.capabilities, strerror(errno));
1003 bad++;
1004 }
1005 } else {
1006 struct vfs_cap_data cap_data;
1007 memset(&cap_data, 0, sizeof(cap_data));
1008 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
1009 cap_data.data[0].permitted = (uint32_t)(parsed.capabilities & 0xffffffff);
1010 cap_data.data[0].inheritable = 0;
1011 cap_data.data[1].permitted = (uint32_t)(parsed.capabilities >> 32);
1012 cap_data.data[1].inheritable = 0;
1013 if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
1014 uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", filename,
1015 parsed.capabilities, strerror(errno));
1016 bad++;
1017 }
1018 }
1019 }
1020
1021 return bad;
1022}
1023
1024// nftw doesn't allow us to pass along context, so we need to use
1025// global variables. *sigh*
1026static struct perm_parsed_args recursive_parsed_args;
1027static State* recursive_state;
1028
1029static int do_SetMetadataRecursive(const char* filename, const struct stat* statptr, int fileflags,
1030 struct FTW* pfwt) {
1031 return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args);
1032}
1033
1034static Value* SetMetadataFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1035 if ((argv.size() % 2) != 1) {
1036 return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %zu",
1037 name, argv.size());
1038 }
1039
1040 std::vector<std::string> args;
1041 if (!ReadArgs(state, argv, &args)) {
1042 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1043 }
1044
1045 struct stat sb;
1046 if (lstat(args[0].c_str(), &sb) == -1) {
1047 return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", name,
1048 args[0].c_str(), strerror(errno));
1049 }
1050
1051 struct perm_parsed_args parsed = ParsePermArgs(state, args);
1052 int bad = 0;
1053 bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
1054
1055 if (recursive) {
1056 recursive_parsed_args = parsed;
1057 recursive_state = state;
1058 bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS);
1059 memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args));
1060 recursive_state = NULL;
1061 } else {
1062 bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed);
1063 }
1064
1065 if (bad > 0) {
1066 return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
1067 }
1068
1069 return StringValue("");
1070}
1071
Tianjie Xuc4447322017-03-06 14:44:59 -08001072Value* GetPropFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1073 if (argv.size() != 1) {
1074 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001075 }
1076 std::string key;
1077 if (!Evaluate(state, argv[0], &key)) {
1078 return nullptr;
1079 }
1080 std::string value = android::base::GetProperty(key, "");
Doug Zongker8edb00c2009-06-11 17:21:44 -07001081
Tao Bao039f2da2016-11-22 16:29:50 -08001082 return StringValue(value);
Doug Zongker8edb00c2009-06-11 17:21:44 -07001083}
1084
Doug Zongker47cace92009-06-18 10:11:50 -07001085// file_getprop(file, key)
1086//
1087// interprets 'file' as a getprop-style file (key=value pairs, one
Tao Bao51d516e2016-11-03 14:49:01 -07001088// per line. # comment lines, blank lines, lines without '=' ignored),
Michael Rungeaa1a31e2014-04-25 18:47:18 -07001089// and returns the value for 'key' (or "" if it isn't defined).
Tianjie Xu5419ad32018-02-02 16:49:15 -08001090Value* FileGetPropFn(const char* name, State* state,
1091 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -08001092 if (argv.size() != 2) {
1093 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1094 argv.size());
Tao Bao358c2ec2016-11-28 11:48:43 -08001095 }
1096
1097 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001098 if (!ReadArgs(state, argv, &args)) {
Tao Bao358c2ec2016-11-28 11:48:43 -08001099 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1100 }
1101 const std::string& filename = args[0];
1102 const std::string& key = args[1];
1103
Tianjie Xu22f11202018-08-27 10:50:31 -07001104 std::string buffer;
1105 if (!android::base::ReadFileToString(filename, &buffer)) {
1106 ErrorAbort(state, kFreadFailure, "%s: failed to read %s", name, filename.c_str());
Tao Bao358c2ec2016-11-28 11:48:43 -08001107 return nullptr;
1108 }
1109
Tao Bao358c2ec2016-11-28 11:48:43 -08001110 std::vector<std::string> lines = android::base::Split(buffer, "\n");
1111 for (size_t i = 0; i < lines.size(); i++) {
1112 std::string line = android::base::Trim(lines[i]);
1113
1114 // comment or blank line: skip to next line
1115 if (line.empty() || line[0] == '#') {
1116 continue;
1117 }
1118 size_t equal_pos = line.find('=');
1119 if (equal_pos == std::string::npos) {
1120 continue;
Doug Zongker47cace92009-06-18 10:11:50 -07001121 }
1122
Tao Bao358c2ec2016-11-28 11:48:43 -08001123 // trim whitespace between key and '='
1124 std::string str = android::base::Trim(line.substr(0, equal_pos));
Doug Zongker47cace92009-06-18 10:11:50 -07001125
Tao Bao358c2ec2016-11-28 11:48:43 -08001126 // not the key we're looking for
1127 if (key != str) continue;
Doug Zongker47cace92009-06-18 10:11:50 -07001128
Tao Bao358c2ec2016-11-28 11:48:43 -08001129 return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
1130 }
Doug Zongker47cace92009-06-18 10:11:50 -07001131
Tao Bao358c2ec2016-11-28 11:48:43 -08001132 return StringValue("");
Doug Zongker8edb00c2009-06-11 17:21:44 -07001133}
1134
Doug Zongker8edb00c2009-06-11 17:21:44 -07001135// apply_patch_space(bytes)
Tianjie Xu5419ad32018-02-02 16:49:15 -08001136Value* ApplyPatchSpaceFn(const char* name, State* state,
1137 const std::vector<std::unique_ptr<Expr>>& argv) {
Tianjie Xuc4447322017-03-06 14:44:59 -08001138 if (argv.size() != 1) {
1139 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 args, got %zu", name,
1140 argv.size());
1141 }
Tao Bao039f2da2016-11-22 16:29:50 -08001142 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001143 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001144 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1145 }
1146 const std::string& bytes_str = args[0];
Doug Zongkerc4351c72010-02-22 14:46:32 -08001147
Tao Bao039f2da2016-11-22 16:29:50 -08001148 size_t bytes;
1149 if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
Tianjie Xu5ad80282018-01-28 15:37:48 -08001150 return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count", name,
1151 bytes_str.c_str());
Tao Bao039f2da2016-11-22 16:29:50 -08001152 }
Doug Zongkerc4351c72010-02-22 14:46:32 -08001153
Tianjie Xu99b73be2017-11-28 17:23:06 -08001154 // Skip the cache size check if the update is a retry.
Tao Bao5ee25662018-07-11 15:55:32 -07001155 if (state->is_retry || CheckAndFreeSpaceOnCache(bytes)) {
Tianjie Xu99b73be2017-11-28 17:23:06 -08001156 return StringValue("t");
Tao Bao039f2da2016-11-22 16:29:50 -08001157 }
Tianjie Xu99b73be2017-11-28 17:23:06 -08001158 return StringValue("");
Doug Zongkerd9c9d102009-06-12 12:24:39 -07001159}
1160
Tianjie Xuc4447322017-03-06 14:44:59 -08001161Value* WipeCacheFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1162 if (!argv.empty()) {
1163 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
1164 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001165 }
1166 fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n");
1167 return StringValue("t");
Doug Zongkerd0181b82011-10-19 10:51:12 -07001168}
1169
Tianjie Xuc4447322017-03-06 14:44:59 -08001170Value* RunProgramFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1171 if (argv.size() < 1) {
Tao Bao039f2da2016-11-22 16:29:50 -08001172 return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
1173 }
Tianjie Xu5fe280a2016-10-17 18:15:20 -07001174
Tao Bao039f2da2016-11-22 16:29:50 -08001175 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001176 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001177 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1178 }
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001179
Tao Bao3d69f0d2018-12-20 09:44:06 -08001180 auto exec_args = StringVectorToNullTerminatedArray(args);
1181 LOG(INFO) << "about to run program [" << exec_args[0] << "] with " << argv.size() << " args";
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001182
Tao Bao039f2da2016-11-22 16:29:50 -08001183 pid_t child = fork();
1184 if (child == 0) {
Tao Bao3d69f0d2018-12-20 09:44:06 -08001185 execv(exec_args[0], exec_args.data());
Tao Bao039f2da2016-11-22 16:29:50 -08001186 PLOG(ERROR) << "run_program: execv failed";
Tao Bao3da88012017-02-03 13:09:23 -08001187 _exit(EXIT_FAILURE);
Tao Bao039f2da2016-11-22 16:29:50 -08001188 }
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001189
Tao Bao039f2da2016-11-22 16:29:50 -08001190 int status;
1191 waitpid(child, &status, 0);
1192 if (WIFEXITED(status)) {
1193 if (WEXITSTATUS(status) != 0) {
1194 LOG(ERROR) << "run_program: child exited with status " << WEXITSTATUS(status);
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001195 }
Tao Bao039f2da2016-11-22 16:29:50 -08001196 } else if (WIFSIGNALED(status)) {
1197 LOG(ERROR) << "run_program: child terminated by signal " << WTERMSIG(status);
1198 }
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001199
Tao Bao039f2da2016-11-22 16:29:50 -08001200 return StringValue(std::to_string(status));
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001201}
1202
Tao Bao511d7592018-06-19 15:56:49 -07001203// read_file(filename)
Tao Baobafd6c72018-07-09 15:08:50 -07001204// Reads a local file 'filename' and returns its contents as a string Value.
Tianjie Xuc4447322017-03-06 14:44:59 -08001205Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1206 if (argv.size() != 1) {
1207 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001208 }
Doug Zongker512536a2010-02-17 16:11:44 -08001209
Tao Bao039f2da2016-11-22 16:29:50 -08001210 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001211 if (!ReadArgs(state, argv, &args)) {
Tao Bao511d7592018-06-19 15:56:49 -07001212 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
Tao Bao039f2da2016-11-22 16:29:50 -08001213 }
1214 const std::string& filename = args[0];
Doug Zongker512536a2010-02-17 16:11:44 -08001215
Tao Baobafd6c72018-07-09 15:08:50 -07001216 std::string contents;
1217 if (android::base::ReadFileToString(filename, &contents)) {
1218 return new Value(Value::Type::STRING, std::move(contents));
Tao Bao039f2da2016-11-22 16:29:50 -08001219 }
Tao Bao511d7592018-06-19 15:56:49 -07001220
1221 // Leave it to caller to handle the failure.
Tao Baobafd6c72018-07-09 15:08:50 -07001222 PLOG(ERROR) << name << ": Failed to read " << filename;
Tao Bao511d7592018-06-19 15:56:49 -07001223 return StringValue("");
Doug Zongker512536a2010-02-17 16:11:44 -08001224}
Doug Zongker8edb00c2009-06-11 17:21:44 -07001225
Tao Bao1bf17722016-11-03 23:52:01 -07001226// write_value(value, filename)
1227// Writes 'value' to 'filename'.
1228// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
Tianjie Xuc4447322017-03-06 14:44:59 -08001229Value* WriteValueFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1230 if (argv.size() != 2) {
1231 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1232 argv.size());
Tao Baod0f30882016-11-03 23:52:01 -07001233 }
Tao Bao1bf17722016-11-03 23:52:01 -07001234
Tao Baod0f30882016-11-03 23:52:01 -07001235 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001236 if (!ReadArgs(state, argv, &args)) {
Tao Baod0f30882016-11-03 23:52:01 -07001237 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
1238 }
Tao Bao1bf17722016-11-03 23:52:01 -07001239
Tao Baod0f30882016-11-03 23:52:01 -07001240 const std::string& filename = args[1];
1241 if (filename.empty()) {
1242 return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
1243 }
Tao Bao1bf17722016-11-03 23:52:01 -07001244
Tao Baod0f30882016-11-03 23:52:01 -07001245 const std::string& value = args[0];
1246 if (!android::base::WriteStringToFile(value, filename)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001247 PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
Tao Baod0f30882016-11-03 23:52:01 -07001248 return StringValue("");
1249 } else {
1250 return StringValue("t");
1251 }
Tao Bao1bf17722016-11-03 23:52:01 -07001252}
1253
Doug Zongkerc87bab12013-11-25 13:53:25 -08001254// Immediately reboot the device. Recovery is not finished normally,
1255// so if you reboot into recovery it will re-start applying the
1256// current package (because nothing has cleared the copy of the
1257// arguments stored in the BCB).
1258//
1259// The argument is the partition name passed to the android reboot
1260// property. It can be "recovery" to boot from the recovery
1261// partition, or "" (empty string) to boot from the regular boot
1262// partition.
Tianjie Xuc4447322017-03-06 14:44:59 -08001263Value* RebootNowFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1264 if (argv.size() != 2) {
1265 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1266 argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001267 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001268
Tao Baobedf5fc2016-11-18 12:01:26 -08001269 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001270 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001271 return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
1272 }
1273 const std::string& filename = args[0];
1274 const std::string& property = args[1];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001275
Tao Baobedf5fc2016-11-18 12:01:26 -08001276 // Zero out the 'command' field of the bootloader message. Leave the rest intact.
1277 bootloader_message boot;
1278 std::string err;
1279 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001280 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001281 return StringValue("");
1282 }
1283 memset(boot.command, 0, sizeof(boot.command));
1284 if (!write_bootloader_message_to(boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001285 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001286 return StringValue("");
1287 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001288
Tao Bao2c526392018-05-03 23:01:13 -07001289 reboot("reboot," + property);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001290
Tao Baobedf5fc2016-11-18 12:01:26 -08001291 sleep(5);
1292 return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001293}
1294
1295// Store a string value somewhere that future invocations of recovery
1296// can access it. This value is called the "stage" and can be used to
1297// drive packages that need to do reboots in the middle of
1298// installation and keep track of where they are in the multi-stage
1299// install.
1300//
1301// The first argument is the block device for the misc partition
1302// ("/misc" in the fstab), which is where this value is stored. The
1303// second argument is the string to store; it should not exceed 31
1304// bytes.
Tianjie Xuc4447322017-03-06 14:44:59 -08001305Value* SetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1306 if (argv.size() != 2) {
1307 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1308 argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001309 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001310
Tao Baobedf5fc2016-11-18 12:01:26 -08001311 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001312 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001313 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1314 }
1315 const std::string& filename = args[0];
1316 const std::string& stagestr = args[1];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001317
Tao Baobedf5fc2016-11-18 12:01:26 -08001318 // Store this value in the misc partition, immediately after the
1319 // bootloader message that the main recovery uses to save its
1320 // arguments in case of the device restarting midway through
1321 // package installation.
1322 bootloader_message boot;
1323 std::string err;
1324 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001325 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001326 return StringValue("");
1327 }
1328 strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
1329 if (!write_bootloader_message_to(boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001330 LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001331 return StringValue("");
1332 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001333
Tao Baobedf5fc2016-11-18 12:01:26 -08001334 return StringValue(filename);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001335}
1336
1337// Return the value most recently saved with SetStageFn. The argument
1338// is the block device for the misc partition.
Tianjie Xuc4447322017-03-06 14:44:59 -08001339Value* GetStageFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1340 if (argv.size() != 1) {
1341 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
Tao Baobedf5fc2016-11-18 12:01:26 -08001342 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001343
Tao Baobedf5fc2016-11-18 12:01:26 -08001344 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001345 if (!ReadArgs(state, argv, &args)) {
Tao Baobedf5fc2016-11-18 12:01:26 -08001346 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1347 }
1348 const std::string& filename = args[0];
Doug Zongkerc87bab12013-11-25 13:53:25 -08001349
Tao Baobedf5fc2016-11-18 12:01:26 -08001350 bootloader_message boot;
1351 std::string err;
1352 if (!read_bootloader_message_from(&boot, filename, &err)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001353 LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
Tao Baobedf5fc2016-11-18 12:01:26 -08001354 return StringValue("");
1355 }
Doug Zongkerc87bab12013-11-25 13:53:25 -08001356
Tao Baobedf5fc2016-11-18 12:01:26 -08001357 return StringValue(boot.stage);
Doug Zongkerc87bab12013-11-25 13:53:25 -08001358}
1359
Tianjie Xuc4447322017-03-06 14:44:59 -08001360Value* WipeBlockDeviceFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1361 if (argv.size() != 2) {
1362 return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %zu", name,
1363 argv.size());
Tao Bao358c2ec2016-11-28 11:48:43 -08001364 }
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001365
Tao Bao358c2ec2016-11-28 11:48:43 -08001366 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001367 if (!ReadArgs(state, argv, &args)) {
Tao Bao358c2ec2016-11-28 11:48:43 -08001368 return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
1369 }
1370 const std::string& filename = args[0];
1371 const std::string& len_str = args[1];
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001372
Tao Bao358c2ec2016-11-28 11:48:43 -08001373 size_t len;
1374 if (!android::base::ParseUint(len_str.c_str(), &len)) {
1375 return nullptr;
1376 }
Tianjie Xu22f11202018-08-27 10:50:31 -07001377 android::base::unique_fd fd(open(filename.c_str(), O_WRONLY));
1378 if (fd == -1) {
1379 PLOG(ERROR) << "Failed to open " << filename;
1380 return StringValue("");
1381 }
1382
Tao Bao358c2ec2016-11-28 11:48:43 -08001383 // The wipe_block_device function in ext4_utils returns 0 on success and 1
1384 // for failure.
1385 int status = wipe_block_device(fd, len);
1386 return StringValue((status == 0) ? "t" : "");
Doug Zongkerc9d6e4f2014-02-24 16:02:50 -08001387}
1388
Tianjie Xuc4447322017-03-06 14:44:59 -08001389Value* EnableRebootFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
1390 if (!argv.empty()) {
1391 return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %zu", name,
1392 argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001393 }
1394 UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
1395 fprintf(ui->cmd_pipe, "enable_reboot\n");
1396 return StringValue("t");
Doug Zongkerc704e062014-05-23 08:40:35 -07001397}
1398
Tianjie Xuc4447322017-03-06 14:44:59 -08001399Value* Tune2FsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
Ethan Yonker7e1b9862015-03-19 14:10:01 -05001400#ifdef HAVE_LIBTUNE2FS
Tianjie Xuc4447322017-03-06 14:44:59 -08001401 if (argv.empty()) {
1402 return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %zu", name, argv.size());
Tao Bao039f2da2016-11-22 16:29:50 -08001403 }
Michael Rungeb278c252014-11-21 00:12:28 -08001404
Tao Bao039f2da2016-11-22 16:29:50 -08001405 std::vector<std::string> args;
Tianjie Xuc4447322017-03-06 14:44:59 -08001406 if (!ReadArgs(state, argv, &args)) {
Tao Bao039f2da2016-11-22 16:29:50 -08001407 return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
1408 }
Michael Rungeb278c252014-11-21 00:12:28 -08001409
Tao Bao3d69f0d2018-12-20 09:44:06 -08001410 // tune2fs expects the program name as its first arg.
1411 args.insert(args.begin(), "tune2fs");
1412 auto tune2fs_args = StringVectorToNullTerminatedArray(args);
Michael Rungeb278c252014-11-21 00:12:28 -08001413
Tao Bao3d69f0d2018-12-20 09:44:06 -08001414 // tune2fs changes the filesystem parameters on an ext2 filesystem; it returns 0 on success.
1415 if (auto result = tune2fs_main(tune2fs_args.size() - 1, tune2fs_args.data()); result != 0) {
Tao Bao039f2da2016-11-22 16:29:50 -08001416 return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
1417 }
1418 return StringValue("t");
Ethan Yonker7e1b9862015-03-19 14:10:01 -05001419#else
Ethan Yonker8373cfe2017-09-08 06:50:54 -05001420 return ErrorAbort(state, kTune2FsFailure, "%s() support not present, no libtune2fs", name);
Ethan Yonker7e1b9862015-03-19 14:10:01 -05001421#endif // HAVE_LIBTUNE2FS
Michael Rungeb278c252014-11-21 00:12:28 -08001422}
1423
Doug Zongker9931f7f2009-06-10 14:11:53 -07001424void RegisterInstallFunctions() {
Tao Bao039f2da2016-11-22 16:29:50 -08001425 RegisterFunction("mount", MountFn);
1426 RegisterFunction("is_mounted", IsMountedFn);
1427 RegisterFunction("unmount", UnmountFn);
1428 RegisterFunction("format", FormatFn);
1429 RegisterFunction("show_progress", ShowProgressFn);
1430 RegisterFunction("set_progress", SetProgressFn);
Tom Marshallbf4f24f2017-08-23 18:14:00 +00001431 RegisterFunction("delete", DeleteFn);
1432 RegisterFunction("delete_recursive", DeleteFn);
Tom Marshall981118e2017-10-25 20:27:08 +02001433 RegisterFunction("package_extract_dir", PackageExtractDirFn);
Tao Bao039f2da2016-11-22 16:29:50 -08001434 RegisterFunction("package_extract_file", PackageExtractFileFn);
Tom Marshallbf4f24f2017-08-23 18:14:00 +00001435 RegisterFunction("symlink", SymlinkFn);
1436
1437 // Usage:
1438 // set_metadata("filename", "key1", "value1", "key2", "value2", ...)
1439 // Example:
1440 // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel",
1441 // "u:object_r:system_file:s0", "capabilities", 0x0);
1442 RegisterFunction("set_metadata", SetMetadataFn);
1443
1444 // Usage:
1445 // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
1446 // Example:
1447 // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755,
1448 // "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
1449 RegisterFunction("set_metadata_recursive", SetMetadataFn);
Nick Kralevich5dbdef02013-09-07 14:41:06 -07001450
Tao Bao039f2da2016-11-22 16:29:50 -08001451 RegisterFunction("getprop", GetPropFn);
1452 RegisterFunction("file_getprop", FileGetPropFn);
Nick Kralevich5dbdef02013-09-07 14:41:06 -07001453
Tao Bao039f2da2016-11-22 16:29:50 -08001454 RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
Tao Bao5609bc82018-06-20 00:30:48 -07001455 RegisterFunction("patch_partition", PatchPartitionFn);
1456 RegisterFunction("patch_partition_check", PatchPartitionCheckFn);
Nick Kralevich5dbdef02013-09-07 14:41:06 -07001457
Tao Bao039f2da2016-11-22 16:29:50 -08001458 RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
Doug Zongker8edb00c2009-06-11 17:21:44 -07001459
Tao Bao039f2da2016-11-22 16:29:50 -08001460 RegisterFunction("read_file", ReadFileFn);
bigbiff26d5d5f2020-03-23 09:56:16 -04001461<<<<<<< HEAD
Tao Bao039f2da2016-11-22 16:29:50 -08001462 RegisterFunction("sha1_check", Sha1CheckFn);
Tom Marshallbf4f24f2017-08-23 18:14:00 +00001463 RegisterFunction("rename", RenameFn);
bigbiff26d5d5f2020-03-23 09:56:16 -04001464=======
1465>>>>>>> android-10.0.0_r25
Tao Bao039f2da2016-11-22 16:29:50 -08001466 RegisterFunction("write_value", WriteValueFn);
Doug Zongkerd9c9d102009-06-12 12:24:39 -07001467
Tao Bao039f2da2016-11-22 16:29:50 -08001468 RegisterFunction("wipe_cache", WipeCacheFn);
Doug Zongker52b40362014-02-10 15:30:30 -08001469
Tao Bao039f2da2016-11-22 16:29:50 -08001470 RegisterFunction("ui_print", UIPrintFn);
Doug Zongker512536a2010-02-17 16:11:44 -08001471
Tao Bao039f2da2016-11-22 16:29:50 -08001472 RegisterFunction("run_program", RunProgramFn);
Doug Zongkerd0181b82011-10-19 10:51:12 -07001473
Tao Bao039f2da2016-11-22 16:29:50 -08001474 RegisterFunction("reboot_now", RebootNowFn);
1475 RegisterFunction("get_stage", GetStageFn);
1476 RegisterFunction("set_stage", SetStageFn);
Doug Zongkera3f89ea2009-09-10 14:10:48 -07001477
Tao Bao039f2da2016-11-22 16:29:50 -08001478 RegisterFunction("enable_reboot", EnableRebootFn);
1479 RegisterFunction("tune2fs", Tune2FsFn);
Doug Zongker9931f7f2009-06-10 14:11:53 -07001480}