am 49138184: am 9568307c: am 43a4a8c7: Fix redundant file backups

* commit '49138184dee54357b1923f302e4b3fedd73ca34f':
  Fix redundant file backups
diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java
index 5466db5..6811532 100644
--- a/core/java/android/app/backup/BackupHelperDispatcher.java
+++ b/core/java/android/app/backup/BackupHelperDispatcher.java
@@ -50,7 +50,6 @@
         Header header = new Header();
         TreeMap<String,BackupHelper> helpers = (TreeMap<String,BackupHelper>)mHelpers.clone();
         FileDescriptor oldStateFD = null;
-        FileDescriptor newStateFD = newState.getFileDescriptor();
 
         if (oldState != null) {
             oldStateFD = oldState.getFileDescriptor();
diff --git a/include/androidfw/BackupHelpers.h b/include/androidfw/BackupHelpers.h
index 1bb04a7..0841af6 100644
--- a/include/androidfw/BackupHelpers.h
+++ b/include/androidfw/BackupHelpers.h
@@ -152,7 +152,7 @@
     KeyedVector<String8,FileRec> m_files;
 };
 
-#define TEST_BACKUP_HELPERS 1
+//#define TEST_BACKUP_HELPERS 1
 
 #if TEST_BACKUP_HELPERS
 int backup_helper_test_empty();
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index 3f82830..4dcb6e7 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -298,8 +298,12 @@
 }
 
 static int
-compute_crc32(int fd)
-{
+compute_crc32(const char* file, FileRec* out) {
+    int fd = open(file, O_RDONLY);
+    if (fd < 0) {
+        return -1;
+    }
+
     const int bufsize = 4*1024;
     int amt;
 
@@ -312,8 +316,11 @@
         crc = crc32(crc, (Bytef*)buf, amt);
     }
 
+    close(fd);
     free(buf);
-    return crc;
+
+    out->s.crc32 = crc;
+    return NO_ERROR;
 }
 
 int
@@ -341,7 +348,8 @@
 
         err = stat(file, &st);
         if (err != 0) {
-            r.deleted = true;
+            // not found => treat as deleted
+            continue;
         } else {
             r.deleted = false;
             r.s.modTime_sec = st.st_mtime;
@@ -349,12 +357,17 @@
             //r.s.modTime_nsec = st.st_mtime_nsec;
             r.s.mode = st.st_mode;
             r.s.size = st.st_size;
-            // we compute the crc32 later down below, when we already have the file open.
 
             if (newSnapshot.indexOfKey(key) >= 0) {
                 LOGP("back_up_files key already in use '%s'", key.string());
                 return -1;
             }
+
+            // compute the CRC
+            if (compute_crc32(file, &r) != NO_ERROR) {
+                ALOGW("Unable to open file %s", file);
+                continue;
+            }
         }
         newSnapshot.add(key, r);
     }
@@ -362,49 +375,41 @@
     int n = 0;
     int N = oldSnapshot.size();
     int m = 0;
+    int M = newSnapshot.size();
 
-    while (n<N && m<fileCount) {
+    while (n<N && m<M) {
         const String8& p = oldSnapshot.keyAt(n);
         const String8& q = newSnapshot.keyAt(m);
         FileRec& g = newSnapshot.editValueAt(m);
         int cmp = p.compare(q);
-        if (g.deleted || cmp < 0) {
-            // file removed
+        if (cmp < 0) {
+            // file present in oldSnapshot, but not present in newSnapshot
             LOGP("file removed: %s", p.string());
-            g.deleted = true; // They didn't mention the file, but we noticed that it's gone.
-            dataStream->WriteEntityHeader(p, -1);
+            write_delete_file(dataStream, p);
             n++;
-        }
-        else if (cmp > 0) {
+        } else if (cmp > 0) {
             // file added
-            LOGP("file added: %s", g.file.string());
+            LOGP("file added: %s crc=0x%08x", g.file.string(), g.s.crc32);
             write_update_file(dataStream, q, g.file.string());
             m++;
-        }
-        else {
-            // both files exist, check them
+        } else {
+            // same file exists in both old and new; check whether to update
             const FileState& f = oldSnapshot.valueAt(n);
 
-            int fd = open(g.file.string(), O_RDONLY);
-            if (fd < 0) {
-                // We can't open the file.  Don't report it as a delete either.  Let the
-                // server keep the old version.  Maybe they'll be able to deal with it
-                // on restore.
-                LOGP("Unable to open file %s - skipping", g.file.string());
-            } else {
-                g.s.crc32 = compute_crc32(fd);
-
-                LOGP("%s", q.string());
-                LOGP("  new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
-                        f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
-                LOGP("  old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
-                        g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
-                if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
-                        || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
+            LOGP("%s", q.string());
+            LOGP("  old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                    f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
+            LOGP("  new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                    g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
+            if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
+                    || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
+                int fd = open(g.file.string(), O_RDONLY);
+                if (fd < 0) {
+                    ALOGE("Unable to read file for backup: %s", g.file.string());
+                } else {
                     write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
+                    close(fd);
                 }
-
-                close(fd);
             }
             n++;
             m++;
@@ -413,12 +418,12 @@
 
     // these were deleted
     while (n<N) {
-        dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1);
+        write_delete_file(dataStream, oldSnapshot.keyAt(n));
         n++;
     }
 
     // these were added
-    while (m<fileCount) {
+    while (m<M) {
         const String8& q = newSnapshot.keyAt(m);
         FileRec& g = newSnapshot.editValueAt(m);
         write_update_file(dataStream, q, g.file.string());