diff options
Diffstat (limited to 'extra-functions.c')
-rw-r--r-- | extra-functions.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/extra-functions.c b/extra-functions.c index cf93052f1..ccdbba576 100644 --- a/extra-functions.c +++ b/extra-functions.c @@ -52,6 +52,7 @@ #include "roots.h" #include "data.h" #include "variables.h" +#include "install.h" //kang system() from bionic/libc/unistd and rename it __system() so we can be even more hackish :) #undef _PATH_BSHELL @@ -413,6 +414,57 @@ int check_md5(char* path) { return o; } +static int really_install_package(const char *path, int* wipe_cache) +{ + //ui->SetBackground(RecoveryUI::INSTALLING); + LOGI("Finding update package...\n"); + //ui->SetProgressType(RecoveryUI::INDETERMINATE); + LOGI("Update location: %s\n", path); + + if (ensure_path_mounted(path) != 0) { + LOGE("Can't mount %s\n", path); + return INSTALL_CORRUPT; + } + + LOGI("Opening update package...\n"); + + int numKeys; + /*RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys); + if (loadedKeys == NULL) { + LOGE("Failed to load keys\n"); + return INSTALL_CORRUPT; + } + LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);*/ + + // Give verification half the progress bar... + LOGI("Verifying update package...\n"); + //ui->SetProgressType(RecoveryUI::DETERMINATE); + //ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); + + int err; + /*err = verify_file(path, loadedKeys, numKeys); + free(loadedKeys); + LOGI("verify_file returned %d\n", err); + if (err != VERIFY_SUCCESS) { + LOGE("signature verification failed\n"); + return INSTALL_CORRUPT; + }*/ + + /* Try to open the package. + */ + ZipArchive zip; + err = mzOpenZipArchive(path, &zip); + if (err != 0) { + LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad"); + return INSTALL_CORRUPT; + } + + /* Verify and install the contents of the package. + */ + LOGI("Installing update...\n"); + return try_update_binary(path, &zip, wipe_cache); +} + static void set_sdcard_update_bootloader_message() { struct bootloader_message boot; memset(&boot, 0, sizeof(boot)); @@ -954,3 +1006,82 @@ int check_backup_name(int show_error) { // No problems found, return 0 return 0; } + +static const char *COMMAND_FILE = "/cache/recovery/command"; +static const char *INTENT_FILE = "/cache/recovery/intent"; +static const char *LOG_FILE = "/cache/recovery/log"; +static const char *LAST_LOG_FILE = "/cache/recovery/last_log"; +static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install"; +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"; + +// close a file, log an error if the error indicator is set +static void check_and_fclose(FILE *fp, const char *name) { + fflush(fp); + if (ferror(fp)) LOGE("Error in %s\n(%s)\n", name, strerror(errno)); + fclose(fp); +} + +static void copy_log_file(const char* source, const char* destination, int append) { + FILE *log = fopen_path(destination, append ? "a" : "w"); + if (log == NULL) { + LOGE("Can't open %s\n", destination); + } else { + FILE *tmplog = fopen(source, "r"); + if (tmplog != NULL) { + if (append) { + fseek(tmplog, tmplog_offset, SEEK_SET); // Since last write + } + char buf[4096]; + while (fgets(buf, sizeof(buf), tmplog)) fputs(buf, log); + if (append) { + tmplog_offset = ftell(tmplog); + } + check_and_fclose(tmplog, source); + } + check_and_fclose(log, destination); + } +} + +// 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), and +// record any intent we were asked to communicate back to the system. +// this function is idempotent: call it as many times as you like. +void twfinish_recovery(const char *send_intent) { + // By this point, we're ready to return to the main system... + if (send_intent != NULL) { + FILE *fp = fopen_path(INTENT_FILE, "w"); + if (fp == NULL) { + LOGE("Can't open %s\n", INTENT_FILE); + } else { + fputs(send_intent, fp); + check_and_fclose(fp, INTENT_FILE); + } + } + + // Copy logs to cache so the system can find out what happened. + 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); + chmod(LOG_FILE, 0600); + chown(LOG_FILE, 1000, 1000); // system user + chmod(LAST_LOG_FILE, 0640); + chmod(LAST_INSTALL_FILE, 0644); + + // Reset to normal system boot so recovery won't cycle indefinitely. + struct bootloader_message boot; + memset(&boot, 0, sizeof(boot)); + set_bootloader_message(&boot); + + // Remove the command file, so recovery won't repeat indefinitely. + if (ensure_path_mounted(COMMAND_FILE) != 0 || + (unlink(COMMAND_FILE) && errno != ENOENT)) { + LOGW("Can't unlink %s\n", COMMAND_FILE); + } + + ensure_path_unmounted(CACHE_ROOT); + sync(); // For good measure. +} + |