Merge "Enable clang for init, after fix of global .mk files."
diff --git a/adb/commandline.c b/adb/commandline.c
index f345787..44541b7 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -1578,7 +1578,7 @@
         {
           if (argc != 3)
             return usage();
-          const char* command = no_rebind ? "forward:norebind:" : "forward";
+          const char* command = no_rebind ? "forward:norebind" : "forward";
           snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
         }
 
diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk
index 1e69e7a..c74f906 100644
--- a/fastbootd/Android.mk
+++ b/fastbootd/Android.mk
@@ -37,7 +37,6 @@
 LOCAL_MODULE := fastbootd
 LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -Wno-deprecated-declarations -DFLASH_CERT
-LOCAL_LDFLAGS := -ldl
 
 LOCAL_STATIC_LIBRARIES := \
     libc \
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 40878c1..d6edd29 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -28,6 +28,9 @@
 #include <libgen.h>
 #include <time.h>
 #include <sys/swap.h>
+#include <dirent.h>
+#include <ext4.h>
+#include <ext4_sb.h>
 
 #include <linux/loop.h>
 #include <private/android_filesystem_config.h>
@@ -325,6 +328,83 @@
     return 0;
 }
 
+static int translate_ext_labels(struct fstab_rec *rec)
+{
+    DIR *blockdir = NULL;
+    struct dirent *ent;
+    char *label;
+    size_t label_len;
+    int ret = -1;
+
+    if (strncmp(rec->blk_device, "LABEL=", 6))
+        return 0;
+
+    label = rec->blk_device + 6;
+    label_len = strlen(label);
+
+    if (label_len > 16) {
+        ERROR("FS label is longer than allowed by filesystem\n");
+        goto out;
+    }
+
+
+    blockdir = opendir("/dev/block");
+    if (!blockdir) {
+        ERROR("couldn't open /dev/block\n");
+        goto out;
+    }
+
+    while ((ent = readdir(blockdir))) {
+        int fd;
+        char super_buf[1024];
+        struct ext4_super_block *sb;
+
+        if (ent->d_type != DT_BLK)
+            continue;
+
+        fd = openat(dirfd(blockdir), ent->d_name, O_RDONLY);
+        if (fd < 0) {
+            ERROR("Cannot open block device /dev/block/%s\n", ent->d_name);
+            goto out;
+        }
+
+        if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
+            TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
+            /* Probably a loopback device or something else without a readable
+             * superblock.
+             */
+            close(fd);
+            continue;
+        }
+
+        sb = (struct ext4_super_block *)super_buf;
+        if (sb->s_magic != EXT4_SUPER_MAGIC) {
+            INFO("/dev/block/%s not ext{234}\n", ent->d_name);
+            continue;
+        }
+
+        if (!strncmp(label, sb->s_volume_name, label_len)) {
+            char *new_blk_device;
+
+            if (asprintf(&new_blk_device, "/dev/block/%s", ent->d_name) < 0) {
+                ERROR("Could not allocate block device string\n");
+                goto out;
+            }
+
+            INFO("resolved label %s to %s\n", rec->blk_device, new_blk_device);
+
+            free(rec->blk_device);
+            rec->blk_device = new_blk_device;
+            ret = 0;
+            break;
+        }
+    }
+
+out:
+    closedir(blockdir);
+    return ret;
+}
+
 /* When multiple fstab records share the same mount_point, it will
  * try to mount each one in turn, and ignore any duplicates after a
  * first successful mount.
@@ -356,6 +436,17 @@
             continue;
         }
 
+        /* Translate LABEL= file system labels into block devices */
+        if (!strcmp(fstab->recs[i].fs_type, "ext2") ||
+            !strcmp(fstab->recs[i].fs_type, "ext3") ||
+            !strcmp(fstab->recs[i].fs_type, "ext4")) {
+            int tret = translate_ext_labels(&fstab->recs[i]);
+            if (tret < 0) {
+                ERROR("Could not translate label to block device\n");
+                continue;
+            }
+        }
+
         if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
             wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
         }
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
new file mode 100644
index 0000000..cc7ba30
--- /dev/null
+++ b/include/private/android_logger.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file is used to define the internal protocol for the Android Logger */
+
+#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
+#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
+
+#include <stdint.h>
+
+#include <log/log.h>
+#include <log/log_read.h>
+
+#define LOGGER_MAGIC 'l'
+
+/* Header Structure to pstore */
+typedef struct __attribute__((__packed__)) {
+    uint8_t magic;
+    uint16_t len;
+    uint16_t uid;
+    uint16_t pid;
+} android_pmsg_log_header_t;
+
+/* Header Structure to logd, and second header for pstore */
+typedef struct __attribute__((__packed__)) {
+    typeof_log_id_t id;
+    uint16_t tid;
+    log_time realtime;
+} android_log_header_t;
+
+#endif
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index b2668ce..1e9b591 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -39,6 +39,7 @@
 #include <log/logger.h>
 #include <log/log_read.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 
 #define LOG_BUF_SIZE 1024
 
@@ -61,6 +62,7 @@
 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
 #else
 static int logd_fd = -1;
+static int pstore_fd = -1;
 #endif
 
 /*
@@ -109,6 +111,12 @@
         logd_fd = -1;
         close(i);
     }
+    if (pstore_fd >= 0) {
+        i = pstore_fd;
+        pstore_fd = -1;
+        close(i);
+    }
+    pstore_fd = open("/dev/pmsg0", O_WRONLY);
 
     i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
     if (i < 0) {
@@ -155,37 +163,27 @@
         }
     } while (ret == -EINTR);
 #else
-    static const unsigned header_length = 3;
+    static const unsigned header_length = 2;
     struct iovec newVec[nr + header_length];
-    typeof_log_id_t log_id_buf;
-    uint16_t tid;
+    android_log_header_t header;
+    android_pmsg_log_header_t pmsg_header;
     struct timespec ts;
-    log_time realtime_ts;
     size_t i, payload_size;
     static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
+    static pid_t last_pid = (pid_t) -1;
 
     if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
         last_uid = getuid();
     }
-    if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
-        /*
-         * ignore log messages we send to ourself (logd).
-         * Such log messages are often generated by libraries we depend on
-         * which use standard Android logging.
-         */
-        return 0;
+    if (last_pid == (pid_t) -1) {
+        last_pid = getpid();
     }
-
-    if (logd_fd < 0) {
-        return -EBADF;
-    }
-
     /*
      *  struct {
-     *      // what we provide
-     *      typeof_log_id_t  log_id;
-     *      u16              tid;
-     *      log_time         realtime;
+     *      // whate we provire to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
      *      // caller provides
      *      union {
      *          struct {
@@ -201,18 +199,21 @@
      */
 
     clock_gettime(CLOCK_REALTIME, &ts);
-    realtime_ts.tv_sec = ts.tv_sec;
-    realtime_ts.tv_nsec = ts.tv_nsec;
 
-    log_id_buf = log_id;
-    tid = gettid();
+    pmsg_header.magic = LOGGER_MAGIC;
+    pmsg_header.len = sizeof(pmsg_header) + sizeof(header);
+    pmsg_header.uid = last_uid;
+    pmsg_header.pid = last_pid;
 
-    newVec[0].iov_base   = (unsigned char *) &log_id_buf;
-    newVec[0].iov_len    = sizeof_log_id_t;
-    newVec[1].iov_base   = (unsigned char *) &tid;
-    newVec[1].iov_len    = sizeof(tid);
-    newVec[2].iov_base   = (unsigned char *) &realtime_ts;
-    newVec[2].iov_len    = sizeof(log_time);
+    header.id = log_id;
+    header.tid = gettid();
+    header.realtime.tv_sec = ts.tv_sec;
+    header.realtime.tv_nsec = ts.tv_nsec;
+
+    newVec[0].iov_base   = (unsigned char *) &pmsg_header;
+    newVec[0].iov_len    = sizeof(pmsg_header);
+    newVec[1].iov_base   = (unsigned char *) &header;
+    newVec[1].iov_len    = sizeof(header);
 
     for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
         newVec[i].iov_base = vec[i - header_length].iov_base;
@@ -223,17 +224,38 @@
             if (newVec[i].iov_len) {
                 ++i;
             }
+            payload_size = LOGGER_ENTRY_MAX_PAYLOAD;
             break;
         }
     }
+    pmsg_header.len += payload_size;
+
+    if (pstore_fd >= 0) {
+        TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i));
+    }
+
+    if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */
+        /*
+         * ignore log messages we send to ourself (logd).
+         * Such log messages are often generated by libraries we depend on
+         * which use standard Android logging.
+         */
+        return 0;
+    }
+
+    if (logd_fd < 0) {
+        return -EBADF;
+    }
 
     /*
      * The write below could be lost, but will never block.
      *
+     * To logd, we drop the pmsg_header
+     *
      * ENOTCONN occurs if logd dies.
      * EAGAIN occurs if logd is overloaded.
      */
-    ret = writev(logd_fd, newVec, i);
+    ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
     if (ret < 0) {
         ret = -errno;
         if (ret == -ENOTCONN) {
@@ -249,15 +271,15 @@
                 return ret;
             }
 
-            ret = writev(logd_fd, newVec, nr + header_length);
+            ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1));
             if (ret < 0) {
                 ret = -errno;
             }
         }
     }
 
-    if (ret > (ssize_t)(sizeof_log_id_t + sizeof(tid) + sizeof(log_time))) {
-        ret -= sizeof_log_id_t + sizeof(tid) + sizeof(log_time);
+    if (ret > (ssize_t)sizeof(header)) {
+        ret -= sizeof(header);
     }
 #endif
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 6307bed..3d0b38f 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -445,7 +445,24 @@
     uid_t uid = reader->getUid();
 
     pthread_mutex_lock(&mLogElementsLock);
-    for (it = mLogElements.begin(); it != mLogElements.end(); ++it) {
+
+    if (start == LogTimeEntry::EPOCH) {
+        // client wants to start from the beginning
+        it = mLogElements.begin();
+    } else {
+        // Client wants to start from some specified time. Chances are
+        // we are better off starting from the end of the time sorted list.
+        for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) {
+            --it;
+            LogBufferElement *element = *it;
+            if (element->getMonotonicTime() <= start) {
+                it++;
+                break;
+            }
+        }
+    }
+
+    for (; it != mLogElements.end(); ++it) {
         LogBufferElement *element = *it;
 
         if (!privileged && (element->getUid() != uid)) {
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 8186cea..fc9e30f 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -23,6 +23,7 @@
 
 #include <cutils/sockets.h>
 #include <log/logger.h>
+#include <private/android_logger.h>
 
 #include "LogListener.h"
 
@@ -54,7 +55,7 @@
     int socket = cli->getSocket();
 
     ssize_t n = recvmsg(socket, &hdr, 0);
-    if (n <= (ssize_t)(sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time))) {
+    if (n <= (ssize_t)(sizeof(android_log_header_t))) {
         return false;
     }
 
@@ -81,28 +82,19 @@
         return false;
     }
 
-    // First log element is always log_id.
-    log_id_t log_id = (log_id_t) *((typeof_log_id_t *) buffer);
-    if (log_id < 0 || log_id >= LOG_ID_MAX) {
+    android_log_header_t *header = reinterpret_cast<android_log_header_t *>(buffer);
+    if (/* header->id < LOG_ID_MIN || */ header->id >= LOG_ID_MAX) {
         return false;
     }
-    char *msg = ((char *)buffer) + sizeof_log_id_t;
-    n -= sizeof_log_id_t;
 
-    // second element is the thread id of the caller
-    pid_t tid = (pid_t) *((uint16_t *) msg);
-    msg += sizeof(uint16_t);
-    n -= sizeof(uint16_t);
-
-    // third element is the realtime at point of caller
-    log_time realtime(msg);
-    msg += sizeof(log_time);
-    n -= sizeof(log_time);
+    char *msg = ((char *)buffer) + sizeof(android_log_header_t);
+    n -= sizeof(android_log_header_t);
 
     // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
     // truncated message to the logs.
 
-    logbuf->log(log_id, realtime, cred->uid, cred->pid, tid, msg,
+    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();