Skip to content

Commit

Permalink
Merge pull request #90 from ssahani/dev
Browse files Browse the repository at this point in the history
Journal reading improvements
  • Loading branch information
ssahani authored May 14, 2024
2 parents 8f816ed + c8ca5bd commit bae4f42
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 66 deletions.
130 changes: 77 additions & 53 deletions src/netlog/netlog-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,81 @@ static const char *const log_format_table[_SYSLOG_TRANSMISSION_LOG_FORMAT_MAX] =

DEFINE_STRING_TABLE_LOOKUP(log_format, int);

static int parse_field(const void *data, size_t length, const char *field, char **target) {
size_t fl, nl;
void *buf;
typedef struct ParseFieldVec {
const char *field;
size_t field_len;
char **target;
size_t *target_len;
} ParseFieldVec;

#define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) { \
.field = _field, \
.field_len = strlen(_field), \
.target = _target, \
.target_len = _target_len \
}

static int parse_field(
const void *data,
size_t length,
const char *field,
size_t field_len,
char **target,
size_t *target_len) {

size_t nl;
char *buf;

assert(data);
assert(field);
assert(target);

fl = strlen(field);
if (length < fl)
if (length < field_len)
return 0;

if (memcmp(data, field, fl))
if (memcmp(data, field, field_len))
return 0;

nl = length - fl;
buf = malloc(nl+1);
nl = length - field_len;

buf = newdup_suffix0(char, (const char*) data + field_len, nl);
if (!buf)
return -ENOMEM;
return log_oom();

memcpy(buf, (const char*) data + fl, nl);
((char*)buf)[nl] = 0;
free_and_replace(*target, buf);

free(*target);
*target = buf;
if (target_len)
*target_len = nl;

return 1;
}

static int parse_fieldv(
const void *data,
size_t length,
const ParseFieldVec *fields,
size_t n_fields) {

int r;

for (size_t i = 0; i < n_fields; i++) {
const ParseFieldVec *f = &fields[i];

r = parse_field(data, length, f->field, f->field_len, f->target, f->target_len);
if (r < 0)
return r;
if (r > 0)
break;
}

return 0;
}

static int manager_read_journal_input(Manager *m) {
_cleanup_free_ char *facility = NULL, *identifier = NULL, *priority = NULL, *message = NULL, *pid = NULL,
*hostname = NULL, *structured_data = NULL, *msgid = NULL;
size_t hostname_len = 0, identifier_len = 0, message_len = 0, priority_len = 0, facility_len = 0,
structured_data_len = 0, msgid_len = 0, pid_len = 0;
unsigned sev = JOURNAL_DEFAULT_SEVERITY;
unsigned fac = JOURNAL_DEFAULT_FACILITY;
struct timeval tv;
Expand All @@ -86,6 +129,16 @@ static int manager_read_journal_input(Manager *m) {
size_t length;
char *cursor;
int r;
const ParseFieldVec fields[] = {
PARSE_FIELD_VEC_ENTRY("_PID=", &pid, &pid_len ),
PARSE_FIELD_VEC_ENTRY("MESSAGE=", &message, &message_len ),
PARSE_FIELD_VEC_ENTRY("PRIORITY=", &priority, &priority_len ),
PARSE_FIELD_VEC_ENTRY("_HOSTNAME=", &hostname, &hostname_len ),
PARSE_FIELD_VEC_ENTRY("SYSLOG_FACILITY=", &facility, &facility_len ),
PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len ),
PARSE_FIELD_VEC_ENTRY("SYSLOG_STRUCTURED_DATA=", &structured_data, &structured_data_len ),
PARSE_FIELD_VEC_ENTRY("SYSLOG_MSGID", &msgid, &msgid_len ),
};

assert(m);
assert(m->journal);
Expand All @@ -97,50 +150,21 @@ static int manager_read_journal_input(Manager *m) {
log_debug("Reading from journal cursor=%s", cursor);

JOURNAL_FOREACH_DATA_RETVAL(m->journal, data, length, r) {

r = parse_field(data, length, "PRIORITY=", &priority);
if (r < 0)
return r;
else if (r > 0)
continue;

r = parse_field(data, length, "SYSLOG_FACILITY=", &facility);
if (r < 0)
return r;
else if (r > 0)
continue;

r = parse_field(data, length, "_HOSTNAME=", &hostname);
if (r < 0)
return r;
else if (r > 0)
continue;

r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier);
if (r < 0)
return r;
else if (r > 0)
continue;

r = parse_field(data, length, "_PID=", &pid);
if (r < 0)
return r;
else if (r > 0)
continue;

r = parse_field(data, length, "MESSAGE=", &message);
r = parse_fieldv(data, length, fields, ELEMENTSOF(fields));
if (r < 0)
return r;
}

r = parse_field(data, length, "SYSLOG_STRUCTURED_DATA=", &structured_data);
if (r < 0)
return r;
else if (r > 0)
continue;
if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
log_debug_errno(r, "Skipping message we can't read: %m");
return 0;
}
if (r < 0)
return log_error_errno(r, "Failed to get journal fields: %m");

