Merge "logd: fix kernel logline stutter"

This commit is contained in:
Mark Salyzyn 2015-06-08 20:33:12 +00:00 committed by Gerrit Code Review
commit 42951a8be7
3 changed files with 140 additions and 4 deletions

View File

@ -36,6 +36,140 @@
static const char priority_message[] = { KMSG_PRIORITY(LOG_INFO), '\0' };
// Parsing is hard
// called if we see a '<', s is the next character, returns pointer after '>'
static char *is_prio(char *s) {
if (!isdigit(*s++)) {
return NULL;
}
char c;
while ((c = *s++)) {
if (!isdigit(c) && (c == '>')) {
return s;
}
}
return NULL;
}
// called if we see a '[', s is the next character, returns pointer after ']'
static char *is_timestamp(char *s) {
while (*s == ' ') {
++s;
}
if (!isdigit(*s++)) {
return NULL;
}
bool first_period = true;
char c;
while ((c = *s++)) {
if ((c == '.') && first_period) {
first_period = false;
continue;
}
if (!isdigit(c) && (c == ']')) {
return s;
}
}
return NULL;
}
// Like strtok_r with "\r\n" except that we look for log signatures (regex)
// \(\(<[0-9]+>\)\([[] *[0-9]+[]]\)\{0,1\}\|[[] *[0-9]+[]]\)
// and split if we see a second one without a newline.
#define SIGNATURE_MASK 0xF0
// <digit> following ('0' to '9' masked with ~SIGNATURE_MASK) added to signature
#define LESS_THAN_SIG SIGNATURE_MASK
#define OPEN_BRACKET_SIG ((SIGNATURE_MASK << 1) & SIGNATURE_MASK)
// space is one more than <digit> of 9
#define OPEN_BRACKET_SPACE (OPEN_BRACKET_SIG | 10)
char *log_strtok_r(char *s, char **last) {
if (!s) {
if (!(s = *last)) {
return NULL;
}
// fixup for log signature split <,
// LESS_THAN_SIG + <digit>
if ((*s & SIGNATURE_MASK) == LESS_THAN_SIG) {
*s = (*s & ~SIGNATURE_MASK) + '0';
*--s = '<';
}
// fixup for log signature split [,
// OPEN_BRACKET_SPACE is space, OPEN_BRACKET_SIG + <digit>
if ((*s & SIGNATURE_MASK) == OPEN_BRACKET_SIG) {
if (*s == OPEN_BRACKET_SPACE) {
*s = ' ';
} else {
*s = (*s & ~SIGNATURE_MASK) + '0';
}
*--s = '[';
}
}
s += strspn(s, "\r\n");
if (!*s) { // no non-delimiter characters
*last = NULL;
return NULL;
}
char *peek, *tok = s;
for (;;) {
char c = *s++;
switch (c) {
case '\0':
*last = NULL;
return tok;
case '\r':
case '\n':
s[-1] = '\0';
*last = s;
return tok;
case '<':
peek = is_prio(s);
if (!peek) {
break;
}
if (s != (tok + 1)) { // not first?
s[-1] = '\0';
*s &= ~SIGNATURE_MASK;
*s |= LESS_THAN_SIG; // signature for '<'
*last = s;
return tok;
}
s = peek;
if ((*s == '[') && ((peek = is_timestamp(s + 1)))) {
s = peek;
}
break;
case '[':
peek = is_timestamp(s);
if (!peek) {
break;
}
if (s != (tok + 1)) { // not first?
s[-1] = '\0';
if (*s == ' ') {
*s = OPEN_BRACKET_SPACE;
} else {
*s &= ~SIGNATURE_MASK;
*s |= OPEN_BRACKET_SIG; // signature for '['
}
*last = s;
return tok;
}
s = peek;
break;
}
}
/* NOTREACHED */
}
log_time LogKlog::correction = log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC);
LogKlog::LogKlog(LogBuffer *buf, LogReader *reader, int fdWrite, int fdRead, bool auditd) :
@ -81,8 +215,8 @@ bool LogKlog::onDataAvailable(SocketClient *cli) {
char *ep = buffer + len;
*ep = '\0';
len = 0;
for(char *ptr, *tok = buffer;
((tok = strtok_r(tok, "\r\n", &ptr)));
for(char *ptr = NULL, *tok = buffer;
((tok = log_strtok_r(tok, &ptr)));
tok = NULL) {
if (((tok + strlen(tok)) == ep) && (retval != 0) && full) {
len = strlen(tok);

View File

@ -21,6 +21,8 @@
#include <log/log_read.h>
#include "LogReader.h"
char *log_strtok_r(char *str, char **saveptr);
class LogKlog : public SocketListener {
LogBuffer *logbuf;
LogReader *reader;

View File

@ -417,8 +417,8 @@ int main(int argc, char *argv[]) {
kl->synchronize(buf);
}
for (char *ptr, *tok = buf;
(rc >= 0) && ((tok = strtok_r(tok, "\r\n", &ptr)));
for (char *ptr = NULL, *tok = buf;
(rc >= 0) && ((tok = log_strtok_r(tok, &ptr)));
tok = NULL) {
if (al) {
rc = al->log(tok);