Merge "minadbd: update service_to_fd() signature."
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index 4d83ffb..50cabbe 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -628,7 +628,15 @@
   }
 
   char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
-  mkstemp(ptemp);
+  int fd = mkstemp(ptemp);
+
+  if (fd == -1) {
+    printf("MakePatch failed to create a temporary file: %s\n",
+           strerror(errno));
+    return NULL;
+  }
+  close(fd); // temporary file is created and we don't need its file
+             // descriptor
 
   int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp);
   if (r != 0) {
diff --git a/recovery.cpp b/recovery.cpp
index c683bae..379137a 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -745,10 +745,7 @@
         int chosen_item = get_menu_selection(headers, entries, 1, 0, device);
         if (strcmp(entries[chosen_item], "Back") == 0) break;
 
-        // TODO: do we need to redirect? ShowFile could just avoid writing to stdio.
-        redirect_stdio("/dev/null");
         ui->ShowFile(entries[chosen_item]);
-        redirect_stdio(TEMPORARY_LOG_FILE);
     }
 
     for (size_t i = 0; i < (sizeof(entries) / sizeof(*entries)); i++) {
diff --git a/screen_ui.cpp b/screen_ui.cpp
index ddf85c1..f2fda2f 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -581,7 +581,7 @@
     bool show_prompt = false;
     while (true) {
         if (show_prompt) {
-            Print("--(%d%% of %d bytes)--",
+            PrintOnScreenOnly("--(%d%% of %d bytes)--",
                   static_cast<int>(100 * (double(ftell(fp)) / double(sb.st_size))),
                   static_cast<int>(sb.st_size));
             Redraw();
diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk
index f31db42..6422cb2 100644
--- a/uncrypt/Android.mk
+++ b/uncrypt/Android.mk
@@ -26,4 +26,6 @@
 
 LOCAL_STATIC_LIBRARIES := libbase liblog libfs_mgr libcutils
 
+LOCAL_INIT_RC := uncrypt.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/uncrypt/uncrypt.rc b/uncrypt/uncrypt.rc
new file mode 100644
index 0000000..5f4c479
--- /dev/null
+++ b/uncrypt/uncrypt.rc
@@ -0,0 +1,9 @@
+service uncrypt /system/bin/uncrypt
+    class main
+    disabled
+    oneshot
+
+service pre-recovery /system/bin/uncrypt --reboot
+    class main
+    disabled
+    oneshot
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 5f5f9bd..091bedf 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -378,19 +378,16 @@
 //    <src_range> <tgt_range>
 //
 // The source range is loaded into the provided buffer, reallocating
-// it to make it larger if necessary.  The target ranges are returned
-// in *tgt, if tgt is non-null.
+// it to make it larger if necessary.
 
-static int LoadSrcTgtVersion1(char** wordsave, RangeSet* tgt, size_t& src_blocks,
+static int LoadSrcTgtVersion1(char** wordsave, RangeSet& tgt, size_t& src_blocks,
         uint8_t** buffer, size_t* buffer_alloc, int fd) {
     char* word = strtok_r(nullptr, " ", wordsave);
     RangeSet src;
     parse_range(word, src);
 
-    if (tgt != nullptr) {
-        word = strtok_r(nullptr, " ", wordsave);
-        parse_range(word, *tgt);
-    }
+    word = strtok_r(nullptr, " ", wordsave);
+    parse_range(word, tgt);
 
     allocate(src.size * BLOCKSIZE, buffer, buffer_alloc);
     int rc = ReadBlocks(src, *buffer, fd);
@@ -730,9 +727,15 @@
         return 0;
     }
 
-    if (LoadSrcTgtVersion1(wordsave, nullptr, blocks, buffer, buffer_alloc, fd) == -1) {
+    char* word = strtok_r(nullptr, " ", wordsave);
+    RangeSet src;
+    parse_range(word, src);
+
+    allocate(src.size * BLOCKSIZE, buffer, buffer_alloc);
+    if (ReadBlocks(src, *buffer, fd) == -1) {
         return -1;
     }
+    blocks = src.size;
 
     if (usehash && VerifyBlocks(id, *buffer, blocks, true) != 0) {
         // Source blocks have unexpected contents. If we actually need this
@@ -791,7 +794,7 @@
 // reallocated if needed to accommodate the source data.  *tgt is the
 // target RangeSet.  Any stashes required are loaded using LoadStash.
 
-static int LoadSrcTgtVersion2(char** wordsave, RangeSet* tgt, size_t& src_blocks, uint8_t** buffer,
+static int LoadSrcTgtVersion2(char** wordsave, RangeSet& tgt, size_t& src_blocks, uint8_t** buffer,
         size_t* buffer_alloc, int fd, const std::string& stashbase, bool* overlap) {
     char* word;
     char* colonsave;
@@ -800,10 +803,8 @@
     size_t stashalloc = 0;
     uint8_t* stash = nullptr;
 
-    if (tgt != nullptr) {
-        word = strtok_r(nullptr, " ", wordsave);
-        parse_range(word, *tgt);
-    }
+    word = strtok_r(nullptr, " ", wordsave);
+    parse_range(word, tgt);
 
     word = strtok_r(nullptr, " ", wordsave);
     src_blocks = strtol(word, nullptr, 0);
@@ -818,8 +819,8 @@
         parse_range(word, src);
         int res = ReadBlocks(src, *buffer, fd);
 
-        if (overlap && tgt) {
-            *overlap = range_overlaps(src, *tgt);
+        if (overlap) {
+            *overlap = range_overlaps(src, tgt);
         }
 
         if (res == -1) {
@@ -902,13 +903,9 @@
 // If the return value is 0, source blocks have expected content and the command
 // can be performed.
 
-static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet* tgt, size_t& src_blocks,
+static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& src_blocks,
         bool onehash, bool& overlap) {
 
-    if (!tgt) {
-        return -1;
-    }
-
     char* srchash = strtok_r(nullptr, " ", &params.cpos);
     if (srchash == nullptr) {
         fprintf(stderr, "missing source hash\n");
@@ -932,13 +929,13 @@
         return -1;
     }
 
-    std::vector<uint8_t> tgtbuffer(tgt->size * BLOCKSIZE);
+    std::vector<uint8_t> tgtbuffer(tgt.size * BLOCKSIZE);
 
-    if (ReadBlocks(*tgt, tgtbuffer.data(), params.fd) == -1) {
+    if (ReadBlocks(tgt, tgtbuffer.data(), params.fd) == -1) {
         return -1;
     }
 
-    if (VerifyBlocks(tgthash, tgtbuffer.data(), tgt->size, false) == 0) {
+    if (VerifyBlocks(tgthash, tgtbuffer.data(), tgt.size, false) == 0) {
         // Target blocks already have expected content, command should be skipped
         fprintf(stderr, "verified, to return 1");
         return 1;
@@ -989,13 +986,13 @@
     RangeSet tgt;
 
     if (params.version == 1) {
-        status = LoadSrcTgtVersion1(&params.cpos, &tgt, blocks, &params.buffer,
+        status = LoadSrcTgtVersion1(&params.cpos, tgt, blocks, &params.buffer,
                     &params.bufsize, params.fd);
     } else if (params.version == 2) {
-        status = LoadSrcTgtVersion2(&params.cpos, &tgt, blocks, &params.buffer,
+        status = LoadSrcTgtVersion2(&params.cpos, tgt, blocks, &params.buffer,
                     &params.bufsize, params.fd, params.stashbase, nullptr);
     } else if (params.version >= 3) {
-        status = LoadSrcTgtVersion3(params, &tgt, blocks, true, overlap);
+        status = LoadSrcTgtVersion3(params, tgt, blocks, true, overlap);
     }
 
     if (status == -1) {
@@ -1149,13 +1146,13 @@
     size_t blocks = 0;
     int status = 0;
     if (params.version == 1) {
-        status = LoadSrcTgtVersion1(&params.cpos, &tgt, blocks, &params.buffer,
+        status = LoadSrcTgtVersion1(&params.cpos, tgt, blocks, &params.buffer,
                     &params.bufsize, params.fd);
     } else if (params.version == 2) {
-        status = LoadSrcTgtVersion2(&params.cpos, &tgt, blocks, &params.buffer,
+        status = LoadSrcTgtVersion2(&params.cpos, tgt, blocks, &params.buffer,
                     &params.bufsize, params.fd, params.stashbase, nullptr);
     } else if (params.version >= 3) {
-        status = LoadSrcTgtVersion3(params, &tgt, blocks, false, overlap);
+        status = LoadSrcTgtVersion3(params, tgt, blocks, false, overlap);
     }
 
     if (status == -1) {
diff --git a/updater/install.cpp b/updater/install.cpp
index 422a1bb..a6ed078 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -34,6 +34,9 @@
 #include <linux/xattr.h>
 #include <inttypes.h>
 
+#include <base/strings.h>
+#include <base/stringprintf.h>
+
 #include "bootloader.h"
 #include "applypatch/applypatch.h"
 #include "cutils/android_reboot.h"
@@ -53,28 +56,35 @@
 #include "wipe.h"
 #endif
 
-void uiPrint(State* state, char* buffer) {
-    char* line = strtok(buffer, "\n");
-    UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
-    while (line) {
-        fprintf(ui->cmd_pipe, "ui_print %s\n", line);
-        line = strtok(NULL, "\n");
-    }
-    fprintf(ui->cmd_pipe, "ui_print\n");
+// Send over the buffer to recovery though the command pipe.
+static void uiPrint(State* state, const std::string& buffer) {
+    UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie);
 
-    // The recovery will only print the contents to screen for pipe command
-    // ui_print. We need to dump the contents to stderr (which has been
-    // redirected to the log file) directly.
-    fprintf(stderr, "%s", buffer);
+    // "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
+    // So skip sending empty strings to UI.
+    std::vector<std::string> lines = android::base::Split(buffer, "\n");
+    for (auto& line: lines) {
+        if (!line.empty()) {
+            fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
+            fprintf(ui->cmd_pipe, "ui_print\n");
+        }
+    }
+
+    // On the updater side, we need to dump the contents to stderr (which has
+    // been redirected to the log file). Because the recovery will only print
+    // the contents to screen when processing pipe command ui_print.
+    fprintf(stderr, "%s", buffer.c_str());
 }
 
 __attribute__((__format__(printf, 2, 3))) __nonnull((2))
 void uiPrintf(State* state, const char* format, ...) {
-    char error_msg[1024];
+    std::string error_msg;
+
     va_list ap;
     va_start(ap, format);
-    vsnprintf(error_msg, sizeof(error_msg), format, ap);
+    android::base::StringAppendV(&error_msg, format, ap);
     va_end(ap);
+
     uiPrint(state, error_msg);
 }
 
@@ -159,7 +169,7 @@
         const MtdPartition* mtd;
         mtd = mtd_find_partition_by_name(location);
         if (mtd == NULL) {
-            uiPrintf(state, "%s: no mtd partition named \"%s\"",
+            uiPrintf(state, "%s: no mtd partition named \"%s\"\n",
                     name, location);
             result = strdup("");
             goto done;
@@ -1246,28 +1256,24 @@
     return StringValue(strdup(result == 0 ? "t" : ""));
 }
 
+// This is the updater side handler for ui_print() in edify script. Contents
+// will be sent over to the recovery side for on-screen display.
 Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
     char** args = ReadVarArgs(state, argc, argv);
     if (args == NULL) {
         return NULL;
     }
 
-    int size = 0;
-    int i;
-    for (i = 0; i < argc; ++i) {
-        size += strlen(args[i]);
-    }
-    char* buffer = reinterpret_cast<char*>(malloc(size+1));
-    size = 0;
-    for (i = 0; i < argc; ++i) {
-        strcpy(buffer+size, args[i]);
-        size += strlen(args[i]);
+    std::string buffer;
+    for (int i = 0; i < argc; ++i) {
+        buffer += args[i];
         free(args[i]);
     }
     free(args);
-    buffer[size] = '\0';
+
+    buffer += "\n";
     uiPrint(state, buffer);
-    return StringValue(buffer);
+    return StringValue(strdup(buffer.c_str()));
 }
 
 Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {