Merge "Move trace.h to stdatomic."
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index fed81f8..02fe2b5 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -215,6 +215,8 @@
 void fs_config(const char *path, int dir,
                unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities);
 
+ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc);
+
 __END_DECLS
 
 #endif
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index b875efd..54cace9 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -57,7 +57,6 @@
 libbacktrace_shared_libraries := \
 	libbase \
 	libunwind \
-	libunwind-ptrace \
 
 libbacktrace_shared_libraries_host := \
 	liblog \
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 11d4225..9f8023e 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -23,7 +23,6 @@
 
 #define _GNU_SOURCE
 
-#include <endian.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
@@ -31,13 +30,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <cutils/fs.h>
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
+#include <utils/Compat.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
 
 /* The following structure is stored little endian */
 struct fs_path_config_from_file {
@@ -49,6 +51,23 @@
     char prefix[];
 } __attribute__((__aligned__(sizeof(uint64_t))));
 
+/* My kingdom for <endian.h> */
+static inline uint16_t get2LE(const uint8_t* src)
+{
+    return src[0] | (src[1] << 8);
+}
+
+static inline uint64_t get8LE(const uint8_t* src)
+{
+    uint32_t low, high;
+
+    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
+    return ((uint64_t) high << 32) | (uint64_t) low;
+}
+
+#define ALIGN(x, alignment) ( ((x) + ((alignment) - 1)) & ~((alignment) - 1) )
+
 /* Rules for directories.
 ** These rules are applied based on "first match", so they
 ** should start with the most specific path and work their
@@ -139,12 +158,12 @@
         char *name = NULL;
         asprintf(&name, "%s%s", out, dir ? conf_dir : conf_file);
         if (name) {
-            fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY));
+            fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_BINARY));
             free(name);
         }
     }
     if (fd < 0) {
-        fd = TEMP_FAILURE_RETRY(open(dir ? conf_dir : conf_file, O_RDONLY));
+        fd = TEMP_FAILURE_RETRY(open(dir ? conf_dir : conf_file, O_RDONLY | O_BINARY));
     }
     return fd;
 }
@@ -172,21 +191,7 @@
                unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities)
 {
     const struct fs_path_config *pc;
-    int plen;
-    struct stat st;
-    void *address = NULL;
-
-    int fd = fs_config_open(dir);
-    if ((fd >= 0)
-     && (TEMP_FAILURE_RETRY(fstat(fd, &st)) >= 0)
-     && (size_t)st.st_size) {
-        address = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-        if (address == MAP_FAILED) {
-            address = NULL;
-        }
-    } else if (fd >= 0) {
-        close(fd);
-    }
+    int fd, plen;
 
     if (path[0] == '/') {
         path++;
@@ -194,44 +199,46 @@
 
     plen = strlen(path);
 
-    if (address) {
-        const struct fs_path_config_from_file *p = (const struct fs_path_config_from_file *)
-            address;
-        const char *end = (const char *)address + st.st_size;
-        const struct fs_path_config_from_file *e = (const struct fs_path_config_from_file *)
-            (end - sizeof(*p));
-        for (; p < e; p = (const struct fs_path_config_from_file *)(((const char *)p) + le16toh(p->len))) {
-            ssize_t len, remainder = le16toh(p->len) - sizeof(*p);
+    fd = fs_config_open(dir);
+    if (fd >= 0) {
+        struct fs_path_config_from_file header;
+
+        while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
+            char *prefix;
+            uint16_t host_len = get2LE((const uint8_t *)&header.len);
+            ssize_t len, remainder = host_len - sizeof(header);
             if (remainder <= 0) {
-                ALOGE("%s is truncated", dir ? conf_dir : conf_file);
-                p = e;
+                ALOGE("%s len is corrupted", dir ? conf_dir : conf_file);
                 break;
             }
-            len = (const char *)e - (const char *)p;
-            if (remainder > len) {
-                remainder = len;
+            prefix = calloc(1, remainder);
+            if (!prefix) {
+                ALOGE("%s out of memory", dir ? conf_dir : conf_file);
+                break;
             }
-            len = strnlen(p->prefix, remainder);
+            if (TEMP_FAILURE_RETRY(read(fd, prefix, remainder)) != remainder) {
+                free(prefix);
+                ALOGE("%s prefix is truncated", dir ? conf_dir : conf_file);
+                break;
+            }
+            len = strnlen(prefix, remainder);
             if (len >= remainder) { /* missing a terminating null */
+                free(prefix);
                 ALOGE("%s is corrupted", dir ? conf_dir : conf_file);
-                p = e;
                 break;
             }
-            if (fs_config_cmp(dir, p->prefix, len, path, plen)) {
-                break;
+            if (fs_config_cmp(dir, prefix, len, path, plen)) {
+                free(prefix);
+                close(fd);
+                *uid = get2LE((const uint8_t *)&(header.uid));
+                *gid = get2LE((const uint8_t *)&(header.gid));
+                *mode = (*mode & (~07777)) | get2LE((const uint8_t *)&(header.mode));
+                *capabilities = get8LE((const uint8_t *)&(header.capabilities));
+                return;
             }
+            free(prefix);
         }
-        if (p < e) {
-            *uid = le16toh(p->uid);
-            *gid = le16toh(p->gid);
-            *mode = (*mode & (~07777)) | le16toh(p->mode);
-            *capabilities = le64toh(p->capabilities);
-        }
-        munmap(address, st.st_size);
         close(fd);
-        if (p < e) {
-            return;
-        }
     }
 
     pc = dir ? android_dirs : android_files;
@@ -245,3 +252,22 @@
     *mode = (*mode & (~07777)) | pc->mode;
     *capabilities = pc->capabilities;
 }
+
+ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc)
+{
+    struct fs_path_config_from_file *p = (struct fs_path_config_from_file *)buffer;
+    size_t len = ALIGN(sizeof(*p) + strlen(pc->prefix) + 1, sizeof(uint64_t));
+
+    if ((length < len) || (len > UINT16_MAX)) {
+        return -ENOSPC;
+    }
+    memset(p, 0, len);
+    uint16_t host_len = len;
+    p->len = get2LE((const uint8_t *)&host_len);
+    p->mode = get2LE((const uint8_t *)&(pc->mode));
+    p->uid = get2LE((const uint8_t *)&(pc->uid));
+    p->gid = get2LE((const uint8_t *)&(pc->gid));
+    p->capabilities = get8LE((const uint8_t *)&(pc->capabilities));
+    strcpy(p->prefix, pc->prefix);
+    return len;
+}
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index 65c09e0..311678a 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -238,14 +238,15 @@
 	struct backed_block *last_bb = NULL;
 	struct backed_block *bb;
 	struct backed_block *start;
+	unsigned int last_block = 0;
 	int64_t file_len = 0;
 	int ret;
 
 	/*
-	 * overhead is sparse file header, initial skip chunk, split chunk, end
-	 * skip chunk, and crc chunk.
+	 * overhead is sparse file header, the potential end skip
+	 * chunk and crc chunk.
 	 */
-	int overhead = sizeof(sparse_header_t) + 4 * sizeof(chunk_header_t) +
+	int overhead = sizeof(sparse_header_t) + 2 * sizeof(chunk_header_t) +
 			sizeof(uint32_t);
 	len -= overhead;
 
@@ -258,6 +259,11 @@
 
 	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
 		count = 0;
+		if (backed_block_block(bb) > last_block)
+			count += sizeof(chunk_header_t);
+		last_block = backed_block_block(bb) +
+				DIV_ROUND_UP(backed_block_len(bb), to->block_size);
+
 		/* will call out_counter_write to update count */
 		ret = sparse_file_write_block(out_counter, bb);
 		if (ret) {
@@ -270,6 +276,7 @@
 			 * requested size, split the chunk.  Results in sparse files that
 			 * are at least 7/8ths of the requested size
 			 */
+			file_len += sizeof(chunk_header_t);
 			if (!last_bb || (len - file_len > (len / 8))) {
 				backed_block_split(from->backed_block_list, bb, len - file_len);
 				last_bb = bb;
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 90370e9..caae54b 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -155,12 +155,14 @@
         event->length = htole32(l);
         memcpy(event->data, str, l);
 
-        logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
-                    reinterpret_cast<char *>(event),
-                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
+                         reinterpret_cast<char *>(event),
+                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
         free(event);
 
-        notify = true;
+        if (rc >= 0) {
+            notify = true;
+        }
     }
 
     // log to main
@@ -197,17 +199,22 @@
         strncpy(newstr + 1 + l, str, estr - str);
         strcpy(newstr + 1 + l + (estr - str), ecomm);
 
-        logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
-                    (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+        rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
+                         (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
         free(newstr);
 
-        notify = true;
+        if (rc >= 0) {
+            notify = true;
+        }
     }
 
     free(str);
 
     if (notify) {
         reader->notifyNewLog();
+        if (rc < 0) {
+            rc = n;
+        }
     }
 
     return rc;
@@ -216,7 +223,7 @@
 int LogAudit::log(char *buf) {
     char *audit = strstr(buf, " audit(");
     if (!audit) {
-        return 0;
+        return -EXDEV;
     }
 
     *audit = '\0';
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 260e237..a0436ef 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/user.h>
@@ -132,11 +133,11 @@
     init();
 }
 
-void LogBuffer::log(log_id_t log_id, log_time realtime,
-                    uid_t uid, pid_t pid, pid_t tid,
-                    const char *msg, unsigned short len) {
+int LogBuffer::log(log_id_t log_id, log_time realtime,
+                   uid_t uid, pid_t pid, pid_t tid,
+                   const char *msg, unsigned short len) {
     if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
-        return;
+        return -EINVAL;
     }
     LogBufferElement *elem = new LogBufferElement(log_id, realtime,
                                                   uid, pid, tid, msg, len);
@@ -193,6 +194,8 @@
     stats.add(elem);
     maybePrune(log_id);
     pthread_mutex_unlock(&mLogElementsLock);
+
+    return len;
 }
 
 // If we're using more than 256K of memory for log entries, prune
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a29e015..9ee243d 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -48,9 +48,9 @@
     LogBuffer(LastLogTimes *times);
     void init();
 
-    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);
+    int log(log_id_t log_id, log_time realtime,
+            uid_t uid, pid_t pid, pid_t tid,
+            const char *msg, unsigned short len);
     uint64_t flushTo(SocketClient *writer, const uint64_t start,
                      bool privileged,
                      int (*filter)(const LogBufferElement *element, void *arg) = NULL,
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 3b4ef88..05ced06 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -98,10 +98,11 @@
     // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
     // truncated message to the logs.
 
-    logbuf->log((log_id_t)header->id, header->realtime,
-        cred->uid, cred->pid, header->tid, msg,
-        ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
-    reader->notifyNewLog();
+    if (logbuf->log((log_id_t)header->id, header->realtime,
+            cred->uid, cred->pid, header->tid, msg,
+            ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX) >= 0) {
+        reader->notifyNewLog();
+    }
 
     return true;
 }
diff --git a/logd/main.cpp b/logd/main.cpp
index 4aa38b3..eb29596 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -367,12 +367,12 @@
 
             int rc = klogctl(KLOG_READ_ALL, buf, len);
 
-            buf[len - 1] = '\0';
+            if (rc >= 0) {
+                buf[len - 1] = '\0';
 
-            for(char *ptr, *tok = buf;
-                    (rc >= 0) && ((tok = strtok_r(tok, "\r\n", &ptr)));
-                    tok = NULL) {
-                rc = al->log(tok);
+                for (char *ptr, *tok = buf; (tok = strtok_r(tok, "\r\n", &ptr)); tok = NULL) {
+                    al->log(tok);
+                }
             }
         }