Merge "pixelflinger: make self-contained"
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 45d33db..eeb2a9c 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -587,6 +587,7 @@
         FATAL("fde %p not created by fdevent_create()\n", fde);
     }
     fdevent_remove(fde);
+    free(fde);
 }
 
 void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index aa5b14a..b9e957f 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -19,10 +19,11 @@
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \
   $(LOCAL_PATH)/../../extras/ext4_utils \
   $(LOCAL_PATH)/../../extras/f2fs_utils
-LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c util.c fs.c
+LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c
 LOCAL_MODULE := fastboot
 LOCAL_MODULE_TAGS := debug
-LOCAL_CFLAGS += -std=gnu99 -Werror
+LOCAL_CONLYFLAGS += -std=gnu99
+LOCAL_CFLAGS += -Wall -Wextra -Werror
 
 ifeq ($(HOST_OS),linux)
   LOCAL_SRC_FILES += usb_linux.c util_linux.c
@@ -52,9 +53,11 @@
 
 LOCAL_STATIC_LIBRARIES := \
     $(EXTRA_STATIC_LIBS) \
-    libzipfile \
+    libziparchive-host \
     libext4_utils_host \
     libsparse_host \
+    libutils \
+    liblog \
     libz
 
 ifneq ($(HOST_OS),windows)
diff --git a/fastboot/bootimg.c b/fastboot/bootimg_utils.cpp
similarity index 95%
rename from fastboot/bootimg.c
rename to fastboot/bootimg_utils.cpp
index 240784f..d8905a6 100644
--- a/fastboot/bootimg.c
+++ b/fastboot/bootimg_utils.cpp
@@ -26,12 +26,12 @@
  * SUCH DAMAGE.
  */
 
+#include "bootimg_utils.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <bootimg.h>
-
 void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
 {
     strcpy((char*) h->cmdline, cmdline);
@@ -47,7 +47,6 @@
     unsigned ramdisk_actual;
     unsigned second_actual;
     unsigned page_mask;
-    boot_img_hdr *hdr;
 
     page_mask = page_size - 1;
 
@@ -57,9 +56,8 @@
 
     *bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual;
 
-    hdr = calloc(*bootimg_size, 1);
-
-    if(hdr == 0) {
+    boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1));
+    if (hdr == 0) {
         return hdr;
     }
 
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
new file mode 100644
index 0000000..b1a86cd
--- /dev/null
+++ b/fastboot/bootimg_utils.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _FASTBOOT_BOOTIMG_UTILS_H_
+#define _FASTBOOT_BOOTIMG_UTILS_H_
+
+#include <bootimg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+                        void *second, unsigned second_size, unsigned second_offset,
+                        unsigned page_size, unsigned base, unsigned tags_offset,
+                        unsigned *bootimg_size);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.cpp
similarity index 90%
rename from fastboot/fastboot.c
rename to fastboot/fastboot.cpp
index fc544a6..6dc7d34 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.cpp
@@ -44,10 +44,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <bootimg.h>
 #include <sparse/sparse.h>
-#include <zipfile/zipfile.h>
+#include <ziparchive/zip_archive.h>
 
+#include "bootimg_utils.h"
 #include "fastboot.h"
 #include "fs.h"
 
@@ -59,14 +59,6 @@
 
 char cur_product[FB_RESPONSE_SZ + 1];
 
-void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
-
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
-                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
-                        void *second, unsigned second_size, unsigned second_offset,
-                        unsigned page_size, unsigned base, unsigned tags_offset,
-                        unsigned *bootimg_size);
-
 static usb_handle *usb = 0;
 static const char *serial = 0;
 static const char *product = 0;
@@ -106,12 +98,10 @@
     {"vendor.img", "vendor.sig", "vendor", true},
 };
 
