turn recovery into a C++ binary

Change-Id: I423a23581048d451d53eef46e5f5eac485b77555
diff --git a/Android.mk b/Android.mk
index 282862f..2c81be6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,12 +4,12 @@
 commands_recovery_local_path := $(LOCAL_PATH)
 
 LOCAL_SRC_FILES := \
-    recovery.c \
-    bootloader.c \
-    install.c \
-    roots.c \
-    ui.c \
-    verifier.c
+    recovery.cpp \
+    bootloader.cpp \
+    install.cpp \
+    roots.cpp \
+    ui.cpp \
+    verifier.cpp
 
 LOCAL_MODULE := recovery
 
@@ -50,7 +50,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := verifier_test.c verifier.c
+LOCAL_SRC_FILES := verifier_test.cpp verifier.cpp
 
 LOCAL_MODULE := verifier_test
 
diff --git a/bootloader.c b/bootloader.cpp
similarity index 100%
rename from bootloader.c
rename to bootloader.cpp
diff --git a/bootloader.h b/bootloader.h
index 2e749aa..712aa1a 100644
--- a/bootloader.h
+++ b/bootloader.h
@@ -17,6 +17,10 @@
 #ifndef _RECOVERY_BOOTLOADER_H
 #define _RECOVERY_BOOTLOADER_H
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Bootloader Message
  *
  * This structure describes the content of a block in flash
@@ -47,4 +51,8 @@
 int get_bootloader_message(struct bootloader_message *out);
 int set_bootloader_message(const struct bootloader_message *in);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/common.h b/common.h
index ef2fe9f..88807b8 100644
--- a/common.h
+++ b/common.h
@@ -19,61 +19,12 @@
 
 #include <stdio.h>
 
-// Initialize the graphics system.
-void ui_init();
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-// Use KEY_* codes from <linux/input.h> or KEY_DREAM_* from "minui/minui.h".
-int ui_wait_key();            // waits for a key/button press, returns the code
-int ui_key_pressed(int key);  // returns >0 if the code is currently pressed
-int ui_text_visible();        // returns >0 if text log is currently visible
-int ui_text_ever_visible();   // returns >0 if text log was ever visible
-void ui_show_text(int visible);
-void ui_clear_key_queue();
-
-// Write a message to the on-screen log shown with Alt-L (also to stderr).
-// The screen is small, and users may need to report these messages to support,
-// so keep the output short and not too cryptic.
-void ui_print(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
-
-// Display some header text followed by a menu of items, which appears
-// at the top of the screen (in place of any scrolling ui_print()
-// output, if necessary).
-void ui_start_menu(char** headers, char** items, int initial_selection);
-// Set the menu highlight to the given index, and return it (capped to
-// the range [0..numitems).
-int ui_menu_select(int sel);
-// End menu mode, resetting the text overlay so that ui_print()
-// statements will be displayed.
-void ui_end_menu();
-
-// Set the icon (normally the only thing visible besides the progress bar).
-enum {
-  BACKGROUND_ICON_NONE,
-  BACKGROUND_ICON_INSTALLING,
-  BACKGROUND_ICON_ERROR,
-  NUM_BACKGROUND_ICONS
-};
-void ui_set_background(int icon);
-
-// Show a progress bar and define the scope of the next operation:
-//   portion - fraction of the progress bar the next operation will use
-//   seconds - expected time interval (progress bar moves at this minimum rate)
-void ui_show_progress(float portion, int seconds);
-void ui_set_progress(float fraction);  // 0.0 - 1.0 within the defined scope
-
-// Default allocation of progress bar segments to operations
-static const int VERIFICATION_PROGRESS_TIME = 60;
-static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
-static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
-static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
-
-// Show a rotating "barberpole" for ongoing operations.  Updates automatically.
-void ui_show_indeterminate_progress();
-
-// Hide and reset the progress bar.
-void ui_reset_progress();
-
-#define LOGE(...) ui_print("E:" __VA_ARGS__)
+// TODO: restore ui_print for LOGE
+#define LOGE(...) fprintf(stdout, "E:" __VA_ARGS__)
 #define LOGW(...) fprintf(stdout, "W:" __VA_ARGS__)
 #define LOGI(...) fprintf(stdout, "I:" __VA_ARGS__)
 
@@ -129,4 +80,8 @@
 // fopen a file, mounting volumes and making parent dirs as necessary.
 FILE* fopen_path(const char *path, const char *mode);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // RECOVERY_COMMON_H
diff --git a/install.c b/install.cpp
similarity index 86%
rename from install.c
rename to install.cpp
index 9d7595e..482e0d7 100644
--- a/install.c
+++ b/install.cpp
@@ -32,6 +32,7 @@
 #include "mtdutils/mtdutils.h"
 #include "roots.h"
 #include "verifier.h"
+#include "ui.h"
 
 #define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"
 #define PUBLIC_KEYS_FILE "/res/keys"
@@ -46,7 +47,7 @@
         return INSTALL_CORRUPT;
     }
 
