support for ext4/EMMC filesystems in updater binary

Make the mount and format functions take extra parameters describing
the filesystem type and add support for mounting and formatting ext4
filesystems on EMMC.

Change recovery to consistently use stdout for status messages instead
of mixing stdout and stderr.
diff --git a/common.h b/common.h
index a428dab..333417f 100644
--- a/common.h
+++ b/common.h
@@ -72,12 +72,12 @@
 void ui_reset_progress();
 
 #define LOGE(...) ui_print("E:" __VA_ARGS__)
-#define LOGW(...) fprintf(stderr, "W:" __VA_ARGS__)
-#define LOGI(...) fprintf(stderr, "I:" __VA_ARGS__)
+#define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
+#define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__)
 
 #if 0
-#define LOGV(...) fprintf(stderr, "V:" __VA_ARGS__)
-#define LOGD(...) fprintf(stderr, "D:" __VA_ARGS__)
+#define LOGV(...) fprintf(stdout, "V:" __VA_ARGS__)
+#define LOGD(...) fprintf(stdout, "D:" __VA_ARGS__)
 #else
 #define LOGV(...) do {} while (0)
 #define LOGD(...) do {} while (0)
diff --git a/install.c b/install.c
index 35ba6ca..20e8998 100644
--- a/install.c
+++ b/install.c
@@ -109,7 +109,7 @@
     if (pid == 0) {
         close(pipefd[0]);
         execv(binary, args);
-        fprintf(stderr, "E:Can't run %s (%s)\n", binary, strerror(errno));
+        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
         _exit(-1);
     }
     close(pipefd[1]);
diff --git a/recovery.c b/recovery.c
index d2c726a..2ce1fd7 100644
--- a/recovery.c
+++ b/recovery.c
@@ -567,7 +567,7 @@
 
 static void
 print_property(const char *key, const char *name, void *cookie) {
-    fprintf(stderr, "%s=%s\n", key, name);
+    printf("%s=%s\n", key, name);
 }
 
 int
@@ -577,7 +577,7 @@
     // If these fail, there's not really anywhere to complain...
     freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);
     freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);
-    fprintf(stderr, "Starting recovery on %s", ctime(&start));
+    printf("Starting recovery on %s", ctime(&start));
 
     ui_init();
     get_args(&argc, &argv);
@@ -607,14 +607,14 @@
 
     device_recovery_start();
 
-    fprintf(stderr, "Command:");
+    printf("Command:");
     for (arg = 0; arg < argc; arg++) {
-        fprintf(stderr, " \"%s\"", argv[arg]);
+        printf(" \"%s\"", argv[arg]);
     }
-    fprintf(stderr, "\n\n");
+    printf("\n\n");
 
     property_list(print_property, NULL);
-    fprintf(stderr, "\n");
+    printf("\n");
 
     int status = INSTALL_SUCCESS;
 
diff --git a/ui.c b/ui.c
index ef21257..3bb2c2a 100644
--- a/ui.c
+++ b/ui.c
@@ -404,7 +404,7 @@
     vsnprintf(buf, 256, fmt, ap);
     va_end(ap);
 
-    fputs(buf, stderr);
+    fputs(buf, stdout);
 
     // This can get called before ui_init(), so be careful.
     pthread_mutex_lock(&gUpdateMutex);
diff --git a/updater/Android.mk b/updater/Android.mk
index d4a4e33..dcc6a49 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -18,7 +18,13 @@
 
 LOCAL_SRC_FILES := $(updater_src_files)
 
-LOCAL_STATIC_LIBRARIES := $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
+ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
+LOCAL_CFLAGS += -DUSE_EXT4
+LOCAL_C_INCLUDES += system/extras/ext4_utils
+LOCAL_STATIC_LIBRARIES += libext4_utils libz
+endif
+
+LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
 LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
 LOCAL_STATIC_LIBRARIES += libmincrypt libbz
 LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
diff --git a/updater/install.c b/updater/install.c
index e869134..167b402 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -36,24 +36,35 @@
 #include "updater.h"
 #include "applypatch/applypatch.h"
 
-// mount(type, location, mount_point)
+#ifdef USE_EXT4
+#include "make_ext4fs.h"
+#endif
+
+// mount(fs_type, partition_type, location, mount_point)
 //
-//   what:  type="MTD"   location="<partition>"            to mount a yaffs2 filesystem
-//          type="vfat"  location="/dev/block/<whatever>"  to mount a device
+//    fs_type="yaffs2" partition_type="MTD"     location=partition
+//    fs_type="ext4"   partition_type="EMMC"    location=device
 Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
     char* result = NULL;
