Merge "recovery: Clean up the log saving while wiping."
am: 28bbe029b6
Change-Id: I0dfd2815874940624bbee2e02a506549fc68e070
This commit is contained in:
commit
7294a8830b
1 changed files with 86 additions and 96 deletions
182
recovery.cpp
182
recovery.cpp
|
@ -512,117 +512,107 @@ static void finish_recovery() {
|
||||||
sync(); // For good measure.
|
sync(); // For good measure.
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _saved_log_file {
|
struct saved_log_file {
|
||||||
char* name;
|
std::string name;
|
||||||
struct stat st;
|
struct stat sb;
|
||||||
unsigned char* data;
|
std::string data;
|
||||||
struct _saved_log_file* next;
|
};
|
||||||
} saved_log_file;
|
|
||||||
|
|
||||||
static bool erase_volume(const char* volume) {
|
static bool erase_volume(const char* volume) {
|
||||||
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
|
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
|
||||||
bool is_data = (strcmp(volume, DATA_ROOT) == 0);
|
bool is_data = (strcmp(volume, DATA_ROOT) == 0);
|
||||||
|
|
||||||
ui->SetBackground(RecoveryUI::ERASING);
|
ui->SetBackground(RecoveryUI::ERASING);
|
||||||
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
||||||
|
|
||||||
saved_log_file* head = NULL;
|
std::vector<saved_log_file> log_files;
|
||||||
|
|
||||||
if (is_cache) {
|
if (is_cache) {
|
||||||
// If we're reformatting /cache, we load any past logs
|
// If we're reformatting /cache, we load any past logs
|
||||||
// (i.e. "/cache/recovery/last_*") and the current log
|
// (i.e. "/cache/recovery/last_*") and the current log
|
||||||
// ("/cache/recovery/log") into memory, so we can restore them after
|
// ("/cache/recovery/log") into memory, so we can restore them after
|
||||||
// the reformat.
|
// the reformat.
|
||||||
|
|
||||||
ensure_path_mounted(volume);
|
ensure_path_mounted(volume);
|
||||||
|
|
||||||
DIR* d;
|
struct dirent* de;
|
||||||
struct dirent* de;
|
std::unique_ptr<DIR, decltype(&closedir)> d(opendir(CACHE_LOG_DIR), closedir);
|
||||||
d = opendir(CACHE_LOG_DIR);
|
if (d) {
|
||||||
if (d) {
|
while ((de = readdir(d.get())) != nullptr) {
|
||||||
char path[PATH_MAX];
|
if (strncmp(de->d_name, "last_", 5) == 0 || strcmp(de->d_name, "log") == 0) {
|
||||||
strcpy(path, CACHE_LOG_DIR);
|
std::string path = android::base::StringPrintf("%s/%s", CACHE_LOG_DIR, de->d_name);
|
||||||
strcat(path, "/");
|
|
||||||
int path_len = strlen(path);
|
struct stat sb;
|
||||||
while ((de = readdir(d)) != NULL) {
|
if (stat(path.c_str(), &sb) == 0) {
|
||||||
if (strncmp(de->d_name, "last_", 5) == 0 || strcmp(de->d_name, "log") == 0) {
|
// truncate files to 512kb
|
||||||
saved_log_file* p = (saved_log_file*) malloc(sizeof(saved_log_file));
|
if (sb.st_size > (1 << 19)) {
|
||||||
strcpy(path+path_len, de->d_name);
|
sb.st_size = 1 << 19;
|
||||||
p->name = strdup(path);
|
|
||||||
if (stat(path, &(p->st)) == 0) {
|
|
||||||
// truncate files to 512kb
|
|
||||||
if (p->st.st_size > (1 << 19)) {
|
|
||||||
p->st.st_size = 1 << 19;
|
|
||||||
}
|
|
||||||
p->data = (unsigned char*) malloc(p->st.st_size);
|
|
||||||
FILE* f = fopen(path, "rb");
|
|
||||||
fread(p->data, 1, p->st.st_size, f);
|
|
||||||
fclose(f);
|
|
||||||
p->next = head;
|
|
||||||
head = p;
|
|
||||||
} else {
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(d);
|
|
||||||
} else {
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
printf("opendir failed: %s\n", strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string data(sb.st_size, '\0');
|
||||||
|
FILE* f = fopen(path.c_str(), "rb");
|
||||||
|
fread(&data[0], 1, data.size(), f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
log_files.emplace_back(saved_log_file{ path, sb, data });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->Print("Formatting %s...\n", volume);
|
|
||||||
|
|
||||||
ensure_path_unmounted(volume);
|
|
||||||
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (is_data && reason && strcmp(reason, "convert_fbe") == 0) {
|
|
||||||
// Create convert_fbe breadcrumb file to signal to init
|
|
||||||
// to convert to file based encryption, not full disk encryption
|
|
||||||
if (mkdir(CONVERT_FBE_DIR, 0700) != 0) {
|
|
||||||
ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
FILE* f = fopen(CONVERT_FBE_FILE, "wb");
|
|
||||||
if (!f) {
|
|
||||||
ui->Print("Failed to convert to file encryption %s\n", strerror(errno));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
result = format_volume(volume, CONVERT_FBE_DIR);
|
|
||||||
remove(CONVERT_FBE_FILE);
|
|
||||||
rmdir(CONVERT_FBE_DIR);
|
|
||||||
} else {
|
} else {
|
||||||
result = format_volume(volume);
|
if (errno != ENOENT) {
|
||||||
|
PLOG(ERROR) << "Failed to opendir " << CACHE_LOG_DIR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is_cache) {
|
ui->Print("Formatting %s...\n", volume);
|
||||||
while (head) {
|
|
||||||
FILE* f = fopen_path(head->name, "wb");
|
ensure_path_unmounted(volume);
|
||||||
if (f) {
|
|
||||||
fwrite(head->data, 1, head->st.st_size, f);
|
int result;
|
||||||
fclose(f);
|
|
||||||
chmod(head->name, head->st.st_mode);
|
if (is_data && reason && strcmp(reason, "convert_fbe") == 0) {
|
||||||
chown(head->name, head->st.st_uid, head->st.st_gid);
|
// Create convert_fbe breadcrumb file to signal to init
|
||||||
}
|
// to convert to file based encryption, not full disk encryption
|
||||||
free(head->name);
|
if (mkdir(CONVERT_FBE_DIR, 0700) != 0) {
|
||||||
free(head->data);
|
ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno));
|
||||||
saved_log_file* temp = head->next;
|
return true;
|
||||||
free(head);
|
}
|
||||||
head = temp;
|
FILE* f = fopen(CONVERT_FBE_FILE, "wb");
|
||||||
|
if (!f) {
|
||||||
|
ui->Print("Failed to convert to file encryption %s\n", strerror(errno));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
result = format_volume(volume, CONVERT_FBE_DIR);
|
||||||
|
remove(CONVERT_FBE_FILE);
|
||||||
|
rmdir(CONVERT_FBE_DIR);
|
||||||
|
} else {
|
||||||
|
result = format_volume(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) {
|
||||||
|
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)) {
|
||||||
|
PLOG(ERROR) << "Failed to write to " << log.name;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Any part of the log we'd copied to cache is now gone.
|
} else {
|
||||||
// Reset the pointer so we copy from the beginning of the temp
|
PLOG(ERROR) << "Failed to mount / create " << CACHE_LOG_DIR;
|
||||||
// log.
|
|
||||||
tmplog_offset = 0;
|
|
||||||
copy_logs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (result == 0);
|
// Any part of the log we'd copied to cache is now gone.
|
||||||
|
// Reset the pointer so we copy from the beginning of the temp
|
||||||
|
// log.
|
||||||
|
tmplog_offset = 0;
|
||||||
|
copy_logs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in a new issue