am 0ccaccf7: am 044a0b4d: recovery: try to write EMMC partitions more reliably

* commit '0ccaccf7d0f50bb9555ee13a841c246a1fea80f2':
  recovery: try to write EMMC partitions more reliably
diff --git a/applypatch/applypatch.c b/applypatch/applypatch.c
index 259fa58..9790de6 100644
--- a/applypatch/applypatch.c
+++ b/applypatch/applypatch.c
@@ -421,18 +421,84 @@
             break;
 
         case EMMC:
-            ;
-            FILE* f = fopen(partition, "wb");
-            if (fwrite(data, 1, len, f) != len) {
-                printf("short write writing to %s (%s)\n",
-                       partition, strerror(errno));
+        {
+            size_t start = 0;
+            int success = 0;
+            FILE* f = fopen(partition, "r+b");
+            if (f == NULL) {
+                printf("failed to open %s: %s\n", partition, strerror(errno));
                 return -1;
             }
+            int attempt;
+
+            for (attempt = 0; attempt < 3; ++attempt) {
+                printf("write %s attempt %d start at %d\n", partition, attempt+1, start);
+                fseek(f, start, SEEK_SET);
+                while (start < len) {
+                    size_t to_write = len - start;
+                    if (to_write > (1<<20)) to_write = 1<<20;
+
+                    if (fwrite(data+start, 1, to_write, f) != to_write) {
+                        printf("short write writing to %s (%s)\n",
+                               partition, strerror(errno));
+                        return -1;
+                    }
+                    start += to_write;
+                    if (start < len) {
+                        usleep(50000);  // 50 ms
+                    }
+                }
+
+                // drop caches so our subsequent verification read
+                // won't just be reading the cache.
+                sync();
+                FILE* dc = fopen("/proc/sys/vm/drop_caches", "w");
+                fwrite("3\n", 2, 1, dc);
+                fclose(dc);
+                sleep(1);
+                printf("  caches dropped\n");
+
+                // verify
+                fseek(f, 0, SEEK_SET);
+                unsigned char buffer[4096];
+                start = len;
+                size_t p;
+                for (p = 0; p < len; p += sizeof(buffer)) {
+                    size_t to_read = len - p;
+                    if (to_read > sizeof(buffer)) to_read = sizeof(buffer);
+
+                    if (fread(buffer, 1, to_read, f) != to_read) {
+                        printf("short verify read %s at %d: %s\n",
+                               partition, p, strerror(errno));
+                        start = p;
+                        break;
+                    }
+
+                    if (memcmp(buffer, data+p, to_read)) {
+                        printf("verification failed starting at %d\n", p);
+                        start = p;
+                        break;
+                    }
+                }
+
+                if (start == len) {
+                    printf("verification read succeeded (attempt %d)\n", attempt+1);
+                    success = true;
+                    break;
+                }
+            }
+
+            if (!success) {
+                printf("failed to verify after all attempts\n");
+                return -1;
+            }
+
             if (fclose(f) != 0) {
                 printf("error closing %s (%s)\n", partition, strerror(errno));
                 return -1;
             }
             break;
+        }
     }
 
     free(copy);
@@ -473,7 +539,7 @@
 // Search an array of sha1 strings for one matching the given sha1.
 // Return the index of the match on success, or -1 if no match is
 // found.
-int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str,
+int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
                       int num_patches) {
     int i;
     uint8_t patch_sha1[SHA_DIGEST_SIZE];
diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h
index d1a0232..f1f13a1 100644
--- a/applypatch/applypatch.h
+++ b/applypatch/applypatch.h
@@ -65,7 +65,7 @@
                      int retouch_flag);
 int SaveFileContents(const char* filename, const FileContents* file);
 void FreeFileContents(FileContents* file);
-int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str,
+int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
                       int num_patches);
 
 // bsdiff.c