-    if (argc != 3) {
-        return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
+    if (argc != 4) {
+        return ErrorAbort(state, "%s() expects 4 args, got %d", name, argc);
     }
-    char* type;
+    char* fs_type;
+    char* partition_type;
     char* location;
     char* mount_point;
-    if (ReadArgs(state, argv, 3, &type, &location, &mount_point) < 0) {
+    if (ReadArgs(state, argv, 4, &fs_type, &partition_type,
+                 &location, &mount_point) < 0) {
         return NULL;
     }
 
-    if (strlen(type) == 0) {
-        ErrorAbort(state, "type argument to %s() can't be empty", name);
+    if (strlen(fs_type) == 0) {
+        ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+        goto done;
+    }
+    if (strlen(partition_type) == 0) {
+        ErrorAbort(state, "partition_type argument to %s() can't be empty",
+                   name);
         goto done;
     }
     if (strlen(location) == 0) {
@@ -67,7 +78,7 @@
 
     mkdir(mount_point, 0755);
 
-    if (strcmp(type, "MTD") == 0) {
+    if (strcmp(partition_type, "MTD") == 0) {
         mtd_scan_partitions();
         const MtdPartition* mtd;
         mtd = mtd_find_partition_by_name(location);
@@ -77,7 +88,7 @@
             result = strdup("");
             goto done;
         }
-        if (mtd_mount_partition(mtd, mount_point, "yaffs2", 0 /* rw */) != 0) {
+        if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) {
             fprintf(stderr, "mtd mount of %s failed: %s\n",
                     location, strerror(errno));
             result = strdup("");
@@ -85,7 +96,7 @@
         }
         result = mount_point;
     } else {
-        if (mount(location, mount_point, type,
+        if (mount(location, mount_point, fs_type,
                   MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) {
             fprintf(stderr, "%s: failed to mount %s at %s: %s\n",
                     name, location, mount_point, strerror(errno));
@@ -96,7 +107,8 @@
     }
 
 done:
-    free(type);
+    free(fs_type);
+    free(partition_type);
     free(location);
     if (result != mount_point) free(mount_point);
     return StringValue(result);
@@ -162,22 +174,29 @@
 }
 
 
-// format(type, location)
+// format(fs_type, partition_type, location)
 //
-//    type="MTD"  location=partition
+//    fs_type="yaffs2" partition_type="MTD"     location=partition
+//    fs_type="ext4"   partition_type="EMMC"    location=device
 Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
     char* result = NULL;
-    if (argc != 2) {
-        return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+    if (argc != 3) {
+        return ErrorAbort(state, "%s() expects 3 args, got %d", name, argc);
     }
-    char* type;
+    char* fs_type;
+    char* partition_type;
     char* location;
-    if (ReadArgs(state, argv, 2, &type, &location) < 0) {
+    if (ReadArgs(state, argv, 3, &fs_type, &partition_type, &location) < 0) {
         return NULL;
     }
 
-    if (strlen(type) == 0) {
-        ErrorAbort(state, "type argument to %s() can't be empty", name);
+    if (strlen(fs_type) == 0) {
+        ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+        goto done;
+    }
+    if (strlen(partition_type) == 0) {
+        ErrorAbort(state, "partition_type argument to %s() can't be empty",
+                   name);
         goto done;
     }
     if (strlen(location) == 0) {
@@ -185,7 +204,7 @@
         goto done;
     }
 
-    if (strcmp(type, "MTD") == 0) {
+    if (strcmp(partition_type, "MTD") == 0) {
         mtd_scan_partitions();
         const MtdPartition* mtd = mtd_find_partition_by_name(location);
         if (mtd == NULL) {
@@ -212,12 +231,26 @@
             goto done;
         }
         result = location;
+#ifdef USE_EXT4
+    } else if (strcmp(fs_type, "ext4") == 0) {
+        reset_ext4fs_info();
+        int status = make_ext4fs(location, NULL, NULL, 0, 0);
+        if (status != 0) {
+            fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
+                    name, status, location);
+            result = strdup("");
+            goto done;
+        }
+        result = location;
+#endif
     } else {
-        fprintf(stderr, "%s: unsupported type \"%s\"", name, type);
+        fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"",
+                name, fs_type, partition_type);
     }
 
 done:
-    free(type);
+    free(fs_type);
+    free(partition_type);
     if (result != location) free(location);
     return StringValue(result);
 }