-    char* binary = "/tmp/update_binary";
+    const char* binary = "/tmp/update_binary";
     unlink(binary);
     int fd = creat(binary, 0755);
     if (fd < 0) {
@@ -100,18 +101,19 @@
     //   - the name of the package zip file.
     //
 
-    char** args = malloc(sizeof(char*) * 5);
+    const char** args = (const char**)malloc(sizeof(char*) * 5);
     args[0] = binary;
     args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
-    args[2] = malloc(10);
-    sprintf(args[2], "%d", pipefd[1]);
+    char* temp = (char*)malloc(10);
+    sprintf(temp, "%d", pipefd[1]);
+    args[2] = temp;
     args[3] = (char*)path;
     args[4] = NULL;
 
     pid_t pid = fork();
     if (pid == 0) {
         close(pipefd[0]);
-        execv(binary, args);
+        execv(binary, (char* const*)args);
         fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
         _exit(-1);
     }
@@ -188,31 +190,32 @@
         goto exit;
     }
 
-    int i;
-    bool done = false;
-    while (!done) {
-        ++*numKeys;
-        out = realloc(out, *numKeys * sizeof(RSAPublicKey));
-        RSAPublicKey* key = out + (*numKeys - 1);
-        if (fscanf(f, " { %i , 0x%x , { %u",
-                   &(key->len), &(key->n0inv), &(key->n[0])) != 3) {
-            goto exit;
-        }
-        if (key->len != RSANUMWORDS) {
-            LOGE("key length (%d) does not match expected size\n", key->len);
-            goto exit;
-        }
-        for (i = 1; i < key->len; ++i) {
-            if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
-        }
-        if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
-        for (i = 1; i < key->len; ++i) {
-            if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
-        }
-        fscanf(f, " } } ");
+    {
+        int i;
+        bool done = false;
+        while (!done) {
+            ++*numKeys;
+            out = (RSAPublicKey*)realloc(out, *numKeys * sizeof(RSAPublicKey));
+            RSAPublicKey* key = out + (*numKeys - 1);
+            if (fscanf(f, " { %i , 0x%x , { %u",
+                       &(key->len), &(key->n0inv), &(key->n[0])) != 3) {
+                goto exit;
+            }
+            if (key->len != RSANUMWORDS) {
+                LOGE("key length (%d) does not match expected size\n", key->len);
+                goto exit;
+            }
+            for (i = 1; i < key->len; ++i) {
+                if (fscanf(f, " , %u", &(key->n[i])) != 1) goto exit;
+            }
+            if (fscanf(f, " } , { %u", &(key->rr[0])) != 1) goto exit;
+            for (i = 1; i < key->len; ++i) {
+                if (fscanf(f, " , %u", &(key->rr[i])) != 1) goto exit;
+            }
+            fscanf(f, " } } ");
 
-        // if the line ends in a comma, this file has more keys.
-        switch (fgetc(f)) {
+            // if the line ends in a comma, this file has more keys.
+            switch (fgetc(f)) {
             case ',':
                 // more keys to come.
                 break;
@@ -224,6 +227,7 @@
             default:
                 LOGE("unexpected character between keys\n");
                 goto exit;
+            }
         }
     }
 
diff --git a/install.h b/install.h
index 5ebe160..1943f02 100644
--- a/install.h
+++ b/install.h
@@ -19,6 +19,10 @@
 
 #include "common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
 // Install the package specified by root_path.  If INSTALL_SUCCESS is
 // returned and *wipe_cache is true on exit, caller should wipe the
@@ -26,4 +30,8 @@
 int install_package(const char *root_path, int* wipe_cache,
                     const char* install_file);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // RECOVERY_INSTALL_H_
diff --git a/minui/minui.h b/minui/minui.h
index 2e2f1f4..74da4e9 100644
--- a/minui/minui.h
+++ b/minui/minui.h
@@ -19,6 +19,10 @@
 
 #include <stdbool.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef void* gr_surface;
 typedef unsigned short gr_pixel;
 
@@ -69,4 +73,8 @@
 int res_create_surface(const char* name, gr_surface* pSurface);
 void res_free_surface(gr_surface surface);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/minzip/DirUtil.h b/minzip/DirUtil.h
index 5d881f5..0d5ea7c 100644
--- a/minzip/DirUtil.h
+++ b/minzip/DirUtil.h
@@ -20,6 +20,10 @@
 #include <stdbool.h>
 #include <utime.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Like "mkdir -p", try to guarantee that all directories
  * specified in path are present, creating as many directories
  * as necessary.  The specified mode is passed to all mkdir
@@ -48,4 +52,8 @@
 int dirSetHierarchyPermissions(const char *path,
          int uid, int gid, int dirMode, int fileMode);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // MINZIP_DIRUTIL_H_
diff --git a/minzip/Zip.h b/minzip/Zip.h
index 9f99fba..739dbf5 100644
--- a/minzip/Zip.h
+++ b/minzip/Zip.h
@@ -14,6 +14,10 @@
 #include "Hash.h"
 #include "SysUtil.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * One entry in the Zip archive.  Treat this as opaque -- use accessors below.
  *
@@ -210,4 +214,8 @@
         int flags, const struct utimbuf *timestamp,
         void (*callback)(const char *fn, void*), void *cookie);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /*_MINZIP_ZIP*/
diff --git a/mtdutils/mounts.h b/mtdutils/mounts.h
index 30b2927..d721355 100644
--- a/mtdutils/mounts.h
+++ b/mtdutils/mounts.h
@@ -17,6 +17,10 @@
 #ifndef MTDUTILS_MOUNTS_H_
 #define MTDUTILS_MOUNTS_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct MountedVolume MountedVolume;
 
 int scan_mounted_volumes(void);
@@ -30,4 +34,8 @@
 
 int remount_read_only(const MountedVolume* volume);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // MTDUTILS_MOUNTS_H_
diff --git a/mtdutils/mtdutils.h b/mtdutils/mtdutils.h
index 45d3ebc..2708c43 100644
--- a/mtdutils/mtdutils.h
+++ b/mtdutils/mtdutils.h
@@ -19,6 +19,10 @@
 
 #include <sys/types.h>  // for size_t, etc.
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct MtdPartition MtdPartition;
 
 int mtd_scan_partitions(void);
@@ -53,4 +57,8 @@
 off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos);
 int mtd_write_close(MtdWriteContext *);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // MTDUTILS_H_