-void get_my_path(char *path);
-
 char *find_item(const char *item, const char *product)
 {
     char *dir;
-    char *fn;
+    const char *fn;
     char path[PATH_MAX + 128];
 
     if(!strcmp(item,"boot")) {
@@ -234,7 +224,7 @@
 int list_devices_callback(usb_ifc_info *info)
 {
     if (match_fastboot_with_serial(info, NULL) == 0) {
-        char* serial = info->serial_number;
+        const char* serial = info->serial_number;
         if (!info->writable) {
             serial = "no permissions"; // like "adb devices"
         }
@@ -389,30 +379,26 @@
     return bdata;
 }
 
-void *unzip_file(zipfile_t zip, const char *name, unsigned *sz)
+static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz)
 {
-    void *data;
-    zipentry_t entry;
-    unsigned datasz;
-
-    entry = lookup_zipentry(zip, name);
-    if (entry == NULL) {
-        fprintf(stderr, "archive does not contain '%s'\n", name);
+    ZipEntryName zip_entry_name(entry_name);
+    ZipEntry zip_entry;
+    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
         return 0;
     }
 
-    *sz = get_zipentry_size(entry);
+    *sz = zip_entry.uncompressed_length;
 
-    datasz = *sz * 1.001;
-    data = malloc(datasz);
-
-    if(data == 0) {
-        fprintf(stderr, "failed to allocate %d bytes\n", *sz);
+    uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
+    if (data == NULL) {
+        fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name);
         return 0;
     }
 
-    if (decompress_zipentry(entry, data, datasz)) {
-        fprintf(stderr, "failed to unzip '%s' from archive\n", name);
+    int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
+    if (error != 0) {
+        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
         free(data);
         return 0;
     }
@@ -420,27 +406,28 @@
     return data;
 }
 
-static int unzip_to_file(zipfile_t zip, char *name)
-{
-    int fd;
-    char *data;
-    unsigned sz;
-
-    fd = fileno(tmpfile());
-    if (fd < 0) {
+static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) {
+    FILE* fp = tmpfile();
+    if (fp == NULL) {
+        fprintf(stderr, "failed to create temporary file for '%s': %s\n",
+                entry_name, strerror(errno));
         return -1;
     }
 
-    data = unzip_file(zip, name, &sz);
-    if (data == 0) {
+    ZipEntryName zip_entry_name(entry_name);
+    ZipEntry zip_entry;
+    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+        fprintf(stderr, "archive does not contain '%s'\n", entry_name);
         return -1;
     }
 
-    if (write(fd, data, sz) != (ssize_t)sz) {
-        fd = -1;
+    int fd = fileno(fp);
+    int error = ExtractEntryToFile(zip, &zip_entry, fd);
+    if (error != 0) {
+        fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
+        return -1;
     }
 
-    free(data);
     lseek(fd, 0, SEEK_SET);
     return fd;
 }
@@ -461,7 +448,6 @@
 static int setup_requirement_line(char *name)
 {
     char *val[MAX_OPTIONS];
-    const char **out;
     char *prod = NULL;
     unsigned n, count;
     char *x;
@@ -501,10 +487,11 @@
     name = strip(name);
     if (name == 0) return -1;
 
-        /* work around an unfortunate name mismatch */
-    if (!strcmp(name,"board")) name = "product";
+    const char* var = name;
+    // Work around an unfortunate name mismatch.
+    if (!strcmp(name,"board")) var = "product";
 
-    out = malloc(sizeof(char*) * count);
+    const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count));
     if (out == 0) return -1;
 
     for(n = 0; n < count; n++) {
@@ -518,7 +505,7 @@
         }
     }
 
-    fb_queue_require(prod, name, invert, n, out);
+    fb_queue_require(prod, var, invert, n, out);
     return 0;
 }
 
@@ -551,21 +538,17 @@
 
 static struct sparse_file **load_sparse_files(int fd, int max_size)
 {
-    struct sparse_file *s;
-    int files;
-    struct sparse_file **out_s;
-
-    s = sparse_file_import_auto(fd, false);
+    struct sparse_file* s = sparse_file_import_auto(fd, false);
     if (!s) {
         die("cannot sparse read file\n");
     }
 
-    files = sparse_file_resparse(s, max_size, NULL, 0);
+    int files = sparse_file_resparse(s, max_size, NULL, 0);
     if (files < 0) {
         die("Failed to resparse\n");
     }
 
-    out_s = calloc(sizeof(struct sparse_file *), files + 1);
+    sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1));
     if (!out_s) {
         die("Failed to allocate sparse file array\n");
     }
@@ -682,11 +665,11 @@
 
 static void flash_buf(const char *pname, struct fastboot_buffer *buf)
 {
-    struct sparse_file **s;
+    sparse_file** s;
 
     switch (buf->type) {
         case FB_BUFFER_SPARSE:
-            s = buf->data;
+            s = reinterpret_cast<sparse_file**>(buf->data);
             while (*s) {
                 int64_t sz64 = sparse_file_len(*s, true, false);
                 fb_queue_flash_sparse(pname, *s++, sz64);
@@ -710,63 +693,44 @@
     flash_buf(pname, &buf);
 }
 
-void do_update_signature(zipfile_t zip, char *fn)
+void do_update_signature(ZipArchiveHandle zip, char *fn)
 {
-    void *data;
     unsigned sz;
-    data = unzip_file(zip, fn, &sz);
+    void* data = unzip_file(zip, fn, &sz);
     if (data == 0) return;
     fb_queue_download("signature", data, sz);
     fb_queue_command("signature", "installing signature");
 }
 
-void do_update(usb_handle *usb, char *fn, int erase_first)
+void do_update(usb_handle *usb, const char *filename, int erase_first)
 {
-    void *zdata;
-    unsigned zsize;
-    void *data;
-    unsigned sz;
-    zipfile_t zip;
-    int fd;
-    int rc;
-    struct fastboot_buffer buf;
-    size_t i;
-
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
-    zdata = load_file(fn, &zsize);
-    if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno));
-
-    zip = init_zipfile(zdata, zsize);
-    if(zip == 0) die("failed to access zipdata in '%s'");
-
-    data = unzip_file(zip, "android-info.txt", &sz);
-    if (data == 0) {
-        char *tmp;
-            /* fallback for older zipfiles */
-        data = unzip_file(zip, "android-product.txt", &sz);
-        if ((data == 0) || (sz < 1)) {
-            die("update package has no android-info.txt or android-product.txt");
-        }
-        tmp = malloc(sz + 128);
-        if (tmp == 0) die("out of memory");
-        sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data);
-        data = tmp;
-        sz = strlen(tmp);
+    ZipArchiveHandle zip;
+    int error = OpenArchive(filename, &zip);
+    if (error != 0) {
+        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
     }
 
-    setup_requirements(data, sz);
+    unsigned sz;
+    void* data = unzip_file(zip, "android-info.txt", &sz);
+    if (data == 0) {
+        die("update package '%s' has no android-info.txt", filename);
+    }
 
-    for (i = 0; i < ARRAY_SIZE(images); i++) {
-        fd = unzip_to_file(zip, images[i].img_name);
+    setup_requirements(reinterpret_cast<char*>(data), sz);
+
+    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
+        int fd = unzip_to_file(zip, images[i].img_name);
         if (fd < 0) {
             if (images[i].is_optional)
                 continue;
             die("update package missing %s", images[i].img_name);
         }
-        rc = load_buf_fd(usb, fd, &buf);
+        fastboot_buffer buf;
+        int rc = load_buf_fd(usb, fd, &buf);
         if (rc) die("cannot load %s from flash", images[i].img_name);
         do_update_signature(zip, images[i].sig_name);
         if (erase_first && needs_erase(images[i].part_name)) {
@@ -778,6 +742,8 @@
          * program exits.
          */
     }
+
+    CloseArchive(zip);
 }
 
 void do_send_signature(char *fn)
@@ -800,24 +766,22 @@
 
 void do_flashall(usb_handle *usb, int erase_first)
 {
-    char *fname;
-    void *data;
-    unsigned sz;
-    struct fastboot_buffer buf;
-    size_t i;
-
     queue_info_dump();
 
     fb_queue_query_save("product", cur_product, sizeof(cur_product));
 
-    fname = find_item("info", product);
+    char* fname = find_item("info", product);
     if (fname == 0) die("cannot find android-info.txt");
-    data = load_file(fname, &sz);
-    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
-    setup_requirements(data, sz);
 
-    for (i = 0; i < ARRAY_SIZE(images); i++) {
+    unsigned sz;
+    void* data = load_file(fname, &sz);
+    if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
+
+    setup_requirements(reinterpret_cast<char*>(data), sz);
+
+    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
         fname = find_item(images[i].part_name, product);
+        fastboot_buffer buf;
         if (load_buf(usb, fname, &buf)) {
             if (images[i].is_optional)
                 continue;
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index fc5d4f4..1786e49 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -31,6 +31,10 @@
 
 #include "usb.h"
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 struct sparse_file;
 
 /* protocol.c - fastboot protocol */
@@ -67,7 +71,13 @@
 char *mkmsg(const char *fmt, ...);
 void die(const char *fmt, ...);
 
+void get_my_path(char *path);
+
 /* Current product */
 extern char cur_product[FB_RESPONSE_SZ + 1];
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/fastboot/fs.h b/fastboot/fs.h
index 8444081..307772b 100644
--- a/fastboot/fs.h
+++ b/fastboot/fs.h
@@ -3,10 +3,18 @@
 
 #include <stdint.h>
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 struct fs_generator;
 
 const struct fs_generator* fs_get_generator(const char *fs_type);
 int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize);
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
 
diff --git a/fastboot/protocol.c b/fastboot/protocol.c
index 10a84c1..5b97600 100644
--- a/fastboot/protocol.c
+++ b/fastboot/protocol.c
@@ -305,7 +305,10 @@
         return -1;
     }
 
-    fb_download_data_sparse_flush(usb);
+    r = fb_download_data_sparse_flush(usb);
+    if (r < 0) {
+        return -1;
+    }
 
     return _command_end(usb);
 }
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 17cf0a9..c7b748e 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -29,6 +29,10 @@
 #ifndef _USB_H_
 #define _USB_H_
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 typedef struct usb_handle usb_handle;
 
 typedef struct usb_ifc_info usb_ifc_info;
@@ -64,4 +68,8 @@
 int usb_write(usb_handle *h, const void *_data, int len);
 int usb_wait_for_disconnect(usb_handle *h);
 
+#if defined(__cplusplus)
+}
+#endif
+
 #endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 543f89b..fb1aa7c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -104,12 +104,6 @@
     }
 }
 
-int do_chroot(int nargs, char **args)
-{
-    chroot(args[1]);
-    return 0;
-}
-
 int do_class_start(int nargs, char **args)
 {
         /* Starting a class does not start services
diff --git a/init/init.cpp b/init/init.cpp
index 3c6e8a4..e1c82a4 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -679,7 +679,6 @@
     if (urandom_fd != -1) {
         close(urandom_fd);
     }
-    memset(buf, 0, sizeof(buf));
     return result;
 }
 
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 5ef54c8..f3d34b2 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -121,7 +121,6 @@
     case 'c':
         if (!strcmp(s, "opy")) return K_copy;
         if (!strcmp(s, "apability")) return K_capability;
-        if (!strcmp(s, "hroot")) return K_chroot;
         if (!strcmp(s, "lass")) return K_class;
         if (!strcmp(s, "lass_start")) return K_class_start;
         if (!strcmp(s, "lass_stop")) return K_class_stop;
diff --git a/init/keywords.h b/init/keywords.h
index 4af8c9e..c8327c3 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -1,6 +1,5 @@
 #ifndef KEYWORD
 int do_bootchart_init(int nargs, char **args);
-int do_chroot(int nargs, char **args);
 int do_class_start(int nargs, char **args);
 int do_class_stop(int nargs, char **args);
 int do_class_reset(int nargs, char **args);
@@ -45,7 +44,6 @@
     K_UNKNOWN,
 #endif
     KEYWORD(capability,  OPTION,  0, 0)
-    KEYWORD(chroot,      COMMAND, 1, do_chroot)
     KEYWORD(class,       OPTION,  0, 0)
     KEYWORD(class_start, COMMAND, 1, do_class_start)
     KEYWORD(class_stop,  COMMAND, 1, do_class_stop)
diff --git a/init/readme.txt b/init/readme.txt
index 0a85a95..7443330 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -170,9 +170,6 @@
 chown <owner> <group> <path>
    Change file owner and group.
 
-chroot <directory>
-  Change process root directory.
-
 class_start <serviceclass>
    Start all services of the specified class if they are
    not already running.
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index a865093..8f8cc3f 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -178,6 +178,10 @@
     static pid_t last_pid = (pid_t) -1;
     static atomic_int_fast32_t dropped;
 
+    if (!nr) {
+        return -EINVAL;
+    }
+
     if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
         last_uid = getuid();
     }
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 0f7c384..70e37c6 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -72,14 +72,16 @@
         maxnaps = 1;
     }
 
-    while (maxnaps-- > 0) {
-        usleep(NAP_TIME * 1000);
+    while (maxnaps-- >= 0) {
         if (property_get(name, value, NULL)) {
             if (desired_value == NULL || 
                     strcmp(value, desired_value) == 0) {
                 return 0;
             }
         }
+        if (maxnaps >= 0) {
+            usleep(NAP_TIME * 1000);
+        }
     }
     return -1; /* failure */
 }
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index baa30cd..65c09e0 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -101,26 +101,32 @@
 	return chunks;
 }
 
-static void sparse_file_write_block(struct output_file *out,
+static int sparse_file_write_block(struct output_file *out,
 		struct backed_block *bb)
 {
+	int ret = -EINVAL;
+
 	switch (backed_block_type(bb)) {
 	case BACKED_BLOCK_DATA:
-		write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
+		ret = write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
 		break;
 	case BACKED_BLOCK_FILE:
-		write_file_chunk(out, backed_block_len(bb),
-				backed_block_filename(bb), backed_block_file_offset(bb));
+		ret = write_file_chunk(out, backed_block_len(bb),
+				       backed_block_filename(bb),
+				       backed_block_file_offset(bb));
 		break;
 	case BACKED_BLOCK_FD:
-		write_fd_chunk(out, backed_block_len(bb),
-				backed_block_fd(bb), backed_block_file_offset(bb));
+		ret = write_fd_chunk(out, backed_block_len(bb),
+				     backed_block_fd(bb),
+				     backed_block_file_offset(bb));
 		break;
 	case BACKED_BLOCK_FILL:
-		write_fill_chunk(out, backed_block_len(bb),
-				backed_block_fill_val(bb));
+		ret = write_fill_chunk(out, backed_block_len(bb),
+				       backed_block_fill_val(bb));
 		break;
 	}
+
+	return ret;
 }
 
 static int write_all_blocks(struct sparse_file *s, struct output_file *out)
@@ -128,6 +134,7 @@
 	struct backed_block *bb;
 	unsigned int last_block = 0;
 	int64_t pad;
+	int ret = 0;
 
 	for (bb = backed_block_iter_new(s->backed_block_list); bb;
 			bb = backed_block_iter_next(bb)) {
@@ -135,7 +142,9 @@
 			unsigned int blocks = backed_block_block(bb) - last_block;
 			write_skip_chunk(out, (int64_t)blocks * s->block_size);
 		}
-		sparse_file_write_block(out, bb);
+		ret = sparse_file_write_block(out, bb);
+		if (ret)
+			return ret;
 		last_block = backed_block_block(bb) +
 				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
 	}
