summaryrefslogtreecommitdiffstats
path: root/extra-functions.c
diff options
context:
space:
mode:
Diffstat (limited to 'extra-functions.c')
-rw-r--r--extra-functions.c131
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.
+}
+