diff options
-rw-r--r-- | recovery.cpp | 104 | ||||
-rw-r--r-- | uncrypt/uncrypt.c | 15 |
2 files changed, 106 insertions, 13 deletions
diff --git a/recovery.cpp b/recovery.cpp index e1a2a9678..1d22b248a 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -25,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/klog.h> #include <sys/stat.h> #include <sys/types.h> #include <time.h> @@ -76,9 +77,14 @@ static const char *CACHE_ROOT = "/cache"; static const char *SDCARD_ROOT = "/sdcard"; static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log"; static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install"; +static const char *LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; +#define KLOG_DEFAULT_LEN (64 * 1024) #define KEEP_LOG_COUNT 10 +// Number of lines per page when displaying a file on screen +#define LINES_PER_PAGE 30 + RecoveryUI* ui = NULL; char* locale = NULL; char recovery_version[PROPERTY_VALUE_MAX+1]; @@ -259,6 +265,44 @@ set_sdcard_update_bootloader_message() { set_bootloader_message(&boot); } +// read from kernel log into buffer and write out to file +static void +save_kernel_log(const char *destination) { + int n; + char *buffer; + int klog_buf_len; + FILE *log; + + klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0); + if (klog_buf_len <= 0) { + LOGE("Error getting klog size (%s), using default\n", strerror(errno)); + klog_buf_len = KLOG_DEFAULT_LEN; + } + + buffer = (char *)malloc(klog_buf_len); + if (!buffer) { + LOGE("Can't alloc %d bytes for klog buffer\n", klog_buf_len); + return; + } + + n = klogctl(KLOG_READ_ALL, buffer, klog_buf_len); + if (n < 0) { + LOGE("Error in reading klog (%s)\n", strerror(errno)); + free(buffer); + return; + } + + log = fopen_path(destination, "w"); + if (log == NULL) { + LOGE("Can't open %s\n", destination); + free(buffer); + return; + } + fwrite(buffer, n, 1, log); + check_and_fclose(log, destination); + free(buffer); +} + // How much of the temp log we have copied to the copy in cache. static long tmplog_offset = 0; @@ -306,8 +350,11 @@ copy_logs() { copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true); copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false); copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false); + save_kernel_log(LAST_KMSG_FILE); chmod(LOG_FILE, 0600); chown(LOG_FILE, 1000, 1000); // system user + chmod(LAST_KMSG_FILE, 0600); + chown(LAST_KMSG_FILE, 1000, 1000); // system user chmod(LAST_LOG_FILE, 0640); chmod(LAST_INSTALL_FILE, 0644); sync(); @@ -681,29 +728,71 @@ static void file_to_ui(const char* fn) { } char line[1024]; int ct = 0; + int key = 0; redirect_stdio("/dev/null"); while(fgets(line, sizeof(line), fp) != NULL) { ui->Print("%s", line); ct++; - if (ct % 30 == 0) { + if (ct % LINES_PER_PAGE == 0) { // give the user time to glance at the entries - ui->WaitKey(); + key = ui->WaitKey(); + + if (key == KEY_POWER) { + break; + } + + if (key == KEY_VOLUMEUP) { + // Go back by seeking to the beginning and dumping ct - n + // lines. It's ugly, but this way we don't need to store + // the previous offsets. The files we're dumping here aren't + // expected to be very large. + int i; + + ct -= 2 * LINES_PER_PAGE; + if (ct < 0) { + ct = 0; + } + fseek(fp, 0, SEEK_SET); + for (i = 0; i < ct; i++) { + fgets(line, sizeof(line), fp); + } + ui->Print("^^^^^^^^^^\n"); + } } } + + // If the user didn't abort, then give the user time to glance at + // the end of the log, sorry, no rewind here + if (key != KEY_POWER) { + ui->Print("\n--END-- (press any key)\n"); + ui->WaitKey(); + } + redirect_stdio(TEMPORARY_LOG_FILE); fclose(fp); } static void choose_recovery_file(Device* device) { - int i; + unsigned int i; + unsigned int n; static const char** title_headers = NULL; char *filename; const char* headers[] = { "Select file to view", "", NULL }; - char* entries[KEEP_LOG_COUNT + 2]; + // "Go back" + LAST_KMSG_FILE + KEEP_LOG_COUNT + terminating NULL entry + char* entries[KEEP_LOG_COUNT + 3]; memset(entries, 0, sizeof(entries)); + n = 0; + entries[n++] = strdup("Go back"); + + // Add kernel kmsg file if available + if ((ensure_path_mounted(LAST_KMSG_FILE) == 0) && (access(LAST_KMSG_FILE, R_OK) == 0)) { + entries[n++] = strdup(LAST_KMSG_FILE); + } + + // Add LAST_LOG_FILE + LAST_LOG_FILE.x for (i = 0; i < KEEP_LOG_COUNT; i++) { char *filename; if (asprintf(&filename, (i==0) ? LAST_LOG_FILE : (LAST_LOG_FILE ".%d"), i) == -1) { @@ -712,13 +801,12 @@ static void choose_recovery_file(Device* device) { } if ((ensure_path_mounted(filename) != 0) || (access(filename, R_OK) == -1)) { free(filename); - entries[i+1] = NULL; + entries[n++] = NULL; break; } - entries[i+1] = filename; + entries[n++] = filename; } - entries[0] = strdup("Go back"); title_headers = prepend_title((const char**)headers); while(1) { @@ -727,7 +815,7 @@ static void choose_recovery_file(Device* device) { file_to_ui(entries[chosen_item]); } - for (i = 0; i < KEEP_LOG_COUNT + 1; i++) { + for (i = 0; i < (sizeof(entries) / sizeof(*entries)); i++) { free(entries[i]); } } diff --git a/uncrypt/uncrypt.c b/uncrypt/uncrypt.c index 189fa57e1..361c80483 100644 --- a/uncrypt/uncrypt.c +++ b/uncrypt/uncrypt.c @@ -164,7 +164,8 @@ char* parse_recovery_command_file() if (f == NULL) { return NULL; } - FILE* fo = fopen(RECOVERY_COMMAND_FILE_TMP, "w"); + int fd = open(RECOVERY_COMMAND_FILE_TMP, O_WRONLY | O_SYNC); + FILE* fo = fdopen(fd, "w"); while (fgets(temp, sizeof(temp), f)) { printf("read: %s", temp); @@ -175,6 +176,7 @@ char* parse_recovery_command_file() fputs(temp, fo); } fclose(f); + fsync(fd); fclose(fo); if (fn) { @@ -190,7 +192,8 @@ int produce_block_map(const char* path, const char* map_file, const char* blk_de struct stat sb; int ret; - FILE* mapf = fopen(map_file, "w"); + int mapfd = open(map_file, O_WRONLY | O_SYNC); + FILE* mapf = fdopen(mapfd, "w"); ret = stat(path, &sb); if (ret != 0) { @@ -232,7 +235,7 @@ int produce_block_map(const char* path, const char* map_file, const char* blk_de int wfd = -1; if (encrypted) { - wfd = open(blk_dev, O_WRONLY); + wfd = open(blk_dev, O_WRONLY | O_SYNC); if (wfd < 0) { ALOGE("failed to open fd for writing: %s\n", strerror(errno)); return -1; @@ -302,9 +305,11 @@ int produce_block_map(const char* path, const char* map_file, const char* blk_de fprintf(mapf, "%d %d\n", ranges[i*2], ranges[i*2+1]); } + fsync(mapfd); fclose(mapf); close(fd); if (encrypted) { + fsync(wfd); close(wfd); } @@ -318,7 +323,7 @@ void wipe_misc() { struct fstab_rec* v = &fstab->recs[i]; if (!v->mount_point) continue; if (strcmp(v->mount_point, "/misc") == 0) { - int fd = open(v->blk_device, O_WRONLY); + int fd = open(v->blk_device, O_WRONLY | O_SYNC); uint8_t zeroes[1088]; // sizeof(bootloader_message) from recovery memset(zeroes, 0, sizeof(zeroes)); @@ -333,7 +338,7 @@ void wipe_misc() { written += w; } } - + fsync(fd); close(fd); } } |