am a94d9548: am 1117c69f: am 7172eb7b: Merge "Mute unharmful build warning at the top of the build log:" into gingerbread

* commit 'a94d954862fab26f6159ed7bb836ba6758a569fd':
  Mute unharmful build warning at the top of the build log:
diff --git a/common.h b/common.h
index cba4c86..ef2fe9f 100644
--- a/common.h
+++ b/common.h
@@ -126,4 +126,7 @@
 
 } UIParameters;
 
+// fopen a file, mounting volumes and making parent dirs as necessary.
+FILE* fopen_path(const char *path, const char *mode);
+
 #endif  // RECOVERY_COMMON_H
diff --git a/install.c b/install.c
index 5bb3a78..707cda4 100644
--- a/install.c
+++ b/install.c
@@ -36,6 +36,8 @@
 #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) {
@@ -233,8 +235,8 @@
     return NULL;
 }
 
-int
-install_package(const char *path)
+static int
+really_install_package(const char *path)
 {
     ui_set_background(BACKGROUND_ICON_INSTALLING);
     ui_print("Finding update package...\n");
@@ -285,3 +287,23 @@
     ui_print("Installing update...\n");
     return try_update_binary(path, &zip);
 }
+
+int
+install_package(const char* path)
+{
+    FILE* install_log = fopen_path(LAST_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);
+    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;
+}
diff --git a/recovery.c b/recovery.c
index fd7ce42..3a412d5 100644
--- a/recovery.c
+++ b/recovery.c
@@ -120,7 +120,7 @@
 static const int MAX_ARGS = 100;
 
 // open a given path, mounting partitions as necessary
-static FILE*
+FILE*
 fopen_path(const char *path, const char *mode) {
     if (ensure_path_mounted(path) != 0) {
         LOGE("Can't mount %s\n", path);
diff --git a/updater/install.c b/updater/install.c
index 6a79964..0396bae 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -782,21 +782,26 @@
     return false;
 }
 
-// write_raw_image(file, partition)
+// write_raw_image(filename_or_blob, partition)
 Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
     char* result = NULL;
 
-    char* partition;
-    char* filename;
-    if (ReadArgs(state, argv, 2, &filename, &partition) < 0) {
+    Value* partition_value;
+    Value* contents;
+    if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) {
         return NULL;
     }
 
+    if (partition_value->type != VAL_STRING) {
+        ErrorAbort(state, "partition argument to %s must be string", name);
+        goto done;
+    }
+    char* partition = partition_value->data;
     if (strlen(partition) == 0) {
         ErrorAbort(state, "partition argument to %s can't be empty", name);
         goto done;
     }
-    if (strlen(filename) == 0) {
+    if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
         ErrorAbort(state, "file argument to %s can't be empty", name);
         goto done;
     }
@@ -819,27 +824,35 @@
 
     bool success;
 
-    FILE* f = fopen(filename, "rb");
-    if (f == NULL) {
-        fprintf(stderr, "%s: can't open %s: %s\n",
-                name, filename, strerror(errno));
-        result = strdup("");
-        goto done;
-    }
-
-    success = true;
-    char* buffer = malloc(BUFSIZ);
-    int read;
-    while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
-        int wrote = mtd_write_data(ctx, buffer, read);
-        success = success && (wrote == read);
-        if (!success) {
-            fprintf(stderr, "mtd_write_data to %s failed: %s\n",
-                    partition, strerror(errno));
+    if (contents->type == VAL_STRING) {
+        // we're given a filename as the contents
+        char* filename = contents->data;
+        FILE* f = fopen(filename, "rb");
+        if (f == NULL) {
+            fprintf(stderr, "%s: can't open %s: %s\n",
+                    name, filename, strerror(errno));
+            result = strdup("");
+            goto done;
         }
+
+        success = true;
+        char* buffer = malloc(BUFSIZ);
+        int read;
+        while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
+            int wrote = mtd_write_data(ctx, buffer, read);
+            success = success && (wrote == read);
+        }
+        free(buffer);
+        fclose(f);
+    } else {
+        // we're given a blob as the contents
+        ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
+        success = (wrote == contents->size);
     }
-    free(buffer);
-    fclose(f);
+    if (!success) {
+        fprintf(stderr, "mtd_write_data to %s failed: %s\n",
+                partition, strerror(errno));
+    }
 
     if (mtd_erase_blocks(ctx, -1) == -1) {
         fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
@@ -848,14 +861,14 @@
         fprintf(stderr, "%s: error closing write of %s\n", name, partition);
     }
 
-    printf("%s %s partition from %s\n",
-           success ? "wrote" : "failed to write", partition, filename);
+    printf("%s %s partition\n",
+           success ? "wrote" : "failed to write", partition);
 
     result = success ? partition : strdup("");
 
 done:
-    if (result != partition) free(partition);
-    free(filename);
+    if (result != partition) FreeValue(partition_value);
+    FreeValue(contents);
     return StringValue(result);
 }