Avoid crashing recovery with unwritable /cache.
When /cache is unwritable, recovery hits a crash loop. Because it passes nullptr to fileno(3) when writing back the locale file. This prevents user from recovering a device - it cannot boot far enough to recovery menu which allows wiping /cache. Bug: 63927337 Test: Corrupt /cache and boot into recovery on bullhead: 1. m -j recoveryimage 2. fastboot erase cache 3. fastboot boot $OUT/recovery.img 4. recovery menu shows up. Change-Id: I1407743f802049eb48add56a36298b665cb86139
This commit is contained in:
parent
f7c00ddaf6
commit
ec57903a7e
1 changed files with 24 additions and 26 deletions
50
recovery.cpp
50
recovery.cpp
|
@ -477,40 +477,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, "we");
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue