diff options
Diffstat (limited to 'recovery.cpp')
-rw-r--r-- | recovery.cpp | 155 |
1 files changed, 75 insertions, 80 deletions
diff --git a/recovery.cpp b/recovery.cpp index 122b89d0b..6f62ff17c 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -53,6 +53,7 @@ #include <healthd/BatteryMonitor.h> #include <private/android_logger.h> /* private pmsg functions */ #include <private/android_filesystem_config.h> /* for AID_SYSTEM */ +#include <selinux/android.h> #include <selinux/label.h> #include <selinux/selinux.h> #include <ziparchive/zip_archive.h> @@ -178,19 +179,19 @@ struct selabel_handle* sehandle; * 7b. the user reboots (pulling the battery, etc) into the main system */ -// open a given path, mounting partitions as necessary -FILE* fopen_path(const char *path, const char *mode) { - if (ensure_path_mounted(path) != 0) { - LOG(ERROR) << "Can't mount " << path; - return NULL; - } - - // When writing, try to create the containing directory, if necessary. - // Use generous permissions, the system (init.rc) will reset them. - if (strchr("wa", mode[0])) dirCreateHierarchy(path, 0777, NULL, 1, sehandle); +// Open a given path, mounting partitions as necessary. +FILE* fopen_path(const char* path, const char* mode) { + if (ensure_path_mounted(path) != 0) { + LOG(ERROR) << "Can't mount " << path; + return nullptr; + } - FILE *fp = fopen(path, mode); - return fp; + // When writing, try to create the containing directory, if necessary. Use generous permissions, + // the system (init.rc) will reset them. + if (strchr("wa", mode[0])) { + mkdir_recursively(path, 0777, true, sehandle); + } + return fopen(path, mode); } // close a file, log an error if the error indicator is set @@ -249,7 +250,7 @@ static void redirect_stdio(const char* filename) { auto start = std::chrono::steady_clock::now(); // Child logger to actually write to the log file. - FILE* log_fp = fopen(filename, "a"); + FILE* log_fp = fopen(filename, "ae"); if (log_fp == nullptr) { PLOG(ERROR) << "fopen \"" << filename << "\" failed"; close(pipefd[0]); @@ -418,27 +419,27 @@ static void copy_log_file_to_pmsg(const char* source, const char* destination) { static off_t tmplog_offset = 0; static void copy_log_file(const char* source, const char* destination, bool append) { - FILE* dest_fp = fopen_path(destination, append ? "a" : "w"); - if (dest_fp == nullptr) { - PLOG(ERROR) << "Can't open " << destination; - } else { - FILE* source_fp = fopen(source, "r"); - if (source_fp != nullptr) { - if (append) { - fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write - } - char buf[4096]; - size_t bytes; - while ((bytes = fread(buf, 1, sizeof(buf), source_fp)) != 0) { - fwrite(buf, 1, bytes, dest_fp); - } - if (append) { - tmplog_offset = ftello(source_fp); - } - check_and_fclose(source_fp, source); - } - check_and_fclose(dest_fp, destination); + FILE* dest_fp = fopen_path(destination, append ? "ae" : "we"); + if (dest_fp == nullptr) { + PLOG(ERROR) << "Can't open " << destination; + } else { + FILE* source_fp = fopen(source, "re"); + if (source_fp != nullptr) { + if (append) { + fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write + } + char buf[4096]; + size_t bytes; + while ((bytes = fread(buf, 1, sizeof(buf), source_fp)) != 0) { + fwrite(buf, 1, bytes, dest_fp); + } + if (append) { + tmplog_offset = ftello(source_fp); + } + check_and_fclose(source_fp, source); } + check_and_fclose(dest_fp, destination); + } } static void copy_logs() { @@ -477,40 +478,38 @@ static void copy_logs() { sync(); } -// clear the recovery command and prepare to boot a (hopefully working) system, +// Clear the recovery command and prepare to boot a (hopefully working) system, // copy our log file to cache as well (for the system to read). This function is // idempotent: call it as many times as you like. static void finish_recovery() { - // Save the locale to cache, so if recovery is next started up - // without a --locale argument (eg, directly from the bootloader) - // it will use the last-known locale. - if (!locale.empty() && has_cache) { - LOG(INFO) << "Saving locale \"" << locale << "\""; - - FILE* fp = fopen_path(LOCALE_FILE, "w"); - if (!android::base::WriteStringToFd(locale, fileno(fp))) { - PLOG(ERROR) << "Failed to save locale to " << LOCALE_FILE; - } - check_and_fclose(fp, LOCALE_FILE); + // Save the locale to cache, so if recovery is next started up without a '--locale' argument + // (e.g., directly from the bootloader) it will use the last-known locale. + if (!locale.empty() && has_cache) { + LOG(INFO) << "Saving locale \"" << locale << "\""; + if (ensure_path_mounted(LOCALE_FILE) != 0) { + LOG(ERROR) << "Failed to mount " << LOCALE_FILE; + } else if (!android::base::WriteStringToFile(locale, LOCALE_FILE)) { + PLOG(ERROR) << "Failed to save locale to " << LOCALE_FILE; } + } - copy_logs(); + copy_logs(); - // Reset to normal system boot so recovery won't cycle indefinitely. - std::string err; - if (!clear_bootloader_message(&err)) { - LOG(ERROR) << "Failed to clear BCB message: " << err; - } + // Reset to normal system boot so recovery won't cycle indefinitely. + std::string err; + if (!clear_bootloader_message(&err)) { + LOG(ERROR) << "Failed to clear BCB message: " << err; + } - // Remove the command file, so recovery won't repeat indefinitely. - if (has_cache) { - if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { - LOG(WARNING) << "Can't unlink " << COMMAND_FILE; - } - ensure_path_unmounted(CACHE_ROOT); + // Remove the command file, so recovery won't repeat indefinitely. + if (has_cache) { + if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { + LOG(WARNING) << "Can't unlink " << COMMAND_FILE; } + ensure_path_unmounted(CACHE_ROOT); + } - sync(); // For good measure. + sync(); // For good measure. } struct saved_log_file { @@ -551,7 +550,7 @@ static bool erase_volume(const char* volume) { } std::string data(sb.st_size, '\0'); - FILE* f = fopen(path.c_str(), "rb"); + FILE* f = fopen(path.c_str(), "rbe"); fread(&data[0], 1, data.size(), f); fclose(f); @@ -579,7 +578,7 @@ static bool erase_volume(const char* volume) { ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno)); return true; } - FILE* f = fopen(CONVERT_FBE_FILE, "wb"); + FILE* f = fopen(CONVERT_FBE_FILE, "wbe"); if (!f) { ui->Print("Failed to convert to file encryption %s\n", strerror(errno)); return true; @@ -595,7 +594,7 @@ static bool erase_volume(const char* volume) { if (is_cache) { // Re-create the log dir and write back the log entries. if (ensure_path_mounted(CACHE_LOG_DIR) == 0 && - dirCreateHierarchy(CACHE_LOG_DIR, 0777, nullptr, false, sehandle) == 0) { + mkdir_recursively(CACHE_LOG_DIR, 0777, false, sehandle) == 0) { for (const auto& log : log_files) { if (!android::base::WriteStringToFile(log.data, log.name, log.sb.st_mode, log.sb.st_uid, log.sb.st_gid)) { @@ -759,12 +758,13 @@ static bool wipe_data(Device* device) { } static bool prompt_and_wipe_data(Device* device) { + // Use a single string and let ScreenRecoveryUI handles the wrapping. const char* const headers[] = { - "Can't load Android system. Your data may be corrupt.", - "If you continue to get this message, you may need to", - "perform a factory data reset and erase all user data", + "Can't load Android system. Your data may be corrupt. " + "If you continue to get this message, you may need to " + "perform a factory data reset and erase all user data " "stored on this device.", - NULL + nullptr }; const char* const items[] = { "Try again", @@ -1481,12 +1481,8 @@ int main(int argc, char **argv) { ui->SetBackground(RecoveryUI::NONE); if (show_text) ui->ShowText(true); - struct selinux_opt seopts[] = { - { SELABEL_OPT_PATH, "/file_contexts" } - }; - - sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); - + sehandle = selinux_android_file_context_handle(); + selinux_android_set_sehandle(sehandle); if (!sehandle) { ui->Print("Warning: No file_contexts\n"); } @@ -1596,15 +1592,14 @@ int main(int argc, char **argv) { ui->Print("Rebooting automatically.\n"); } } else if (!just_exit) { - status = INSTALL_NONE; // No command specified - ui->SetBackground(RecoveryUI::NO_COMMAND); - - // http://b/17489952 - // If this is an eng or userdebug build, automatically turn on the - // text display if no command is specified. - if (is_ro_debuggable()) { - ui->ShowText(true); - } + // If this is an eng or userdebug build, automatically turn on the text display if no command + // is specified. Note that this should be called before setting the background to avoid + // flickering the background image. + if (is_ro_debuggable()) { + ui->ShowText(true); + } + status = INSTALL_NONE; // No command specified + ui->SetBackground(RecoveryUI::NO_COMMAND); } if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) { |