r = parse_field(data, length, "SYSLOG_MSGID=", &msgid);
if (r < 0)
return r;
if (!message) {
log_debug("Skipping message without MESSAGE= field.");
return 0;
}

r = sd_journal_get_realtime_usec(m->journal, &realtime);
Expand Down
18 changes: 18 additions & 0 deletions src/share/alloc-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ void* memdup(const void *p, size_t l) {
return r;
}

void* memdup_suffix0(const void *p, size_t l) {
void *ret;

assert(l == 0 || p);

/* The same as memdup() but place a safety NUL byte after the allocated memory */

if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */
return NULL;

ret = malloc(l + 1);
if (!ret)
return NULL;

((uint8_t*) ret)[l] = 0;
return memcpy_safe(ret, p, l);
}

void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
size_t a, newalloc;
void *q;
Expand Down
56 changes: 54 additions & 2 deletions src/share/alloc-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@

#include "macro.h"

/* Normal memcpy() requires src to be nonnull. We do nothing if n is 0. */
static inline void *memcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0)
return dst;
assert(src);
return memcpy(dst, src, n);
}

/* Normal mempcpy() requires src to be nonnull. We do nothing if n is 0. */
static inline void *mempcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0)
return dst;
assert(src);
return mempcpy(dst, src, n);
}

/* Normal memcmp() requires s1 and s2 to be nonnull. We do nothing if n is 0. */
static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
if (n == 0)
return 0;
assert(s1);
assert(s2);
return memcmp(s1, s2, n);
}

#define zero(x) (memzero(&(x), sizeof(x)))

#define new(t, n) ((t*) malloc_multiply(n, sizeof(t)))

#define new0(t, n) ((t*) calloc((n), sizeof(t)))
Expand All @@ -25,14 +52,17 @@ static inline void *mfree(void *memory) {
return NULL;
}

void* memdup(const void *p, size_t l) _alloc_(2);

static inline void freep(void *p) {
free(*(void**) p);
}

#define _cleanup_free_ _cleanup_(freep)

void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l);

#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, n, sizeof(t)))

static inline bool size_multiply_overflow(size_t size, size_t need) {
return _unlikely_(need != 0 && size > (SIZE_MAX / need));
}
Expand All @@ -58,6 +88,15 @@ _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, si
return memdup(p, size * need);
}

/* Note that we can't decorate this function with _alloc_() since the returned memory area is one byte larger
* than the product of its parameters. */
static inline void *memdup_suffix0_multiply(const void *p, size_t need, size_t size) {
if (size_multiply_overflow(size, need))
return NULL;

return memdup_suffix0(p, size * need);
}

void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);

Expand Down Expand Up @@ -91,3 +130,16 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
_new_ = alloca_align(_size_, (align)); \
(void*)memset(_new_, 0, _size_); \
})

#define free_and_replace_full(a, b, free_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b)* _b = &(b); \
free_func(*_a); \
*_a = *_b; \
*_b = NULL; \
0; \
})

#define free_and_replace(a, b) \
free_and_replace_full(a, b, free)
16 changes: 5 additions & 11 deletions src/share/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,12 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
qsort(base, nmemb, size, compar);
}

/**
* Normal memcpy requires src to be nonnull. We do nothing if n is 0.
*/
static inline void memcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0)
return;
assert(src);
memcpy(dst, src, n);
}
#define memzero(x, l) \
({ \
size_t _l_ = (l); \
_l_ > 0 ? memset((x), 0, _l_) : (x); \
})

#define memzero(x,l) (memset((x), 0, (l)))
#define zero(x) (memzero(&(x), sizeof(x)))

static inline void *mempset(void *s, int c, size_t n) {
memset(s, c, n);
Expand Down

0 comments on commit bae4f42

Please sign in to comment.