logd: propagate ::log status

Add a return value for the ::log() methods, this allows
us to optimize the wakeup for the readers to only occur
when the log message is actually placed.

This is for a future where we may dedupe identical log
messages, filter out log messages, and certainly if we
filter the messages out with an internal logd check of
__android_log_is_loggable().

Change-Id: I763b2a7c29502ab7fa0a5d5022c7b60244fcfde4
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);
+                }
             }
         }