diff options
Diffstat (limited to 'updater/install.cpp')
-rw-r--r-- | updater/install.cpp | 207 |
1 files changed, 119 insertions, 88 deletions
diff --git a/updater/install.cpp b/updater/install.cpp index b885f864e..b9bc19e2c 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,28 +454,32 @@ 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, ×tamp, sehandle); + bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle); - return StringValue(success ? "t" : ""); + return StringValue(success ? "t" : ""); } // package_extract_file(package_file[, dest_file]) @@ -861,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 @@ -1155,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 @@ -1165,31 +1196,35 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) { // partition, or "" (empty string) to boot from the regular boot // partition. Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + 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[0]; - const std::string& property = args[1]; - - // zero out the 'command' field of the bootloader message. - char buffer[80]; - memset(buffer, 0, sizeof(((struct bootloader_message*)0)->command)); - FILE* f = ota_fopen(filename.c_str(), "r+b"); - fseek(f, offsetof(struct bootloader_message, command), SEEK_SET); - ota_fwrite(buffer, sizeof(((struct bootloader_message*)0)->command), 1, f); - ota_fclose(f); + 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[0]; + const std::string& property = args[1]; + + // Zero out the 'command' field of the bootloader message. Leave the rest intact. + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } + memset(boot.command, 0, sizeof(boot.command)); + if (!write_bootloader_message_to(boot, filename, &err)) { + printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - std::string reboot_cmd = "reboot,"; - reboot_cmd += property; - android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); + const std::string reboot_cmd = "reboot," + property; + android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd); - sleep(5); - return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); + sleep(5); + return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name); } // Store a string value somewhere that future invocations of recovery @@ -1203,62 +1238,57 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) { // second argument is the string to store; it should not exceed 31 // bytes. Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } + 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[0]; - std::string& stagestr = args[1]; - - // Store this value in the misc partition, immediately after the - // bootloader message that the main recovery uses to save its - // arguments in case of the device restarting midway through - // package installation. - FILE* f = ota_fopen(filename.c_str(), "r+b"); - fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - size_t to_write = stagestr.size(); - size_t max_size = sizeof(((struct bootloader_message*)0)->stage); - if (to_write > max_size) { - to_write = max_size; - stagestr = stagestr.substr(0, max_size-1); - } - size_t status = ota_fwrite(stagestr.c_str(), to_write, 1, f); - ota_fclose(f); + 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[0]; + const std::string& stagestr = args[1]; + + // Store this value in the misc partition, immediately after the + // bootloader message that the main recovery uses to save its + // arguments in case of the device restarting midway through + // package installation. + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } + strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage)); + if (!write_bootloader_message_to(boot, filename, &err)) { + printf("%s(): Failed to write to \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - if (status != to_write) { - return StringValue(""); - } - return StringValue(filename); + return StringValue(filename); } // Return the value most recently saved with SetStageFn. The argument // is the block device for the misc partition. Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); - } + if (argc != 1) { + return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); + } - std::vector<std::string> args; - if (!ReadArgs(state, 1, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& filename = args[0]; + std::vector<std::string> args; + if (!ReadArgs(state, 1, argv, &args)) { + return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); + } + const std::string& filename = args[0]; - char buffer[sizeof(((struct bootloader_message*)0)->stage)]; - FILE* f = ota_fopen(filename.c_str(), "rb"); - fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); - size_t status = ota_fread(buffer, sizeof(buffer), 1, f); - ota_fclose(f); - if (status != sizeof(buffer)) { - return StringValue(""); - } + bootloader_message boot; + std::string err; + if (!read_bootloader_message_from(&boot, filename, &err)) { + printf("%s(): Failed to read from \"%s\": %s", name, filename.c_str(), err.c_str()); + return StringValue(""); + } - buffer[sizeof(buffer)-1] = '\0'; - return StringValue(buffer); + return StringValue(boot.stage); } Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { @@ -1363,6 +1393,7 @@ void RegisterInstallFunctions() { RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); RegisterFunction("rename", RenameFn); + RegisterFunction("write_value", WriteValueFn); RegisterFunction("wipe_cache", WipeCacheFn); |