summaryrefslogtreecommitdiffstats
path: root/updater/install.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'updater/install.cpp')
-rw-r--r--updater/install.cpp217
1 files changed, 121 insertions, 96 deletions
diff --git a/updater/install.cpp b/updater/install.cpp
index 59c54dd4c..6c110732a 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -39,11 +39,12 @@
#include <string>
#include <vector>
-#include <android-base/parseint.h>
+#include <android-base/file.h>
#include <android-base/parsedouble.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
-#include <android-base/strings.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <ext4_utils/make_ext4fs.h>
#include <ext4_utils/wipe.h>
@@ -453,117 +454,114 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(frac_str);
}
-// package_extract_dir(package_path, destination_path)
-Value* PackageExtractDirFn(const char* name, State* state,
- int argc, Expr* argv[]) {
- if (argc != 2) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
- }
+// package_extract_dir(package_dir, dest_dir)
+// Extracts all files from the package underneath package_dir and writes them to the
+// corresponding tree beneath dest_dir. Any existing files are overwritten.
+// Example: package_extract_dir("system", "/system")
+//
+// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
+Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) {
+ if (argc != 2) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
+ }
- std::vector<std::string> args;
- if (!ReadArgs(state, 2, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
- }
- const std::string& zip_path = args[0];
- const std::string& dest_path = args[1];
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 2, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
+ }
+ const std::string& zip_path = args[0];
+ const std::string& dest_path = args[1];
- ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip;
+ ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
- // To create a consistent system image, never use the clock for timestamps.
- struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
+ // To create a consistent system image, never use the clock for timestamps.
+ constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
- bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
+ bool success = ExtractPackageRecursive(za, zip_path, dest_path, &timestamp, sehandle);
- return StringValue(success ? "t" : "");
+ return StringValue(success ? "t" : "");
}
+// package_extract_file(package_file[, dest_file])
+// Extracts a single package_file from the update package and writes it to dest_file,
+// overwriting existing files if necessary. Without the dest_file argument, returns the
+// contents of the package file as a binary blob.
+Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) {
+ if (argc < 1 || argc > 2) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc);
+ }
-// package_extract_file(package_path, destination_path)
-// or
-// package_extract_file(package_path)
-// to return the entire contents of the file as the result of this
-// function (the char* returned is actually a FileContents*).
-Value* PackageExtractFileFn(const char* name, State* state,
- int argc, Expr* argv[]) {
- if (argc < 1 || argc > 2) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d",
- name, argc);
- }
- bool success = false;
-
- if (argc == 2) {
- // The two-argument version extracts to a file.
+ if (argc == 2) {
+ // The two-argument version extracts to a file.
- ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip;
-
- std::vector<std::string> args;
- if (!ReadArgs(state, 2, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name,
- argc);
- }
- const std::string& zip_path = args[0];
- const std::string& dest_path = args[1];
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 2, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc);
+ }
+ const std::string& zip_path = args[0];
+ const std::string& dest_path = args[1];
- ZipString zip_string_path(zip_path.c_str());
- ZipEntry entry;
- if (FindEntry(za, zip_string_path, &entry) != 0) {
- printf("%s: no %s in package\n", name, zip_path.c_str());
- return StringValue("");
- }
+ ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
+ ZipString zip_string_path(zip_path.c_str());
+ ZipEntry entry;
+ if (FindEntry(za, zip_string_path, &entry) != 0) {
+ printf("%s: no %s in package\n", name, zip_path.c_str());
+ return StringValue("");
+ }
- int fd = TEMP_FAILURE_RETRY(ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR));
- if (fd == -1) {
- printf("%s: can't open %s for write: %s\n", name, dest_path.c_str(), strerror(errno));
- return StringValue("");
- }
- success = ExtractEntryToFile(za, &entry, fd);
- if (ota_fsync(fd) == -1) {
- printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno));
- success = false;
- }
- if (ota_close(fd) == -1) {
- printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno));
- success = false;
- }
+ int fd = TEMP_FAILURE_RETRY(
+ ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
+ if (fd == -1) {
+ printf("%s: can't open %s for write: %s\n", name, dest_path.c_str(), strerror(errno));
+ return StringValue("");
+ }
- return StringValue(success ? "t" : "");
- } else {
- // The one-argument version returns the contents of the file
- // as the result.
+ bool success = true;
+ int32_t ret = ExtractEntryToFile(za, &entry, fd);
+ if (ret != 0) {
+ printf("%s: Failed to extract entry \"%s\" (%u bytes) to \"%s\": %s\n", name,
+ zip_path.c_str(), entry.uncompressed_length, dest_path.c_str(), ErrorCodeString(ret));
+ success = false;
+ }
+ if (ota_fsync(fd) == -1) {
+ printf("fsync of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno));
+ success = false;
+ }
+ if (ota_close(fd) == -1) {
+ printf("close of \"%s\" failed: %s\n", dest_path.c_str(), strerror(errno));
+ success = false;
+ }
- std::vector<std::string> args;
- if (!ReadArgs(state, 1, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name,
- argc);
- }
- const std::string& zip_path = args[0];
+ return StringValue(success ? "t" : "");
+ } else {
+ // The one-argument version returns the contents of the file as the result.
- Value* v = new Value(VAL_INVALID, "");
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 1, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc);
+ }
+ const std::string& zip_path = args[0];
- ZipArchiveHandle za = ((UpdaterInfo*)(state->cookie))->package_zip;
- ZipString zip_string_path(zip_path.c_str());
- ZipEntry entry;
- if (FindEntry(za, zip_string_path, &entry) != 0) {
- printf("%s: no %s in package\n", name, zip_path.c_str());
- return v;
- }
+ ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
+ ZipString zip_string_path(zip_path.c_str());
+ ZipEntry entry;
+ if (FindEntry(za, zip_string_path, &entry) != 0) {
+ return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
+ zip_path.c_str());
+ }
- v->data.resize(entry.uncompressed_length);
- if (ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&v->data[0]),
- v->data.size()) != 0) {
- printf("%s: faled to extract %zu bytes to memory\n", name, v->data.size());
- } else {
- success = true;
- }
+ std::string buffer;
+ buffer.resize(entry.uncompressed_length);
- if (!success) {
- v->data.clear();
- } else {
- v->type = VAL_BLOB;
- }
- return v;
+ int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
+ if (ret != 0) {
+ return ErrorAbort(state, kPackageExtractFileFailure,
+ "%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
+ zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
}
+
+ return new Value(VAL_BLOB, buffer);
+ }
}
// symlink(target, [src1, src2, ...])
@@ -868,7 +866,6 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(value);
}
-
// file_getprop(file, key)
//
// interprets 'file' as a getprop-style file (key=value pairs, one
@@ -1162,6 +1159,33 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
return v;
}
+// write_value(value, filename)
+// Writes 'value' to 'filename'.
+// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
+Value* WriteValueFn(const char* name, State* state, int argc, Expr* argv[]) {
+ if (argc != 2) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
+ }
+
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 2, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
+ }
+
+ const std::string& filename = args[1];
+ if (filename.empty()) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
+ }
+
+ const std::string& value = args[0];
+ if (!android::base::WriteStringToFile(value, filename)) {
+ printf("%s: Failed to write to \"%s\": %s\n", name, filename.c_str(), strerror(errno));
+ return StringValue("");
+ } else {
+ return StringValue("t");
+ }
+}
+
// Immediately reboot the device. Recovery is not finished normally,
// so if you reboot into recovery it will re-start applying the
// current package (because nothing has cleared the copy of the
@@ -1370,6 +1394,7 @@ void RegisterInstallFunctions() {
RegisterFunction("read_file", ReadFileFn);
RegisterFunction("sha1_check", Sha1CheckFn);
RegisterFunction("rename", RenameFn);
+ RegisterFunction("write_value", WriteValueFn);
RegisterFunction("wipe_cache", WipeCacheFn);