updater: Check the return value from ApplyImagePatch / ApplyBSDiffPatch

Return NULL to abort the update process. Note that returning ""
won't stop the script.

Change-Id: Ifd108c1356f7c92a905c8776247a8842c6445319
diff --git a/recovery.cpp b/recovery.cpp
index 1d22b24..6deeaaa 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1107,6 +1107,7 @@
         }
         if (status != INSTALL_SUCCESS) {
             ui->Print("Installation aborted.\n");
+            ui->Print("OTA failed! Please power off the device to keep it in this state and file a bug report!\n");
 
             // If this is an eng or userdebug build, then automatically
             // turn the text display on if the script fails so the error
diff --git a/updater/blockimg.c b/updater/blockimg.c
index 3026893..6060ac2 100644
--- a/updater/blockimg.c
+++ b/updater/blockimg.c
@@ -687,19 +687,26 @@
             rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
             check_lseek(fd, (off64_t)tgt->pos[0] * BLOCKSIZE, SEEK_SET);
 
+            int ret;
             if (style[0] == 'i') {      // imgdiff
-                ApplyImagePatch(buffer, src_blocks * BLOCKSIZE,
-                                &patch_value,
-                                &RangeSinkWrite, &rss, NULL, NULL);
+                ret = ApplyImagePatch(buffer, src_blocks * BLOCKSIZE,
+                                      &patch_value,
+                                      &RangeSinkWrite, &rss, NULL, NULL);
             } else {
-                ApplyBSDiffPatch(buffer, src_blocks * BLOCKSIZE,
-                                 &patch_value, 0,
-                                 &RangeSinkWrite, &rss, NULL);
+                ret = ApplyBSDiffPatch(buffer, src_blocks * BLOCKSIZE,
+                                       &patch_value, 0,
+                                       &RangeSinkWrite, &rss, NULL);
+            }
+
+            if (ret != 0) {
+                ErrorAbort(state, "patch failed\n");
+                goto done;
             }
 
             // We expect the output of the patcher to fill the tgt ranges exactly.
             if (rss.p_block != tgt->count || rss.p_remain != 0) {
-                fprintf(stderr, "range sink underrun?\n");
+                ErrorAbort(state, "range sink underrun?\n");
+                goto done;
             }
 
             blocks_so_far += tgt->size;
@@ -723,7 +730,8 @@
                     range[1] = (tgt->pos[i*2+1] - tgt->pos[i*2]) * (uint64_t)BLOCKSIZE;
 
                     if (ioctl(fd, BLKDISCARD, &range) < 0) {
-                        printf("    blkdiscard failed: %s\n", strerror(errno));
+                        ErrorAbort(state, "    blkdiscard failed: %s\n", strerror(errno));
+                        goto done;
                     }
                 }
 
@@ -732,8 +740,8 @@
                 printf("  ignoring erase (not block device)\n");
             }
         } else {
-            fprintf(stderr, "unknown transfer style \"%s\"\n", style);
-            exit(1);
+            ErrorAbort(state, "unknown transfer style \"%s\"\n", style);
+            goto done;
         }
     }
 
@@ -744,13 +752,19 @@
     printf("wrote %d blocks; expected %d\n", blocks_so_far, total_blocks);
     printf("max alloc needed was %zu\n", buffer_alloc);
 
-  done:
+done:
     free(transfer_list);
     FreeValue(blockdev_filename);
     FreeValue(transfer_list_value);
     FreeValue(new_data_fn);
     FreeValue(patch_data_fn);
-    return StringValue(success ? strdup("t") : strdup(""));
+    if (success) {
+        return StringValue(strdup("t"));
+    } else {
+        // NULL will be passed to its caller at Evaluate() and abort the OTA
+        // process.
+        return NULL;
+    }
 }
 
 Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -793,11 +807,11 @@
     digest = SHA_final(&ctx);
     close(fd);
 
-  done:
+done:
     FreeValue(blockdev_filename);
     FreeValue(ranges);
     if (digest == NULL) {
-        return StringValue(strdup(""));
+        return NULL;
     } else {
         return StringValue(PrintSha1(digest));
     }