Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0181b8f authored by Doug Zongker's avatar Doug Zongker
Browse files

allow recovery packages to wipe cache

updater now has a function "wipe_cache();" which causes recovery to
wipe the cache partition after the successful installation of the
package.  Move log copying around a bit so logs and the last_install
flag file are copied to cache after it's wiped.

Bug: 5314244
Change-Id: Id35a9eb6dcd626c8f3a3a0076074f462ed3d44bd
parent 441031da
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -36,11 +36,9 @@
#define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"
#define PUBLIC_KEYS_FILE "/res/keys"

static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";

// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip) {
try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
    const ZipEntry* binary_entry =
            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    if (binary_entry == NULL) {
@@ -54,7 +52,7 @@ try_update_binary(const char *path, ZipArchive *zip) {
    if (fd < 0) {
        mzCloseZipArchive(zip);
        LOGE("Can't make %s\n", binary);
        return 1;
        return INSTALL_ERROR;
    }
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);
@@ -62,7 +60,7 @@ try_update_binary(const char *path, ZipArchive *zip) {

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
        return 1;
        return INSTALL_ERROR;
    }

    int pipefd[2];
@@ -119,6 +117,8 @@ try_update_binary(const char *path, ZipArchive *zip) {
    }
    close(pipefd[1]);

    *wipe_cache = 0;

    char buffer[1024];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
@@ -145,6 +145,8 @@ try_update_binary(const char *path, ZipArchive *zip) {
            } else {
                ui_print("\n");
            }
        } else if (strcmp(command, "wipe_cache") == 0) {
            *wipe_cache = 1;
        } else {
            LOGE("unknown command [%s]\n", command);
        }
@@ -236,7 +238,7 @@ exit:
}

static int
really_install_package(const char *path)
really_install_package(const char *path, int* wipe_cache)
{
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
@@ -285,25 +287,24 @@ really_install_package(const char *path)
    /* Verify and install the contents of the package.
     */
    ui_print("Installing update...\n");
    return try_update_binary(path, &zip);
    return try_update_binary(path, &zip, wipe_cache);
}

int
install_package(const char* path)
install_package(const char* path, int* wipe_cache, const char* install_file)
{
    FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w");
    FILE* install_log = fopen_path(install_file, "w");
    if (install_log) {
        fputs(path, install_log);
        fputc('\n', install_log);
    } else {
        LOGE("failed to open last_install: %s\n", strerror(errno));
    }
    int result = really_install_package(path);
    int result = really_install_package(path, wipe_cache);
    if (install_log) {
        fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
        fputc('\n', install_log);
        fclose(install_log);
        chmod(LAST_INSTALL_FILE, 0644);
    }
    return result;
}
+5 −1
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@
#include "common.h"

enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
int install_package(const char *root_path);
// Install the package specified by root_path.  If INSTALL_SUCCESS is
// returned and *wipe_cache is true on exit, caller should wipe the
// cache partition.
int install_package(const char *root_path, int* wipe_cache,
                    const char* install_file);

#endif  // RECOVERY_INSTALL_H_
+44 −14
Original line number Diff line number Diff line
@@ -52,9 +52,11 @@ 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";
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";

extern UIParameters ui_parameters;    // from ui.c
@@ -223,15 +225,13 @@ set_sdcard_update_bootloader_message() {
static long tmplog_offset = 0;

static void
copy_log_file(const char* destination, int append) {
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(TEMPORARY_LOG_FILE, "r");
        if (tmplog == NULL) {
            LOGE("Can't open %s\n", TEMPORARY_LOG_FILE);
        } else {
        FILE *tmplog = fopen(source, "r");
        if (tmplog != NULL) {
            if (append) {
                fseek(tmplog, tmplog_offset, SEEK_SET);  // Since last write
            }
@@ -240,7 +240,7 @@ copy_log_file(const char* destination, int append) {
            if (append) {
                tmplog_offset = ftell(tmplog);
            }
            check_and_fclose(tmplog, TEMPORARY_LOG_FILE);
            check_and_fclose(tmplog, source);
        }
        check_and_fclose(log, destination);
    }
@@ -265,9 +265,13 @@ finish_recovery(const char *send_intent) {
    }

    // Copy logs to cache so the system can find out what happened.
    copy_log_file(LOG_FILE, true);
    copy_log_file(LAST_LOG_FILE, false);
    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 mormal system boot so recovery won't cycle indefinitely.
    struct bootloader_message boot;
@@ -280,6 +284,7 @@ finish_recovery(const char *send_intent) {
        LOGW("Can't unlink %s\n", COMMAND_FILE);
    }

    ensure_path_unmounted(CACHE_ROOT);
    sync();  // For good measure.
}

@@ -289,6 +294,8 @@ erase_volume(const char *volume) {
    ui_show_indeterminate_progress();
    ui_print("Formatting %s...\n", volume);

    ensure_path_unmounted(volume);

    if (strcmp(volume, "/cache") == 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
@@ -469,7 +476,8 @@ static int compare_string(const void* a, const void* b) {
}

static int
update_directory(const char* path, const char* unmount_when_done) {
update_directory(const char* path, const char* unmount_when_done,
                 int* wipe_cache) {
    ensure_path_mounted(path);

    const char* MENU_HEADERS[] = { "Choose a package to install:",
@@ -558,7 +566,7 @@ update_directory(const char* path, const char* unmount_when_done) {
            strlcat(new_path, "/", PATH_MAX);
            strlcat(new_path, item, PATH_MAX);
            new_path[strlen(new_path)-1] = '\0';  // truncate the trailing '/'
            result = update_directory(new_path, unmount_when_done);
            result = update_directory(new_path, unmount_when_done, wipe_cache);
            if (result >= 0) break;
        } else {
            // selected a zip file:  attempt to install it, and return
@@ -575,7 +583,7 @@ update_directory(const char* path, const char* unmount_when_done) {
                ensure_path_unmounted(unmount_when_done);
            }
            if (copy) {
                result = install_package(copy);
                result = install_package(copy, wipe_cache, TEMPORARY_INSTALL_FILE);
                free(copy);
            } else {
                result = INSTALL_ERROR;
@@ -650,6 +658,7 @@ prompt_and_wait() {
        chosen_item = device_perform_action(chosen_item);

        int status;
        int wipe_cache;
        switch (chosen_item) {
            case ITEM_REBOOT:
                return;
@@ -667,7 +676,15 @@ prompt_and_wait() {
                break;

            case ITEM_APPLY_SDCARD:
                status = update_directory(SDCARD_ROOT, SDCARD_ROOT);
                status = update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache);
                if (status == INSTALL_SUCCESS && wipe_cache) {
                    ui_print("\n-- Wiping cache (at package request)...\n");
                    if (erase_volume("/cache")) {
                        ui_print("Cache wipe failed.\n");
                    } else {
                        ui_print("Cache wipe complete.\n");
                    }
                }
                if (status >= 0) {
                    if (status != INSTALL_SUCCESS) {
                        ui_set_background(BACKGROUND_ICON_ERROR);
@@ -681,7 +698,15 @@ prompt_and_wait() {
                break;
            case ITEM_APPLY_CACHE:
                // Don't unmount cache at the end of this.
                status = update_directory(CACHE_ROOT, NULL);
                status = update_directory(CACHE_ROOT, NULL, &wipe_cache);
                if (status == INSTALL_SUCCESS && wipe_cache) {
                    ui_print("\n-- Wiping cache (at package request)...\n");
                    if (erase_volume("/cache")) {
                        ui_print("Cache wipe failed.\n");
                    } else {
                        ui_print("Cache wipe complete.\n");
                    }
                }
                if (status >= 0) {
                    if (status != INSTALL_SUCCESS) {
                        ui_set_background(BACKGROUND_ICON_ERROR);
@@ -768,7 +793,12 @@ main(int argc, char **argv) {
    int status = INSTALL_SUCCESS;

    if (update_package != NULL) {
        status = install_package(update_package);
        status = install_package(update_package, &wipe_cache, TEMPORARY_INSTALL_FILE);
        if (status == INSTALL_SUCCESS && wipe_cache) {
            if (erase_volume("/cache")) {
                LOGE("Cache wipe (requested by package) failed.");
            }
        }
        if (status != INSTALL_SUCCESS) ui_print("Installation aborted.\n");
    } else if (wipe_data) {
        if (device_wipe_data()) status = INSTALL_ERROR;
+10 −0
Original line number Diff line number Diff line
@@ -1024,6 +1024,14 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
    return StringValue(buffer);
}

Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc != 0) {
        return ErrorAbort(state, "%s() expects no args, got %d", name, argc);
    }
    fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
    return StringValue(strdup("t"));
}

Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc < 1) {
        return ErrorAbort(state, "%s() expects at least 1 arg", name);
@@ -1198,6 +1206,8 @@ void RegisterInstallFunctions() {
    RegisterFunction("read_file", ReadFileFn);
    RegisterFunction("sha1_check", Sha1CheckFn);

    RegisterFunction("wipe_cache", WipeCacheFn);

    RegisterFunction("ui_print", UIPrintFn);

    RegisterFunction("run_program", RunProgramFn);