diff --git a/recovery.c b/recovery.cpp
similarity index 93%
rename from recovery.c
rename to recovery.cpp
index 06d6498..7c1d7fb 100644
--- a/recovery.c
+++ b/recovery.cpp
@@ -38,6 +38,7 @@
 #include "minzip/DirUtil.h"
 #include "roots.h"
 #include "recovery_ui.h"
+#include "ui.h"
 
 static const struct option OPTIONS[] = {
   { "send_intent", required_argument, NULL, 's' },
@@ -349,7 +350,7 @@
   strcpy(copy_path, SIDELOAD_TEMP_DIR);
   strcat(copy_path, "/package.zip");
 
-  char* buffer = malloc(BUFSIZ);
+  char* buffer = (char*)malloc(BUFSIZ);
   if (buffer == NULL) {
     LOGE("Failed to allocate buffer\n");
     return NULL;
@@ -396,22 +397,22 @@
   return strdup(copy_path);
 }
 
-static char**
+static const char**
 prepend_title(const char** headers) {
-    char* title[] = { "Android system recovery <"
-                          EXPAND(RECOVERY_API_VERSION) "e>",
-                      "",
-                      NULL };
+    const char* title[] = { "Android system recovery <"
+                            EXPAND(RECOVERY_API_VERSION) "e>",
+                            "",
+                            NULL };
 
     // count the number of lines in our title, plus the
     // caller-provided headers.
     int count = 0;
-    char** p;
+    const char** p;
     for (p = title; *p; ++p, ++count);
     for (p = headers; *p; ++p, ++count);
 
-    char** new_headers = malloc((count+1) * sizeof(char*));
-    char** h = new_headers;
+    const char** new_headers = (const char**)malloc((count+1) * sizeof(char*));
+    const char** h = new_headers;
     for (p = title; *p; ++p, ++h) *h = *p;
     for (p = headers; *p; ++p, ++h) *h = *p;
     *h = NULL;
@@ -420,8 +421,8 @@
 }
 
 static int
-get_menu_selection(char** headers, char** items, int menu_only,
-                   int initial_selection) {
+get_menu_selection(const char* const * headers, const char* const * items,
+                   int menu_only, int initial_selection) {
     // throw away keys pressed previously, so user doesn't
     // accidentally trigger menu items.
     ui_clear_key_queue();
@@ -495,14 +496,14 @@
         return 0;
     }
 
-    char** headers = prepend_title(MENU_HEADERS);
+    const char** headers = prepend_title(MENU_HEADERS);
 
     int d_size = 0;
     int d_alloc = 10;
-    char** dirs = malloc(d_alloc * sizeof(char*));
+    char** dirs = (char**)malloc(d_alloc * sizeof(char*));
     int z_size = 1;
     int z_alloc = 10;
-    char** zips = malloc(z_alloc * sizeof(char*));
+    char** zips = (char**)malloc(z_alloc * sizeof(char*));
     zips[0] = strdup("../");
 
     while ((de = readdir(d)) != NULL) {
@@ -516,9 +517,9 @@
 
             if (d_size >= d_alloc) {
                 d_alloc *= 2;
-                dirs = realloc(dirs, d_alloc * sizeof(char*));
+                dirs = (char**)realloc(dirs, d_alloc * sizeof(char*));
             }
-            dirs[d_size] = malloc(name_len + 2);
+            dirs[d_size] = (char*)malloc(name_len + 2);
             strcpy(dirs[d_size], de->d_name);
             dirs[d_size][name_len] = '/';
             dirs[d_size][name_len+1] = '\0';
@@ -528,7 +529,7 @@
                    strncasecmp(de->d_name + (name_len-4), ".zip", 4) == 0) {
             if (z_size >= z_alloc) {
                 z_alloc *= 2;
-                zips = realloc(zips, z_alloc * sizeof(char*));
+                zips = (char**)realloc(zips, z_alloc * sizeof(char*));
             }
             zips[z_size++] = strdup(de->d_name);
         }
@@ -541,7 +542,7 @@
     // append dirs to the zips list
     if (d_size + z_size + 1 > z_alloc) {
         z_alloc = d_size + z_size + 1;
-        zips = realloc(zips, z_alloc * sizeof(char*));
+        zips = (char**)realloc(zips, z_alloc * sizeof(char*));
     }
     memcpy(zips + z_size, dirs, d_size * sizeof(char*));
     free(dirs);
@@ -606,28 +607,28 @@
 static void
 wipe_data(int confirm) {
     if (confirm) {
-        static char** title_headers = NULL;
+        static const char** title_headers = NULL;
 
         if (title_headers == NULL) {
-            char* headers[] = { "Confirm wipe of all user data?",
-                                "  THIS CAN NOT BE UNDONE.",
-                                "",
-                                NULL };
+            const char* headers[] = { "Confirm wipe of all user data?",
+                                      "  THIS CAN NOT BE UNDONE.",
+                                      "",
+                                      NULL };
             title_headers = prepend_title((const char**)headers);
         }
 
-        char* items[] = { " No",
-                          " No",
-                          " No",
-                          " No",
-                          " No",
-                          " No",
-                          " No",
-                          " Yes -- delete all user data",   // [7]
-                          " No",
-                          " No",
-                          " No",
-                          NULL };
+        const char* items[] = { " No",
+                                " No",
+                                " No",
+                                " No",
+                                " No",
+                                " No",
+                                " No",
+                                " Yes -- delete all user data",   // [7]
+                                " No",
+                                " No",
+                                " No",
+                                NULL };
 
         int chosen_item = get_menu_selection(title_headers, items, 1, 0);
         if (chosen_item != 7) {
@@ -644,7 +645,7 @@
 
 static void
 prompt_and_wait() {
-    char** headers = prepend_title((const char**)MENU_HEADERS);
+    const char** headers = prepend_title((const char**)MENU_HEADERS);
 
     for (;;) {
         finish_recovery(NULL);
@@ -777,7 +778,7 @@
         // "/cache/foo".
         if (strncmp(update_package, "CACHE:", 6) == 0) {
             int len = strlen(update_package) + 10;
-            char* modified_path = malloc(len);
+            char* modified_path = (char*)malloc(len);
             strlcpy(modified_path, "/cache/", len);
             strlcat(modified_path, update_package+6, len);
             printf("(replacing path \"%s\" with \"%s\")\n",
diff --git a/recovery_ui.h b/recovery_ui.h
index 5f01770..4c4baf5 100644
--- a/recovery_ui.h
+++ b/recovery_ui.h
@@ -19,6 +19,10 @@
 
 #include "common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Called before UI library is initialized.  Can change things like
 // how many frames are included in various animations, etc.
 extern void device_ui_init(UIParameters* ui_parameters);
@@ -84,4 +88,8 @@
 // Text of menu items.
 extern char* MENU_ITEMS[];
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/roots.c b/roots.cpp
similarity index 97%
rename from roots.c
rename to roots.cpp
index cb7e067..9345cb0 100644
--- a/roots.c
+++ b/roots.cpp
@@ -33,7 +33,7 @@
 
 static int parse_options(char* options, Volume* volume) {
     char* option;
-    while (option = strtok(options, ",")) {
+    while ((option = strtok(options, ","))) {
         options = NULL;
 
         if (strncmp(option, "length=", 7) == 0) {
@@ -48,7 +48,7 @@
 
 void load_volume_table() {
     int alloc = 2;
-    device_volumes = malloc(alloc * sizeof(Volume));
+    device_volumes = (Volume*)malloc(alloc * sizeof(Volume));
 
     // Insert an entry for /tmp, which is the ramdisk and is always mounted.
     device_volumes[0].mount_point = "/tmp";
@@ -91,7 +91,7 @@
         if (mount_point && fs_type && device) {
             while (num_volumes >= alloc) {
                 alloc *= 2;
-                device_volumes = realloc(device_volumes, alloc*sizeof(Volume));
+                device_volumes = (Volume*)realloc(device_volumes, alloc*sizeof(Volume));
             }
             device_volumes[num_volumes].mount_point = strdup(mount_point);
             device_volumes[num_volumes].fs_type = strdup(fs_type);
diff --git a/roots.h b/roots.h
index cf59bfd..8abe18f 100644
--- a/roots.h
+++ b/roots.h
@@ -19,6 +19,10 @@
 
 #include "common.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 // Load and parse volume data from /etc/recovery.fstab.
 void load_volume_table();
 
@@ -38,4 +42,8 @@
 // it is mounted.
 int format_volume(const char* volume);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif  // RECOVERY_ROOTS_H_
diff --git a/ui.c b/ui.cpp
similarity index 97%
rename from ui.c
rename to ui.cpp
index 25df3d0..657a01e 100644
--- a/ui.c
+++ b/ui.cpp
@@ -32,6 +32,7 @@
 #include <cutils/android_reboot.h>
 #include "minui/minui.h"
 #include "recovery_ui.h"
+#include "ui.h"
 
 #define MAX_COLS 96
 #define MAX_ROWS 32
@@ -397,8 +398,8 @@
         }
     }
 
-    gProgressBarIndeterminate = malloc(ui_parameters.indeterminate_frames *
-                                       sizeof(gr_surface));
+    gProgressBarIndeterminate = (gr_surface*)malloc(ui_parameters.indeterminate_frames *
+                                                    sizeof(gr_surface));
     for (i = 0; i < ui_parameters.indeterminate_frames; ++i) {
         char filename[40];
         // "indeterminate01.png", "indeterminate02.png", ...
@@ -410,8 +411,8 @@
     }
 
     if (ui_parameters.installing_frames > 0) {
-        gInstallationOverlay = malloc(ui_parameters.installing_frames *
-                                      sizeof(gr_surface));
+        gInstallationOverlay = (gr_surface*)malloc(ui_parameters.installing_frames *
+                                                   sizeof(gr_surface));
         for (i = 0; i < ui_parameters.installing_frames; ++i) {
             char filename[40];
             // "icon_installing_overlay01.png",
@@ -529,7 +530,8 @@
     pthread_mutex_unlock(&gUpdateMutex);
 }
 
-void ui_start_menu(char** headers, char** items, int initial_selection) {
+void ui_start_menu(const char* const * headers, const char* const * items,
+                   int initial_selection) {
     int i;
     pthread_mutex_lock(&gUpdateMutex);
     if (text_rows > 0 && text_cols > 0) {
diff --git a/ui.h b/ui.h
new file mode 100644
index 0000000..fa7a53c
--- /dev/null
+++ b/ui.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RECOVERY_UI_H
+#define RECOVERY_UI_H
+
+// Initialize the graphics system.
+void ui_init();
+
+// Use KEY_* codes from <linux/input.h> or KEY_DREAM_* from "minui/minui.h".
+int ui_wait_key();            // waits for a key/button press, returns the code
+int ui_key_pressed(int key);  // returns >0 if the code is currently pressed
+int ui_text_visible();        // returns >0 if text log is currently visible
+int ui_text_ever_visible();   // returns >0 if text log was ever visible
+void ui_show_text(int visible);
+void ui_clear_key_queue();
+
+// Write a message to the on-screen log shown with Alt-L (also to stderr).
+// The screen is small, and users may need to report these messages to support,
+// so keep the output short and not too cryptic.
+void ui_print(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
+
+// Display some header text followed by a menu of items, which appears
+// at the top of the screen (in place of any scrolling ui_print()
+// output, if necessary).
+void ui_start_menu(const char* const * headers, const char* const * items,
+                   int initial_selection);
+// Set the menu highlight to the given index, and return it (capped to
+// the range [0..numitems).
+int ui_menu_select(int sel);
+// End menu mode, resetting the text overlay so that ui_print()
+// statements will be displayed.
+void ui_end_menu();
+
+// Set the icon (normally the only thing visible besides the progress bar).
+enum {
+  BACKGROUND_ICON_NONE,
+  BACKGROUND_ICON_INSTALLING,
+  BACKGROUND_ICON_ERROR,
+  NUM_BACKGROUND_ICONS
+};
+void ui_set_background(int icon);
+
+// Show a progress bar and define the scope of the next operation:
+//   portion - fraction of the progress bar the next operation will use
+//   seconds - expected time interval (progress bar moves at this minimum rate)
+void ui_show_progress(float portion, int seconds);
+void ui_set_progress(float fraction);  // 0.0 - 1.0 within the defined scope
+
+// Default allocation of progress bar segments to operations
+static const int VERIFICATION_PROGRESS_TIME = 60;
+static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
+static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
+static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
+
+// Show a rotating "barberpole" for ongoing operations.  Updates automatically.
+void ui_show_indeterminate_progress();
+
+// Hide and reset the progress bar.
+void ui_reset_progress();
+
+#endif  // RECOVERY_UI_H
diff --git a/verifier.c b/verifier.cpp
similarity index 94%
rename from verifier.c
rename to verifier.cpp
index 729e085..58ca723 100644
--- a/verifier.c
+++ b/verifier.cpp
@@ -16,6 +16,7 @@
 
 #include "common.h"
 #include "verifier.h"
+#include "ui.h"
 
 #include "mincrypt/rsa.h"
 #include "mincrypt/sha.h"
@@ -69,8 +70,8 @@
         return VERIFY_FAILURE;
     }
 
-    int comment_size = footer[4] + (footer[5] << 8);
-    int signature_start = footer[0] + (footer[1] << 8);
+    size_t comment_size = footer[4] + (footer[5] << 8);
+    size_t signature_start = footer[0] + (footer[1] << 8);
     LOGI("comment is %d bytes; signature %d bytes from end\n",
          comment_size, signature_start);
 
@@ -99,7 +100,7 @@
     // bytes) and the comment data.
     size_t signed_len = ftell(f) + EOCD_HEADER_SIZE - 2;
 
-    unsigned char* eocd = malloc(eocd_size);
+    unsigned char* eocd = (unsigned char*)malloc(eocd_size);
     if (eocd == NULL) {
         LOGE("malloc for EOCD record failed\n");
         fclose(f);
@@ -120,7 +121,7 @@
         return VERIFY_FAILURE;
     }
 
-    int i;
+    size_t i;
     for (i = 4; i < eocd_size-3; ++i) {
         if (eocd[i  ] == 0x50 && eocd[i+1] == 0x4b &&
             eocd[i+2] == 0x05 && eocd[i+3] == 0x06) {
@@ -138,7 +139,7 @@
 
     SHA_CTX ctx;
     SHA_init(&ctx);
-    unsigned char* buffer = malloc(BUFFER_SIZE);
+    unsigned char* buffer = (unsigned char*)malloc(BUFFER_SIZE);
     if (buffer == NULL) {
         LOGE("failed to alloc memory for sha1 buffer\n");
         fclose(f);
@@ -149,7 +150,7 @@
     size_t so_far = 0;
     fseek(f, 0, SEEK_SET);
     while (so_far < signed_len) {
-        int size = BUFFER_SIZE;
+        size_t size = BUFFER_SIZE;
         if (signed_len - so_far < size) size = signed_len - so_far;
         if (fread(buffer, 1, size, f) != size) {
             LOGE("failed to read data from %s (%s)\n", path, strerror(errno));
diff --git a/verifier_test.c b/verifier_test.cpp
similarity index 100%
rename from verifier_test.c
rename to verifier_test.cpp
diff --git a/verifier_test.sh b/verifier_test.sh
index 6350e80..a1de5c5 100755
--- a/verifier_test.sh
+++ b/verifier_test.sh
@@ -1,11 +1,7 @@
 #!/bin/bash
 #
-# A test suite for applypatch.  Run in a client where you have done
-# envsetup, choosecombo, etc.
-#
-# DO NOT RUN THIS ON A DEVICE YOU CARE ABOUT.  It will mess up your
-# system partition.
-#
+# A test suite for recovery's package signature verifier.  Run in a
+# client where you have done envsetup, lunch, etc.
 #
 # TODO: find some way to get this run regularly along with the rest of
 # the tests.