1ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn/* 2ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * Copyright (C) 2014 The Android Open Source Project 3ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * 4ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 5ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * you may not use this file except in compliance with the License. 6ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * You may obtain a copy of the License at 7ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * 8ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 9ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * 10ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * Unless required by applicable law or agreed to in writing, software 11ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 12ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * See the License for the specific language governing permissions and 14ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn * limitations under the License. 15ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn */ 16ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 17ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <ctype.h> 18ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <errno.h> 19ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <inttypes.h> 20ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <limits.h> 21ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <stdarg.h> 22ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <stdlib.h> 23317bfb923c12af688d18fc9a3580dff201b2482bMark Salyzyn#include <string.h> 24ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <sys/prctl.h> 25ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <sys/uio.h> 26ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include <syslog.h> 27ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 2883b247891cea88347b759d638814cea61995d2caMark Salyzyn#include <private/android_filesystem_config.h> 29501c373916e292764400dbae735f44b33378400fMark Salyzyn#include <private/android_logger.h> 30ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 31317bfb923c12af688d18fc9a3580dff201b2482bMark Salyzyn#include "LogBuffer.h" 32ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn#include "LogKlog.h" 33317bfb923c12af688d18fc9a3580dff201b2482bMark Salyzyn#include "LogReader.h" 34ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 35501c373916e292764400dbae735f44b33378400fMark Salyzyn#define KMSG_PRIORITY(PRI) \ 36501c373916e292764400dbae735f44b33378400fMark Salyzyn '<', '0' + (LOG_SYSLOG | (PRI)) / 10, '0' + (LOG_SYSLOG | (PRI)) % 10, '>' 37ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 38ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzynstatic const char priority_message[] = { KMSG_PRIORITY(LOG_INFO), '\0' }; 39ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 400484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn// List of the _only_ needles we supply here to android::strnstr 410484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char suspendStr[] = "PM: suspend entry "; 420484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char resumeStr[] = "PM: suspend exit "; 430484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char suspendedStr[] = "Suspended for "; 440484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char healthdStr[] = "healthd"; 450484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char batteryStr[] = ": battery "; 460484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char auditStr[] = " audit("; 470484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char klogdStr[] = "logd.klogd: "; 480484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn 492c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// Parsing is hard 502c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 512c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// called if we see a '<', s is the next character, returns pointer after '>' 520484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic char* is_prio(char* s, ssize_t len) { 530484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len <= 0) || !isdigit(*s++)) return nullptr; 54ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn --len; 55ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn static const size_t max_prio_len = (len < 4) ? len : 4; 56ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn size_t priolen = 0; 572c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn char c; 58ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn while (((c = *s++)) && (++priolen <= max_prio_len)) { 590484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (!isdigit(c)) return ((c == '>') && (*s == '[')) ? s : nullptr; 602c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 610484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn return nullptr; 622c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn} 632c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 642c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// called if we see a '[', s is the next character, returns pointer after ']' 650484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic char* is_timestamp(char* s, ssize_t len) { 660484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((len > 0) && (*s == ' ')) { 672c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn ++s; 68ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn --len; 692c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 700484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len <= 0) || !isdigit(*s++)) return nullptr; 71ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn --len; 722c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn bool first_period = true; 732c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn char c; 740484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((len > 0) && ((c = *s++))) { 75ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn --len; 762c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn if ((c == '.') && first_period) { 772c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn first_period = false; 78ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn } else if (!isdigit(c)) { 790484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn return ((c == ']') && !first_period && (*s == ' ')) ? s : nullptr; 802c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 812c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 820484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn return nullptr; 832c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn} 842c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 852c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// Like strtok_r with "\r\n" except that we look for log signatures (regex) 86501c373916e292764400dbae735f44b33378400fMark Salyzyn// \(\(<[0-9]\{1,4\}>\)\([[] *[0-9]+[.][0-9]+[]] \)\{0,1\}\|[[] 87501c373916e292764400dbae735f44b33378400fMark Salyzyn// *[0-9]+[.][0-9]+[]] \) 882c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// and split if we see a second one without a newline. 89151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn// We allow nuls in content, monitoring the overall length and sub-length of 90151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn// the discovered tokens. 912c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 92501c373916e292764400dbae735f44b33378400fMark Salyzyn#define SIGNATURE_MASK 0xF0 932c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// <digit> following ('0' to '9' masked with ~SIGNATURE_MASK) added to signature 94501c373916e292764400dbae735f44b33378400fMark Salyzyn#define LESS_THAN_SIG SIGNATURE_MASK 95501c373916e292764400dbae735f44b33378400fMark Salyzyn#define OPEN_BRACKET_SIG ((SIGNATURE_MASK << 1) & SIGNATURE_MASK) 962c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn// space is one more than <digit> of 9 973e21de2915a44d9f6d6a9e8610a2fc5feb33d107Mark Salyzyn#define OPEN_BRACKET_SPACE ((char)(OPEN_BRACKET_SIG | 10)) 982c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 990484b3b5757594a43c6b646824b44643d2a007deMark Salyzynchar* android::log_strntok_r(char* s, ssize_t& len, char*& last, 1000484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t& sublen) { 1010484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sublen = 0; 1020484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len <= 0) return nullptr; 1032c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn if (!s) { 1040484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (!(s = last)) return nullptr; 1052c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn // fixup for log signature split <, 1062c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn // LESS_THAN_SIG + <digit> 1072c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn if ((*s & SIGNATURE_MASK) == LESS_THAN_SIG) { 1082c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn *s = (*s & ~SIGNATURE_MASK) + '0'; 1092c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn *--s = '<'; 1100484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ++len; 1112c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 1122c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn // fixup for log signature split [, 1132c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn // OPEN_BRACKET_SPACE is space, OPEN_BRACKET_SIG + <digit> 1142c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn if ((*s & SIGNATURE_MASK) == OPEN_BRACKET_SIG) { 1150484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn *s = (*s == OPEN_BRACKET_SPACE) ? ' ' : (*s & ~SIGNATURE_MASK) + '0'; 1162c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn *--s = '['; 1170484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ++len; 1182c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 1192c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 1202c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 1210484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((len > 0) && ((*s == '\r') || (*s == '\n'))) { 122ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn ++s; 1230484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn --len; 124ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn } 1252c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 1260484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len <= 0) return last = nullptr; 1272c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn char *peek, *tok = s; 1282c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 1292c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn for (;;) { 1300484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len <= 0) { 1310484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn last = nullptr; 1322c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn return tok; 133ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn } 134ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn char c = *s++; 1350484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn --len; 1360484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t adjust; 137ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn switch (c) { 138501c373916e292764400dbae735f44b33378400fMark Salyzyn case '\r': 139501c373916e292764400dbae735f44b33378400fMark Salyzyn case '\n': 1402c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn s[-1] = '\0'; 1410484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn last = s; 1422c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn return tok; 143501c373916e292764400dbae735f44b33378400fMark Salyzyn 144501c373916e292764400dbae735f44b33378400fMark Salyzyn case '<': 1450484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn peek = is_prio(s, len); 1460484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (!peek) break; 147501c373916e292764400dbae735f44b33378400fMark Salyzyn if (s != (tok + 1)) { // not first? 148501c373916e292764400dbae735f44b33378400fMark Salyzyn s[-1] = '\0'; 149501c373916e292764400dbae735f44b33378400fMark Salyzyn *s &= ~SIGNATURE_MASK; 150501c373916e292764400dbae735f44b33378400fMark Salyzyn *s |= LESS_THAN_SIG; // signature for '<' 1510484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn last = s; 152501c373916e292764400dbae735f44b33378400fMark Salyzyn return tok; 153501c373916e292764400dbae735f44b33378400fMark Salyzyn } 154ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn adjust = peek - s; 1550484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (adjust > len) { 1560484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn adjust = len; 157ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn } 1580484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sublen += adjust; 1590484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn len -= adjust; 1602c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn s = peek; 1610484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((*s == '[') && ((peek = is_timestamp(s + 1, len - 1)))) { 162501c373916e292764400dbae735f44b33378400fMark Salyzyn adjust = peek - s; 1630484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (adjust > len) { 1640484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn adjust = len; 165501c373916e292764400dbae735f44b33378400fMark Salyzyn } 1660484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sublen += adjust; 1670484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn len -= adjust; 168501c373916e292764400dbae735f44b33378400fMark Salyzyn s = peek; 169501c373916e292764400dbae735f44b33378400fMark Salyzyn } 1702c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn break; 171501c373916e292764400dbae735f44b33378400fMark Salyzyn 172501c373916e292764400dbae735f44b33378400fMark Salyzyn case '[': 1730484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn peek = is_timestamp(s, len); 1740484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (!peek) break; 175501c373916e292764400dbae735f44b33378400fMark Salyzyn if (s != (tok + 1)) { // not first? 176501c373916e292764400dbae735f44b33378400fMark Salyzyn s[-1] = '\0'; 177501c373916e292764400dbae735f44b33378400fMark Salyzyn if (*s == ' ') { 178501c373916e292764400dbae735f44b33378400fMark Salyzyn *s = OPEN_BRACKET_SPACE; 179501c373916e292764400dbae735f44b33378400fMark Salyzyn } else { 180501c373916e292764400dbae735f44b33378400fMark Salyzyn *s &= ~SIGNATURE_MASK; 181501c373916e292764400dbae735f44b33378400fMark Salyzyn *s |= OPEN_BRACKET_SIG; // signature for '[' 182501c373916e292764400dbae735f44b33378400fMark Salyzyn } 1830484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn last = s; 184501c373916e292764400dbae735f44b33378400fMark Salyzyn return tok; 185501c373916e292764400dbae735f44b33378400fMark Salyzyn } 186501c373916e292764400dbae735f44b33378400fMark Salyzyn adjust = peek - s; 1870484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (adjust > len) { 1880484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn adjust = len; 189501c373916e292764400dbae735f44b33378400fMark Salyzyn } 1900484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sublen += adjust; 1910484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn len -= adjust; 192501c373916e292764400dbae735f44b33378400fMark Salyzyn s = peek; 193501c373916e292764400dbae735f44b33378400fMark Salyzyn break; 1942c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 1950484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ++sublen; 1962c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn } 197618d0dec5037df0fad1ce5cc90da2b7fc2c88b0cMark Salyzyn // NOTREACHED 1982c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn} 1992c3b300fd8307e8da13608197d0a89bc613de5fbMark Salyzyn 20010b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzynlog_time LogKlog::correction = 20110b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn (log_time(CLOCK_REALTIME) < log_time(CLOCK_MONOTONIC)) 20210b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn ? log_time::EPOCH 20310b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn : (log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC)); 204ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 205501c373916e292764400dbae735f44b33378400fMark SalyzynLogKlog::LogKlog(LogBuffer* buf, LogReader* reader, int fdWrite, int fdRead, 206501c373916e292764400dbae735f44b33378400fMark Salyzyn bool auditd) 207501c373916e292764400dbae735f44b33378400fMark Salyzyn : SocketListener(fdRead, false), 208501c373916e292764400dbae735f44b33378400fMark Salyzyn logbuf(buf), 209501c373916e292764400dbae735f44b33378400fMark Salyzyn reader(reader), 210501c373916e292764400dbae735f44b33378400fMark Salyzyn signature(CLOCK_MONOTONIC), 211501c373916e292764400dbae735f44b33378400fMark Salyzyn initialized(false), 212501c373916e292764400dbae735f44b33378400fMark Salyzyn enableLogging(true), 213501c373916e292764400dbae735f44b33378400fMark Salyzyn auditd(auditd) { 2140484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const char klogd_message[] = "%s%s%" PRIu64 "\n"; 2150484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn char buffer[strlen(priority_message) + strlen(klogdStr) + 2160484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn strlen(klogd_message) + 20]; 2170484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn snprintf(buffer, sizeof(buffer), klogd_message, priority_message, klogdStr, 218501c373916e292764400dbae735f44b33378400fMark Salyzyn signature.nsec()); 219ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn write(fdWrite, buffer, strlen(buffer)); 220ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 221ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 222501c373916e292764400dbae735f44b33378400fMark Salyzynbool LogKlog::onDataAvailable(SocketClient* cli) { 223ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (!initialized) { 224ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn prctl(PR_SET_NAME, "logd.klogd"); 225ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn initialized = true; 226ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn enableLogging = false; 227ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 228ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 229ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn char buffer[LOGGER_ENTRY_MAX_PAYLOAD]; 2300484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t len = 0; 231ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 232501c373916e292764400dbae735f44b33378400fMark Salyzyn for (;;) { 233ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn ssize_t retval = 0; 2340484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len < (ssize_t)(sizeof(buffer) - 1)) { 235501c373916e292764400dbae735f44b33378400fMark Salyzyn retval = 236501c373916e292764400dbae735f44b33378400fMark Salyzyn read(cli->getSocket(), buffer + len, sizeof(buffer) - 1 - len); 237ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 2380484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((retval == 0) && (len <= 0)) { 239ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn break; 240ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 241ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (retval < 0) { 242ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return false; 243ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 244ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn len += retval; 245ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn bool full = len == (sizeof(buffer) - 1); 246501c373916e292764400dbae735f44b33378400fMark Salyzyn char* ep = buffer + len; 247ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn *ep = '\0'; 2480484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t sublen; 2490484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (char *ptr = nullptr, *tok = buffer; 2500484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn !!(tok = android::log_strntok_r(tok, len, ptr, sublen)); 2510484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn tok = nullptr) { 252ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn if (((tok + sublen) >= ep) && (retval != 0) && full) { 2530484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (sublen > 0) memmove(buffer, tok, sublen); 254ea1a24110767d6d5666fda8a19dd0b3f954068d6Mark Salyzyn len = sublen; 255ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn break; 256ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 2570484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((sublen > 0) && *tok) { 258151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn log(tok, sublen); 259ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 260ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 261ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 262ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 263ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return true; 264ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 265ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 266501c373916e292764400dbae735f44b33378400fMark Salyzynvoid LogKlog::calculateCorrection(const log_time& monotonic, 2670484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* real_string, ssize_t len) { 2680484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const char real_format[] = "%Y-%m-%d %H:%M:%S.%09q UTC"; 2690484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len < (ssize_t)(strlen(real_format) + 5)) return; 2700484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn 271ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn log_time real; 2720484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* ep = real.strptime(real_string, real_format); 27310b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn if (!ep || (ep > &real_string[len]) || (real > log_time(CLOCK_REALTIME))) { 274ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return; 275ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 276ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // kernel report UTC, log_time::strptime is localtime from calendar. 277ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Bionic and liblog strptime does not support %z or %Z to pick up 278ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // timezone so we are calculating our own correction. 279ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn time_t now = real.tv_sec; 280ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn struct tm tm; 281ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn memset(&tm, 0, sizeof(tm)); 282ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn tm.tm_isdst = -1; 283ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn localtime_r(&now, &tm); 284ff8b8e838bb4c79bf767691be4c6a5d5583bb136Mark Salyzyn if ((tm.tm_gmtoff < 0) && ((-tm.tm_gmtoff) > (long)real.tv_sec)) { 28510b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn real = log_time::EPOCH; 28610b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } else { 28710b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn real.tv_sec += tm.tm_gmtoff; 28810b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } 28910b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn if (monotonic > real) { 29010b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn correction = log_time::EPOCH; 29110b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } else { 29210b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn correction = real - monotonic; 29310b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } 294ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 295ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 2960484b3b5757594a43c6b646824b44643d2a007deMark Salyzynvoid LogKlog::sniffTime(log_time& now, const char*& buf, ssize_t len, 297151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn bool reverse) { 2980484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len <= 0) return; 2990484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn 3000484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* cp = nullptr; 3010484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len > 10) && (*buf == '[')) { 3020484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn cp = now.strptime(buf, "[ %s.%q]"); // can index beyond buffer bounds 3030484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (cp && (cp > &buf[len - 1])) cp = nullptr; 304151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn } 305151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn if (cp) { 3060484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn len -= cp - buf; 3070484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len > 0) && isspace(*cp)) { 308ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn ++cp; 309151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn --len; 310ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 3110484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn buf = cp; 3122d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn 3130484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (isMonotonic()) return; 314b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn 315a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn const char* b; 316501c373916e292764400dbae735f44b33378400fMark Salyzyn if (((b = android::strnstr(cp, len, suspendStr))) && 3170484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (((b += strlen(suspendStr)) - cp) < len)) { 318151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn len -= b - cp; 319151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn calculateCorrection(now, b, len); 320501c373916e292764400dbae735f44b33378400fMark Salyzyn } else if (((b = android::strnstr(cp, len, resumeStr))) && 3210484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (((b += strlen(resumeStr)) - cp) < len)) { 322151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn len -= b - cp; 323151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn calculateCorrection(now, b, len); 3240484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn } else if (((b = android::strnstr(cp, len, healthdStr))) && 3250484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (((b += strlen(healthdStr)) - cp) < len) && 3260484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ((b = android::strnstr(b, len -= b - cp, batteryStr))) && 3270484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (((b += strlen(batteryStr)) - cp) < len)) { 32810b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn // NB: healthd is roughly 150us late, so we use it instead to 32910b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn // trigger a check for ntp-induced or hardware clock drift. 33010b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn log_time real(CLOCK_REALTIME); 33110b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn log_time mono(CLOCK_MONOTONIC); 33210b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn correction = (real < mono) ? log_time::EPOCH : (real - mono); 333501c373916e292764400dbae735f44b33378400fMark Salyzyn } else if (((b = android::strnstr(cp, len, suspendedStr))) && 3340484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (((b += strlen(suspendStr)) - cp) < len)) { 335151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn len -= b - cp; 336ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn log_time real; 337501c373916e292764400dbae735f44b33378400fMark Salyzyn char* endp; 338151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn real.tv_sec = strtol(b, &endp, 10); 3390484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((*endp == '.') && ((endp - b) < len)) { 3402d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn unsigned long multiplier = NS_PER_SEC; 3412d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn real.tv_nsec = 0; 342151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn len -= endp - b; 343151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn while (--len && isdigit(*++endp) && (multiplier /= 10)) { 3442d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn real.tv_nsec += (*endp - '0') * multiplier; 3452d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 346ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (reverse) { 34710b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn if (real > correction) { 34810b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn correction = log_time::EPOCH; 34910b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } else { 35010b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn correction -= real; 35110b82b683405e9ccd0cc162fa44a2ec6a9f26448Mark Salyzyn } 352ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } else { 353ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn correction += real; 354ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 355ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 356ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 357ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 358ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn convertMonotonicToReal(now); 359ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } else { 360b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn if (isMonotonic()) { 361b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn now = log_time(CLOCK_MONOTONIC); 362b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn } else { 363b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn now = log_time(CLOCK_REALTIME); 364b6bee33182cedea49199eb2252b3f3b442899c6dMark Salyzyn } 365ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 366ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 367ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 3680484b3b5757594a43c6b646824b44643d2a007deMark Salyzynpid_t LogKlog::sniffPid(const char*& buf, ssize_t len) { 3690484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len <= 0) return 0; 3700484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn 3710484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* cp = buf; 3720484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn // sscanf does a strlen, let's check if the string is not nul terminated. 3730484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn // pseudo out-of-bounds access since we always have an extra char on buffer. 3740484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (((ssize_t)strnlen(cp, len) == len) && cp[len]) { 3750484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn return 0; 3760484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn } 3770b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn // HTC kernels with modified printk "c0 1648 " 378501c373916e292764400dbae735f44b33378400fMark Salyzyn if ((len > 9) && (cp[0] == 'c') && isdigit(cp[1]) && 379501c373916e292764400dbae735f44b33378400fMark Salyzyn (isdigit(cp[2]) || (cp[2] == ' ')) && (cp[3] == ' ')) { 3800b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn bool gotDigit = false; 3810b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn int i; 3820b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn for (i = 4; i < 9; ++i) { 3830b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn if (isdigit(cp[i])) { 3840b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn gotDigit = true; 3850b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } else if (gotDigit || (cp[i] != ' ')) { 3860b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn break; 3870b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } 3880b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } 3890b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn if ((i == 9) && (cp[i] == ' ')) { 3900b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn int pid = 0; 3910b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn char dummy; 3920b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn if (sscanf(cp + 4, "%d%c", &pid, &dummy) == 2) { 3930484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn buf = cp + 10; // skip-it-all 3940b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn return pid; 3950b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } 3960b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } 3970b4a63d2127b553538262d552d3e4aba8f08733aMark Salyzyn } 398151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn while (len) { 39946d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn // Mediatek kernels with modified printk 40046d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn if (*cp == '[') { 40146d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn int pid = 0; 40246d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn char dummy; 40346d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn if (sscanf(cp, "[%d:%*[a-z_./0-9:A-Z]]%c", &pid, &dummy) == 2) { 40446d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn return pid; 40546d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn } 406501c373916e292764400dbae735f44b33378400fMark Salyzyn break; // Only the first one 40746d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn } 40846d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn ++cp; 409151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn --len; 41046d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn } 41146d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn return 0; 41246d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn} 41346d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn 4142d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn// kernel log prefix, convert to a kernel log priority number 4150484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic int parseKernelPrio(const char*& buf, ssize_t len) { 4162d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn int pri = LOG_USER | LOG_INFO; 4170484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* cp = buf; 4180484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len > 0) && (*cp == '<')) { 4192d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn pri = 0; 420501c373916e292764400dbae735f44b33378400fMark Salyzyn while (--len && isdigit(*++cp)) { 4212d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn pri = (pri * 10) + *cp - '0'; 4222d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 4230484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((len > 0) && (*cp == '>')) { 4242d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn ++cp; 4252d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } else { 4260484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn cp = buf; 4272d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn pri = LOG_USER | LOG_INFO; 4282d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 4290484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn buf = cp; 4302d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 4312d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn return pri; 4322d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn} 4332d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn 434ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Passed the entire SYSLOG_ACTION_READ_ALL buffer and interpret a 435ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// compensated start time. 4360484b3b5757594a43c6b646824b44643d2a007deMark Salyzynvoid LogKlog::synchronize(const char* buf, ssize_t len) { 437a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn const char* cp = android::strnstr(buf, len, suspendStr); 438ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (!cp) { 439a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn cp = android::strnstr(buf, len, resumeStr); 440a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn if (!cp) return; 4412d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } else { 442a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn const char* rp = android::strnstr(buf, len, resumeStr); 443a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn if (rp && (rp < cp)) cp = rp; 444ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 445ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 446ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn do { 447ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn --cp; 4482d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } while ((cp > buf) && (*cp != '\n')); 4492d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn if (*cp == '\n') { 4502d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn ++cp; 4512d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 4520484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn parseKernelPrio(cp, len - (cp - buf)); 453ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 454ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn log_time now; 4550484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sniffTime(now, cp, len - (cp - buf), true); 456ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 457a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn const char* suspended = android::strnstr(buf, len, suspendedStr); 458ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (!suspended || (suspended > cp)) { 459ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return; 460ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 461ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn cp = suspended; 462ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 463ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn do { 464ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn --cp; 4652d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } while ((cp > buf) && (*cp != '\n')); 4662d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn if (*cp == '\n') { 4672d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn ++cp; 4682d159bf3b597eb6defbb9e74c60a003bc9387a0aMark Salyzyn } 4690484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn parseKernelPrio(cp, len - (cp - buf)); 470ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 4710484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sniffTime(now, cp, len - (cp - buf), true); 472ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 473ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 474ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Convert kernel log priority number into an Android Logger priority number 475ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzynstatic int convertKernelPrioToAndroidPrio(int pri) { 476501c373916e292764400dbae735f44b33378400fMark Salyzyn switch (pri & LOG_PRIMASK) { 477501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_EMERG: 478ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // FALLTHRU 479501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_ALERT: 480ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // FALLTHRU 481501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_CRIT: 482501c373916e292764400dbae735f44b33378400fMark Salyzyn return ANDROID_LOG_FATAL; 483ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 484501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_ERR: 485501c373916e292764400dbae735f44b33378400fMark Salyzyn return ANDROID_LOG_ERROR; 486ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 487501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_WARNING: 488501c373916e292764400dbae735f44b33378400fMark Salyzyn return ANDROID_LOG_WARN; 489ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 490501c373916e292764400dbae735f44b33378400fMark Salyzyn default: 491ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // FALLTHRU 492501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_NOTICE: 493ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // FALLTHRU 494501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_INFO: 495501c373916e292764400dbae735f44b33378400fMark Salyzyn break; 496ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 497501c373916e292764400dbae735f44b33378400fMark Salyzyn case LOG_DEBUG: 498501c373916e292764400dbae735f44b33378400fMark Salyzyn return ANDROID_LOG_DEBUG; 499ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 500ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 501ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return ANDROID_LOG_INFO; 502ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 503ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 5040484b3b5757594a43c6b646824b44643d2a007deMark Salyzynstatic const char* strnrchr(const char* s, ssize_t len, char c) { 5050484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* save = nullptr; 5060484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (; len > 0; ++s, len--) { 507501c373916e292764400dbae735f44b33378400fMark Salyzyn if (*s == c) { 508501c373916e292764400dbae735f44b33378400fMark Salyzyn save = s; 509501c373916e292764400dbae735f44b33378400fMark Salyzyn } 51047dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn } 511501c373916e292764400dbae735f44b33378400fMark Salyzyn return save; 51247dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn} 51347dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn 514ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// 515ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// log a message into the kernel log buffer 516ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// 517ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Filter rules to parse <PRI> <TIME> <tag> and <message> in order for 518ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// them to appear correct in the logcat output: 519ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// 520ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// LOG_KERN (0): 521ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag> ":" <message> 522ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag> <tag> ":" <message> 523ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag> <tag>_work ":" <message> 524ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag> '<tag>.<num>' ":" <message> 525ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag> '<tag><num>' ":" <message> 526ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] <tag>_host '<tag>.<num>' ":" <message> 527ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// (unimplemented) <PRI>[<TIME>] <tag> '<num>.<tag>' ":" <message> 528ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] "[INFO]"<tag> : <message> 529ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] "------------[ cut here ]------------" (?) 530ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI>[<TIME>] "---[ end trace 3225a3070ca3e4ac ]---" (?) 531ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_SYSLOG, LOG_LPR, LOG_NEWS 532ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_FTP: 533ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// <PRI+TAG>[<TIME>] (see sys/syslog.h) 534ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Observe: 535ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Minimum tag length = 3 NB: drops things like r5:c00bbadf, but allow PM: 536ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Maximum tag words = 2 537ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Maximum tag length = 16 NB: we are thinking of how ugly logcat can get. 538ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Not a Tag if there is no message content. 539ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// leading additional spaces means no tag, inherit last tag. 540ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Not a Tag if <tag>: is "ERROR:", "WARNING:", "INFO:" or "CPU:" 541ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// Drop: 542ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// empty messages 543ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// messages with ' audit(' in them if auditd is running 544ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// logd.klogd: 545ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// return -1 if message logd.klogd: <signature> 546ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn// 5470484b3b5757594a43c6b646824b44643d2a007deMark Salyzynint LogKlog::log(const char* buf, ssize_t len) { 5480484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (auditd && android::strnstr(buf, len, auditStr)) { 549ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return 0; 550ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 551ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 552a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn const char* p = buf; 5530484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn int pri = parseKernelPrio(p, len); 554ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 555ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn log_time now; 5560484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn sniffTime(now, p, len - (p - buf), false); 557ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 558ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // sniff for start marker 5590484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const char* start = android::strnstr(p, len - (p - buf), klogdStr); 56046d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn if (start) { 5610484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn uint64_t sig = strtoll(start + strlen(klogdStr), nullptr, 10); 562ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (sig == signature.nsec()) { 563ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (initialized) { 564ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn enableLogging = true; 565ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } else { 566ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn enableLogging = false; 567ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 568ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return -1; 569ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 570ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return 0; 571ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 572ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 573ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (!enableLogging) { 574ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return 0; 575ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 576ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 57746d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn // Parse pid, tid and uid 5780484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn const pid_t pid = sniffPid(p, len - (p - buf)); 57946d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn const pid_t tid = pid; 58083b247891cea88347b759d638814cea61995d2caMark Salyzyn uid_t uid = AID_ROOT; 58183b247891cea88347b759d638814cea61995d2caMark Salyzyn if (pid) { 58283b247891cea88347b759d638814cea61995d2caMark Salyzyn logbuf->lock(); 58383b247891cea88347b759d638814cea61995d2caMark Salyzyn uid = logbuf->pidToUid(pid); 58483b247891cea88347b759d638814cea61995d2caMark Salyzyn logbuf->unlock(); 58583b247891cea88347b759d638814cea61995d2caMark Salyzyn } 586ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 587ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Parse (rules at top) to pull out a tag from the incoming kernel message. 588ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Some may view the following as an ugly heuristic, the desire is to 589ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // beautify the kernel logs into an Android Logging format; the goal is 590ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // admirable but costly. 591eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn while ((p < &buf[len]) && (isspace(*p) || !*p)) { 592151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn ++p; 593ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 594501c373916e292764400dbae735f44b33378400fMark Salyzyn if (p >= &buf[len]) { // timestamp, no content 595ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return 0; 596ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 597151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn start = p; 598501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* tag = ""; 599501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* etag = tag; 6000484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t taglen = len - (p - buf); 601501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* bt = p; 602a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 603a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char infoBrace[] = "[INFO]"; 6040484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t infoBraceLen = strlen(infoBrace); 605501c373916e292764400dbae735f44b33378400fMark Salyzyn if ((taglen >= infoBraceLen) && 606501c373916e292764400dbae735f44b33378400fMark Salyzyn !fastcmp<strncmp>(p, infoBrace, infoBraceLen)) { 607a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // <PRI>[<TIME>] "[INFO]"<tag> ":" message 608a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn bt = p + infoBraceLen; 609a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn taglen -= infoBraceLen; 610a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } 611a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 612501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* et; 6130484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (et = bt; (taglen > 0) && *et && (*et != ':') && !isspace(*et); 614501c373916e292764400dbae735f44b33378400fMark Salyzyn ++et, --taglen) { 615501c373916e292764400dbae735f44b33378400fMark Salyzyn // skip ':' within [ ... ] 616501c373916e292764400dbae735f44b33378400fMark Salyzyn if (*et == '[') { 6170484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((taglen > 0) && *et && *et != ']') { 618501c373916e292764400dbae735f44b33378400fMark Salyzyn ++et; 619501c373916e292764400dbae735f44b33378400fMark Salyzyn --taglen; 620501c373916e292764400dbae735f44b33378400fMark Salyzyn } 6210484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (taglen <= 0) { 622501c373916e292764400dbae735f44b33378400fMark Salyzyn break; 623501c373916e292764400dbae735f44b33378400fMark Salyzyn } 624501c373916e292764400dbae735f44b33378400fMark Salyzyn } 625501c373916e292764400dbae735f44b33378400fMark Salyzyn } 626501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* cp; 6270484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (cp = et; (taglen > 0) && isspace(*cp); ++cp, --taglen) { 628a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } 629a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 630a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // Validate tag 6310484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t size = et - bt; 6320484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((taglen > 0) && (size > 0)) { 633ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (*cp == ':') { 634a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // ToDo: handle case insensitive colon separated logging stutter: 635a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // <tag> : <tag>: ... 636a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 637ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // One Word 638ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn tag = bt; 639ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn etag = et; 640151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn p = cp + 1; 641a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) { 642a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // clean up any tag stutter 643501c373916e292764400dbae735f44b33378400fMark Salyzyn if (!fastcmp<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match 644ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // <PRI>[<TIME>] <tag> <tag> : message 645a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // <PRI>[<TIME>] <tag> <tag>: message 646ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // <PRI>[<TIME>] <tag> '<tag>.<num>' : message 647ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // <PRI>[<TIME>] <tag> '<tag><num>' : message 648a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // <PRI>[<TIME>] <tag> '<tag><stuff>' : message 649501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* b = cp; 650ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn cp += size; 651151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn taglen -= size; 6520484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((--taglen > 0) && !isspace(*++cp) && (*cp != ':')) { 653501c373916e292764400dbae735f44b33378400fMark Salyzyn } 654501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* e; 6550484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (e = cp; (taglen > 0) && isspace(*cp); ++cp, --taglen) { 656501c373916e292764400dbae735f44b33378400fMark Salyzyn } 6570484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((taglen > 0) && (*cp == ':')) { 658ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn tag = b; 659ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn etag = e; 660151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn p = cp + 1; 661ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 662ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } else { 663a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // what about <PRI>[<TIME>] <tag>_host '<tag><stuff>' : message 664a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char host[] = "_host"; 6650484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t hostlen = strlen(host); 666a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn if ((size > hostlen) && 667501c373916e292764400dbae735f44b33378400fMark Salyzyn !fastcmp<strncmp>(bt + size - hostlen, host, hostlen) && 668501c373916e292764400dbae735f44b33378400fMark Salyzyn !fastcmp<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) { 669501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* b = cp; 670a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn cp += size - hostlen; 671a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn taglen -= size - hostlen; 672a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn if (*cp == '.') { 6730484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((--taglen > 0) && !isspace(*++cp) && 6740484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn (*cp != ':')) { 675501c373916e292764400dbae735f44b33378400fMark Salyzyn } 676501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* e; 6770484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (e = cp; (taglen > 0) && isspace(*cp); 6780484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ++cp, --taglen) { 679501c373916e292764400dbae735f44b33378400fMark Salyzyn } 6800484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((taglen > 0) && (*cp == ':')) { 681a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn tag = b; 682a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn etag = e; 683a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn p = cp + 1; 684a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } 685a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } 686a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } else { 687a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn goto twoWord; 688ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 689ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 690a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } else { 691501c373916e292764400dbae735f44b33378400fMark Salyzyn // <PRI>[<TIME>] <tag> <stuff>' : message 692501c373916e292764400dbae735f44b33378400fMark Salyzyn twoWord: 6930484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((--taglen > 0) && !isspace(*++cp) && (*cp != ':')) { 694501c373916e292764400dbae735f44b33378400fMark Salyzyn } 695501c373916e292764400dbae735f44b33378400fMark Salyzyn const char* e; 6960484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn for (e = cp; (taglen > 0) && isspace(*cp); ++cp, --taglen) { 697501c373916e292764400dbae735f44b33378400fMark Salyzyn } 698a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // Two words 6990484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((taglen > 0) && (*cp == ':')) { 700a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn tag = bt; 701a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn etag = e; 702a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn p = cp + 1; 703a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn } 704ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 705501c373916e292764400dbae735f44b33378400fMark Salyzyn } // else no tag 706a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 707a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char cpu[] = "CPU"; 7080484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t cpuLen = strlen(cpu); 709a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char warning[] = "WARNING"; 7100484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t warningLen = strlen(warning); 711a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char error[] = "ERROR"; 7120484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t errorLen = strlen(error); 713a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn static const char info[] = "INFO"; 7140484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn static const ssize_t infoLen = strlen(info); 715a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 716a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn size = etag - tag; 717501c373916e292764400dbae735f44b33378400fMark Salyzyn if ((size <= 1) || 718a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // register names like x9 719501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1]))) || 720a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // register names like x18 but not driver names like en0 721501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2]))) || 722a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn // blacklist 723501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == cpuLen) && !fastcmp<strncmp>(tag, cpu, cpuLen)) || 724501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == warningLen) && 725501c373916e292764400dbae735f44b33378400fMark Salyzyn !fastcmp<strncasecmp>(tag, warning, warningLen)) || 726501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == errorLen) && !fastcmp<strncasecmp>(tag, error, errorLen)) || 727501c373916e292764400dbae735f44b33378400fMark Salyzyn ((size == infoLen) && !fastcmp<strncasecmp>(tag, info, infoLen))) { 728a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn p = start; 729a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn etag = tag = ""; 730ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 731a146a779e2154c51c87b140e06c456d010af1197Mark Salyzyn 73246d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn // Suppress additional stutter in tag: 73346d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn // eg: [143:healthd]healthd -> [143:healthd] 734151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn taglen = etag - tag; 73546d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn // Mediatek-special printk induced stutter 73634450d70c5ba8efb20df14721507b1bf56e06f82Andreas Gampe const char* mp = strnrchr(tag, taglen, ']'); 73747dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn if (mp && (++mp < etag)) { 7380484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t s = etag - mp; 7390eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn if (((s + s) < taglen) && !fastcmp<memcmp>(mp, mp - 1 - s, s)) { 74047dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn taglen = mp - tag; 74146d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn } 74246d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn } 743eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // Deal with sloppy and simplistic harmless p = cp + 1 etc above. 7440484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if (len < (p - buf)) { 745eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn p = &buf[len]; 746eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn } 747ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn // skip leading space 748eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn while ((p < &buf[len]) && (isspace(*p) || !*p)) { 749151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn ++p; 750ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 751151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn // truncate trailing space or nuls 7520484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t b = len - (p - buf); 7530484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn while ((b > 0) && (isspace(p[b - 1]) || !p[b - 1])) { 754ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn --b; 755ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn } 756ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn // trick ... allow tag with empty content to be logged. log() drops empty 7570484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((b <= 0) && (taglen > 0)) { 758151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn p = " "; 759ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn b = 1; 760ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn } 761eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // paranoid sanity check, can not happen ... 762ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn if (b > LOGGER_ENTRY_MAX_PAYLOAD) { 763ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn b = LOGGER_ENTRY_MAX_PAYLOAD; 764ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn } 765eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn if (taglen > LOGGER_ENTRY_MAX_PAYLOAD) { 766eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn taglen = LOGGER_ENTRY_MAX_PAYLOAD; 767eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn } 768eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // calculate buffer copy requirements 7690484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn ssize_t n = 1 + taglen + 1 + b + 1; 770eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // paranoid sanity check, first two just can not happen ... 7710484b3b5757594a43c6b646824b44643d2a007deMark Salyzyn if ((taglen > n) || (b > n) || (n > (ssize_t)USHRT_MAX) || (n <= 0)) { 772eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn return -EINVAL; 77347dba71f240624fc0fc9d39e2b91dc82ef164b39Mark Salyzyn } 774ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 775eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // Careful. 776eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // We are using the stack to house the log buffer for speed reasons. 777eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // If we malloc'd this buffer, we could get away without n's USHRT_MAX 778eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // test above, but we would then required a max(n, USHRT_MAX) as 779eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // truncating length argument to logbuf->log() below. Gain is protection 780eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn // of stack sanity and speedup, loss is truncated long-line content. 781ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn char newstr[n]; 782501c373916e292764400dbae735f44b33378400fMark Salyzyn char* np = newstr; 783ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 784ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Convert priority into single-byte Android logger priority 785ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn *np = convertKernelPrioToAndroidPrio(pri); 786ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn ++np; 787ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 788ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Copy parsed tag following priority 789151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn memcpy(np, tag, taglen); 79046d159d4626ca5d5667b739792840c3178a1457bMark Salyzyn np += taglen; 791ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn *np = '\0'; 792ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn ++np; 793ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 794ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Copy main message to the remainder 795151beac76d372c5c1bd71e656a6cfbd177e36509Mark Salyzyn memcpy(np, p, b); 796ee49c6a670a54e0636f81f39ddc93c87c9a4d766Mark Salyzyn np[b] = '\0'; 797ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 798b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn if (!isMonotonic()) { 799b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn // Watch out for singular race conditions with timezone causing near 800b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn // integer quarter-hour jumps in the time and compensate accordingly. 801b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn // Entries will be temporal within near_seconds * 2. b/21868540 802b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn static uint32_t vote_time[3]; 803b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn vote_time[2] = vote_time[1]; 804b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn vote_time[1] = vote_time[0]; 805b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn vote_time[0] = now.tv_sec; 806b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn 807b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn if (vote_time[1] && vote_time[2]) { 808b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn static const unsigned near_seconds = 10; 809b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn static const unsigned timezones_seconds = 900; 810b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn int diff0 = (vote_time[0] - vote_time[1]) / near_seconds; 811b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn unsigned abs0 = (diff0 < 0) ? -diff0 : diff0; 812b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn int diff1 = (vote_time[1] - vote_time[2]) / near_seconds; 813b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn unsigned abs1 = (diff1 < 0) ? -diff1 : diff1; 814501c373916e292764400dbae735f44b33378400fMark Salyzyn if ((abs1 <= 1) && // last two were in agreement on timezone 815501c373916e292764400dbae735f44b33378400fMark Salyzyn ((abs0 + 1) % (timezones_seconds / near_seconds)) <= 2) { 816b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn abs0 = (abs0 + 1) / (timezones_seconds / near_seconds) * 817501c373916e292764400dbae735f44b33378400fMark Salyzyn timezones_seconds; 818b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn now.tv_sec -= (diff0 < 0) ? -abs0 : abs0; 819b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn } 820b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn } 821b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn } 822b06247d9a0de9dd31a84e17deaf597f6a2cb2920Mark Salyzyn 823ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // Log message 824eb298086153a9502bb0b02a1a26919a482b52535Mark Salyzyn int rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr, 825501c373916e292764400dbae735f44b33378400fMark Salyzyn (unsigned short)n); 826ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 827ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn // notify readers 828ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn if (!rc) { 829ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn reader->notifyNewLog(); 830ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn } 831ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn 832ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn return rc; 833ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn} 834