@@ -230,6 +239,7 @@
 	struct backed_block *bb;
 	struct backed_block *start;
 	int64_t file_len = 0;
+	int ret;
 
 	/*
 	 * overhead is sparse file header, initial skip chunk, split chunk, end
@@ -249,7 +259,11 @@
 	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
 		count = 0;
 		/* will call out_counter_write to update count */
-		sparse_file_write_block(out_counter, bb);
+		ret = sparse_file_write_block(out_counter, bb);
+		if (ret) {
+			bb = NULL;
+			goto out;
+		}
 		if (file_len + count > len) {
 			/*
 			 * If the remaining available size is more than 1/8th of the
@@ -260,16 +274,17 @@
 				backed_block_split(from->backed_block_list, bb, len - file_len);
 				last_bb = bb;
 			}
-			goto out;
+			goto move;
 		}
 		file_len += count;
 		last_bb = bb;
 	}
 
-out:
+move:
 	backed_block_list_move(from->backed_block_list,
 		to->backed_block_list, start, last_bb);
 
+out:
 	output_file_close(out_counter);
 
 	return bb;
diff --git a/libziparchive/testdata/declaredlength.zip b/libziparchive/testdata/declaredlength.zip
new file mode 100644
index 0000000..773380c
--- /dev/null
+++ b/libziparchive/testdata/declaredlength.zip
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index e820f2a..6475649 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -824,7 +824,7 @@
   // name in the central directory.
   if (lfh->file_name_length == nameLen) {
     const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
-    if (name_offset + lfh->file_name_length >= cd_offset) {
+    if (name_offset + lfh->file_name_length > cd_offset) {
       ALOGW("Zip: Invalid declared length");
       return kInvalidOffset;
     }
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index c8dafa9..64faa6d 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -171,6 +171,22 @@
   CloseArchive(handle);
 }
 
+TEST(ziparchive, TestInvalidDeclaredLength) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
+
+  void* iteration_cookie;
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
+
+  ZipEntryName name;
+  ZipEntry data;
+
+  ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
+  ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
+
+  CloseArchive(handle);
+}
+
 TEST(ziparchive, ExtractToMemory) {
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 3be07c0..26a1861 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -27,7 +27,7 @@
                            unsigned long tail,
                            unsigned int logMask,
                            pid_t pid,
-                           log_time start)
+                           uint64_t start)
         : mReader(reader)
         , mNonBlock(nonBlock)
         , mTail(tail)
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index f34c06a..61c6858 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -31,7 +31,7 @@
     unsigned long mTail;
     unsigned int mLogMask;
     pid_t mPid;
-    log_time mStart;
+    uint64_t mStart;
 
 public:
     FlushCommand(LogReader &mReader,
@@ -39,7 +39,7 @@
                  unsigned long tail = -1,
                  unsigned int logMask = -1,
                  pid_t pid = 0,
-                 log_time start = LogTimeEntry::EPOCH);
+                 uint64_t start = 1);
     virtual void runSocketCommand(SocketClient *client);
 
     static bool hasReadLogs(SocketClient *client);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 2b495ab..2693583 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -161,7 +161,7 @@
     if (last == mLogElements.end()) {
         mLogElements.push_back(elem);
     } else {
-        log_time end = log_time::EPOCH;
+        uint64_t end = 1;
         bool end_set = false;
         bool end_always = false;
 
@@ -184,7 +184,7 @@
         }
 
         if (end_always
-                || (end_set && (end >= (*last)->getMonotonicTime()))) {
+                || (end_set && (end >= (*last)->getSequence()))) {
             mLogElements.push_back(elem);
         } else {
             mLogElements.insert(last,elem);
@@ -241,7 +241,7 @@
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 break;
             }
 
@@ -293,7 +293,7 @@
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 break;
             }
 
@@ -334,7 +334,7 @@
     while((pruneRows > 0) && (it != mLogElements.end())) {
         LogBufferElement *e = *it;
         if (e->getLogId() == id) {
-            if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+            if (oldest && (oldest->mStart <= e->getSequence())) {
                 if (!whitelist) {
                     if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                         // kick a misbehaving log reader client off the island
@@ -366,7 +366,7 @@
         while((it != mLogElements.end()) && (pruneRows > 0)) {
             LogBufferElement *e = *it;
             if (e->getLogId() == id) {
-                if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+                if (oldest && (oldest->mStart <= e->getSequence())) {
                     if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                         // kick a misbehaving log reader client off the island
                         oldest->release_Locked();
@@ -423,16 +423,16 @@
     return retval;
 }
 
-log_time LogBuffer::flushTo(
-        SocketClient *reader, const log_time start, bool privileged,
-        bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
+uint64_t LogBuffer::flushTo(
+        SocketClient *reader, const uint64_t start, bool privileged,
+        int (*filter)(const LogBufferElement *element, void *arg), void *arg) {
     LogBufferElementCollection::iterator it;
-    log_time max = start;
+    uint64_t max = start;
     uid_t uid = reader->getUid();
 
     pthread_mutex_lock(&mLogElementsLock);
 
-    if (start == LogTimeEntry::EPOCH) {
+    if (start <= 1) {
         // client wants to start from the beginning
         it = mLogElements.begin();
     } else {
@@ -441,7 +441,7 @@
         for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) {
             --it;
             LogBufferElement *element = *it;
-            if (element->getMonotonicTime() <= start) {
+            if (element->getSequence() <= start) {
                 it++;
                 break;
             }
@@ -455,13 +455,19 @@
             continue;
         }
 
-        if (element->getMonotonicTime() <= start) {
+        if (element->getSequence() <= start) {
             continue;
         }
 
         // NB: calling out to another object with mLogElementsLock held (safe)
-        if (filter && !(*filter)(element, arg)) {
-            continue;
+        if (filter) {
+            int ret = (*filter)(element, arg);
+            if (ret == false) {
+                continue;
+            }
+            if (ret != true) {
+                break;
+            }
         }
 
         pthread_mutex_unlock(&mLogElementsLock);
@@ -481,7 +487,7 @@
 }
 
 void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
-    log_time oldest(CLOCK_MONOTONIC);
+    uint64_t oldest = UINT64_MAX;
 
     pthread_mutex_lock(&mLogElementsLock);
 
@@ -491,7 +497,7 @@
         LogBufferElement *element = *it;
 
         if ((logMask & (1 << element->getLogId()))) {
-            oldest = element->getMonotonicTime();
+            oldest = element->getSequence();
             break;
         }
     }
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 86a2a2a..13e6aa8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -51,9 +51,9 @@
     void log(log_id_t log_id, log_time realtime,
              uid_t uid, pid_t pid, pid_t tid,
              const char *msg, unsigned short len);
-    log_time flushTo(SocketClient *writer, const log_time start,
+    uint64_t flushTo(SocketClient *writer, const uint64_t start,
                      bool privileged,
-                     bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
+                     int (*filter)(const LogBufferElement *element, void *arg) = NULL,
                      void *arg = NULL);
 
     void clear(log_id_t id, uid_t uid = AID_ROOT);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index d959ceb..5e780b5 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -24,7 +24,8 @@
 #include "LogBufferElement.h"
 #include "LogReader.h"
 
-const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0);
+const uint64_t LogBufferElement::FLUSH_ERROR(0);
+atomic_int_fast64_t LogBufferElement::sequence;
 
 LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
                                    uid_t uid, pid_t pid, pid_t tid,
@@ -34,7 +35,7 @@
         , mPid(pid)
         , mTid(tid)
         , mMsgLen(len)
-        , mMonotonicTime(CLOCK_MONOTONIC)
+        , mSequence(sequence.fetch_add(1, memory_order_relaxed))
         , mRealTime(realtime) {
     mMsg = new char[len];
     memcpy(mMsg, msg, len);
@@ -44,7 +45,7 @@
     delete [] mMsg;
 }
 
-log_time LogBufferElement::flushTo(SocketClient *reader) {
+uint64_t LogBufferElement::flushTo(SocketClient *reader) {
     struct logger_entry_v3 entry;
     memset(&entry, 0, sizeof(struct logger_entry_v3));
     entry.hdr_size = sizeof(struct logger_entry_v3);
@@ -64,5 +65,5 @@
         return FLUSH_ERROR;
     }
 
-    return mMonotonicTime;
+    return mSequence;
 }
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index fdca973..25f1450 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -18,6 +18,7 @@
 #define _LOGD_LOG_BUFFER_ELEMENT_H__
 
 #include <sys/types.h>
+#include <stdatomic.h>
 #include <sysutils/SocketClient.h>
 #include <log/log.h>
 #include <log/log_read.h>
@@ -29,8 +30,9 @@
     const pid_t mTid;
     char *mMsg;
     const unsigned short mMsgLen;
-    const log_time mMonotonicTime;
+    const uint64_t mSequence;
     const log_time mRealTime;
+    static atomic_int_fast64_t sequence;
 
 public:
     LogBufferElement(log_id_t log_id, log_time realtime,
@@ -43,11 +45,12 @@
     pid_t getPid(void) const { return mPid; }
     pid_t getTid(void) const { return mTid; }
     unsigned short getMsgLen() const { return mMsgLen; }
-    log_time getMonotonicTime(void) const { return mMonotonicTime; }
+    uint64_t getSequence(void) const { return mSequence; }
+    static uint64_t getCurrentSequence(void) { return sequence.load(memory_order_relaxed); }
     log_time getRealTime(void) const { return mRealTime; }
 
-    static const log_time FLUSH_ERROR;
-    log_time flushTo(SocketClient *writer);
+    static const uint64_t FLUSH_ERROR;
+    uint64_t flushTo(SocketClient *writer);
 };
 
 #endif
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 26df087..f7df275 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -100,50 +100,51 @@
         nonBlock = true;
     }
 
-    // Convert realtime to monotonic time
-    if (start == log_time::EPOCH) {
-        start = LogTimeEntry::EPOCH;
-    } else {
+    uint64_t sequence = 1;
+    // Convert realtime to sequence number
+    if (start != log_time::EPOCH) {
         class LogFindStart {
             const pid_t mPid;
             const unsigned mLogMask;
             bool startTimeSet;
             log_time &start;
-            log_time last;
+            uint64_t &sequence;
+            uint64_t last;
 
         public:
-            LogFindStart(unsigned logMask, pid_t pid, log_time &start)
+            LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence)
                     : mPid(pid)
                     , mLogMask(logMask)
                     , startTimeSet(false)
                     , start(start)
-                    , last(LogTimeEntry::EPOCH)
+                    , sequence(sequence)
+                    , last(sequence)
             { }
 
-            static bool callback(const LogBufferElement *element, void *obj) {
+            static int callback(const LogBufferElement *element, void *obj) {
                 LogFindStart *me = reinterpret_cast<LogFindStart *>(obj);
-                if (!me->startTimeSet
-                        && (!me->mPid || (me->mPid == element->getPid()))
+                if ((!me->mPid || (me->mPid == element->getPid()))
                         && (me->mLogMask & (1 << element->getLogId()))) {
                     if (me->start == element->getRealTime()) {
-                        me->start = element->getMonotonicTime();
+                        me->sequence = element->getSequence();
                         me->startTimeSet = true;
+                        return -1;
                     } else {
                         if (me->start < element->getRealTime()) {
-                            me->start = me->last;
+                            me->sequence = me->last;
                             me->startTimeSet = true;
+                            return -1;
                         }
-                        me->last = element->getMonotonicTime();
+                        me->last = element->getSequence();
                     }
                 }
                 return false;
             }
 
             bool found() { return startTimeSet; }
-        } logFindStart(logMask, pid, start);
+        } logFindStart(logMask, pid, start, sequence);
 
-        logbuf().flushTo(cli, LogTimeEntry::EPOCH,
-                         FlushCommand::hasReadLogs(cli),
+        logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli),
                          logFindStart.callback, &logFindStart);
 
         if (!logFindStart.found()) {
@@ -151,12 +152,11 @@
                 doSocketDelete(cli);
                 return false;
             }
-            log_time now(CLOCK_MONOTONIC);
-            start = now;
+            sequence = LogBufferElement::getCurrentSequence();
         }
     }
 
-    FlushCommand command(*this, nonBlock, tail, logMask, pid, start);
+    FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence);
     command.runSocketCommand(cli);
     return true;
 }
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 5f9db8d..1b60b7e 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -23,12 +23,10 @@
 
 pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
 
-const struct timespec LogTimeEntry::EPOCH = { 0, 1 };
-
 LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
                            bool nonBlock, unsigned long tail,
                            unsigned int logMask, pid_t pid,
-                           log_time start)
+                           uint64_t start)
         : mRefCount(1)
         , mRelease(false)
         , mError(false)
@@ -42,7 +40,7 @@
         , mClient(client)
         , mStart(start)
         , mNonBlock(nonBlock)
-        , mEnd(CLOCK_MONOTONIC)
+        , mEnd(LogBufferElement::getCurrentSequence())
 {
         pthread_cond_init(&threadTriggeredCondition, NULL);
         cleanSkip_Locked();
@@ -129,7 +127,7 @@
     lock();
 
     while (me->threadRunning && !me->isError_Locked()) {
-        log_time start = me->mStart;
+        uint64_t start = me->mStart;
 
         unlock();
 
@@ -161,13 +159,13 @@
 }
 
 // A first pass to count the number of elements
-bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
     LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
 
     LogTimeEntry::lock();
 
     if (me->mCount == 0) {
-        me->mStart = element->getMonotonicTime();
+        me->mStart = element->getSequence();
     }
 
     if ((!me->mPid || (me->mPid == element->getPid()))
@@ -181,12 +179,12 @@
 }
 
 // A second pass to send the selected elements
-bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
+int LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
     LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
 
     LogTimeEntry::lock();
 
-    me->mStart = element->getMonotonicTime();
+    me->mStart = element->getSequence();
 
     if (me->skipAhead[element->getLogId()]) {
         me->skipAhead[element->getLogId()]--;
@@ -195,7 +193,7 @@
 
     // Truncate to close race between first and second pass
     if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
-        goto skip;
+        goto stop;
     }
 
     if (!me->isWatching(element->getLogId())) {
@@ -207,7 +205,7 @@
     }
 
     if (me->isError_Locked()) {
-        goto skip;
+        goto stop;
     }
 
     if (!me->mTail) {
@@ -234,6 +232,10 @@
 skip:
     LogTimeEntry::unlock();
     return false;
+
+stop:
+    LogTimeEntry::unlock();
+    return -1;
 }
 
 void LogTimeEntry::cleanSkip_Locked(void) {
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 81aedfb..ae2f92b 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -47,13 +47,12 @@
 public:
     LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
                  unsigned long tail, unsigned int logMask, pid_t pid,
-                 log_time start);
+                 uint64_t start);
 
     SocketClient *mClient;
-    static const struct timespec EPOCH;
-    log_time mStart;
+    uint64_t mStart;
     const bool mNonBlock;
-    const log_time mEnd; // only relevant if mNonBlock
+    const uint64_t mEnd; // only relevant if mNonBlock
 
     // Protect List manipulations
     static void lock(void) { pthread_mutex_lock(&timesLock); }
@@ -103,8 +102,8 @@
     }
     bool isWatching(log_id_t id) { return (mLogMask & (1<<id)) != 0; }
     // flushTo filter callbacks
-    static bool FilterFirstPass(const LogBufferElement *element, void *me);
-    static bool FilterSecondPass(const LogBufferElement *element, void *me);
+    static int FilterFirstPass(const LogBufferElement *element, void *me);
+    static int FilterSecondPass(const LogBufferElement *element, void *me);
 };
 
 typedef android::List<LogTimeEntry *> LastLogTimes;