Merge "Pixelflinger: Support for handling 64-bit addresses in GGL Assembler"
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
index beb8bda..6e52c3b 100644
--- a/include/sysutils/NetlinkListener.h
+++ b/include/sysutils/NetlinkListener.h
@@ -21,7 +21,7 @@
 class NetlinkEvent;
 
 class NetlinkListener : public SocketListener {
-    char mBuffer[64 * 1024];
+    char mBuffer[64 * 1024] __attribute__((aligned(4)));
     int mFormat;
 
 public:
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index ac3d792..1877494 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -152,7 +152,10 @@
 int32_t Next(void* cookie, ZipEntry* data, ZipEntryName *name);
 
 /*
- * Uncompress and write an entry to a file descriptor.
+ * Uncompress and write an entry to an open file identified by |fd|.
+ * |entry->uncompressed_length| bytes will be written to the file at
+ * its current offset, and the file will be truncated at the end of
+ * the uncompressed data.
  *
  * Returns 0 on success and negative values on failure.
  */
diff --git a/libion/ion_test.c b/libion/ion_test.c
index d2c37ca..8179b57 100644
--- a/libion/ion_test.c
+++ b/libion/ion_test.c
@@ -73,7 +73,7 @@
 	}
 	for (i = 0; i < len; i++)
 		if (ptr[i] != (unsigned char)i)
-			printf("%s failed wrote %d read %d from mapped "
+			printf("%s failed wrote %zu read %d from mapped "
 			       "memory\n", __func__, i, ptr[i]);
 	/* clean up properly */
 	ret = ion_free(fd, handle);
@@ -257,7 +257,7 @@
 			break;
 		}
 	}
-	printf("test %d, len %u, align %u, map_flags %d, prot %d, heap_mask %d,"
+	printf("test %d, len %zu, align %zu, map_flags %d, prot %d, heap_mask %d,"
 	       " alloc_flags %d\n", test, len, align, map_flags, prot,
 	       heap_mask, alloc_flags);
 	switch (test) {
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 4143fac..2b827b3 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -818,7 +818,7 @@
     archive->hash_table_size, entryName, nameLen);
 
   if (ent < 0) {
-    ALOGW("Zip: Could not find entry %.*s", nameLen, entryName);
+    ALOGD("Zip: Could not find entry %.*s", nameLen, entryName);
     return ent;
   }
 
@@ -1007,13 +1007,21 @@
                            ZipEntry* entry, int fd) {
   const int32_t declared_length = entry->uncompressed_length;
 
-  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length));
-  if (result == -1) {
-    ALOGW("Zip: unable to truncate file to %ud", declared_length);
+  const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
+  if (current_offset == -1) {
+    ALOGW("Zip: unable to seek to current location on fd %d: %s", fd,
+          strerror(errno));
     return kIoError;
   }
 
-  android::FileMap* map  = MapFileSegment(fd, 0, declared_length,
+  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+  if (result == -1) {
+    ALOGW("Zip: unable to truncate file to %lld: %s", declared_length + current_offset,
+          strerror(errno));
+    return kIoError;
+  }
+
+  android::FileMap* map  = MapFileSegment(fd, current_offset, declared_length,
                                           false, kTempMappingFileName);
   if (map == NULL) {
     return kMmapFailed;
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 55cb755..022be5b 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -16,8 +16,12 @@
 
 #include "ziparchive/zip_archive.h"
 
-#include "getopt.h"
+#include <errno.h>
+#include <getopt.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <vector>
+
 #include <gtest/gtest.h>
 
 static std::string test_data_dir;
@@ -136,6 +140,43 @@
   CloseArchive(handle);
 }
 
+TEST(ziparchive, ExtractToFile) {
+  char kTempFilePattern[] = "zip_archive_test_XXXXXX";
+  int fd = mkstemp(kTempFilePattern);
+  ASSERT_NE(-1, fd);
+  const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
+  const ssize_t data_size = sizeof(data);
+
+  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));
+
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  ZipEntry entry;
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
+  ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));
+
+
+  // Assert that the first 8 bytes of the file haven't been clobbered.
+  uint8_t read_buffer[data_size];
+  ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
+  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
+  ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
+
+  // Assert that the remainder of the file contains the incompressed data.
+  std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
+  ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
+            TEMP_FAILURE_RETRY(
+                read(fd, &uncompressed_data[0], entry.uncompressed_length)));
+  ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
+                      sizeof(kATxtContents)));
+
+  // Assert that the total length of the file is sane
+  ASSERT_EQ(data_size + sizeof(kATxtContents), lseek64(fd, 0, SEEK_END));
+
+  close(fd);
+}
+
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d1822cf..9706c89 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -211,6 +211,7 @@
     mkdir /data/misc/radio 0770 system radio
     mkdir /data/misc/sms 0770 system radio
     mkdir /data/misc/zoneinfo 0775 system system
+    restorecon_recursive /data/misc/zoneinfo
     mkdir /data/misc/vpn 0770 system vpn
     mkdir /data/misc/systemkeys 0700 system system
     # give system access to wpa_supplicant.conf for backup and restore