From 87d2c1ff6a7375f03476767e6f59454bcc5cd04b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2011 21:06:39 +0200 Subject: journal: add preliminary incomplete implementation --- src/journal/journalctl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/journal/journalctl.c (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c new file mode 100644 index 0000000000..838e8436e4 --- /dev/null +++ b/src/journal/journalctl.c @@ -0,0 +1,91 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "journal-private.h" + +int main(int argc, char *argv[]) { + int r; + JournalFile *f; + Object *o = NULL; + + log_parse_environment(); + log_open(); + + r = journal_file_open(NULL, "/var/log/journal/system.journal", O_RDONLY, 0644, &f); + if (r == -ENOENT) + r = journal_file_open(NULL, "/run/log/journal/system.journal", O_RDONLY, 0644, &f); + + if (r < 0) { + log_error("Failed to open journal: %s", strerror(-r)); + return EXIT_FAILURE; + } + + for (;;) { + uint64_t offset; + uint64_t n, i; + + r = journal_file_next_entry(f, o, &o, &offset); + if (r < 0) { + log_error("Failed to read journal: %s", strerror(-r)); + goto finish; + } + + if (r == 0) + break; + + printf("entry: %llu\n", (unsigned long long) le64toh(o->entry.seqnum)); + + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + uint64_t p, l; + + p = le64toh(o->entry.items[i].object_offset); + r = journal_file_move_to_object(f, p, &o); + if (r < 0) { + log_error("Failed to move to data: %s", strerror(-r)); + goto finish; + } + + if (le64toh(o->object.type) != OBJECT_DATA) { + log_error("Invalid file"); + goto finish; + } + + l = o->object.size - offsetof(Object, data.payload); + printf("\t[%.*s]\n", (int) l, o->data.payload); + + r = journal_file_move_to_object(f, offset, &o); + if (r < 0) { + log_error("Failed to move back to entry: %s", strerror(-r)); + goto finish; + } + } + } + +finish: + journal_file_close(f); + + return 0; +} -- cgit v1.2.3-54-g00ecf From 260a2be45522f03ce8d8aca38e471d7b0882ff05 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2011 22:00:05 +0200 Subject: journal: replace linked list by hashmap when merging files --- src/journal/journal-private.h | 12 +++++++++- src/journal/journalctl.c | 4 ++-- src/journal/journald.c | 4 ++-- src/journal/sd-journal.c | 54 ++++++++++++++++++++++++------------------- src/journal/test-journal.c | 2 +- 5 files changed, 46 insertions(+), 30 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-private.h b/src/journal/journal-private.h index 863a39893b..914b73a40b 100644 --- a/src/journal/journal-private.h +++ b/src/journal/journal-private.h @@ -27,10 +27,20 @@ #include "sd-journal.h" #include "journal-def.h" #include "util.h" +#include "sd-id128.h" + +typedef struct JournalCoursor { + sd_id128_t file_id; + sd_id128_t boot_id; + uint64_t seqnum; + uint64_t monotonic; + uint64_t realtime; + uint64_t xor_hash; +} JournalCoursor; typedef struct JournalFile JournalFile; -int journal_file_open(sd_journal *j, const char *fname, int flags, mode_t mode, JournalFile **ret); +int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile **ret); void journal_file_close(JournalFile *j); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 838e8436e4..7bcd842f6d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -33,9 +33,9 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - r = journal_file_open(NULL, "/var/log/journal/system.journal", O_RDONLY, 0644, &f); + r = journal_file_open("/var/log/journal/system.journal", O_RDONLY, 0644, &f); if (r == -ENOENT) - r = journal_file_open(NULL, "/run/log/journal/system.journal", O_RDONLY, 0644, &f); + r = journal_file_open("/run/log/journal/system.journal", O_RDONLY, 0644, &f); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); diff --git a/src/journal/journald.c b/src/journal/journald.c index 9297ca6fb7..818e146f94 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -257,11 +257,11 @@ static int process_event(Server *s, struct epoll_event *ev) { static int open_system_journal(JournalFile **f) { int r; - r = journal_file_open(NULL, "/var/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f); + r = journal_file_open("/var/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f); if (r == -ENOENT) { mkdir_p("/run/log/journal", 0755); - r = journal_file_open(NULL, "/run/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f); + r = journal_file_open("/run/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f); } return r; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index d49f717915..8bca300f93 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -32,6 +32,7 @@ #include "journal-private.h" #include "lookup3.h" #include "list.h" +#include "hashmap.h" #define DEFAULT_ARENA_MAX_SIZE (16ULL*1024ULL*1024ULL*1024ULL) #define DEFAULT_ARENA_MIN_SIZE (256ULL*1024ULL) @@ -43,8 +44,6 @@ #define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL) struct JournalFile { - sd_journal *journal; - int fd; char *path; struct stat last_stat; @@ -72,7 +71,7 @@ struct JournalFile { }; struct sd_journal { - LIST_HEAD(JournalFile, files); + Hashmap *files; }; static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; @@ -82,9 +81,6 @@ static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; void journal_file_close(JournalFile *f) { assert(f); - if (f->journal) - LIST_REMOVE(JournalFile, files, f->journal->files, f); - if (f->fd >= 0) close_nointr_nofail(f->fd); @@ -1146,7 +1142,6 @@ fail: } int journal_file_open( - sd_journal *j, const char *fname, int flags, mode_t mode, @@ -1242,11 +1237,6 @@ int journal_file_open( if (r < 0) goto fail; - if (j) { - LIST_PREPEND(JournalFile, files, j->files, f); - f->journal = j; - } - if (ret) *ret = f; @@ -1273,6 +1263,10 @@ int sd_journal_open(sd_journal **ret) { if (!j) return -ENOMEM; + j->files = hashmap_new(string_hash_func, string_compare_func); + if (!j->files) + goto fail; + NULSTR_FOREACH(p, search_paths) { DIR *d; @@ -1287,6 +1281,7 @@ int sd_journal_open(sd_journal **ret) { for (;;) { struct dirent buf, *de; int k; + JournalFile *f; k = readdir_r(d, &buf, &de); if (k != 0) { @@ -1309,19 +1304,24 @@ int sd_journal_open(sd_journal **ret) { goto fail; } - k = journal_file_open(j, fn, O_RDONLY, 0, NULL); - if (k < 0 && r == 0) - r = -k; - + k = journal_file_open(fn, O_RDONLY, 0, &f); free(fn); - } - } - if (!j->files) { - if (r >= 0) - r = -ENOENT; + if (k < 0) { - goto fail; + if (r == 0) + r = -k; + } else { + k = hashmap_put(j->files, f->path, f); + if (k < 0) { + journal_file_close(f); + closedir(d); + + r = k; + goto fail; + } + } + } } *ret = j; @@ -1336,8 +1336,14 @@ fail: void sd_journal_close(sd_journal *j) { assert(j); - while (j->files) - journal_file_close(j->files); + if (j->files) { + JournalFile *f; + + while ((f = hashmap_steal_first(j->files))) + journal_file_close(f); + + hashmap_free(j->files); + } free(j); } diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 92bef5f3ef..e0aedc7b83 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); - assert_se(journal_file_open(NULL, "test", O_RDWR|O_CREAT, 0666, &f) == 0); + assert_se(journal_file_open("test", O_RDWR|O_CREAT, 0666, &f) == 0); dual_timestamp_get(&ts); -- cgit v1.2.3-54-g00ecf From cec736d21ff86c4ac81b4d306ddba2120333818c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 8 Oct 2011 02:20:44 +0200 Subject: journal: implement parallel traversal in client --- Makefile.am | 3 + src/journal/journal-def.h | 5 +- src/journal/journal-file.c | 1191 +++++++++++++++++++++++++++++++++++++++ src/journal/journal-file.h | 86 +++ src/journal/journal-private.h | 86 --- src/journal/journalctl.c | 11 +- src/journal/journald.c | 11 +- src/journal/sd-journal.c | 1241 +++++------------------------------------ src/journal/sd-journal.h | 27 +- src/journal/test-journal.c | 2 +- 10 files changed, 1434 insertions(+), 1229 deletions(-) create mode 100644 src/journal/journal-file.c create mode 100644 src/journal/journal-file.h delete mode 100644 src/journal/journal-private.h (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index d43da3c47b..892072318f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -965,6 +965,7 @@ test_id128_LDADD = \ test_journal_SOURCES = \ src/journal/test-journal.c \ src/journal/sd-journal.c \ + src/journal/journal-file.c \ src/journal/lookup3.c \ src/sd-id128.c @@ -977,6 +978,7 @@ test_journal_LDADD = \ systemd_journald_SOURCES = \ src/journal/journald.c \ src/journal/sd-journal.c \ + src/journal/journal-file.c \ src/journal/lookup3.c \ src/sd-id128.c \ src/acl-util.c @@ -993,6 +995,7 @@ systemd_journald_LDADD = \ systemd_journalctl_SOURCES = \ src/journal/journalctl.c \ src/journal/sd-journal.c \ + src/journal/journal-file.c \ src/journal/lookup3.c \ src/sd-id128.c diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 2a519fe0db..b3fa1e524f 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -48,7 +48,7 @@ enum { _packed_ struct ObjectHeader { uint8_t type; - uint8_t reserved[3]; + uint8_t reserved[7]; uint64_t size; uint8_t payload[]; }; @@ -74,6 +74,7 @@ _packed_ struct EntryObject { uint64_t seqnum; uint64_t realtime; uint64_t monotonic; + sd_id128_t boot_id; uint64_t xor_hash; uint64_t prev_entry_offset; uint64_t next_entry_offset; @@ -118,6 +119,7 @@ _packed_ struct Header { sd_id128_t file_id; sd_id128_t machine_id; sd_id128_t boot_id; + sd_id128_t seqnum_id; uint64_t arena_offset; uint64_t arena_size; uint64_t arena_max_size; @@ -133,7 +135,6 @@ _packed_ struct Header { uint64_t tail_entry_offset; uint64_t last_bisect_offset; uint64_t n_objects; - uint64_t seqnum_base; uint64_t seqnum; }; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c new file mode 100644 index 0000000000..37e2e37eb1 --- /dev/null +++ b/src/journal/journal-file.c @@ -0,0 +1,1191 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "journal-def.h" +#include "journal-file.h" +#include "lookup3.h" + +#define DEFAULT_ARENA_MAX_SIZE (16ULL*1024ULL*1024ULL*1024ULL) +#define DEFAULT_ARENA_MIN_SIZE (256ULL*1024ULL) +#define DEFAULT_ARENA_KEEP_FREE (1ULL*1024ULL*1024ULL) + +#define DEFAULT_HASH_TABLE_SIZE (2047ULL*16ULL) +#define DEFAULT_BISECT_TABLE_SIZE ((DEFAULT_ARENA_MAX_SIZE/(64ULL*1024ULL))*8ULL) + +#define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL) + +static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; + +#define ALIGN64(x) (((x) + 7ULL) & ~7ULL) + +void journal_file_close(JournalFile *f) { + assert(f); + + if (f->fd >= 0) + close_nointr_nofail(f->fd); + + if (f->header) + munmap(f->header, PAGE_ALIGN(sizeof(Header))); + + if (f->hash_table_window) + munmap(f->hash_table_window, f->hash_table_window_size); + + if (f->bisect_table_window) + munmap(f->bisect_table_window, f->bisect_table_window_size); + + if (f->window) + munmap(f->window, f->window_size); + + free(f->path); + free(f); +} + +static int journal_file_init_header(JournalFile *f) { + Header h; + ssize_t k; + int r; + + assert(f); + + zero(h); + memcpy(h.signature, signature, 8); + h.arena_offset = htole64(ALIGN64(sizeof(h))); + h.arena_max_size = htole64(DEFAULT_ARENA_MAX_SIZE); + h.arena_min_size = htole64(DEFAULT_ARENA_MIN_SIZE); + h.arena_keep_free = htole64(DEFAULT_ARENA_KEEP_FREE); + + r = sd_id128_randomize(&h.file_id); + if (r < 0) + return r; + + h.seqnum_id = h.file_id; + + k = pwrite(f->fd, &h, sizeof(h), 0); + if (k < 0) + return -errno; + + if (k != sizeof(h)) + return -EIO; + + return 0; +} + +static int journal_file_refresh_header(JournalFile *f) { + int r; + + assert(f); + + r = sd_id128_get_machine(&f->header->machine_id); + if (r < 0) + return r; + + r = sd_id128_get_boot(&f->header->boot_id); + if (r < 0) + return r; + + f->header->state = htole32(STATE_ONLINE); + return 0; +} + +static int journal_file_verify_header(JournalFile *f) { + assert(f); + + if (memcmp(f->header, signature, 8)) + return -EBADMSG; + + if (f->header->incompatible_flags != 0) + return -EPROTONOSUPPORT; + + if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->arena_offset) + le64toh(f->header->arena_size))) + return -ENODATA; + + if (f->writable) { + uint32_t state; + sd_id128_t machine_id; + int r; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return r; + + if (!sd_id128_equal(machine_id, f->header->machine_id)) + return -EHOSTDOWN; + + state = le32toh(f->header->state); + + if (state == STATE_ONLINE) + log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); + else if (state == STATE_ARCHIVED) + return -ESHUTDOWN; + else if (state != STATE_OFFLINE) + log_debug("Journal file %s has unknown state %u. Ignoring.", f->path, state); + } + + return 0; +} + +static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { + uint64_t asize; + uint64_t old_size, new_size; + + assert(f); + + if (offset < le64toh(f->header->arena_offset)) + return -EINVAL; + + new_size = PAGE_ALIGN(offset + size); + + /* We assume that this file is not sparse, and we know that + * for sure, since we alway call posix_fallocate() + * ourselves */ + + old_size = + le64toh(f->header->arena_offset) + + le64toh(f->header->arena_size); + + if (old_size >= new_size) + return 0; + + asize = new_size - le64toh(f->header->arena_offset); + + if (asize > le64toh(f->header->arena_min_size)) { + struct statvfs svfs; + + if (fstatvfs(f->fd, &svfs) >= 0) { + uint64_t available; + + available = svfs.f_bfree * svfs.f_bsize; + + if (available >= f->header->arena_keep_free) + available -= f->header->arena_keep_free; + else + available = 0; + + if (new_size - old_size > available) + return -E2BIG; + } + } + + if (asize > le64toh(f->header->arena_max_size)) + return -E2BIG; + + if (posix_fallocate(f->fd, 0, new_size) < 0) + return -errno; + + if (fstat(f->fd, &f->last_stat) < 0) + return -errno; + + f->header->arena_size = htole64(asize); + + return 0; +} + +static int journal_file_map( + JournalFile *f, + uint64_t offset, + uint64_t size, + void **_window, + uint64_t *_woffset, + uint64_t *_wsize, + void **ret) { + + uint64_t woffset, wsize; + void *window; + + assert(f); + assert(size > 0); + assert(ret); + + woffset = offset & ~((uint64_t) page_size() - 1ULL); + wsize = size + (offset - woffset); + wsize = PAGE_ALIGN(wsize); + + window = mmap(NULL, wsize, f->prot, MAP_SHARED, f->fd, woffset); + if (window == MAP_FAILED) + return -errno; + + if (_window) + *_window = window; + + if (_woffset) + *_woffset = woffset; + + if (_wsize) + *_wsize = wsize; + + *ret = (uint8_t*) window + (offset - woffset); + + return 0; +} + +static int journal_file_move_to(JournalFile *f, uint64_t offset, uint64_t size, void **ret) { + void *p; + uint64_t delta; + int r; + + assert(f); + assert(ret); + + if (_likely_(f->window && + f->window_offset <= offset && + f->window_offset+f->window_size >= offset + size)) { + + *ret = (uint8_t*) f->window + (offset - f->window_offset); + return 0; + } + + if (f->window) { + if (munmap(f->window, f->window_size) < 0) + return -errno; + + f->window = NULL; + f->window_size = f->window_offset = 0; + } + + if (size < DEFAULT_WINDOW_SIZE) { + /* If the default window size is larger then what was + * asked for extend the mapping a bit in the hope to + * minimize needed remappings later on. We add half + * the window space before and half behind the + * requested mapping */ + + delta = PAGE_ALIGN((DEFAULT_WINDOW_SIZE - size) / 2); + + if (offset < delta) + delta = offset; + + offset -= delta; + size += (DEFAULT_WINDOW_SIZE - delta); + } else + delta = 0; + + r = journal_file_map(f, + offset, size, + &f->window, &f->window_offset, &f->window_size, + & p); + + if (r < 0) + return r; + + *ret = (uint8_t*) p + delta; + return 0; +} + +static bool verify_hash(Object *o) { + uint64_t t; + + assert(o); + + t = le64toh(o->object.type); + if (t == OBJECT_DATA) { + uint64_t s, h1, h2; + + s = le64toh(o->object.size); + + h1 = le64toh(o->data.hash); + h2 = hash64(o->data.payload, s - offsetof(Object, data.payload)); + + return h1 == h2; + } + + return true; +} + +int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Object **ret) { + int r; + void *t; + Object *o; + uint64_t s; + + assert(f); + assert(ret); + + r = journal_file_move_to(f, offset, sizeof(ObjectHeader), &t); + if (r < 0) + return r; + + o = (Object*) t; + s = le64toh(o->object.size); + + if (s < sizeof(ObjectHeader)) + return -EBADMSG; + + if (type >= 0 && le64toh(o->object.type) != type) + return -EBADMSG; + + if (s > sizeof(ObjectHeader)) { + r = journal_file_move_to(f, offset, s, &t); + if (r < 0) + return r; + + o = (Object*) t; + } + + if (!verify_hash(o)) + return -EBADMSG; + + *ret = o; + return 0; +} + +static uint64_t journal_file_seqnum(JournalFile *f) { + uint64_t r; + + assert(f); + + r = le64toh(f->header->seqnum) + 1; + f->header->seqnum = htole64(r); + + return r; +} + +static int journal_file_append_object(JournalFile *f, uint64_t size, Object **ret, uint64_t *offset) { + int r; + uint64_t p; + Object *tail, *o; + void *t; + + assert(f); + assert(size >= sizeof(ObjectHeader)); + assert(offset); + assert(ret); + + p = le64toh(f->header->tail_object_offset); + + if (p == 0) + p = le64toh(f->header->arena_offset); + else { + r = journal_file_move_to_object(f, p, -1, &tail); + if (r < 0) + return r; + + p += ALIGN64(le64toh(tail->object.size)); + } + + r = journal_file_allocate(f, p, size); + if (r < 0) + return r; + + r = journal_file_move_to(f, p, size, &t); + if (r < 0) + return r; + + o = (Object*) t; + + zero(o->object); + o->object.type = htole64(OBJECT_UNUSED); + zero(o->object.reserved); + o->object.size = htole64(size); + + f->header->tail_object_offset = htole64(p); + if (f->header->head_object_offset == 0) + f->header->head_object_offset = htole64(p); + + f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); + + *ret = o; + *offset = p; + + return 0; +} + +static int journal_file_setup_hash_table(JournalFile *f) { + uint64_t s, p; + Object *o; + int r; + + assert(f); + + s = DEFAULT_HASH_TABLE_SIZE; + r = journal_file_append_object(f, offsetof(Object, hash_table.table) + s, &o, &p); + if (r < 0) + return r; + + o->object.type = htole64(OBJECT_HASH_TABLE); + memset(o->hash_table.table, 0, s); + + f->header->hash_table_offset = htole64(p + offsetof(Object, hash_table.table)); + f->header->hash_table_size = htole64(s); + + return 0; +} + +static int journal_file_setup_bisect_table(JournalFile *f) { + uint64_t s, p; + Object *o; + int r; + + assert(f); + + s = DEFAULT_BISECT_TABLE_SIZE; + r = journal_file_append_object(f, offsetof(Object, bisect_table.table) + s, &o, &p); + if (r < 0) + return r; + + o->object.type = htole64(OBJECT_BISECT_TABLE); + memset(o->bisect_table.table, 0, s); + + f->header->bisect_table_offset = htole64(p + offsetof(Object, bisect_table.table)); + f->header->bisect_table_size = htole64(s); + + return 0; +} + +static int journal_file_map_hash_table(JournalFile *f) { + uint64_t s, p; + void *t; + int r; + + assert(f); + + p = le64toh(f->header->hash_table_offset); + s = le64toh(f->header->hash_table_size); + + r = journal_file_map(f, + p, s, + &f->hash_table_window, NULL, &f->hash_table_window_size, + &t); + if (r < 0) + return r; + + f->hash_table = t; + return 0; +} + +static int journal_file_map_bisect_table(JournalFile *f) { + uint64_t s, p; + void *t; + int r; + + assert(f); + + p = le64toh(f->header->bisect_table_offset); + s = le64toh(f->header->bisect_table_size); + + r = journal_file_map(f, + p, s, + &f->bisect_table_window, NULL, &f->bisect_table_window_size, + &t); + + if (r < 0) + return r; + + f->bisect_table = t; + return 0; +} + +static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, uint64_t hash_index) { + uint64_t p; + int r; + + assert(f); + assert(o); + assert(offset > 0); + assert(o->object.type == htole64(OBJECT_DATA)); + + o->data.head_entry_offset = o->data.tail_entry_offset = 0; + o->data.next_hash_offset = 0; + + p = le64toh(f->hash_table[hash_index].tail_hash_offset); + if (p == 0) { + /* Only entry in the hash table is easy */ + + o->data.prev_hash_offset = 0; + f->hash_table[hash_index].head_hash_offset = htole64(offset); + } else { + o->data.prev_hash_offset = htole64(p); + + /* Temporarily move back to the previous data object, + * to patch in pointer */ + + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + o->data.next_hash_offset = offset; + + r = journal_file_move_to_object(f, offset, OBJECT_DATA, &o); + if (r < 0) + return r; + } + + f->hash_table[hash_index].tail_hash_offset = htole64(offset); + + return 0; +} + +static int journal_file_append_data(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { + uint64_t hash, h, p, np; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(data || size == 0); + + osize = offsetof(Object, data.payload) + size; + + hash = hash64(data, size); + h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); + p = le64toh(f->hash_table[h].head_hash_offset); + + while (p != 0) { + /* Look for this data object in the hash table */ + + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + if (le64toh(o->object.size) == osize && + memcmp(o->data.payload, data, size) == 0) { + + if (le64toh(o->data.hash) != hash) + return -EBADMSG; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; + } + + p = le64toh(o->data.next_hash_offset); + } + + r = journal_file_append_object(f, osize, &o, &np); + if (r < 0) + return r; + + o->object.type = htole64(OBJECT_DATA); + o->data.hash = htole64(hash); + memcpy(o->data.payload, data, size); + + r = journal_file_link_data(f, o, np, h); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = np; + + return 0; +} + +uint64_t journal_file_entry_n_items(Object *o) { + assert(o); + assert(o->object.type == htole64(OBJECT_ENTRY)); + + return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); +} + +static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { + uint64_t p, q; + int r; + assert(f); + assert(o); + assert(offset > 0); + + p = le64toh(o->entry.items[i].object_offset); + if (p == 0) + return -EINVAL; + + o->entry.items[i].next_entry_offset = 0; + + /* Move to the data object */ + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + q = le64toh(o->data.tail_entry_offset); + o->data.tail_entry_offset = htole64(offset); + + if (q == 0) + o->data.head_entry_offset = htole64(offset); + else { + uint64_t n, j; + + /* Move to previous entry */ + r = journal_file_move_to_object(f, q, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + n = journal_file_entry_n_items(o); + for (j = 0; j < n; j++) + if (le64toh(o->entry.items[j].object_offset) == p) + break; + + if (j >= n) + return -EBADMSG; + + o->entry.items[j].next_entry_offset = offset; + } + + /* Move back to original entry */ + r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + o->entry.items[i].prev_entry_offset = q; + return 0; +} + +static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { + uint64_t p, i, n, k, a, b; + int r; + + assert(f); + assert(o); + assert(offset > 0); + assert(o->object.type == htole64(OBJECT_ENTRY)); + + /* Link up the entry itself */ + p = le64toh(f->header->tail_entry_offset); + + o->entry.prev_entry_offset = f->header->tail_entry_offset; + o->entry.next_entry_offset = 0; + + if (p == 0) + f->header->head_entry_offset = htole64(offset); + else { + /* Temporarily move back to the previous entry, to + * patch in pointer */ + + r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + o->entry.next_entry_offset = htole64(offset); + + r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + } + + f->header->tail_entry_offset = htole64(offset); + + /* Link up the items */ + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + r = journal_file_link_entry_item(f, o, offset, i); + if (r < 0) + return r; + } + + /* Link up the entry in the bisect table */ + n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); + k = le64toh(f->header->arena_max_size) / n; + + a = (le64toh(f->header->last_bisect_offset) + k - 1) / k; + b = offset / k; + + for (; a <= b; a++) + f->bisect_table[a] = htole64(offset); + + f->header->last_bisect_offset = htole64(offset + le64toh(o->object.size)); + + return 0; +} + +static int journal_file_append_entry_internal( + JournalFile *f, + const dual_timestamp *ts, + uint64_t xor_hash, + const EntryItem items[], unsigned n_items, + Object **ret, uint64_t *offset) { + uint64_t np; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(items || n_items == 0); + + osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem)); + + r = journal_file_append_object(f, osize, &o, &np); + if (r < 0) + return r; + + o->object.type = htole64(OBJECT_ENTRY); + o->entry.seqnum = htole64(journal_file_seqnum(f)); + memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); + o->entry.realtime = ts ? htole64(ts->realtime) : 0; + o->entry.monotonic = ts ? htole64(ts->monotonic) : 0; + o->entry.xor_hash = htole64(xor_hash); + o->entry.boot_id = f->header->boot_id; + + r = journal_file_link_entry(f, o, np); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = np; + + return 0; +} + +int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset) { + unsigned i; + EntryItem *items; + int r; + uint64_t xor_hash = 0; + + assert(f); + assert(iovec || n_iovec == 0); + + items = new(EntryItem, n_iovec); + if (!items) + return -ENOMEM; + + for (i = 0; i < n_iovec; i++) { + uint64_t p; + Object *o; + + r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p); + if (r < 0) + goto finish; + + xor_hash ^= le64toh(o->data.hash); + items[i].object_offset = htole64(p); + } + + r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, ret, offset); + +finish: + free(items); + + return r; +} + +int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset) { + Object *o; + uint64_t lower, upper, p, n, k; + int r; + + assert(f); + + n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); + k = le64toh(f->header->arena_max_size) / n; + + lower = 0; + upper = le64toh(f->header->last_bisect_offset)/k+1; + + while (lower < upper) { + k = (upper + lower) / 2; + p = le64toh(f->bisect_table[k]); + + if (p == 0) { + upper = k; + continue; + } + + r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (o->entry.seqnum == seqnum) { + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + } else if (seqnum < o->entry.seqnum) + upper = k; + else if (seqnum > o->entry.seqnum) + lower = k+1; + } + + assert(lower == upper); + + if (lower <= 0) + return 0; + + /* The object we are looking for is between + * bisect_table[lower-1] and bisect_table[lower] */ + + p = le64toh(f->bisect_table[lower-1]); + + for (;;) { + r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (o->entry.seqnum == seqnum) { + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + + } if (seqnum < o->entry.seqnum) + return 0; + + if (o->entry.next_entry_offset == 0) + return 0; + + p = le64toh(o->entry.next_entry_offset); + } + + return 0; +} + +int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) { + uint64_t np; + int r; + + assert(f); + + if (!o) + np = le64toh(f->header->head_entry_offset); + else { + if (le64toh(o->object.type) != OBJECT_ENTRY) + return -EINVAL; + + np = le64toh(o->entry.next_entry_offset); + } + + if (np == 0) + return 0; + + r = journal_file_move_to_object(f, np, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = np; + + return 1; +} + +int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) { + uint64_t np; + int r; + + assert(f); + + if (!o) + np = le64toh(f->header->tail_entry_offset); + else { + if (le64toh(o->object.type) != OBJECT_ENTRY) + return -EINVAL; + + np = le64toh(o->entry.prev_entry_offset); + } + + if (np == 0) + return 0; + + r = journal_file_move_to_object(f, np, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = np; + + return 1; +} + +int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { + uint64_t p, osize, hash, h; + int r; + + assert(f); + assert(data || size == 0); + + osize = offsetof(Object, data.payload) + size; + + hash = hash64(data, size); + h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); + p = le64toh(f->hash_table[h].head_hash_offset); + + while (p != 0) { + Object *o; + + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + if (le64toh(o->object.size) == osize && + memcmp(o->data.payload, data, size) == 0) { + + if (le64toh(o->data.hash) != hash) + return -EBADMSG; + + if (o->data.head_entry_offset == 0) + return 0; + + p = le64toh(o->data.head_entry_offset); + r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + } + + p = le64toh(o->data.next_hash_offset); + } + + return 0; +} + +int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { + uint64_t p, osize, hash, h; + int r; + + assert(f); + assert(data || size == 0); + + osize = offsetof(Object, data.payload) + size; + + hash = hash64(data, size); + h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); + p = le64toh(f->hash_table[h].tail_hash_offset); + + while (p != 0) { + Object *o; + + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + if (le64toh(o->object.size) == osize && + memcmp(o->data.payload, data, size) == 0) { + + if (le64toh(o->data.hash) != hash) + return -EBADMSG; + + if (o->data.tail_entry_offset == 0) + return 0; + + p = le64toh(o->data.tail_entry_offset); + r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + } + + p = le64toh(o->data.prev_hash_offset); + } + + return 0; +} + +void journal_file_dump(JournalFile *f) { + char a[33], b[33], c[33]; + Object *o; + int r; + uint64_t p; + + assert(f); + + printf("File ID: %s\n" + "Machine ID: %s\n" + "Boot ID: %s\n" + "Arena size: %llu\n", + sd_id128_to_string(f->header->file_id, a), + sd_id128_to_string(f->header->machine_id, b), + sd_id128_to_string(f->header->boot_id, c), + (unsigned long long) le64toh(f->header->arena_size)); + + p = le64toh(f->header->head_object_offset); + while (p != 0) { + r = journal_file_move_to_object(f, p, -1, &o); + if (r < 0) + goto fail; + + switch (o->object.type) { + + case OBJECT_UNUSED: + printf("Type: OBJECT_UNUSED\n"); + break; + + case OBJECT_DATA: + printf("Type: OBJECT_DATA\n"); + break; + + case OBJECT_ENTRY: + printf("Type: OBJECT_ENTRY %llu\n", (unsigned long long) le64toh(o->entry.seqnum)); + break; + + case OBJECT_HASH_TABLE: + printf("Type: OBJECT_HASH_TABLE\n"); + break; + + case OBJECT_BISECT_TABLE: + printf("Type: OBJECT_BISECT_TABLE\n"); + break; + } + + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } + + return; +fail: + log_error("File corrupt"); +} + +int journal_file_open( + const char *fname, + int flags, + mode_t mode, + JournalFile **ret) { + + JournalFile *f; + int r; + bool newly_created = false; + + assert(fname); + + if ((flags & O_ACCMODE) != O_RDONLY && + (flags & O_ACCMODE) != O_RDWR) + return -EINVAL; + + f = new0(JournalFile, 1); + if (!f) + return -ENOMEM; + + f->writable = (flags & O_ACCMODE) != O_RDONLY; + f->prot = prot_from_flags(flags); + + f->fd = open(fname, flags|O_CLOEXEC, mode); + if (f->fd < 0) { + r = -errno; + goto fail; + } + + f->path = strdup(fname); + if (!f->path) { + r = -ENOMEM; + goto fail; + } + + if (fstat(f->fd, &f->last_stat) < 0) { + r = -errno; + goto fail; + } + + if (f->last_stat.st_size == 0 && f->writable) { + newly_created = true; + + r = journal_file_init_header(f); + if (r < 0) + goto fail; + + if (fstat(f->fd, &f->last_stat) < 0) { + r = -errno; + goto fail; + } + } + + if (f->last_stat.st_size < (off_t) sizeof(Header)) { + r = -EIO; + goto fail; + } + + f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0); + if (f->header == MAP_FAILED) { + f->header = NULL; + r = -errno; + goto fail; + } + + if (!newly_created) { + r = journal_file_verify_header(f); + if (r < 0) + goto fail; + } + + if (f->writable) { + r = journal_file_refresh_header(f); + if (r < 0) + goto fail; + } + + if (newly_created) { + + r = journal_file_setup_hash_table(f); + if (r < 0) + goto fail; + + r = journal_file_setup_bisect_table(f); + if (r < 0) + goto fail; + } + + r = journal_file_map_hash_table(f); + if (r < 0) + goto fail; + + r = journal_file_map_bisect_table(f); + if (r < 0) + goto fail; + + if (ret) + *ret = f; + + return 0; + +fail: + journal_file_close(f); + + return r; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h new file mode 100644 index 0000000000..55cc7153af --- /dev/null +++ b/src/journal/journal-file.h @@ -0,0 +1,86 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foojournalfilehfoo +#define foojournalfilehfoo + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include + +#include "journal-def.h" +#include "util.h" +#include "sd-id128.h" + +typedef struct JournalFile { + int fd; + char *path; + struct stat last_stat; + int prot; + bool writable; + + Header *header; + + HashItem *hash_table; + void *hash_table_window; + uint64_t hash_table_window_size; + + uint64_t *bisect_table; + void *bisect_table_window; + uint64_t bisect_table_window_size; + + void *window; + uint64_t window_offset; + uint64_t window_size; + + uint64_t current_offset; +} JournalFile; + +typedef struct JournalCursor { + uint8_t version; + uint8_t reserved[7]; + uint64_t seqnum; + sd_id128_t seqnum_id; + sd_id128_t boot_id; + uint64_t monotonic; + uint64_t realtime; + uint64_t xor_hash; +} JournalCursor; + +int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile **ret); + +void journal_file_close(JournalFile *j); + +int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Object **ret); + +uint64_t journal_file_entry_n_items(Object *o); + +int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset); + +int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset); + +int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); + +int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset); +int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset); + +void journal_file_dump(JournalFile *f); + +#endif diff --git a/src/journal/journal-private.h b/src/journal/journal-private.h deleted file mode 100644 index 3277d29542..0000000000 --- a/src/journal/journal-private.h +++ /dev/null @@ -1,86 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foojournalprivatehfoo -#define foojournalprivatehfoo - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include - -#include "sd-journal.h" -#include "journal-def.h" -#include "util.h" -#include "sd-id128.h" - -typedef struct JournalFile { - int fd; - char *path; - struct stat last_stat; - int prot; - bool writable; - - Header *header; - - HashItem *hash_table; - void *hash_table_window; - uint64_t hash_table_window_size; - - uint64_t *bisect_table; - void *bisect_table_window; - uint64_t bisect_table_window_size; - - void *window; - uint64_t window_offset; - uint64_t window_size; - - Object *current; - uint64_t current_offset; -} JournalFile; - -typedef struct JournalCoursor { - sd_id128_t file_id; - sd_id128_t boot_id; - uint64_t seqnum; - uint64_t monotonic; - uint64_t realtime; - uint64_t xor_hash; -} JournalCoursor; - -int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile **ret); - -void journal_file_close(JournalFile *j); - -int journal_file_move_to_object(JournalFile *f, uint64_t offset, Object **ret); - -uint64_t journal_file_entry_n_items(Object *o); - -int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset); - -int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset); - -int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); -int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); - -int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset); -int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset); - -void journal_file_dump(JournalFile *f); - -#endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7bcd842f6d..5f17f45cac 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -23,7 +23,7 @@ #include #include -#include "journal-private.h" +#include "journal-file.h" int main(int argc, char *argv[]) { int r; @@ -62,21 +62,16 @@ int main(int argc, char *argv[]) { uint64_t p, l; p = le64toh(o->entry.items[i].object_offset); - r = journal_file_move_to_object(f, p, &o); + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); if (r < 0) { log_error("Failed to move to data: %s", strerror(-r)); goto finish; } - if (le64toh(o->object.type) != OBJECT_DATA) { - log_error("Invalid file"); - goto finish; - } - l = o->object.size - offsetof(Object, data.payload); printf("\t[%.*s]\n", (int) l, o->data.payload); - r = journal_file_move_to_object(f, offset, &o); + r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); if (r < 0) { log_error("Failed to move back to entry: %s", strerror(-r)); goto finish; diff --git a/src/journal/journald.c b/src/journal/journald.c index e9ac3a832e..d65451df58 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -29,7 +29,7 @@ #include #include "hashmap.h" -#include "journal-private.h" +#include "journal-file.h" #include "sd-daemon.h" #include "socket-util.h" #include "acl-util.h" @@ -282,7 +282,9 @@ static int process_event(Server *s, struct epoll_event *ev) { log_debug("Received SIG%s", signal_to_string(sfsi.ssi_signo)); return 0; - } else { + } + + if (ev->data.fd == s->syslog_fd) { for (;;) { char buf[LINE_MAX+1]; struct msghdr msghdr; @@ -339,9 +341,12 @@ static int process_event(Server *s, struct epoll_event *ev) { process_message(s, strstrip(buf), ucred, tv); } + + return 1; } - return 1; + log_error("Unknown event."); + return 0; } static int server_init(Server *s) { diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 89bf545837..8426b3bf9e 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -19,1206 +19,223 @@ along with systemd; If not, see . ***/ -#include #include -#include -#include -#include #include -#include #include "sd-journal.h" #include "journal-def.h" -#include "journal-private.h" -#include "lookup3.h" -#include "list.h" +#include "journal-file.h" #include "hashmap.h" +#include "list.h" -#define DEFAULT_ARENA_MAX_SIZE (16ULL*1024ULL*1024ULL*1024ULL) -#define DEFAULT_ARENA_MIN_SIZE (256ULL*1024ULL) -#define DEFAULT_ARENA_KEEP_FREE (1ULL*1024ULL*1024ULL) +typedef struct Match Match; -#define DEFAULT_HASH_TABLE_SIZE (2047ULL*16ULL) -#define DEFAULT_BISECT_TABLE_SIZE ((DEFAULT_ARENA_MAX_SIZE/(64ULL*1024ULL))*8ULL) +struct Match { + char *data; + size_t size; + uint64_t hash; -#define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL) + LIST_FIELDS(Match, matches); +}; struct sd_journal { Hashmap *files; -}; - -static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; - -#define ALIGN64(x) (((x) + 7ULL) & ~7ULL) - -void journal_file_close(JournalFile *f) { - assert(f); - - if (f->fd >= 0) - close_nointr_nofail(f->fd); - - if (f->header) - munmap(f->header, PAGE_ALIGN(sizeof(Header))); - - if (f->hash_table_window) - munmap(f->hash_table_window, f->hash_table_window_size); - - if (f->bisect_table_window) - munmap(f->bisect_table_window, f->bisect_table_window_size); - - if (f->window) - munmap(f->window, f->window_size); - - free(f->path); - free(f); -} - -static int journal_file_init_header(JournalFile *f) { - Header h; - ssize_t k; - int r; - - assert(f); - - zero(h); - memcpy(h.signature, signature, 8); - h.arena_offset = htole64(ALIGN64(sizeof(h))); - h.arena_max_size = htole64(DEFAULT_ARENA_MAX_SIZE); - h.arena_min_size = htole64(DEFAULT_ARENA_MIN_SIZE); - h.arena_keep_free = htole64(DEFAULT_ARENA_KEEP_FREE); - - r = sd_id128_randomize(&h.file_id); - if (r < 0) - return r; - - k = pwrite(f->fd, &h, sizeof(h), 0); - if (k < 0) - return -errno; - - if (k != sizeof(h)) - return -EIO; - - return 0; -} - -static int journal_file_refresh_header(JournalFile *f) { - int r; - - assert(f); - - r = sd_id128_get_machine(&f->header->machine_id); - if (r < 0) - return r; - - r = sd_id128_get_boot(&f->header->boot_id); - if (r < 0) - return r; - - f->header->state = htole32(STATE_ONLINE); - return 0; -} - -static int journal_file_verify_header(JournalFile *f) { - assert(f); - - if (memcmp(f->header, signature, 8)) - return -EBADMSG; - - if (f->header->incompatible_flags != 0) - return -EPROTONOSUPPORT; - - if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->arena_offset) + le64toh(f->header->arena_size))) - return -ENODATA; - - if (f->writable) { - uint32_t state; - sd_id128_t machine_id; - int r; - - r = sd_id128_get_machine(&machine_id); - if (r < 0) - return r; - - if (!sd_id128_equal(machine_id, f->header->machine_id)) - return -EHOSTDOWN; - - state = le32toh(f->header->state); - - if (state == STATE_ONLINE) - log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); - else if (state == STATE_ARCHIVED) - return -ESHUTDOWN; - else if (state != STATE_OFFLINE) - log_debug("Journal file %s has unknown state %u. Ignoring.", f->path, state); - } - - return 0; -} - -static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { - uint64_t asize; - uint64_t old_size, new_size; - - assert(f); - - if (offset < le64toh(f->header->arena_offset)) - return -EINVAL; - - new_size = PAGE_ALIGN(offset + size); - - /* We assume that this file is not sparse, and we know that - * for sure, since we alway call posix_fallocate() - * ourselves */ - - old_size = - le64toh(f->header->arena_offset) + - le64toh(f->header->arena_size); - - if (old_size >= new_size) - return 0; - - asize = new_size - le64toh(f->header->arena_offset); - if (asize > le64toh(f->header->arena_min_size)) { - struct statvfs svfs; - - if (fstatvfs(f->fd, &svfs) >= 0) { - uint64_t available; - - available = svfs.f_bfree * svfs.f_bsize; - - if (available >= f->header->arena_keep_free) - available -= f->header->arena_keep_free; - else - available = 0; - - if (new_size - old_size > available) - return -E2BIG; - } - } - - if (asize > le64toh(f->header->arena_max_size)) - return -E2BIG; - - if (posix_fallocate(f->fd, 0, new_size) < 0) - return -errno; - - if (fstat(f->fd, &f->last_stat) < 0) - return -errno; - - f->header->arena_size = htole64(asize); - - return 0; -} - -static int journal_file_map( - JournalFile *f, - uint64_t offset, - uint64_t size, - void **_window, - uint64_t *_woffset, - uint64_t *_wsize, - void **ret) { - - uint64_t woffset, wsize; - void *window; - - assert(f); - assert(size > 0); - assert(ret); - - woffset = offset & ~((uint64_t) page_size() - 1ULL); - wsize = size + (offset - woffset); - wsize = PAGE_ALIGN(wsize); - - window = mmap(NULL, wsize, f->prot, MAP_SHARED, f->fd, woffset); - if (window == MAP_FAILED) - return -errno; - - if (_window) - *_window = window; - - if (_woffset) - *_woffset = woffset; - - if (_wsize) - *_wsize = wsize; - - *ret = (uint8_t*) window + (offset - woffset); - - return 0; -} - -static int journal_file_move_to(JournalFile *f, uint64_t offset, uint64_t size, void **ret) { - void *p; - uint64_t delta; - int r; - - assert(f); - assert(ret); - - if (_likely_(f->window && - f->window_offset <= offset && - f->window_offset+f->window_size >= offset + size)) { - - *ret = (uint8_t*) f->window + (offset - f->window_offset); - return 0; - } - - if (f->window) { - if (munmap(f->window, f->window_size) < 0) - return -errno; - - f->window = NULL; - f->window_size = f->window_offset = 0; - } - - if (size < DEFAULT_WINDOW_SIZE) { - /* If the default window size is larger then what was - * asked for extend the mapping a bit in the hope to - * minimize needed remappings later on. We add half - * the window space before and half behind the - * requested mapping */ - - delta = PAGE_ALIGN((DEFAULT_WINDOW_SIZE - size) / 2); - - if (offset < delta) - delta = offset; - - offset -= delta; - size += (DEFAULT_WINDOW_SIZE - delta); - } else - delta = 0; - - r = journal_file_map(f, - offset, size, - &f->window, &f->window_offset, &f->window_size, - & p); - - if (r < 0) - return r; - - *ret = (uint8_t*) p + delta; - return 0; -} - -static bool verify_hash(Object *o) { - uint64_t t; - - assert(o); - - t = le64toh(o->object.type); - if (t == OBJECT_DATA) { - uint64_t s, h1, h2; - - s = le64toh(o->object.size); - - h1 = le64toh(o->data.hash); - h2 = hash64(o->data.payload, s - offsetof(Object, data.payload)); - - return h1 == h2; - } - - return true; -} - -int journal_file_move_to_object(JournalFile *f, uint64_t offset, Object **ret) { - int r; - void *t; - Object *o; - uint64_t s; - - assert(f); - assert(ret); + JournalFile *current_file; - r = journal_file_move_to(f, offset, sizeof(ObjectHeader), &t); - if (r < 0) - return r; + LIST_HEAD(Match, matches); +}; - o = (Object*) t; - s = le64toh(o->object.size); +int sd_journal_add_match(sd_journal *j, const char *field, const void *data, size_t size) { + Match *m; + char *e; - if (s < sizeof(ObjectHeader)) - return -EBADMSG; + assert(j); + assert(field); + assert(data || size == 0); - if (s > sizeof(ObjectHeader)) { - r = journal_file_move_to(f, offset, s, &t); - if (r < 0) - return r; + m = new0(Match, 1); + if (!m) + return -ENOMEM; - o = (Object*) t; + m->size = strlen(field) + 1 + size; + m->data = malloc(m->size); + if (!m->data) { + free(m); + return -ENOMEM; } - if (!verify_hash(o)) - return -EBADMSG; + e = stpcpy(m->data, field); + *(e++) = '='; + memcpy(e, data, size); - *ret = o; + LIST_PREPEND(Match, matches, j->matches, m); return 0; } -static uint64_t journal_file_seqnum(JournalFile *f) { - uint64_t r; - - assert(f); - - r = le64toh(f->header->seqnum) + 1; - f->header->seqnum = htole64(r); - - return r; -} - -static int journal_file_append_object(JournalFile *f, uint64_t size, Object **ret, uint64_t *offset) { - int r; - uint64_t p; - Object *tail, *o; - void *t; - - assert(f); - assert(size >= sizeof(ObjectHeader)); - assert(offset); - assert(ret); - - p = le64toh(f->header->tail_object_offset); +void sd_journal_flush_matches(sd_journal *j) { + assert(j); - if (p == 0) - p = le64toh(f->header->arena_offset); - else { - r = journal_file_move_to_object(f, p, &tail); - if (r < 0) - return r; + while (j->matches) { + Match *m = j->matches; - p += ALIGN64(le64toh(tail->object.size)); + LIST_REMOVE(Match, matches, j->matches, m); + free(m->data); + free(m); } - - r = journal_file_allocate(f, p, size); - if (r < 0) - return r; - - r = journal_file_move_to(f, p, size, &t); - if (r < 0) - return r; - - o = (Object*) t; - - zero(o->object); - o->object.type = htole64(OBJECT_UNUSED); - zero(o->object.reserved); - o->object.size = htole64(size); - - f->header->tail_object_offset = htole64(p); - if (f->header->head_object_offset == 0) - f->header->head_object_offset = htole64(p); - - f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); - - *ret = o; - *offset = p; - - return 0; -} - -static int journal_file_setup_hash_table(JournalFile *f) { - uint64_t s, p; - Object *o; - int r; - - assert(f); - - s = DEFAULT_HASH_TABLE_SIZE; - r = journal_file_append_object(f, offsetof(Object, hash_table.table) + s, &o, &p); - if (r < 0) - return r; - - o->object.type = htole64(OBJECT_HASH_TABLE); - memset(o->hash_table.table, 0, s); - - f->header->hash_table_offset = htole64(p + offsetof(Object, hash_table.table)); - f->header->hash_table_size = htole64(s); - - return 0; -} - -static int journal_file_setup_bisect_table(JournalFile *f) { - uint64_t s, p; - Object *o; - int r; - - assert(f); - - s = DEFAULT_BISECT_TABLE_SIZE; - r = journal_file_append_object(f, offsetof(Object, bisect_table.table) + s, &o, &p); - if (r < 0) - return r; - - o->object.type = htole64(OBJECT_BISECT_TABLE); - memset(o->bisect_table.table, 0, s); - - f->header->bisect_table_offset = htole64(p + offsetof(Object, bisect_table.table)); - f->header->bisect_table_size = htole64(s); - - return 0; -} - -static int journal_file_map_hash_table(JournalFile *f) { - uint64_t s, p; - void *t; - int r; - - assert(f); - - p = le64toh(f->header->hash_table_offset); - s = le64toh(f->header->hash_table_size); - - r = journal_file_map(f, - p, s, - &f->hash_table_window, NULL, &f->hash_table_window_size, - &t); - if (r < 0) - return r; - - f->hash_table = t; - return 0; } -static int journal_file_map_bisect_table(JournalFile *f) { - uint64_t s, p; - void *t; - int r; - - assert(f); - - p = le64toh(f->header->bisect_table_offset); - s = le64toh(f->header->bisect_table_size); +static int compare_order(JournalFile *af, Object *ao, uint64_t ap, + JournalFile *bf, Object *bo, uint64_t bp) { - r = journal_file_map(f, - p, s, - &f->bisect_table_window, NULL, &f->bisect_table_window_size, - &t); - - if (r < 0) - return r; + uint64_t a, b; - f->bisect_table = t; - return 0; -} + if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) { -static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, uint64_t hash_index) { - uint64_t p; - int r; + /* If this is from the same seqnum source, compare + * seqnums */ + a = le64toh(ao->entry.seqnum); + b = le64toh(bo->entry.seqnum); - assert(f); - assert(o); - assert(offset > 0); - assert(o->object.type == htole64(OBJECT_DATA)); - o->data.head_entry_offset = o->data.tail_entry_offset = 0; - o->data.next_hash_offset = 0; + } else if (sd_id128_equal(ao->entry.boot_id, bo->entry.boot_id)) { - p = le64toh(f->hash_table[hash_index].tail_hash_offset); - if (p == 0) { - /* Only entry in the hash table is easy */ + /* If the boot id matches compare monotonic time */ + a = le64toh(ao->entry.monotonic); + b = le64toh(bo->entry.monotonic); - o->data.prev_hash_offset = 0; - f->hash_table[hash_index].head_hash_offset = htole64(offset); } else { - o->data.prev_hash_offset = htole64(p); - /* Temporarily move back to the previous data object, - * to patch in pointer */ - - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - o->data.next_hash_offset = offset; - - r = journal_file_move_to_object(f, offset, &o); - if (r < 0) - return r; + /* Otherwise compare UTC time */ + a = le64toh(ao->entry.realtime); + b = le64toh(ao->entry.realtime); } - f->hash_table[hash_index].tail_hash_offset = htole64(offset); - - return 0; + return + a < b ? -1 : + a > b ? +1 : 0; } -static int journal_file_append_data(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { - uint64_t hash, h, p, np; - uint64_t osize; - Object *o; +int sd_journal_next(sd_journal *j) { + JournalFile *f, *new_current = NULL; + Iterator i; int r; + uint64_t new_offset = 0; + Object *new_entry = NULL; - assert(f); - assert(data || size == 0); - - osize = offsetof(Object, data.payload) + size; + assert(j); - hash = hash64(data, size); - h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); - p = le64toh(f->hash_table[h].head_hash_offset); + HASHMAP_FOREACH(f, j->files, i) { + Object *o; + uint64_t p; - while (p != 0) { - /* Look for this data object in the hash table */ + if (f->current_offset > 0) { + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + } else + o = NULL; - r = journal_file_move_to_object(f, p, &o); + r = journal_file_next_entry(f, o, &o, &p); if (r < 0) return r; + else if (r == 0) + continue; - if (le64toh(o->object.type) != OBJECT_DATA) - return -EBADMSG; - - if (le64toh(o->object.size) == osize && - memcmp(o->data.payload, data, size) == 0) { - - if (le64toh(o->data.hash) != hash) - return -EBADMSG; - - if (ret) - *ret = o; - - if (offset) - *offset = p; - - return 0; + if (!new_current || compare_order(new_current, new_entry, new_offset, f, o, p) > 0) { + new_current = f; + new_entry = o; + new_offset = p; } - - p = le64toh(o->data.next_hash_offset); } - r = journal_file_append_object(f, osize, &o, &np); - if (r < 0) - return r; - - o->object.type = htole64(OBJECT_DATA); - o->data.hash = htole64(hash); - memcpy(o->data.payload, data, size); - - r = journal_file_link_data(f, o, np, h); - if (r < 0) - return r; - - if (ret) - *ret = o; - - if (offset) - *offset = np; - - return 0; -} - -uint64_t journal_file_entry_n_items(Object *o) { - assert(o); - assert(o->object.type == htole64(OBJECT_ENTRY)); - - return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); -} - -static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { - uint64_t p, q; - int r; - assert(f); - assert(o); - assert(offset > 0); - - p = le64toh(o->entry.items[i].object_offset); - if (p == 0) - return -EINVAL; - - o->entry.items[i].next_entry_offset = 0; - - /* Move to the data object */ - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (o->object.type != htole64(OBJECT_DATA)) - return -EBADMSG; - - q = le64toh(o->data.tail_entry_offset); - o->data.tail_entry_offset = htole64(offset); - - if (q == 0) - o->data.head_entry_offset = htole64(offset); - else { - uint64_t n, j; - - /* Move to previous entry */ - r = journal_file_move_to_object(f, q, &o); - if (r < 0) - return r; - - if (o->object.type != htole64(OBJECT_ENTRY)) - return -EBADMSG; - - n = journal_file_entry_n_items(o); - for (j = 0; j < n; j++) - if (le64toh(o->entry.items[j].object_offset) == p) - break; - - if (j >= n) - return -EBADMSG; - - o->entry.items[j].next_entry_offset = offset; - } - - /* Move back to original entry */ - r = journal_file_move_to_object(f, offset, &o); - if (r < 0) - return r; - - o->entry.items[i].prev_entry_offset = q; - return 0; -} - -static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { - uint64_t p, i, n, k, a, b; - int r; - - assert(f); - assert(o); - assert(offset > 0); - assert(o->object.type == htole64(OBJECT_ENTRY)); - - /* Link up the entry itself */ - p = le64toh(f->header->tail_entry_offset); - - o->entry.prev_entry_offset = f->header->tail_entry_offset; - o->entry.next_entry_offset = 0; - - if (p == 0) - f->header->head_entry_offset = htole64(offset); - else { - /* Temporarily move back to the previous entry, to - * patch in pointer */ - - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - o->entry.next_entry_offset = htole64(offset); - - r = journal_file_move_to_object(f, offset, &o); - if (r < 0) - return r; - } - - f->header->tail_entry_offset = htole64(offset); - - /* Link up the items */ - n = journal_file_entry_n_items(o); - for (i = 0; i < n; i++) { - r = journal_file_link_entry_item(f, o, offset, i); - if (r < 0) - return r; + if (new_current) { + j->current_file = new_current; + f->current_offset = new_offset; + return 1; } - /* Link up the entry in the bisect table */ - n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); - k = le64toh(f->header->arena_max_size) / n; - - a = (le64toh(f->header->last_bisect_offset) + k - 1) / k; - b = offset / k; - - for (; a <= b; a++) - f->bisect_table[a] = htole64(offset); - - f->header->last_bisect_offset = htole64(offset + le64toh(o->object.size)); - return 0; } -static int journal_file_append_entry_internal( - JournalFile *f, - const dual_timestamp *ts, - uint64_t xor_hash, - const EntryItem items[], unsigned n_items, - Object **ret, uint64_t *offset) { - uint64_t np; - uint64_t osize; - Object *o; +int sd_journal_previous(sd_journal *j) { + JournalFile *f, *new_current = NULL; + Iterator i; int r; + uint64_t new_offset = 0; + Object *new_entry = NULL; - assert(f); - assert(items || n_items == 0); - - osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem)); - - r = journal_file_append_object(f, osize, &o, &np); - if (r < 0) - return r; - - o->object.type = htole64(OBJECT_ENTRY); - o->entry.seqnum = htole64(journal_file_seqnum(f)); - memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); - o->entry.realtime = ts ? htole64(ts->realtime) : 0; - o->entry.monotonic = ts ? htole64(ts->monotonic) : 0; - o->entry.xor_hash = htole64(xor_hash); - - r = journal_file_link_entry(f, o, np); - if (r < 0) - return r; - - if (ret) - *ret = o; - - if (offset) - *offset = np; - - return 0; -} - -int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset) { - unsigned i; - EntryItem *items; - int r; - uint64_t xor_hash = 0; - - assert(f); - assert(iovec || n_iovec == 0); - - items = new(EntryItem, n_iovec); - if (!items) - return -ENOMEM; + assert(j); - for (i = 0; i < n_iovec; i++) { - uint64_t p; + HASHMAP_FOREACH(f, j->files, i) { Object *o; + uint64_t p; - r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p); - if (r < 0) - goto finish; - - xor_hash ^= le64toh(o->data.hash); - items[i].object_offset = htole64(p); - } - - r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, ret, offset); - -finish: - free(items); - - return r; -} - -int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset) { - Object *o; - uint64_t lower, upper, p, n, k; - int r; - - assert(f); - - n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); - k = le64toh(f->header->arena_max_size) / n; - - lower = 0; - upper = le64toh(f->header->last_bisect_offset)/k+1; - - while (lower < upper) { - k = (upper + lower) / 2; - p = le64toh(f->bisect_table[k]); - - if (p == 0) { - upper = k; - continue; - } + if (f->current_offset > 0) { + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + } else + o = NULL; - r = journal_file_move_to_object(f, p, &o); + r = journal_file_prev_entry(f, o, &o, &p); if (r < 0) return r; + else if (r == 0) + continue; - if (o->object.type != htole64(OBJECT_ENTRY)) - return -EBADMSG; - - if (o->entry.seqnum == seqnum) { - if (ret) - *ret = o; - - if (offset) - *offset = p; - - return 1; - } else if (seqnum < o->entry.seqnum) - upper = k; - else if (seqnum > o->entry.seqnum) - lower = k+1; + if (!new_current || compare_order(new_current, new_entry, new_offset, f, o, p) > 0) { + new_current = f; + new_entry = o; + new_offset = p; + } } - assert(lower == upper); - - if (lower <= 0) - return 0; - - /* The object we are looking for is between - * bisect_table[lower-1] and bisect_table[lower] */ - - p = le64toh(f->bisect_table[lower-1]); - - for (;;) { - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (o->entry.seqnum == seqnum) { - if (ret) - *ret = o; - - if (offset) - *offset = p; - - return 1; - - } if (seqnum < o->entry.seqnum) - return 0; - - if (o->entry.next_entry_offset == 0) - return 0; - - p = le64toh(o->entry.next_entry_offset); + if (new_current) { + j->current_file = new_current; + f->current_offset = new_offset; + return 1; } return 0; } -int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) { - uint64_t np; - int r; - - assert(f); - - if (!o) - np = le64toh(f->header->head_entry_offset); - else { - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EINVAL; - - np = le64toh(o->entry.next_entry_offset); - } - - if (np == 0) - return 0; - - r = journal_file_move_to_object(f, np, &o); - if (r < 0) - return r; - - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EBADMSG; - - if (ret) - *ret = o; - - if (offset) - *offset = np; - - return 1; -} - -int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) { - uint64_t np; +int sd_journal_get_cursor(sd_journal *j, void **cursor, size_t *size) { + JournalCursor *c; + Object *o; int r; - assert(f); - - if (!o) - np = le64toh(f->header->tail_entry_offset); - else { - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EINVAL; - - np = le64toh(o->entry.prev_entry_offset); - } + assert(j); + assert(cursor); + assert(size); - if (np == 0) + if (!j->current_file || !j->current_file->current_offset <= 0) return 0; - r = journal_file_move_to_object(f, np, &o); + r = journal_file_move_to_object(j->current_file, j->current_file->current_offset, OBJECT_ENTRY, &o); if (r < 0) return r; - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EBADMSG; + c = new0(JournalCursor, 1); + if (!c) + return -ENOMEM; - if (ret) - *ret = o; + c->version = 1; + c->seqnum = o->entry.seqnum; + c->seqnum_id = j->current_file->header->seqnum_id; + c->boot_id = o->entry.boot_id; + c->monotonic = o->entry.monotonic; + c->realtime = o->entry.realtime; + c->xor_hash = o->entry.xor_hash; - if (offset) - *offset = np; + *cursor = c; + *size = sizeof(JournalCursor); return 1; } -int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { - uint64_t p, osize, hash, h; - int r; - - assert(f); - assert(data || size == 0); - - osize = offsetof(Object, data.payload) + size; - - hash = hash64(data, size); - h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); - p = le64toh(f->hash_table[h].head_hash_offset); - - while (p != 0) { - Object *o; - - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (le64toh(o->object.type) != OBJECT_DATA) - return -EBADMSG; - - if (le64toh(o->object.size) == osize && - memcmp(o->data.payload, data, size) == 0) { - - if (le64toh(o->data.hash) != hash) - return -EBADMSG; - - if (o->data.head_entry_offset == 0) - return 0; - - p = le64toh(o->data.head_entry_offset); - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EBADMSG; - - if (ret) - *ret = o; - - if (offset) - *offset = p; - - return 1; - } - - p = le64toh(o->data.next_hash_offset); - } - - return 0; -} - -int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { - uint64_t p, osize, hash, h; - int r; - - assert(f); - assert(data || size == 0); - - osize = offsetof(Object, data.payload) + size; - - hash = hash64(data, size); - h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); - p = le64toh(f->hash_table[h].tail_hash_offset); - - while (p != 0) { - Object *o; - - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (le64toh(o->object.type) != OBJECT_DATA) - return -EBADMSG; - - if (le64toh(o->object.size) == osize && - memcmp(o->data.payload, data, size) == 0) { - - if (le64toh(o->data.hash) != hash) - return -EBADMSG; - - if (o->data.tail_entry_offset == 0) - return 0; - - p = le64toh(o->data.tail_entry_offset); - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - return r; - - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EBADMSG; - - if (ret) - *ret = o; - - if (offset) - *offset = p; - - return 1; - } - - p = le64toh(o->data.prev_hash_offset); - } - - return 0; -} - -void journal_file_dump(JournalFile *f) { - char a[33], b[33], c[33]; - Object *o; - int r; - uint64_t p; - - assert(f); - - printf("File ID: %s\n" - "Machine ID: %s\n" - "Boot ID: %s\n" - "Arena size: %llu\n", - sd_id128_to_string(f->header->file_id, a), - sd_id128_to_string(f->header->machine_id, b), - sd_id128_to_string(f->header->boot_id, c), - (unsigned long long) le64toh(f->header->arena_size)); - - p = le64toh(f->header->head_object_offset); - while (p != 0) { - r = journal_file_move_to_object(f, p, &o); - if (r < 0) - goto fail; - - switch (o->object.type) { - - case OBJECT_UNUSED: - printf("Type: OBJECT_UNUSED\n"); - break; - - case OBJECT_DATA: - printf("Type: OBJECT_DATA\n"); - break; - - case OBJECT_ENTRY: - printf("Type: OBJECT_ENTRY %llu\n", (unsigned long long) le64toh(o->entry.seqnum)); - break; - - case OBJECT_HASH_TABLE: - printf("Type: OBJECT_HASH_TABLE\n"); - break; - - case OBJECT_BISECT_TABLE: - printf("Type: OBJECT_BISECT_TABLE\n"); - break; - } - - if (p == le64toh(f->header->tail_object_offset)) - p = 0; - else - p = p + ALIGN64(le64toh(o->object.size)); - } - - return; -fail: - log_error("File corrupt"); -} - -int journal_file_open( - const char *fname, - int flags, - mode_t mode, - JournalFile **ret) { - - JournalFile *f; - int r; - bool newly_created = false; - - assert(fname); - - if ((flags & O_ACCMODE) != O_RDONLY && - (flags & O_ACCMODE) != O_RDWR) - return -EINVAL; - - f = new0(JournalFile, 1); - if (!f) - return -ENOMEM; - - f->writable = (flags & O_ACCMODE) != O_RDONLY; - f->prot = prot_from_flags(flags); - - f->fd = open(fname, flags|O_CLOEXEC, mode); - if (f->fd < 0) { - r = -errno; - goto fail; - } - - f->path = strdup(fname); - if (!f->path) { - r = -ENOMEM; - goto fail; - } - - if (fstat(f->fd, &f->last_stat) < 0) { - r = -errno; - goto fail; - } - - if (f->last_stat.st_size == 0 && f->writable) { - newly_created = true; - - r = journal_file_init_header(f); - if (r < 0) - goto fail; - - if (fstat(f->fd, &f->last_stat) < 0) { - r = -errno; - goto fail; - } - } - - if (f->last_stat.st_size < (off_t) sizeof(Header)) { - r = -EIO; - goto fail; - } - - f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0); - if (f->header == MAP_FAILED) { - f->header = NULL; - r = -errno; - goto fail; - } - - if (!newly_created) { - r = journal_file_verify_header(f); - if (r < 0) - goto fail; - } - - if (f->writable) { - r = journal_file_refresh_header(f); - if (r < 0) - goto fail; - } - - if (newly_created) { - - r = journal_file_setup_hash_table(f); - if (r < 0) - goto fail; - - r = journal_file_setup_bisect_table(f); - if (r < 0) - goto fail; - } - - r = journal_file_map_hash_table(f); - if (r < 0) - goto fail; - - r = journal_file_map_bisect_table(f); - if (r < 0) - goto fail; - - if (ret) - *ret = f; - - return 0; - -fail: - journal_file_close(f); - - return r; +int sd_journal_set_cursor(sd_journal *j, const void *cursor, size_t size) { + return -EINVAL; } int sd_journal_open(sd_journal **ret) { diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 8170dea87c..55e58601fe 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -25,13 +25,12 @@ #include #include -#include "sd-id128.h" - /* TODO: * * - implement rotation * - check LE/BE conversion for 8bit, 16bit, 32bit values * - implement parallel traversal + * - implement inotify usage on client * - implement audit gateway * - implement native gateway * - extend hash table/bisect table as we go @@ -45,12 +44,13 @@ void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); int sd_journal_next(sd_journal *j); -void* sd_journal_get(sd_journal *j, const char *field, size_t *size); -uint64_t sd_journal_get_seqnum(sd_journal *j); -uint64_t sd_journal_get_realtime_usec(sd_journal *j); -uint64_t sd_journal_get_monotonic_usec(sd_journal *j); +int sd_journal_get(sd_journal *j, const char *field, const void **data, size_t *size); +int sd_journal_get_seqnum(sd_journal *j, uint64_t *ret); +int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret); -int sd_journal_add_match(sd_journal *j, const char *item, size_t *size); +int sd_journal_add_match(sd_journal *j, const char *field, const void *data, size_t size); +void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_tail(sd_journal *j); @@ -59,16 +59,9 @@ int sd_journal_seek_seqnum(sd_journal *j, uint64_t seqnum); int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); -uint64_t sd_journal_get_max_size(sd_journal *j); -uint64_t sd_journal_get_min_size(sd_journal *j); -uint64_t sd_journal_get_keep_free(sd_journal *j); - -int sd_journal_set_max_size(sd_journal *j, uint64_t size); -int sd_journal_set_min_size(sd_journal *j, uint64_t size); -int sd_journal_set_keep_free(sd_journal *j, uint64_t size); +int sd_journal_get_cursor(sd_journal *j, void **cursor, size_t *size); +int sd_journal_set_cursor(sd_journal *j, const void *cursor, size_t size); -sd_id128_t sd_journal_get_file_id(sd_journal *j); -sd_id128_t sd_journal_get_machine_id(sd_journal *j); -sd_id128_t sd_journal_get_boot_id(sd_journal *j); +int sd_journal_get_fd(sd_journal *j); #endif diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index e0aedc7b83..7028f11f7c 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -21,7 +21,7 @@ #include -#include "journal-private.h" +#include "journal-file.h" #include "log.h" int main(int argc, char *argv[]) { -- cgit v1.2.3-54-g00ecf From 250d54b5bee6a46fe1c1626211e3a7e238eda628 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2011 05:29:08 +0200 Subject: journalctl: find journal files in right path --- src/journal/journalctl.c | 47 ++++++++++++++++++++++++++++++++++++++++++---- src/journal/journald.c | 49 +++++++++++++++++++++++++----------------------- 2 files changed, 69 insertions(+), 27 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5f17f45cac..ac376eaf4f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -25,6 +25,48 @@ #include "journal-file.h" +static int system_journal_open(JournalFile **f) { + int r; + char *fn; + sd_id128_t machine; + char ids[33]; + + assert(f); + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + fn = join("/var/log/journal/", sd_id128_to_string(machine, ids), "/system.journal", NULL); + if (!fn) + return -ENOMEM; + + r = journal_file_open(fn, O_RDONLY, 0640, f); + free(fn); + + if (r >= 0) + return r; + + if (r < 0 && r != -ENOENT) { + log_error("Failed to open system journal: %s", strerror(-r)); + return r; + } + + fn = join("/run/log/journal/", ids, "/system.journal", NULL); + if (!fn) + return -ENOMEM; + + r = journal_file_open(fn, O_RDONLY, 0640, f); + free(fn); + + if (r < 0) { + log_error("Failed to open system journal: %s", strerror(-r)); + return r; + } + + return r; +} + int main(int argc, char *argv[]) { int r; JournalFile *f; @@ -33,10 +75,7 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - r = journal_file_open("/var/log/journal/system.journal", O_RDONLY, 0644, &f); - if (r == -ENOENT) - r = journal_file_open("/run/log/journal/system.journal", O_RDONLY, 0644, &f); - + r = system_journal_open(&f); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); return EXIT_FAILURE; diff --git a/src/journal/journald.c b/src/journal/journald.c index b8a9fc3adf..94261f6763 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -375,7 +375,7 @@ static int system_journal_open(Server *s) { return r; /* First try to create the machine path, but not the prefix */ - fn = join("/var/log/journal/", sd_id128_to_string(machine, ids), NULL); + fn = strappend("/var/log/journal/", sd_id128_to_string(machine, ids)); if (!fn) return -ENOMEM; (void) mkdir(fn, 0755); @@ -389,35 +389,38 @@ static int system_journal_open(Server *s) { r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, &s->system_journal); free(fn); - if (r >= 0) + if (r >= 0) { fix_perms(s->system_journal, 0); - else if (r == -ENOENT) { - - /* /var didn't work, so try /run, but this time we - * create the prefix too */ - fn = join("/run/log/journal/", ids, NULL); - if (!fn) - return -ENOMEM; - (void) mkdir_p(fn, 0755); - free(fn); - - /* Then create the runtime journal file */ - fn = join("/run/log/journal/", ids, "/system.journal", NULL); - if (!fn) - return -ENOMEM; - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, &s->runtime_journal); - free(fn); - - if (r >= 0) - fix_perms(s->runtime_journal, 0); + return r; } if (r < 0 && r != -ENOENT) { - log_error("Failed to open journal: %s", strerror(-r)); + log_error("Failed to open system journal: %s", strerror(-r)); return r; } - return 0; + /* /var didn't work, so try /run, but this time we + * create the prefix too */ + fn = strappend("/run/log/journal/", ids); + if (!fn) + return -ENOMEM; + (void) mkdir_p(fn, 0755); + free(fn); + + /* Then create the runtime journal file */ + fn = join("/run/log/journal/", ids, "/system.journal", NULL); + if (!fn) + return -ENOMEM; + r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, &s->runtime_journal); + free(fn); + + if (r < 0) { + log_error("Failed to open runtime journal: %s", strerror(-r)); + return r; + } + + fix_perms(s->runtime_journal, 0); + return r; } static int server_init(Server *s) { -- cgit v1.2.3-54-g00ecf From 0ac38b707212e9aa40e25d65ffbae648cc9116f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Oct 2011 05:19:35 +0200 Subject: journal: implementation rotation --- src/journal/journal-def.h | 2 + src/journal/journal-file.c | 247 ++++++++++++++++++++++++++++++++++++++++++--- src/journal/journal-file.h | 9 +- src/journal/journalctl.c | 4 +- src/journal/journald.c | 10 +- src/journal/sd-journal.c | 2 +- src/journal/test-journal.c | 10 +- 7 files changed, 260 insertions(+), 24 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index b3fa1e524f..d44b070fd0 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -136,6 +136,8 @@ _packed_ struct Header { uint64_t last_bisect_offset; uint64_t n_objects; uint64_t seqnum; + uint64_t head_entry_realtime; + uint64_t tail_entry_realtime; }; #endif diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 45cc0d1d8e..934c043aff 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -35,6 +35,8 @@ #define DEFAULT_ARENA_MIN_SIZE (256ULL*1024ULL) #define DEFAULT_ARENA_KEEP_FREE (1ULL*1024ULL*1024ULL) +#define DEFAULT_MAX_USE (16ULL*1024ULL*1024ULL*16ULL) + #define DEFAULT_HASH_TABLE_SIZE (2047ULL*16ULL) #define DEFAULT_BISECT_TABLE_SIZE ((DEFAULT_ARENA_MAX_SIZE/(64ULL*1024ULL))*8ULL) @@ -47,11 +49,12 @@ static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; void journal_file_close(JournalFile *f) { assert(f); - if (f->fd >= 0) - close_nointr_nofail(f->fd); + if (f->header) { + if (f->writable && f->header->state == htole32(STATE_ONLINE)) + f->header->state = htole32(STATE_OFFLINE); - if (f->header) munmap(f->header, PAGE_ALIGN(sizeof(Header))); + } if (f->hash_table_window) munmap(f->hash_table_window, f->hash_table_window_size); @@ -62,11 +65,14 @@ void journal_file_close(JournalFile *f) { if (f->window) munmap(f->window, f->window_size); + if (f->fd >= 0) + close_nointr_nofail(f->fd); + free(f->path); free(f); } -static int journal_file_init_header(JournalFile *f) { +static int journal_file_init_header(JournalFile *f, JournalFile *template) { Header h; ssize_t k; int r; @@ -84,7 +90,11 @@ static int journal_file_init_header(JournalFile *f) { if (r < 0) return r; - h.seqnum_id = h.file_id; + if (template) { + h.seqnum_id = template->header->seqnum_id; + h.seqnum = template->header->seqnum; + } else + h.seqnum_id = h.file_id; k = pwrite(f->fd, &h, sizeof(h), 0); if (k < 0) @@ -674,9 +684,10 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { o->entry.prev_entry_offset = f->header->tail_entry_offset; o->entry.next_entry_offset = 0; - if (p == 0) + if (p == 0) { f->header->head_entry_offset = htole64(offset); - else { + f->header->head_entry_realtime = o->entry.realtime; + } else { /* Temporarily move back to the previous entry, to * patch in pointer */ @@ -692,6 +703,7 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { } f->header->tail_entry_offset = htole64(offset); + f->header->tail_entry_realtime = o->entry.realtime; /* Link up the items */ n = journal_file_entry_n_items(o); @@ -1087,6 +1099,7 @@ int journal_file_open( const char *fname, int flags, mode_t mode, + JournalFile *template, JournalFile **ret) { JournalFile *f; @@ -1103,21 +1116,24 @@ int journal_file_open( if (!f) return -ENOMEM; + f->fd = -1; + f->flags = flags; + f->mode = mode; f->writable = (flags & O_ACCMODE) != O_RDONLY; f->prot = prot_from_flags(flags); - f->fd = open(fname, flags|O_CLOEXEC, mode); - if (f->fd < 0) { - r = -errno; - goto fail; - } - f->path = strdup(fname); if (!f->path) { r = -ENOMEM; goto fail; } + f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode); + if (f->fd < 0) { + r = -errno; + goto fail; + } + if (fstat(f->fd, &f->last_stat) < 0) { r = -errno; goto fail; @@ -1126,7 +1142,7 @@ int journal_file_open( if (f->last_stat.st_size == 0 && f->writable) { newly_created = true; - r = journal_file_init_header(f); + r = journal_file_init_header(f, template); if (r < 0) goto fail; @@ -1189,3 +1205,206 @@ fail: return r; } + +int journal_file_rotate(JournalFile **f) { + char *p; + size_t l; + JournalFile *old_file, *new_file = NULL; + int r; + + assert(f); + assert(*f); + + old_file = *f; + + if (!old_file->writable) + return -EINVAL; + + if (!endswith(old_file->path, ".journal")) + return -EINVAL; + + l = strlen(old_file->path); + + p = new(char, l + 1 + 16 + 1 + 32 + 1 + 16 + 1); + if (!p) + return -ENOMEM; + + memcpy(p, old_file->path, l - 8); + p[l-8] = '@'; + sd_id128_to_string(old_file->header->seqnum_id, p + l - 8 + 1); + snprintf(p + l - 8 + 1 + 32, 1 + 16 + 1 + 16 + 8 + 1, + "-%016llx-%016llx.journal", + (unsigned long long) le64toh((*f)->header->seqnum), + (unsigned long long) le64toh((*f)->header->tail_entry_realtime)); + + r = rename(old_file->path, p); + free(p); + + if (r < 0) + return -errno; + + old_file->header->state = le32toh(STATE_ARCHIVED); + + r = journal_file_open(old_file->path, old_file->flags, old_file->mode, old_file, &new_file); + journal_file_close(old_file); + + *f = new_file; + return r; +} + +struct vacuum_info { + off_t usage; + char *filename; + + uint64_t realtime; + sd_id128_t seqnum_id; + uint64_t seqnum; +}; + +static int vacuum_compare(const void *_a, const void *_b) { + const struct vacuum_info *a, *b; + + a = _a; + b = _b; + + if (sd_id128_equal(a->seqnum_id, b->seqnum_id)) { + if (a->seqnum < b->seqnum) + return -1; + else if (a->seqnum > b->seqnum) + return 1; + else + return 0; + } + + if (a->realtime < b->realtime) + return -1; + else if (a->realtime > b->realtime) + return 1; + else + return memcmp(&a->seqnum_id, &b->seqnum_id, 16); +} + +int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free) { + DIR *d; + int r = 0; + struct vacuum_info *list = NULL; + unsigned n_list = 0, n_allocated = 0, i; + uint64_t sum = 0; + + assert(directory); + + if (max_use <= 0) + max_use = DEFAULT_MAX_USE; + + d = opendir(directory); + if (!d) + return -errno; + + for (;;) { + int k; + struct dirent buf, *de; + size_t q; + struct stat st; + char *p; + unsigned long long seqnum, realtime; + sd_id128_t seqnum_id; + + k = readdir_r(d, &buf, &de); + if (k != 0) { + r = -k; + goto finish; + } + + if (!de) + break; + + if (!dirent_is_file_with_suffix(de, ".journal")) + continue; + + q = strlen(de->d_name); + + if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) + continue; + + if (de->d_name[q-8-16-1] != '-' || + de->d_name[q-8-16-1-16-1] != '-' || + de->d_name[q-8-16-1-16-1-32-1] != '@') + continue; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) + continue; + + if (!S_ISREG(st.st_mode)) + continue; + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + de->d_name[q-8-16-1-16-1] = 0; + if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { + free(p); + continue; + } + + if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { + free(p); + continue; + } + + if (n_list >= n_allocated) { + struct vacuum_info *j; + + n_allocated = MAX(n_allocated * 2U, 8U); + j = realloc(list, n_allocated * sizeof(struct vacuum_info)); + if (!j) { + free(p); + r = -ENOMEM; + goto finish; + } + + list = j; + } + + list[n_list].filename = p; + list[n_list].usage = (uint64_t) st.st_blksize * (uint64_t) st.st_blocks; + list[n_list].seqnum = seqnum; + list[n_list].realtime = realtime; + list[n_list].seqnum_id = seqnum_id; + + sum += list[n_list].usage; + + n_list ++; + } + + qsort(list, n_list, sizeof(struct vacuum_info), vacuum_compare); + + for(i = 0; i < n_list; i++) { + struct statvfs ss; + + if (fstatvfs(dirfd(d), &ss) < 0) { + r = -errno; + goto finish; + } + + if (sum <= max_use && + (uint64_t) ss.f_bavail * (uint64_t) ss.f_bsize >= min_free) + break; + + if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { + log_debug("Deleted archived journal %s/%s.", directory, list[i].filename); + sum -= list[i].usage; + } else if (errno != ENOENT) + log_warning("Failed to delete %s/%s: %m", directory, list[i].filename); + } + +finish: + for (i = 0; i < n_list; i++) + free(list[i].filename); + + free(list); + + return r; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 55cc7153af..4665f4da38 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -32,6 +32,8 @@ typedef struct JournalFile { int fd; char *path; struct stat last_stat; + mode_t mode; + int flags; int prot; bool writable; @@ -63,7 +65,7 @@ typedef struct JournalCursor { uint64_t xor_hash; } JournalCursor; -int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile **ret); +int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret); void journal_file_close(JournalFile *j); @@ -83,4 +85,9 @@ int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *o void journal_file_dump(JournalFile *f); +int journal_file_rotate(JournalFile **f); + +int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); + + #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ac376eaf4f..4645f9ebb0 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -41,7 +41,7 @@ static int system_journal_open(JournalFile **f) { if (!fn) return -ENOMEM; - r = journal_file_open(fn, O_RDONLY, 0640, f); + r = journal_file_open(fn, O_RDONLY, 0640, NULL, f); free(fn); if (r >= 0) @@ -56,7 +56,7 @@ static int system_journal_open(JournalFile **f) { if (!fn) return -ENOMEM; - r = journal_file_open(fn, O_RDONLY, 0640, f); + r = journal_file_open(fn, O_RDONLY, 0640, NULL, f); free(fn); if (r < 0) { diff --git a/src/journal/journald.c b/src/journal/journald.c index 94261f6763..7a2b50b017 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -109,10 +109,10 @@ static JournalFile* find_journal(Server *s, uid_t uid) { if (f) return f; - if (asprintf(&p, "/var/log/journal/%lu.journal", (unsigned long) uid) < 0) + if (asprintf(&p, "/var/log/journal/user-%lu.journal", (unsigned long) uid) < 0) return s->system_journal; - r = journal_file_open(p, O_RDWR|O_CREAT, 0640, &f); + r = journal_file_open(p, O_RDWR|O_CREAT, 0640, NULL, &f); free(p); if (r < 0) @@ -386,7 +386,7 @@ static int system_journal_open(Server *s) { if (!fn) return -ENOMEM; - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, &s->system_journal); + r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal); free(fn); if (r >= 0) { @@ -411,7 +411,7 @@ static int system_journal_open(Server *s) { fn = join("/run/log/journal/", ids, "/system.journal", NULL); if (!fn) return -ENOMEM; - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, &s->runtime_journal); + r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); free(fn); if (r < 0) { @@ -584,7 +584,7 @@ int main(int argc, char *argv[]) { sd_notify(false, "READY=1\n" "STATUS=Processing messages..."); - +# for (;;) { struct epoll_event event; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 8426b3bf9e..9f5f1e858b 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -294,7 +294,7 @@ int sd_journal_open(sd_journal **ret) { goto fail; } - k = journal_file_open(fn, O_RDONLY, 0, &f); + k = journal_file_open(fn, O_RDONLY, 0, NULL, &f); free(fn); if (k < 0) { diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 7028f11f7c..8dd26bbc32 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -20,6 +20,7 @@ ***/ #include +#include #include "journal-file.h" #include "log.h" @@ -33,7 +34,9 @@ int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); - assert_se(journal_file_open("test", O_RDWR|O_CREAT, 0666, &f) == 0); + unlink("test.journal"); + + assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, NULL, &f) == 0); dual_timestamp_get(&ts); @@ -87,7 +90,12 @@ int main(int argc, char *argv[]) { assert(journal_file_move_to_entry(f, 10, &o, NULL) == 0); + journal_file_rotate(&f); + journal_file_rotate(&f); + journal_file_close(f); + journal_directory_vacuum(".", 3000000, 0); + return 0; } -- cgit v1.2.3-54-g00ecf From 3fbf9cbb02690e40cd65802e777519f3f3c8d88a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Oct 2011 04:44:50 +0200 Subject: journal: implement parallel file traversal --- src/journal/journal-file.c | 9 +- src/journal/journal-file.h | 12 +- src/journal/journalctl.c | 103 ++++---------- src/journal/journald.c | 17 +-- src/journal/sd-journal.c | 346 +++++++++++++++++++++++++++++++++++++-------- src/journal/sd-journal.h | 20 ++- 6 files changed, 340 insertions(+), 167 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 934c043aff..6c8d712dbd 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -751,8 +751,8 @@ static int journal_file_append_entry_internal( o->object.type = htole64(OBJECT_ENTRY); o->entry.seqnum = htole64(journal_file_seqnum(f)); memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); - o->entry.realtime = ts ? htole64(ts->realtime) : 0; - o->entry.monotonic = ts ? htole64(ts->monotonic) : 0; + o->entry.realtime = htole64(ts ? ts->realtime : now(CLOCK_REALTIME)); + o->entry.monotonic = htole64(ts ? ts->monotonic : now(CLOCK_MONOTONIC)); o->entry.xor_hash = htole64(xor_hash); o->entry.boot_id = f->header->boot_id; @@ -1072,7 +1072,10 @@ void journal_file_dump(JournalFile *f) { break; case OBJECT_ENTRY: - printf("Type: OBJECT_ENTRY %llu\n", (unsigned long long) le64toh(o->entry.seqnum)); + printf("Type: OBJECT_ENTRY %llu %llu %llu\n", + (unsigned long long) le64toh(o->entry.seqnum), + (unsigned long long) le64toh(o->entry.monotonic), + (unsigned long long) le64toh(o->entry.realtime)); break; case OBJECT_HASH_TABLE: diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 4665f4da38..c51504d11b 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -52,19 +52,9 @@ typedef struct JournalFile { uint64_t window_size; uint64_t current_offset; + uint64_t current_field; } JournalFile; -typedef struct JournalCursor { - uint8_t version; - uint8_t reserved[7]; - uint64_t seqnum; - sd_id128_t seqnum_id; - sd_id128_t boot_id; - uint64_t monotonic; - uint64_t realtime; - uint64_t xor_hash; -} JournalCursor; - int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret); void journal_file_close(JournalFile *j); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 4645f9ebb0..bb1f18a21f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -22,104 +22,51 @@ #include #include #include +#include +#include +#include +#include -#include "journal-file.h" - -static int system_journal_open(JournalFile **f) { - int r; - char *fn; - sd_id128_t machine; - char ids[33]; - - assert(f); - - r = sd_id128_get_machine(&machine); - if (r < 0) - return r; - - fn = join("/var/log/journal/", sd_id128_to_string(machine, ids), "/system.journal", NULL); - if (!fn) - return -ENOMEM; - - r = journal_file_open(fn, O_RDONLY, 0640, NULL, f); - free(fn); - - if (r >= 0) - return r; - - if (r < 0 && r != -ENOENT) { - log_error("Failed to open system journal: %s", strerror(-r)); - return r; - } - - fn = join("/run/log/journal/", ids, "/system.journal", NULL); - if (!fn) - return -ENOMEM; - - r = journal_file_open(fn, O_RDONLY, 0640, NULL, f); - free(fn); - - if (r < 0) { - log_error("Failed to open system journal: %s", strerror(-r)); - return r; - } - - return r; -} +#include "sd-journal.h" +#include "log.h" int main(int argc, char *argv[]) { int r; - JournalFile *f; - Object *o = NULL; + sd_journal *j = NULL; + + log_set_max_level(LOG_DEBUG); + log_set_target(LOG_TARGET_CONSOLE); log_parse_environment(); log_open(); - r = system_journal_open(&f); + r = sd_journal_open(&j); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); - return EXIT_FAILURE; + goto finish; } - for (;;) { - uint64_t offset; - uint64_t n, i; + SD_JOURNAL_FOREACH(j) { + const void *data; + size_t length; + char *cursor; - r = journal_file_next_entry(f, o, &o, &offset); + r = sd_journal_get_cursor(j, &cursor); if (r < 0) { - log_error("Failed to read journal: %s", strerror(-r)); + log_error("Failed to get cursor: %s", strerror(-r)); goto finish; } - if (r == 0) - break; + printf("entry: %s\n", cursor); + free(cursor); - printf("entry: %llu\n", (unsigned long long) le64toh(o->entry.seqnum)); - - n = journal_file_entry_n_items(o); - for (i = 0; i < n; i++) { - uint64_t p, l; - - p = le64toh(o->entry.items[i].object_offset); - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); - if (r < 0) { - log_error("Failed to move to data: %s", strerror(-r)); - goto finish; - } - - l = o->object.size - offsetof(Object, data.payload); - printf("\t[%.*s]\n", (int) l, o->data.payload); - - r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); - if (r < 0) { - log_error("Failed to move back to entry: %s", strerror(-r)); - goto finish; - } - } + SD_JOURNAL_FOREACH_FIELD(j, data, length) + printf("\t%.*s\n", (int) length, (const char*) data); } finish: - journal_file_close(f); + if (j) + sd_journal_close(j); - return 0; + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/journal/journald.c b/src/journal/journald.c index 7a2b50b017..1143d81abc 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -95,6 +95,8 @@ static JournalFile* find_journal(Server *s, uid_t uid) { char *p; int r; JournalFile *f; + char ids[33]; + sd_id128_t machine; assert(s); @@ -105,11 +107,15 @@ static JournalFile* find_journal(Server *s, uid_t uid) { if (uid <= 0) return s->system_journal; + r = sd_id128_get_machine(&machine); + if (r < 0) + return s->system_journal; + f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid)); if (f) return f; - if (asprintf(&p, "/var/log/journal/user-%lu.journal", (unsigned long) uid) < 0) + if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0) return s->system_journal; r = journal_file_open(p, O_RDWR|O_CREAT, 0640, NULL, &f); @@ -401,16 +407,11 @@ static int system_journal_open(Server *s) { /* /var didn't work, so try /run, but this time we * create the prefix too */ - fn = strappend("/run/log/journal/", ids); - if (!fn) - return -ENOMEM; - (void) mkdir_p(fn, 0755); - free(fn); - - /* Then create the runtime journal file */ fn = join("/run/log/journal/", ids, "/system.journal", NULL); if (!fn) return -ENOMEM; + + (void) mkdir_parents(fn, 0755); r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); free(fn); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 9f5f1e858b..6f47520217 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -21,6 +21,7 @@ #include #include +#include #include "sd-journal.h" #include "journal-def.h" @@ -151,7 +152,8 @@ int sd_journal_next(sd_journal *j) { if (new_current) { j->current_file = new_current; - f->current_offset = new_offset; + j->current_file->current_offset = new_offset; + j->current_file->current_field = 0; return 1; } @@ -193,59 +195,134 @@ int sd_journal_previous(sd_journal *j) { if (new_current) { j->current_file = new_current; - f->current_offset = new_offset; + j->current_file->current_offset = new_offset; + j->current_file->current_field = 0; return 1; } return 0; } -int sd_journal_get_cursor(sd_journal *j, void **cursor, size_t *size) { - JournalCursor *c; +int sd_journal_get_cursor(sd_journal *j, char **cursor) { Object *o; int r; + char bid[33], sid[33]; assert(j); assert(cursor); - assert(size); - if (!j->current_file || !j->current_file->current_offset <= 0) - return 0; + if (!j->current_file || j->current_file->current_offset <= 0) + return -EADDRNOTAVAIL; r = journal_file_move_to_object(j->current_file, j->current_file->current_offset, OBJECT_ENTRY, &o); if (r < 0) return r; - c = new0(JournalCursor, 1); - if (!c) - return -ENOMEM; + sd_id128_to_string(j->current_file->header->seqnum_id, sid); + sd_id128_to_string(o->entry.boot_id, bid); - c->version = 1; - c->seqnum = o->entry.seqnum; - c->seqnum_id = j->current_file->header->seqnum_id; - c->boot_id = o->entry.boot_id; - c->monotonic = o->entry.monotonic; - c->realtime = o->entry.realtime; - c->xor_hash = o->entry.xor_hash; - - *cursor = c; - *size = sizeof(JournalCursor); + if (asprintf(cursor, + "s=%s;i=%llx;b=%s;m=%llx;t=%llx;x=%llx;p=%s", + sid, (unsigned long long) le64toh(o->entry.seqnum), + bid, (unsigned long long) le64toh(o->entry.monotonic), + (unsigned long long) le64toh(o->entry.realtime), + (unsigned long long) le64toh(o->entry.xor_hash), + file_name_from_path(j->current_file->path)) < 0) + return -ENOMEM; return 1; } -int sd_journal_set_cursor(sd_journal *j, const void *cursor, size_t size) { +int sd_journal_set_cursor(sd_journal *j, const char *cursor) { return -EINVAL; } +static int add_file(sd_journal *j, const char *prefix, const char *dir, const char *filename) { + char *fn; + int r; + JournalFile *f; + + assert(j); + assert(prefix); + assert(filename); + + if (dir) + fn = join(prefix, "/", dir, "/", filename, NULL); + else + fn = join(prefix, "/", filename, NULL); + + if (!fn) + return -ENOMEM; + + r = journal_file_open(fn, O_RDONLY, 0, NULL, &f); + free(fn); + + if (r < 0) { + if (errno == ENOENT) + return 0; + + return r; + } + + r = hashmap_put(j->files, f->path, f); + if (r < 0) { + journal_file_close(f); + return r; + } + + return 0; +} + +static int add_directory(sd_journal *j, const char *prefix, const char *dir) { + char *fn; + int r; + DIR *d; + + assert(j); + assert(prefix); + assert(dir); + + fn = join(prefix, "/", dir, NULL); + if (!fn) + return -ENOMEM; + + d = opendir(fn); + free(fn); + + if (!d) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + for (;;) { + struct dirent buf, *de; + + r = readdir_r(d, &buf, &de); + if (r != 0 || !de) + break; + + if (!dirent_is_file_with_suffix(de, ".journal")) + continue; + + r = add_file(j, prefix, dir, de->d_name); + if (r < 0) + log_debug("Failed to add file %s/%s/%s: %s", prefix, dir, de->d_name, strerror(-r)); + } + + closedir(d); + + return 0; +} + int sd_journal_open(sd_journal **ret) { sd_journal *j; - char *fn; const char *p; - int r = 0; const char search_paths[] = "/run/log/journal\0" "/var/log/journal\0"; + int r; assert(ret); @@ -254,64 +331,47 @@ int sd_journal_open(sd_journal **ret) { return -ENOMEM; j->files = hashmap_new(string_hash_func, string_compare_func); - if (!j->files) + if (!j->files) { + r = -ENOMEM; goto fail; + } + + /* We ignore most errors here, since the idea is to only open + * what's actually accessible, and ignore the rest. */ NULSTR_FOREACH(p, search_paths) { DIR *d; d = opendir(p); if (!d) { - if (errno != ENOENT && r == 0) - r = -errno; - + if (errno != ENOENT) + log_debug("Failed to open %s: %m", p); continue; } for (;;) { struct dirent buf, *de; - int k; - JournalFile *f; - - k = readdir_r(d, &buf, &de); - if (k != 0) { - if (r == 0) - r = -k; - - break; - } + sd_id128_t id; - if (!de) + r = readdir_r(d, &buf, &de); + if (r != 0 || !de) break; - if (!dirent_is_file_with_suffix(de, ".journal")) - continue; + if (dirent_is_file_with_suffix(de, ".journal")) { + r = add_file(j, p, NULL, de->d_name); + if (r < 0) + log_debug("Failed to add file %s/%s: %s", p, de->d_name, strerror(-r)); - fn = join(p, "/", de->d_name, NULL); - if (!fn) { - r = -ENOMEM; - closedir(d); - goto fail; - } - - k = journal_file_open(fn, O_RDONLY, 0, NULL, &f); - free(fn); - - if (k < 0) { + } else if ((de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) && + sd_id128_from_string(de->d_name, &id) >= 0) { - if (r == 0) - r = -k; - } else { - k = hashmap_put(j->files, f->path, f); - if (k < 0) { - journal_file_close(f); - closedir(d); - - r = k; - goto fail; - } + r = add_directory(j, p, de->d_name); + if (r < 0) + log_debug("Failed to add directory %s/%s: %s", p, de->d_name, strerror(-r)); } } + + closedir(d); } *ret = j; @@ -337,3 +397,165 @@ void sd_journal_close(sd_journal *j) { free(j); } + +int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { + Object *o; + JournalFile *f; + int r; + + assert(j); + assert(ret); + + f = j->current_file; + if (!f) + return 0; + + if (f->current_offset <= 0) + return 0; + + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + *ret = le64toh(o->entry.realtime); + return 1; +} + +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret) { + Object *o; + JournalFile *f; + int r; + sd_id128_t id; + + assert(j); + assert(ret); + + f = j->current_file; + if (!f) + return 0; + + if (f->current_offset <= 0) + return 0; + + r = sd_id128_get_machine(&id); + if (r < 0) + return r; + + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + if (!sd_id128_equal(id, o->entry.boot_id)) + return 0; + + *ret = le64toh(o->entry.monotonic); + return 1; + +} + +int sd_journal_get_field(sd_journal *j, const char *field, const void **data, size_t *size) { + JournalFile *f; + uint64_t i, n; + size_t field_length; + int r; + Object *o; + + assert(j); + assert(field); + assert(data); + assert(size); + + if (isempty(field) || strchr(field, '=')) + return -EINVAL; + + f = j->current_file; + if (!f) + return 0; + + if (f->current_offset <= 0) + return 0; + + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + field_length = strlen(field); + + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + uint64_t p, l; + size_t t; + + p = le64toh(o->entry.items[i].object_offset); + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + + if (field_length+1 > l) + continue; + + if (memcmp(o->data.payload, field, field_length) || + o->data.payload[field_length] != '=') + continue; + + t = (size_t) l; + + if ((uint64_t) t != l) + return -E2BIG; + + *data = o->data.payload; + *size = t; + + return 1; + } + + return 0; +} + +int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { + JournalFile *f; + uint64_t p, l, n; + size_t t; + int r; + Object *o; + + assert(j); + assert(data); + assert(size); + + f = j->current_file; + if (!f) + return 0; + + if (f->current_offset <= 0) + return 0; + + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + if (r < 0) + return r; + + n = journal_file_entry_n_items(o); + if (f->current_field >= n) + return 0; + + p = le64toh(o->entry.items[f->current_field].object_offset); + r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + if (r < 0) + return r; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + t = (size_t) l; + + /* We can't read objects larger than 4G on a 32bit machine */ + if ((uint64_t) t != l) + return -E2BIG; + + *data = o->data.payload; + *size = t; + + f->current_field ++; + + return 1; +} diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 55e58601fe..bbfcda6f2a 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -27,13 +27,14 @@ /* TODO: * - * - implement rotation * - check LE/BE conversion for 8bit, 16bit, 32bit values * - implement parallel traversal * - implement inotify usage on client * - implement audit gateway * - implement native gateway + * - implement stdout gateway * - extend hash table/bisect table as we go + * - accelerate looking for "all hostnames" and suchlike. */ typedef struct sd_journal sd_journal; @@ -44,10 +45,10 @@ void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); int sd_journal_next(sd_journal *j); -int sd_journal_get(sd_journal *j, const char *field, const void **data, size_t *size); -int sd_journal_get_seqnum(sd_journal *j, uint64_t *ret); int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret); +int sd_journal_get_field(sd_journal *j, const char *field, const void **data, size_t *l); +int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *l); int sd_journal_add_match(sd_journal *j, const char *field, const void *data, size_t size); void sd_journal_flush_matches(sd_journal *j); @@ -59,9 +60,18 @@ int sd_journal_seek_seqnum(sd_journal *j, uint64_t seqnum); int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); -int sd_journal_get_cursor(sd_journal *j, void **cursor, size_t *size); -int sd_journal_set_cursor(sd_journal *j, const void *cursor, size_t size); +int sd_journal_get_cursor(sd_journal *j, char **cursor); +int sd_journal_set_cursor(sd_journal *j, const char *cursor); int sd_journal_get_fd(sd_journal *j); +#define SD_JOURNAL_FOREACH(j) \ + while (sd_journal_next(j) > 0) + +#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ + while (sd_journal_previous(j) > 0) + +#define SD_JOURNAL_FOREACH_FIELD(j, data, l) \ + while (sd_journal_iterate_fields((j), &(data), &(l)) > 0) + #endif -- cgit v1.2.3-54-g00ecf From c2373f848dddcc1827cf715c5ef778dc8d475761 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Oct 2011 05:12:58 +0200 Subject: journal: synchronize seqnum across files --- src/journal/journal-file.c | 21 +++++++++++++++++---- src/journal/journal-file.h | 2 +- src/journal/journalctl.c | 8 ++++++++ src/journal/journald.c | 6 ++++-- src/journal/sd-journal.c | 10 ++++++++++ src/journal/sd-journal.h | 1 - src/journal/test-journal.c | 6 +++--- 7 files changed, 43 insertions(+), 11 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 6c8d712dbd..537978137b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -364,12 +364,24 @@ int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Objec return 0; } -static uint64_t journal_file_seqnum(JournalFile *f) { +static uint64_t journal_file_seqnum(JournalFile *f, uint64_t *seqnum) { uint64_t r; assert(f); r = le64toh(f->header->seqnum) + 1; + + if (seqnum) { + /* If an external seqno counter was passed, we update + * both the local and the external one, and set it to + * the maximum of both */ + + if (*seqnum + 1 > r) + r = *seqnum + 1; + + *seqnum = r; + } + f->header->seqnum = htole64(r); return r; @@ -733,6 +745,7 @@ static int journal_file_append_entry_internal( const dual_timestamp *ts, uint64_t xor_hash, const EntryItem items[], unsigned n_items, + uint64_t *seqno, Object **ret, uint64_t *offset) { uint64_t np; uint64_t osize; @@ -749,7 +762,7 @@ static int journal_file_append_entry_internal( return r; o->object.type = htole64(OBJECT_ENTRY); - o->entry.seqnum = htole64(journal_file_seqnum(f)); + o->entry.seqnum = htole64(journal_file_seqnum(f, seqno)); memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); o->entry.realtime = htole64(ts ? ts->realtime : now(CLOCK_REALTIME)); o->entry.monotonic = htole64(ts ? ts->monotonic : now(CLOCK_MONOTONIC)); @@ -769,7 +782,7 @@ static int journal_file_append_entry_internal( return 0; } -int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset) { +int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset) { unsigned i; EntryItem *items; int r; @@ -794,7 +807,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st items[i].object_offset = htole64(p); } - r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, ret, offset); + r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqno, ret, offset); finish: free(items); diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index c51504d11b..92f671a756 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -63,7 +63,7 @@ int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Objec uint64_t journal_file_entry_n_items(Object *o); -int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, Object **ret, uint64_t *offset); +int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset); int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index bb1f18a21f..a6b6e0fbd6 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -50,6 +50,7 @@ int main(int argc, char *argv[]) { const void *data; size_t length; char *cursor; + uint64_t realtime = 0, monotonic = 0; r = sd_journal_get_cursor(j, &cursor); if (r < 0) { @@ -60,6 +61,13 @@ int main(int argc, char *argv[]) { printf("entry: %s\n", cursor); free(cursor); + sd_journal_get_realtime_usec(j, &realtime); + sd_journal_get_monotonic_usec(j, &monotonic); + printf("realtime: %llu\n" + "monotonic: %llu\n", + (unsigned long long) realtime, + (unsigned long long) monotonic); + SD_JOURNAL_FOREACH_FIELD(j, data, length) printf("\t%.*s\n", (int) length, (const char*) data); } diff --git a/src/journal/journald.c b/src/journal/journald.c index 1143d81abc..ede314a55f 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -43,6 +43,8 @@ typedef struct Server { JournalFile *runtime_journal; JournalFile *system_journal; Hashmap *user_journals; + + uint64_t seqnum; } Server; static void fix_perms(JournalFile *f, uid_t uid) { @@ -118,7 +120,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0) return s->system_journal; - r = journal_file_open(p, O_RDWR|O_CREAT, 0640, NULL, &f); + r = journal_file_open(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f); free(p); if (r < 0) @@ -252,7 +254,7 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str if (!f) log_warning("Dropping message, as we can't find a place to store the data."); else { - r = journal_file_append_entry(f, NULL, iovec, n, NULL, NULL); + r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); if (r < 0) log_error("Failed to write entry, ignoring: %s", strerror(-r)); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 1f4ad0ff64..1614bbf27f 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -561,3 +561,13 @@ int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { return 1; } + +int sd_journal_seek_head(sd_journal *j) { + assert(j); + return -EINVAL; +} + +int sd_journal_seek_tail(sd_journal *j) { + assert(j); + return -EINVAL; +} diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index bbfcda6f2a..13b5f891d7 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -56,7 +56,6 @@ void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_tail(sd_journal *j); -int sd_journal_seek_seqnum(sd_journal *j, uint64_t seqnum); int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 8dd26bbc32..3b67f1aa9f 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -42,15 +42,15 @@ int main(int argc, char *argv[]) { iovec.iov_base = (void*) test; iovec.iov_len = strlen(test); - assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL) == 0); + assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); iovec.iov_base = (void*) test2; iovec.iov_len = strlen(test2); - assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL) == 0); + assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); iovec.iov_base = (void*) test; iovec.iov_len = strlen(test); - assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL) == 0); + assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); journal_file_dump(f); -- cgit v1.2.3-54-g00ecf From de7b95cdc3228131498021c2fdcf6647004c3920 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 15 Oct 2011 01:13:37 +0200 Subject: journal: properly implement matching with multiple matches --- src/journal/journal-def.h | 1 + src/journal/journal-file.c | 1 + src/journal/journalctl.c | 10 +++- src/journal/sd-journal.c | 138 ++++++++++++++++++++++++++++++++++++++------- 4 files changed, 129 insertions(+), 21 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index d44b070fd0..5cb1e6d9c8 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -65,6 +65,7 @@ _packed_ struct DataObject { _packed_ struct EntryItem { uint64_t object_offset; + uint64_t hash; uint64_t prev_entry_offset; uint64_t next_entry_offset; }; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 537978137b..5557028147 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -805,6 +805,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st xor_hash ^= le64toh(o->data.hash); items[i].object_offset = htole64(p); + items[i].hash = o->data.hash; } r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqno, ret, offset); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index a6b6e0fbd6..3475b9d43c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -31,7 +31,7 @@ #include "log.h" int main(int argc, char *argv[]) { - int r; + int r, i; sd_journal *j = NULL; log_set_max_level(LOG_DEBUG); @@ -46,6 +46,14 @@ int main(int argc, char *argv[]) { goto finish; } + for (i = 1; i < argc; i++) { + r = sd_journal_add_match(j, argv[i], strlen(argv[i])); + if (r < 0) { + log_error("Failed to add match: %s", strerror(-r)); + goto finish; + } + } + SD_JOURNAL_FOREACH(j) { const void *data; size_t length; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index d580b8e768..bc6d255662 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -28,13 +28,14 @@ #include "journal-file.h" #include "hashmap.h" #include "list.h" +#include "lookup3.h" typedef struct Match Match; struct Match { char *data; size_t size; - uint64_t hash; + uint64_t le_hash; LIST_FIELDS(Match, matches); }; @@ -46,6 +47,7 @@ struct sd_journal { uint64_t current_field; LIST_HEAD(Match, matches); + unsigned n_matches; }; int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { @@ -71,8 +73,11 @@ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { } memcpy(m->data, data, size); + m->le_hash = hash64(m->data, size); LIST_PREPEND(Match, matches, j->matches, m); + j->n_matches ++; + return 0; } @@ -86,6 +91,8 @@ void sd_journal_flush_matches(sd_journal *j) { free(m->data); free(m); } + + j->n_matches = 0; } static int compare_order(JournalFile *af, Object *ao, uint64_t ap, @@ -155,6 +162,103 @@ static int compare_order(JournalFile *af, Object *ao, uint64_t ap, return 0; } +static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o, uint64_t *p) { + int r; + uint64_t cp; + Object *c; + + assert(j); + assert(f); + assert(o); + assert(p); + + if (!j->matches) { + /* No matches is easy, just go on to the next entry */ + + if (f->current_offset > 0) { + r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &c); + if (r < 0) + return r; + } else + c = NULL; + + return journal_file_next_entry(f, c, o, p); + } + + /* So there are matches we have to adhere to, let's find the + * first entry that matches all of them */ + + if (f->current_offset > 0) + cp = f->current_offset; + else { + r = journal_file_find_first_entry(f, j->matches->data, j->matches->size, &c, &cp); + if (r <= 0) + return r; + + /* We can shortcut this if there's only one match */ + if (j->n_matches == 1) { + *o = c; + *p = cp; + return r; + } + } + + for (;;) { + uint64_t np, n; + bool found; + Match *m; + + r = journal_file_move_to_object(f, cp, OBJECT_ENTRY, &c); + if (r < 0) + return r; + + n = journal_file_entry_n_items(c); + + /* Make sure we don't match the entry we are starting + * from. */ + found = f->current_offset != cp; + + np = 0; + LIST_FOREACH(matches, m, j->matches) { + uint64_t q, k; + + for (k = 0; k < n; k++) + if (c->entry.items[k].hash == m->le_hash) + break; + + if (k >= n) { + /* Hmm, didn't find any field that matched, so ignore + * this match. Go on with next match */ + + found = false; + continue; + } + + /* Hmm, so, this field matched, let's remember + * where we'd have to try next, in case the other + * matches are not OK */ + q = le64toh(c->entry.items[k].next_entry_offset); + if (q > np) + np = q; + } + + /* Did this entry match against all matches? */ + if (found) { + *o = c; + *p = cp; + return 1; + } + + /* Did we find a subsequent entry? */ + if (np == 0) + return 0; + + /* Hmm, ok, this entry only matched partially, so + * let's try another one */ + cp = np; + } +} + int sd_journal_next(sd_journal *j) { JournalFile *f, *new_current = NULL; Iterator i; @@ -168,14 +272,7 @@ int sd_journal_next(sd_journal *j) { Object *o; uint64_t p; - if (f->current_offset > 0) { - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); - if (r < 0) - return r; - } else - o = NULL; - - r = journal_file_next_entry(f, o, &o, &p); + r = move_to_next_with_matches(j, f, &o, &p); if (r < 0) return r; else if (r == 0) @@ -203,14 +300,7 @@ int sd_journal_next(sd_journal *j) { if (j->current_file == f) continue; - if (f->current_offset > 0) { - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); - if (r < 0) - return r; - } else - o = NULL; - - r = journal_file_next_entry(f, o, &o, &p); + r = move_to_next_with_matches(j, f, &o, &p); if (r < 0) return r; else if (r == 0) @@ -532,7 +622,7 @@ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret) { if (f->current_offset <= 0) return 0; - r = sd_id128_get_machine(&id); + r = sd_id128_get_boot(&id); if (r < 0) return r; @@ -578,14 +668,18 @@ int sd_journal_get_field(sd_journal *j, const char *field, const void **data, si n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { - uint64_t p, l; + uint64_t p, l, h; size_t t; p = le64toh(o->entry.items[i].object_offset); + h = o->entry.items[j->current_field].hash; r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); if (r < 0) return r; + if (h != o->data.hash) + return -EBADMSG; + l = le64toh(o->object.size) - offsetof(Object, data.payload); if (l >= field_length+1 && @@ -613,7 +707,7 @@ int sd_journal_get_field(sd_journal *j, const char *field, const void **data, si int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { JournalFile *f; - uint64_t p, l, n; + uint64_t p, l, n, h; size_t t; int r; Object *o; @@ -638,10 +732,14 @@ int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { return 0; p = le64toh(o->entry.items[j->current_field].object_offset); + h = o->entry.items[j->current_field].hash; r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); if (r < 0) return r; + if (h != o->data.hash) + return -EBADMSG; + l = le64toh(o->object.size) - offsetof(Object, data.payload); t = (size_t) l; -- cgit v1.2.3-54-g00ecf From 8725d60ae4f7a8471aa8a0207fa105e335d069a6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 15 Oct 2011 02:45:58 +0200 Subject: journal: implement seek to head/tail --- src/journal/journalctl.c | 8 +++++--- src/journal/sd-journal.c | 31 +++++++++++++++++++++++++------ src/journal/sd-journal.h | 43 +++++++++++++++++++++++++++++++------------ 3 files changed, 61 insertions(+), 21 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 3475b9d43c..3e5ee1af96 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -54,7 +54,8 @@ int main(int argc, char *argv[]) { } } - SD_JOURNAL_FOREACH(j) { + SD_JOURNAL_FOREACH_BEGIN(j) { + const void *data; size_t length; char *cursor; @@ -76,9 +77,10 @@ int main(int argc, char *argv[]) { (unsigned long long) realtime, (unsigned long long) monotonic); - SD_JOURNAL_FOREACH_FIELD(j, data, length) + SD_JOURNAL_FOREACH_DATA(j, data, length) printf("\t%.*s\n", (int) length, (const char*) data); - } + + } SD_JOURNAL_FOREACH_END(j); finish: if (j) diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 985e3210ce..6a68275e9e 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -585,7 +585,7 @@ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret) { } -int sd_journal_get_field(sd_journal *j, const char *field, const void **data, size_t *size) { +int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) { JournalFile *f; uint64_t i, n; size_t field_length; @@ -652,7 +652,7 @@ int sd_journal_get_field(sd_journal *j, const char *field, const void **data, si return 0; } -int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { +int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { JournalFile *f; uint64_t p, l, n, h; size_t t; @@ -702,12 +702,31 @@ int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *size) { return 1; } -int sd_journal_seek_head(sd_journal *j) { +void sd_journal_start_data(sd_journal *j) { assert(j); - return -EINVAL; + + j->current_field = 0; } -int sd_journal_seek_tail(sd_journal *j) { +static int real_journal_seek_head(sd_journal *j, direction_t direction) { + Iterator i; + JournalFile *f; + assert(j); - return -EINVAL; + + j->current_file = NULL; + j->current_field = 0; + + HASHMAP_FOREACH(f, j->files, i) + f->current_offset = 0; + + return real_journal_next(j, direction); +} + +int sd_journal_seek_head(sd_journal *j) { + return real_journal_seek_head(j, DIRECTION_DOWN); +} + +int sd_journal_seek_tail(sd_journal *j) { + return real_journal_seek_head(j, DIRECTION_UP); } diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 6b451b5765..bf6673453d 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -49,8 +49,9 @@ int sd_journal_next(sd_journal *j); int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret); -int sd_journal_get_field(sd_journal *j, const char *field, const void **data, size_t *l); -int sd_journal_iterate_fields(sd_journal *j, const void **data, size_t *l); +int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); +int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); +void sd_journal_start_data(sd_journal *j); int sd_journal_add_match(sd_journal *j, const void *data, size_t size); void sd_journal_flush_matches(sd_journal *j); @@ -58,13 +59,16 @@ void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_tail(sd_journal *j); -int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); -int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); +int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); /* missing */ +int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); /* missing */ int sd_journal_get_cursor(sd_journal *j, char **cursor); -int sd_journal_set_cursor(sd_journal *j, const char *cursor); +int sd_journal_set_cursor(sd_journal *j, const char *cursor); /* missing */ -int sd_journal_get_fd(sd_journal *j); +int sd_journal_unique_seek(sd_journal *j, const char *field); /* missing */ +int sd_journal_unique_enumerate(sd_journal *j, const void **data, size_t *l); /* missing */ + +int sd_journal_get_fd(sd_journal *j); /* missing */ enum { SD_JOURNAL_NOP, @@ -74,13 +78,28 @@ enum { int sd_journal_process(sd_journal *j); -#define SD_JOURNAL_FOREACH(j) \ - while (sd_journal_next(j) > 0) +#define SD_JOURNAL_FOREACH_BEGIN(j) \ + if (sd_journal_seek_head(j) > 0) do { + +#define SD_JOURNAL_FOREACH_END(j) \ + } while (sd_journal_next(j) > 0) + +#define SD_JOURNAL_FOREACH_CONTINUE(j) \ + do { + +#define SD_JOURNAL_FOREACH_BACKWARDS_BEGIN(j) \ + if (sd_journal_seek_tail(j) > 0) do { + +#define SD_JOURNAL_FOREACH_BACKWARDS_END(j) \ + } while (sd_journal_previous(j) > 0) + +#define SD_JOURNAL_FOREACH_BACKWARDS_CONTINUE(j) \ + do { -#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ - while (sd_journal_previous(j) > 0) +#define SD_JOURNAL_FOREACH_DATA(j, data, l) \ + for (sd_journal_start_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) -#define SD_JOURNAL_FOREACH_FIELD(j, data, l) \ - while (sd_journal_iterate_fields((j), &(data), &(l)) > 0) +#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ + while (sd_journal_enumerate_unique_data((j), &(data), &(l)) > 0) #endif -- cgit v1.2.3-54-g00ecf From de190aef08bb267b645205a747762df573b36834 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 8 Nov 2011 18:20:03 +0100 Subject: journal: implement multiple field matches --- src/journal/journal-def.h | 66 +-- src/journal/journal-file.c | 1134 ++++++++++++++++++++++++++++++++------------ src/journal/journal-file.h | 51 +- src/journal/journalctl.c | 6 +- src/journal/journald.c | 34 +- src/journal/sd-journal.c | 801 +++++++++++++++++++++++++------ src/journal/sd-journal.h | 61 ++- src/journal/test-journal.c | 41 +- src/journal/wjournal.c | 57 --- src/journal/wjournal.h | 39 -- 10 files changed, 1642 insertions(+), 648 deletions(-) delete mode 100644 src/journal/wjournal.c delete mode 100644 src/journal/wjournal.h (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 5cb1e6d9c8..1a63ca1f8d 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -31,9 +31,10 @@ typedef struct Header Header; typedef struct ObjectHeader ObjectHeader; typedef union Object Object; typedef struct DataObject DataObject; +typedef struct FieldObject FieldObject; typedef struct EntryObject EntryObject; typedef struct HashTableObject HashTableObject; -typedef struct BisectTableObject BisectTableObject; +typedef struct EntryArrayObject EntryArrayObject; typedef struct EntryItem EntryItem; typedef struct HashItem HashItem; @@ -41,9 +42,12 @@ typedef struct HashItem HashItem; enum { OBJECT_UNUSED, OBJECT_DATA, + OBJECT_FIELD, OBJECT_ENTRY, - OBJECT_HASH_TABLE, - OBJECT_BISECT_TABLE + OBJECT_DATA_HASH_TABLE, + OBJECT_FIELD_HASH_TABLE, + OBJECT_ENTRY_ARRAY, + _OBJECT_TYPE_MAX }; _packed_ struct ObjectHeader { @@ -56,18 +60,26 @@ _packed_ struct ObjectHeader { _packed_ struct DataObject { ObjectHeader object; uint64_t hash; - uint64_t head_entry_offset; - uint64_t tail_entry_offset; - uint64_t prev_hash_offset; uint64_t next_hash_offset; + uint64_t next_field_offset; + uint64_t entry_offset; /* the first array entry we store inline */ + uint64_t entry_array_offset; + uint64_t n_entries; + uint8_t payload[]; +}; + +_packed_ struct FieldObject { + ObjectHeader object; + uint64_t hash; + uint64_t next_hash_offset; + uint64_t head_data_offset; + uint64_t tail_data_offset; uint8_t payload[]; }; _packed_ struct EntryItem { uint64_t object_offset; uint64_t hash; - uint64_t prev_entry_offset; - uint64_t next_entry_offset; }; _packed_ struct EntryObject { @@ -77,8 +89,6 @@ _packed_ struct EntryObject { uint64_t monotonic; sd_id128_t boot_id; uint64_t xor_hash; - uint64_t prev_entry_offset; - uint64_t next_entry_offset; EntryItem items[]; }; @@ -89,20 +99,22 @@ _packed_ struct HashItem { _packed_ struct HashTableObject { ObjectHeader object; - HashItem table[]; + HashItem items[]; }; -_packed_ struct BisectTableObject { +_packed_ struct EntryArrayObject { ObjectHeader object; - uint64_t table[]; + uint64_t next_entry_array_offset; + uint64_t items[]; }; union Object { ObjectHeader object; DataObject data; + FieldObject field; EntryObject entry; HashTableObject hash_table; - BisectTableObject bisect_table; + EntryArrayObject entry_array; }; enum { @@ -115,30 +127,30 @@ _packed_ struct Header { uint8_t signature[8]; /* "LPKSHHRH" */ uint32_t compatible_flags; uint32_t incompatible_flags; - uint32_t state; - uint8_t reserved[4]; + uint8_t state; + uint8_t reserved[7]; sd_id128_t file_id; sd_id128_t machine_id; sd_id128_t boot_id; sd_id128_t seqnum_id; uint64_t arena_offset; uint64_t arena_size; - uint64_t arena_max_size; - uint64_t arena_min_size; - uint64_t arena_keep_free; - uint64_t hash_table_offset; /* for looking up data objects */ - uint64_t hash_table_size; - uint64_t bisect_table_offset; /* for looking up entry objects */ - uint64_t bisect_table_size; - uint64_t head_object_offset; + uint64_t arena_max_size; /* obsolete */ + uint64_t arena_min_size; /* obsolete */ + uint64_t arena_keep_free; /* obsolete */ + uint64_t data_hash_table_offset; /* for looking up data objects */ + uint64_t data_hash_table_size; + uint64_t field_hash_table_offset; /* for looking up field objects */ + uint64_t field_hash_table_size; uint64_t tail_object_offset; - uint64_t head_entry_offset; - uint64_t tail_entry_offset; - uint64_t last_bisect_offset; uint64_t n_objects; + uint64_t n_entries; uint64_t seqnum; + uint64_t first_seqnum; + uint64_t entry_array_offset; uint64_t head_entry_realtime; uint64_t tail_entry_realtime; + uint64_t tail_entry_monotonic; }; #endif diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index ab45132f0f..427631d30a 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -37,8 +37,8 @@ #define DEFAULT_MAX_USE (16ULL*1024ULL*1024ULL*16ULL) -#define DEFAULT_HASH_TABLE_SIZE (2047ULL*16ULL) -#define DEFAULT_BISECT_TABLE_SIZE ((DEFAULT_ARENA_MAX_SIZE/(64ULL*1024ULL))*8ULL) +#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*16ULL) +#define DEFAULT_FIELD_HASH_TABLE_SIZE (2047ULL*16ULL) #define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL) @@ -47,23 +47,17 @@ static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; #define ALIGN64(x) (((x) + 7ULL) & ~7ULL) void journal_file_close(JournalFile *f) { - assert(f); - - if (f->header) { - if (f->writable && f->header->state == htole32(STATE_ONLINE)) - f->header->state = htole32(STATE_OFFLINE); + int t; - munmap(f->header, PAGE_ALIGN(sizeof(Header))); - } + assert(f); - if (f->hash_table_window) - munmap(f->hash_table_window, f->hash_table_window_size); + if (f->header && f->writable) + f->header->state = STATE_OFFLINE; - if (f->bisect_table_window) - munmap(f->bisect_table_window, f->bisect_table_window_size); - if (f->window) - munmap(f->window, f->window_size); + for (t = 0; t < _WINDOW_MAX; t++) + if (f->windows[t].ptr) + munmap(f->windows[t].ptr, f->windows[t].size); if (f->fd >= 0) close_nointr_nofail(f->fd); @@ -108,6 +102,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { static int journal_file_refresh_header(JournalFile *f) { int r; + sd_id128_t boot_id; assert(f); @@ -115,11 +110,16 @@ static int journal_file_refresh_header(JournalFile *f) { if (r < 0) return r; - r = sd_id128_get_boot(&f->header->boot_id); + r = sd_id128_get_boot(&boot_id); if (r < 0) return r; - f->header->state = htole32(STATE_ONLINE); + if (sd_id128_equal(boot_id, f->header->boot_id)) + f->tail_entry_monotonic_valid = true; + + f->header->boot_id = boot_id; + + f->header->state = STATE_ONLINE; return 0; } @@ -147,7 +147,7 @@ static int journal_file_verify_header(JournalFile *f) { if (!sd_id128_equal(machine_id, f->header->machine_id)) return -EHOSTDOWN; - state = le32toh(f->header->state); + state = f->header->state; if (state == STATE_ONLINE) log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); @@ -254,28 +254,33 @@ static int journal_file_map( return 0; } -static int journal_file_move_to(JournalFile *f, uint64_t offset, uint64_t size, void **ret) { +static int journal_file_move_to(JournalFile *f, int wt, uint64_t offset, uint64_t size, void **ret) { void *p; uint64_t delta; int r; + Window *w; assert(f); assert(ret); + assert(wt >= 0); + assert(wt < _WINDOW_MAX); - if (_likely_(f->window && - f->window_offset <= offset && - f->window_offset+f->window_size >= offset + size)) { + w = f->windows + wt; - *ret = (uint8_t*) f->window + (offset - f->window_offset); + if (_likely_(w->ptr && + w->offset <= offset && + w->offset + w->size >= offset + size)) { + + *ret = (uint8_t*) w->ptr + (offset - w->offset); return 0; } - if (f->window) { - if (munmap(f->window, f->window_size) < 0) + if (w->ptr) { + if (munmap(w->ptr, w->size) < 0) return -errno; - f->window = NULL; - f->window_size = f->window_offset = 0; + w->ptr = NULL; + w->size = w->offset = 0; } if (size < DEFAULT_WINDOW_SIZE) { @@ -297,8 +302,8 @@ static int journal_file_move_to(JournalFile *f, uint64_t offset, uint64_t size, r = journal_file_map(f, offset, size, - &f->window, &f->window_offset, &f->window_size, - & p); + &w->ptr, &w->offset, &w->size, + &p); if (r < 0) return r; @@ -308,26 +313,23 @@ static int journal_file_move_to(JournalFile *f, uint64_t offset, uint64_t size, } static bool verify_hash(Object *o) { - uint64_t t; + uint64_t h1, h2; assert(o); - t = le64toh(o->object.type); - if (t == OBJECT_DATA) { - uint64_t s, h1, h2; - - s = le64toh(o->object.size); - + if (o->object.type == OBJECT_DATA) { h1 = le64toh(o->data.hash); - h2 = hash64(o->data.payload, s - offsetof(Object, data.payload)); - - return h1 == h2; - } + h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload)); + } else if (o->object.type == OBJECT_FIELD) { + h1 = le64toh(o->field.hash); + h2 = hash64(o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload)); + } else + return true; - return true; + return h1 == h2; } -int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Object **ret) { +int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) { int r; void *t; Object *o; @@ -335,8 +337,9 @@ int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Objec assert(f); assert(ret); + assert(type < _OBJECT_TYPE_MAX); - r = journal_file_move_to(f, offset, sizeof(ObjectHeader), &t); + r = journal_file_move_to(f, type >= 0 ? type : WINDOW_UNKNOWN, offset, sizeof(ObjectHeader), &t); if (r < 0) return r; @@ -346,11 +349,11 @@ int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Objec if (s < sizeof(ObjectHeader)) return -EBADMSG; - if (type >= 0 && le64toh(o->object.type) != type) + if (type >= 0 && o->object.type != type) return -EBADMSG; if (s > sizeof(ObjectHeader)) { - r = journal_file_move_to(f, offset, s, &t); + r = journal_file_move_to(f, o->object.type, offset, s, &t); if (r < 0) return r; @@ -372,7 +375,7 @@ static uint64_t journal_file_seqnum(JournalFile *f, uint64_t *seqnum) { r = le64toh(f->header->seqnum) + 1; if (seqnum) { - /* If an external seqno counter was passed, we update + /* If an external seqnum counter was passed, we update * both the local and the external one, and set it to * the maximum of both */ @@ -384,10 +387,13 @@ static uint64_t journal_file_seqnum(JournalFile *f, uint64_t *seqnum) { f->header->seqnum = htole64(r); + if (f->header->first_seqnum == 0) + f->header->first_seqnum = htole64(r); + return r; } -static int journal_file_append_object(JournalFile *f, uint64_t size, Object **ret, uint64_t *offset) { +static int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) { int r; uint64_t p; Object *tail, *o; @@ -399,11 +405,10 @@ static int journal_file_append_object(JournalFile *f, uint64_t size, Object **re assert(ret); p = le64toh(f->header->tail_object_offset); - if (p == 0) p = le64toh(f->header->arena_offset); else { - r = journal_file_move_to_object(f, p, -1, &tail); + r = journal_file_move_to_object(f, -1, p, &tail); if (r < 0) return r; @@ -414,21 +419,17 @@ static int journal_file_append_object(JournalFile *f, uint64_t size, Object **re if (r < 0) return r; - r = journal_file_move_to(f, p, size, &t); + r = journal_file_move_to(f, type, p, size, &t); if (r < 0) return r; o = (Object*) t; zero(o->object); - o->object.type = htole64(OBJECT_UNUSED); - zero(o->object.reserved); + o->object.type = type; o->object.size = htole64(size); f->header->tail_object_offset = htole64(p); - if (f->header->head_object_offset == 0) - f->header->head_object_offset = htole64(p); - f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); *ret = o; @@ -437,135 +438,137 @@ static int journal_file_append_object(JournalFile *f, uint64_t size, Object **re return 0; } -static int journal_file_setup_hash_table(JournalFile *f) { +static int journal_file_setup_data_hash_table(JournalFile *f) { uint64_t s, p; Object *o; int r; assert(f); - s = DEFAULT_HASH_TABLE_SIZE; - r = journal_file_append_object(f, offsetof(Object, hash_table.table) + s, &o, &p); + s = DEFAULT_DATA_HASH_TABLE_SIZE; + r = journal_file_append_object(f, + OBJECT_DATA_HASH_TABLE, + offsetof(Object, hash_table.items) + s, + &o, &p); if (r < 0) return r; - o->object.type = htole64(OBJECT_HASH_TABLE); - memset(o->hash_table.table, 0, s); + memset(o->hash_table.items, 0, s); - f->header->hash_table_offset = htole64(p + offsetof(Object, hash_table.table)); - f->header->hash_table_size = htole64(s); + f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); + f->header->data_hash_table_size = htole64(s); return 0; } -static int journal_file_setup_bisect_table(JournalFile *f) { +static int journal_file_setup_field_hash_table(JournalFile *f) { uint64_t s, p; Object *o; int r; assert(f); - s = DEFAULT_BISECT_TABLE_SIZE; - r = journal_file_append_object(f, offsetof(Object, bisect_table.table) + s, &o, &p); + s = DEFAULT_FIELD_HASH_TABLE_SIZE; + r = journal_file_append_object(f, + OBJECT_FIELD_HASH_TABLE, + offsetof(Object, hash_table.items) + s, + &o, &p); if (r < 0) return r; - o->object.type = htole64(OBJECT_BISECT_TABLE); - memset(o->bisect_table.table, 0, s); + memset(o->hash_table.items, 0, s); - f->header->bisect_table_offset = htole64(p + offsetof(Object, bisect_table.table)); - f->header->bisect_table_size = htole64(s); + f->header->field_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); + f->header->field_hash_table_size = htole64(s); return 0; } -static int journal_file_map_hash_table(JournalFile *f) { +static int journal_file_map_data_hash_table(JournalFile *f) { uint64_t s, p; void *t; int r; assert(f); - p = le64toh(f->header->hash_table_offset); - s = le64toh(f->header->hash_table_size); + p = le64toh(f->header->data_hash_table_offset); + s = le64toh(f->header->data_hash_table_size); - r = journal_file_map(f, - p, s, - &f->hash_table_window, NULL, &f->hash_table_window_size, - &t); + r = journal_file_move_to(f, + WINDOW_DATA_HASH_TABLE, + p, s, + &t); if (r < 0) return r; - f->hash_table = t; + f->data_hash_table = t; return 0; } -static int journal_file_map_bisect_table(JournalFile *f) { +static int journal_file_map_field_hash_table(JournalFile *f) { uint64_t s, p; void *t; int r; assert(f); - p = le64toh(f->header->bisect_table_offset); - s = le64toh(f->header->bisect_table_size); - - r = journal_file_map(f, - p, s, - &f->bisect_table_window, NULL, &f->bisect_table_window_size, - &t); + p = le64toh(f->header->field_hash_table_offset); + s = le64toh(f->header->field_hash_table_size); + r = journal_file_move_to(f, + WINDOW_FIELD_HASH_TABLE, + p, s, + &t); if (r < 0) return r; - f->bisect_table = t; + f->field_hash_table = t; return 0; } -static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, uint64_t hash_index) { - uint64_t p; +static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, uint64_t hash) { + uint64_t p, h; int r; assert(f); assert(o); assert(offset > 0); - assert(o->object.type == htole64(OBJECT_DATA)); + assert(o->object.type == OBJECT_DATA); - o->data.head_entry_offset = o->data.tail_entry_offset = 0; - o->data.next_hash_offset = 0; + o->data.next_hash_offset = o->data.next_field_offset = 0; + o->data.entry_offset = o->data.entry_array_offset = 0; + o->data.n_entries = 0; - p = le64toh(f->hash_table[hash_index].tail_hash_offset); + h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)); + p = le64toh(f->data_hash_table[h].head_hash_offset); if (p == 0) { /* Only entry in the hash table is easy */ - - o->data.prev_hash_offset = 0; - f->hash_table[hash_index].head_hash_offset = htole64(offset); + f->data_hash_table[h].head_hash_offset = htole64(offset); } else { - o->data.prev_hash_offset = htole64(p); - /* Temporarily move back to the previous data object, * to patch in pointer */ - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; - o->data.next_hash_offset = offset; + o->data.next_hash_offset = htole64(offset); - r = journal_file_move_to_object(f, offset, OBJECT_DATA, &o); + r = journal_file_move_to_object(f, OBJECT_DATA, offset, &o); if (r < 0) return r; } - f->hash_table[hash_index].tail_hash_offset = htole64(offset); + f->data_hash_table[h].tail_hash_offset = htole64(offset); return 0; } -static int journal_file_append_data(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { - uint64_t hash, h, p, np; - uint64_t osize; - Object *o; +int journal_file_find_data_object_with_hash( + JournalFile *f, + const void *data, uint64_t size, uint64_t hash, + Object **ret, uint64_t *offset) { + uint64_t p, osize, h; int r; assert(f); @@ -573,14 +576,13 @@ static int journal_file_append_data(JournalFile *f, const void *data, uint64_t s osize = offsetof(Object, data.payload) + size; - hash = hash64(data, size); - h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); - p = le64toh(f->hash_table[h].head_hash_offset); + h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)); + p = le64toh(f->data_hash_table[h].head_hash_offset); - while (p != 0) { - /* Look for this data object in the hash table */ + while (p > 0) { + Object *o; - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; @@ -596,21 +598,66 @@ static int journal_file_append_data(JournalFile *f, const void *data, uint64_t s if (offset) *offset = p; - return 0; + return 1; } p = le64toh(o->data.next_hash_offset); } - r = journal_file_append_object(f, osize, &o, &np); + return 0; +} + +int journal_file_find_data_object( + JournalFile *f, + const void *data, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash; + + assert(f); + assert(data || size == 0); + + hash = hash64(data, size); + + return journal_file_find_data_object_with_hash(f, + data, size, hash, + ret, offset); +} + +static int journal_file_append_data(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) { + uint64_t hash, p; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(data || size == 0); + + hash = hash64(data, size); + + r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p); + if (r < 0) + return r; + else if (r > 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; + } + + osize = offsetof(Object, data.payload) + size; + r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p); if (r < 0) return r; - o->object.type = htole64(OBJECT_DATA); o->data.hash = htole64(hash); memcpy(o->data.payload, data, size); - r = journal_file_link_data(f, o, np, h); + r = journal_file_link_data(f, o, p, hash); if (r < 0) return r; @@ -618,7 +665,7 @@ static int journal_file_append_data(JournalFile *f, const void *data, uint64_t s *ret = o; if (offset) - *offset = np; + *offset = p; return 0; } @@ -630,92 +677,154 @@ uint64_t journal_file_entry_n_items(Object *o) { return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); } -static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { - uint64_t p, q; +static uint64_t journal_file_entry_array_n_items(Object *o) { + assert(o); + assert(o->object.type == htole64(OBJECT_ENTRY_ARRAY)); + + return (le64toh(o->object.size) - offsetof(Object, entry_array.items)) / sizeof(uint64_t); +} + +static int link_entry_into_array(JournalFile *f, + uint64_t *first, + uint64_t *idx, + uint64_t p) { int r; + uint64_t n = 0, ap = 0, q, i, a, hidx; + Object *o; + assert(f); - assert(o); - assert(offset > 0); + assert(first); + assert(idx); + assert(p > 0); - p = le64toh(o->entry.items[i].object_offset); - if (p == 0) - return -EINVAL; + a = le64toh(*first); + i = hidx = le64toh(*idx); + while (a > 0) { + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; - o->entry.items[i].next_entry_offset = 0; + n = journal_file_entry_array_n_items(o); + if (i < n) { + o->entry_array.items[i] = htole64(p); + *idx = htole64(hidx + 1); + return 0; + } - /* Move to the data object */ - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + i -= n; + ap = a; + a = le64toh(o->entry_array.next_entry_array_offset); + } + + if (hidx > n) + n = (hidx+1) * 2; + else + n = n * 2; + + if (n < 4) + n = 4; + + r = journal_file_append_object(f, OBJECT_ENTRY_ARRAY, + offsetof(Object, entry_array.items) + n * sizeof(uint64_t), + &o, &q); if (r < 0) return r; - q = le64toh(o->data.tail_entry_offset); - o->data.tail_entry_offset = htole64(offset); + o->entry_array.items[i] = htole64(p); - if (q == 0) - o->data.head_entry_offset = htole64(offset); + if (ap == 0) + *first = q; else { - uint64_t n, j; - - /* Move to previous entry */ - r = journal_file_move_to_object(f, q, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o); if (r < 0) return r; - n = journal_file_entry_n_items(o); - for (j = 0; j < n; j++) - if (le64toh(o->entry.items[j].object_offset) == p) - break; + o->entry_array.next_entry_array_offset = htole64(q); + } - if (j >= n) - return -EBADMSG; + *idx = htole64(hidx + 1); + + return 0; +} - o->entry.items[j].next_entry_offset = offset; +static int link_entry_into_array_plus_one(JournalFile *f, + uint64_t *extra, + uint64_t *first, + uint64_t *idx, + uint64_t p) { + + int r; + + assert(f); + assert(extra); + assert(first); + assert(idx); + assert(p > 0); + + if (*idx == 0) + *extra = htole64(p); + else { + uint64_t i; + + i = le64toh(*idx) - 1; + r = link_entry_into_array(f, first, &i, p); + if (r < 0) + return r; } - /* Move back to original entry */ - r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); + *idx = htole64(le64toh(*idx) + 1); + return 0; +} + +static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { + uint64_t p; + int r; + assert(f); + assert(o); + assert(offset > 0); + + p = le64toh(o->entry.items[i].object_offset); + if (p == 0) + return -EINVAL; + + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; - o->entry.items[i].prev_entry_offset = q; - return 0; + return link_entry_into_array_plus_one(f, + &o->data.entry_offset, + &o->data.entry_array_offset, + &o->data.n_entries, + offset); } static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { - uint64_t p, i, n, k, a, b; + uint64_t n, i; int r; assert(f); assert(o); assert(offset > 0); - assert(o->object.type == htole64(OBJECT_ENTRY)); + assert(o->object.type == OBJECT_ENTRY); /* Link up the entry itself */ - p = le64toh(f->header->tail_entry_offset); + r = link_entry_into_array(f, + &f->header->entry_array_offset, + &f->header->n_entries, + offset); + if (r < 0) + return r; - o->entry.prev_entry_offset = f->header->tail_entry_offset; - o->entry.next_entry_offset = 0; + log_error("%s %lu", f->path, (unsigned long) f->header->n_entries); - if (p == 0) { - f->header->head_entry_offset = htole64(offset); + if (f->header->head_entry_realtime == 0) f->header->head_entry_realtime = o->entry.realtime; - } else { - /* Temporarily move back to the previous entry, to - * patch in pointer */ - - r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); - if (r < 0) - return r; - - o->entry.next_entry_offset = htole64(offset); - r = journal_file_move_to_object(f, offset, OBJECT_ENTRY, &o); - if (r < 0) - return r; - } - - f->header->tail_entry_offset = htole64(offset); f->header->tail_entry_realtime = o->entry.realtime; + f->header->tail_entry_monotonic = o->entry.monotonic; + + f->tail_entry_monotonic_valid = true; /* Link up the items */ n = journal_file_entry_n_items(o); @@ -725,18 +834,6 @@ static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { return r; } - /* Link up the entry in the bisect table */ - n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); - k = le64toh(f->header->arena_max_size) / n; - - a = (le64toh(f->header->last_bisect_offset) + k - 1) / k; - b = offset / k; - - for (; a <= b; a++) - f->bisect_table[a] = htole64(offset); - - f->header->last_bisect_offset = htole64(offset + le64toh(o->object.size)); - return 0; } @@ -745,7 +842,7 @@ static int journal_file_append_entry_internal( const dual_timestamp *ts, uint64_t xor_hash, const EntryItem items[], unsigned n_items, - uint64_t *seqno, + uint64_t *seqnum, Object **ret, uint64_t *offset) { uint64_t np; uint64_t osize; @@ -754,18 +851,18 @@ static int journal_file_append_entry_internal( assert(f); assert(items || n_items == 0); + assert(ts); osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem)); - r = journal_file_append_object(f, osize, &o, &np); + r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np); if (r < 0) return r; - o->object.type = htole64(OBJECT_ENTRY); - o->entry.seqnum = htole64(journal_file_seqnum(f, seqno)); + o->entry.seqnum = htole64(journal_file_seqnum(f, seqnum)); memcpy(o->entry.items, items, n_items * sizeof(EntryItem)); - o->entry.realtime = htole64(ts ? ts->realtime : now(CLOCK_REALTIME)); - o->entry.monotonic = htole64(ts ? ts->monotonic : now(CLOCK_MONOTONIC)); + o->entry.realtime = htole64(ts->realtime); + o->entry.monotonic = htole64(ts->monotonic); o->entry.xor_hash = htole64(xor_hash); o->entry.boot_id = f->header->boot_id; @@ -782,15 +879,31 @@ static int journal_file_append_entry_internal( return 0; } -int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset) { +int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) { unsigned i; EntryItem *items; int r; uint64_t xor_hash = 0; + struct dual_timestamp _ts; assert(f); assert(iovec || n_iovec == 0); + if (!f->writable) + return -EPERM; + + if (!ts) { + dual_timestamp_get(&_ts); + ts = &_ts; + } + + if (f->tail_entry_monotonic_valid && + ts->monotonic < le64toh(f->header->tail_entry_monotonic)) + return -EINVAL; + + if (ts->realtime < le64toh(f->header->tail_entry_realtime)) + return -EINVAL; + items = new(EntryItem, n_iovec); if (!items) return -ENOMEM; @@ -808,7 +921,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st items[i].hash = o->data.hash; } - r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqno, ret, offset); + r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset); finish: free(items); @@ -816,198 +929,590 @@ finish: return r; } -int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset) { +static int generic_array_get(JournalFile *f, + uint64_t first, + uint64_t i, + Object **ret, uint64_t *offset) { + Object *o; - uint64_t lower, upper, p, n, k; + uint64_t p, a; int r; assert(f); - n = le64toh(f->header->bisect_table_size) / sizeof(uint64_t); - k = le64toh(f->header->arena_max_size) / n; + a = first; + while (a > 0) { + uint64_t n; - lower = 0; - upper = le64toh(f->header->last_bisect_offset)/k+1; - - while (lower < upper) { - k = (upper + lower) / 2; - p = le64toh(f->bisect_table[k]); + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; - if (p == 0) { - upper = k; - continue; + n = journal_file_entry_array_n_items(o); + if (i < n) { + p = le64toh(o->entry_array.items[i]); + break; } - r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + i -= n; + a = le64toh(o->entry_array.next_entry_array_offset); + } + + if (a <= 0 || p <= 0) + return 0; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; +} + +static int generic_array_get_plus_one(JournalFile *f, + uint64_t extra, + uint64_t first, + uint64_t i, + Object **ret, uint64_t *offset) { + + Object *o; + + assert(f); + + if (i == 0) { + int r; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); if (r < 0) return r; - if (o->entry.seqnum == seqnum) { - if (ret) - *ret = o; + if (ret) + *ret = o; - if (offset) - *offset = p; + if (offset) + *offset = extra; - return 1; - } else if (seqnum < o->entry.seqnum) - upper = k; - else if (seqnum > o->entry.seqnum) - lower = k+1; + return 1; } - assert(lower == upper); + return generic_array_get(f, first, i-1, ret, offset); +} - if (lower <= 0) - return 0; +enum { + TEST_FOUND, + TEST_LEFT, + TEST_RIGHT +}; - /* The object we are looking for is between - * bisect_table[lower-1] and bisect_table[lower] */ +static int generic_array_bisect(JournalFile *f, + uint64_t first, + uint64_t n, + uint64_t needle, + int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), + direction_t direction, + Object **ret, + uint64_t *offset, + uint64_t *idx) { + + uint64_t a, p, t = 0, i = 0, last_p = 0; + bool subtract_one = false; + Object *o, *array = NULL; + int r; - p = le64toh(f->bisect_table[lower-1]); + assert(f); + assert(test_object); - for (;;) { - r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); + a = first; + while (a > 0) { + uint64_t left, right, k, lp; + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array); if (r < 0) return r; - if (o->entry.seqnum == seqnum) { - if (ret) - *ret = o; + k = journal_file_entry_array_n_items(array); + right = MIN(k, n); + if (right <= 0) + return 0; - if (offset) - *offset = p; + i = right - 1; + lp = p = le64toh(array->entry_array.items[i]); + if (p <= 0) + return -EBADMSG; - return 1; + r = test_object(f, p, needle); + if (r < 0) + return r; - } if (seqnum < o->entry.seqnum) - return 0; + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) { + left = 0; + right -= 1; + for (;;) { + if (left == right) { + if (direction == DIRECTION_UP) + subtract_one = true; + + i = left; + goto found; + } + + assert(left < right); + + i = (left + right) / 2; + p = le64toh(array->entry_array.items[i]); + if (p <= 0) + return -EBADMSG; + + r = test_object(f, p, needle); + if (r < 0) + return r; - if (o->entry.next_entry_offset == 0) + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) + right = i; + else + left = i + 1; + } + } + + if (k > n) return 0; - p = le64toh(o->entry.next_entry_offset); + last_p = lp; + + n -= k; + t += k; + a = le64toh(array->entry_array.next_entry_array_offset); } return 0; + +found: + if (subtract_one && t == 0 && i == 0) + return 0; + + if (subtract_one && i == 0) + p = last_p; + else if (subtract_one) + p = le64toh(array->entry_array.items[i-1]); + else + p = le64toh(array->entry_array.items[i]); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + if (idx) + *idx = t + i - (subtract_one ? 1 : 0); + + return 1; } -int journal_file_next_entry(JournalFile *f, Object *o, direction_t direction, Object **ret, uint64_t *offset) { - uint64_t np; +static int generic_array_bisect_plus_one(JournalFile *f, + uint64_t extra, + uint64_t first, + uint64_t n, + uint64_t needle, + int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), + direction_t direction, + Object **ret, + uint64_t *offset, + uint64_t *idx) { + int r; assert(f); + assert(test_object); - if (!o) - np = le64toh(direction == DIRECTION_DOWN ? - f->header->head_entry_offset : - f->header->tail_entry_offset); - else { - if (le64toh(o->object.type) != OBJECT_ENTRY) - return -EINVAL; + if (n <= 0) + return 0; - np = le64toh(direction == DIRECTION_DOWN ? - o->entry.next_entry_offset : - o->entry.prev_entry_offset); - } + /* This bisects the array in object 'first', but first checks + * an extra */ + + r = test_object(f, extra, needle); + if (r < 0) + return r; + else if (r == TEST_FOUND) { + Object *o; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; - if (np == 0) + if (offset) + *offset = extra; + } else if (r == TEST_RIGHT) return 0; - r = journal_file_move_to_object(f, np, OBJECT_ENTRY, &o); + r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx); + + if (r > 0) + (*idx) ++; + + return r; +} + +static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; - if (ret) - *ret = o; + if (le64toh(o->entry.seqnum) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.seqnum) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} - if (offset) - *offset = np; +int journal_file_move_to_entry_by_seqnum( + JournalFile *f, + uint64_t seqnum, + direction_t direction, + Object **ret, + uint64_t *offset) { + + return generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + seqnum, + test_object_seqnum, + direction, + ret, offset, NULL); +} - return 1; +static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (le64toh(o->entry.realtime) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.realtime) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; } -int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) { - uint64_t np; +int journal_file_move_to_entry_by_realtime( + JournalFile *f, + uint64_t realtime, + direction_t direction, + Object **ret, + uint64_t *offset) { + + return generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + realtime, + test_object_realtime, + direction, + ret, offset, NULL); +} + +static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (le64toh(o->entry.monotonic) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.monotonic) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +int journal_file_move_to_entry_by_monotonic( + JournalFile *f, + sd_id128_t boot_id, + uint64_t monotonic, + direction_t direction, + Object **ret, + uint64_t *offset) { + + char t[8+32+1] = "_BOOT_ID="; + Object *o; + int r; + + sd_id128_to_string(boot_id, t + 8); + + r = journal_file_find_data_object(f, t, strlen(t), &o, NULL); + if (r < 0) + return r; + else if (r == 0) + return -ENOENT; + + return generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + monotonic, + test_object_monotonic, + direction, + ret, offset, NULL); +} + +static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) { + assert(f); + assert(p > 0); + + if (p == needle) + return TEST_FOUND; + else if (p < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +int journal_file_next_entry( + JournalFile *f, + Object *o, uint64_t p, + direction_t direction, + Object **ret, uint64_t *offset) { + + uint64_t i, n; int r; assert(f); + assert(p > 0 || !o); + + n = le64toh(f->header->n_entries); + if (n <= 0) + return 0; if (!o) - np = le64toh(f->header->tail_entry_offset); + i = direction == DIRECTION_DOWN ? 0 : n - 1; else { - if (le64toh(o->object.type) != OBJECT_ENTRY) + if (o->object.type != OBJECT_ENTRY) return -EINVAL; - np = le64toh(o->entry.prev_entry_offset); + r = generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + p, + test_object_offset, + DIRECTION_DOWN, + NULL, NULL, + &i); + if (r <= 0) + return r; + + if (direction == DIRECTION_DOWN) { + if (i >= n - 1) + return 0; + + i++; + } else { + if (i <= 0) + return 0; + + i--; + } } - if (np == 0) - return 0; + /* And jump to it */ + return generic_array_get(f, + le64toh(f->header->entry_array_offset), + i, + ret, offset); +} - r = journal_file_move_to_object(f, np, OBJECT_ENTRY, &o); - if (r < 0) +int journal_file_skip_entry( + JournalFile *f, + Object *o, uint64_t p, + int64_t skip, + Object **ret, uint64_t *offset) { + + uint64_t i, n; + int r; + + assert(f); + assert(o); + assert(p > 0); + + if (o->object.type != OBJECT_ENTRY) + return -EINVAL; + + r = generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + p, + test_object_offset, + DIRECTION_DOWN, + NULL, NULL, + &i); + if (r <= 0) return r; - if (ret) - *ret = o; + /* Calculate new index */ + if (skip < 0) { + if ((uint64_t) -skip >= i) + i = 0; + else + i = i - (uint64_t) -skip; + } else + i += (uint64_t) skip; - if (offset) - *offset = np; + n = le64toh(f->header->n_entries); + if (n <= 0) + return -EBADMSG; - return 1; + if (i >= n) + i = n-1; + + return generic_array_get(f, + le64toh(f->header->entry_array_offset), + i, + ret, offset); } -int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, direction_t direction, Object **ret, uint64_t *offset) { - uint64_t p, osize, hash, h; +int journal_file_next_entry_for_data( + JournalFile *f, + Object *o, uint64_t p, + uint64_t data_offset, + direction_t direction, + Object **ret, uint64_t *offset) { + + uint64_t n, i; int r; + Object *d; assert(f); - assert(data || size == 0); + assert(p > 0 || !o); - osize = offsetof(Object, data.payload) + size; + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r <= 0) + return r; - hash = hash64(data, size); - h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem)); - p = le64toh(f->hash_table[h].head_hash_offset); + n = le64toh(d->data.n_entries); + if (n <= 0) + return n; - while (p != 0) { - Object *o; + if (!o) + i = direction == DIRECTION_DOWN ? 0 : n - 1; + else { + if (o->object.type != OBJECT_ENTRY) + return -EINVAL; - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); - if (r < 0) + r = generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + p, + test_object_offset, + DIRECTION_DOWN, + NULL, NULL, + &i); + + if (r <= 0) return r; - if (le64toh(o->object.size) == osize && - memcmp(o->data.payload, data, size) == 0) { + if (direction == DIRECTION_DOWN) { + if (i >= n - 1) + return 0; - if (le64toh(o->data.hash) != hash) - return -EBADMSG; + i++; + } else { + if (i <= 0) + return 0; - p = le64toh(direction == DIRECTION_DOWN ? - o->data.head_entry_offset : - o->data.tail_entry_offset); + i--; + } - if (p == 0) - return 0; + } - r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o); - if (r < 0) - return r; + return generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, offset); +} - if (ret) - *ret = o; +int journal_file_move_to_entry_by_seqnum_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t seqnum, + direction_t direction, + Object **ret, uint64_t *offset) { - if (offset) - *offset = p; + Object *d; + int r; - return 1; - } + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r <= 0) + return r; - p = le64toh(o->data.next_hash_offset); - } + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + seqnum, + test_object_seqnum, + direction, + ret, offset, NULL); +} - return 0; +int journal_file_move_to_entry_by_realtime_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t realtime, + direction_t direction, + Object **ret, uint64_t *offset) { + + Object *d; + int r; + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r <= 0) + return r; + + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + realtime, + test_object_realtime, + direction, + ret, offset, NULL); } void journal_file_dump(JournalFile *f) { @@ -1018,18 +1523,24 @@ void journal_file_dump(JournalFile *f) { assert(f); - printf("File ID: %s\n" + printf("File Path: %s\n" + "File ID: %s\n" "Machine ID: %s\n" "Boot ID: %s\n" - "Arena size: %llu\n", + "Arena size: %llu\n" + "Objects: %lu\n" + "Entries: %lu\n", + f->path, sd_id128_to_string(f->header->file_id, a), sd_id128_to_string(f->header->machine_id, b), sd_id128_to_string(f->header->boot_id, c), - (unsigned long long) le64toh(f->header->arena_size)); + (unsigned long long) le64toh(f->header->arena_size), + (unsigned long) le64toh(f->header->n_objects), + (unsigned long) le64toh(f->header->n_entries)); - p = le64toh(f->header->head_object_offset); + p = le64toh(f->header->arena_offset); while (p != 0) { - r = journal_file_move_to_object(f, p, -1, &o); + r = journal_file_move_to_object(f, -1, p, &o); if (r < 0) goto fail; @@ -1050,12 +1561,16 @@ void journal_file_dump(JournalFile *f) { (unsigned long long) le64toh(o->entry.realtime)); break; - case OBJECT_HASH_TABLE: - printf("Type: OBJECT_HASH_TABLE\n"); + case OBJECT_FIELD_HASH_TABLE: + printf("Type: OBJECT_FIELD_HASH_TABLE\n"); break; - case OBJECT_BISECT_TABLE: - printf("Type: OBJECT_BISECT_TABLE\n"); + case OBJECT_DATA_HASH_TABLE: + printf("Type: OBJECT_DATA_HASH_TABLE\n"); + break; + + case OBJECT_ENTRY_ARRAY: + printf("Type: OBJECT_ENTRY_ARRAY\n"); break; } @@ -1153,20 +1668,20 @@ int journal_file_open( if (newly_created) { - r = journal_file_setup_hash_table(f); + r = journal_file_setup_field_hash_table(f); if (r < 0) goto fail; - r = journal_file_setup_bisect_table(f); + r = journal_file_setup_data_hash_table(f); if (r < 0) goto fail; } - r = journal_file_map_hash_table(f); + r = journal_file_map_field_hash_table(f); if (r < 0) goto fail; - r = journal_file_map_bisect_table(f); + r = journal_file_map_data_hash_table(f); if (r < 0) goto fail; @@ -1381,5 +1896,8 @@ finish: free(list); + if (d) + closedir(d); + return r; } diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 795a446dc8..664f917bb0 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -28,6 +28,23 @@ #include "util.h" #include "sd-id128.h" +typedef struct Window { + void *ptr; + uint64_t offset; + uint64_t size; +} Window; + +enum { + WINDOW_UNKNOWN = OBJECT_UNUSED, + WINDOW_DATA = OBJECT_DATA, + WINDOW_ENTRY = OBJECT_ENTRY, + WINDOW_DATA_HASH_TABLE = OBJECT_DATA_HASH_TABLE, + WINDOW_FIELD_HASH_TABLE = OBJECT_FIELD_HASH_TABLE, + WINDOW_ENTRY_ARRAY = OBJECT_ENTRY_ARRAY, + WINDOW_HEADER, + _WINDOW_MAX +}; + typedef struct JournalFile { int fd; char *path; @@ -36,20 +53,13 @@ typedef struct JournalFile { int flags; int prot; bool writable; + bool tail_entry_monotonic_valid; Header *header; + HashItem *data_hash_table; + HashItem *field_hash_table; - HashItem *hash_table; - void *hash_table_window; - uint64_t hash_table_window_size; - - uint64_t *bisect_table; - void *bisect_table_window; - uint64_t bisect_table_window_size; - - void *window; - uint64_t window_offset; - uint64_t window_size; + Window windows[_WINDOW_MAX]; uint64_t current_offset; } JournalFile; @@ -60,20 +70,28 @@ typedef enum direction { } direction_t; int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret); - void journal_file_close(JournalFile *j); -int journal_file_move_to_object(JournalFile *f, uint64_t offset, int type, Object **ret); +int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret); uint64_t journal_file_entry_n_items(Object *o); int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset); -int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset); +int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); -int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset); -int journal_file_next_entry(JournalFile *f, Object *o, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); void journal_file_dump(JournalFile *f); @@ -81,5 +99,4 @@ int journal_file_rotate(JournalFile **f); int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); - #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 3e5ee1af96..9220efdfec 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) { } } - SD_JOURNAL_FOREACH_BEGIN(j) { + SD_JOURNAL_FOREACH(j) { const void *data; size_t length; @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { free(cursor); sd_journal_get_realtime_usec(j, &realtime); - sd_journal_get_monotonic_usec(j, &monotonic); + sd_journal_get_monotonic_usec(j, &monotonic, NULL); printf("realtime: %llu\n" "monotonic: %llu\n", (unsigned long long) realtime, @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) { SD_JOURNAL_FOREACH_DATA(j, data, length) printf("\t%.*s\n", (int) length, (const char*) data); - } SD_JOURNAL_FOREACH_END(j); + } finish: if (j) diff --git a/src/journal/journald.c b/src/journal/journald.c index ede314a55f..89d8bee2a2 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -144,14 +144,14 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str *audit_session = NULL, *audit_loginuid = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *exe = NULL, *cgroup = NULL; - struct iovec iovec[16]; + struct iovec iovec[17]; unsigned n = 0; char idbuf[33]; sd_id128_t id; int r; char *t; int priority = LOG_USER | LOG_INFO; - uid_t loginuid = 0; + uid_t loginuid = 0, realuid = 0; JournalFile *f; parse_syslog_priority((char**) &buf, &priority); @@ -171,18 +171,20 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str uint32_t session; char *path; - if (asprintf(&pid, "PID=%lu", (unsigned long) ucred->pid) >= 0) + realuid = ucred->uid; + + if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0) IOVEC_SET_STRING(iovec[n++], pid); - if (asprintf(&uid, "UID=%lu", (unsigned long) ucred->uid) >= 0) + if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0) IOVEC_SET_STRING(iovec[n++], uid); - if (asprintf(&gid, "GID=%lu", (unsigned long) ucred->gid) >= 0) + if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0) IOVEC_SET_STRING(iovec[n++], gid); r = get_process_comm(ucred->pid, &t); if (r >= 0) { - comm = strappend("COMM=", t); + comm = strappend("_COMM=", t); if (comm) IOVEC_SET_STRING(iovec[n++], comm); free(t); @@ -190,7 +192,7 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str r = get_process_exe(ucred->pid, &t); if (r >= 0) { - exe = strappend("EXE=", t); + exe = strappend("_EXE=", t); if (comm) IOVEC_SET_STRING(iovec[n++], exe); free(t); @@ -198,7 +200,7 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t); if (r >= 0) { - cmdline = strappend("CMDLINE=", t); + cmdline = strappend("_CMDLINE=", t); if (cmdline) IOVEC_SET_STRING(iovec[n++], cmdline); free(t); @@ -206,17 +208,17 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str r = audit_session_from_pid(ucred->pid, &session); if (r >= 0) - if (asprintf(&audit_session, "AUDIT_SESSION=%lu", (unsigned long) session) >= 0) + if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) session) >= 0) IOVEC_SET_STRING(iovec[n++], audit_session); r = audit_loginuid_from_pid(ucred->pid, &loginuid); if (r >= 0) - if (asprintf(&audit_loginuid, "AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0) + if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0) IOVEC_SET_STRING(iovec[n++], audit_loginuid); r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, ucred->pid, &path); if (r >= 0) { - cgroup = strappend("SYSTEMD_CGROUP=", path); + cgroup = strappend("_SYSTEMD_CGROUP=", path); if (cgroup) IOVEC_SET_STRING(iovec[n++], cgroup); free(path); @@ -224,7 +226,7 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str } if (tv) { - if (asprintf(&source_time, "SOURCE_REALTIME_TIMESTAMP=%llu", + if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv)) >= 0) IOVEC_SET_STRING(iovec[n++], source_time); } @@ -234,23 +236,23 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str * anyway. However, we need this indexed, too. */ r = sd_id128_get_boot(&id); if (r >= 0) - if (asprintf(&boot_id, "BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0) + if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0) IOVEC_SET_STRING(iovec[n++], boot_id); r = sd_id128_get_machine(&id); if (r >= 0) - if (asprintf(&machine_id, "MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0) + if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0) IOVEC_SET_STRING(iovec[n++], machine_id); t = gethostname_malloc(); if (t) { - hostname = strappend("HOSTNAME=", t); + hostname = strappend("_HOSTNAME=", t); if (hostname) IOVEC_SET_STRING(iovec[n++], hostname); free(t); } - f = find_journal(s, loginuid); + f = find_journal(s, realuid == 0 ? 0 : loginuid); if (!f) log_warning("Dropping message, as we can't find a place to store the data."); else { diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 5d518a3870..85c57170d5 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -40,9 +40,34 @@ struct Match { LIST_FIELDS(Match, matches); }; +typedef enum location_type { + LOCATION_HEAD, + LOCATION_TAIL, + LOCATION_DISCRETE +} location_type_t; + +typedef struct Location { + location_type_t type; + + uint64_t seqnum; + sd_id128_t seqnum_id; + bool seqnum_set; + + uint64_t realtime; + bool realtime_set; + + uint64_t monotonic; + sd_id128_t boot_id; + bool monotonic_set; + + uint64_t xor_hash; + bool xor_hash_set; +} Location; + struct sd_journal { Hashmap *files; + Location current_location; JournalFile *current_file; uint64_t current_field; @@ -50,7 +75,7 @@ struct sd_journal { unsigned n_matches; }; -static void reset_location(sd_journal *j) { +static void detach_location(sd_journal *j) { Iterator i; JournalFile *f; @@ -63,8 +88,66 @@ static void reset_location(sd_journal *j) { f->current_offset = 0; } +static void reset_location(sd_journal *j) { + assert(j); + + detach_location(j); + zero(j->current_location); +} + +static void init_location(Location *l, JournalFile *f, Object *o) { + assert(l); + assert(f); + assert(o->object.type == OBJECT_ENTRY); + + l->type = LOCATION_DISCRETE; + l->seqnum = le64toh(o->entry.seqnum); + l->seqnum_id = f->header->seqnum_id; + l->realtime = le64toh(o->entry.realtime); + l->monotonic = le64toh(o->entry.monotonic); + l->boot_id = le64toh(o->entry.boot_id); + l->xor_hash = le64toh(o->entry.xor_hash); + + l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true; +} + +static void set_location(sd_journal *j, JournalFile *f, Object *o, uint64_t offset) { + assert(j); + assert(f); + assert(o); + + init_location(&j->current_location, f, o); + + j->current_file = f; + j->current_field = 0; + + f->current_offset = offset; +} + +static int same_field(const void *_a, size_t s, const void *_b, size_t t) { + const uint8_t *a = _a, *b = _b; + size_t j; + bool a_good = false, b_good = false, different = false; + + for (j = 0; j < s && j < t; j++) { + + if (a[j] == '=') + a_good = true; + if (b[j] == '=') + b_good = true; + if (a[j] != b[j]) + different = true; + + if (a_good && b_good) + return different ? 0 : 1; + } + + return -EINVAL; +} + int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { - Match *m; + Match *m, *after = NULL; + uint64_t le_hash; assert(j); @@ -73,6 +156,23 @@ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { assert(data); + le_hash = htole64(hash64(data, size)); + + LIST_FOREACH(matches, m, j->matches) { + int r; + + if (m->le_hash == le_hash && + m->size == size && + memcmp(m->data, data, size) == 0) + return 0; + + r = same_field(data, size, m->data, m->size); + if (r < 0) + return r; + else if (r > 0) + after = m; + } + m = new0(Match, 1); if (!m) return -ENOMEM; @@ -86,12 +186,14 @@ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { } memcpy(m->data, data, size); - m->le_hash = hash64(m->data, size); + m->le_hash = le_hash; - LIST_PREPEND(Match, matches, j->matches, m); + /* Matches for the same fields we order adjacent to each + * other */ + LIST_INSERT_AFTER(Match, matches, j->matches, after, m); j->n_matches ++; - reset_location(j); + detach_location(j); return 0; } @@ -109,14 +211,19 @@ void sd_journal_flush_matches(sd_journal *j) { j->n_matches = 0; - reset_location(j); + detach_location(j); } -static int compare_order(JournalFile *af, Object *ao, uint64_t ap, - JournalFile *bf, Object *bo, uint64_t bp) { +static int compare_order(JournalFile *af, Object *ao, + JournalFile *bf, Object *bo) { uint64_t a, b; + assert(af); + assert(ao); + assert(bf); + assert(bo); + /* We operate on two different files here, hence we can access * two objects at the same time, which we normally can't. * @@ -179,99 +286,302 @@ static int compare_order(JournalFile *af, Object *ao, uint64_t ap, return 0; } -static int move_to_next_with_matches(sd_journal *j, JournalFile *f, direction_t direction, Object **o, uint64_t *p) { +static int compare_with_location(JournalFile *af, Object *ao, Location *l) { + uint64_t a; + + assert(af); + assert(ao); + assert(l); + assert(l->type == LOCATION_DISCRETE); + + if (l->monotonic_set && + sd_id128_equal(ao->entry.boot_id, l->boot_id) && + l->realtime_set && + le64toh(ao->entry.realtime) == l->realtime && + l->xor_hash_set && + le64toh(ao->entry.xor_hash) == l->xor_hash) + return 0; + + if (l->seqnum_set && + sd_id128_equal(af->header->seqnum_id, l->seqnum_id)) { + + a = le64toh(ao->entry.seqnum); + + if (a < l->seqnum) + return -1; + if (a > l->seqnum) + return 1; + } + + if (l->monotonic_set && + sd_id128_equal(ao->entry.boot_id, l->boot_id)) { + + a = le64toh(ao->entry.monotonic); + + if (a < l->monotonic) + return -1; + if (a > l->monotonic) + return 1; + } + + if (l->realtime_set) { + + a = le64toh(ao->entry.realtime); + + if (a < l->realtime) + return -1; + if (a > l->realtime) + return 1; + } + + if (l->xor_hash_set) { + a = le64toh(ao->entry.xor_hash); + + if (a < l->xor_hash) + return -1; + if (a > l->xor_hash) + return 1; + } + + return 0; +} + +static int find_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { + Object *o = NULL; + uint64_t p = 0; int r; - uint64_t cp; - Object *c; assert(j); - assert(f); - assert(o); - assert(p); if (!j->matches) { - /* No matches is easy, just go on to the next entry */ + /* No matches is simple */ + + if (j->current_location.type == LOCATION_HEAD) + r = journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p); + else if (j->current_location.type == LOCATION_TAIL) + r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, &p); + else if (j->current_location.seqnum_set && + sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + r = journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, &o, &p); + else if (j->current_location.monotonic_set) + r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, &o, &p); + else if (j->current_location.realtime_set) + r = journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, &o, &p); + else + r = journal_file_next_entry(f, NULL, 0, direction, &o, &p); + + if (r <= 0) + return r; + + } else { + Match *m, *term_match = NULL; + Object *to = NULL; + uint64_t tp = 0; + + /* We have matches, first, let's jump to the monotonic + * position if we have any, since it implies a + * match. */ - if (f->current_offset > 0) { - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &c); - if (r < 0) + if (j->current_location.type == LOCATION_DISCRETE && + j->current_location.monotonic_set) { + + r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, &o, &p); + if (r <= 0) return r; - } else - c = NULL; + } + + LIST_FOREACH(matches, m, j->matches) { + Object *c, *d; + uint64_t cp, dp; + + r = journal_file_find_data_object_with_hash(f, m->data, m->size, m->le_hash, &d, &dp); + if (r <= 0) + return r; + + if (j->current_location.type == LOCATION_HEAD) + r = journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, &c, &cp); + else if (j->current_location.type == LOCATION_TAIL) + r = journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, &c, &cp); + else if (j->current_location.seqnum_set && + sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + r = journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, &c, &cp); + else if (j->current_location.realtime_set) + r = journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, &c, &cp); + else + r = journal_file_next_entry_for_data(f, NULL, 0, dp, direction, &c, &cp); + + if (!term_match) { + term_match = m; + + if (r > 0) { + to = c; + tp = cp; + } + } else if (same_field(term_match->data, term_match->size, m->data, m->size)) { + + /* Same field as previous match... */ + if (r > 0) { + + /* Find the earliest of the OR matches */ + + if (!to || + (direction == DIRECTION_DOWN && cp < tp) || + (direction == DIRECTION_UP && cp > tp)) { + to = c; + tp = tp; + } + + } - return journal_file_next_entry(f, c, direction, o, p); + } else { + + /* Previous term is finished, did anything match? */ + if (!to) + return 0; + + /* Find the last of the AND matches */ + if (!o || + (direction == DIRECTION_DOWN && tp > p) || + (direction == DIRECTION_UP && tp < p)) { + o = to; + p = tp; + } + + term_match = m; + + if (r > 0) { + to = c; + tp = cp; + } else { + to = NULL; + tp = 0; + } + } + } + + /* Last term is finished, did anything match? */ + if (!to) + return 0; + + if (!o || + (direction == DIRECTION_DOWN && tp > p) || + (direction == DIRECTION_UP && tp < p)) { + o = to; + p = tp; + } + + if (!o) + return 0; } - /* So there are matches we have to adhere to, let's find the - * first entry that matches all of them */ + if (ret) + *ret = o; - if (f->current_offset > 0) - cp = f->current_offset; - else { - r = journal_file_find_first_entry(f, j->matches->data, j->matches->size, direction, &c, &cp); + if (offset) + *offset = p; + + return 1; +} + +static int next_with_matches(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { + int r; + uint64_t cp; + Object *c; + + assert(j); + assert(f); + assert(ret); + assert(offset); + + c = *ret; + cp = *offset; + + if (!j->matches) { + /* No matches is easy */ + + r = journal_file_next_entry(f, c, cp, direction, &c, &cp); if (r <= 0) return r; - /* We can shortcut this if there's only one match */ - if (j->n_matches == 1) { - *o = c; - *p = cp; - return r; - } + if (ret) + *ret = c; + if (offset) + *offset = cp; + return 1; } + /* So there are matches we have to adhere to, let's find the + * first entry that matches all of them */ + for (;;) { uint64_t np, n; - bool found; - Match *m; - - r = journal_file_move_to_object(f, cp, OBJECT_ENTRY, &c); - if (r < 0) - return r; + bool found, term_result = false; + Match *m, *term_match = NULL; n = journal_file_entry_n_items(c); /* Make sure we don't match the entry we are starting * from. */ - found = f->current_offset != cp; + found = cp > *offset; np = 0; LIST_FOREACH(matches, m, j->matches) { uint64_t q, k; + /* Let's check if this is the beginning of a + * new term, i.e. has a different field prefix + * as the preceeding match. */ + if (!term_match) { + term_match = m; + term_result = false; + } else if (!same_field(term_match->data, term_match->size, m->data, m->size)) { + if (!term_result) + found = false; + + term_match = m; + term_result = false; + } + for (k = 0; k < n; k++) if (c->entry.items[k].hash == m->le_hash) break; if (k >= n) { - /* Hmm, didn't find any field that matched, so ignore - * this match. Go on with next match */ - - found = false; + /* Hmm, didn't find any field that + * matched this rule, so ignore this + * match. Go on with next match */ continue; } + term_result = true; + /* Hmm, so, this field matched, let's remember * where we'd have to try next, in case the other * matches are not OK */ - if (direction == DIRECTION_DOWN) { - q = le64toh(c->entry.items[k].next_entry_offset); - - if (q > np) - np = q; - } else { - q = le64toh(c->entry.items[k].prev_entry_offset); + r = journal_file_next_entry_for_data(f, c, cp, le64toh(c->entry.items[k].object_offset), direction, NULL, &q); + if (r > 0) { - if (q != 0 && (np == 0 || q < np)) - np = q; + if (direction == DIRECTION_DOWN) { + if (q > np) + np = q; + } else { + if (np == 0 || q < np) + np = q; + } } } + /* Check the last term */ + if (term_match && term_result) + found = true; + /* Did this entry match against all matches? */ if (found) { - *o = c; - *p = cp; + if (ret) + *ret = c; + if (offset) + *offset = cp; return 1; } @@ -285,6 +595,62 @@ static int move_to_next_with_matches(sd_journal *j, JournalFile *f, direction_t } } +static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { + Object *c; + uint64_t cp; + int compare_value, r; + + assert(j); + assert(f); + + if (f->current_offset > 0) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &c); + if (r < 0) + return r; + + cp = f->current_offset; + + r = next_with_matches(j, f, direction, &c, &cp); + if (r <= 0) + return r; + + compare_value = 1; + } else { + r = find_location(j, f, direction, &c, &cp); + if (r <= 0) + return r; + + compare_value = 0; + } + + for (;;) { + bool found; + + if (j->current_location.type == LOCATION_DISCRETE) { + int k; + + k = compare_with_location(f, c, &j->current_location); + if (direction == DIRECTION_DOWN) + found = k >= compare_value; + else + found = k <= -compare_value; + } else + found = true; + + if (found) { + if (ret) + *ret = c; + if (offset) + *offset = cp; + return 1; + } + + r = next_with_matches(j, f, direction, &c, &cp); + if (r <= 0) + return r; + } +} + static int real_journal_next(sd_journal *j, direction_t direction) { JournalFile *f, *new_current = NULL; Iterator i; @@ -297,57 +663,88 @@ static int real_journal_next(sd_journal *j, direction_t direction) { HASHMAP_FOREACH(f, j->files, i) { Object *o; uint64_t p; + bool found; - r = move_to_next_with_matches(j, f, direction, &o, &p); + r = next_beyond_location(j, f, direction, &o, &p); if (r < 0) return r; else if (r == 0) continue; - if (!new_current || - compare_order(new_current, new_entry, new_offset, f, o, p) > 0) { + if (!new_current) + found = true; + else { + int k; + + k = compare_order(f, o, new_current, new_entry); + + if (direction == DIRECTION_DOWN) + found = k < 0; + else + found = k > 0; + } + + if (found) { new_current = f; new_entry = o; new_offset = p; } } - if (new_current) { - j->current_file = new_current; - j->current_file->current_offset = new_offset; - j->current_field = 0; + if (!new_current) + return 0; - /* Skip over any identical entries in the other files too */ + set_location(j, new_current, new_entry, new_offset); - HASHMAP_FOREACH(f, j->files, i) { - Object *o; - uint64_t p; + return 1; +} - if (j->current_file == f) - continue; +int sd_journal_next(sd_journal *j) { + return real_journal_next(j, DIRECTION_DOWN); +} - r = move_to_next_with_matches(j, f, direction, &o, &p); - if (r < 0) - return r; - else if (r == 0) - continue; +int sd_journal_previous(sd_journal *j) { + return real_journal_next(j, DIRECTION_UP); +} - if (compare_order(new_current, new_entry, new_offset, f, o, p) == 0) - f->current_offset = p; - } +int sd_journal_next_skip(sd_journal *j, uint64_t skip) { + int c = 0, r; - return 1; + assert(j); + + while (skip > 0) { + r = sd_journal_next(j); + if (r < 0) + return r; + + if (r == 0) + return c; + + skip--; + c++; } - return 0; + return c; } -int sd_journal_next(sd_journal *j) { - return real_journal_next(j, DIRECTION_DOWN); -} +int sd_journal_previous_skip(sd_journal *j, uint64_t skip) { + int c = 0, r; -int sd_journal_previous(sd_journal *j) { - return real_journal_next(j, DIRECTION_UP); + assert(j); + + while (skip > 0) { + r = sd_journal_previous(j); + if (r < 0) + return r; + + if (r == 0) + return c; + + skip--; + c++; + } + + return 1; } int sd_journal_get_cursor(sd_journal *j, char **cursor) { @@ -361,7 +758,7 @@ int sd_journal_get_cursor(sd_journal *j, char **cursor) { if (!j->current_file || j->current_file->current_offset <= 0) return -EADDRNOTAVAIL; - r = journal_file_move_to_object(j->current_file, j->current_file->current_offset, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o); if (r < 0) return r; @@ -380,8 +777,150 @@ int sd_journal_get_cursor(sd_journal *j, char **cursor) { return 1; } -int sd_journal_set_cursor(sd_journal *j, const char *cursor) { - return -EINVAL; +int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { + char *w; + size_t l; + char *state; + unsigned long long seqnum, monotonic, realtime, xor_hash; + bool + seqnum_id_set = false, + seqnum_set = false, + boot_id_set = false, + monotonic_set = false, + realtime_set = false, + xor_hash_set = false; + sd_id128_t seqnum_id, boot_id; + + assert(j); + assert(cursor); + + FOREACH_WORD_SEPARATOR(w, l, cursor, ";", state) { + char *item; + int k = 0; + + if (l < 2 || w[1] != '=') + return -EINVAL; + + item = strndup(w, l); + if (!item) + return -ENOMEM; + + switch (w[0]) { + + case 's': + seqnum_id_set = true; + k = sd_id128_from_string(w+2, &seqnum_id); + break; + + case 'i': + seqnum_set = true; + if (sscanf(w+2, "%llx", &seqnum) != 1) + k = -EINVAL; + break; + + case 'b': + boot_id_set = true; + k = sd_id128_from_string(w+2, &boot_id); + break; + + case 'm': + monotonic_set = true; + if (sscanf(w+2, "%llx", &monotonic) != 1) + k = -EINVAL; + break; + + case 't': + realtime_set = true; + if (sscanf(w+2, "%llx", &realtime) != 1) + k = -EINVAL; + break; + + case 'x': + xor_hash_set = true; + if (sscanf(w+2, "%llx", &xor_hash) != 1) + k = -EINVAL; + break; + } + + free(item); + + if (k < 0) + return k; + } + + if ((!seqnum_set || !seqnum_id_set) && + (!monotonic_set || !boot_id_set) && + !realtime_set) + return -EINVAL; + + reset_location(j); + + j->current_location.type = LOCATION_DISCRETE; + + if (realtime_set) { + j->current_location.realtime = (uint64_t) realtime; + j->current_location.realtime_set = true; + } + + if (seqnum_set && seqnum_id_set) { + j->current_location.seqnum = (uint64_t) seqnum; + j->current_location.seqnum_id = seqnum_id; + j->current_location.seqnum_set = true; + } + + if (monotonic_set && boot_id_set) { + j->current_location.monotonic = (uint64_t) monotonic; + j->current_location.boot_id = boot_id; + j->current_location.monotonic_set = true; + } + + if (xor_hash_set) { + j->current_location.xor_hash = (uint64_t) xor_hash; + j->current_location.xor_hash_set = true; + } + + return 0; +} + +int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) { + assert(j); + + reset_location(j); + j->current_location.type = LOCATION_DISCRETE; + j->current_location.boot_id = boot_id; + j->current_location.monotonic = usec; + j->current_location.monotonic_set = true; + + return 0; +} + +int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { + assert(j); + + reset_location(j); + j->current_location.type = LOCATION_DISCRETE; + j->current_location.realtime = usec; + j->current_location.realtime_set = true; + + return 0; +} + +int sd_journal_seek_head(sd_journal *j) { + assert(j); + + reset_location(j); + j->current_location.type = LOCATION_HEAD; + + return 0; +} + +int sd_journal_seek_tail(sd_journal *j) { + assert(j); + + reset_location(j); + j->current_location.type = LOCATION_TAIL; + + return 0; } static int add_file(sd_journal *j, const char *prefix, const char *dir, const char *filename) { @@ -411,6 +950,9 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch return r; } + journal_file_dump(f); + + r = hashmap_put(j->files, f->path, f); if (r < 0) { journal_file_close(f); @@ -557,20 +1099,20 @@ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { f = j->current_file; if (!f) - return 0; + return -EADDRNOTAVAIL; if (f->current_offset <= 0) - return 0; + return -EADDRNOTAVAIL; - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; *ret = le64toh(o->entry.realtime); - return 1; + return 0; } -int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret) { +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) { Object *o; JournalFile *f; int r; @@ -581,25 +1123,28 @@ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret) { f = j->current_file; if (!f) - return 0; + return -EADDRNOTAVAIL; if (f->current_offset <= 0) - return 0; + return -EADDRNOTAVAIL; - r = sd_id128_get_boot(&id); + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); - if (r < 0) - return r; + if (ret_boot_id) + *ret_boot_id = o->entry.boot_id; + else { + r = sd_id128_get_boot(&id); + if (r < 0) + return r; - if (!sd_id128_equal(id, o->entry.boot_id)) - return 0; + if (!sd_id128_equal(id, o->entry.boot_id)) + return -ENOENT; + } *ret = le64toh(o->entry.monotonic); - return 1; - + return 0; } int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) { @@ -619,12 +1164,12 @@ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, siz f = j->current_file; if (!f) - return 0; + return -EADDRNOTAVAIL; if (f->current_offset <= 0) - return 0; + return -EADDRNOTAVAIL; - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; @@ -632,16 +1177,16 @@ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, siz n = journal_file_entry_n_items(o); for (i = 0; i < n; i++) { - uint64_t p, l, h; + uint64_t p, l, le_hash; size_t t; p = le64toh(o->entry.items[i].object_offset); - h = o->entry.items[j->current_field].hash; - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + le_hash = o->entry.items[j->current_field].hash; + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; - if (h != o->data.hash) + if (le_hash != o->data.hash) return -EBADMSG; l = le64toh(o->object.size) - offsetof(Object, data.payload); @@ -658,23 +1203,23 @@ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, siz *data = o->data.payload; *size = t; - return 1; + return 0; } - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; } - return 0; + return -ENOENT; } int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { JournalFile *f; - uint64_t p, l, n, h; - size_t t; + uint64_t p, l, n, le_hash; int r; Object *o; + size_t t; assert(j); assert(data); @@ -682,12 +1227,12 @@ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { f = j->current_file; if (!f) - return 0; + return -EADDRNOTAVAIL; if (f->current_offset <= 0) - return 0; + return -EADDRNOTAVAIL; - r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o); + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); if (r < 0) return r; @@ -696,12 +1241,12 @@ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { return 0; p = le64toh(o->entry.items[j->current_field].object_offset); - h = o->entry.items[j->current_field].hash; - r = journal_file_move_to_object(f, p, OBJECT_DATA, &o); + le_hash = o->entry.items[j->current_field].hash; + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; - if (h != o->data.hash) + if (le_hash != o->data.hash) return -EBADMSG; l = le64toh(o->object.size) - offsetof(Object, data.payload); @@ -719,24 +1264,8 @@ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { return 1; } -void sd_journal_start_data(sd_journal *j) { +void sd_journal_restart_data(sd_journal *j) { assert(j); j->current_field = 0; } - -int sd_journal_seek_head(sd_journal *j) { - assert(j); - - reset_location(j); - - return real_journal_next(j, DIRECTION_DOWN); -} - -int sd_journal_seek_tail(sd_journal *j) { - assert(j); - - reset_location(j); - - return real_journal_next(j, DIRECTION_UP); -} diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 9978ca9ac0..8d7e314223 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -25,18 +25,22 @@ #include #include +#include "sd-id128.h" + /* TODO: * * - check LE/BE conversion for 8bit, 16bit, 32bit values - * - implement parallel traversal * - implement inotify usage on client * - implement audit gateway * - implement native gateway * - implement stdout gateway - * - extend hash table/bisect table as we go + * - extend hash tables table as we go * - accelerate looking for "all hostnames" and suchlike. * - throttling * - enforce limit on open journal files in journald and journalctl + * - cryptographic hash + * - fix space reservation logic + * - comm, argv can be manipulated, should it be _COMM=, _CMDLINE= or COMM=, CMDLINE=? */ typedef struct sd_journal sd_journal; @@ -47,59 +51,52 @@ void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); int sd_journal_next(sd_journal *j); +int sd_journal_previous_skip(sd_journal *j, uint64_t skip); +int sd_journal_next_skip(sd_journal *j, uint64_t skip); + int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); -int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret); +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); -void sd_journal_start_data(sd_journal *j); +void sd_journal_restart_data(sd_journal *j); int sd_journal_add_match(sd_journal *j, const void *data, size_t size); void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_tail(sd_journal *j); - -int sd_journal_seek_monotonic_usec(sd_journal *j, uint64_t usec); /* missing */ -int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); /* missing */ +int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec); +int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); +int sd_journal_seek_cursor(sd_journal *j, const char *cursor); int sd_journal_get_cursor(sd_journal *j, char **cursor); -int sd_journal_set_cursor(sd_journal *j, const char *cursor); /* missing */ -int sd_journal_unique_seek(sd_journal *j, const char *field); /* missing */ -int sd_journal_unique_enumerate(sd_journal *j, const void **data, size_t *l); /* missing */ - -int sd_journal_get_fd(sd_journal *j); /* missing */ +int sd_journal_query_unique(sd_journal *j, const char *field); /* missing */ +int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */ +void sd_journal_restart_unique(sd_journal *j); /* missing */ enum { SD_JOURNAL_NOP, SD_JOURNAL_APPEND, - SD_JOURNAL_DROP + SD_JOURNAL_INVALIDATE_ADD, + SD_JOURNAL_INVALIDATE_REMOVE }; +int sd_journal_get_fd(sd_journal *j); /* missing */ int sd_journal_process(sd_journal *j); /* missing */ -#define SD_JOURNAL_FOREACH_BEGIN(j) \ - if (sd_journal_seek_head(j) > 0) do { - -#define SD_JOURNAL_FOREACH_END(j) \ - } while (sd_journal_next(j) > 0) - -#define SD_JOURNAL_FOREACH_CONTINUE(j) \ - do { - -#define SD_JOURNAL_FOREACH_BACKWARDS_BEGIN(j) \ - if (sd_journal_seek_tail(j) > 0) do { - -#define SD_JOURNAL_FOREACH_BACKWARDS_END(j) \ - } while (sd_journal_previous(j) > 0) +#define SD_JOURNAL_FOREACH(j) \ + if (sd_journal_seek_head(j) >= 0) \ + while (sd_journal_next(j) > 0) \ -#define SD_JOURNAL_FOREACH_BACKWARDS_CONTINUE(j) \ - do { +#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ + if (sd_journal_seek_tail(j) >= 0) \ + while (sd_journal_previous(j) > 0) \ #define SD_JOURNAL_FOREACH_DATA(j, data, l) \ - for (sd_journal_start_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) + for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) -#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ - while (sd_journal_enumerate_unique_data((j), &(data), &(l)) > 0) +#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ + for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) #endif diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 93e2b4dab4..45ced12b46 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -31,6 +31,7 @@ int main(int argc, char *argv[]) { struct iovec iovec; static const char test[] = "test", test2[] = "test2"; Object *o; + uint64_t p; log_set_max_level(LOG_DEBUG); @@ -54,41 +55,55 @@ int main(int argc, char *argv[]) { journal_file_dump(f); - assert(journal_file_next_entry(f, NULL, DIRECTION_DOWN, &o, NULL) == 1); + assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1); assert(le64toh(o->entry.seqnum) == 1); - assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 1); + assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1); assert(le64toh(o->entry.seqnum) == 2); - assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 1); + assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 1); assert(le64toh(o->entry.seqnum) == 3); - assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 0); + assert(journal_file_next_entry(f, o, p, DIRECTION_DOWN, &o, &p) == 0); - assert(journal_file_find_first_entry(f, test, strlen(test), DIRECTION_DOWN, &o, NULL) == 1); + assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1); assert(le64toh(o->entry.seqnum) == 1); - assert(journal_file_find_first_entry(f, test, strlen(test), DIRECTION_UP, &o, NULL) == 1); + assert(journal_file_skip_entry(f, o, p, 2, &o, &p) == 1); assert(le64toh(o->entry.seqnum) == 3); - assert(journal_file_find_first_entry(f, test2, strlen(test2), DIRECTION_UP, &o, NULL) == 1); + assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1); + assert(le64toh(o->entry.seqnum) == 1); + + assert(journal_file_skip_entry(f, o, p, -2, &o, &p) == 1); + assert(le64toh(o->entry.seqnum) == 1); + + assert(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1); + assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); + assert(le64toh(o->entry.seqnum) == 1); + + assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); + assert(le64toh(o->entry.seqnum) == 3); + + assert(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1); + assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); assert(le64toh(o->entry.seqnum) == 2); - assert(journal_file_find_first_entry(f, test2, strlen(test2), DIRECTION_DOWN, &o, NULL) == 1); + assert(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); assert(le64toh(o->entry.seqnum) == 2); - assert(journal_file_find_first_entry(f, "quux", 4, DIRECTION_DOWN, &o, NULL) == 0); + assert(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0); - assert(journal_file_move_to_entry(f, 1, &o, NULL) == 1); + assert(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1); assert(le64toh(o->entry.seqnum) == 1); - assert(journal_file_move_to_entry(f, 3, &o, NULL) == 1); + assert(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1); assert(le64toh(o->entry.seqnum) == 3); - assert(journal_file_move_to_entry(f, 2, &o, NULL) == 1); + assert(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1); assert(le64toh(o->entry.seqnum) == 2); - assert(journal_file_move_to_entry(f, 10, &o, NULL) == 0); + assert(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0); journal_file_rotate(&f); journal_file_rotate(&f); diff --git a/src/journal/wjournal.c b/src/journal/wjournal.c deleted file mode 100644 index 3122aa054e..0000000000 --- a/src/journal/wjournal.c +++ /dev/null @@ -1,57 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include "wjournal.h" -#include "journal-def.h" - -struct WJournal { - int fd; - - Header *header; - HashItem *hash_table; - uint64_t *bisect_table; -}; - -int wjournal_open(const char *fn, WJournal **ret) { - assert(fn); - assert(ret); -} - -void wjournal_close(WJournal *j) { - assert(j); - - if (j->fd >= 0) - close_nointr_nofail(j->fd); - - if (j->header) { - munmap(j->header, PAGE_ALIGN(sizeof(Header))); - - } - - free(j); -} - -int wjournal_write_object_begin(WJournal *j, uint64_t type, uint64_t size, Object **ret); -int wjournal_write_object_finish(WJournal *j, Object *ret); - -int wjournal_write_field(WJournal *j, const char *buffer, uint64_t size, Object **ret); -int wjournal_write_entry(WJournal *j, const Field *fields, unsigned n_fields, Object **ret); -int wjournal_write_eof(WJournal *j); diff --git a/src/journal/wjournal.h b/src/journal/wjournal.h deleted file mode 100644 index b0250d0fe2..0000000000 --- a/src/journal/wjournal.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foojournalhfoo -#define foojournalhfoo - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include - -typedef struct WJournal WJournal; - -int wjournal_open(const char *fn, WJournal **ret); -void wjournal_close(WJournal *j); - -int wjournal_write_object_begin(WJournal *j, uint64_t type, uint64_t size, Object **ret); -int wjournal_write_object_finish(WJournal *j, Object *ret); - -int wjournal_write_field(WJournal *j, const char *buffer, uint64_t size, Object **ret); -int wjournal_write_entry(WJournal *j, const Field *fields, unsigned n_fields, Object **ret); -int wjournal_write_eof(WJournal *j); - -#endif -- cgit v1.2.3-54-g00ecf From 50f20cfdb0f127e415ab38c024d9ca7a3602f74b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Dec 2011 22:35:46 +0100 Subject: journal: implement inotify-based live logging logic --- src/journal/journal-file.c | 14 +++ src/journal/journalctl.c | 79 +++++++++---- src/journal/journald.c | 2 +- src/journal/sd-journal.c | 278 ++++++++++++++++++++++++++++++++++++++++++++- src/journal/sd-journal.h | 11 +- src/util.c | 2 +- 6 files changed, 352 insertions(+), 34 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 427631d30a..7626743248 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -879,6 +879,18 @@ static int journal_file_append_entry_internal( return 0; } +static void journal_file_post_change(JournalFile *f) { + assert(f); + + /* inotify() does not receive IN_MODIFY events from file + * accesses done via mmap(). After each access we hence + * trigger IN_MODIFY by truncating the journal file to its + * current size which triggers IN_MODIFY. */ + + if (ftruncate(f->fd, f->last_stat.st_size) < 0) + log_error("Failed to to truncate file to its own size: %m"); +} + int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqnum, Object **ret, uint64_t *offset) { unsigned i; EntryItem *items; @@ -923,6 +935,8 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st r = journal_file_append_entry_internal(f, ts, xor_hash, items, n_iovec, seqnum, ret, offset); + journal_file_post_change(f); + finish: free(items); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 9220efdfec..c947730441 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -26,12 +26,15 @@ #include #include #include +#include #include "sd-journal.h" #include "log.h" +static bool arg_follow = true; + int main(int argc, char *argv[]) { - int r, i; + int r, i, fd; sd_journal *j = NULL; log_set_max_level(LOG_DEBUG); @@ -54,32 +57,68 @@ int main(int argc, char *argv[]) { } } - SD_JOURNAL_FOREACH(j) { + fd = sd_journal_get_fd(j); + if (fd < 0) { + log_error("Failed to get wakeup fd: %s", strerror(-fd)); + goto finish; + } - const void *data; - size_t length; - char *cursor; - uint64_t realtime = 0, monotonic = 0; + r = sd_journal_seek_head(j); + if (r < 0) { + log_error("Failed to seek to head: %s", strerror(-r)); + goto finish; + } - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) { - log_error("Failed to get cursor: %s", strerror(-r)); - goto finish; + for (;;) { + struct pollfd pollfd; + + while (sd_journal_next(j) > 0) { + const void *data; + size_t length; + char *cursor; + uint64_t realtime = 0, monotonic = 0; + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + goto finish; + } + + printf("entry: %s\n", cursor); + free(cursor); + + sd_journal_get_realtime_usec(j, &realtime); + sd_journal_get_monotonic_usec(j, &monotonic, NULL); + printf("realtime: %llu\n" + "monotonic: %llu\n", + (unsigned long long) realtime, + (unsigned long long) monotonic); + + SD_JOURNAL_FOREACH_DATA(j, data, length) + printf("\t%.*s\n", (int) length, (const char*) data); } - printf("entry: %s\n", cursor); - free(cursor); + if (!arg_follow) + break; + + zero(pollfd); + pollfd.fd = fd; + pollfd.events = POLLIN; - sd_journal_get_realtime_usec(j, &realtime); - sd_journal_get_monotonic_usec(j, &monotonic, NULL); - printf("realtime: %llu\n" - "monotonic: %llu\n", - (unsigned long long) realtime, - (unsigned long long) monotonic); + if (poll(&pollfd, 1, -1) < 0) { + if (errno == EINTR) + break; - SD_JOURNAL_FOREACH_DATA(j, data, length) - printf("\t%.*s\n", (int) length, (const char*) data); + log_error("poll(): %m"); + r = -errno; + goto finish; + } + r = sd_journal_process(j); + if (r < 0) { + log_error("Failed to process: %s", strerror(-r)); + goto finish; + } } finish: diff --git a/src/journal/journald.c b/src/journal/journald.c index 630ead0053..c457d2786b 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -866,7 +866,7 @@ int main(int argc, char *argv[]) { sd_notify(false, "READY=1\n" "STATUS=Processing messages..."); -# + for (;;) { struct epoll_event event; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index bcfcbfb9e1..bd510be51c 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "sd-journal.h" #include "journal-def.h" @@ -73,6 +75,10 @@ struct sd_journal { JournalFile *current_file; uint64_t current_field; + int inotify_fd; + Hashmap *inotify_wd_dirs; + Hashmap *inotify_wd_roots; + LIST_HEAD(Match, matches); unsigned n_matches; }; @@ -934,11 +940,6 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch assert(prefix); assert(filename); - if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) { - log_debug("Too many open journal files, ignoring."); - return 0; - } - if (dir) fn = join(prefix, "/", dir, "/", filename, NULL); else @@ -947,6 +948,17 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch if (!fn) return -ENOMEM; + if (hashmap_get(j->files, fn)) { + free(fn); + return 0; + } + + if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) { + log_debug("Too many open journal files, not adding %s, ignoring.", fn); + free(fn); + return 0; + } + r = journal_file_open(fn, O_RDONLY, 0, NULL, &f); free(fn); @@ -965,6 +977,37 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch return r; } + log_debug("File %s got added.", f->path); + + return 0; +} + +static int remove_file(sd_journal *j, const char *prefix, const char *dir, const char *filename) { + char *fn; + JournalFile *f; + + assert(j); + assert(prefix); + assert(filename); + + if (dir) + fn = join(prefix, "/", dir, "/", filename, NULL); + else + fn = join(prefix, "/", filename, NULL); + + if (!fn) + return -ENOMEM; + + f = hashmap_get(j->files, fn); + free(fn); + + if (!f) + return 0; + + hashmap_remove(j->files, f->path); + journal_file_close(f); + + log_debug("File %s got removed.", f->path); return 0; } @@ -972,6 +1015,7 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dir) { char *fn; int r; DIR *d; + int wd; assert(j); assert(prefix); @@ -982,15 +1026,28 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dir) { return -ENOMEM; d = opendir(fn); - free(fn); if (!d) { + free(fn); if (errno == ENOENT) return 0; return -errno; } + wd = inotify_add_watch(j->inotify_fd, fn, + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT| + IN_DONT_FOLLOW|IN_ONLYDIR); + if (wd > 0) { + if (hashmap_put(j->inotify_wd_dirs, INT_TO_PTR(wd), fn) < 0) + inotify_rm_watch(j->inotify_fd, wd); + else + fn = NULL; + } + + free(fn); + for (;;) { struct dirent buf, *de; @@ -1008,9 +1065,65 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dir) { closedir(d); + log_debug("Directory %s/%s got added.", prefix, dir); + return 0; } +static void remove_directory_wd(sd_journal *j, int wd) { + char *p; + + assert(j); + assert(wd > 0); + + if (j->inotify_fd >= 0) + inotify_rm_watch(j->inotify_fd, wd); + + p = hashmap_remove(j->inotify_wd_dirs, INT_TO_PTR(wd)); + + if (p) { + log_debug("Directory %s got removed.", p); + free(p); + } +} + +static void add_root_wd(sd_journal *j, const char *p) { + int wd; + char *k; + + assert(j); + assert(p); + + wd = inotify_add_watch(j->inotify_fd, p, + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_DONT_FOLLOW|IN_ONLYDIR); + if (wd <= 0) + return; + + k = strdup(p); + if (!k || hashmap_put(j->inotify_wd_roots, INT_TO_PTR(wd), k) < 0) { + inotify_rm_watch(j->inotify_fd, wd); + free(k); + } +} + +static void remove_root_wd(sd_journal *j, int wd) { + char *p; + + assert(j); + assert(wd > 0); + + if (j->inotify_fd >= 0) + inotify_rm_watch(j->inotify_fd, wd); + + p = hashmap_remove(j->inotify_wd_roots, INT_TO_PTR(wd)); + + if (p) { + log_debug("Root %s got removed.", p); + free(p); + } +} + int sd_journal_open(sd_journal **ret) { sd_journal *j; const char *p; @@ -1025,12 +1138,26 @@ int sd_journal_open(sd_journal **ret) { if (!j) return -ENOMEM; + j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (j->inotify_fd < 0) { + r = -errno; + goto fail; + } + j->files = hashmap_new(string_hash_func, string_compare_func); if (!j->files) { r = -ENOMEM; goto fail; } + j->inotify_wd_dirs = hashmap_new(trivial_hash_func, trivial_compare_func); + j->inotify_wd_roots = hashmap_new(trivial_hash_func, trivial_compare_func); + + if (!j->inotify_wd_dirs || !j->inotify_wd_roots) { + r = -ENOMEM; + goto fail; + } + /* We ignore most errors here, since the idea is to only open * what's actually accessible, and ignore the rest. */ @@ -1044,6 +1171,8 @@ int sd_journal_open(sd_journal **ret) { continue; } + add_root_wd(j, p); + for (;;) { struct dirent buf, *de; sd_id128_t id; @@ -1081,6 +1210,24 @@ fail: void sd_journal_close(sd_journal *j) { assert(j); + if (j->inotify_wd_dirs) { + void *k; + + while ((k = hashmap_first_key(j->inotify_wd_dirs))) + remove_directory_wd(j, PTR_TO_INT(k)); + + hashmap_free(j->inotify_wd_dirs); + } + + if (j->inotify_wd_roots) { + void *k; + + while ((k = hashmap_first_key(j->inotify_wd_roots))) + remove_root_wd(j, PTR_TO_INT(k)); + + hashmap_free(j->inotify_wd_roots); + } + if (j->files) { JournalFile *f; @@ -1092,6 +1239,9 @@ void sd_journal_close(sd_journal *j) { sd_journal_flush_matches(j); + if (j->inotify_fd >= 0) + close_nointr_nofail(j->inotify_fd); + free(j); } @@ -1275,3 +1425,119 @@ void sd_journal_restart_data(sd_journal *j) { j->current_field = 0; } + +int sd_journal_get_fd(sd_journal *j) { + assert(j); + + return j->inotify_fd; +} + +static void process_inotify_event(sd_journal *j, struct inotify_event *e) { + char *p; + int r; + + assert(j); + assert(e); + + /* Is this a subdirectory we watch? */ + p = hashmap_get(j->inotify_wd_dirs, INT_TO_PTR(e->wd)); + if (p) { + + if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) { + + /* Event for a journal file */ + + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { + r = add_file(j, p, NULL, e->name); + if (r < 0) + log_debug("Failed to add file %s/%s: %s", p, e->name, strerror(-r)); + } else if (e->mask & (IN_DELETE|IN_UNMOUNT)) { + + r = remove_file(j, p, NULL, e->name); + if (r < 0) + log_debug("Failed to remove file %s/%s: %s", p, e->name, strerror(-r)); + } + + } else if (e->len == 0) { + + /* Event for the directory itself */ + + if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) + remove_directory_wd(j, e->wd); + } + + return; + } + + /* Must be the root directory then? */ + p = hashmap_get(j->inotify_wd_roots, INT_TO_PTR(e->wd)); + if (p) { + sd_id128_t id; + + if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) { + + /* Event for a journal file */ + + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { + r = add_file(j, p, NULL, e->name); + if (r < 0) + log_debug("Failed to add file %s/%s: %s", p, e->name, strerror(-r)); + } else if (e->mask & (IN_DELETE|IN_UNMOUNT)) { + + r = remove_file(j, p, NULL, e->name); + if (r < 0) + log_debug("Failed to remove file %s/%s: %s", p, e->name, strerror(-r)); + } + + } else if ((e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) { + + /* Event for subdirectory */ + + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { + + r = add_directory(j, p, e->name); + if (r < 0) + log_debug("Failed to add directory %s/%s: %s", p, e->name, strerror(-r)); + } + } + + return; + } + + if (e->mask & IN_IGNORED) + return; + + log_warning("Unknown inotify event."); +} + +int sd_journal_process(sd_journal *j) { + uint8_t buffer[sizeof(struct inotify_event) + FILENAME_MAX]; + + assert(j); + + for (;;) { + struct inotify_event *e; + ssize_t l; + + l = read(j->inotify_fd, buffer, sizeof(buffer)); + if (l < 0) { + if (errno == EINTR || errno == EAGAIN) + return 0; + + return -errno; + } + + e = (struct inotify_event*) buffer; + while (l > 0) { + size_t step; + + process_inotify_event(j, e); + + step = sizeof(struct inotify_event) + e->len; + assert(step <= (size_t) l); + + e = (struct inotify_event*) ((uint8_t*) e + step); + l -= step; + } + } +} diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 05a929d910..33e4b78855 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -32,7 +32,6 @@ /* TODO: * * - check LE/BE conversion for 8bit, 16bit, 32bit values - * - implement inotify usage on client * - implement audit gateway * - implement stdout gateway * - extend hash tables table as we go @@ -40,7 +39,7 @@ * - throttling * - cryptographic hash * - fix space reservation logic - * - comm, argv can be manipulated, should it be _COMM=, _CMDLINE= or COMM=, CMDLINE=? + * - compression */ /* Write to daemon */ @@ -92,16 +91,16 @@ enum { SD_JOURNAL_INVALIDATE_REMOVE }; -int sd_journal_get_fd(sd_journal *j); /* missing */ -int sd_journal_process(sd_journal *j); /* missing */ +int sd_journal_get_fd(sd_journal *j); +int sd_journal_process(sd_journal *j); #define SD_JOURNAL_FOREACH(j) \ if (sd_journal_seek_head(j) >= 0) \ - while (sd_journal_next(j) > 0) \ + while (sd_journal_next(j) > 0) #define SD_JOURNAL_FOREACH_BACKWARDS(j) \ if (sd_journal_seek_tail(j) >= 0) \ - while (sd_journal_previous(j) > 0) \ + while (sd_journal_previous(j) > 0) #define SD_JOURNAL_FOREACH_DATA(j, data, l) \ for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) diff --git a/src/util.c b/src/util.c index e5b5e53f7e..37942de534 100644 --- a/src/util.c +++ b/src/util.c @@ -2674,7 +2674,7 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst ssize_t l; struct inotify_event *e; - if ((l = read(notify, &inotify_buffer, sizeof(inotify_buffer))) < 0) { + if ((l = read(notify, inotify_buffer, sizeof(inotify_buffer))) < 0) { if (errno == EINTR) continue; -- cgit v1.2.3-54-g00ecf From 72f597065c60fbfca501a8d8c29e9a11cb740946 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Dec 2011 18:17:22 +0100 Subject: journalctl: add json, export, short and verbose output modes --- src/journal/journalctl.c | 347 +++++++++++++++++++++++++++++++++++++++++++---- src/journal/sd-journal.c | 2 +- src/util.c | 31 +++-- src/util.h | 5 +- 4 files changed, 345 insertions(+), 40 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index c947730441..6f4342e597 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -27,15 +27,328 @@ #include #include #include +#include #include "sd-journal.h" #include "log.h" +#include "util.h" -static bool arg_follow = true; +#define PRINT_THRESHOLD 128 + +static enum { + OUTPUT_SHORT, + OUTPUT_VERBOSE, + OUTPUT_EXPORT, + OUTPUT_JSON, + _OUTPUT_MAX +} arg_output = OUTPUT_JSON; + +static bool arg_follow = false; +static bool arg_show_all = false; + +static bool contains_unprintable(const void *p, size_t l) { + const char *j; + + for (j = p; j < (const char *) p + l; j++) + if (*j < ' ' || *j >= 127) + return true; + + return false; +} + +static int output_short(sd_journal *j, unsigned line) { + int r; + uint64_t realtime; + time_t t; + struct tm tm; + char buf[64]; + const void *data; + size_t length; + size_t n = 0; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime: %s", strerror(-r)); + return r; + } + + t = (time_t) (realtime / USEC_PER_SEC); + if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { + log_error("Failed to format time."); + return -EINVAL; + } + + fputs(buf, stdout); + n += strlen(buf); + + if (sd_journal_get_data(j, "_HOSTNAME", &data, &length) >= 0 && + (arg_show_all || (!contains_unprintable(data, length) && + length < PRINT_THRESHOLD))) { + printf(" %.*s", (int) length - 10, ((const char*) data) + 10); + n += length - 10 + 1; + } + + if (sd_journal_get_data(j, "MESSAGE", &data, &length) >= 0) { + if (arg_show_all) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else if (contains_unprintable(data, length)) + fputs(" [blob data]", stdout); + else if (length - 8 + n < columns()) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else if (n < columns()) { + char *e; + + e = ellipsize_mem((const char *) data + 8, length - 8, columns() - n - 2, 90); + + if (!e) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else + printf(" %s", e); + + free(e); + } + } + + fputc('\n', stdout); + + return 0; +} + +static int output_verbose(sd_journal *j, unsigned line) { + const void *data; + size_t length; + char *cursor; + uint64_t realtime; + char ts[FORMAT_TIMESTAMP_MAX]; + int r; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + printf("%s [%s]\n", + format_timestamp(ts, sizeof(ts), realtime), + cursor); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + if (!arg_show_all && (length > PRINT_THRESHOLD || + contains_unprintable(data, length))) { + const char *c; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + printf("\t%.*s=[blob data]\n", + (int) (c - (const char*) data), + (const char*) data); + } else + printf("\t%.*s\n", (int) length, (const char*) data); + } + + return 0; +} + +static int output_export(sd_journal *j, unsigned line) { + sd_id128_t boot_id; + char sid[33]; + int r; + usec_t realtime, monotonic; + char *cursor; + const void *data; + size_t length; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) { + log_error("Failed to get monotonic timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + printf(".cursor=%s\n" + ".realtime=%llu\n" + ".monotonic=%llu\n" + ".boot_id=%s\n", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + + if (contains_unprintable(data, length)) { + const char *c; + uint64_t le64; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + fwrite(data, c - (const char*) data, 1, stdout); + fputc('\n', stdout); + le64 = htole64(length - (c - (const char*) data) - 1); + fwrite(&le64, sizeof(le64), 1, stdout); + fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout); + } else + fwrite(data, length, 1, stdout); + + fputc('\n', stdout); + } + + fputc('\n', stdout); + + return 0; +} + +static void json_escape(const char* p, size_t l) { + + if (contains_unprintable(p, l)) { + bool not_first = false; + + fputs("[ ", stdout); + + while (l > 0) { + if (not_first) + printf(", %u", (uint8_t) *p); + else { + not_first = true; + printf("%u", (uint8_t) *p); + } + + p++; + l--; + } + + fputs(" ]", stdout); + } else { + fputc('\"', stdout); + + while (l > 0) { + if (*p == '"' || *p == '\\') { + fputc('\\', stdout); + fputc(*p, stdout); + } else + fputc(*p, stdout); + + p++; + l--; + } + + fputc('\"', stdout); + } +} + +static int output_json(sd_journal *j, unsigned line) { + uint64_t realtime, monotonic; + char *cursor; + const void *data; + size_t length; + sd_id128_t boot_id; + char sid[33]; + int r; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) { + log_error("Failed to get monotonic timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + if (line == 1) + fputc('\n', stdout); + else + fputs(",\n", stdout); + + printf("{\n" + "\t\".cursor\" : \"%s\",\n" + "\t\".realtime\" : %llu,\n" + "\t\".monotonic\" : %llu,\n" + "\t\".boot_id\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + const char *c; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + fputs(",\n\t", stdout); + json_escape(data, c - (const char*) data); + fputs(" : ", stdout); + json_escape(c + 1, length - (c - (const char*) data) - 1); + } + + fputs("\n}", stdout); + fflush(stdout); + + return 0; +} + +static int (*output_funcs[_OUTPUT_MAX])(sd_journal*j, unsigned line) = { + [OUTPUT_SHORT] = output_short, + [OUTPUT_VERBOSE] = output_verbose, + [OUTPUT_EXPORT] = output_export, + [OUTPUT_JSON] = output_json +}; int main(int argc, char *argv[]) { int r, i, fd; sd_journal *j = NULL; + unsigned line = 0; log_set_max_level(LOG_DEBUG); log_set_target(LOG_TARGET_CONSOLE); @@ -69,33 +382,18 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_output == OUTPUT_JSON) + fputc('[', stdout); + for (;;) { struct pollfd pollfd; while (sd_journal_next(j) > 0) { - const void *data; - size_t length; - char *cursor; - uint64_t realtime = 0, monotonic = 0; - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) { - log_error("Failed to get cursor: %s", strerror(-r)); - goto finish; - } - - printf("entry: %s\n", cursor); - free(cursor); + line ++; - sd_journal_get_realtime_usec(j, &realtime); - sd_journal_get_monotonic_usec(j, &monotonic, NULL); - printf("realtime: %llu\n" - "monotonic: %llu\n", - (unsigned long long) realtime, - (unsigned long long) monotonic); - - SD_JOURNAL_FOREACH_DATA(j, data, length) - printf("\t%.*s\n", (int) length, (const char*) data); + r = output_funcs[arg_output](j, line); + if (r < 0) + goto finish; } if (!arg_follow) @@ -121,6 +419,9 @@ int main(int argc, char *argv[]) { } } + if (arg_output == OUTPUT_JSON) + fputs("\n]\n", stdout); + finish: if (j) sd_journal_close(j); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index bc575b43ef..b9abbdff92 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -977,7 +977,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch return r; } - journal_file_dump(f); + /* journal_file_dump(f); */ r = hashmap_put(j->files, f->path, f); if (r < 0) { diff --git a/src/util.c b/src/util.c index 37942de534..195835425d 100644 --- a/src/util.c +++ b/src/util.c @@ -3905,7 +3905,7 @@ char **replace_env_argv(char **argv, char **env) { return r; } -int columns(void) { +unsigned columns(void) { static __thread int parsed_columns = 0; const char *e; @@ -3948,38 +3948,41 @@ int running_in_chroot(void) { a.st_ino != b.st_ino; } -char *ellipsize(const char *s, unsigned length, unsigned percent) { - size_t l, x; +char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { + size_t x; char *r; assert(s); assert(percent <= 100); - assert(length >= 3); + assert(new_length >= 3); - l = strlen(s); + if (old_length <= 3 || old_length <= new_length) + return strndup(s, old_length); - if (l <= 3 || l <= length) - return strdup(s); - - if (!(r = new0(char, length+1))) + r = new0(char, new_length+1); + if (!r) return r; - x = (length * percent) / 100; + x = (new_length * percent) / 100; - if (x > length - 3) - x = length - 3; + if (x > new_length - 3) + x = new_length - 3; memcpy(r, s, x); r[x] = '.'; r[x+1] = '.'; r[x+2] = '.'; memcpy(r + x + 3, - s + l - (length - x - 3), - length - x - 3); + s + old_length - (new_length - x - 3), + new_length - x - 3); return r; } +char *ellipsize(const char *s, size_t length, unsigned percent) { + return ellipsize_mem(s, strlen(s), length, percent); +} + int touch(const char *path) { int fd; diff --git a/src/util.h b/src/util.h index 1db82f83e0..ac2ec8c351 100644 --- a/src/util.h +++ b/src/util.h @@ -378,11 +378,12 @@ void status_vprintf(const char *format, va_list ap); void status_printf(const char *format, ...); void status_welcome(void); -int columns(void); +unsigned columns(void); int running_in_chroot(void); -char *ellipsize(const char *s, unsigned length, unsigned percent); +char *ellipsize(const char *s, size_t length, unsigned percent); +char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent); int touch(const char *path); -- cgit v1.2.3-54-g00ecf From 0d43c6944bbca30d5692d4b02885f007a0c630c8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Dec 2011 18:59:56 +0100 Subject: journalctl: add command line parsing --- Makefile.am | 3 +- src/journal/journalctl.c | 125 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 123 insertions(+), 5 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 7d551a9dcf..81b5c50199 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1069,7 +1069,8 @@ systemd_journalctl_SOURCES = \ src/journal/sd-journal.c \ src/journal/journal-file.c \ src/journal/lookup3.c \ - src/sd-id128.c + src/sd-id128.c \ + src/pager.c systemd_journalctl_CFLAGS = \ $(AM_CFLAGS) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6f4342e597..5a1cb6e88a 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -28,10 +28,13 @@ #include #include #include +#include #include "sd-journal.h" #include "log.h" #include "util.h" +#include "build.h" +#include "pager.h" #define PRINT_THRESHOLD 128 @@ -41,10 +44,11 @@ static enum { OUTPUT_EXPORT, OUTPUT_JSON, _OUTPUT_MAX -} arg_output = OUTPUT_JSON; +} arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; +static bool arg_no_pager = false; static bool contains_unprintable(const void *p, size_t l) { const char *j; @@ -345,6 +349,96 @@ static int (*output_funcs[_OUTPUT_MAX])(sd_journal*j, unsigned line) = { [OUTPUT_JSON] = output_json }; +static int help(void) { + + printf("%s [OPTIONS...] {COMMAND} ...\n\n" + "Send control commands to or query the login manager.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -a --all Show all properties, including long and unprintable\n" + " -f --follow Follow journal\n" + " -o --output=STRING Change output mode (short, verbose, export, json)\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "follow", no_argument, NULL, 'f' }, + { "output", required_argument, NULL, 'o' }, + { "all", no_argument, NULL, 'a' }, + { NULL, 0, NULL, 0 } + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hfo:a", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + puts(PACKAGE_STRING); + puts(DISTRIBUTION); + puts(SYSTEMD_FEATURES); + return 0; + + case ARG_NO_PAGER: + arg_no_pager = true; + break; + + case 'f': + arg_follow = true; + break; + + case 'o': + if (streq(optarg, "short")) + arg_output = OUTPUT_SHORT; + else if (streq(optarg, "verbose")) + arg_output = OUTPUT_VERBOSE; + else if (streq(optarg, "export")) + arg_output = OUTPUT_EXPORT; + else if (streq(optarg, "json")) + arg_output = OUTPUT_JSON; + else { + log_error("Unknown output '%s'.", optarg); + return -EINVAL; + } + break; + + case 'a': + arg_show_all = true; + break; + + case '?': + return -EINVAL; + + default: + log_error("Unknown option code %c", c); + return -EINVAL; + } + } + + return 1; +} + int main(int argc, char *argv[]) { int r, i, fd; sd_journal *j = NULL; @@ -356,13 +450,17 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + r = sd_journal_open(&j); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); goto finish; } - for (i = 1; i < argc; i++) { + for (i = optind; i < argc; i++) { r = sd_journal_add_match(j, argv[i], strlen(argv[i])); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); @@ -382,13 +480,30 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_output == OUTPUT_JSON) + if (!arg_no_pager && !arg_follow) { + columns(); + pager_open(); + } + + if (arg_output == OUTPUT_JSON) { fputc('[', stdout); + fflush(stdout); + } for (;;) { struct pollfd pollfd; - while (sd_journal_next(j) > 0) { + for (;;) { + r = sd_journal_next(j); + + if (r < 0) { + log_error("Failed to iterate through journal: %s", strerror(-r)); + goto finish; + } + + if (r == 0) + break; + line ++; r = output_funcs[arg_output](j, line); @@ -426,5 +541,7 @@ finish: if (j) sd_journal_close(j); + pager_close(); + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf From cf244689e9d1ab50082c9ddd0f3c4d1eb982badc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 29 Dec 2011 15:00:57 +0100 Subject: journald: flush /run to /var as soon as it becomes available --- src/journal/journal-file.c | 93 +++++++++++++++-- src/journal/journal-file.h | 4 + src/journal/journalctl.c | 2 +- src/journal/journald.c | 248 +++++++++++++++++++++++++++++++++------------ src/journal/sd-journal.c | 69 ++++--------- src/journal/sd-journal.h | 23 +++-- 6 files changed, 309 insertions(+), 130 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 6c7718de31..190bfb996b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -950,7 +950,7 @@ static int journal_file_append_entry_internal( return 0; } -static void journal_file_post_change(JournalFile *f) { +void journal_file_post_change(JournalFile *f) { assert(f); /* inotify() does not receive IN_MODIFY events from file @@ -989,9 +989,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st if (ts->realtime < le64toh(f->header->tail_entry_realtime)) return -EINVAL; - items = new(EntryItem, n_iovec); - if (!items) - return -ENOMEM; + items = alloca(sizeof(EntryItem) * n_iovec); for (i = 0; i < n_iovec; i++) { uint64_t p; @@ -999,7 +997,7 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p); if (r < 0) - goto finish; + return r; xor_hash ^= le64toh(o->data.hash); items[i].object_offset = htole64(p); @@ -1010,9 +1008,6 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st journal_file_post_change(f); -finish: - free(items); - return r; } @@ -1999,3 +1994,85 @@ finish: return r; } + +int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) { + uint64_t i, n; + uint64_t q, xor_hash = 0; + int r; + EntryItem *items; + dual_timestamp ts; + + assert(from); + assert(to); + assert(o); + assert(p); + + if (!to->writable) + return -EPERM; + + ts.monotonic = le64toh(o->entry.monotonic); + ts.realtime = le64toh(o->entry.realtime); + + if (to->tail_entry_monotonic_valid && + ts.monotonic < le64toh(to->header->tail_entry_monotonic)) + return -EINVAL; + + if (ts.realtime < le64toh(to->header->tail_entry_realtime)) + return -EINVAL; + + n = journal_file_entry_n_items(o); + items = alloca(sizeof(EntryItem) * n); + + for (i = 0; i < n; i++) { + uint64_t le_hash, l, h; + size_t t; + void *data; + Object *u; + + q = le64toh(o->entry.items[i].object_offset); + le_hash = o->entry.items[i].hash; + + r = journal_file_move_to_object(from, OBJECT_DATA, q, &o); + if (r < 0) + return r; + + if (le_hash != o->data.hash) + return -EBADMSG; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + t = (size_t) l; + + /* We hit the limit on 32bit machines */ + if ((uint64_t) t != l) + return -E2BIG; + + if (o->object.flags & OBJECT_COMPRESSED) { +#ifdef HAVE_XZ + uint64_t rsize; + + if (!uncompress_blob(o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize)) + return -EBADMSG; + + data = from->compress_buffer; + l = rsize; +#else + return -EPROTONOSUPPORT; +#endif + } else + data = o->data.payload; + + r = journal_file_append_data(to, data, l, &u, &h); + if (r < 0) + return r; + + xor_hash ^= le64toh(u->data.hash); + items[i].object_offset = htole64(h); + items[i].hash = u->data.hash; + + r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + } + + return journal_file_append_entry_internal(to, &ts, xor_hash, items, n, seqnum, ret, offset); +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 421dfa6766..ab2970ca00 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -113,10 +113,14 @@ int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset); + void journal_file_dump(JournalFile *f); int journal_file_rotate(JournalFile **f); int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); +void journal_file_post_change(JournalFile *f); + #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5a1cb6e88a..da4f51021d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -454,7 +454,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = sd_journal_open(&j); + r = sd_journal_open(&j, 0); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); goto finish; diff --git a/src/journal/journald.c b/src/journal/journald.c index e7231d96f7..1efe0420db 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -40,6 +40,8 @@ #include "cgroup-util.h" #include "list.h" #include "journal-rate-limit.h" +#include "sd-journal.h" +#include "journal-internal.h" #define USER_JOURNALS_MAX 1024 #define STDOUT_STREAMS_MAX 4096 @@ -107,6 +109,8 @@ struct StdoutStream { LIST_FIELDS(StdoutStream, stdout_stream); }; +static int server_flush_to_var(Server *s); + static uint64_t available_space(Server *s) { char ids[33]; sd_id128_t machine; @@ -239,8 +243,12 @@ static JournalFile* find_journal(Server *s, uid_t uid) { assert(s); - /* We split up user logs only on /var, not on /run */ - if (!s->system_journal) + /* We split up user logs only on /var, not on /run. If the + * runtime file is open, we write to it exclusively, in order + * to guarantee proper order as soon as we flush /run to + * /var and close the runtime file. */ + + if (s->runtime_journal) return s->runtime_journal; if (uid <= 0) @@ -486,6 +494,8 @@ static void dispatch_message_real(Server *s, assert(n <= m); + server_flush_to_var(s); + retry: f = find_journal(s, realuid == 0 ? 0 : loginuid); if (!f) @@ -1088,6 +1098,170 @@ fail: return r; } +static int system_journal_open(Server *s) { + int r; + char *fn; + sd_id128_t machine; + char ids[33]; + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + sd_id128_to_string(machine, ids); + + if (!s->system_journal) { + + /* First try to create the machine path, but not the prefix */ + fn = strappend("/var/log/journal/", ids); + if (!fn) + return -ENOMEM; + (void) mkdir(fn, 0755); + free(fn); + + /* The create the system journal file */ + fn = join("/var/log/journal/", ids, "/system.journal", NULL); + if (!fn) + return -ENOMEM; + + r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal); + free(fn); + + if (r >= 0) { + s->system_journal->metrics = s->metrics; + s->system_journal->compress = s->compress; + + fix_perms(s->system_journal, 0); + } else if (r < 0) { + + if (r == -ENOENT) + r = 0; + else { + log_error("Failed to open system journal: %s", strerror(-r)); + return r; + } + } + } + + if (!s->runtime_journal) { + + fn = join("/run/log/journal/", ids, "/system.journal", NULL); + if (!fn) + return -ENOMEM; + + if (s->system_journal) { + + /* Try to open the runtime journal, but only + * if it already exists, so that we can flush + * it into the system journal */ + + r = journal_file_open(fn, O_RDWR, 0640, NULL, &s->runtime_journal); + free(fn); + + if (r < 0) { + + if (r == -ENOENT) + r = 0; + else { + log_error("Failed to open runtime journal: %s", strerror(-r)); + return r; + } + } + + } else { + + /* OK, we really need the runtime journal, so create + * it if necessary. */ + + (void) mkdir_parents(fn, 0755); + r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); + free(fn); + + if (r < 0) { + log_error("Failed to open runtime journal: %s", strerror(-r)); + return r; + } + } + + if (s->runtime_journal) { + s->runtime_journal->metrics = s->metrics; + s->runtime_journal->compress = s->compress; + + fix_perms(s->runtime_journal, 0); + } + } + + return r; +} + +static int server_flush_to_var(Server *s) { + char path[] = "/run/log/journal/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + Object *o = NULL; + int r; + sd_id128_t machine; + sd_journal *j; + + assert(s); + + system_journal_open(s); + + if (!s->system_journal || !s->runtime_journal) + return 0; + + r = sd_id128_get_machine(&machine); + if (r < 0) { + log_error("Failed to get machine id: %s", strerror(-r)); + return r; + } + + r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY); + if (r < 0) { + log_error("Failed to read runtime journal: %s", strerror(-r)); + return r; + } + + SD_JOURNAL_FOREACH(j) { + JournalFile *f; + + f = j->current_file; + assert(f && f->current_offset > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) { + log_error("Can't read entry: %s", strerror(-r)); + goto finish; + } + + r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL); + if (r == -E2BIG) { + log_info("Allocation limit reached."); + + journal_file_post_change(s->system_journal); + server_vacuum(s); + + r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL); + } + + if (r < 0) { + log_error("Can't write entry: %s", strerror(-r)); + goto finish; + } + } + +finish: + journal_file_post_change(s->system_journal); + + journal_file_close(s->runtime_journal); + s->runtime_journal = NULL; + + if (r >= 0) { + sd_id128_to_string(machine, path + 17); + rm_rf(path, false, true, false); + } + + return r; +} + static int process_event(Server *s, struct epoll_event *ev) { assert(s); @@ -1112,6 +1286,11 @@ static int process_event(Server *s, struct epoll_event *ev) { return -errno; } + if (sfsi.ssi_signo == SIGUSR1) { + server_flush_to_var(s); + return 0; + } + log_debug("Received SIG%s", signal_to_string(sfsi.ssi_signo)); return 0; @@ -1247,66 +1426,6 @@ static int process_event(Server *s, struct epoll_event *ev) { return 0; } -static int system_journal_open(Server *s) { - int r; - char *fn; - sd_id128_t machine; - char ids[33]; - - r = sd_id128_get_machine(&machine); - if (r < 0) - return r; - - /* First try to create the machine path, but not the prefix */ - fn = strappend("/var/log/journal/", sd_id128_to_string(machine, ids)); - if (!fn) - return -ENOMEM; - (void) mkdir(fn, 0755); - free(fn); - - /* The create the system journal file */ - fn = join("/var/log/journal/", ids, "/system.journal", NULL); - if (!fn) - return -ENOMEM; - - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->system_journal); - free(fn); - - if (r >= 0) { - s->system_journal->metrics = s->metrics; - s->system_journal->compress = s->compress; - - fix_perms(s->system_journal, 0); - return r; - } - - if (r < 0 && r != -ENOENT) { - log_error("Failed to open system journal: %s", strerror(-r)); - return r; - } - - /* /var didn't work, so try /run, but this time we - * create the prefix too */ - fn = join("/run/log/journal/", ids, "/system.journal", NULL); - if (!fn) - return -ENOMEM; - - (void) mkdir_parents(fn, 0755); - r = journal_file_open(fn, O_RDWR|O_CREAT, 0640, NULL, &s->runtime_journal); - free(fn); - - if (r < 0) { - log_error("Failed to open runtime journal: %s", strerror(-r)); - return r; - } - - s->runtime_journal->metrics = s->metrics; - s->runtime_journal->compress = s->compress; - - fix_perms(s->runtime_journal, 0); - return r; -} - static int open_syslog_socket(Server *s) { union sockaddr_union sa; int one, r; @@ -1470,7 +1589,7 @@ static int open_signalfd(Server *s) { assert(s); assert_se(sigemptyset(&mask) == 0); - sigset_add_many(&mask, SIGINT, SIGTERM, -1); + sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); @@ -1652,6 +1771,9 @@ int main(int argc, char *argv[]) { "READY=1\n" "STATUS=Processing requests..."); + server_vacuum(&server); + server_flush_to_var(&server); + for (;;) { struct epoll_event event; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 8fc8ec5885..38e58f5732 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -32,58 +32,10 @@ #include "list.h" #include "lookup3.h" #include "compress.h" +#include "journal-internal.h" #define JOURNAL_FILES_MAX 1024 -typedef struct Match Match; - -struct Match { - char *data; - size_t size; - uint64_t le_hash; - - LIST_FIELDS(Match, matches); -}; - -typedef enum location_type { - LOCATION_HEAD, - LOCATION_TAIL, - LOCATION_DISCRETE -} location_type_t; - -typedef struct Location { - location_type_t type; - - uint64_t seqnum; - sd_id128_t seqnum_id; - bool seqnum_set; - - uint64_t realtime; - bool realtime_set; - - uint64_t monotonic; - sd_id128_t boot_id; - bool monotonic_set; - - uint64_t xor_hash; - bool xor_hash_set; -} Location; - -struct sd_journal { - Hashmap *files; - - Location current_location; - JournalFile *current_file; - uint64_t current_field; - - int inotify_fd; - Hashmap *inotify_wd_dirs; - Hashmap *inotify_wd_roots; - - LIST_HEAD(Match, matches); - unsigned n_matches; -}; - static void detach_location(sd_journal *j) { Iterator i; JournalFile *f; @@ -948,6 +900,10 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch assert(prefix); assert(filename); + if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) && + !startswith(filename, "system.journal")) + return 0; + if (dir) fn = join(prefix, "/", dir, "/", filename, NULL); else @@ -1024,11 +980,18 @@ static int add_directory(sd_journal *j, const char *prefix, const char *dir) { int r; DIR *d; int wd; + sd_id128_t id, mid; assert(j); assert(prefix); assert(dir); + if ((j->flags & SD_JOURNAL_LOCAL_ONLY) && + (sd_id128_from_string(dir, &id) < 0 || + sd_id128_get_machine(&mid) < 0 || + !sd_id128_equal(id, mid))) + return 0; + fn = join(prefix, "/", dir, NULL); if (!fn) return -ENOMEM; @@ -1132,7 +1095,7 @@ static void remove_root_wd(sd_journal *j, int wd) { } } -int sd_journal_open(sd_journal **ret) { +int sd_journal_open(sd_journal **ret, int flags) { sd_journal *j; const char *p; const char search_paths[] = @@ -1146,6 +1109,8 @@ int sd_journal_open(sd_journal **ret) { if (!j) return -ENOMEM; + j->flags = flags; + j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (j->inotify_fd < 0) { r = -errno; @@ -1172,6 +1137,10 @@ int sd_journal_open(sd_journal **ret) { NULSTR_FOREACH(p, search_paths) { DIR *d; + if ((flags & SD_JOURNAL_RUNTIME_ONLY) && + !path_startswith(p, "/run")) + continue; + d = opendir(p); if (!d) { if (errno != ENOENT) diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h index 7f9f78598b..f6b1c955fb 100644 --- a/src/journal/sd-journal.h +++ b/src/journal/sd-journal.h @@ -31,19 +31,20 @@ /* TODO: * - * - check LE/BE conversion for 8bit, 16bit, 32bit values - * - implement audit gateway + * - OR of matches is borked... * - extend hash tables table as we go * - accelerate looking for "all hostnames" and suchlike. - * - cryptographic hash - * - OR of matches is borked... - * - flush /run to /var * - hookup with systemctl + * - handle incomplete header + * * - local deserializer - * - think about manipulations of header * - http server - * - handle incomplete header * - message catalog + * + * - check LE/BE conversion for 8bit, 16bit, 32bit values + * - cryptographic hash + * - think about manipulations of header + * - implement audit gateway */ /* Write to daemon */ @@ -60,7 +61,13 @@ int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix); typedef struct sd_journal sd_journal; -int sd_journal_open(sd_journal **ret); +enum { + SD_JOURNAL_LOCAL_ONLY = 1, + SD_JOURNAL_RUNTIME_ONLY = 2, + SD_JOURNAL_SYSTEM_ONLY = 4 +}; + +int sd_journal_open(sd_journal **ret, int flags); void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); -- cgit v1.2.3-54-g00ecf From b3a0ad5ab142a142ab526aeb3d0b69e98e4e523c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 30 Dec 2011 22:29:23 +0100 Subject: journal: disable default debug logging --- src/journal/journalctl.c | 3 --- src/journal/journald.c | 1 - 2 files changed, 4 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index da4f51021d..701518244c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -444,9 +444,6 @@ int main(int argc, char *argv[]) { sd_journal *j = NULL; unsigned line = 0; - log_set_max_level(LOG_DEBUG); - log_set_target(LOG_TARGET_CONSOLE); - log_parse_environment(); log_open(); diff --git a/src/journal/journald.c b/src/journal/journald.c index 8d6b3ab438..a25f81ef66 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -1858,7 +1858,6 @@ int main(int argc, char *argv[]) { } log_set_target(LOG_TARGET_CONSOLE); - log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); -- cgit v1.2.3-54-g00ecf From 86aa7ba4f9969bbfc75ebd51f944313695f1a0a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Jan 2012 21:08:28 +0100 Subject: systemctl: hook up systemctl with the journal --- Makefile.am | 17 +- src/journal/journalctl.c | 311 +----------------------------------- src/logs-show.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++ src/logs-show.h | 49 ++++++ src/systemctl.c | 4 + 5 files changed, 469 insertions(+), 316 deletions(-) create mode 100644 src/logs-show.c create mode 100644 src/logs-show.h (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 8bb5b9d949..6c0fd055d0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -98,7 +98,8 @@ AM_CPPFLAGS = \ -DSYSTEMD_KBD_MODEL_MAP=\"$(pkgdatadir)/kbd-model-map\" \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/readahead \ - -I $(top_srcdir)/src/login + -I $(top_srcdir)/src/login \ + -I $(top_srcdir)/src/journal if TARGET_GENTOO AM_CPPFLAGS += \ @@ -923,7 +924,8 @@ systemctl_SOURCES = \ src/unit-name.c \ src/pager.c \ src/install.c \ - src/spawn-agent.c + src/spawn-agent.c \ + src/logs-show.c systemctl_CFLAGS = \ $(AM_CFLAGS) \ @@ -932,6 +934,7 @@ systemctl_CFLAGS = \ systemctl_LDADD = \ libsystemd-basic.la \ libsystemd-daemon.la \ + libsystemd-journal.la \ $(DBUS_LIBS) systemd_notify_SOURCES = \ @@ -1189,14 +1192,12 @@ endif systemd_journalctl_SOURCES = \ src/journal/journalctl.c \ - src/journal/sd-journal.c \ - src/journal/journal-file.c \ - src/journal/lookup3.c \ - src/sd-id128.c \ - src/pager.c + src/pager.c \ + src/logs-show.c systemd_journalctl_LDADD = \ - libsystemd-basic.la + libsystemd-basic.la \ + libsystemd-journal.la if HAVE_XZ systemd_journalctl_SOURCES += \ diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 701518244c..4c20ff66a8 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -35,319 +35,14 @@ #include "util.h" #include "build.h" #include "pager.h" +#include "logs-show.h" -#define PRINT_THRESHOLD 128 - -static enum { - OUTPUT_SHORT, - OUTPUT_VERBOSE, - OUTPUT_EXPORT, - OUTPUT_JSON, - _OUTPUT_MAX -} arg_output = OUTPUT_SHORT; +static output_mode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; static bool arg_no_pager = false; -static bool contains_unprintable(const void *p, size_t l) { - const char *j; - - for (j = p; j < (const char *) p + l; j++) - if (*j < ' ' || *j >= 127) - return true; - - return false; -} - -static int output_short(sd_journal *j, unsigned line) { - int r; - uint64_t realtime; - time_t t; - struct tm tm; - char buf[64]; - const void *data; - size_t length; - size_t n = 0; - - assert(j); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) { - log_error("Failed to get realtime: %s", strerror(-r)); - return r; - } - - t = (time_t) (realtime / USEC_PER_SEC); - if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { - log_error("Failed to format time."); - return -EINVAL; - } - - fputs(buf, stdout); - n += strlen(buf); - - if (sd_journal_get_data(j, "_HOSTNAME", &data, &length) >= 0 && - (arg_show_all || (!contains_unprintable(data, length) && - length < PRINT_THRESHOLD))) { - printf(" %.*s", (int) length - 10, ((const char*) data) + 10); - n += length - 10 + 1; - } - - if (sd_journal_get_data(j, "MESSAGE", &data, &length) >= 0) { - if (arg_show_all) - printf(" %.*s", (int) length - 8, ((const char*) data) + 8); - else if (contains_unprintable(data, length)) - fputs(" [blob data]", stdout); - else if (length - 8 + n < columns()) - printf(" %.*s", (int) length - 8, ((const char*) data) + 8); - else if (n < columns()) { - char *e; - - e = ellipsize_mem((const char *) data + 8, length - 8, columns() - n - 2, 90); - - if (!e) - printf(" %.*s", (int) length - 8, ((const char*) data) + 8); - else - printf(" %s", e); - - free(e); - } - } - - fputc('\n', stdout); - - return 0; -} - -static int output_verbose(sd_journal *j, unsigned line) { - const void *data; - size_t length; - char *cursor; - uint64_t realtime; - char ts[FORMAT_TIMESTAMP_MAX]; - int r; - - assert(j); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) { - log_error("Failed to get realtime timestamp: %s", strerror(-r)); - return r; - } - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) { - log_error("Failed to get cursor: %s", strerror(-r)); - return r; - } - - printf("%s [%s]\n", - format_timestamp(ts, sizeof(ts), realtime), - cursor); - - free(cursor); - - SD_JOURNAL_FOREACH_DATA(j, data, length) { - if (!arg_show_all && (length > PRINT_THRESHOLD || - contains_unprintable(data, length))) { - const char *c; - - c = memchr(data, '=', length); - if (!c) { - log_error("Invalid field."); - return -EINVAL; - } - - printf("\t%.*s=[blob data]\n", - (int) (c - (const char*) data), - (const char*) data); - } else - printf("\t%.*s\n", (int) length, (const char*) data); - } - - return 0; -} - -static int output_export(sd_journal *j, unsigned line) { - sd_id128_t boot_id; - char sid[33]; - int r; - usec_t realtime, monotonic; - char *cursor; - const void *data; - size_t length; - - assert(j); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) { - log_error("Failed to get realtime timestamp: %s", strerror(-r)); - return r; - } - - r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); - if (r < 0) { - log_error("Failed to get monotonic timestamp: %s", strerror(-r)); - return r; - } - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) { - log_error("Failed to get cursor: %s", strerror(-r)); - return r; - } - - printf(".cursor=%s\n" - ".realtime=%llu\n" - ".monotonic=%llu\n" - ".boot_id=%s\n", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); - - free(cursor); - - SD_JOURNAL_FOREACH_DATA(j, data, length) { - - if (contains_unprintable(data, length)) { - const char *c; - uint64_t le64; - - c = memchr(data, '=', length); - if (!c) { - log_error("Invalid field."); - return -EINVAL; - } - - fwrite(data, c - (const char*) data, 1, stdout); - fputc('\n', stdout); - le64 = htole64(length - (c - (const char*) data) - 1); - fwrite(&le64, sizeof(le64), 1, stdout); - fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout); - } else - fwrite(data, length, 1, stdout); - - fputc('\n', stdout); - } - - fputc('\n', stdout); - - return 0; -} - -static void json_escape(const char* p, size_t l) { - - if (contains_unprintable(p, l)) { - bool not_first = false; - - fputs("[ ", stdout); - - while (l > 0) { - if (not_first) - printf(", %u", (uint8_t) *p); - else { - not_first = true; - printf("%u", (uint8_t) *p); - } - - p++; - l--; - } - - fputs(" ]", stdout); - } else { - fputc('\"', stdout); - - while (l > 0) { - if (*p == '"' || *p == '\\') { - fputc('\\', stdout); - fputc(*p, stdout); - } else - fputc(*p, stdout); - - p++; - l--; - } - - fputc('\"', stdout); - } -} - -static int output_json(sd_journal *j, unsigned line) { - uint64_t realtime, monotonic; - char *cursor; - const void *data; - size_t length; - sd_id128_t boot_id; - char sid[33]; - int r; - - assert(j); - - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) { - log_error("Failed to get realtime timestamp: %s", strerror(-r)); - return r; - } - - r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); - if (r < 0) { - log_error("Failed to get monotonic timestamp: %s", strerror(-r)); - return r; - } - - r = sd_journal_get_cursor(j, &cursor); - if (r < 0) { - log_error("Failed to get cursor: %s", strerror(-r)); - return r; - } - - if (line == 1) - fputc('\n', stdout); - else - fputs(",\n", stdout); - - printf("{\n" - "\t\".cursor\" : \"%s\",\n" - "\t\".realtime\" : %llu,\n" - "\t\".monotonic\" : %llu,\n" - "\t\".boot_id\" : \"%s\"", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); - - free(cursor); - - SD_JOURNAL_FOREACH_DATA(j, data, length) { - const char *c; - - c = memchr(data, '=', length); - if (!c) { - log_error("Invalid field."); - return -EINVAL; - } - - fputs(",\n\t", stdout); - json_escape(data, c - (const char*) data); - fputs(" : ", stdout); - json_escape(c + 1, length - (c - (const char*) data) - 1); - } - - fputs("\n}", stdout); - fflush(stdout); - - return 0; -} - -static int (*output_funcs[_OUTPUT_MAX])(sd_journal*j, unsigned line) = { - [OUTPUT_SHORT] = output_short, - [OUTPUT_VERBOSE] = output_verbose, - [OUTPUT_EXPORT] = output_export, - [OUTPUT_JSON] = output_json -}; static int help(void) { @@ -503,7 +198,7 @@ int main(int argc, char *argv[]) { line ++; - r = output_funcs[arg_output](j, line); + r = output_journal(j, arg_output, line, arg_show_all); if (r < 0) goto finish; } diff --git a/src/logs-show.c b/src/logs-show.c new file mode 100644 index 0000000000..d178f95f94 --- /dev/null +++ b/src/logs-show.c @@ -0,0 +1,404 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "logs-show.h" +#include "log.h" +#include "util.h" + +#define PRINT_THRESHOLD 128 + +static bool contains_unprintable(const void *p, size_t l) { + const char *j; + + for (j = p; j < (const char *) p + l; j++) + if (*j < ' ' || *j >= 127) + return true; + + return false; +} + +static int output_short(sd_journal *j, unsigned line, bool show_all) { + int r; + uint64_t realtime; + time_t t; + struct tm tm; + char buf[64]; + const void *data; + size_t length; + size_t n = 0; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime: %s", strerror(-r)); + return r; + } + + t = (time_t) (realtime / USEC_PER_SEC); + if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { + log_error("Failed to format time."); + return -EINVAL; + } + + fputs(buf, stdout); + n += strlen(buf); + + if (sd_journal_get_data(j, "_HOSTNAME", &data, &length) >= 0 && + (show_all || (!contains_unprintable(data, length) && + length < PRINT_THRESHOLD))) { + printf(" %.*s", (int) length - 10, ((const char*) data) + 10); + n += length - 10 + 1; + } + + if (sd_journal_get_data(j, "MESSAGE", &data, &length) >= 0) { + if (show_all) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else if (contains_unprintable(data, length)) + fputs(" [blob data]", stdout); + else if (length - 8 + n < columns()) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else if (n < columns()) { + char *e; + + e = ellipsize_mem((const char *) data + 8, length - 8, columns() - n - 2, 90); + + if (!e) + printf(" %.*s", (int) length - 8, ((const char*) data) + 8); + else + printf(" %s", e); + + free(e); + } + } + + fputc('\n', stdout); + + return 0; +} + +static int output_verbose(sd_journal *j, unsigned line, bool show_all) { + const void *data; + size_t length; + char *cursor; + uint64_t realtime; + char ts[FORMAT_TIMESTAMP_MAX]; + int r; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + printf("%s [%s]\n", + format_timestamp(ts, sizeof(ts), realtime), + cursor); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + if (!show_all && (length > PRINT_THRESHOLD || + contains_unprintable(data, length))) { + const char *c; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + printf("\t%.*s=[blob data]\n", + (int) (c - (const char*) data), + (const char*) data); + } else + printf("\t%.*s\n", (int) length, (const char*) data); + } + + return 0; +} + +static int output_export(sd_journal *j, unsigned line, bool show_all) { + sd_id128_t boot_id; + char sid[33]; + int r; + usec_t realtime, monotonic; + char *cursor; + const void *data; + size_t length; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) { + log_error("Failed to get monotonic timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + printf(".cursor=%s\n" + ".realtime=%llu\n" + ".monotonic=%llu\n" + ".boot_id=%s\n", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + + if (contains_unprintable(data, length)) { + const char *c; + uint64_t le64; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + fwrite(data, c - (const char*) data, 1, stdout); + fputc('\n', stdout); + le64 = htole64(length - (c - (const char*) data) - 1); + fwrite(&le64, sizeof(le64), 1, stdout); + fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout); + } else + fwrite(data, length, 1, stdout); + + fputc('\n', stdout); + } + + fputc('\n', stdout); + + return 0; +} + +static void json_escape(const char* p, size_t l) { + + if (contains_unprintable(p, l)) { + bool not_first = false; + + fputs("[ ", stdout); + + while (l > 0) { + if (not_first) + printf(", %u", (uint8_t) *p); + else { + not_first = true; + printf("%u", (uint8_t) *p); + } + + p++; + l--; + } + + fputs(" ]", stdout); + } else { + fputc('\"', stdout); + + while (l > 0) { + if (*p == '"' || *p == '\\') { + fputc('\\', stdout); + fputc(*p, stdout); + } else + fputc(*p, stdout); + + p++; + l--; + } + + fputc('\"', stdout); + } +} + +static int output_json(sd_journal *j, unsigned line, bool show_all) { + uint64_t realtime, monotonic; + char *cursor; + const void *data; + size_t length; + sd_id128_t boot_id; + char sid[33]; + int r; + + assert(j); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) { + log_error("Failed to get monotonic timestamp: %s", strerror(-r)); + return r; + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) { + log_error("Failed to get cursor: %s", strerror(-r)); + return r; + } + + if (line == 1) + fputc('\n', stdout); + else + fputs(",\n", stdout); + + printf("{\n" + "\t\".cursor\" : \"%s\",\n" + "\t\".realtime\" : %llu,\n" + "\t\".monotonic\" : %llu,\n" + "\t\".boot_id\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); + + free(cursor); + + SD_JOURNAL_FOREACH_DATA(j, data, length) { + const char *c; + + c = memchr(data, '=', length); + if (!c) { + log_error("Invalid field."); + return -EINVAL; + } + + fputs(",\n\t", stdout); + json_escape(data, c - (const char*) data); + fputs(" : ", stdout); + json_escape(c + 1, length - (c - (const char*) data) - 1); + } + + fputs("\n}", stdout); + fflush(stdout); + + return 0; +} + +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = { + [OUTPUT_SHORT] = output_short, + [OUTPUT_VERBOSE] = output_verbose, + [OUTPUT_EXPORT] = output_export, + [OUTPUT_JSON] = output_json +}; + +int output_journal(sd_journal *j, output_mode mode, unsigned line, bool show_all) { + assert(mode < _OUTPUT_MODE_MAX); + + return output_funcs[mode](j, line, show_all); +} + +int show_journal_by_service( + const char *service, + output_mode mode, + const char *prefix, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + bool show_all) { + + char *m = NULL; + sd_journal *j; + int r; + unsigned i; + + assert(service); + + if (n_columns <= 0) + n_columns = columns(); + + if (how_many <= 0) + how_many = 10; + + if (!prefix) + prefix = ""; + + if (asprintf(&m, "_SYSTEMD_SERVICE=%s", service) < 0) { + r = -ENOMEM; + goto finish; + } + + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY); + if (r < 0) + goto finish; + + r = sd_journal_add_match(j, m, strlen(m)); + if (r < 0) + goto finish; + + r = sd_journal_seek_tail(j); + if (r < 0) + goto finish; + + for (i = 0; i < how_many; i++) + sd_journal_previous(j); + + for (i = 0; i < how_many; i++) { + + r = sd_journal_next(j); + if (r < 0) + goto finish; + + if (r == 0) + break; + + r = output_journal(j, mode, i+1, show_all); + if (r < 0) + goto finish; + } + +finish: + if (m) + free(m); + + if (j) + sd_journal_close(j); + + return r; +} diff --git a/src/logs-show.h b/src/logs-show.h new file mode 100644 index 0000000000..f83df069cf --- /dev/null +++ b/src/logs-show.h @@ -0,0 +1,49 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foologsshowhfoo +#define foologsshowhfoo + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include + +#include "sd-journal.h" +#include "util.h" + +typedef enum output_mode { + OUTPUT_SHORT, + OUTPUT_VERBOSE, + OUTPUT_EXPORT, + OUTPUT_JSON, + _OUTPUT_MODE_MAX +} output_mode; + +int output_journal(sd_journal *j, output_mode mode, unsigned line, bool show_all); + +int show_journal_by_service( + const char *service, + output_mode mode, + const char *prefix, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + bool show_all); + +#endif diff --git a/src/systemctl.c b/src/systemctl.c index 1142200e42..10e3991745 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -58,6 +58,7 @@ #include "pager.h" #include "spawn-agent.h" #include "install.h" +#include "logs-show.h" static const char *arg_type = NULL; static char **arg_property = NULL; @@ -2261,6 +2262,9 @@ static void print_status_info(UnitStatusInfo *i) { } } + if (i->id && arg_transport != TRANSPORT_SSH) + show_journal_by_service(i->id, OUTPUT_SHORT, NULL, 0, 0, 0, arg_all); + if (i->need_daemon_reload) printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n", ansi_highlight(true), -- cgit v1.2.3-54-g00ecf From 2100675e9fe0707fae8cee13fbe9316e94ef98f9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Jan 2012 02:14:42 +0100 Subject: journalctl: add -n switch --- src/journal/journalctl.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 4c20ff66a8..fc1fed277c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -42,7 +42,7 @@ static output_mode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; static bool arg_no_pager = false; - +static int arg_lines = -1; static int help(void) { @@ -53,6 +53,7 @@ static int help(void) { " --no-pager Do not pipe output into a pager\n" " -a --all Show all properties, including long and unprintable\n" " -f --follow Follow journal\n" + " -n --lines=INTEGER Lines to show\n" " -o --output=STRING Change output mode (short, verbose, export, json)\n", program_invocation_short_name); @@ -73,15 +74,16 @@ static int parse_argv(int argc, char *argv[]) { { "follow", no_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, + { "lines", required_argument, NULL, 'n' }, { NULL, 0, NULL, 0 } }; - int c; + int c, r; assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:a", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:", options, NULL)) >= 0) { switch (c) { @@ -122,6 +124,14 @@ static int parse_argv(int argc, char *argv[]) { arg_show_all = true; break; + case 'n': + r = safe_atoi(optarg, &arg_lines); + if (r < 0) { + log_error("Failed to parse lines '%s'", optarg); + return -EINVAL; + } + break; + case '?': return -EINVAL; @@ -166,10 +176,24 @@ int main(int argc, char *argv[]) { goto finish; } - r = sd_journal_seek_head(j); - if (r < 0) { - log_error("Failed to seek to head: %s", strerror(-r)); - goto finish; + if (arg_lines >= 0) { + r = sd_journal_seek_tail(j); + if (r < 0) { + log_error("Failed to seek to tail: %s", strerror(-r)); + goto finish; + } + + r = sd_journal_previous_skip(j, arg_lines); + if (r < 0) { + log_error("Failed to iterate through journal: %s", strerror(-r)); + goto finish; + } + } else { + r = sd_journal_seek_head(j); + if (r < 0) { + log_error("Failed to seek to head: %s", strerror(-r)); + goto finish; + } } if (!arg_no_pager && !arg_follow) { -- cgit v1.2.3-54-g00ecf From 6f003b43043da7b57c0ebe15b86856c8248fea4a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Jan 2012 04:00:14 +0100 Subject: journalctl: fix counting of -n parameter --- src/journal/journalctl.c | 25 ++++++++++++++++--------- src/journal/sd-journal.c | 40 ++++++++++++++++++---------------------- src/systemctl.c | 4 +++- 3 files changed, 37 insertions(+), 32 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index fc1fed277c..0e1fb66de6 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -148,6 +148,7 @@ int main(int argc, char *argv[]) { int r, i, fd; sd_journal *j = NULL; unsigned line = 0; + bool need_seek = false; log_parse_environment(); log_open(); @@ -184,16 +185,19 @@ int main(int argc, char *argv[]) { } r = sd_journal_previous_skip(j, arg_lines); - if (r < 0) { - log_error("Failed to iterate through journal: %s", strerror(-r)); - goto finish; - } } else { r = sd_journal_seek_head(j); if (r < 0) { log_error("Failed to seek to head: %s", strerror(-r)); goto finish; } + + r = sd_journal_next(j); + } + + if (r < 0) { + log_error("Failed to iterate through journal: %s", strerror(-r)); + goto finish; } if (!arg_no_pager && !arg_follow) { @@ -210,11 +214,12 @@ int main(int argc, char *argv[]) { struct pollfd pollfd; for (;;) { - r = sd_journal_next(j); - - if (r < 0) { - log_error("Failed to iterate through journal: %s", strerror(-r)); - goto finish; + if (need_seek) { + r = sd_journal_next(j); + if (r < 0) { + log_error("Failed to iterate through journal: %s", strerror(-r)); + goto finish; + } } if (r == 0) @@ -225,6 +230,8 @@ int main(int argc, char *argv[]) { r = output_journal(j, arg_output, line, arg_show_all); if (r < 0) goto finish; + + need_seek = true; } if (!arg_follow) diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 78a91a3eb0..05c0d96ce1 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -683,14 +683,23 @@ _public_ int sd_journal_previous(sd_journal *j) { return real_journal_next(j, DIRECTION_UP); } -_public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) { +static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) { int c = 0, r; if (!j) return -EINVAL; - while (skip > 0) { - r = sd_journal_next(j); + if (skip == 0) { + /* If this is not a discrete skip, then at least + * resolve the current location */ + if (j->current_location.type != LOCATION_DISCRETE) + return real_journal_next(j, direction); + + return 0; + } + + do { + r = real_journal_next(j, direction); if (r < 0) return r; @@ -699,30 +708,17 @@ _public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) { skip--; c++; - } + } while (skip > 0); return c; } -_public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) { - int c = 0, r; - - if (!j) - return -EINVAL; - - while (skip > 0) { - r = sd_journal_previous(j); - if (r < 0) - return r; - - if (r == 0) - return c; - - skip--; - c++; - } +_public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) { + return real_journal_next_skip(j, DIRECTION_DOWN, skip); +} - return 1; +_public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) { + return real_journal_next_skip(j, DIRECTION_UP, skip); } _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { diff --git a/src/systemctl.c b/src/systemctl.c index 10e3991745..6f87b06dd3 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -2262,8 +2262,10 @@ static void print_status_info(UnitStatusInfo *i) { } } - if (i->id && arg_transport != TRANSPORT_SSH) + if (i->id && arg_transport != TRANSPORT_SSH) { + printf("\n"); show_journal_by_service(i->id, OUTPUT_SHORT, NULL, 0, 0, 0, arg_all); + } if (i->need_daemon_reload) printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n", -- cgit v1.2.3-54-g00ecf From e91af489a25e8bb65016a63f533ae28a505119ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Jan 2012 15:27:31 +0100 Subject: journalctl: only output 10 most recent lines in --follow mode --- src/journal/journalctl.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0e1fb66de6..e888990f23 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -38,11 +38,11 @@ #include "logs-show.h" static output_mode arg_output = OUTPUT_SHORT; - static bool arg_follow = false; static bool arg_show_all = false; static bool arg_no_pager = false; static int arg_lines = -1; +static bool arg_no_tail = false; static int help(void) { @@ -54,6 +54,7 @@ static int help(void) { " -a --all Show all properties, including long and unprintable\n" " -f --follow Follow journal\n" " -n --lines=INTEGER Lines to show\n" + " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change output mode (short, verbose, export, json)\n", program_invocation_short_name); @@ -64,7 +65,8 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, - ARG_NO_PAGER + ARG_NO_PAGER, + ARG_NO_TAIL }; static const struct option options[] = { @@ -75,6 +77,7 @@ static int parse_argv(int argc, char *argv[]) { { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, { "lines", required_argument, NULL, 'n' }, + { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { NULL, 0, NULL, 0 } }; @@ -126,12 +129,16 @@ static int parse_argv(int argc, char *argv[]) { case 'n': r = safe_atoi(optarg, &arg_lines); - if (r < 0) { + if (r < 0 || arg_lines < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } break; + case ARG_NO_TAIL: + arg_no_tail = true; + break; + case '?': return -EINVAL; @@ -141,6 +148,9 @@ static int parse_argv(int argc, char *argv[]) { } } + if (arg_follow && !arg_no_tail) + arg_lines = 10; + return 1; } -- cgit v1.2.3-54-g00ecf From df50185b43916926a72246ab3a80875eda7ad2a3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Jan 2012 18:33:36 +0100 Subject: journal: beef up journal output of systemctl and journalctl --- src/journal/journalctl.c | 35 +++++---------- src/journal/sd-journal.c | 2 +- src/logs-show.c | 110 +++++++++++++++++++++++++++++++++++++---------- src/logs-show.h | 21 +++++---- src/systemctl.c | 40 +++++++++++++++-- src/util.c | 18 ++++++++ src/util.h | 2 + 7 files changed, 167 insertions(+), 61 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e888990f23..17d6a7fc23 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -37,7 +37,7 @@ #include "pager.h" #include "logs-show.h" -static output_mode arg_output = OUTPUT_SHORT; +static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; static bool arg_no_pager = false; @@ -47,15 +47,15 @@ static bool arg_no_tail = false; static int help(void) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" - "Send control commands to or query the login manager.\n\n" + "Send control commands to or query the journal.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all properties, including long and unprintable\n" " -f --follow Follow journal\n" - " -n --lines=INTEGER Lines to show\n" + " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change output mode (short, verbose, export, json)\n", + " -o --output=STRING Change journal output mode (short, verbose, export, json)\n", program_invocation_short_name); return 0; @@ -109,18 +109,12 @@ static int parse_argv(int argc, char *argv[]) { break; case 'o': - if (streq(optarg, "short")) - arg_output = OUTPUT_SHORT; - else if (streq(optarg, "verbose")) - arg_output = OUTPUT_VERBOSE; - else if (streq(optarg, "export")) - arg_output = OUTPUT_EXPORT; - else if (streq(optarg, "json")) - arg_output = OUTPUT_JSON; - else { + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; } + break; case 'a': @@ -221,8 +215,6 @@ int main(int argc, char *argv[]) { } for (;;) { - struct pollfd pollfd; - for (;;) { if (need_seek) { r = sd_journal_next(j); @@ -247,16 +239,9 @@ int main(int argc, char *argv[]) { if (!arg_follow) break; - zero(pollfd); - pollfd.fd = fd; - pollfd.events = POLLIN; - - if (poll(&pollfd, 1, -1) < 0) { - if (errno == EINTR) - break; - - log_error("poll(): %m"); - r = -errno; + r = fd_wait_for_event(fd, POLLIN); + if (r < 0) { + log_error("Couldn't wait for event: %s", strerror(-r)); goto finish; } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 05c0d96ce1..fe9208c01b 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1298,7 +1298,7 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 return r; if (!sd_id128_equal(id, o->entry.boot_id)) - return -ENOENT; + return -ESTALE; } *ret = le64toh(o->entry.monotonic); diff --git a/src/logs-show.c b/src/logs-show.c index d44c50a291..539dfeddb6 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "logs-show.h" #include "log.h" @@ -328,44 +329,50 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool s [OUTPUT_JSON] = output_json }; -int output_journal(sd_journal *j, output_mode mode, unsigned line, bool show_all) { +int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all) { + assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); return output_funcs[mode](j, line, show_all); } -int show_journal_by_service( - const char *service, - output_mode mode, +int show_journal_by_unit( + const char *unit, + OutputMode mode, const char *prefix, unsigned n_columns, usec_t not_before, unsigned how_many, - bool show_all) { + bool show_all, + bool follow) { char *m = NULL; sd_journal *j; int r; - unsigned i; + int fd; + unsigned line = 0; + bool need_seek = false; - assert(service); + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + assert(unit); + + if (!endswith(unit, ".service") && + !endswith(unit, ".socket") && + !endswith(unit, ".mount") && + !endswith(unit, ".swap")) + return 0; - if (!endswith(service, ".service") && - !endswith(service, ".socket") && - !endswith(service, ".mount") && - !endswith(service, ".swap")) + if (how_many <= 0) return 0; if (n_columns <= 0) n_columns = columns(); - if (how_many <= 0) - how_many = 10; - if (!prefix) prefix = ""; - if (asprintf(&m, "_SYSTEMD_UNIT=%s", service) < 0) { + if (asprintf(&m, "_SYSTEMD_UNIT=%s", unit) < 0) { r = -ENOMEM; goto finish; } @@ -374,6 +381,10 @@ int show_journal_by_service( if (r < 0) goto finish; + fd = sd_journal_get_fd(j); + if (fd < 0) + goto finish; + r = sd_journal_add_match(j, m, strlen(m)); if (r < 0) goto finish; @@ -382,23 +393,67 @@ int show_journal_by_service( if (r < 0) goto finish; - for (i = 0; i < how_many; i++) - sd_journal_previous(j); + r = sd_journal_previous_skip(j, how_many); + if (r < 0) + goto finish; - for (i = 0; i < how_many; i++) { + if (mode == OUTPUT_JSON) { + fputc('[', stdout); + fflush(stdout); + } - r = sd_journal_next(j); - if (r < 0) - goto finish; + for (;;) { + for (;;) { + usec_t usec; + + if (need_seek) { + r = sd_journal_next(j); + if (r < 0) + goto finish; + } + + if (r == 0) + break; - if (r == 0) + need_seek = true; + + if (not_before > 0) { + r = sd_journal_get_monotonic_usec(j, &usec, NULL); + + /* -ESTALE is returned if the + timestamp is not from this boot */ + if (r == -ESTALE) + continue; + else if (r < 0) + goto finish; + + if (usec < not_before) + continue; + } + + line ++; + + r = output_journal(j, mode, line, show_all); + if (r < 0) + goto finish; + } + + if (!follow) break; - r = output_journal(j, mode, i+1, show_all); + r = fd_wait_for_event(fd, POLLIN); if (r < 0) goto finish; + + r = sd_journal_process(j); + if (r < 0) + goto finish; + } + if (mode == OUTPUT_JSON) + fputs("\n]\n", stdout); + finish: if (m) free(m); @@ -408,3 +463,12 @@ finish: return r; } + +static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { + [OUTPUT_SHORT] = "short", + [OUTPUT_VERBOSE] = "verbose", + [OUTPUT_EXPORT] = "export", + [OUTPUT_JSON] = "json" +}; + +DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); diff --git a/src/logs-show.h b/src/logs-show.h index f83df069cf..5cf1a6369b 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -27,23 +27,28 @@ #include "sd-journal.h" #include "util.h" -typedef enum output_mode { +typedef enum OutputMode { OUTPUT_SHORT, OUTPUT_VERBOSE, OUTPUT_EXPORT, OUTPUT_JSON, - _OUTPUT_MODE_MAX -} output_mode; + _OUTPUT_MODE_MAX, + _OUTPUT_MODE_INVALID = -1 +} OutputMode; -int output_journal(sd_journal *j, output_mode mode, unsigned line, bool show_all); +int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all); -int show_journal_by_service( - const char *service, - output_mode mode, +int show_journal_by_unit( + const char *unit, + OutputMode mode, const char *prefix, unsigned n_columns, usec_t not_before, unsigned how_many, - bool show_all); + bool show_all, + bool follow); + +const char* output_mode_to_string(OutputMode m); +OutputMode output_mode_from_string(const char *s); #endif diff --git a/src/systemctl.c b/src/systemctl.c index 6f87b06dd3..2f03f6baa8 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -118,6 +118,9 @@ static enum transport { TRANSPORT_POLKIT } arg_transport = TRANSPORT_NORMAL; static const char *arg_host = NULL; +static bool arg_follow = false; +static unsigned arg_lines = 10; +static OutputMode arg_output = OUTPUT_SHORT; static bool private_bus = false; @@ -2001,6 +2004,7 @@ typedef struct UnitStatusInfo { const char *load_error; usec_t inactive_exit_timestamp; + usec_t inactive_exit_timestamp_monotonic; usec_t active_enter_timestamp; usec_t active_exit_timestamp; usec_t inactive_enter_timestamp; @@ -2264,7 +2268,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->id && arg_transport != TRANSPORT_SSH) { printf("\n"); - show_journal_by_service(i->id, OUTPUT_SHORT, NULL, 0, 0, 0, arg_all); + show_journal_by_unit(i->id, arg_output, NULL, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow); } if (i->need_daemon_reload) @@ -2391,6 +2395,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn i->inactive_enter_timestamp = (usec_t) u; else if (streq(name, "InactiveExitTimestamp")) i->inactive_exit_timestamp = (usec_t) u; + else if (streq(name, "InactiveExitTimestampMonotonic")) + i->inactive_exit_timestamp_monotonic = (usec_t) u; else if (streq(name, "ActiveExitTimestamp")) i->active_exit_timestamp = (usec_t) u; else if (streq(name, "ConditionTimestamp")) @@ -3969,7 +3975,10 @@ static int systemctl_help(void) { " -f --force When enabling unit files, override existing symlinks\n" " When shutting down, execute action immediately\n" " --root=PATH Enable unit files in the specified root directory\n" - " --runtime Enable unit files only temporarily until next reboot\n\n" + " --runtime Enable unit files only temporarily until next reboot\n" + " -n --lines=INTEGER Journal entries to show\n" + " --follow Follow journal\n" + " -o --output=STRING Change journal output mode (short, verbose, export, json)\n\n" "Unit Commands:\n" " list-units List loaded units\n" " start [NAME...] Start (activate) one or more units\n" @@ -4120,7 +4129,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_KILL_WHO, ARG_NO_ASK_PASSWORD, ARG_FAILED, - ARG_RUNTIME + ARG_RUNTIME, + ARG_FOLLOW }; static const struct option options[] = { @@ -4153,6 +4163,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "host", required_argument, NULL, 'H' }, { "privileged",no_argument, NULL, 'P' }, { "runtime", no_argument, NULL, ARG_RUNTIME }, + { "lines", required_argument, NULL, 'n' }, + { "follow", no_argument, NULL, ARG_FOLLOW }, + { "output", required_argument, NULL, 'o' }, { NULL, 0, NULL, 0 } }; @@ -4164,7 +4177,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { /* Only when running as systemctl we ask for passwords */ arg_ask_password = true; - while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:P", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) { switch (c) { @@ -4302,6 +4315,25 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_runtime = true; break; + case 'n': + if (safe_atou(optarg, &arg_lines) < 0) { + log_error("Failed to parse lines '%s'", optarg); + return -EINVAL; + } + break; + + case ARG_FOLLOW: + arg_follow = true; + break; + + case 'o': + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) { + log_error("Unknown output '%s'.", optarg); + return -EINVAL; + } + break; + case '?': return -EINVAL; diff --git a/src/util.c b/src/util.c index de36d1595e..8a6c3bb5e7 100644 --- a/src/util.c +++ b/src/util.c @@ -4694,6 +4694,24 @@ int pipe_eof(int fd) { return pollfd.revents & POLLHUP; } +int fd_wait_for_event(int fd, int event) { + struct pollfd pollfd; + int r; + + zero(pollfd); + pollfd.fd = fd; + pollfd.events = event; + + r = poll(&pollfd, 1, -1); + if (r < 0) + return -errno; + + if (r == 0) + return 0; + + return pollfd.revents; +} + int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { FILE *f; char *t; diff --git a/src/util.h b/src/util.h index 7f25788b3f..e285ec77ff 100644 --- a/src/util.h +++ b/src/util.h @@ -520,4 +520,6 @@ unsigned long cap_last_cap(void); char *format_bytes(char *buf, size_t l, off_t t); +int fd_wait_for_event(int fd, int event); + #endif -- cgit v1.2.3-54-g00ecf From 81527be142678057215665be66e4b3c8306a7ab3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Jan 2012 16:01:58 +0100 Subject: build-sys: move public header files into a dir of their own --- Makefile.am | 15 ++- src/initctl.c | 2 +- src/journal/journal-def.h | 3 +- src/journal/journal-file.h | 3 +- src/journal/journal-internal.h | 3 +- src/journal/journalctl.c | 3 +- src/journal/journald.c | 9 +- src/journal/sd-journal.h | 124 ----------------- src/journal/test-journal.c | 3 +- src/kmsg-syslogd.c | 3 +- src/login/logind.c | 3 +- src/login/pam-module.c | 3 +- src/login/sd-login.h | 125 ----------------- src/login/test-login.c | 3 +- src/login/uaccess.c | 5 +- src/logs-show.h | 3 +- src/machine-id-setup.c | 3 +- src/manager.c | 3 +- src/notify.c | 3 +- src/nspawn.c | 3 +- src/readahead/readahead-collect.c | 3 +- src/readahead/readahead-replay.c | 3 +- src/readahead/sd-readahead.h | 73 ---------- src/sd-daemon.h | 277 -------------------------------------- src/sd-id128.c | 1 + src/sd-id128.h | 63 --------- src/shutdownd.c | 3 +- src/stdout-syslog-bridge.c | 3 +- src/systemctl.c | 3 +- src/systemd/sd-daemon.h | 277 ++++++++++++++++++++++++++++++++++++++ src/systemd/sd-id128.h | 63 +++++++++ src/systemd/sd-journal.h | 124 +++++++++++++++++ src/systemd/sd-login.h | 125 +++++++++++++++++ src/systemd/sd-readahead.h | 73 ++++++++++ src/test-daemon.c | 2 +- src/test-id128.c | 3 +- 36 files changed, 721 insertions(+), 697 deletions(-) delete mode 100644 src/journal/sd-journal.h delete mode 100644 src/login/sd-login.h delete mode 100644 src/readahead/sd-readahead.h delete mode 100644 src/sd-daemon.h delete mode 100644 src/sd-id128.h create mode 100644 src/systemd/sd-daemon.h create mode 100644 src/systemd/sd-id128.h create mode 100644 src/systemd/sd-journal.h create mode 100644 src/systemd/sd-login.h create mode 100644 src/systemd/sd-readahead.h (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index e668c09dd1..0c8804f481 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,7 +100,8 @@ AM_CPPFLAGS = \ -I $(top_srcdir)/src \ -I $(top_srcdir)/src/readahead \ -I $(top_srcdir)/src/login \ - -I $(top_srcdir)/src/journal + -I $(top_srcdir)/src/journal \ + -I $(top_srcdir)/src/systemd if TARGET_GENTOO AM_CPPFLAGS += \ @@ -1053,7 +1054,7 @@ libsystemd_daemon_la_LDFLAGS = \ -Wl,--version-script=$(top_srcdir)/src/libsystemd-daemon.sym pkginclude_HEADERS += \ - src/sd-daemon.h + src/systemd/sd-daemon.h # move lib from $(libdir) to $(rootlibdir) and update devel link, if needed libsystemd-daemon-install-hook: @@ -1131,7 +1132,7 @@ noinst_PROGRAMS += \ test-id128 pkginclude_HEADERS += \ - src/sd-id128.h + src/systemd/sd-id128.h lib_LTLIBRARIES += \ libsystemd-id128.la @@ -1290,8 +1291,8 @@ noinst_PROGRAMS += \ test-journal pkginclude_HEADERS += \ - src/journal/sd-journal.h \ - src/journal/sd-messages.h + src/systemd/sd-journal.h \ + src/systemd/sd-messages.h lib_LTLIBRARIES += \ libsystemd-journal.la @@ -1451,7 +1452,7 @@ nodist_systemunit_DATA += \ units/systemd-readahead-done.service EXTRA_DIST += \ - src/readahead/sd-readahead.h \ + src/systemd/sd-readahead.h \ src/readahead/readahead-common.h \ units/systemd-readahead-collect.service.in \ units/systemd-readahead-replay.service.in \ @@ -1878,7 +1879,7 @@ dist_pkgsysconf_DATA += \ src/login/systemd-logind.conf pkginclude_HEADERS += \ - src/login/sd-login.h + src/systemd/sd-login.h lib_LTLIBRARIES += \ libsystemd-login.la diff --git a/src/initctl.c b/src/initctl.c index 097c85fdd4..e2189e9ee1 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -34,13 +34,13 @@ #include #include +#include #include "util.h" #include "log.h" #include "list.h" #include "initreq.h" #include "special.h" -#include "sd-daemon.h" #include "dbus-common.h" #include "def.h" diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index ef0cb6dae6..964e0c2b81 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -24,8 +24,9 @@ #include +#include + #include "macro.h" -#include "sd-id128.h" typedef struct Header Header; typedef struct ObjectHeader ObjectHeader; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 51d7119d09..0be3932921 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -24,9 +24,10 @@ #include +#include + #include "journal-def.h" #include "util.h" -#include "sd-id128.h" typedef struct Window { void *ptr; diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 1b64666da3..e5914bfb63 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -26,8 +26,9 @@ #include #include +#include + #include "list.h" -#include "sd-id128.h" typedef struct Match Match; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 17d6a7fc23..2e708e959b 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -30,7 +30,8 @@ #include #include -#include "sd-journal.h" +#include + #include "log.h" #include "util.h" #include "build.h" diff --git a/src/journal/journald.c b/src/journal/journald.c index d6206a802f..d7f0ed52b4 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -32,19 +32,20 @@ #include #include +#include +#include +#include +#include + #include "hashmap.h" #include "journal-file.h" -#include "sd-daemon.h" #include "socket-util.h" #include "acl-util.h" #include "cgroup-util.h" #include "list.h" #include "journal-rate-limit.h" -#include "sd-journal.h" -#include "sd-login.h" #include "journal-internal.h" #include "conf-parser.h" -#include "sd-messages.h" #include "journald.h" #define USER_JOURNALS_MAX 1024 diff --git a/src/journal/sd-journal.h b/src/journal/sd-journal.h deleted file mode 100644 index 87da17ddc6..0000000000 --- a/src/journal/sd-journal.h +++ /dev/null @@ -1,124 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foojournalhfoo -#define foojournalhfoo - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include - -#include "sd-id128.h" - -/* TODO: - * - * - add options for copy-to-console, copy-to-kmsg - * - OR of matches is borked... - * - extend hash tables table as we go - * - accelerate looking for "all hostnames" and suchlike. - * - handle incomplete header - * - * - local deserializer - * - http server - * - message catalog - * - * - check LE/BE conversion for 8bit, 16bit, 32bit values - * - cryptographic hash - * - think about manipulations of header - * - implement audit gateway - */ - -/* Write to daemon */ - -int sd_journal_print(int piority, const char *format, ...) __attribute__ ((format (printf, 2, 3))); -int sd_journal_printv(int priority, const char *format, va_list ap); - -int sd_journal_send(const char *format, ...) __attribute__((sentinel)); -int sd_journal_sendv(const struct iovec *iov, int n); - -int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix); - -/* Browse journal stream */ - -typedef struct sd_journal sd_journal; - -enum { - SD_JOURNAL_LOCAL_ONLY = 1, - SD_JOURNAL_RUNTIME_ONLY = 2, - SD_JOURNAL_SYSTEM_ONLY = 4 -}; - -int sd_journal_open(sd_journal **ret, int flags); -void sd_journal_close(sd_journal *j); - -int sd_journal_previous(sd_journal *j); -int sd_journal_next(sd_journal *j); - -int sd_journal_previous_skip(sd_journal *j, uint64_t skip); -int sd_journal_next_skip(sd_journal *j, uint64_t skip); - -int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); -int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); -int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); -int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); -void sd_journal_restart_data(sd_journal *j); - -int sd_journal_add_match(sd_journal *j, const void *data, size_t size); -void sd_journal_flush_matches(sd_journal *j); - -int sd_journal_seek_head(sd_journal *j); -int sd_journal_seek_tail(sd_journal *j); -int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec); -int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); -int sd_journal_seek_cursor(sd_journal *j, const char *cursor); - -int sd_journal_get_cursor(sd_journal *j, char **cursor); - -int sd_journal_query_unique(sd_journal *j, const char *field); /* missing */ -int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */ -void sd_journal_restart_unique(sd_journal *j); /* missing */ - -enum { - SD_JOURNAL_NOP, - SD_JOURNAL_APPEND, - SD_JOURNAL_INVALIDATE_ADD, - SD_JOURNAL_INVALIDATE_REMOVE -}; - -int sd_journal_get_fd(sd_journal *j); -int sd_journal_process(sd_journal *j); - -#define SD_JOURNAL_FOREACH(j) \ - if (sd_journal_seek_head(j) >= 0) \ - while (sd_journal_next(j) > 0) - -#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ - if (sd_journal_seek_tail(j) >= 0) \ - while (sd_journal_previous(j) > 0) - -#define SD_JOURNAL_FOREACH_DATA(j, data, l) \ - for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) - -#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ - for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) - -#endif diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 3d429bea90..a023509b70 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -22,7 +22,8 @@ #include #include -#include "sd-journal.h" +#include + #include "journal-file.h" #include "log.h" diff --git a/src/kmsg-syslogd.c b/src/kmsg-syslogd.c index f42f72c2ad..da83bb2b1e 100644 --- a/src/kmsg-syslogd.c +++ b/src/kmsg-syslogd.c @@ -33,9 +33,10 @@ #include #include +#include + #include "util.h" #include "log.h" -#include "sd-daemon.h" #include "fdset.h" #define SERVER_FD_MAX 16 diff --git a/src/login/logind.c b/src/login/logind.c index 99534a52ed..4aeac0cc2e 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -29,8 +29,9 @@ #include #include +#include + #include "logind.h" -#include "sd-daemon.h" #include "dbus-common.h" #include "dbus-loop.h" #include "strv.h" diff --git a/src/login/pam-module.c b/src/login/pam-module.c index 14e706b374..82594c30d5 100644 --- a/src/login/pam-module.c +++ b/src/login/pam-module.c @@ -32,9 +32,10 @@ #include #include +#include + #include "util.h" #include "macro.h" -#include "sd-daemon.h" #include "strv.h" #include "dbus-common.h" #include "def.h" diff --git a/src/login/sd-login.h b/src/login/sd-login.h deleted file mode 100644 index 00de6716b0..0000000000 --- a/src/login/sd-login.h +++ /dev/null @@ -1,125 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foosdloginhfoo -#define foosdloginhfoo - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include - -/* - * A few points: - * - * Instead of returning an empty string array or empty uid array, we - * may return NULL. - * - * Free the data we return with libc free(). - * - * We return error codes as negative errno, kernel-style. 0 or - * positive on success. - * - * These functions access data in /proc, /sys/fs/cgroup and /run. All - * of these are virtual file systems, hence the accesses are - * relatively cheap. - */ - -/* Get session from PID. Note that 'shared' processes of a user are - * not attached to a session, but only attached to a user. This will - * return an error for system processes and 'shared' processes of a - * user. */ -int sd_pid_get_session(pid_t pid, char **session); - -/* Get UID of the owner of the session of the PID (or in case the - * process is a 'shared' user process the UID of that user is - * returned). This will not return the UID of the process, but rather - * the UID of the owner of the cgroup the process is in. This will - * return an error for system processes. */ -int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); - -/* Get systemd unit (i.e. service) name from PID. This will return an - * error for non-service processes. */ -int sd_pid_get_unit(pid_t, char **unit); - -/* Get state from uid. Possible states: offline, lingering, online, active */ -int sd_uid_get_state(uid_t uid, char**state); - -/* Return 1 if uid has session on seat. If require_active is true will - * look for active sessions only. */ -int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat); - -/* Return sessions of user. If require_active is true will look for - * active sessions only. Returns number of sessions as return - * value. If sessions is NULL will just return number of sessions. */ -int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); - -/* Return seats of user is on. If require_active is true will look for - * active seats only. Returns number of seats. If seats is NULL will - * just return number of seats.*/ -int sd_uid_get_seats(uid_t uid, int require_active, char ***seats); - -/* Return 1 if the session is a active */ -int sd_session_is_active(const char *session); - -/* Determine user id of session */ -int sd_session_get_uid(const char *session, uid_t *uid); - -/* Determine seat of session */ -int sd_session_get_seat(const char *session, char **seat); - -/* Return active session and user of seat */ -int sd_seat_get_active(const char *seat, char **session, uid_t *uid); - -/* Return sessions and users on seat. Returns number of sessions as - * return value. If sessions is NULL returns only the number of - * sessions. */ -int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); - -/* Return whether the seat is multi-session capable */ -int sd_seat_can_multi_session(const char *seat); - -/* Get all seats, store in *seats. Returns the number of seats. If - * seats is NULL only returns number of seats. */ -int sd_get_seats(char ***seats); - -/* Get all sessions, store in *sessions. Returns the number of - * sessions. If sessions is NULL only returns number of sessions. */ -int sd_get_sessions(char ***sessions); - -/* Get all logged in users, store in *users. Returns the number of - * users. If users is NULL only returns the number of users. */ -int sd_get_uids(uid_t **users); - -/* Monitor object */ -typedef struct sd_login_monitor sd_login_monitor; - -/* Create a new monitor. Category must be NULL, "seat", "session", - * "uid" to get monitor events for the specific category (or all). */ -int sd_login_monitor_new(const char *category, sd_login_monitor** ret); - -/* Destroys the passed monitor. Returns NULL. */ -sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m); - -/* Flushes the monitor */ -int sd_login_monitor_flush(sd_login_monitor *m); - -/* Get FD from monitor */ -int sd_login_monitor_get_fd(sd_login_monitor *m); - -#endif diff --git a/src/login/test-login.c b/src/login/test-login.c index 7d6f08202d..ae041b6a59 100644 --- a/src/login/test-login.c +++ b/src/login/test-login.c @@ -22,7 +22,8 @@ #include #include -#include "sd-login.h" +#include + #include "util.h" #include "strv.h" diff --git a/src/login/uaccess.c b/src/login/uaccess.c index 49ac4af0f4..e1af5bf431 100644 --- a/src/login/uaccess.c +++ b/src/login/uaccess.c @@ -22,11 +22,12 @@ #include #include +#include +#include + #include "logind-acl.h" #include "util.h" #include "log.h" -#include "sd-daemon.h" -#include "sd-login.h" int main(int argc, char *argv[]) { int r; diff --git a/src/logs-show.h b/src/logs-show.h index 5cf1a6369b..d3f3c75960 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -24,7 +24,8 @@ #include -#include "sd-journal.h" +#include + #include "util.h" typedef enum OutputMode { diff --git a/src/machine-id-setup.c b/src/machine-id-setup.c index 9b25b10438..531f3b2073 100644 --- a/src/machine-id-setup.c +++ b/src/machine-id-setup.c @@ -27,11 +27,12 @@ #include #include +#include + #include "machine-id-setup.h" #include "macro.h" #include "util.h" #include "log.h" -#include "sd-id128.h" static int generate(char id[34]) { int fd, r; diff --git a/src/manager.c b/src/manager.c index 9957bbf12a..7fd860ed06 100644 --- a/src/manager.c +++ b/src/manager.c @@ -41,6 +41,8 @@ #include #endif +#include + #include "manager.h" #include "hashmap.h" #include "macro.h" @@ -58,7 +60,6 @@ #include "special.h" #include "bus-errors.h" #include "exit-status.h" -#include "sd-daemon.h" #include "virt.h" /* As soon as 16 units are in our GC queue, make sure to run a gc sweep */ diff --git a/src/notify.c b/src/notify.c index a9bc51e2db..9d52bdfdd3 100644 --- a/src/notify.c +++ b/src/notify.c @@ -27,10 +27,11 @@ #include #include +#include + #include "strv.h" #include "util.h" #include "log.h" -#include "sd-daemon.h" #include "sd-readahead.h" static bool arg_ready = false; diff --git a/src/nspawn.c b/src/nspawn.c index 3ea603f235..b8b379d991 100644 --- a/src/nspawn.c +++ b/src/nspawn.c @@ -39,11 +39,12 @@ #include #include +#include + #include "log.h" #include "util.h" #include "missing.h" #include "cgroup-util.h" -#include "sd-daemon.h" #include "strv.h" #include "loopback-setup.h" diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index eac11e7e5c..6bff32f4dd 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -43,10 +43,11 @@ #include #include +#include + #include "missing.h" #include "util.h" #include "set.h" -#include "sd-daemon.h" #include "ioprio.h" #include "readahead-common.h" #include "virt.h" diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c index 65011ac4be..88c7a219a8 100644 --- a/src/readahead/readahead-replay.c +++ b/src/readahead/readahead-replay.c @@ -35,10 +35,11 @@ #include #include +#include + #include "missing.h" #include "util.h" #include "set.h" -#include "sd-daemon.h" #include "ioprio.h" #include "readahead-common.h" #include "virt.h" diff --git a/src/readahead/sd-readahead.h b/src/readahead/sd-readahead.h deleted file mode 100644 index ee7e30606e..0000000000 --- a/src/readahead/sd-readahead.h +++ /dev/null @@ -1,73 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foosdreadaheadhfoo -#define foosdreadaheadhfoo - -/*** - Copyright 2010 Lennart Poettering - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -***/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - Reference implementation of a few boot readahead related - interfaces. These interfaces are trivial to implement. To simplify - porting we provide this reference implementation. Applications are - welcome to reimplement the algorithms described here if they do not - want to include these two source files. - - You may compile this with -DDISABLE_SYSTEMD to disable systemd - support. This makes all calls NOPs. - - Since this is drop-in code we don't want any of our symbols to be - exported in any case. Hence we declare hidden visibility for all of - them. - - You may find an up-to-date version of these source files online: - - http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.h - http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.c - - This should compile on non-Linux systems, too, but all functions - will become NOPs. - - See sd-readahead(7) for more information. -*/ - -/* - Controls ongoing disk read-ahead operations during boot-up. The argument - must be a string, and either "cancel", "done" or "noreplay". - - cancel = terminate read-ahead data collection, drop collected information - done = terminate read-ahead data collection, keep collected information - noreplay = terminate read-ahead replay -*/ -int sd_readahead(const char *action); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/sd-daemon.h b/src/sd-daemon.h deleted file mode 100644 index 46dc7fd7e5..0000000000 --- a/src/sd-daemon.h +++ /dev/null @@ -1,277 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foosddaemonhfoo -#define foosddaemonhfoo - -/*** - Copyright 2010 Lennart Poettering - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -***/ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - Reference implementation of a few systemd related interfaces for - writing daemons. These interfaces are trivial to implement. To - simplify porting we provide this reference implementation. - Applications are welcome to reimplement the algorithms described - here if they do not want to include these two source files. - - The following functionality is provided: - - - Support for logging with log levels on stderr - - File descriptor passing for socket-based activation - - Daemon startup and status notification - - Detection of systemd boots - - You may compile this with -DDISABLE_SYSTEMD to disable systemd - support. This makes all those calls NOPs that are directly related to - systemd (i.e. only sd_is_xxx() will stay useful). - - Since this is drop-in code we don't want any of our symbols to be - exported in any case. Hence we declare hidden visibility for all of - them. - - You may find an up-to-date version of these source files online: - - http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h - http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c - - This should compile on non-Linux systems, too, but with the - exception of the sd_is_xxx() calls all functions will become NOPs. - - See sd-daemon(7) for more information. -*/ - -#ifndef _sd_printf_attr_ -#if __GNUC__ >= 4 -#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) -#else -#define _sd_printf_attr_(a,b) -#endif -#endif - -/* - Log levels for usage on stderr: - - fprintf(stderr, SD_NOTICE "Hello World!\n"); - - This is similar to printk() usage in the kernel. -*/ -#define SD_EMERG "<0>" /* system is unusable */ -#define SD_ALERT "<1>" /* action must be taken immediately */ -#define SD_CRIT "<2>" /* critical conditions */ -#define SD_ERR "<3>" /* error conditions */ -#define SD_WARNING "<4>" /* warning conditions */ -#define SD_NOTICE "<5>" /* normal but significant condition */ -#define SD_INFO "<6>" /* informational */ -#define SD_DEBUG "<7>" /* debug-level messages */ - -/* The first passed file descriptor is fd 3 */ -#define SD_LISTEN_FDS_START 3 - -/* - Returns how many file descriptors have been passed, or a negative - errno code on failure. Optionally, removes the $LISTEN_FDS and - $LISTEN_PID file descriptors from the environment (recommended, but - problematic in threaded environments). If r is the return value of - this function you'll find the file descriptors passed as fds - SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative - errno style error code on failure. This function call ensures that - the FD_CLOEXEC flag is set for the passed file descriptors, to make - sure they are not passed on to child processes. If FD_CLOEXEC shall - not be set, the caller needs to unset it after this call for all file - descriptors that are used. - - See sd_listen_fds(3) for more information. -*/ -int sd_listen_fds(int unset_environment); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a FIFO in the file system stored under the - specified path, 0 otherwise. If path is NULL a path name check will - not be done and the call only verifies if the file descriptor - refers to a FIFO. Returns a negative errno style error code on - failure. - - See sd_is_fifo(3) for more information. -*/ -int sd_is_fifo(int fd, const char *path); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a special character device on the file - system stored under the specified path, 0 otherwise. - If path is NULL a path name check will not be done and the call - only verifies if the file descriptor refers to a special character. - Returns a negative errno style error code on failure. - - See sd_is_special(3) for more information. -*/ -int sd_is_special(int fd, const char *path); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a socket of the specified family (AF_INET, - ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If - family is 0 a socket family check will not be done. If type is 0 a - socket type check will not be done and the call only verifies if - the file descriptor refers to a socket. If listening is > 0 it is - verified that the socket is in listening mode. (i.e. listen() has - been called) If listening is == 0 it is verified that the socket is - not in listening mode. If listening is < 0 no listening mode check - is done. Returns a negative errno style error code on failure. - - See sd_is_socket(3) for more information. -*/ -int sd_is_socket(int fd, int family, int type, int listening); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is an Internet socket, of the specified family - (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, - SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version - check is not done. If type is 0 a socket type check will not be - done. If port is 0 a socket port check will not be done. The - listening flag is used the same way as in sd_is_socket(). Returns a - negative errno style error code on failure. - - See sd_is_socket_inet(3) for more information. -*/ -int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is an AF_UNIX socket of the specified type - (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 - a socket type check will not be done. If path is NULL a socket path - check will not be done. For normal AF_UNIX sockets set length to - 0. For abstract namespace sockets set length to the length of the - socket name (including the initial 0 byte), and pass the full - socket path in path (including the initial 0 byte). The listening - flag is used the same way as in sd_is_socket(). Returns a negative - errno style error code on failure. - - See sd_is_socket_unix(3) for more information. -*/ -int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); - -/* - Helper call for identifying a passed file descriptor. Returns 1 if - the file descriptor is a POSIX Message Queue of the specified name, - 0 otherwise. If path is NULL a message queue name check is not - done. Returns a negative errno style error code on failure. -*/ -int sd_is_mq(int fd, const char *path); - -/* - Informs systemd about changed daemon state. This takes a number of - newline separated environment-style variable assignments in a - string. The following variables are known: - - READY=1 Tells systemd that daemon startup is finished (only - relevant for services of Type=notify). The passed - argument is a boolean "1" or "0". Since there is - little value in signaling non-readiness the only - value daemons should send is "READY=1". - - STATUS=... Passes a single-line status string back to systemd - that describes the daemon state. This is free-from - and can be used for various purposes: general state - feedback, fsck-like programs could pass completion - percentages and failing programs could pass a human - readable error message. Example: "STATUS=Completed - 66% of file system check..." - - ERRNO=... If a daemon fails, the errno-style error code, - formatted as string. Example: "ERRNO=2" for ENOENT. - - BUSERROR=... If a daemon fails, the D-Bus error-style error - code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" - - MAINPID=... The main pid of a daemon, in case systemd did not - fork off the process itself. Example: "MAINPID=4711" - - Daemons can choose to send additional variables. However, it is - recommended to prefix variable names not listed above with X_. - - Returns a negative errno-style error code on failure. Returns > 0 - if systemd could be notified, 0 if it couldn't possibly because - systemd is not running. - - Example: When a daemon finished starting up, it could issue this - call to notify systemd about it: - - sd_notify(0, "READY=1"); - - See sd_notifyf() for more complete examples. - - See sd_notify(3) for more information. -*/ -int sd_notify(int unset_environment, const char *state); - -/* - Similar to sd_notify() but takes a format string. - - Example 1: A daemon could send the following after initialization: - - sd_notifyf(0, "READY=1\n" - "STATUS=Processing requests...\n" - "MAINPID=%lu", - (unsigned long) getpid()); - - Example 2: A daemon could send the following shortly before - exiting, on failure: - - sd_notifyf(0, "STATUS=Failed to start up: %s\n" - "ERRNO=%i", - strerror(errno), - errno); - - See sd_notifyf(3) for more information. -*/ -int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); - -/* - Returns > 0 if the system was booted with systemd. Returns < 0 on - error. Returns 0 if the system was not booted with systemd. Note - that all of the functions above handle non-systemd boots just - fine. You should NOT protect them with a call to this function. Also - note that this function checks whether the system, not the user - session is controlled by systemd. However the functions above work - for both user and system services. - - See sd_booted(3) for more information. -*/ -int sd_booted(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/sd-id128.c b/src/sd-id128.c index 387cf919b0..289bcdc4ff 100644 --- a/src/sd-id128.c +++ b/src/sd-id128.c @@ -24,6 +24,7 @@ #include #include "sd-id128.h" + #include "util.h" #include "macro.h" diff --git a/src/sd-id128.h b/src/sd-id128.h deleted file mode 100644 index d835cf4768..0000000000 --- a/src/sd-id128.h +++ /dev/null @@ -1,63 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef fooid128hfoo -#define fooid128hfoo - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -typedef union sd_id128 sd_id128_t; - -union sd_id128 { - uint8_t bytes[16]; - uint64_t qwords[2]; -}; - -char *sd_id128_to_string(sd_id128_t id, char s[33]); - -int sd_id128_from_string(const char s[33], sd_id128_t *ret); - -int sd_id128_randomize(sd_id128_t *ret); - -sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id); - -int sd_id128_get_machine(sd_id128_t *ret); - -int sd_id128_get_boot(sd_id128_t *ret); - -#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ - ((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ - 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }}) - -/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16 - * times. It is hence not a good idea to call this macro with an - * expensive function as paramater or an expression with side - * effects */ -#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" -#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] - -static inline bool sd_id128_equal(sd_id128_t a, sd_id128_t b) { - return memcmp(&a, &b, 16) == 0; -} - -#endif diff --git a/src/shutdownd.c b/src/shutdownd.c index 46856b01ad..19b16cbe39 100644 --- a/src/shutdownd.c +++ b/src/shutdownd.c @@ -29,11 +29,12 @@ #include #include +#include + #include "shutdownd.h" #include "log.h" #include "macro.h" #include "util.h" -#include "sd-daemon.h" #include "utmp-wtmp.h" static int read_packet(int fd, struct shutdownd_command *_c) { diff --git a/src/stdout-syslog-bridge.c b/src/stdout-syslog-bridge.c index 6ec23ec612..e82716a1bd 100644 --- a/src/stdout-syslog-bridge.c +++ b/src/stdout-syslog-bridge.c @@ -32,10 +32,11 @@ #include #include +#include + #include "util.h" #include "log.h" #include "list.h" -#include "sd-daemon.h" #include "tcpwrap.h" #include "def.h" diff --git a/src/systemctl.c b/src/systemctl.c index 2f03f6baa8..9b915f65d6 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -35,6 +35,8 @@ #include #include +#include + #include "log.h" #include "util.h" #include "macro.h" @@ -49,7 +51,6 @@ #include "list.h" #include "path-lookup.h" #include "conf-parser.h" -#include "sd-daemon.h" #include "shutdownd.h" #include "exit-status.h" #include "bus-errors.h" diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h new file mode 100644 index 0000000000..46dc7fd7e5 --- /dev/null +++ b/src/systemd/sd-daemon.h @@ -0,0 +1,277 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foosddaemonhfoo +#define foosddaemonhfoo + +/*** + Copyright 2010 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Reference implementation of a few systemd related interfaces for + writing daemons. These interfaces are trivial to implement. To + simplify porting we provide this reference implementation. + Applications are welcome to reimplement the algorithms described + here if they do not want to include these two source files. + + The following functionality is provided: + + - Support for logging with log levels on stderr + - File descriptor passing for socket-based activation + - Daemon startup and status notification + - Detection of systemd boots + + You may compile this with -DDISABLE_SYSTEMD to disable systemd + support. This makes all those calls NOPs that are directly related to + systemd (i.e. only sd_is_xxx() will stay useful). + + Since this is drop-in code we don't want any of our symbols to be + exported in any case. Hence we declare hidden visibility for all of + them. + + You may find an up-to-date version of these source files online: + + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c + + This should compile on non-Linux systems, too, but with the + exception of the sd_is_xxx() calls all functions will become NOPs. + + See sd-daemon(7) for more information. +*/ + +#ifndef _sd_printf_attr_ +#if __GNUC__ >= 4 +#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) +#else +#define _sd_printf_attr_(a,b) +#endif +#endif + +/* + Log levels for usage on stderr: + + fprintf(stderr, SD_NOTICE "Hello World!\n"); + + This is similar to printk() usage in the kernel. +*/ +#define SD_EMERG "<0>" /* system is unusable */ +#define SD_ALERT "<1>" /* action must be taken immediately */ +#define SD_CRIT "<2>" /* critical conditions */ +#define SD_ERR "<3>" /* error conditions */ +#define SD_WARNING "<4>" /* warning conditions */ +#define SD_NOTICE "<5>" /* normal but significant condition */ +#define SD_INFO "<6>" /* informational */ +#define SD_DEBUG "<7>" /* debug-level messages */ + +/* The first passed file descriptor is fd 3 */ +#define SD_LISTEN_FDS_START 3 + +/* + Returns how many file descriptors have been passed, or a negative + errno code on failure. Optionally, removes the $LISTEN_FDS and + $LISTEN_PID file descriptors from the environment (recommended, but + problematic in threaded environments). If r is the return value of + this function you'll find the file descriptors passed as fds + SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative + errno style error code on failure. This function call ensures that + the FD_CLOEXEC flag is set for the passed file descriptors, to make + sure they are not passed on to child processes. If FD_CLOEXEC shall + not be set, the caller needs to unset it after this call for all file + descriptors that are used. + + See sd_listen_fds(3) for more information. +*/ +int sd_listen_fds(int unset_environment); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a FIFO in the file system stored under the + specified path, 0 otherwise. If path is NULL a path name check will + not be done and the call only verifies if the file descriptor + refers to a FIFO. Returns a negative errno style error code on + failure. + + See sd_is_fifo(3) for more information. +*/ +int sd_is_fifo(int fd, const char *path); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a special character device on the file + system stored under the specified path, 0 otherwise. + If path is NULL a path name check will not be done and the call + only verifies if the file descriptor refers to a special character. + Returns a negative errno style error code on failure. + + See sd_is_special(3) for more information. +*/ +int sd_is_special(int fd, const char *path); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a socket of the specified family (AF_INET, + ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If + family is 0 a socket family check will not be done. If type is 0 a + socket type check will not be done and the call only verifies if + the file descriptor refers to a socket. If listening is > 0 it is + verified that the socket is in listening mode. (i.e. listen() has + been called) If listening is == 0 it is verified that the socket is + not in listening mode. If listening is < 0 no listening mode check + is done. Returns a negative errno style error code on failure. + + See sd_is_socket(3) for more information. +*/ +int sd_is_socket(int fd, int family, int type, int listening); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is an Internet socket, of the specified family + (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, + SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version + check is not done. If type is 0 a socket type check will not be + done. If port is 0 a socket port check will not be done. The + listening flag is used the same way as in sd_is_socket(). Returns a + negative errno style error code on failure. + + See sd_is_socket_inet(3) for more information. +*/ +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is an AF_UNIX socket of the specified type + (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 + a socket type check will not be done. If path is NULL a socket path + check will not be done. For normal AF_UNIX sockets set length to + 0. For abstract namespace sockets set length to the length of the + socket name (including the initial 0 byte), and pass the full + socket path in path (including the initial 0 byte). The listening + flag is used the same way as in sd_is_socket(). Returns a negative + errno style error code on failure. + + See sd_is_socket_unix(3) for more information. +*/ +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a POSIX Message Queue of the specified name, + 0 otherwise. If path is NULL a message queue name check is not + done. Returns a negative errno style error code on failure. +*/ +int sd_is_mq(int fd, const char *path); + +/* + Informs systemd about changed daemon state. This takes a number of + newline separated environment-style variable assignments in a + string. The following variables are known: + + READY=1 Tells systemd that daemon startup is finished (only + relevant for services of Type=notify). The passed + argument is a boolean "1" or "0". Since there is + little value in signaling non-readiness the only + value daemons should send is "READY=1". + + STATUS=... Passes a single-line status string back to systemd + that describes the daemon state. This is free-from + and can be used for various purposes: general state + feedback, fsck-like programs could pass completion + percentages and failing programs could pass a human + readable error message. Example: "STATUS=Completed + 66% of file system check..." + + ERRNO=... If a daemon fails, the errno-style error code, + formatted as string. Example: "ERRNO=2" for ENOENT. + + BUSERROR=... If a daemon fails, the D-Bus error-style error + code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" + + MAINPID=... The main pid of a daemon, in case systemd did not + fork off the process itself. Example: "MAINPID=4711" + + Daemons can choose to send additional variables. However, it is + recommended to prefix variable names not listed above with X_. + + Returns a negative errno-style error code on failure. Returns > 0 + if systemd could be notified, 0 if it couldn't possibly because + systemd is not running. + + Example: When a daemon finished starting up, it could issue this + call to notify systemd about it: + + sd_notify(0, "READY=1"); + + See sd_notifyf() for more complete examples. + + See sd_notify(3) for more information. +*/ +int sd_notify(int unset_environment, const char *state); + +/* + Similar to sd_notify() but takes a format string. + + Example 1: A daemon could send the following after initialization: + + sd_notifyf(0, "READY=1\n" + "STATUS=Processing requests...\n" + "MAINPID=%lu", + (unsigned long) getpid()); + + Example 2: A daemon could send the following shortly before + exiting, on failure: + + sd_notifyf(0, "STATUS=Failed to start up: %s\n" + "ERRNO=%i", + strerror(errno), + errno); + + See sd_notifyf(3) for more information. +*/ +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); + +/* + Returns > 0 if the system was booted with systemd. Returns < 0 on + error. Returns 0 if the system was not booted with systemd. Note + that all of the functions above handle non-systemd boots just + fine. You should NOT protect them with a call to this function. Also + note that this function checks whether the system, not the user + session is controlled by systemd. However the functions above work + for both user and system services. + + See sd_booted(3) for more information. +*/ +int sd_booted(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h new file mode 100644 index 0000000000..d835cf4768 --- /dev/null +++ b/src/systemd/sd-id128.h @@ -0,0 +1,63 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef fooid128hfoo +#define fooid128hfoo + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +typedef union sd_id128 sd_id128_t; + +union sd_id128 { + uint8_t bytes[16]; + uint64_t qwords[2]; +}; + +char *sd_id128_to_string(sd_id128_t id, char s[33]); + +int sd_id128_from_string(const char s[33], sd_id128_t *ret); + +int sd_id128_randomize(sd_id128_t *ret); + +sd_id128_t sd_id128_make_v4_uuid(sd_id128_t id); + +int sd_id128_get_machine(sd_id128_t *ret); + +int sd_id128_get_boot(sd_id128_t *ret); + +#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ + ((sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ + 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }}) + +/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16 + * times. It is hence not a good idea to call this macro with an + * expensive function as paramater or an expression with side + * effects */ +#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" +#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] + +static inline bool sd_id128_equal(sd_id128_t a, sd_id128_t b) { + return memcmp(&a, &b, 16) == 0; +} + +#endif diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h new file mode 100644 index 0000000000..87da17ddc6 --- /dev/null +++ b/src/systemd/sd-journal.h @@ -0,0 +1,124 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foojournalhfoo +#define foojournalhfoo + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include + +#include "sd-id128.h" + +/* TODO: + * + * - add options for copy-to-console, copy-to-kmsg + * - OR of matches is borked... + * - extend hash tables table as we go + * - accelerate looking for "all hostnames" and suchlike. + * - handle incomplete header + * + * - local deserializer + * - http server + * - message catalog + * + * - check LE/BE conversion for 8bit, 16bit, 32bit values + * - cryptographic hash + * - think about manipulations of header + * - implement audit gateway + */ + +/* Write to daemon */ + +int sd_journal_print(int piority, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +int sd_journal_printv(int priority, const char *format, va_list ap); + +int sd_journal_send(const char *format, ...) __attribute__((sentinel)); +int sd_journal_sendv(const struct iovec *iov, int n); + +int sd_journal_stream_fd(const char *tag, int priority, int priority_prefix); + +/* Browse journal stream */ + +typedef struct sd_journal sd_journal; + +enum { + SD_JOURNAL_LOCAL_ONLY = 1, + SD_JOURNAL_RUNTIME_ONLY = 2, + SD_JOURNAL_SYSTEM_ONLY = 4 +}; + +int sd_journal_open(sd_journal **ret, int flags); +void sd_journal_close(sd_journal *j); + +int sd_journal_previous(sd_journal *j); +int sd_journal_next(sd_journal *j); + +int sd_journal_previous_skip(sd_journal *j, uint64_t skip); +int sd_journal_next_skip(sd_journal *j, uint64_t skip); + +int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); +int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); +int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); +void sd_journal_restart_data(sd_journal *j); + +int sd_journal_add_match(sd_journal *j, const void *data, size_t size); +void sd_journal_flush_matches(sd_journal *j); + +int sd_journal_seek_head(sd_journal *j); +int sd_journal_seek_tail(sd_journal *j); +int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec); +int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); +int sd_journal_seek_cursor(sd_journal *j, const char *cursor); + +int sd_journal_get_cursor(sd_journal *j, char **cursor); + +int sd_journal_query_unique(sd_journal *j, const char *field); /* missing */ +int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /* missing */ +void sd_journal_restart_unique(sd_journal *j); /* missing */ + +enum { + SD_JOURNAL_NOP, + SD_JOURNAL_APPEND, + SD_JOURNAL_INVALIDATE_ADD, + SD_JOURNAL_INVALIDATE_REMOVE +}; + +int sd_journal_get_fd(sd_journal *j); +int sd_journal_process(sd_journal *j); + +#define SD_JOURNAL_FOREACH(j) \ + if (sd_journal_seek_head(j) >= 0) \ + while (sd_journal_next(j) > 0) + +#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ + if (sd_journal_seek_tail(j) >= 0) \ + while (sd_journal_previous(j) > 0) + +#define SD_JOURNAL_FOREACH_DATA(j, data, l) \ + for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) + +#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ + for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) + +#endif diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h new file mode 100644 index 0000000000..00de6716b0 --- /dev/null +++ b/src/systemd/sd-login.h @@ -0,0 +1,125 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foosdloginhfoo +#define foosdloginhfoo + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include + +/* + * A few points: + * + * Instead of returning an empty string array or empty uid array, we + * may return NULL. + * + * Free the data we return with libc free(). + * + * We return error codes as negative errno, kernel-style. 0 or + * positive on success. + * + * These functions access data in /proc, /sys/fs/cgroup and /run. All + * of these are virtual file systems, hence the accesses are + * relatively cheap. + */ + +/* Get session from PID. Note that 'shared' processes of a user are + * not attached to a session, but only attached to a user. This will + * return an error for system processes and 'shared' processes of a + * user. */ +int sd_pid_get_session(pid_t pid, char **session); + +/* Get UID of the owner of the session of the PID (or in case the + * process is a 'shared' user process the UID of that user is + * returned). This will not return the UID of the process, but rather + * the UID of the owner of the cgroup the process is in. This will + * return an error for system processes. */ +int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); + +/* Get systemd unit (i.e. service) name from PID. This will return an + * error for non-service processes. */ +int sd_pid_get_unit(pid_t, char **unit); + +/* Get state from uid. Possible states: offline, lingering, online, active */ +int sd_uid_get_state(uid_t uid, char**state); + +/* Return 1 if uid has session on seat. If require_active is true will + * look for active sessions only. */ +int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat); + +/* Return sessions of user. If require_active is true will look for + * active sessions only. Returns number of sessions as return + * value. If sessions is NULL will just return number of sessions. */ +int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); + +/* Return seats of user is on. If require_active is true will look for + * active seats only. Returns number of seats. If seats is NULL will + * just return number of seats.*/ +int sd_uid_get_seats(uid_t uid, int require_active, char ***seats); + +/* Return 1 if the session is a active */ +int sd_session_is_active(const char *session); + +/* Determine user id of session */ +int sd_session_get_uid(const char *session, uid_t *uid); + +/* Determine seat of session */ +int sd_session_get_seat(const char *session, char **seat); + +/* Return active session and user of seat */ +int sd_seat_get_active(const char *seat, char **session, uid_t *uid); + +/* Return sessions and users on seat. Returns number of sessions as + * return value. If sessions is NULL returns only the number of + * sessions. */ +int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); + +/* Return whether the seat is multi-session capable */ +int sd_seat_can_multi_session(const char *seat); + +/* Get all seats, store in *seats. Returns the number of seats. If + * seats is NULL only returns number of seats. */ +int sd_get_seats(char ***seats); + +/* Get all sessions, store in *sessions. Returns the number of + * sessions. If sessions is NULL only returns number of sessions. */ +int sd_get_sessions(char ***sessions); + +/* Get all logged in users, store in *users. Returns the number of + * users. If users is NULL only returns the number of users. */ +int sd_get_uids(uid_t **users); + +/* Monitor object */ +typedef struct sd_login_monitor sd_login_monitor; + +/* Create a new monitor. Category must be NULL, "seat", "session", + * "uid" to get monitor events for the specific category (or all). */ +int sd_login_monitor_new(const char *category, sd_login_monitor** ret); + +/* Destroys the passed monitor. Returns NULL. */ +sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m); + +/* Flushes the monitor */ +int sd_login_monitor_flush(sd_login_monitor *m); + +/* Get FD from monitor */ +int sd_login_monitor_get_fd(sd_login_monitor *m); + +#endif diff --git a/src/systemd/sd-readahead.h b/src/systemd/sd-readahead.h new file mode 100644 index 0000000000..ee7e30606e --- /dev/null +++ b/src/systemd/sd-readahead.h @@ -0,0 +1,73 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foosdreadaheadhfoo +#define foosdreadaheadhfoo + +/*** + Copyright 2010 Lennart Poettering + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +***/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Reference implementation of a few boot readahead related + interfaces. These interfaces are trivial to implement. To simplify + porting we provide this reference implementation. Applications are + welcome to reimplement the algorithms described here if they do not + want to include these two source files. + + You may compile this with -DDISABLE_SYSTEMD to disable systemd + support. This makes all calls NOPs. + + Since this is drop-in code we don't want any of our symbols to be + exported in any case. Hence we declare hidden visibility for all of + them. + + You may find an up-to-date version of these source files online: + + http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.h + http://cgit.freedesktop.org/systemd/plain/src/sd-readahead.c + + This should compile on non-Linux systems, too, but all functions + will become NOPs. + + See sd-readahead(7) for more information. +*/ + +/* + Controls ongoing disk read-ahead operations during boot-up. The argument + must be a string, and either "cancel", "done" or "noreplay". + + cancel = terminate read-ahead data collection, drop collected information + done = terminate read-ahead data collection, keep collected information + noreplay = terminate read-ahead replay +*/ +int sd_readahead(const char *action); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/test-daemon.c b/src/test-daemon.c index c7600d4d63..20c5d1517e 100644 --- a/src/test-daemon.c +++ b/src/test-daemon.c @@ -21,7 +21,7 @@ #include -#include "sd-daemon.h" +#include int main(int argc, char*argv[]) { diff --git a/src/test-id128.c b/src/test-id128.c index d7c9d4326e..617c95568b 100644 --- a/src/test-id128.c +++ b/src/test-id128.c @@ -21,7 +21,8 @@ #include -#include "sd-id128.h" +#include + #include "util.h" #include "macro.h" -- cgit v1.2.3-54-g00ecf From 55ee336cdcb57efe2ef9a4152f5b9e1063ec1a06 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Jan 2012 16:28:17 +0100 Subject: journalctl: add --new-id switch to generate a new 128Bit id --- src/journal/journalctl.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 2e708e959b..914dd8d0f4 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -44,6 +44,7 @@ static bool arg_show_all = false; static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; +static bool arg_new_id = false; static int help(void) { @@ -56,7 +57,8 @@ static int help(void) { " -f --follow Follow journal\n" " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, verbose, export, json)\n", + " -o --output=STRING Change journal output mode (short, verbose, export, json)\n" + " --new-id Generate a new 128 Bit id\n", program_invocation_short_name); return 0; @@ -67,7 +69,8 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, - ARG_NO_TAIL + ARG_NO_TAIL, + ARG_NEW_ID }; static const struct option options[] = { @@ -79,6 +82,7 @@ static int parse_argv(int argc, char *argv[]) { { "all", no_argument, NULL, 'a' }, { "lines", required_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, + { "new-id", no_argument, NULL, ARG_NEW_ID }, { NULL, 0, NULL, 0 } }; @@ -134,6 +138,10 @@ static int parse_argv(int argc, char *argv[]) { arg_no_tail = true; break; + case ARG_NEW_ID: + arg_new_id = true; + break; + case '?': return -EINVAL; @@ -149,6 +157,34 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +static int generate_new_id(void) { + sd_id128_t id; + int r; + unsigned i; + + r = sd_id128_randomize(&id); + if (r < 0) { + log_error("Failed to generate ID: %s", strerror(-r)); + return r; + } + + printf("As string:\n" + SD_ID128_FORMAT_STR "\n\n" + "As UUID:\n" + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n" + "As macro:\n" + "#define MESSAGE_XYZ SD_ID128_MAKE(", + SD_ID128_FORMAT_VAL(id), + SD_ID128_FORMAT_VAL(id)); + + for (i = 0; i < 16; i++) + printf("%02x%s", id.bytes[i], i != 15 ? "," : ""); + + fputs(")\n", stdout); + + return 0; +} + int main(int argc, char *argv[]) { int r, i, fd; sd_journal *j = NULL; @@ -162,6 +198,11 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; + if (arg_new_id) { + r = generate_new_id(); + goto finish; + } + r = sd_journal_open(&j, 0); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); -- cgit v1.2.3-54-g00ecf From 39f7f5c108a55b8f6898154d4f7702a3443ac4d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Jan 2012 01:37:15 +0100 Subject: journalctl: rename --new-id to --new-id128 in order not to introduce yet another new name --- src/journal/journalctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 914dd8d0f4..393601c775 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -44,7 +44,7 @@ static bool arg_show_all = false; static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; -static bool arg_new_id = false; +static bool arg_new_id128 = false; static int help(void) { @@ -58,7 +58,7 @@ static int help(void) { " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, verbose, export, json)\n" - " --new-id Generate a new 128 Bit id\n", + " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); return 0; @@ -70,7 +70,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_TAIL, - ARG_NEW_ID + ARG_NEW_ID128 }; static const struct option options[] = { @@ -82,7 +82,7 @@ static int parse_argv(int argc, char *argv[]) { { "all", no_argument, NULL, 'a' }, { "lines", required_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, - { "new-id", no_argument, NULL, ARG_NEW_ID }, + { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { NULL, 0, NULL, 0 } }; @@ -138,8 +138,8 @@ static int parse_argv(int argc, char *argv[]) { arg_no_tail = true; break; - case ARG_NEW_ID: - arg_new_id = true; + case ARG_NEW_ID128: + arg_new_id128 = true; break; case '?': @@ -157,7 +157,7 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static int generate_new_id(void) { +static int generate_new_id128(void) { sd_id128_t id; int r; unsigned i; @@ -198,8 +198,8 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - if (arg_new_id) { - r = generate_new_id(); + if (arg_new_id128) { + r = generate_new_id128(); goto finish; } -- cgit v1.2.3-54-g00ecf From 67a122058b077efaed3b07706e91761e09de4f59 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 7 Jan 2012 04:41:30 +0100 Subject: journalctl: add new short-monotonic output mode --- src/journal/journalctl.c | 2 +- src/logs-show.c | 61 ++++++++++++++++++++++++++++++++++-------------- src/logs-show.h | 1 + src/systemctl.c | 2 +- 4 files changed, 46 insertions(+), 20 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 393601c775..910259f732 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -57,7 +57,7 @@ static int help(void) { " -f --follow Follow journal\n" " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, verbose, export, json)\n" + " -o --output=STRING Change journal output mode (short, short-verbose, verbose, export, json)\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); diff --git a/src/logs-show.c b/src/logs-show.c index decb89b6df..58d1e99dfa 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -84,12 +84,8 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, unsigned line, bool show_all) { +static int output_short(sd_journal *j, unsigned line, bool show_all, bool monotonic) { int r; - uint64_t realtime; - time_t t; - struct tm tm; - char buf[64]; const void *data; size_t length; size_t n = 0; @@ -140,20 +136,39 @@ static int output_short(sd_journal *j, unsigned line, bool show_all) { goto finish; } - r = sd_journal_get_realtime_usec(j, &realtime); - if (r < 0) { - log_error("Failed to get realtime: %s", strerror(-r)); - goto finish; - } + if (monotonic) { + uint64_t t; - t = (time_t) (realtime / USEC_PER_SEC); - if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { - log_error("Failed to format time."); - goto finish; - } + r = sd_journal_get_monotonic_usec(j, &t, NULL); + if (r >= 0) { + printf("[%5llu.%06llu]", + (unsigned long long) (t / USEC_PER_SEC), + (unsigned long long) (t % USEC_PER_SEC)); - fputs(buf, stdout); - n += strlen(buf); + n += 1 + 5 + 1 + 6 + 1; + } + + } else { + char buf[64]; + uint64_t realtime; + time_t t; + struct tm tm; + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) { + log_error("Failed to get realtime: %s", strerror(-r)); + goto finish; + } + + t = (time_t) (realtime / USEC_PER_SEC); + if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { + log_error("Failed to format time."); + goto finish; + } + + fputs(buf, stdout); + n += strlen(buf); + } if (hostname && shall_print(show_all, hostname, hostname_len)) { printf(" %.*s", (int) hostname_len, hostname); @@ -209,6 +224,14 @@ finish: return r; } +static int output_short_realtime(sd_journal *j, unsigned line, bool show_all) { + return output_short(j, line, show_all, false); +} + +static int output_short_monotonic(sd_journal *j, unsigned line, bool show_all) { + return output_short(j, line, show_all, true); +} + static int output_verbose(sd_journal *j, unsigned line, bool show_all) { const void *data; size_t length; @@ -432,7 +455,8 @@ static int output_json(sd_journal *j, unsigned line, bool show_all) { } static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = { - [OUTPUT_SHORT] = output_short, + [OUTPUT_SHORT] = output_short_realtime, + [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json @@ -575,6 +599,7 @@ finish: static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT] = "short", + [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", [OUTPUT_VERBOSE] = "verbose", [OUTPUT_EXPORT] = "export", [OUTPUT_JSON] = "json" diff --git a/src/logs-show.h b/src/logs-show.h index d3f3c75960..2158a44cea 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -30,6 +30,7 @@ typedef enum OutputMode { OUTPUT_SHORT, + OUTPUT_SHORT_MONOTONIC, OUTPUT_VERBOSE, OUTPUT_EXPORT, OUTPUT_JSON, diff --git a/src/systemctl.c b/src/systemctl.c index 9b915f65d6..dfdbd1d633 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -3979,7 +3979,7 @@ static int systemctl_help(void) { " --runtime Enable unit files only temporarily until next reboot\n" " -n --lines=INTEGER Journal entries to show\n" " --follow Follow journal\n" - " -o --output=STRING Change journal output mode (short, verbose, export, json)\n\n" + " -o --output=STRING Change journal output mode (short, short-monotonic, verbose, export, json)\n\n" "Unit Commands:\n" " list-units List loaded units\n" " start [NAME...] Start (activate) one or more units\n" -- cgit v1.2.3-54-g00ecf From d1e44dd8271c0e1348bbdb0046f8fa2437c4a567 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Jan 2012 16:03:42 +0100 Subject: journalctl: fix --help text --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 910259f732..b2ebc7a498 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -57,7 +57,7 @@ static int help(void) { " -f --follow Follow journal\n" " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, short-verbose, verbose, export, json)\n" + " -o --output=STRING Change journal output mode (short, short-monotonic, verbose, export, json)\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); -- cgit v1.2.3-54-g00ecf From d3f2bdbfee94a4cd124b66e610f4b926b749e192 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Jan 2012 02:58:45 +0100 Subject: journal: add output mode that just prints simple messages without any decorations --- src/journal/journalctl.c | 3 ++- src/logs-show.c | 27 +++++++++++++++++++++++++-- src/logs-show.h | 1 + src/systemctl.c | 3 ++- 4 files changed, 30 insertions(+), 4 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b2ebc7a498..4d9864729b 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -57,7 +57,8 @@ static int help(void) { " -f --follow Follow journal\n" " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, short-monotonic, verbose, export, json)\n" + " -o --output=STRING Change journal output mode (short, short-monotonic,\n" + " verbose, export, json, cat)\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); diff --git a/src/logs-show.c b/src/logs-show.c index 8d728a66de..8d1c77e5c3 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -488,12 +488,34 @@ static int output_json(sd_journal *j, unsigned line, bool show_all) { return 0; } +static int output_cat(sd_journal *j, unsigned line, bool show_all) { + const void *data; + size_t l; + int r; + + assert(j); + + r = sd_journal_get_data(j, "MESSAGE", &data, &l); + if (r < 0) { + log_error("Failed to get data: %s", strerror(-r)); + return r; + } + + assert(l >= 8); + + fwrite((const char*) data + 8, 1, l - 8, stdout); + putchar('\n'); + + return 0; +} + static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = { [OUTPUT_SHORT] = output_short_realtime, [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, - [OUTPUT_JSON] = output_json + [OUTPUT_JSON] = output_json, + [OUTPUT_CAT] = output_cat }; int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all) { @@ -636,7 +658,8 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", [OUTPUT_VERBOSE] = "verbose", [OUTPUT_EXPORT] = "export", - [OUTPUT_JSON] = "json" + [OUTPUT_JSON] = "json", + [OUTPUT_CAT] = "cat" }; DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); diff --git a/src/logs-show.h b/src/logs-show.h index 2158a44cea..abb82c8aac 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -34,6 +34,7 @@ typedef enum OutputMode { OUTPUT_VERBOSE, OUTPUT_EXPORT, OUTPUT_JSON, + OUTPUT_CAT, _OUTPUT_MODE_MAX, _OUTPUT_MODE_INVALID = -1 } OutputMode; diff --git a/src/systemctl.c b/src/systemctl.c index dfdbd1d633..b72fcbf807 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -3979,7 +3979,8 @@ static int systemctl_help(void) { " --runtime Enable unit files only temporarily until next reboot\n" " -n --lines=INTEGER Journal entries to show\n" " --follow Follow journal\n" - " -o --output=STRING Change journal output mode (short, short-monotonic, verbose, export, json)\n\n" + " -o --output=STRING Change journal output mode (short, short-monotonic,\n" + " verbose, export, json, cat)\n\n" "Unit Commands:\n" " list-units List loaded units\n" " start [NAME...] Start (activate) one or more units\n" -- cgit v1.2.3-54-g00ecf From 62f21ec91ad8e7e24079962f4df066b0094fe68d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 17 Jan 2012 15:21:40 +0100 Subject: journalctl: properly honour -n when -f is passed, too --- TODO | 8 ++++++++ src/journal/journalctl.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index ba510d2239..e2a19adef5 100644 --- a/TODO +++ b/TODO @@ -21,6 +21,14 @@ Bugfixes: Features: +* systemctl journal command + +* journalctl: --cursor support, priority filtering + +* systemctl status: show coredumps + +* systemctl status: show whether journal was rotated since service started + * save coredump in Windows/Mozilla minidump format * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 4d9864729b..52db7a9365 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -152,7 +152,7 @@ static int parse_argv(int argc, char *argv[]) { } } - if (arg_follow && !arg_no_tail) + if (arg_follow && !arg_no_tail && arg_lines < 0) arg_lines = 10; return 1; -- cgit v1.2.3-54-g00ecf From 8f2d43a0121bc9a57ba8b79b33d5ac87d36ca2f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 22 Jan 2012 18:21:15 +0100 Subject: cgtop: add new cgtop tool --- .gitignore | 1 + Makefile.am | 8 + src/cgtop.c | 729 +++++++++++++++++++++++++++++++++++++++++++++++ src/journal/journalctl.c | 2 +- src/logs-show.c | 2 +- src/util.c | 55 +++- src/util.h | 7 +- 7 files changed, 795 insertions(+), 9 deletions(-) create mode 100644 src/cgtop.c (limited to 'src/journal/journalctl.c') diff --git a/.gitignore b/.gitignore index 011aecec95..d27424ba9a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/systemd-cgtop /systemd-coredump /systemd-cat /systemd-rc-local-generator diff --git a/Makefile.am b/Makefile.am index 110a2f4df3..be5e70c9f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,6 +169,7 @@ rootbin_PROGRAMS = \ bin_PROGRAMS = \ systemd-cgls \ + systemd-cgtop \ systemd-stdio-bridge \ systemd-nspawn @@ -1008,6 +1009,13 @@ systemd_cgls_SOURCES = \ systemd_cgls_LDADD = \ libsystemd-basic.la +systemd_cgtop_SOURCES = \ + src/cgtop.c \ + src/cgroup-util.c + +systemd_cgtop_LDADD = \ + libsystemd-basic.la + systemd_nspawn_SOURCES = \ src/nspawn.c \ src/cgroup-util.c \ diff --git a/src/cgtop.c b/src/cgtop.c new file mode 100644 index 0000000000..4624bc4af5 --- /dev/null +++ b/src/cgtop.c @@ -0,0 +1,729 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "hashmap.h" +#include "cgroup-util.h" + +typedef struct Group { + char *path; + + bool n_tasks_valid:1; + bool cpu_valid:1; + bool memory_valid:1; + bool io_valid:1; + + unsigned n_tasks; + + unsigned cpu_iteration; + uint64_t cpu_usage; + struct timespec cpu_timestamp; + double cpu_fraction; + + uint64_t memory; + + unsigned io_iteration; + uint64_t io_input, io_output; + struct timespec io_timestamp; + uint64_t io_input_bps, io_output_bps; +} Group; + +static unsigned arg_depth = 2; +static usec_t arg_delay = 1*USEC_PER_SEC; + +static enum { + ORDER_PATH, + ORDER_TASKS, + ORDER_CPU, + ORDER_MEMORY, + ORDER_IO +} arg_order = ORDER_CPU; + +static void group_free(Group *g) { + assert(g); + + free(g->path); + free(g); +} + +static void group_hashmap_clear(Hashmap *h) { + Group *g; + + while ((g = hashmap_steal_first(h))) + group_free(g); +} + +static void group_hashmap_free(Hashmap *h) { + group_hashmap_clear(h); + hashmap_free(h); +} + +static int process(const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration) { + Group *g; + int r; + FILE *f; + pid_t pid; + unsigned n; + + assert(controller); + assert(path); + assert(a); + + g = hashmap_get(a, path); + if (!g) { + g = hashmap_get(b, path); + if (!g) { + g = new0(Group, 1); + if (!g) + return -ENOMEM; + + g->path = strdup(path); + if (!g->path) { + group_free(g); + return -ENOMEM; + } + + r = hashmap_put(a, g->path, g); + if (r < 0) { + group_free(g); + return r; + } + } else { + assert_se(hashmap_move_one(a, b, path) == 0); + g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false; + } + } + + /* Regardless which controller, let's find the maximum number + * of processes in any of it */ + + r = cg_enumerate_tasks(controller, path, &f); + if (r < 0) + return r; + + n = 0; + while (cg_read_pid(f, &pid) > 0) + n++; + fclose(f); + + if (n > 0) { + if (g->n_tasks_valid) + g->n_tasks = MAX(g->n_tasks, n); + else + g->n_tasks = n; + + g->n_tasks_valid = true; + } + + if (streq(controller, "cpuacct")) { + uint64_t new_usage; + char *p, *v; + struct timespec ts; + + r = cg_get_path(controller, path, "cpuacct.usage", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + free(p); + if (r < 0) + return r; + + r = safe_atou64(v, &new_usage); + free(v); + if (r < 0) + return r; + + assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); + + if (g->cpu_iteration == iteration - 1) { + uint64_t x, y; + + x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) - + ((uint64_t) g->cpu_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->cpu_timestamp.tv_nsec); + + y = new_usage - g->cpu_usage; + + if (y > 0) { + g->cpu_fraction = (double) y / (double) x; + g->cpu_valid = true; + } + } + + g->cpu_usage = new_usage; + g->cpu_timestamp = ts; + g->cpu_iteration = iteration; + + } else if (streq(controller, "memory")) { + char *p, *v; + + r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + free(p); + if (r < 0) + return r; + + r = safe_atou64(v, &g->memory); + free(v); + if (r < 0) + return r; + + if (g->memory > 0) + g->memory_valid = true; + + } else if (streq(controller, "blkio")) { + char *p; + uint64_t wr = 0, rd = 0; + struct timespec ts; + + r = cg_get_path(controller, path, "blkio.io_service_bytes", &p); + if (r < 0) + return r; + + f = fopen(p, "re"); + free(p); + + if (!f) + return -errno; + + for (;;) { + char line[LINE_MAX], *l; + uint64_t k, *q; + + if (!fgets(line, sizeof(line), f)) + break; + + l = strstrip(line); + l += strcspn(l, WHITESPACE); + l += strspn(l, WHITESPACE); + + if (first_word(l, "Read")) { + l += 4; + q = &rd; + } else if (first_word(l, "Write")) { + l += 5; + q = ≀ + } else + continue; + + l += strspn(l, WHITESPACE); + r = safe_atou64(l, &k); + if (r < 0) + continue; + + *q += k; + } + + fclose(f); + + assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); + + if (g->io_iteration == iteration - 1) { + uint64_t x, yr, yw; + + x = ((uint64_t) ts.tv_sec * 1000000000ULL + (uint64_t) ts.tv_nsec) - + ((uint64_t) g->io_timestamp.tv_sec * 1000000000ULL + (uint64_t) g->io_timestamp.tv_nsec); + + yr = rd - g->io_input; + yw = wr - g->io_output; + + if (yr > 0 || yw > 0) { + g->io_input_bps = (yr * 1000000000ULL) / x; + g->io_output_bps = (yw * 1000000000ULL) / x; + g->io_valid = true; + + } + } + + g->io_input = rd; + g->io_output = wr; + g->io_timestamp = ts; + g->io_iteration = iteration; + } + + return 0; +} + +static int refresh_one( + const char *controller, + const char *path, + Hashmap *a, + Hashmap *b, + unsigned iteration, + unsigned depth) { + + DIR *d = NULL; + int r; + + assert(controller); + assert(path); + assert(a); + + if (depth > arg_depth) + return 0; + + r = process(controller, path, a, b, iteration); + if (r < 0) + return r; + + r = cg_enumerate_subgroups(controller, path, &d); + if (r < 0) { + if (r == ENOENT) + return 0; + + return r; + } + + for (;;) { + char *fn, *p; + + r = cg_read_subgroup(d, &fn); + if (r <= 0) + goto finish; + + p = join(path, "/", fn, NULL); + free(fn); + + if (!p) { + r = -ENOMEM; + goto finish; + } + + path_kill_slashes(p); + + r = refresh_one(controller, p, a, b, iteration, depth + 1); + free(p); + + if (r < 0) + goto finish; + } + +finish: + if (d) + closedir(d); + + return r; +} + +static int refresh(Hashmap *a, Hashmap *b, unsigned iteration) { + int r; + + assert(a); + + r = refresh_one("name=systemd", "/", a, b, iteration, 0); + if (r < 0) + return r; + + r = refresh_one("cpuacct", "/", a, b, iteration, 0); + if (r < 0) + return r; + + r = refresh_one("memory", "/", a, b, iteration, 0); + if (r < 0) + return r; + + return refresh_one("blkio", "/", a, b, iteration, 0); +} + +static int group_compare(const void*a, const void *b) { + const Group *x = *(Group**)a, *y = *(Group**)b; + + if (path_startswith(y->path, x->path)) + return -1; + if (path_startswith(x->path, y->path)) + return 1; + + if (arg_order == ORDER_CPU) { + if (x->cpu_valid && y->cpu_valid) { + + if (x->cpu_fraction > y->cpu_fraction) + return -1; + else if (x->cpu_fraction < y->cpu_fraction) + return 1; + } else if (x->cpu_valid) + return -1; + else if (y->cpu_valid) + return 1; + } + + if (arg_order == ORDER_TASKS) { + + if (x->n_tasks_valid && y->n_tasks_valid) { + if (x->n_tasks > y->n_tasks) + return -1; + else if (x->n_tasks < y->n_tasks) + return 1; + } else if (x->n_tasks_valid) + return -1; + else if (y->n_tasks_valid) + return 1; + } + + if (arg_order == ORDER_MEMORY) { + if (x->memory_valid && y->memory_valid) { + if (x->memory > y->memory) + return -1; + else if (x->memory < y->memory) + return 1; + } else if (x->memory_valid) + return -1; + else if (y->memory_valid) + return 1; + } + + if (arg_order == ORDER_IO) { + if (x->io_valid && y->io_valid) { + if (x->io_input_bps + x->io_output_bps > y->io_input_bps + y->io_output_bps) + return -1; + else if (x->io_input_bps + x->io_output_bps < y->io_input_bps + y->io_output_bps) + return 1; + } else if (x->io_valid) + return -1; + else if (y->io_valid) + return 1; + } + + return strcmp(x->path, y->path); +} + +static int display(Hashmap *a) { + Iterator i; + Group *g; + Group **array; + unsigned rows, n = 0, j; + + assert(a); + + /* Set cursor to top left corner and clear screen */ + fputs("\033[H" + "\033[2J", stdout); + + array = alloca(sizeof(Group*) * hashmap_size(a)); + + HASHMAP_FOREACH(g, a, i) + if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) + array[n++] = g; + + qsort(array, n, sizeof(Group*), group_compare); + + rows = fd_lines(STDOUT_FILENO); + if (rows <= 0) + rows = 25; + + printf("%s%-37s%s %s%7s%s %s%6s%s %s%8s%s %s%8s%s %s%8s%s\n\n", + arg_order == ORDER_PATH ? ANSI_HIGHLIGHT_ON : "", "Path", arg_order == ORDER_PATH ? ANSI_HIGHLIGHT_OFF : "", + arg_order == ORDER_TASKS ? ANSI_HIGHLIGHT_ON : "", "Tasks", arg_order == ORDER_TASKS ? ANSI_HIGHLIGHT_OFF : "", + arg_order == ORDER_CPU ? ANSI_HIGHLIGHT_ON : "", "%CPU", arg_order == ORDER_CPU ? ANSI_HIGHLIGHT_OFF : "", + arg_order == ORDER_MEMORY ? ANSI_HIGHLIGHT_ON : "", "Memory", arg_order == ORDER_MEMORY ? ANSI_HIGHLIGHT_OFF : "", + arg_order == ORDER_IO ? ANSI_HIGHLIGHT_ON : "", "Input/s", arg_order == ORDER_IO ? ANSI_HIGHLIGHT_OFF : "", + arg_order == ORDER_IO ? ANSI_HIGHLIGHT_ON : "", "Output/s", arg_order == ORDER_IO ? ANSI_HIGHLIGHT_OFF : ""); + + for (j = 0; j < n; j++) { + char *p; + char m[FORMAT_BYTES_MAX]; + + if (j + 5 > rows) + break; + + g = array[j]; + + p = ellipsize(g->path, 37, 33); + printf("%-37s", p ? p : g->path); + free(p); + + if (g->n_tasks_valid) + printf(" %7u", g->n_tasks); + else + fputs(" -", stdout); + + if (g->cpu_valid) + printf(" %6.1f", g->cpu_fraction*100); + else + fputs(" -", stdout); + + if (g->memory_valid) + printf(" %8s", format_bytes(m, sizeof(m), g->memory)); + else + fputs(" -", stdout); + + if (g->io_valid) { + printf(" %8s", + format_bytes(m, sizeof(m), g->io_input_bps)); + printf(" %8s", + format_bytes(m, sizeof(m), g->io_output_bps)); + } else + fputs(" - -", stdout); + + putchar('\n'); + } + + return 0; +} + +static void help(void) { + + printf("%s [OPTIONS...]\n\n" + "Show top control groups by their resource usage.\n\n" + " -h --help Show this help\n" + " -p Order by path\n" + " -t Order by number of tasks\n" + " -c Order by CPU load\n" + " -m Order by memory load\n" + " -i Order by IO load\n" + " -d --delay=DELAY Specify delay\n" + " --depth=DEPTH Maximum traversal depth\n", + program_invocation_short_name); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_DEPTH = 0x100 + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "delay", required_argument, NULL, 'd' }, + { "depth", required_argument, NULL, ARG_DEPTH }, + { NULL, 0, NULL, 0 } + }; + + int c; + int r; + + assert(argc >= 1); + assert(argv); + + while ((c = getopt_long(argc, argv, "hptcmid:", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_DEPTH: + r = safe_atou(optarg, &arg_depth); + if (r < 0) { + log_error("Failed to parse depth parameter."); + return -EINVAL; + } + + break; + + case 'd': + r = parse_usec(optarg, &arg_delay); + if (r < 0 || arg_delay <= 0) { + log_error("Failed to parse delay parameter."); + return -EINVAL; + } + + break; + + case 'p': + arg_order = ORDER_PATH; + break; + + case 't': + arg_order = ORDER_TASKS; + break; + + case 'c': + arg_order = ORDER_CPU; + break; + + case 'm': + arg_order = ORDER_MEMORY; + break; + + case 'i': + arg_order = ORDER_IO; + break; + + case '?': + return -EINVAL; + + default: + log_error("Unknown option code %c", c); + return -EINVAL; + } + } + + if (optind < argc) { + log_error("Too many arguments."); + return -EINVAL; + } + + return 1; +} + +int main(int argc, char *argv[]) { + int r; + Hashmap *a = NULL, *b = NULL; + unsigned iteration = 0; + usec_t last_refresh = 0; + bool quit = false, immediate_refresh = false; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + a = hashmap_new(string_hash_func, string_compare_func); + b = hashmap_new(string_hash_func, string_compare_func); + if (!a || !b) { + log_error("Out of memory"); + r = -ENOMEM; + goto finish; + } + + while (!quit) { + Hashmap *c; + usec_t t; + char key; + char h[FORMAT_TIMESPAN_MAX]; + + t = now(CLOCK_MONOTONIC); + + if (t >= last_refresh + arg_delay || immediate_refresh) { + + r = refresh(a, b, iteration++); + if (r < 0) + goto finish; + + group_hashmap_clear(b); + + c = a; + a = b; + b = c; + + last_refresh = t; + immediate_refresh = false; + } + + r = display(b); + if (r < 0) + goto finish; + + r = read_one_char(stdin, &key, last_refresh + arg_delay - t, NULL); + if (r == -ETIMEDOUT) + continue; + if (r < 0) { + log_error("Couldn't read key: %s", strerror(-r)); + goto finish; + } + + fputs("\r \r", stdout); + fflush(stdout); + + switch (key) { + + case ' ': + immediate_refresh = true; + break; + + case 'q': + quit = true; + break; + + case 'p': + arg_order = ORDER_PATH; + break; + + case 't': + arg_order = ORDER_TASKS; + break; + + case 'c': + arg_order = ORDER_CPU; + break; + + case 'm': + arg_order = ORDER_MEMORY; + break; + + case 'i': + arg_order = ORDER_IO; + break; + + case '+': + if (arg_delay < USEC_PER_SEC) + arg_delay += USEC_PER_MSEC*250; + else + arg_delay += USEC_PER_SEC; + + fprintf(stdout, "\nIncreased delay to %s.", format_timespan(h, sizeof(h), arg_delay)); + fflush(stdout); + sleep(1); + break; + + case '-': + if (arg_delay <= USEC_PER_MSEC*500) + arg_delay = USEC_PER_MSEC*250; + else if (arg_delay < USEC_PER_MSEC*1250) + arg_delay -= USEC_PER_MSEC*250; + else + arg_delay -= USEC_PER_SEC; + + fprintf(stdout, "\nDecreased delay to %s.", format_timespan(h, sizeof(h), arg_delay)); + fflush(stdout); + sleep(1); + break; + + case '?': + case 'h': + fprintf(stdout, + "\t<" ANSI_HIGHLIGHT_ON "P" ANSI_HIGHLIGHT_OFF "> By path; <" ANSI_HIGHLIGHT_ON "T" ANSI_HIGHLIGHT_OFF "> By tasks; <" ANSI_HIGHLIGHT_ON "C" ANSI_HIGHLIGHT_OFF "> By CPU; <" ANSI_HIGHLIGHT_ON "M" ANSI_HIGHLIGHT_OFF "> By memory; <" ANSI_HIGHLIGHT_ON "I" ANSI_HIGHLIGHT_OFF "> By I/O\n" + "\t<" ANSI_HIGHLIGHT_ON "Q" ANSI_HIGHLIGHT_OFF "> Quit; <" ANSI_HIGHLIGHT_ON "+" ANSI_HIGHLIGHT_OFF "> Increase delay; <" ANSI_HIGHLIGHT_ON "-" ANSI_HIGHLIGHT_OFF "> Decrease delay; <" ANSI_HIGHLIGHT_ON "SPACE" ANSI_HIGHLIGHT_OFF "> Refresh"); + fflush(stdout); + sleep(3); + break; + + default: + fprintf(stdout, "\nUnknown key '%c'. Ignoring.", key); + fflush(stdout); + sleep(1); + break; + } + } + + log_info("Exiting."); + + r = 0; + +finish: + group_hashmap_free(a); + group_hashmap_free(b); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 52db7a9365..8db3fc9201 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -282,7 +282,7 @@ int main(int argc, char *argv[]) { if (!arg_follow) break; - r = fd_wait_for_event(fd, POLLIN); + r = fd_wait_for_event(fd, POLLIN, (usec_t) -1); if (r < 0) { log_error("Couldn't wait for event: %s", strerror(-r)); goto finish; diff --git a/src/logs-show.c b/src/logs-show.c index 5a00133140..f023f0aaef 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -633,7 +633,7 @@ int show_journal_by_unit( if (!follow) break; - r = fd_wait_for_event(fd, POLLIN); + r = fd_wait_for_event(fd, POLLIN, (usec_t) -1); if (r < 0) goto finish; diff --git a/src/util.c b/src/util.c index ef6eea4b9f..1babb6aed4 100644 --- a/src/util.c +++ b/src/util.c @@ -2434,7 +2434,7 @@ fail: return r; } -int read_one_char(FILE *f, char *ret, bool *need_nl) { +int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { struct termios old_termios, new_termios; char c; char line[LINE_MAX]; @@ -2452,6 +2452,13 @@ int read_one_char(FILE *f, char *ret, bool *need_nl) { if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) { size_t k; + if (t != (usec_t) -1) { + if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) { + tcsetattr(fileno(f), TCSADRAIN, &old_termios); + return -ETIMEDOUT; + } + } + k = fread(&c, 1, 1, f); tcsetattr(fileno(f), TCSADRAIN, &old_termios); @@ -2467,7 +2474,11 @@ int read_one_char(FILE *f, char *ret, bool *need_nl) { } } - if (!(fgets(line, sizeof(line), f))) + if (t != (usec_t) -1) + if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) + return -ETIMEDOUT; + + if (!fgets(line, sizeof(line), f)) return -EIO; truncate_nl(line); @@ -2509,7 +2520,8 @@ int ask(char *ret, const char *replies, const char *text, ...) { fflush(stdout); - if ((r = read_one_char(stdin, &c, &need_nl)) < 0) { + r = read_one_char(stdin, &c, (usec_t) -1, &need_nl); + if (r < 0) { if (r == -EBADMSG) { puts("Bad input, please try again."); @@ -4079,6 +4091,39 @@ unsigned columns(void) { return parsed_columns; } +int fd_lines(int fd) { + struct winsize ws; + zero(ws); + + if (ioctl(fd, TIOCGWINSZ, &ws) < 0) + return -errno; + + if (ws.ws_row <= 0) + return -EIO; + + return ws.ws_row; +} + +unsigned lines(void) { + static __thread int parsed_lines = 0; + const char *e; + + if (_likely_(parsed_lines > 0)) + return parsed_lines; + + e = getenv("LINES"); + if (e) + parsed_lines = atoi(e); + + if (parsed_lines <= 0) + parsed_lines = fd_lines(STDOUT_FILENO); + + if (parsed_lines <= 0) + parsed_lines = 25; + + return parsed_lines; +} + int running_in_chroot(void) { struct stat a, b; @@ -4850,7 +4895,7 @@ int pipe_eof(int fd) { return pollfd.revents & POLLHUP; } -int fd_wait_for_event(int fd, int event) { +int fd_wait_for_event(int fd, int event, usec_t t) { struct pollfd pollfd; int r; @@ -4858,7 +4903,7 @@ int fd_wait_for_event(int fd, int event) { pollfd.fd = fd; pollfd.events = event; - r = poll(&pollfd, 1, -1); + r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC)); if (r < 0) return -errno; diff --git a/src/util.h b/src/util.h index 1ce2440f3f..202d07a854 100644 --- a/src/util.h +++ b/src/util.h @@ -327,7 +327,7 @@ bool fstype_is_network(const char *fstype); int chvt(int vt); -int read_one_char(FILE *f, char *ret, bool *need_nl); +int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl); int ask(char *ret, const char *replies, const char *text, ...); int reset_terminal_fd(int fd); @@ -384,6 +384,9 @@ void status_welcome(void); int fd_columns(int fd); unsigned columns(void); +int fd_lines(int fd); +unsigned lines(void); + int running_in_chroot(void); char *ellipsize(const char *s, size_t length, unsigned percent); @@ -525,7 +528,7 @@ unsigned long cap_last_cap(void); char *format_bytes(char *buf, size_t l, off_t t); -int fd_wait_for_event(int fd, int event); +int fd_wait_for_event(int fd, int event, usec_t timeout); void* memdup(const void *p, size_t l); -- cgit v1.2.3-54-g00ecf From 4367379907f40cbe7df6a64e51c36f34dd854197 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 14 Mar 2012 19:54:22 +0100 Subject: journalctl: warn if the user is not in the adm group --- src/journal/journalctl.c | 11 ++++++++++- src/util.c | 30 ++++++++++++++++++++++++++++++ src/util.h | 2 ++ 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 8db3fc9201..5f8b240b00 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -45,6 +45,7 @@ static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; static bool arg_new_id128 = false; +static bool arg_quiet = false; static int help(void) { @@ -59,6 +60,7 @@ static int help(void) { " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, cat)\n" + " -q --quiet Don't show privilege warning\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); @@ -84,6 +86,7 @@ static int parse_argv(int argc, char *argv[]) { { "lines", required_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, + { "quiet", no_argument, NULL, 'q' }, { NULL, 0, NULL, 0 } }; @@ -92,7 +95,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:q", options, NULL)) >= 0) { switch (c) { @@ -143,6 +146,9 @@ static int parse_argv(int argc, char *argv[]) { arg_new_id128 = true; break; + case 'q': + arg_quiet = true; + case '?': return -EINVAL; @@ -204,6 +210,9 @@ int main(int argc, char *argv[]) { goto finish; } + if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) + log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); + r = sd_journal_open(&j, 0); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); diff --git a/src/util.c b/src/util.c index 73481abee6..20cbc2b0db 100644 --- a/src/util.c +++ b/src/util.c @@ -5608,6 +5608,36 @@ int get_group_creds(const char **groupname, gid_t *gid) { return 0; } +int in_group(const char *name) { + gid_t gid, *gids; + int ngroups_max, r, i; + + r = get_group_creds(&name, &gid); + if (r < 0) + return r; + + if (getgid() == gid) + return 1; + + if (getegid() == gid) + return 1; + + ngroups_max = sysconf(_SC_NGROUPS_MAX); + assert(ngroups_max > 0); + + gids = alloca(sizeof(gid_t) * ngroups_max); + + r = getgroups(ngroups_max, gids); + if (r < 0) + return -errno; + + for (i = 0; i < r; i++) + if (gids[i] == gid) + return 1; + + return 0; +} + int glob_exists(const char *path) { glob_t g; int r, k; diff --git a/src/util.h b/src/util.h index 890a3b5d46..b1af6dbe7c 100644 --- a/src/util.h +++ b/src/util.h @@ -466,6 +466,8 @@ int socket_from_display(const char *display, char **path); int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home); int get_group_creds(const char **groupname, gid_t *gid); +int in_group(const char *name); + int glob_exists(const char *path); int dirent_ensure_type(DIR *d, struct dirent *de); -- cgit v1.2.3-54-g00ecf From 4f4d6a7073e6aa740291bbe54da809024d372955 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Mar 2012 00:44:10 +0100 Subject: journalctl: suppress messages about adm group if ACL support is not enabled --- src/journal/journalctl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5f8b240b00..38c9d73b44 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -210,8 +210,10 @@ int main(int argc, char *argv[]) { goto finish; } +#ifdef HAVE_ACL if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); +#endif r = sd_journal_open(&j, 0); if (r < 0) { -- cgit v1.2.3-54-g00ecf From 490e567dbb12928528d395d2c759b80960312e8f Mon Sep 17 00:00:00 2001 From: Tero Roponen Date: Thu, 15 Mar 2012 08:26:55 +0200 Subject: journalctl: add a missing 'break' There is a 'break' missing in the -q handling so, for example, 'systemd-journalctl --new-id128 -q' does nothing. This patch fixes the problem. --- src/journal/journalctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 38c9d73b44..089086eb98 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -148,6 +148,7 @@ static int parse_argv(int argc, char *argv[]) { case 'q': arg_quiet = true; + break; case '?': return -EINVAL; -- cgit v1.2.3-54-g00ecf From 34a35eced40860181757abe5ec00ac0e5d8d0225 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 15 Mar 2012 20:49:25 +0100 Subject: a couple of fixes to make llvm-analyze quiet --- src/journal/journalctl.c | 2 +- src/journal/journald.c | 9 +++------ src/kmod-setup.c | 2 +- src/logs-show.c | 42 +++++++++++++++++++----------------------- src/logs-show.h | 3 +-- src/systemctl.c | 2 +- 6 files changed, 26 insertions(+), 34 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 089086eb98..d5560723bc 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -284,7 +284,7 @@ int main(int argc, char *argv[]) { line ++; - r = output_journal(j, arg_output, line, arg_show_all); + r = output_journal(j, arg_output, line, 0, arg_show_all); if (r < 0) goto finish; diff --git a/src/journal/journald.c b/src/journal/journald.c index 74a58b0462..baad3ab1ad 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -154,13 +154,10 @@ static uint64_t available_space(Server *s) { for (;;) { struct stat st; struct dirent buf, *de; - int k; - k = readdir_r(d, &buf, &de); - if (k != 0) { - r = -k; - goto finish; - } + r = readdir_r(d, &buf, &de); + if (r != 0) + break; if (!de) break; diff --git a/src/kmod-setup.c b/src/kmod-setup.c index dc3515676f..debf87130d 100644 --- a/src/kmod-setup.c +++ b/src/kmod-setup.c @@ -90,7 +90,7 @@ int kmod_setup(void) { } if (ctx) - ctx = kmod_unref(ctx); + kmod_unref(ctx); return 0; } diff --git a/src/logs-show.c b/src/logs-show.c index f023f0aaef..f71c6b0845 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -86,7 +86,7 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, unsigned line, bool show_all, bool monotonic_mode) { +static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool show_all, bool monotonic_mode) { int r; const void *data; size_t length; @@ -228,12 +228,12 @@ static int output_short(sd_journal *j, unsigned line, bool show_all, bool monoto else if (contains_unprintable(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else if (message_len + n < columns()) + } else if (message_len + n < n_columns) printf(": %.*s\n", (int) message_len, message); - else if (n < columns()) { + else if (n < n_columns) { char *e; - e = ellipsize_mem(message, message_len, columns() - n - 2, 90); + e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); if (!e) printf(": %.*s\n", (int) message_len, message); @@ -259,15 +259,15 @@ finish: return r; } -static int output_short_realtime(sd_journal *j, unsigned line, bool show_all) { - return output_short(j, line, show_all, false); +static int output_short_realtime(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { + return output_short(j, line, n_columns, show_all, false); } -static int output_short_monotonic(sd_journal *j, unsigned line, bool show_all) { - return output_short(j, line, show_all, true); +static int output_short_monotonic(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { + return output_short(j, line, n_columns, show_all, true); } -static int output_verbose(sd_journal *j, unsigned line, bool show_all) { +static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { const void *data; size_t length; char *cursor; @@ -318,7 +318,7 @@ static int output_verbose(sd_journal *j, unsigned line, bool show_all) { return 0; } -static int output_export(sd_journal *j, unsigned line, bool show_all) { +static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { sd_id128_t boot_id; char sid[33]; int r; @@ -424,7 +424,7 @@ static void json_escape(const char* p, size_t l) { } } -static int output_json(sd_journal *j, unsigned line, bool show_all) { +static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { uint64_t realtime, monotonic; char *cursor; const void *data; @@ -491,7 +491,7 @@ static int output_json(sd_journal *j, unsigned line, bool show_all) { return 0; } -static int output_cat(sd_journal *j, unsigned line, bool show_all) { +static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { const void *data; size_t l; int r; @@ -512,7 +512,7 @@ static int output_cat(sd_journal *j, unsigned line, bool show_all) { return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = { +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsigned n_columns, bool show_all) = { [OUTPUT_SHORT] = output_short_realtime, [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, [OUTPUT_VERBOSE] = output_verbose, @@ -521,17 +521,19 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool s [OUTPUT_CAT] = output_cat }; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all) { +int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all) { assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); - return output_funcs[mode](j, line, show_all); + if (n_columns <= 0) + n_columns = columns(); + + return output_funcs[mode](j, line, n_columns, show_all); } int show_journal_by_unit( const char *unit, OutputMode mode, - const char *prefix, unsigned n_columns, usec_t not_before, unsigned how_many, @@ -558,12 +560,6 @@ int show_journal_by_unit( if (how_many <= 0) return 0; - if (n_columns <= 0) - n_columns = columns(); - - if (!prefix) - prefix = ""; - if (asprintf(&m, "_SYSTEMD_UNIT=%s", unit) < 0) { r = -ENOMEM; goto finish; @@ -625,7 +621,7 @@ int show_journal_by_unit( line ++; - r = output_journal(j, mode, line, show_all); + r = output_journal(j, mode, line, n_columns, show_all); if (r < 0) goto finish; } diff --git a/src/logs-show.h b/src/logs-show.h index abb82c8aac..db9c7e34ab 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -39,12 +39,11 @@ typedef enum OutputMode { _OUTPUT_MODE_INVALID = -1 } OutputMode; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all); +int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all); int show_journal_by_unit( const char *unit, OutputMode mode, - const char *prefix, unsigned n_columns, usec_t not_before, unsigned how_many, diff --git a/src/systemctl.c b/src/systemctl.c index 8f99a724b8..f51085f8c4 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -2375,7 +2375,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->id && arg_transport != TRANSPORT_SSH) { printf("\n"); - show_journal_by_unit(i->id, arg_output, NULL, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow); + show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow); } if (i->need_daemon_reload) -- cgit v1.2.3-54-g00ecf From 2af777ba966fcaefb02e87524583917726a470a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 16 Mar 2012 00:50:52 +0100 Subject: man: document systemd-journalctl(1) --- Makefile.am | 3 +- man/systemd-journalctl.xml | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/journal/journalctl.c | 2 +- 3 files changed, 255 insertions(+), 2 deletions(-) create mode 100644 man/systemd-journalctl.xml (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 0b2660ae5f..ea342bc839 100644 --- a/Makefile.am +++ b/Makefile.am @@ -694,7 +694,8 @@ MANPAGES = \ man/systemd-ask-password.1 \ man/systemd-cat.1 \ man/systemd-machine-id-setup.1 \ - man/systemd-journald.conf.5 + man/systemd-journald.conf.5 \ + man/systemd-journalctl.1 MANPAGES_ALIAS = \ man/reboot.8 \ diff --git a/man/systemd-journalctl.xml b/man/systemd-journalctl.xml new file mode 100644 index 0000000000..ff3bb3d057 --- /dev/null +++ b/man/systemd-journalctl.xml @@ -0,0 +1,252 @@ + + + + + + + + + systemd-journalctl + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd-journalctl + 1 + + + + systemd-journalctl + Query the systemd journal + + + + + systemd-journalctl OPTIONS MATCH + + + + + Description + + systemd-journalctl may be + used to query the contents of the + systemd1 + journal. + + If called without parameter will show the full + contents of the journal, starting with the oldest + entry collected. + + If a match argument is passed the output is + filtered accordingly. A match is in the format + FIELD=VALUE, + e.g. _SYSTEMD_UNIT=httpd.service. + + Output is interleaved from all accessible + journal files, whether they are rotated or currently + being written, and regardless whether they belong to the + system itself or are accessible user journals. + + All users are granted access to their private + per-user journals. However, by default only root and + users who are members of the adm + group get access to the system journal and the + journals of other users. + + + + Options + + The following options are understood: + + + + + + + Prints a short help + text and exits. + + + + + + Prints a short version + string and exits. + + + + + + Do not pipe output into a + pager. + + + + + + + Show all fields in + full, even if they include unprintable + characters or are very + long. + + + + + + + Show only most recent + entries, and continously print new + entries as they are appended to the + journal. + + + + + + + Controls the number of + journal lines to show, counting from + the most recent ones. Takes a positive + integer argument. In follow mode + defaults to 10, otherwise is unset + thus not limiting how many lines are + shown. + + + + + + Show all stored output + lines, even in follow mode. Undoes the + effect of + . + + + + + + + Controls the + formatting of the entries that are + shown. Takes one of + short, + short-monotonic, + verbose, + export, + json, + cat. short + is the default and generates an output + that is mostly identical to the + formatting of classic syslog log + files, showing one line per journal + entry. short-monotonic + is very similar but shows monotonic + timestamps instead of wallclock + timestamps. verbose + shows the full structered entry items + with all + fiels. export + serializes the journal into a binary + (but mostly text-based) stream + suitable for backups and network + transfer. json + formats entries as JSON data + structures. cat + generates a very terse output only + showing the actual message of each + journal entry with no meta data, not + even a timestamp. + + + + + + + Suppresses any warning + message regarding inaccessable system + journals when run as normal + user. + + + + + + Instead of showing + journal contents generate a new 128 + bit ID suitable for identifying + messages. This is intended for usage + by developers who need a new + identifier for a new message they + introduce and want to make + recognizable. Will print the new ID in + three different formats which can be + copied into source code or + similar. + + + + + + + Exit status + + On success 0 is returned, a non-zero failure + code otherwise. + + + + Environment + + + + $SYSTEMD_PAGER + Pager to use when + is not given; + overrides $PAGER. Setting + this to an empty string or the value + cat is equivalent to passing + . + + + + + + See Also + + systemd1, + systemctl1, + systemd-journald.conf5 + + + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index d5560723bc..f90b2ddabe 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -54,7 +54,7 @@ static int help(void) { " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" - " -a --all Show all properties, including long and unprintable\n" + " -a --all Show all fields, including long and unprintable\n" " -f --follow Follow journal\n" " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" -- cgit v1.2.3-54-g00ecf From 2bd3c38a44c5c3acbf5afdb9c0bcbaf4a72dac3f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 27 Mar 2012 00:14:29 +0200 Subject: journalctl: add --local switch --- TODO | 2 ++ man/journalctl.xml | 8 ++++++++ src/journal/journalctl.c | 13 ++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 7f19c3adcb..2fe676a724 100644 --- a/TODO +++ b/TODO @@ -18,6 +18,8 @@ Bugfixes: Features: +* Make -f in systemctl enable both --follow and --force + * ensure that logind sets the syslog facility to AUTH when logging * when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting diff --git a/man/journalctl.xml b/man/journalctl.xml index c4d2a7e0e8..efceefa43f 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -199,6 +199,14 @@ user. + + + + + Show only locally + generated messages. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f90b2ddabe..01dceca237 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -46,6 +46,7 @@ static int arg_lines = -1; static bool arg_no_tail = false; static bool arg_new_id128 = false; static bool arg_quiet = false; +static bool arg_local = false; static int help(void) { @@ -61,7 +62,8 @@ static int help(void) { " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, cat)\n" " -q --quiet Don't show privilege warning\n" - " --new-id128 Generate a new 128 Bit id\n", + " --new-id128 Generate a new 128 Bit id\n" + " -l --local Only local entries\n", program_invocation_short_name); return 0; @@ -87,6 +89,7 @@ static int parse_argv(int argc, char *argv[]) { { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, + { "local", no_argument, NULL, 'l' }, { NULL, 0, NULL, 0 } }; @@ -95,7 +98,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:q", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:ql", options, NULL)) >= 0) { switch (c) { @@ -150,6 +153,10 @@ static int parse_argv(int argc, char *argv[]) { arg_quiet = true; break; + case 'l': + arg_local = true; + break; + case '?': return -EINVAL; @@ -216,7 +223,7 @@ int main(int argc, char *argv[]) { log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); #endif - r = sd_journal_open(&j, 0); + r = sd_journal_open(&j, arg_local ? SD_JOURNAL_LOCAL_ONLY : 0); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); goto finish; -- cgit v1.2.3-54-g00ecf From 5430f7f2bc7330f3088b894166bf3524a067e3d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 12 Apr 2012 00:20:58 +0200 Subject: relicense to LGPLv2.1 (with exceptions) We finally got the OK from all contributors with non-trivial commits to relicense systemd from GPL2+ to LGPL2.1+. Some udev bits continue to be GPL2+ for now, but we are looking into relicensing them too, to allow free copy/paste of all code within systemd. The bits that used to be MIT continue to be MIT. The big benefit of the relicensing is that closed source code may now link against libsystemd-login.so and friends. --- LICENSE | 339 --------------- LICENSE.GPL2 | 339 +++++++++++++++ LICENSE.LGPL2.1 | 508 +++++++++++++++++++++++ LICENSE.MIT | 19 + Makefile.am | 12 +- README | 10 +- autogen.sh | 8 +- configure.ac | 8 +- man/binfmt.d.xml | 8 +- man/custom-html.xsl | 8 +- man/daemon.xml | 8 +- man/halt.xml | 8 +- man/hostname.xml | 8 +- man/journalctl.xml | 8 +- man/journald.conf.xml | 8 +- man/locale.conf.xml | 8 +- man/loginctl.xml | 8 +- man/logind.conf.xml | 8 +- man/machine-id.xml | 8 +- man/machine-info.xml | 8 +- man/modules-load.d.xml | 8 +- man/os-release.xml | 8 +- man/pam_systemd.xml | 8 +- man/runlevel.xml | 8 +- man/sd-daemon.xml | 8 +- man/sd-login.xml | 8 +- man/sd-readahead.xml | 8 +- man/sd_booted.xml | 8 +- man/sd_get_seats.xml | 8 +- man/sd_is_fifo.xml | 8 +- man/sd_listen_fds.xml | 8 +- man/sd_login_monitor_new.xml | 8 +- man/sd_notify.xml | 8 +- man/sd_pid_get_session.xml | 8 +- man/sd_readahead.xml | 8 +- man/sd_seat_get_active.xml | 8 +- man/sd_session_is_active.xml | 8 +- man/sd_uid_get_state.xml | 8 +- man/shutdown.xml | 8 +- man/sysctl.d.xml | 8 +- man/systemctl.xml | 8 +- man/systemd-ask-password.xml | 8 +- man/systemd-cat.xml | 8 +- man/systemd-cgls.xml | 8 +- man/systemd-cgtop.xml | 8 +- man/systemd-machine-id-setup.xml | 8 +- man/systemd-notify.xml | 8 +- man/systemd-nspawn.xml | 8 +- man/systemd-tmpfiles.xml | 8 +- man/systemd.automount.xml | 8 +- man/systemd.conf.xml | 8 +- man/systemd.device.xml | 8 +- man/systemd.exec.xml | 8 +- man/systemd.journal-fields.xml | 8 +- man/systemd.mount.xml | 8 +- man/systemd.path.xml | 8 +- man/systemd.service.xml | 8 +- man/systemd.snapshot.xml | 8 +- man/systemd.socket.xml | 8 +- man/systemd.special.xml | 8 +- man/systemd.swap.xml | 8 +- man/systemd.target.xml | 8 +- man/systemd.timer.xml | 8 +- man/systemd.unit.xml | 8 +- man/systemd.xml | 8 +- man/telinit.xml | 8 +- man/timezone.xml | 8 +- man/tmpfiles.d.xml | 8 +- man/vconsole.conf.xml | 8 +- rules/99-systemd.rules.in | 4 +- src/Makefile | 8 +- src/ac-power.c | 8 +- src/ask-password-api.c | 8 +- src/ask-password.c | 8 +- src/binfmt/binfmt.c | 8 +- src/bridge.c | 8 +- src/cgls.c | 8 +- src/cgroup-show.c | 8 +- src/cgroup-show.h | 8 +- src/cgroups-agent.c | 8 +- src/cgtop.c | 8 +- src/core/ask-password-api.h | 8 +- src/core/automount.c | 8 +- src/core/automount.h | 8 +- src/core/build.h | 8 +- src/core/bus-errors.h | 8 +- src/core/cgroup-attr.c | 8 +- src/core/cgroup-attr.h | 8 +- src/core/cgroup.c | 8 +- src/core/cgroup.h | 8 +- src/core/condition.c | 8 +- src/core/condition.h | 8 +- src/core/dbus-automount.c | 8 +- src/core/dbus-automount.h | 8 +- src/core/dbus-device.c | 8 +- src/core/dbus-device.h | 8 +- src/core/dbus-execute.c | 8 +- src/core/dbus-execute.h | 8 +- src/core/dbus-job.c | 8 +- src/core/dbus-job.h | 8 +- src/core/dbus-loop.h | 8 +- src/core/dbus-manager.c | 8 +- src/core/dbus-manager.h | 8 +- src/core/dbus-mount.c | 8 +- src/core/dbus-mount.h | 8 +- src/core/dbus-path.c | 8 +- src/core/dbus-path.h | 8 +- src/core/dbus-service.c | 8 +- src/core/dbus-service.h | 8 +- src/core/dbus-snapshot.c | 8 +- src/core/dbus-snapshot.h | 8 +- src/core/dbus-socket.c | 8 +- src/core/dbus-socket.h | 8 +- src/core/dbus-swap.c | 8 +- src/core/dbus-swap.h | 8 +- src/core/dbus-target.c | 8 +- src/core/dbus-target.h | 8 +- src/core/dbus-timer.c | 8 +- src/core/dbus-timer.h | 8 +- src/core/dbus-unit.c | 8 +- src/core/dbus-unit.h | 8 +- src/core/dbus.c | 8 +- src/core/dbus.h | 8 +- src/core/device.c | 8 +- src/core/device.h | 8 +- src/core/execute.c | 8 +- src/core/execute.h | 8 +- src/core/fdset.c | 8 +- src/core/fdset.h | 8 +- src/core/ima-setup.c | 8 +- src/core/ima-setup.h | 8 +- src/core/job.c | 8 +- src/core/job.h | 8 +- src/core/kmod-setup.c | 8 +- src/core/kmod-setup.h | 8 +- src/core/load-dropin.c | 8 +- src/core/load-dropin.h | 8 +- src/core/load-fragment.c | 8 +- src/core/load-fragment.h | 8 +- src/core/locale-setup.c | 8 +- src/core/locale-setup.h | 8 +- src/core/manager.c | 8 +- src/core/manager.h | 8 +- src/core/mount.c | 8 +- src/core/mount.h | 8 +- src/core/namespace.c | 8 +- src/core/namespace.h | 8 +- src/core/path.c | 8 +- src/core/path.h | 8 +- src/core/polkit.h | 8 +- src/core/selinux-setup.c | 8 +- src/core/selinux-setup.h | 8 +- src/core/service.c | 8 +- src/core/service.h | 8 +- src/core/snapshot.c | 8 +- src/core/snapshot.h | 8 +- src/core/socket.c | 8 +- src/core/socket.h | 8 +- src/core/special.h | 8 +- src/core/swap.c | 8 +- src/core/swap.h | 8 +- src/core/sysfs-show.h | 8 +- src/core/target.c | 8 +- src/core/target.h | 8 +- src/core/tcpwrap.c | 8 +- src/core/tcpwrap.h | 8 +- src/core/timer.c | 8 +- src/core/timer.h | 8 +- src/core/unit.c | 8 +- src/core/unit.h | 8 +- src/cryptsetup/cryptsetup-generator.c | 8 +- src/cryptsetup/cryptsetup.c | 8 +- src/dbus-common.c | 8 +- src/dbus-common.h | 8 +- src/dbus-loop.c | 8 +- src/def.h | 8 +- src/detect-virt.c | 8 +- src/fsck.c | 8 +- src/getty-generator.c | 8 +- src/hostname-setup.c | 8 +- src/hostname-setup.h | 8 +- src/hostname/hostnamed.c | 8 +- src/hostname/org.freedesktop.hostname1.conf | 4 +- src/hostname/org.freedesktop.hostname1.policy.in | 4 +- src/hostname/org.freedesktop.hostname1.service | 4 +- src/initctl.c | 8 +- src/install.c | 8 +- src/install.h | 8 +- src/journal/cat.c | 8 +- src/journal/compress.c | 8 +- src/journal/compress.h | 8 +- src/journal/coredump.c | 8 +- src/journal/journal-def.h | 8 +- src/journal/journal-file.c | 8 +- src/journal/journal-file.h | 8 +- src/journal/journal-internal.h | 8 +- src/journal/journal-rate-limit.c | 8 +- src/journal/journal-rate-limit.h | 8 +- src/journal/journal-send.c | 8 +- src/journal/journalctl.c | 8 +- src/journal/journald.c | 8 +- src/journal/journald.conf | 4 +- src/journal/journald.h | 8 +- src/journal/libsystemd-journal.pc.in | 4 +- src/journal/libsystemd-journal.sym | 4 +- src/journal/sd-journal.c | 8 +- src/journal/test-journal-send.c | 8 +- src/journal/test-journal.c | 8 +- src/libsystemd-id128.pc.in | 4 +- src/libsystemd-id128.sym | 4 +- src/locale/localed.c | 8 +- src/locale/org.freedesktop.locale1.conf | 4 +- src/locale/org.freedesktop.locale1.policy.in | 4 +- src/locale/org.freedesktop.locale1.service | 4 +- src/login/70-uaccess.rules | 4 +- src/login/71-seat.rules | 4 +- src/login/73-seat-late.rules.in | 4 +- src/login/libsystemd-login.pc.in | 4 +- src/login/libsystemd-login.sym | 4 +- src/login/loginctl.c | 8 +- src/login/logind-acl.c | 8 +- src/login/logind-acl.h | 8 +- src/login/logind-dbus.c | 8 +- src/login/logind-device.c | 8 +- src/login/logind-device.h | 8 +- src/login/logind-seat-dbus.c | 8 +- src/login/logind-seat.c | 8 +- src/login/logind-seat.h | 8 +- src/login/logind-session-dbus.c | 8 +- src/login/logind-session.c | 8 +- src/login/logind-session.h | 8 +- src/login/logind-user-dbus.c | 8 +- src/login/logind-user.c | 8 +- src/login/logind-user.h | 8 +- src/login/logind.c | 8 +- src/login/logind.conf | 4 +- src/login/logind.h | 8 +- src/login/multi-seat-x.c | 8 +- src/login/org.freedesktop.login1.conf | 4 +- src/login/org.freedesktop.login1.policy.in | 4 +- src/login/org.freedesktop.login1.service | 4 +- src/login/pam-module.c | 8 +- src/login/sd-login.c | 8 +- src/login/sysfs-show.c | 8 +- src/login/test-login.c | 8 +- src/login/uaccess.c | 8 +- src/login/user-sessions.c | 8 +- src/logs-show.c | 8 +- src/logs-show.h | 8 +- src/loopback-setup.c | 8 +- src/loopback-setup.h | 8 +- src/machine-id-main.c | 8 +- src/machine-id-setup.c | 8 +- src/machine-id-setup.h | 8 +- src/main.c | 8 +- src/missing.h | 8 +- src/modules-load.c | 8 +- src/mount-setup.c | 8 +- src/mount-setup.h | 8 +- src/notify.c | 8 +- src/nspawn.c | 8 +- src/org.freedesktop.systemd1.conf | 4 +- src/org.freedesktop.systemd1.policy.in.in | 4 +- src/org.freedesktop.systemd1.service | 4 +- src/path-lookup.c | 8 +- src/path-lookup.h | 8 +- src/polkit.c | 8 +- src/quotacheck.c | 8 +- src/random-seed.c | 8 +- src/rc-local-generator.c | 8 +- src/readahead/readahead-collect.c | 8 +- src/readahead/readahead-common.c | 8 +- src/readahead/readahead-common.h | 8 +- src/readahead/readahead-replay.c | 8 +- src/remount-api-vfs.c | 8 +- src/reply-password.c | 8 +- src/sd-id128.c | 8 +- src/shared/acl-util.c | 8 +- src/shared/acl-util.h | 8 +- src/shared/audit.c | 8 +- src/shared/audit.h | 8 +- src/shared/capability.c | 8 +- src/shared/capability.h | 8 +- src/shared/cgroup-label.c | 8 +- src/shared/cgroup-util.c | 8 +- src/shared/cgroup-util.h | 8 +- src/shared/conf-parser.c | 8 +- src/shared/conf-parser.h | 8 +- src/shared/exit-status.c | 8 +- src/shared/exit-status.h | 8 +- src/shared/hashmap.c | 8 +- src/shared/hashmap.h | 8 +- src/shared/label.c | 8 +- src/shared/label.h | 8 +- src/shared/list.h | 8 +- src/shared/log.c | 8 +- src/shared/log.h | 8 +- src/shared/macro.h | 8 +- src/shared/mkdir.c | 8 +- src/shared/mkdir.h | 8 +- src/shared/pager.c | 8 +- src/shared/pager.h | 8 +- src/shared/ratelimit.c | 8 +- src/shared/ratelimit.h | 8 +- src/shared/set.c | 8 +- src/shared/set.h | 8 +- src/shared/socket-label.c | 8 +- src/shared/socket-util.c | 8 +- src/shared/socket-util.h | 8 +- src/shared/strv.c | 8 +- src/shared/strv.h | 8 +- src/shared/utf8.c | 8 +- src/shared/utf8.h | 8 +- src/shared/util.c | 8 +- src/shared/util.h | 8 +- src/shared/virt.c | 8 +- src/shared/virt.h | 8 +- src/shutdown.c | 8 +- src/shutdownd.c | 8 +- src/spawn-ask-password-agent.c | 8 +- src/spawn-ask-password-agent.h | 8 +- src/spawn-polkit-agent.c | 8 +- src/spawn-polkit-agent.h | 8 +- src/specifier.c | 8 +- src/specifier.h | 8 +- src/sysctl.c | 8 +- src/system.conf | 4 +- src/systemctl.c | 8 +- src/systemd-bash-completion.sh | 6 +- src/systemd.pc.in | 4 +- src/systemd/sd-id128.h | 8 +- src/systemd/sd-journal.h | 8 +- src/systemd/sd-login.h | 8 +- src/systemd/sd-messages.h | 8 +- src/systemd/sd-shutdown.h | 8 +- src/test-cgroup.c | 8 +- src/test-daemon.c | 8 +- src/test-engine.c | 8 +- src/test-env-replace.c | 8 +- src/test-hostname.c | 8 +- src/test-id128.c | 8 +- src/test-install.c | 8 +- src/test-job-type.c | 8 +- src/test-loopback.c | 8 +- src/test-ns.c | 8 +- src/test-strv.c | 8 +- src/test-watchdog.c | 8 +- src/timedate/org.freedesktop.timedate1.conf | 4 +- src/timedate/org.freedesktop.timedate1.policy.in | 4 +- src/timedate/org.freedesktop.timedate1.service | 4 +- src/timedate/timedated.c | 8 +- src/timestamp.c | 8 +- src/tmpfiles.c | 8 +- src/tty-ask-password-agent.c | 8 +- src/umount.c | 8 +- src/umount.h | 8 +- src/unit-name.c | 8 +- src/unit-name.h | 8 +- src/update-utmp.c | 8 +- src/user.conf | 4 +- src/utmp-wtmp.c | 8 +- src/utmp-wtmp.h | 8 +- src/vconsole/vconsole-setup.c | 8 +- src/watchdog.c | 8 +- src/watchdog.h | 8 +- sysctl.d/coredump.conf.in | 4 +- tmpfiles.d/legacy.conf | 4 +- tmpfiles.d/systemd.conf | 4 +- tmpfiles.d/tmp.conf | 4 +- tmpfiles.d/x11.conf | 4 +- units/basic.target | 4 +- units/bluetooth.target | 4 +- units/console-shell.service.m4.in | 4 +- units/cryptsetup.target | 4 +- units/dev-hugepages.mount | 4 +- units/dev-mqueue.mount | 4 +- units/emergency.service.in | 4 +- units/emergency.target | 4 +- units/fedora/halt-local.service | 4 +- units/fedora/prefdm.service | 4 +- units/fedora/rc-local.service | 4 +- units/final.target | 4 +- units/frugalware/display-manager.service | 4 +- units/fsck-root.service.in | 4 +- units/fsck@.service.in | 4 +- units/getty.target | 4 +- units/getty@.service.m4 | 4 +- units/graphical.target | 4 +- units/halt.service.in | 4 +- units/halt.target | 4 +- units/http-daemon.target | 4 +- units/kexec.service.in | 4 +- units/kexec.target | 4 +- units/local-fs-pre.target | 4 +- units/local-fs.target | 4 +- units/mageia/prefdm.service | 4 +- units/mail-transfer-agent.target | 4 +- units/mandriva/prefdm.service | 4 +- units/multi-user.target | 4 +- units/network.target | 4 +- units/nss-lookup.target | 4 +- units/nss-user-lookup.target | 4 +- units/plymouth-halt.service | 4 +- units/plymouth-kexec.service | 4 +- units/plymouth-poweroff.service | 4 +- units/plymouth-quit-wait.service | 4 +- units/plymouth-quit.service | 4 +- units/plymouth-read-write.service | 4 +- units/plymouth-reboot.service | 4 +- units/plymouth-start.service | 4 +- units/poweroff.service.in | 4 +- units/poweroff.target | 4 +- units/printer.target | 4 +- units/proc-sys-fs-binfmt_misc.automount | 4 +- units/proc-sys-fs-binfmt_misc.mount | 4 +- units/quotacheck.service.in | 4 +- units/quotaon.service | 4 +- units/reboot.service.in | 4 +- units/reboot.target | 4 +- units/remote-fs-pre.target | 4 +- units/remote-fs.target | 4 +- units/remount-rootfs.service | 4 +- units/rescue.service.m4.in | 4 +- units/rescue.target | 4 +- units/rpcbind.target | 4 +- units/serial-getty@.service.m4 | 4 +- units/shutdown.target | 4 +- units/sigpwr.target | 4 +- units/smartcard.target | 4 +- units/sockets.target | 4 +- units/sound.target | 4 +- units/suse/halt-local.service | 4 +- units/suse/rc-local.service | 4 +- units/swap.target | 4 +- units/sys-fs-fuse-connections.mount | 4 +- units/sys-kernel-config.mount | 4 +- units/sys-kernel-debug.mount | 4 +- units/sysinit.target | 4 +- units/syslog.socket | 4 +- units/syslog.target | 4 +- units/systemd-ask-password-console.path | 4 +- units/systemd-ask-password-console.service.in | 4 +- units/systemd-ask-password-plymouth.path | 4 +- units/systemd-ask-password-plymouth.service.in | 4 +- units/systemd-ask-password-wall.path | 4 +- units/systemd-ask-password-wall.service.in | 4 +- units/systemd-binfmt.service.in | 4 +- units/systemd-hostnamed.service.in | 4 +- units/systemd-initctl.service.in | 4 +- units/systemd-initctl.socket | 4 +- units/systemd-journald.service.in | 4 +- units/systemd-journald.socket | 4 +- units/systemd-localed.service.in | 4 +- units/systemd-logind.service.in | 4 +- units/systemd-modules-load.service.in | 4 +- units/systemd-random-seed-load.service.in | 4 +- units/systemd-random-seed-save.service.in | 4 +- units/systemd-readahead-collect.service.in | 4 +- units/systemd-readahead-done.service.in | 4 +- units/systemd-readahead-done.timer | 4 +- units/systemd-readahead-replay.service.in | 4 +- units/systemd-remount-api-vfs.service.in | 4 +- units/systemd-shutdownd.service.in | 4 +- units/systemd-shutdownd.socket | 4 +- units/systemd-sysctl.service.in | 4 +- units/systemd-timedated.service.in | 4 +- units/systemd-tmpfiles-clean.service.in | 4 +- units/systemd-tmpfiles-clean.timer | 4 +- units/systemd-tmpfiles-setup.service.in | 4 +- units/systemd-update-utmp-runlevel.service.in | 4 +- units/systemd-update-utmp-shutdown.service.in | 4 +- units/systemd-user-sessions.service.in | 4 +- units/systemd-vconsole-setup.service.in | 4 +- units/time-sync.target | 4 +- units/tmp.mount | 4 +- units/umount.target | 4 +- units/user/default.target | 4 +- units/user/exit.service.in | 4 +- units/user/exit.target | 4 +- units/user@.service.in | 4 +- 480 files changed, 2485 insertions(+), 1952 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE.GPL2 create mode 100644 LICENSE.LGPL2.1 create mode 100644 LICENSE.MIT (limited to 'src/journal/journalctl.c') diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d511905c16..0000000000 --- a/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/LICENSE.GPL2 b/LICENSE.GPL2 new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/LICENSE.GPL2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/LICENSE.LGPL2.1 b/LICENSE.LGPL2.1 new file mode 100644 index 0000000000..89d4489cec --- /dev/null +++ b/LICENSE.LGPL2.1 @@ -0,0 +1,508 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/LICENSE.MIT b/LICENSE.MIT new file mode 100644 index 0000000000..fd44f736ee --- /dev/null +++ b/LICENSE.MIT @@ -0,0 +1,19 @@ +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile.am b/Makefile.am index 675e591352..0a9f2e5198 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,16 +4,16 @@ # Copyright 2010-2012 Kay Sievers # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} @@ -457,7 +457,9 @@ endif dist_doc_DATA = \ README \ NEWS \ - LICENSE \ + LICENSE.LGPL2.1 \ + LICENSE.GPL2 \ + LICENSE.MIT \ DISTRO_PORTING pkgconfigdata_DATA = \ diff --git a/README b/README index 6b0eb51ecd..2467b1e03e 100644 --- a/README +++ b/README @@ -24,11 +24,15 @@ BUG REPORTS: https://bugs.freedesktop.org/enter_bug.cgi?product=systemd AUTHOR: - Lennart Poettering with major support from Kay Sievers + Lennart Poettering + Kay Sievers + ...and many others LICENSE: - GPLv2+ for all code, except sd-daemon.[ch] and - sd-readahead.[ch] which are MIT + LGPLv2.1+ for all code + - except sd-daemon.[ch] and sd-readahead.[ch] which are MIT + - except src/udev/ which is GPLv2.0+, excluding + src/udev/libudev* which is LGPLv2.1+ REQUIREMENTS: Linux kernel >= 2.6.39 diff --git a/autogen.sh b/autogen.sh index fba3dc08b8..0e1b5bedf6 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,16 +3,16 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then diff --git a/configure.ac b/configure.ac index 52374c15dd..93523d53d9 100644 --- a/configure.ac +++ b/configure.ac @@ -4,16 +4,16 @@ # Copyright 2010-2012 Kay Sievers # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . AC_PREREQ(2.63) diff --git a/man/binfmt.d.xml b/man/binfmt.d.xml index f5ec805e29..e997bcf21c 100644 --- a/man/binfmt.d.xml +++ b/man/binfmt.d.xml @@ -7,16 +7,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/custom-html.xsl b/man/custom-html.xsl index 2d2f458793..df16d08718 100644 --- a/man/custom-html.xsl +++ b/man/custom-html.xsl @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/daemon.xml b/man/daemon.xml index 997ee5b253..a7217c84aa 100644 --- a/man/daemon.xml +++ b/man/daemon.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/halt.xml b/man/halt.xml index 97a53ba350..7ba85ed88d 100644 --- a/man/halt.xml +++ b/man/halt.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/hostname.xml b/man/hostname.xml index 1acda1af5d..2ada32ff71 100644 --- a/man/hostname.xml +++ b/man/hostname.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/journalctl.xml b/man/journalctl.xml index 4728d36e1c..5e0c6dd5c1 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -8,16 +8,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/journald.conf.xml b/man/journald.conf.xml index eb596eb3ab..251e01dddf 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/locale.conf.xml b/man/locale.conf.xml index 37239974b6..0c4d351ec7 100644 --- a/man/locale.conf.xml +++ b/man/locale.conf.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/loginctl.xml b/man/loginctl.xml index cf0be0d19b..8e34a29801 100644 --- a/man/loginctl.xml +++ b/man/loginctl.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 950f81fa93..6a10fa9868 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/machine-id.xml b/man/machine-id.xml index 97c622c6fa..73f0926c0b 100644 --- a/man/machine-id.xml +++ b/man/machine-id.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/machine-info.xml b/man/machine-info.xml index 240da25a6b..e27b600211 100644 --- a/man/machine-info.xml +++ b/man/machine-info.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/modules-load.d.xml b/man/modules-load.d.xml index e2f7d5c68c..91d230c35a 100644 --- a/man/modules-load.d.xml +++ b/man/modules-load.d.xml @@ -7,16 +7,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/os-release.xml b/man/os-release.xml index ff8fdf16be..a5f1a917a8 100644 --- a/man/os-release.xml +++ b/man/os-release.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml index c07b46bab2..d681276c40 100644 --- a/man/pam_systemd.xml +++ b/man/pam_systemd.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/runlevel.xml b/man/runlevel.xml index 160d1b14e7..02d5371c5d 100644 --- a/man/runlevel.xml +++ b/man/runlevel.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml index 4ea88e43d7..31115a5d69 100644 --- a/man/sd-daemon.xml +++ b/man/sd-daemon.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd-login.xml b/man/sd-login.xml index 3fc0e16f69..acb78ac689 100644 --- a/man/sd-login.xml +++ b/man/sd-login.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd-readahead.xml b/man/sd-readahead.xml index 7fb8634120..4eed56ad32 100644 --- a/man/sd-readahead.xml +++ b/man/sd-readahead.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_booted.xml b/man/sd_booted.xml index 141625d9ad..62d6e57415 100644 --- a/man/sd_booted.xml +++ b/man/sd_booted.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_get_seats.xml b/man/sd_get_seats.xml index 2ac76500ec..d30d193a59 100644 --- a/man/sd_get_seats.xml +++ b/man/sd_get_seats.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml index 4db512012c..289e1ba138 100644 --- a/man/sd_is_fifo.xml +++ b/man/sd_is_fifo.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml index c3c70a0df0..e76630e4ff 100644 --- a/man/sd_listen_fds.xml +++ b/man/sd_listen_fds.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml index de484329a9..4642e99f74 100644 --- a/man/sd_login_monitor_new.xml +++ b/man/sd_login_monitor_new.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 9d9ea4132f..eb449555cb 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_pid_get_session.xml b/man/sd_pid_get_session.xml index 94f5330222..9a1b1997d9 100644 --- a/man/sd_pid_get_session.xml +++ b/man/sd_pid_get_session.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_readahead.xml b/man/sd_readahead.xml index 2e7e09c5ec..2a92727881 100644 --- a/man/sd_readahead.xml +++ b/man/sd_readahead.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml index acc6ee4ea7..997c388901 100644 --- a/man/sd_seat_get_active.xml +++ b/man/sd_seat_get_active.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_session_is_active.xml b/man/sd_session_is_active.xml index afdeed55d6..45151aaaf9 100644 --- a/man/sd_session_is_active.xml +++ b/man/sd_session_is_active.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml index 9249021aa1..c5096e885b 100644 --- a/man/sd_uid_get_state.xml +++ b/man/sd_uid_get_state.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/shutdown.xml b/man/shutdown.xml index c8c4b54620..d54fcb25ab 100644 --- a/man/shutdown.xml +++ b/man/shutdown.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml index 20f2e24820..4f30276ad4 100644 --- a/man/sysctl.d.xml +++ b/man/sysctl.d.xml @@ -7,16 +7,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemctl.xml b/man/systemctl.xml index 84f1b1cd60..dd0ff786ec 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml index c607b1a367..f09b38cd8d 100644 --- a/man/systemd-ask-password.xml +++ b/man/systemd-ask-password.xml @@ -8,16 +8,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-cat.xml b/man/systemd-cat.xml index 350a345d43..8acf9b7781 100644 --- a/man/systemd-cat.xml +++ b/man/systemd-cat.xml @@ -8,16 +8,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml index 1e53147e1b..fb9f06b307 100644 --- a/man/systemd-cgls.xml +++ b/man/systemd-cgls.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml index 2d67ae5ef4..9322fb0920 100644 --- a/man/systemd-cgtop.xml +++ b/man/systemd-cgtop.xml @@ -8,16 +8,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml index 49b92f6891..b6b236ac7e 100644 --- a/man/systemd-machine-id-setup.xml +++ b/man/systemd-machine-id-setup.xml @@ -8,16 +8,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml index c5ffafe895..073bc1313e 100644 --- a/man/systemd-notify.xml +++ b/man/systemd-notify.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index dbd2ff5a8a..2a26b1ef18 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index bbb80b2f98..f58913d0c2 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml index 754d1e37f3..bf4b5d8214 100644 --- a/man/systemd.automount.xml +++ b/man/systemd.automount.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.conf.xml b/man/systemd.conf.xml index c7890287b5..d05a30bd48 100644 --- a/man/systemd.conf.xml +++ b/man/systemd.conf.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.device.xml b/man/systemd.device.xml index 63863bebdf..78cddd6518 100644 --- a/man/systemd.device.xml +++ b/man/systemd.device.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index e6f49c9fd0..219733be37 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml index e638893b63..99b1caab9b 100644 --- a/man/systemd.journal-fields.xml +++ b/man/systemd.journal-fields.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index 8f1cc514cf..2352b6a8fe 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.path.xml b/man/systemd.path.xml index 5b1ff75f7a..01082ad61d 100644 --- a/man/systemd.path.xml +++ b/man/systemd.path.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 837a992ba4..258b059efa 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.snapshot.xml b/man/systemd.snapshot.xml index a3e23225c6..db3343af67 100644 --- a/man/systemd.snapshot.xml +++ b/man/systemd.snapshot.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index d9921e496d..d3762cd63d 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.special.xml b/man/systemd.special.xml index 4c64a0fef2..39c3802210 100644 --- a/man/systemd.special.xml +++ b/man/systemd.special.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index ab00f9f318..30a15ecfc3 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.target.xml b/man/systemd.target.xml index 6b1dbfbde3..61eeb7fd8a 100644 --- a/man/systemd.target.xml +++ b/man/systemd.target.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml index 9b6b486bf4..0b204353f4 100644 --- a/man/systemd.timer.xml +++ b/man/systemd.timer.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 3cc126b12a..3fc7f78198 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/systemd.xml b/man/systemd.xml index aef65e30c1..d179273caa 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/telinit.xml b/man/telinit.xml index fec059aa66..4c6064f54a 100644 --- a/man/telinit.xml +++ b/man/telinit.xml @@ -8,16 +8,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/timezone.xml b/man/timezone.xml index 4e33279158..dedb7d90ff 100644 --- a/man/timezone.xml +++ b/man/timezone.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index f70bf0ef9f..5d4b2ac6d4 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -7,16 +7,16 @@ Copyright 2010 Brandon Philips systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml index a73db00d1c..72f1530620 100644 --- a/man/vconsole.conf.xml +++ b/man/vconsole.conf.xml @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . --> diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in index d306f71b63..1d53735c82 100644 --- a/rules/99-systemd.rules.in +++ b/rules/99-systemd.rules.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="systemd_end" diff --git a/src/Makefile b/src/Makefile index bc7e9fa363..9d07505194 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,16 +3,16 @@ # Copyright 2010 Lennart Poettering # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. +# Lesser General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . # This file is a dirty trick to simplify compilation from within diff --git a/src/ac-power.c b/src/ac-power.c index 24a68e717e..37313cf144 100644 --- a/src/ac-power.c +++ b/src/ac-power.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/ask-password-api.c b/src/ask-password-api.c index 4b50d28d30..55be807cf2 100644 --- a/src/ask-password-api.c +++ b/src/ask-password-api.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include diff --git a/src/ask-password.c b/src/ask-password.c index 5162f62eee..5f675700f8 100644 --- a/src/ask-password.c +++ b/src/ask-password.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 3c8d815d64..5bd763339e 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/bridge.c b/src/bridge.c index bfb38a8bb4..f926fe5538 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cgls.c b/src/cgls.c index d5417f9505..fd02d52c23 100644 --- a/src/cgls.c +++ b/src/cgls.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cgroup-show.c b/src/cgroup-show.c index ee2a241c9f..550a2f5f31 100644 --- a/src/cgroup-show.c +++ b/src/cgroup-show.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cgroup-show.h b/src/cgroup-show.h index 992e17b986..5433f46a53 100644 --- a/src/cgroup-show.h +++ b/src/cgroup-show.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cgroups-agent.c b/src/cgroups-agent.c index 1bbc8827d7..7a6173e2a2 100644 --- a/src/cgroups-agent.c +++ b/src/cgroups-agent.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cgtop.c b/src/cgtop.c index 8b8617dc1c..1fe247c667 100644 --- a/src/cgtop.c +++ b/src/cgtop.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/ask-password-api.h b/src/core/ask-password-api.h index fec8625a0f..155afad33b 100644 --- a/src/core/ask-password-api.h +++ b/src/core/ask-password-api.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/automount.c b/src/core/automount.c index 6857a6fd76..11c217beb9 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/automount.h b/src/core/automount.h index 19baee208b..5704502ef7 100644 --- a/src/core/automount.h +++ b/src/core/automount.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/build.h b/src/core/build.h index 0619013141..4ccfab1361 100644 --- a/src/core/build.h +++ b/src/core/build.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/bus-errors.h b/src/core/bus-errors.h index 82d4e99eef..a6f055f099 100644 --- a/src/core/bus-errors.h +++ b/src/core/bus-errors.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/cgroup-attr.c b/src/core/cgroup-attr.c index 474a6865c4..71af09cf87 100644 --- a/src/core/cgroup-attr.c +++ b/src/core/cgroup-attr.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/cgroup-attr.h b/src/core/cgroup-attr.h index 63a73b8101..2b3c1aea9e 100644 --- a/src/core/cgroup-attr.h +++ b/src/core/cgroup-attr.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 1f6139e25f..ef9b02f463 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 5faa7dc0f7..de248fbca3 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/condition.c b/src/core/condition.c index 2b51a16f17..5dad5248bb 100644 --- a/src/core/condition.c +++ b/src/core/condition.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/condition.h b/src/core/condition.h index 71b1c6761e..2a44ba681f 100644 --- a/src/core/condition.h +++ b/src/core/condition.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c index 8e45f81fcf..b93e3ea35f 100644 --- a/src/core/dbus-automount.c +++ b/src/core/dbus-automount.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h index 2fc8345048..6849244b43 100644 --- a/src/core/dbus-automount.h +++ b/src/core/dbus-automount.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c index b39fb9d381..dfbbafb66d 100644 --- a/src/core/dbus-device.c +++ b/src/core/dbus-device.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h index fba270b4e6..068adee5b8 100644 --- a/src/core/dbus-device.h +++ b/src/core/dbus-device.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 1fd2b21336..ef55ef12b9 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h index 03cd69d126..b8bbe1c9f2 100644 --- a/src/core/dbus-execute.h +++ b/src/core/dbus-execute.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index ab6d610243..1b86e96624 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h index 103c2ff3ec..1ee0a42793 100644 --- a/src/core/dbus-job.h +++ b/src/core/dbus-job.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-loop.h b/src/core/dbus-loop.h index 0bbdfe5925..3902b354cf 100644 --- a/src/core/dbus-loop.h +++ b/src/core/dbus-loop.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 3bf0c07b88..46b47849d2 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h index 2eb2fbbed6..0563b324f3 100644 --- a/src/core/dbus-manager.h +++ b/src/core/dbus-manager.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 35d6ea7a1d..f6db4682af 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h index b5613fa7b6..097421396e 100644 --- a/src/core/dbus-mount.h +++ b/src/core/dbus-mount.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c index 5506784c38..b77b5191c9 100644 --- a/src/core/dbus-path.c +++ b/src/core/dbus-path.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h index 2888400a13..db2d5b9161 100644 --- a/src/core/dbus-path.h +++ b/src/core/dbus-path.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index d840415417..e0e5ffcbfd 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h index d6eab65c52..27f65f5c98 100644 --- a/src/core/dbus-service.h +++ b/src/core/dbus-service.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-snapshot.c b/src/core/dbus-snapshot.c index e69388a524..7ff0bca2c8 100644 --- a/src/core/dbus-snapshot.c +++ b/src/core/dbus-snapshot.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-snapshot.h b/src/core/dbus-snapshot.h index 0b82279f1c..fea13872aa 100644 --- a/src/core/dbus-snapshot.h +++ b/src/core/dbus-snapshot.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 2e3342cb55..80d19dd1bd 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h index 069a2f5df0..eafb3af6b8 100644 --- a/src/core/dbus-socket.h +++ b/src/core/dbus-socket.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c index 09cd1e8b9c..f327ca8b02 100644 --- a/src/core/dbus-swap.c +++ b/src/core/dbus-swap.c @@ -7,16 +7,16 @@ Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h index 15b914726b..196756534b 100644 --- a/src/core/dbus-swap.h +++ b/src/core/dbus-swap.h @@ -10,16 +10,16 @@ Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c index 55cf862de0..67ffff870f 100644 --- a/src/core/dbus-target.c +++ b/src/core/dbus-target.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h index 13d38764a2..f11cec7d21 100644 --- a/src/core/dbus-target.h +++ b/src/core/dbus-target.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index b396aed047..c76c2e0500 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h index e692e12fcb..daa26c8512 100644 --- a/src/core/dbus-timer.h +++ b/src/core/dbus-timer.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index c7532c7255..0484d75829 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 4f19a808bf..e6d549c0fb 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus.c b/src/core/dbus.c index ddf91f225a..fe73b0a434 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/dbus.h b/src/core/dbus.h index bd539d0e72..ed0b1c7cec 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/device.c b/src/core/device.c index 0575379d80..88ce0cdd18 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/device.h b/src/core/device.h index a05c3d37b0..fa806575c9 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/execute.c b/src/core/execute.c index 179ca7e55c..8ae3923c5d 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/execute.h b/src/core/execute.h index 0d7e7dd65d..fc4c71e534 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/fdset.c b/src/core/fdset.c index e67fe6fabf..fe918cd8cc 100644 --- a/src/core/fdset.c +++ b/src/core/fdset.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/fdset.h b/src/core/fdset.h index 044a9e6d1f..bb58172430 100644 --- a/src/core/fdset.h +++ b/src/core/fdset.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c index 03e43dcf16..e8cc1ba8b6 100644 --- a/src/core/ima-setup.c +++ b/src/core/ima-setup.c @@ -8,16 +8,16 @@ TORSEC group -- http://security.polito.it systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/ima-setup.h b/src/core/ima-setup.h index 7d677cf852..8de64bfdb1 100644 --- a/src/core/ima-setup.h +++ b/src/core/ima-setup.h @@ -11,16 +11,16 @@ TORSEC group -- http://security.polito.it systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/job.c b/src/core/job.c index bae6ab9f32..781f83e175 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/job.h b/src/core/job.h index 60a43e074d..3ce2d65a0d 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c index debf87130d..22ff067d58 100644 --- a/src/core/kmod-setup.c +++ b/src/core/kmod-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/kmod-setup.h b/src/core/kmod-setup.h index 496aef3e15..faaaa9ab41 100644 --- a/src/core/kmod-setup.h +++ b/src/core/kmod-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index d869ee0c76..4323147a01 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h index cf3a799381..0b613c53f1 100644 --- a/src/core/load-dropin.h +++ b/src/core/load-dropin.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 637c82b427..1665be82a0 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 79fc76da92..03e13a9c8c 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c index 7f692e9c5d..aab454e83b 100644 --- a/src/core/locale-setup.c +++ b/src/core/locale-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/locale-setup.h b/src/core/locale-setup.h index 09a6bc682d..418fdfae1a 100644 --- a/src/core/locale-setup.h +++ b/src/core/locale-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/manager.c b/src/core/manager.c index 312527aa9c..6be8e8fbe2 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/manager.h b/src/core/manager.h index 9ecc926cbf..39e16aee98 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/mount.c b/src/core/mount.c index 7dbeaf9cf0..6c768a3d02 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/mount.h b/src/core/mount.h index 9318444249..3153a2a99d 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/namespace.c b/src/core/namespace.c index 09bc82909f..da555cd23c 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/namespace.h b/src/core/namespace.h index 7cf1dedd32..eb912e9e2d 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/path.c b/src/core/path.c index 1d50885ed4..0f23f1494d 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/path.h b/src/core/path.h index efb6b5eb44..1b4d0d49d4 100644 --- a/src/core/path.h +++ b/src/core/path.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/polkit.h b/src/core/polkit.h index 0d08194b26..5aecfff635 100644 --- a/src/core/polkit.h +++ b/src/core/polkit.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c index a7e1fa4007..d8643bc162 100644 --- a/src/core/selinux-setup.c +++ b/src/core/selinux-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h index 6b8fe00b7d..e9a45f589a 100644 --- a/src/core/selinux-setup.h +++ b/src/core/selinux-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/service.c b/src/core/service.c index bf2e0a9d98..1c04ed338a 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/service.h b/src/core/service.h index 60b10516eb..eb41314931 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/snapshot.c b/src/core/snapshot.c index 82ec5104db..5bb3c4a8fd 100644 --- a/src/core/snapshot.c +++ b/src/core/snapshot.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/snapshot.h b/src/core/snapshot.h index bf92e99a8b..9c63216421 100644 --- a/src/core/snapshot.h +++ b/src/core/snapshot.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/socket.c b/src/core/socket.c index 5b24b3422b..37a0236156 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/socket.h b/src/core/socket.h index 6470d8b63e..576506fef7 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/special.h b/src/core/special.h index 43e2e6f6d7..f1ff1b94c0 100644 --- a/src/core/special.h +++ b/src/core/special.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/swap.c b/src/core/swap.c index 9c72732b94..6331864d8c 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/swap.h b/src/core/swap.h index 62d08da30b..5c0ef73026 100644 --- a/src/core/swap.h +++ b/src/core/swap.h @@ -10,16 +10,16 @@ Copyright 2010 Maarten Lankhorst systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/sysfs-show.h b/src/core/sysfs-show.h index 9939e8b069..51d73fb151 100644 --- a/src/core/sysfs-show.h +++ b/src/core/sysfs-show.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/target.c b/src/core/target.c index 6c1e0c368a..f99b2a5af0 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/target.h b/src/core/target.h index 5b97c86fbf..62bc34382b 100644 --- a/src/core/target.h +++ b/src/core/target.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/tcpwrap.c b/src/core/tcpwrap.c index 0aab1427dd..6c630fac60 100644 --- a/src/core/tcpwrap.c +++ b/src/core/tcpwrap.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/tcpwrap.h b/src/core/tcpwrap.h index 4d4553e8ae..0c87b111ee 100644 --- a/src/core/tcpwrap.h +++ b/src/core/tcpwrap.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/timer.c b/src/core/timer.c index e318fee201..6bd4cc359c 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/timer.h b/src/core/timer.h index f5c5c64f25..985b460ab1 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/unit.c b/src/core/unit.c index 9e33701c8f..df79fe3a69 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/core/unit.h b/src/core/unit.h index 756f465da3..d8f4644ca9 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 5e92fb9af8..4d10373a79 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index ac7b6d6c38..f214d60d56 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/dbus-common.c b/src/dbus-common.c index fc97108e95..038fdd41a0 100644 --- a/src/dbus-common.c +++ b/src/dbus-common.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/dbus-common.h b/src/dbus-common.h index 892d1297fe..38d8e6538c 100644 --- a/src/dbus-common.h +++ b/src/dbus-common.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/dbus-loop.c b/src/dbus-loop.c index 8eb1d171a7..da0a00443a 100644 --- a/src/dbus-loop.c +++ b/src/dbus-loop.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/def.h b/src/def.h index 20aaa7c580..be969fca2e 100644 --- a/src/def.h +++ b/src/def.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/detect-virt.c b/src/detect-virt.c index 79cad5d8ab..b3d8fb53a4 100644 --- a/src/detect-virt.c +++ b/src/detect-virt.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/fsck.c b/src/fsck.c index d3ac83c25e..f25ec49442 100644 --- a/src/fsck.c +++ b/src/fsck.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/getty-generator.c b/src/getty-generator.c index dc979e9e8e..58ad8a6635 100644 --- a/src/getty-generator.c +++ b/src/getty-generator.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/hostname-setup.c b/src/hostname-setup.c index 2c2f10cfd1..550d3c2113 100644 --- a/src/hostname-setup.c +++ b/src/hostname-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/hostname-setup.h b/src/hostname-setup.h index ff11df945e..9550b8c5ab 100644 --- a/src/hostname-setup.h +++ b/src/hostname-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index ad72440845..67c56f3313 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/hostname/org.freedesktop.hostname1.conf b/src/hostname/org.freedesktop.hostname1.conf index eb241c022f..46b4aadc83 100644 --- a/src/hostname/org.freedesktop.hostname1.conf +++ b/src/hostname/org.freedesktop.hostname1.conf @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/hostname/org.freedesktop.hostname1.policy.in b/src/hostname/org.freedesktop.hostname1.policy.in index 7d56b22c28..df082d8e6f 100644 --- a/src/hostname/org.freedesktop.hostname1.policy.in +++ b/src/hostname/org.freedesktop.hostname1.policy.in @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/hostname/org.freedesktop.hostname1.service b/src/hostname/org.freedesktop.hostname1.service index 42e4adb2c9..6041ed60ca 100644 --- a/src/hostname/org.freedesktop.hostname1.service +++ b/src/hostname/org.freedesktop.hostname1.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] diff --git a/src/initctl.c b/src/initctl.c index 53d03a9e10..0eb008d9e6 100644 --- a/src/initctl.c +++ b/src/initctl.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/install.c b/src/install.c index 45018043c2..080ae6a01d 100644 --- a/src/install.c +++ b/src/install.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty . ***/ diff --git a/src/install.h b/src/install.h index 0505a82f00..d365c01bc7 100644 --- a/src/install.h +++ b/src/install.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/cat.c b/src/journal/cat.c index f0a666642c..cdd46bcf5b 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/compress.c b/src/journal/compress.c index ff906581f0..75e70c5ffa 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/compress.h b/src/journal/compress.h index f187a6e00c..1cdfe3d481 100644 --- a/src/journal/compress.h +++ b/src/journal/compress.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 5ecdef37a7..db805d6cb5 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 9cb8051082..d1174456cb 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index be92c90447..973c51f802 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 57d66cafc5..aeb6d46c79 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 17f1d317c7..bcffa35055 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-rate-limit.c b/src/journal/journal-rate-limit.c index 243ff2a378..25ea437ea3 100644 --- a/src/journal/journal-rate-limit.c +++ b/src/journal/journal-rate-limit.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-rate-limit.h b/src/journal/journal-rate-limit.h index 2bbdd5f9fe..cbf526c64f 100644 --- a/src/journal/journal-rate-limit.h +++ b/src/journal/journal-rate-limit.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index 32e94af91f..4c9753cec1 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 01dceca237..ebc2a6aa49 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journald.c b/src/journal/journald.c index ea23cff26e..1549e6e039 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/journald.conf b/src/journal/journald.conf index 710b0aa941..26bdc36baa 100644 --- a/src/journal/journald.conf +++ b/src/journal/journald.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # See system-journald.conf(5) for details diff --git a/src/journal/journald.h b/src/journal/journald.h index 7840fd5730..3c69f7ec24 100644 --- a/src/journal/journald.h +++ b/src/journal/journald.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/libsystemd-journal.pc.in b/src/journal/libsystemd-journal.pc.in index 13cc8208df..9883595644 100644 --- a/src/journal/libsystemd-journal.pc.in +++ b/src/journal/libsystemd-journal.pc.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index cd434aea26..3ebcd28aa1 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -2,8 +2,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 92ba57822b..9d381e044c 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c index 2f9987dcde..d682abbf01 100644 --- a/src/journal/test-journal-send.c +++ b/src/journal/test-journal-send.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index a023509b70..39f4c16778 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/libsystemd-id128.pc.in b/src/libsystemd-id128.pc.in index 4d984fdff5..bb65ffde33 100644 --- a/src/libsystemd-id128.pc.in +++ b/src/libsystemd-id128.pc.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ diff --git a/src/libsystemd-id128.sym b/src/libsystemd-id128.sym index 2373fe6646..604c0026c6 100644 --- a/src/libsystemd-id128.sym +++ b/src/libsystemd-id128.sym @@ -2,8 +2,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ diff --git a/src/locale/localed.c b/src/locale/localed.c index e6aaa5cab3..d582a9cbab 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/locale/org.freedesktop.locale1.conf b/src/locale/org.freedesktop.locale1.conf index 68273311e7..79d0ecd2bb 100644 --- a/src/locale/org.freedesktop.locale1.conf +++ b/src/locale/org.freedesktop.locale1.conf @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/locale/org.freedesktop.locale1.policy.in b/src/locale/org.freedesktop.locale1.policy.in index 1ac50bf86c..91296c2356 100644 --- a/src/locale/org.freedesktop.locale1.policy.in +++ b/src/locale/org.freedesktop.locale1.policy.in @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/locale/org.freedesktop.locale1.service b/src/locale/org.freedesktop.locale1.service index 29bd582459..025f9a0fc2 100644 --- a/src/locale/org.freedesktop.locale1.service +++ b/src/locale/org.freedesktop.locale1.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules index 18dd4433e7..ca7ca133a3 100644 --- a/src/login/70-uaccess.rules +++ b/src/login/70-uaccess.rules @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="uaccess_end" diff --git a/src/login/71-seat.rules b/src/login/71-seat.rules index 04ccac7570..52750f7885 100644 --- a/src/login/71-seat.rules +++ b/src/login/71-seat.rules @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="seat_end" diff --git a/src/login/73-seat-late.rules.in b/src/login/73-seat-late.rules.in index 933c952b97..901df750fd 100644 --- a/src/login/73-seat-late.rules.in +++ b/src/login/73-seat-late.rules.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. ACTION=="remove", GOTO="seat_late_end" diff --git a/src/login/libsystemd-login.pc.in b/src/login/libsystemd-login.pc.in index cd36a9cb35..7b2a7245fc 100644 --- a/src/login/libsystemd-login.pc.in +++ b/src/login/libsystemd-login.pc.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym index a5e6c1e756..0fd61e000b 100644 --- a/src/login/libsystemd-login.sym +++ b/src/login/libsystemd-login.sym @@ -2,8 +2,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. ***/ diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 2633b47e1c..c4604909cd 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index eb8a48d191..cb045a9928 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-acl.h b/src/login/logind-acl.h index 72740f5b95..ea34590bd1 100644 --- a/src/login/logind-acl.h +++ b/src/login/logind-acl.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 1c6dc979ed..6b013b9fb2 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-device.c b/src/login/logind-device.c index bbd370fbff..828e1efe4a 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-device.h b/src/login/logind-device.h index e25a5344ef..bdb9741727 100644 --- a/src/login/logind-device.h +++ b/src/login/logind-device.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 95ef5ffdb5..4bf9bf7b1f 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 906ede6cda..1bae6f6e07 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h index 3b2c7f0965..d41320da46 100644 --- a/src/login/logind-seat.h +++ b/src/login/logind-seat.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 102f8ac99b..0780f3f42a 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 641678210f..cbc4b5cf3c 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-session.h b/src/login/logind-session.h index d0b8c87fab..1afbdcc410 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index a9d680f899..2d3375a09c 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 92ba2c2208..27f78adae1 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind-user.h b/src/login/logind-user.h index db9a5f6a34..78249ac647 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind.c b/src/login/logind.c index a54195cebb..67117405e6 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/logind.conf b/src/login/logind.conf index 24b9d77a67..6a2cefa576 100644 --- a/src/login/logind.conf +++ b/src/login/logind.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # See logind.conf(5) for details diff --git a/src/login/logind.h b/src/login/logind.h index 9586793ad4..a3080371d0 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/multi-seat-x.c b/src/login/multi-seat-x.c index 96554462a8..32d868888f 100644 --- a/src/login/multi-seat-x.c +++ b/src/login/multi-seat-x.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index 9ef852bb73..7ebf9ea99c 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in index adc904886d..fb5c539d50 100644 --- a/src/login/org.freedesktop.login1.policy.in +++ b/src/login/org.freedesktop.login1.policy.in @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/login/org.freedesktop.login1.service b/src/login/org.freedesktop.login1.service index 4a64177e30..762dae2bb3 100644 --- a/src/login/org.freedesktop.login1.service +++ b/src/login/org.freedesktop.login1.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] diff --git a/src/login/pam-module.c b/src/login/pam-module.c index 1edb91c804..0727164db2 100644 --- a/src/login/pam-module.c +++ b/src/login/pam-module.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/sd-login.c b/src/login/sd-login.c index 887c421009..8e5667c705 100644 --- a/src/login/sd-login.c +++ b/src/login/sd-login.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c index b8b356d77b..b0edc33b80 100644 --- a/src/login/sysfs-show.c +++ b/src/login/sysfs-show.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/test-login.c b/src/login/test-login.c index dd8404285b..707cf21589 100644 --- a/src/login/test-login.c +++ b/src/login/test-login.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/uaccess.c b/src/login/uaccess.c index e1af5bf431..2c530c8f39 100644 --- a/src/login/uaccess.c +++ b/src/login/uaccess.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c index 64aa3bb1c6..98b36c60e8 100644 --- a/src/login/user-sessions.c +++ b/src/login/user-sessions.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/logs-show.c b/src/logs-show.c index 42d84edbaf..fedb4532db 100644 --- a/src/logs-show.c +++ b/src/logs-show.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/logs-show.h b/src/logs-show.h index db9c7e34ab..94caed5579 100644 --- a/src/logs-show.h +++ b/src/logs-show.h @@ -9,16 +9,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/loopback-setup.c b/src/loopback-setup.c index b6359def7f..46c1fc843a 100644 --- a/src/loopback-setup.c +++ b/src/loopback-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/loopback-setup.h b/src/loopback-setup.h index 81f4529630..cbb969e1e4 100644 --- a/src/loopback-setup.h +++ b/src/loopback-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/machine-id-main.c b/src/machine-id-main.c index 03970a2b06..ca8af596f7 100644 --- a/src/machine-id-main.c +++ b/src/machine-id-main.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/machine-id-setup.c b/src/machine-id-setup.c index 94198cb83b..9e84ac0cb9 100644 --- a/src/machine-id-setup.c +++ b/src/machine-id-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/machine-id-setup.h b/src/machine-id-setup.h index 4d0a9cf331..16f45d86d3 100644 --- a/src/machine-id-setup.h +++ b/src/machine-id-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/main.c b/src/main.c index 4e800e7430..8c115bd548 100644 --- a/src/main.c +++ b/src/main.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/missing.h b/src/missing.h index 095bf1fe04..5951e06cfc 100644 --- a/src/missing.h +++ b/src/missing.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/modules-load.c b/src/modules-load.c index ff1f690aac..0f2144c2ed 100644 --- a/src/modules-load.c +++ b/src/modules-load.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/mount-setup.c b/src/mount-setup.c index dd7938ebe7..52fe523674 100644 --- a/src/mount-setup.c +++ b/src/mount-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/mount-setup.h b/src/mount-setup.h index c1a27ba6bd..720b66f76c 100644 --- a/src/mount-setup.h +++ b/src/mount-setup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/notify.c b/src/notify.c index 943808eb0d..ffc8dfeb9b 100644 --- a/src/notify.c +++ b/src/notify.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/nspawn.c b/src/nspawn.c index 8c4f49a1ed..5a04404587 100644 --- a/src/nspawn.c +++ b/src/nspawn.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/org.freedesktop.systemd1.conf b/src/org.freedesktop.systemd1.conf index 201afe65be..a07a8e1ce3 100644 --- a/src/org.freedesktop.systemd1.conf +++ b/src/org.freedesktop.systemd1.conf @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/org.freedesktop.systemd1.policy.in.in b/src/org.freedesktop.systemd1.policy.in.in index 1771314e09..51bdafac45 100644 --- a/src/org.freedesktop.systemd1.policy.in.in +++ b/src/org.freedesktop.systemd1.policy.in.in @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/org.freedesktop.systemd1.service b/src/org.freedesktop.systemd1.service index 7e1dfd47e0..d4df3e93a2 100644 --- a/src/org.freedesktop.systemd1.service +++ b/src/org.freedesktop.systemd1.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] diff --git a/src/path-lookup.c b/src/path-lookup.c index d33ebc71be..1d95f7d1f8 100644 --- a/src/path-lookup.c +++ b/src/path-lookup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/path-lookup.h b/src/path-lookup.h index fc2887d3c7..e8a5a77a7b 100644 --- a/src/path-lookup.h +++ b/src/path-lookup.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/polkit.c b/src/polkit.c index 3acbdc6135..07d18e7d5f 100644 --- a/src/polkit.c +++ b/src/polkit.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/quotacheck.c b/src/quotacheck.c index b6648b8369..e4420eeb1b 100644 --- a/src/quotacheck.c +++ b/src/quotacheck.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/random-seed.c b/src/random-seed.c index c1022c719f..d1cab8b87a 100644 --- a/src/random-seed.c +++ b/src/random-seed.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/rc-local-generator.c b/src/rc-local-generator.c index 108827d699..42d7ae41ed 100644 --- a/src/rc-local-generator.c +++ b/src/rc-local-generator.c @@ -7,16 +7,16 @@ Copyright 2011 Michal Schmidt systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index 7e6c243b5e..3e91d5c28a 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c index 67214ec379..4e8e636975 100644 --- a/src/readahead/readahead-common.c +++ b/src/readahead/readahead-common.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/readahead/readahead-common.h b/src/readahead/readahead-common.h index 9547ad201c..b4eab71b1a 100644 --- a/src/readahead/readahead-common.h +++ b/src/readahead/readahead-common.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c index 0c739c82be..7c263f6e53 100644 --- a/src/readahead/readahead-replay.c +++ b/src/readahead/readahead-replay.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/remount-api-vfs.c b/src/remount-api-vfs.c index 3e146ebb5c..6cb77c1d1a 100644 --- a/src/remount-api-vfs.c +++ b/src/remount-api-vfs.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/reply-password.c b/src/reply-password.c index 3a96049d7f..a935d0f084 100644 --- a/src/reply-password.c +++ b/src/reply-password.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/sd-id128.c b/src/sd-id128.c index b4184e1c7e..4286ae7d14 100644 --- a/src/sd-id128.c +++ b/src/sd-id128.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index a2a9f9a22b..d1eb6f2268 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h index 798ce43364..9f11636aa1 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/audit.c b/src/shared/audit.c index 3850059132..e5c483ab08 100644 --- a/src/shared/audit.c +++ b/src/shared/audit.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/audit.h b/src/shared/audit.h index 3529046ff3..f2740bc42c 100644 --- a/src/shared/audit.h +++ b/src/shared/audit.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/capability.c b/src/shared/capability.c index b8002159ec..b2cd9ed75e 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/capability.h b/src/shared/capability.h index ab7e40b601..9f9c49cf5b 100644 --- a/src/shared/capability.h +++ b/src/shared/capability.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/cgroup-label.c b/src/shared/cgroup-label.c index f9a42c679e..f132d71e21 100644 --- a/src/shared/cgroup-label.c +++ b/src/shared/cgroup-label.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index ad677d4262..86f354dbe7 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index 37e4255a9c..5da0004d81 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index a9b01135e6..30980a3ea2 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index be7d708171..d37029f083 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c index ab8907d32c..b07a66a3e2 100644 --- a/src/shared/exit-status.c +++ b/src/shared/exit-status.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h index 44ef879562..349e24fbf2 100644 --- a/src/shared/exit-status.h +++ b/src/shared/exit-status.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index 6928118615..5d1e63208a 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h index ab4363a7a3..fcf2cb1c81 100644 --- a/src/shared/hashmap.h +++ b/src/shared/hashmap.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/label.c b/src/shared/label.c index 2c887a0fe5..dce6f45c80 100644 --- a/src/shared/label.c +++ b/src/shared/label.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/label.h b/src/shared/label.h index ead44837a4..ccf405bbe0 100644 --- a/src/shared/label.h +++ b/src/shared/label.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/list.h b/src/shared/list.h index 2bec8c9e73..9a491b990e 100644 --- a/src/shared/list.h +++ b/src/shared/list.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/log.c b/src/shared/log.c index 9fffc1dbc0..2151200644 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/log.h b/src/shared/log.h index 3283808ff8..b2f5f2a920 100644 --- a/src/shared/log.h +++ b/src/shared/log.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/macro.h b/src/shared/macro.h index 19f259e4f1..1355aac908 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c index e668cc2558..3d98221296 100644 --- a/src/shared/mkdir.c +++ b/src/shared/mkdir.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h index c006e7ccdb..b1477c5f63 100644 --- a/src/shared/mkdir.h +++ b/src/shared/mkdir.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/pager.c b/src/shared/pager.c index 3fc81820e9..6a85af33c4 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/pager.h b/src/shared/pager.h index b5b4998445..7d2108f73e 100644 --- a/src/shared/pager.h +++ b/src/shared/pager.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/ratelimit.c b/src/shared/ratelimit.c index 93157c7a2e..1054d52f97 100644 --- a/src/shared/ratelimit.c +++ b/src/shared/ratelimit.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/ratelimit.h b/src/shared/ratelimit.h index a6443e7f87..07e8205c81 100644 --- a/src/shared/ratelimit.h +++ b/src/shared/ratelimit.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/set.c b/src/shared/set.c index 097b9d3aae..20e457eda4 100644 --- a/src/shared/set.c +++ b/src/shared/set.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/set.h b/src/shared/set.h index 885780c4c0..a4653b3a45 100644 --- a/src/shared/set.h +++ b/src/shared/set.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/socket-label.c b/src/shared/socket-label.c index 9ab07a9b31..5158beeda8 100644 --- a/src/shared/socket-label.c +++ b/src/shared/socket-label.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c index 618c928f06..471b6dc284 100644 --- a/src/shared/socket-util.c +++ b/src/shared/socket-util.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h index 8ccbd371cf..a5a9463f18 100644 --- a/src/shared/socket-util.h +++ b/src/shared/socket-util.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/strv.c b/src/shared/strv.c index f61680d476..18de4f8391 100644 --- a/src/shared/strv.c +++ b/src/shared/strv.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/strv.h b/src/shared/strv.h index 9becf9b575..afb31f385f 100644 --- a/src/shared/strv.h +++ b/src/shared/strv.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 11619dce2f..13f0521e8c 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/utf8.h b/src/shared/utf8.h index 9a72bec084..af2420fda4 100644 --- a/src/shared/utf8.h +++ b/src/shared/utf8.h @@ -9,16 +9,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/util.c b/src/shared/util.c index 7778b0a06b..a3873a9318 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/util.h b/src/shared/util.h index 062ab6dd05..3f4e49e6bc 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/virt.c b/src/shared/virt.c index 4c526ff454..b74c513d12 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shared/virt.h b/src/shared/virt.h index f55c9a68fd..0b6dc1a9bd 100644 --- a/src/shared/virt.h +++ b/src/shared/virt.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shutdown.c b/src/shutdown.c index b0c680a030..cd478b0349 100644 --- a/src/shutdown.c +++ b/src/shutdown.c @@ -6,16 +6,16 @@ Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/shutdownd.c b/src/shutdownd.c index 9801b5e19c..0497cd41a0 100644 --- a/src/shutdownd.c +++ b/src/shutdownd.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/spawn-ask-password-agent.c b/src/spawn-ask-password-agent.c index c77c71340c..c1a9c58681 100644 --- a/src/spawn-ask-password-agent.c +++ b/src/spawn-ask-password-agent.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/spawn-ask-password-agent.h b/src/spawn-ask-password-agent.h index dae039ad05..fa5e7b0260 100644 --- a/src/spawn-ask-password-agent.h +++ b/src/spawn-ask-password-agent.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/spawn-polkit-agent.c b/src/spawn-polkit-agent.c index 97bc9f5e9e..fd72588417 100644 --- a/src/spawn-polkit-agent.c +++ b/src/spawn-polkit-agent.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/spawn-polkit-agent.h b/src/spawn-polkit-agent.h index 34131f019a..b91d20f120 100644 --- a/src/spawn-polkit-agent.h +++ b/src/spawn-polkit-agent.h @@ -9,16 +9,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/specifier.c b/src/specifier.c index a9fff88d35..ae00ae10bb 100644 --- a/src/specifier.c +++ b/src/specifier.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/specifier.h b/src/specifier.h index 041166c90e..57d1fcb35c 100644 --- a/src/specifier.h +++ b/src/specifier.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/sysctl.c b/src/sysctl.c index 17c6719841..57fba25605 100644 --- a/src/sysctl.c +++ b/src/sysctl.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/system.conf b/src/system.conf index 36eac07788..83c1f46814 100644 --- a/src/system.conf +++ b/src/system.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # See systemd.conf(5) for details diff --git a/src/systemctl.c b/src/systemctl.c index 7abd928389..28bdfa96a4 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/systemd-bash-completion.sh b/src/systemd-bash-completion.sh index 62601de90a..25ab0c5e97 100644 --- a/src/systemd-bash-completion.sh +++ b/src/systemd-bash-completion.sh @@ -3,8 +3,8 @@ # Copyright 2010 Ran Benita # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # systemd is distributed in the hope that it will be useful, but @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . __systemctl() { diff --git a/src/systemd.pc.in b/src/systemd.pc.in index 79470f4edd..49f65b2a65 100644 --- a/src/systemd.pc.in +++ b/src/systemd.pc.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. prefix=@prefix@ diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h index af2841eb77..30cb686557 100644 --- a/src/systemd/sd-id128.h +++ b/src/systemd/sd-id128.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index f27e461b03..72c23ba522 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h index 6e99cfc951..f8c3c6913a 100644 --- a/src/systemd/sd-login.h +++ b/src/systemd/sd-login.h @@ -9,16 +9,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index c5ac3abd0c..3f7eedd806 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -9,16 +9,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/systemd/sd-shutdown.h b/src/systemd/sd-shutdown.h index 29fcf3417e..cee4350173 100644 --- a/src/systemd/sd-shutdown.h +++ b/src/systemd/sd-shutdown.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-cgroup.c b/src/test-cgroup.c index eb189374fa..e742632032 100644 --- a/src/test-cgroup.c +++ b/src/test-cgroup.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-daemon.c b/src/test-daemon.c index 20c5d1517e..3215f0c560 100644 --- a/src/test-daemon.c +++ b/src/test-daemon.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-engine.c b/src/test-engine.c index 46a2d2cda0..11389a5ac7 100644 --- a/src/test-engine.c +++ b/src/test-engine.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-env-replace.c b/src/test-env-replace.c index 05dbacd7df..4b6b884779 100644 --- a/src/test-env-replace.c +++ b/src/test-env-replace.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-hostname.c b/src/test-hostname.c index 0a08416a17..8c1a60f940 100644 --- a/src/test-hostname.c +++ b/src/test-hostname.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-id128.c b/src/test-id128.c index 617c95568b..bfd743eca3 100644 --- a/src/test-id128.c +++ b/src/test-id128.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-install.c b/src/test-install.c index f8e87e0c74..709974f9e5 100644 --- a/src/test-install.c +++ b/src/test-install.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-job-type.c b/src/test-job-type.c index 9de21e1823..ba8b307dd3 100644 --- a/src/test-job-type.c +++ b/src/test-job-type.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-loopback.c b/src/test-loopback.c index 9784aaf24b..ab330ac840 100644 --- a/src/test-loopback.c +++ b/src/test-loopback.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-ns.c b/src/test-ns.c index e2bdfc5894..102b005880 100644 --- a/src/test-ns.c +++ b/src/test-ns.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-strv.c b/src/test-strv.c index 1d577dfd3c..5ee4447669 100644 --- a/src/test-strv.c +++ b/src/test-strv.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/test-watchdog.c b/src/test-watchdog.c index d53fddbb9d..ccb1854708 100644 --- a/src/test-watchdog.c +++ b/src/test-watchdog.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/timedate/org.freedesktop.timedate1.conf b/src/timedate/org.freedesktop.timedate1.conf index c9c221b644..36557d5841 100644 --- a/src/timedate/org.freedesktop.timedate1.conf +++ b/src/timedate/org.freedesktop.timedate1.conf @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/timedate/org.freedesktop.timedate1.policy.in b/src/timedate/org.freedesktop.timedate1.policy.in index 3d9c2081d6..dd0a54d81a 100644 --- a/src/timedate/org.freedesktop.timedate1.policy.in +++ b/src/timedate/org.freedesktop.timedate1.policy.in @@ -6,8 +6,8 @@ This file is part of systemd. systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. --> diff --git a/src/timedate/org.freedesktop.timedate1.service b/src/timedate/org.freedesktop.timedate1.service index c3120b66cb..875f4bec78 100644 --- a/src/timedate/org.freedesktop.timedate1.service +++ b/src/timedate/org.freedesktop.timedate1.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [D-BUS Service] diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 6a7d980c3e..4fbee7ccbd 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -6,16 +6,16 @@ Copyright 2011 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/timestamp.c b/src/timestamp.c index ce5142946a..1152f1b52e 100644 --- a/src/timestamp.c +++ b/src/timestamp.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/tmpfiles.c b/src/tmpfiles.c index c5f6fc00b3..15913089ba 100644 --- a/src/tmpfiles.c +++ b/src/tmpfiles.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering, Kay Sievers systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/tty-ask-password-agent.c b/src/tty-ask-password-agent.c index c928b5f454..9fbd7f5fb2 100644 --- a/src/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/umount.c b/src/umount.c index 0a63d23a01..24c0947f21 100644 --- a/src/umount.c +++ b/src/umount.c @@ -6,16 +6,16 @@ Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/umount.h b/src/umount.h index acdf09acf1..2e2f9c181a 100644 --- a/src/umount.h +++ b/src/umount.h @@ -9,16 +9,16 @@ Copyright 2010 ProFUSION embedded systems systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/unit-name.c b/src/unit-name.c index 1cbb804561..566cdc51cc 100644 --- a/src/unit-name.c +++ b/src/unit-name.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/unit-name.h b/src/unit-name.h index e369910aea..4dfb9fa3ce 100644 --- a/src/unit-name.h +++ b/src/unit-name.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/update-utmp.c b/src/update-utmp.c index 0d177d6164..ec07b92125 100644 --- a/src/update-utmp.c +++ b/src/update-utmp.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/user.conf b/src/user.conf index 9508a02eec..e02b46bc3a 100644 --- a/src/user.conf +++ b/src/user.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # See systemd.conf(5) for details diff --git a/src/utmp-wtmp.c b/src/utmp-wtmp.c index 217ae1e2c7..6bba325d3e 100644 --- a/src/utmp-wtmp.c +++ b/src/utmp-wtmp.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/utmp-wtmp.h b/src/utmp-wtmp.h index a5998ebb21..ab950617a1 100644 --- a/src/utmp-wtmp.h +++ b/src/utmp-wtmp.h @@ -9,16 +9,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 91967891f1..9ce6fae1da 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -6,16 +6,16 @@ Copyright 2010 Kay Sievers systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/watchdog.c b/src/watchdog.c index 372c16f317..13265e7692 100644 --- a/src/watchdog.c +++ b/src/watchdog.c @@ -6,16 +6,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/src/watchdog.h b/src/watchdog.h index 5ba70798ae..2e00cb9f4b 100644 --- a/src/watchdog.h +++ b/src/watchdog.h @@ -9,16 +9,16 @@ Copyright 2012 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ diff --git a/sysctl.d/coredump.conf.in b/sysctl.d/coredump.conf.in index ab19b1e988..5c791b791b 100644 --- a/sysctl.d/coredump.conf.in +++ b/sysctl.d/coredump.conf.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See sysctl.d(5) for details diff --git a/tmpfiles.d/legacy.conf b/tmpfiles.d/legacy.conf index 9198e89dd1..92bd71b98c 100644 --- a/tmpfiles.d/legacy.conf +++ b/tmpfiles.d/legacy.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf index 2f9b038460..28362e86bc 100644 --- a/tmpfiles.d/systemd.conf +++ b/tmpfiles.d/systemd.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details diff --git a/tmpfiles.d/tmp.conf b/tmpfiles.d/tmp.conf index 8915b82ab5..1284fc4700 100644 --- a/tmpfiles.d/tmp.conf +++ b/tmpfiles.d/tmp.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details diff --git a/tmpfiles.d/x11.conf b/tmpfiles.d/x11.conf index 7f81af62da..ece6a5ce98 100644 --- a/tmpfiles.d/x11.conf +++ b/tmpfiles.d/x11.conf @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See tmpfiles.d(5) for details diff --git a/units/basic.target b/units/basic.target index 0258ca0c03..c3c7ced7c6 100644 --- a/units/basic.target +++ b/units/basic.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/bluetooth.target b/units/bluetooth.target index c66718e113..6b9b5b5442 100644 --- a/units/bluetooth.target +++ b/units/bluetooth.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/console-shell.service.m4.in b/units/console-shell.service.m4.in index b0ced10aaa..7d0da9b860 100644 --- a/units/console-shell.service.m4.in +++ b/units/console-shell.service.m4.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/cryptsetup.target b/units/cryptsetup.target index 64ee8c6144..af38e5d673 100644 --- a/units/cryptsetup.target +++ b/units/cryptsetup.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/dev-hugepages.mount b/units/dev-hugepages.mount index 72a522e69c..fcc50736e0 100644 --- a/units/dev-hugepages.mount +++ b/units/dev-hugepages.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/dev-mqueue.mount b/units/dev-mqueue.mount index cffdaf773f..a55ac935c4 100644 --- a/units/dev-mqueue.mount +++ b/units/dev-mqueue.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/emergency.service.in b/units/emergency.service.in index 11ff472f6e..c1421ba22c 100644 --- a/units/emergency.service.in +++ b/units/emergency.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/emergency.target b/units/emergency.target index 6a99e05f03..791dbe595c 100644 --- a/units/emergency.target +++ b/units/emergency.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/fedora/halt-local.service b/units/fedora/halt-local.service index a9f6feb320..a0a3a292e7 100644 --- a/units/fedora/halt-local.service +++ b/units/fedora/halt-local.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/fedora/prefdm.service b/units/fedora/prefdm.service index 77a0e9ad7c..51da6c77f1 100644 --- a/units/fedora/prefdm.service +++ b/units/fedora/prefdm.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/fedora/rc-local.service b/units/fedora/rc-local.service index 0bef5c72ab..3b3bda9f6f 100644 --- a/units/fedora/rc-local.service +++ b/units/fedora/rc-local.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # This unit gets pulled automatically into multi-user.target by diff --git a/units/final.target b/units/final.target index 9cfda197b0..d516f38e9e 100644 --- a/units/final.target +++ b/units/final.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/frugalware/display-manager.service b/units/frugalware/display-manager.service index 2376e1977c..a5c475cd9e 100644 --- a/units/frugalware/display-manager.service +++ b/units/frugalware/display-manager.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/fsck-root.service.in b/units/fsck-root.service.in index 4086149128..f2870bdee7 100644 --- a/units/fsck-root.service.in +++ b/units/fsck-root.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/fsck@.service.in b/units/fsck@.service.in index c06684b634..4c595772de 100644 --- a/units/fsck@.service.in +++ b/units/fsck@.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/getty.target b/units/getty.target index e4435dc8e7..f1c926c72d 100644 --- a/units/getty.target +++ b/units/getty.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/getty@.service.m4 b/units/getty@.service.m4 index 6b931fb871..762fbfe383 100644 --- a/units/getty@.service.m4 +++ b/units/getty@.service.m4 @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/graphical.target b/units/graphical.target index f2e30341d4..2e82d6f898 100644 --- a/units/graphical.target +++ b/units/graphical.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/halt.service.in b/units/halt.service.in index 42e347043e..b746d1ea35 100644 --- a/units/halt.service.in +++ b/units/halt.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/halt.target b/units/halt.target index 04b42cd3d1..dc908805db 100644 --- a/units/halt.target +++ b/units/halt.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/http-daemon.target b/units/http-daemon.target index 45f10182e9..1de1ec4018 100644 --- a/units/http-daemon.target +++ b/units/http-daemon.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/kexec.service.in b/units/kexec.service.in index cf6bd65615..17d0344972 100644 --- a/units/kexec.service.in +++ b/units/kexec.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/kexec.target b/units/kexec.target index b77e6a43f1..4941f51c91 100644 --- a/units/kexec.target +++ b/units/kexec.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/local-fs-pre.target b/units/local-fs-pre.target index 11e67bac1c..a928c1d79e 100644 --- a/units/local-fs-pre.target +++ b/units/local-fs-pre.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/local-fs.target b/units/local-fs.target index 1886f7499d..2aa51fca8c 100644 --- a/units/local-fs.target +++ b/units/local-fs.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/mageia/prefdm.service b/units/mageia/prefdm.service index 4a896bf582..c85a7a93a8 100644 --- a/units/mageia/prefdm.service +++ b/units/mageia/prefdm.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/mail-transfer-agent.target b/units/mail-transfer-agent.target index ebb1ea125a..94d134e345 100644 --- a/units/mail-transfer-agent.target +++ b/units/mail-transfer-agent.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/mandriva/prefdm.service b/units/mandriva/prefdm.service index 4a896bf582..c85a7a93a8 100644 --- a/units/mandriva/prefdm.service +++ b/units/mandriva/prefdm.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/multi-user.target b/units/multi-user.target index 66f1a950f9..fe19cbcd0b 100644 --- a/units/multi-user.target +++ b/units/multi-user.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/network.target b/units/network.target index d97f64f674..da800da5b0 100644 --- a/units/network.target +++ b/units/network.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/nss-lookup.target b/units/nss-lookup.target index f7b0b5c955..c2d605c8a1 100644 --- a/units/nss-lookup.target +++ b/units/nss-lookup.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/nss-user-lookup.target b/units/nss-user-lookup.target index 40e214897c..0053f0608c 100644 --- a/units/nss-user-lookup.target +++ b/units/nss-user-lookup.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/plymouth-halt.service b/units/plymouth-halt.service index 2e194b360e..5dca3cc622 100644 --- a/units/plymouth-halt.service +++ b/units/plymouth-halt.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-kexec.service b/units/plymouth-kexec.service index 919c3f1294..8c36b7583b 100644 --- a/units/plymouth-kexec.service +++ b/units/plymouth-kexec.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-poweroff.service b/units/plymouth-poweroff.service index 8fcff3bab1..e69033a8e3 100644 --- a/units/plymouth-poweroff.service +++ b/units/plymouth-poweroff.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-quit-wait.service b/units/plymouth-quit-wait.service index 45c67bdabd..55a95ef02d 100644 --- a/units/plymouth-quit-wait.service +++ b/units/plymouth-quit-wait.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-quit.service b/units/plymouth-quit.service index 164499a2a6..b68b016664 100644 --- a/units/plymouth-quit.service +++ b/units/plymouth-quit.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-read-write.service b/units/plymouth-read-write.service index 09fbf7d4c4..e8ef447b74 100644 --- a/units/plymouth-read-write.service +++ b/units/plymouth-read-write.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-reboot.service b/units/plymouth-reboot.service index fb65bcc836..5c52bc6ece 100644 --- a/units/plymouth-reboot.service +++ b/units/plymouth-reboot.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/plymouth-start.service b/units/plymouth-start.service index f618257a93..1f05d5cd7b 100644 --- a/units/plymouth-start.service +++ b/units/plymouth-start.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/poweroff.service.in b/units/poweroff.service.in index 124a4c0f36..851a0f9451 100644 --- a/units/poweroff.service.in +++ b/units/poweroff.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/poweroff.target b/units/poweroff.target index d2ccf4b2c7..b81d6ee0d4 100644 --- a/units/poweroff.target +++ b/units/poweroff.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/printer.target b/units/printer.target index 14c90ff84b..b8582da7ad 100644 --- a/units/printer.target +++ b/units/printer.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/proc-sys-fs-binfmt_misc.automount b/units/proc-sys-fs-binfmt_misc.automount index acbbcbb0cb..6edd1f55d3 100644 --- a/units/proc-sys-fs-binfmt_misc.automount +++ b/units/proc-sys-fs-binfmt_misc.automount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/proc-sys-fs-binfmt_misc.mount b/units/proc-sys-fs-binfmt_misc.mount index 1829c2162a..ff958ca01b 100644 --- a/units/proc-sys-fs-binfmt_misc.mount +++ b/units/proc-sys-fs-binfmt_misc.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/quotacheck.service.in b/units/quotacheck.service.in index c97b7a4687..d28b533f9c 100644 --- a/units/quotacheck.service.in +++ b/units/quotacheck.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/quotaon.service b/units/quotaon.service index ef2fc8c976..f90a7fe7d9 100644 --- a/units/quotaon.service +++ b/units/quotaon.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/reboot.service.in b/units/reboot.service.in index f320fd886d..e6a8aabd9d 100644 --- a/units/reboot.service.in +++ b/units/reboot.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/reboot.target b/units/reboot.target index 41e133cb76..6d02417eb5 100644 --- a/units/reboot.target +++ b/units/reboot.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/remote-fs-pre.target b/units/remote-fs-pre.target index eca271b3be..8f688ad7af 100644 --- a/units/remote-fs-pre.target +++ b/units/remote-fs-pre.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/remote-fs.target b/units/remote-fs.target index a48f87e5dd..87455a4a99 100644 --- a/units/remote-fs.target +++ b/units/remote-fs.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/remount-rootfs.service b/units/remount-rootfs.service index 7b63752c7e..6ca057ec67 100644 --- a/units/remount-rootfs.service +++ b/units/remount-rootfs.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in index da4c4da03f..c736f83478 100644 --- a/units/rescue.service.m4.in +++ b/units/rescue.service.m4.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/rescue.target b/units/rescue.target index 5bf3f8e8ee..85099a1ee0 100644 --- a/units/rescue.target +++ b/units/rescue.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/rpcbind.target b/units/rpcbind.target index a5cea8c576..5a286ebe6a 100644 --- a/units/rpcbind.target +++ b/units/rpcbind.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4 index d1d14d35e6..ed6912d034 100644 --- a/units/serial-getty@.service.m4 +++ b/units/serial-getty@.service.m4 @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/shutdown.target b/units/shutdown.target index 99a659e92f..1bbef68280 100644 --- a/units/shutdown.target +++ b/units/shutdown.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/sigpwr.target b/units/sigpwr.target index 0ca502dbbe..18a9683fb8 100644 --- a/units/sigpwr.target +++ b/units/sigpwr.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/smartcard.target b/units/smartcard.target index 28dd2bba1a..3e554a0303 100644 --- a/units/smartcard.target +++ b/units/smartcard.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/sockets.target b/units/sockets.target index 22963128d7..ab1b786870 100644 --- a/units/sockets.target +++ b/units/sockets.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/sound.target b/units/sound.target index e53221c7a6..6a17360c10 100644 --- a/units/sound.target +++ b/units/sound.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/suse/halt-local.service b/units/suse/halt-local.service index 796012c0c4..3a3a7930e2 100644 --- a/units/suse/halt-local.service +++ b/units/suse/halt-local.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/suse/rc-local.service b/units/suse/rc-local.service index 2384a18f94..0fd70e0fc9 100644 --- a/units/suse/rc-local.service +++ b/units/suse/rc-local.service @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # This unit gets pulled automatically into multi-user.target by diff --git a/units/swap.target b/units/swap.target index 26dd261d17..4e165424b2 100644 --- a/units/swap.target +++ b/units/swap.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/sys-fs-fuse-connections.mount b/units/sys-fs-fuse-connections.mount index 037471537b..6f3670155a 100644 --- a/units/sys-fs-fuse-connections.mount +++ b/units/sys-fs-fuse-connections.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/sys-kernel-config.mount b/units/sys-kernel-config.mount index d6862bf6bd..9150da4b50 100644 --- a/units/sys-kernel-config.mount +++ b/units/sys-kernel-config.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/sys-kernel-debug.mount b/units/sys-kernel-debug.mount index d9fca1ff3d..85d53072f1 100644 --- a/units/sys-kernel-debug.mount +++ b/units/sys-kernel-debug.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/sysinit.target b/units/sysinit.target index eb9a1c7cc2..5bc568ff22 100644 --- a/units/sysinit.target +++ b/units/sysinit.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/syslog.socket b/units/syslog.socket index 0e211e16e7..f644f6e38b 100644 --- a/units/syslog.socket +++ b/units/syslog.socket @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/syslog.target b/units/syslog.target index 825b26e7bf..92d2576e95 100644 --- a/units/syslog.target +++ b/units/syslog.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-ask-password-console.path b/units/systemd-ask-password-console.path index c3143d1da6..dc8ab32bcb 100644 --- a/units/systemd-ask-password-console.path +++ b/units/systemd-ask-password-console.path @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-ask-password-console.service.in b/units/systemd-ask-password-console.service.in index 5ff3ed55d7..55e3d8648e 100644 --- a/units/systemd-ask-password-console.service.in +++ b/units/systemd-ask-password-console.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-ask-password-plymouth.path b/units/systemd-ask-password-plymouth.path index 06a587620f..b938ae57cf 100644 --- a/units/systemd-ask-password-plymouth.path +++ b/units/systemd-ask-password-plymouth.path @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-ask-password-plymouth.service.in b/units/systemd-ask-password-plymouth.service.in index 92cbfdbf09..fcc2853642 100644 --- a/units/systemd-ask-password-plymouth.service.in +++ b/units/systemd-ask-password-plymouth.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-ask-password-wall.path b/units/systemd-ask-password-wall.path index 050b73b2e1..73e13616b6 100644 --- a/units/systemd-ask-password-wall.path +++ b/units/systemd-ask-password-wall.path @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-ask-password-wall.service.in b/units/systemd-ask-password-wall.service.in index d8e27bf96b..1db408e55b 100644 --- a/units/systemd-ask-password-wall.service.in +++ b/units/systemd-ask-password-wall.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in index d43497c151..267d5c3fd8 100644 --- a/units/systemd-binfmt.service.in +++ b/units/systemd-binfmt.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in index 6efab1e25f..1ed942fe17 100644 --- a/units/systemd-hostnamed.service.in +++ b/units/systemd-hostnamed.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-initctl.service.in b/units/systemd-initctl.service.in index 7df3aa6db3..bcadcc8d1a 100644 --- a/units/systemd-initctl.service.in +++ b/units/systemd-initctl.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-initctl.socket b/units/systemd-initctl.socket index 7a3a0236eb..66597ee107 100644 --- a/units/systemd-initctl.socket +++ b/units/systemd-initctl.socket @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index 92606b0d88..a3c22c8ffa 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-journald.socket b/units/systemd-journald.socket index 15fc49ef29..d613e2288f 100644 --- a/units/systemd-journald.socket +++ b/units/systemd-journald.socket @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in index 4be65df75d..ae94bee3c5 100644 --- a/units/systemd-localed.service.in +++ b/units/systemd-localed.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index 48c1f2c3f0..a16bc81e79 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-modules-load.service.in b/units/systemd-modules-load.service.in index 5dc373d208..72e1d70dce 100644 --- a/units/systemd-modules-load.service.in +++ b/units/systemd-modules-load.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-random-seed-load.service.in b/units/systemd-random-seed-load.service.in index a2b6a557dc..6360436021 100644 --- a/units/systemd-random-seed-load.service.in +++ b/units/systemd-random-seed-load.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-random-seed-save.service.in b/units/systemd-random-seed-save.service.in index 9a074cf3fe..219731bae5 100644 --- a/units/systemd-random-seed-save.service.in +++ b/units/systemd-random-seed-save.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-readahead-collect.service.in b/units/systemd-readahead-collect.service.in index 56ba54f0b3..63840b916b 100644 --- a/units/systemd-readahead-collect.service.in +++ b/units/systemd-readahead-collect.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-readahead-done.service.in b/units/systemd-readahead-done.service.in index d665e45f24..893a819a7f 100644 --- a/units/systemd-readahead-done.service.in +++ b/units/systemd-readahead-done.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-readahead-done.timer b/units/systemd-readahead-done.timer index d144bfaece..c64e6ea341 100644 --- a/units/systemd-readahead-done.timer +++ b/units/systemd-readahead-done.timer @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-readahead-replay.service.in b/units/systemd-readahead-replay.service.in index 7c82e408e2..ad27395d9a 100644 --- a/units/systemd-readahead-replay.service.in +++ b/units/systemd-readahead-replay.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-remount-api-vfs.service.in b/units/systemd-remount-api-vfs.service.in index f4df0ca263..d1eba4b17e 100644 --- a/units/systemd-remount-api-vfs.service.in +++ b/units/systemd-remount-api-vfs.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-shutdownd.service.in b/units/systemd-shutdownd.service.in index 657365a451..ec88b23fde 100644 --- a/units/systemd-shutdownd.service.in +++ b/units/systemd-shutdownd.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-shutdownd.socket b/units/systemd-shutdownd.socket index 7f13c9386e..c97e01a337 100644 --- a/units/systemd-shutdownd.socket +++ b/units/systemd-shutdownd.socket @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-sysctl.service.in b/units/systemd-sysctl.service.in index 6d53422630..692fa3b889 100644 --- a/units/systemd-sysctl.service.in +++ b/units/systemd-sysctl.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in index 90ff4432ba..4073de58e7 100644 --- a/units/systemd-timedated.service.in +++ b/units/systemd-timedated.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/systemd-tmpfiles-clean.service.in b/units/systemd-tmpfiles-clean.service.in index 3c8e72ebf5..0a8707e138 100644 --- a/units/systemd-tmpfiles-clean.service.in +++ b/units/systemd-tmpfiles-clean.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-tmpfiles-clean.timer b/units/systemd-tmpfiles-clean.timer index d8529a8d7e..c9f89e803d 100644 --- a/units/systemd-tmpfiles-clean.timer +++ b/units/systemd-tmpfiles-clean.timer @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in index f90121e12e..58c3415b1e 100644 --- a/units/systemd-tmpfiles-setup.service.in +++ b/units/systemd-tmpfiles-setup.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-update-utmp-runlevel.service.in b/units/systemd-update-utmp-runlevel.service.in index 614c759a63..0a227cd396 100644 --- a/units/systemd-update-utmp-runlevel.service.in +++ b/units/systemd-update-utmp-runlevel.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-update-utmp-shutdown.service.in b/units/systemd-update-utmp-shutdown.service.in index e7c3c04a00..4af9212700 100644 --- a/units/systemd-update-utmp-shutdown.service.in +++ b/units/systemd-update-utmp-shutdown.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-user-sessions.service.in b/units/systemd-user-sessions.service.in index a93d586a43..363093ee1d 100644 --- a/units/systemd-user-sessions.service.in +++ b/units/systemd-user-sessions.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in index 673fb6ccf6..ef222a5f7d 100644 --- a/units/systemd-vconsole-setup.service.in +++ b/units/systemd-vconsole-setup.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/time-sync.target b/units/time-sync.target index aa34ecb5f4..36b9e7aeea 100644 --- a/units/time-sync.target +++ b/units/time-sync.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/tmp.mount b/units/tmp.mount index de3ec1b657..7367f7e642 100644 --- a/units/tmp.mount +++ b/units/tmp.mount @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] diff --git a/units/umount.target b/units/umount.target index b9ecca6fb1..c583062911 100644 --- a/units/umount.target +++ b/units/umount.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/user/default.target b/units/user/default.target index deb310c2f7..4f9379ea5e 100644 --- a/units/user/default.target +++ b/units/user/default.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/user/exit.service.in b/units/user/exit.service.in index a20b089c9a..c785fbd64a 100644 --- a/units/user/exit.service.in +++ b/units/user/exit.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/user/exit.target b/units/user/exit.target index f34844c0d3..ffc8fad019 100644 --- a/units/user/exit.target +++ b/units/user/exit.target @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # See systemd.special(7) for details diff --git a/units/user@.service.in b/units/user@.service.in index 91e3b25158..2c154953b1 100644 --- a/units/user@.service.in +++ b/units/user@.service.in @@ -1,8 +1,8 @@ # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] -- cgit v1.2.3-54-g00ecf From 89834a7c1c5f194d072d42d1c30077f5b2c207ec Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 18 May 2012 21:58:35 +0200 Subject: journalctl: fix built-in usage output This brings journalctl's built-in usage output in sync with the man page. There are no commands to pass, and the help screen should not confuse users. --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ebc2a6aa49..58778a81f6 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -50,7 +50,7 @@ static bool arg_local = false; static int help(void) { - printf("%s [OPTIONS...] {COMMAND} ...\n\n" + printf("%s [OPTIONS...] [MATCH]\n\n" "Send control commands to or query the journal.\n\n" " -h --help Show this help\n" " --version Show package version\n" -- cgit v1.2.3-54-g00ecf From 509407003de0c77259e5e46b567d2a464acbb6f4 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Wed, 30 May 2012 09:43:23 -0700 Subject: journalctl: support /usr/bin/nginx, etc --- TODO | 2 +- src/journal/journalctl.c | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 15d596a45b..90bd48c604 100644 --- a/TODO +++ b/TODO @@ -32,7 +32,7 @@ Features: * parse kernel cmdline option for capability bset -* journalctl /dev/sda, journalctl /usr/bin/httpd, journalctl --device=b12:8 (--device=n12, --device=+usb:1-1) +* journalctl /dev/sda, journalctl --device=b12:8 (--device=n12, --device=+usb:1-1) * make use of /sys/power/wake_lock in inhibitors diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 58778a81f6..daf4281065 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -38,6 +39,8 @@ #include "pager.h" #include "logs-show.h" +#define SD_JOURNALCTL_EXE "_EXE=" + static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; @@ -205,6 +208,8 @@ int main(int argc, char *argv[]) { sd_journal *j = NULL; unsigned line = 0; bool need_seek = false; + struct stat st; + char* journal_exe_buff; log_parse_environment(); log_open(); @@ -230,7 +235,25 @@ int main(int argc, char *argv[]) { } for (i = optind; i < argc; i++) { - r = sd_journal_add_match(j, argv[i], strlen(argv[i])); + if (strchr(argv[i], '=')) { + r = sd_journal_add_match(j, argv[i], strlen(argv[i])); + } else { + if (stat(argv[i], &st) < 0) { + log_error("Failed to add match: %s", strerror(-r)); + goto finish; /* maybe try sd_journal_add_match() when stat() fails, + * even thought we know there is no '=' ? */ + } else if (S_ISREG(st.st_mode) && + S_IXUSR & st.st_mode) { + journal_exe_buff = malloc(strlen(SD_JOURNALCTL_EXE) + strlen(argv[i]) + 1); + journal_exe_buff = strcpy(journal_exe_buff, SD_JOURNALCTL_EXE); + strncat(journal_exe_buff, argv[i], strlen(argv[i])); + r = sd_journal_add_match(j, journal_exe_buff, strlen(journal_exe_buff)); + free(journal_exe_buff); + } else { + log_error("File is not a regular file or is not executable: %s", argv[i]); + goto finish; + } + } if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); goto finish; -- cgit v1.2.3-54-g00ecf From e51240886f54e0128b1711c7dd0454b23e3f7d5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 30 May 2012 22:45:47 +0200 Subject: journalctl: check first if match is a path name --- src/journal/journalctl.c | 51 +++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index daf4281065..9d4403267e 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -35,12 +35,11 @@ #include "log.h" #include "util.h" +#include "path-util.h" #include "build.h" #include "pager.h" #include "logs-show.h" -#define SD_JOURNALCTL_EXE "_EXE=" - static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; @@ -209,7 +208,6 @@ int main(int argc, char *argv[]) { unsigned line = 0; bool need_seek = false; struct stat st; - char* journal_exe_buff; log_parse_environment(); log_open(); @@ -235,25 +233,42 @@ int main(int argc, char *argv[]) { } for (i = optind; i < argc; i++) { - if (strchr(argv[i], '=')) { - r = sd_journal_add_match(j, argv[i], strlen(argv[i])); - } else { - if (stat(argv[i], &st) < 0) { - log_error("Failed to add match: %s", strerror(-r)); - goto finish; /* maybe try sd_journal_add_match() when stat() fails, - * even thought we know there is no '=' ? */ - } else if (S_ISREG(st.st_mode) && - S_IXUSR & st.st_mode) { - journal_exe_buff = malloc(strlen(SD_JOURNALCTL_EXE) + strlen(argv[i]) + 1); - journal_exe_buff = strcpy(journal_exe_buff, SD_JOURNALCTL_EXE); - strncat(journal_exe_buff, argv[i], strlen(argv[i])); - r = sd_journal_add_match(j, journal_exe_buff, strlen(journal_exe_buff)); - free(journal_exe_buff); + if (path_is_absolute(argv[i])) { + char *p = NULL; + const char *path; + + p = canonicalize_file_name(argv[i]); + path = p ? p : argv[i]; + + if (stat(path, &st) < 0) { + free(p); + log_error("Couldn't stat file: %m"); + r = -errno; + goto finish; + } + + if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) { + char *t; + + t = strappend("_EXE=", path); + if (!t) { + free(p); + log_error("Out of memory"); + goto finish; + } + + r = sd_journal_add_match(j, t, strlen(t)); + free(t); } else { + free(p); log_error("File is not a regular file or is not executable: %s", argv[i]); goto finish; } - } + + free(p); + } else + r = sd_journal_add_match(j, argv[i], strlen(argv[i])); + if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); goto finish; -- cgit v1.2.3-54-g00ecf From 089842938dd0f4080084044bb9a1a3b00137926a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Jun 2012 10:32:38 +0200 Subject: journal: expose and make use of cutoff times of journal This helps explaining when the log output of "systemctl status" is incomplete because the logs got rotated since the service was started. --- src/journal/journal-def.h | 4 +- src/journal/journal-file.c | 72 ++++++++++++++++++++++++++++++++++++ src/journal/journal-file.h | 3 ++ src/journal/journalctl.c | 20 ++++++++++ src/journal/libsystemd-journal.sym | 6 +++ src/journal/sd-journal.c | 75 ++++++++++++++++++++++++++++++++++++++ src/shared/logs-show.c | 23 +++++++++++- src/shared/logs-show.h | 3 +- src/systemctl/systemctl.c | 2 +- src/systemd/sd-journal.h | 3 ++ 10 files changed, 206 insertions(+), 5 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 86aef8f372..b30ae79683 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -160,8 +160,8 @@ _packed_ struct Header { uint8_t state; uint8_t reserved[7]; sd_id128_t file_id; - sd_id128_t machine_id; - sd_id128_t boot_id; + sd_id128_t machine_id; /* last writer */ + sd_id128_t boot_id; /* last writer */ sd_id128_t seqnum_id; le64_t header_size; le64_t arena_size; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 9cec140f58..73420d9c1b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -183,6 +183,7 @@ static int journal_file_verify_header(JournalFile *f) { if (state == STATE_ONLINE) log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); + /* FIXME: immediately rotate */ else if (state == STATE_ARCHIVED) return -ESHUTDOWN; else if (state != STATE_OFFLINE) @@ -2284,3 +2285,74 @@ void journal_default_metrics(JournalMetrics *m, int fd) { format_bytes(c, sizeof(c), m->min_size), format_bytes(d, sizeof(d), m->keep_free)); } + +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { + Object *o; + int r; + + assert(f); + assert(from || to); + + if (from) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, NULL); + if (r <= 0) + return r; + + *from = le64toh(o->entry.realtime); + } + + if (to) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.realtime); + } + + return 1; +} + +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { + char t[9+32+1] = "_BOOT_ID="; + Object *o; + uint64_t p; + int r; + + assert(f); + assert(from || to); + + sd_id128_to_string(boot_id, t + 9); + + r = journal_file_find_data_object(f, t, strlen(t), &o, &p); + if (r <= 0) + return r; + + if (le64toh(o->data.n_entries) <= 0) + return 0; + + if (from) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); + if (r < 0) + return r; + + *from = le64toh(o->entry.monotonic); + } + + if (to) { + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + r = generic_array_get_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries)-1, + &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.monotonic); + } + + return 1; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index aeb6d46c79..a9925c0754 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -125,4 +125,7 @@ void journal_file_post_change(JournalFile *f); void journal_default_metrics(JournalMetrics *m, int fd); +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); + #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 9d4403267e..e9d918a733 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -281,6 +281,26 @@ int main(int argc, char *argv[]) { goto finish; } + if (!arg_quiet) { + usec_t start, end; + char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; + + r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); + if (r < 0) { + log_error("Failed to get cutoff: %s", strerror(-r)); + goto finish; + } + + if (r > 0) { + if (arg_follow) + printf("Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start)); + else + printf("Logs begin at %s, end at %s.\n", + format_timestamp(start_buf, sizeof(start_buf), start), + format_timestamp(end_buf, sizeof(end_buf), end)); + } + } + if (arg_lines >= 0) { r = sd_journal_seek_tail(j); if (r < 0) { diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 74bd298fdc..d291084262 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -51,3 +51,9 @@ global: sd_journal_send_with_location; sd_journal_sendv_with_location; } LIBSYSTEMD_JOURNAL_38; + +LIBSYSTEMD_JOURNAL_184 { +global: + sd_journal_get_cutoff_realtime_usec; + sd_journal_get_cutoff_monotonic_usec; +} LIBSYSTEMD_JOURNAL_183; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 9f46f5c6aa..5ed8c3f7a5 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1620,6 +1620,81 @@ _public_ int sd_journal_process(sd_journal *j) { } } +_public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool first = true; + int r; + + if (!j) + return -EINVAL; + if (!from && !to) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_realtime_usec(f, &fr, &t); + if (r < 0) + return r; + if (r == 0) + continue; + + if (first) { + if (from) + *from = fr; + if (to) + *to = t; + first = false; + } else { + if (from) + *from = MIN(fr, *from); + if (to) + *to = MIN(t, *to); + } + } + + return first ? 0 : 1; +} + +_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool first = true; + int r; + + if (!j) + return -EINVAL; + if (!from && !to) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t); + if (r < 0) + return r; + if (r == 0) + continue; + + if (first) { + if (from) + *from = fr; + if (to) + *to = t; + first = false; + } else { + if (from) + *from = MIN(fr, *from); + if (to) + *to = MIN(t, *to); + } + } + + return first ? 0 : 1; +} + + /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ /* if (!j) */ /* return -EINVAL; */ diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 4c59ca34cd..697b5cf4b7 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -551,7 +551,8 @@ int show_journal_by_unit( usec_t not_before, unsigned how_many, bool show_all, - bool follow) { + bool follow, + bool warn_cutoff) { char *m = NULL; sd_journal *j = NULL; @@ -639,6 +640,26 @@ int show_journal_by_unit( goto finish; } + if (warn_cutoff && line < how_many && not_before > 0) { + sd_id128_t boot_id; + usec_t cutoff; + + /* Check whether the cutoff line is too early */ + + r = sd_id128_get_boot(&boot_id); + if (r < 0) + goto finish; + + r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL); + if (r < 0) + goto finish; + + if (not_before < cutoff) + printf("Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); + + warn_cutoff = false; + } + if (!follow) break; diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 94caed5579..f8a9d406bd 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -48,7 +48,8 @@ int show_journal_by_unit( usec_t not_before, unsigned how_many, bool show_all, - bool follow); + bool follow, + bool warn_cutoff); const char* output_mode_to_string(OutputMode m); OutputMode output_mode_from_string(const char *s); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 133a27c67e..ad0cd17e14 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2554,7 +2554,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->id && arg_transport != TRANSPORT_SSH) { printf("\n"); - show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow); + show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow, !arg_quiet); } if (i->need_daemon_reload) diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index 72c23ba522..85f8604991 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -97,6 +97,9 @@ int sd_journal_seek_cursor(sd_journal *j, const char *cursor); int sd_journal_get_cursor(sd_journal *j, char **cursor); +int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to); +int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to); + /* int sd_journal_query_unique(sd_journal *j, const char *field); /\* missing *\/ */ /* int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /\* missing *\/ */ /* void sd_journal_restart_unique(sd_journal *j); /\* missing *\/ */ -- cgit v1.2.3-54-g00ecf From 59cea26a349cfa8db906b520dac72563dd773ff2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 1 Jul 2012 18:47:40 +0200 Subject: journalctl: add new switch -b to show data from current boot only --- TODO | 7 +------ man/journalctl.xml | 8 ++++++++ src/journal/journalctl.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 9 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 1a7b60e236..b3aac5af30 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,3 @@ -Fedora 18: -* chrony/ntp target? - Bugfixes: * remove MS_SHARED from src/core/execute.c and src/test/test-ns.c. They are always combined with MS_REMOUNT, which currently does nothing in the kernel, but might which fail in the @@ -52,9 +49,7 @@ Features: * new dependency type to "group" services in a target -* add switch to journalctl to only show data from current boot - -* change REquires=basic.target to RequisiteOverride=basic.target +* change Requires=basic.target to RequisiteOverride=basic.target * turn $NOTIFY_SOCKET back into an abstract namespace socket for compatibility with services which chroot() diff --git a/man/journalctl.xml b/man/journalctl.xml index d46a1648c7..6254c5c682 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -209,6 +209,14 @@ generated messages. + + + + + Show data only from + local boot. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e9d918a733..6929b76018 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -49,6 +49,7 @@ static bool arg_no_tail = false; static bool arg_new_id128 = false; static bool arg_quiet = false; static bool arg_local = false; +static bool arg_this_boot = false; static int help(void) { @@ -64,8 +65,9 @@ static int help(void) { " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, cat)\n" " -q --quiet Don't show privilege warning\n" - " --new-id128 Generate a new 128 Bit id\n" - " -l --local Only local entries\n", + " -l --local Only local entries\n" + " -b --this-boot Show data only from current boot\n" + " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); return 0; @@ -92,6 +94,7 @@ static int parse_argv(int argc, char *argv[]) { { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, { "local", no_argument, NULL, 'l' }, + { "this-boot", no_argument, NULL, 'b' }, { NULL, 0, NULL, 0 } }; @@ -100,7 +103,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:ql", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:qlb", options, NULL)) >= 0) { switch (c) { @@ -159,6 +162,10 @@ static int parse_argv(int argc, char *argv[]) { arg_local = true; break; + case 'b': + arg_this_boot = true; + break; + case '?': return -EINVAL; @@ -232,6 +239,25 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_this_boot) { + char match[9+32+1] = "_BOOT_ID="; + sd_id128_t boot_id; + + r = sd_id128_get_boot(&boot_id); + if (r < 0) { + log_error("Failed to get boot id: %s", strerror(-r)); + goto finish; + } + + sd_id128_to_string(boot_id, match + 9); + + r = sd_journal_add_match(j, match, strlen(match)); + if (r < 0) { + log_error("Failed to add match: %s", strerror(-r)); + goto finish; + } + } + for (i = optind; i < argc; i++) { if (path_is_absolute(argv[i])) { char *p = NULL; -- cgit v1.2.3-54-g00ecf From e02d1cf72d115d1d61defdca5b551672d876c6bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Jul 2012 21:46:11 +0200 Subject: journal: introduce sd_journal_wait() to simplify writing synchronous clients --- src/journal/journalctl.c | 18 +++--------------- src/journal/libsystemd-journal.sym | 5 +++++ src/journal/sd-journal.c | 15 +++++++++++++++ src/shared/logs-show.c | 11 +---------- src/systemd/sd-journal.h | 1 + 5 files changed, 25 insertions(+), 25 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6929b76018..7d8b8e51c8 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -210,7 +210,7 @@ static int generate_new_id128(void) { } int main(int argc, char *argv[]) { - int r, i, fd; + int r, i; sd_journal *j = NULL; unsigned line = 0; bool need_seek = false; @@ -301,12 +301,6 @@ int main(int argc, char *argv[]) { } } - fd = sd_journal_get_fd(j); - if (fd < 0) { - log_error("Failed to get wakeup fd: %s", strerror(-fd)); - goto finish; - } - if (!arg_quiet) { usec_t start, end; char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; @@ -385,15 +379,9 @@ int main(int argc, char *argv[]) { if (!arg_follow) break; - r = fd_wait_for_event(fd, POLLIN, (usec_t) -1); - if (r < 0) { - log_error("Couldn't wait for event: %s", strerror(-r)); - goto finish; - } - - r = sd_journal_process(j); + r = sd_journal_wait(j, (uint64_t) -1); if (r < 0) { - log_error("Failed to process: %s", strerror(-r)); + log_error("Couldn't wait for log event: %s", strerror(-r)); goto finish; } } diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index d291084262..d1ba9e8e31 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -57,3 +57,8 @@ global: sd_journal_get_cutoff_realtime_usec; sd_journal_get_cutoff_monotonic_usec; } LIBSYSTEMD_JOURNAL_183; + +LIBSYSTEMD_JOURNAL_187 { +global: + sd_journal_wait; +} LIBSYSTEMD_JOURNAL_184; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 75884594a1..149dc10bdf 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "sd-journal.h" #include "journal-def.h" @@ -1622,6 +1623,20 @@ _public_ int sd_journal_process(sd_journal *j) { } } +_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + int r, k; + + assert(j); + + r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec); + k = sd_journal_process(j); + + if (r < 0) + return r; + + return k; +} + _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { Iterator i; JournalFile *f; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 697b5cf4b7..540b5a2a2c 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -557,7 +557,6 @@ int show_journal_by_unit( char *m = NULL; sd_journal *j = NULL; int r; - int fd; unsigned line = 0; bool need_seek = false; @@ -583,10 +582,6 @@ int show_journal_by_unit( if (r < 0) goto finish; - fd = sd_journal_get_fd(j); - if (fd < 0) - goto finish; - r = sd_journal_add_match(j, m, strlen(m)); if (r < 0) goto finish; @@ -663,11 +658,7 @@ int show_journal_by_unit( if (!follow) break; - r = fd_wait_for_event(fd, POLLIN, (usec_t) -1); - if (r < 0) - goto finish; - - r = sd_journal_process(j); + r = sd_journal_wait(j, (usec_t) -1); if (r < 0) goto finish; diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index a69aa25a68..ee4acffd65 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -113,6 +113,7 @@ enum { int sd_journal_get_fd(sd_journal *j); int sd_journal_process(sd_journal *j); +int sd_journal_wait(sd_journal *j, uint64_t timeout_usec); #define SD_JOURNAL_FOREACH(j) \ if (sd_journal_seek_head(j) >= 0) \ -- cgit v1.2.3-54-g00ecf From a963990ff4ebc7908d3cf82bbd8cf34a42d57b7f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Jul 2012 01:08:38 +0200 Subject: journal: rework directory enumeration/watch logic There's now sd_journal_new_directory() for watching specific journal directories. This is exposed in journalctl -D. sd_journal_wait() and sd_journal_process() now return whether changes in the journal are invalidating or just appending. We now create inotify kernel watches only when we actually need them --- TODO | 7 +- man/journalctl.xml | 12 + src/journal/journal-internal.h | 31 ++- src/journal/journalctl.c | 152 ++++++---- src/journal/libsystemd-journal.sym | 1 + src/journal/sd-journal.c | 548 ++++++++++++++++++++++--------------- src/systemd/sd-journal.h | 4 +- 7 files changed, 464 insertions(+), 291 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 3f5c3e098b..5df72cdc5e 100644 --- a/TODO +++ b/TODO @@ -34,6 +34,8 @@ Bugfixes: Features: +* compile libsystemd-journal statically into journalctl so that we can share util.c and suchlike + * replace BindTo= by BindsTo=, but keep old name for compat * switch-root: sockets need relabelling @@ -50,8 +52,6 @@ Features: * .device aliases need to be implemented with the "following" logic, probably. -* add sd_journal_wait() to make things easier for sync programs that just want to wait for changes - * refuse taking lower-case variable names in sd_journal_send() and friends. * when running as user instance: implicitly default to WorkingDirectory=$HOME for all services. @@ -206,9 +206,6 @@ Features: * support container_ttys= -* journald: make configurable "store-on-var", "store-on-run", "dont-store", "auto" - (store-persistent, store-volatile?) - * introduce mix of BindTo and Requisite * journalctl: show multiline log messages sanely, expand tabs, and show all valid utf8 messages diff --git a/man/journalctl.xml b/man/journalctl.xml index bbc9b34151..ffe988a619 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -217,6 +217,18 @@ current boot. + + + + + Takes an absolute + directory path as argument. If + specified will opearte on the + specified journal directory instead of + the default runtime and system journal + paths. + + diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index bcffa35055..929dfcdcb8 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -31,6 +31,14 @@ #include "list.h" typedef struct Match Match; +typedef struct Location Location; +typedef struct Directory Directory; + +typedef enum location_type { + LOCATION_HEAD, + LOCATION_TAIL, + LOCATION_DISCRETE +} location_type_t; struct Match { char *data; @@ -40,13 +48,7 @@ struct Match { LIST_FIELDS(Match, matches); }; -typedef enum location_type { - LOCATION_HEAD, - LOCATION_TAIL, - LOCATION_DISCRETE -} location_type_t; - -typedef struct Location { +struct Location { location_type_t type; uint64_t seqnum; @@ -62,7 +64,13 @@ typedef struct Location { uint64_t xor_hash; bool xor_hash_set; -} Location; +}; + +struct Directory { + char *path; + int wd; + bool is_root; +}; struct sd_journal { int flags; @@ -73,12 +81,15 @@ struct sd_journal { JournalFile *current_file; uint64_t current_field; + Hashmap *directories_by_path; + Hashmap *directories_by_wd; + int inotify_fd; - Hashmap *inotify_wd_dirs; - Hashmap *inotify_wd_roots; LIST_HEAD(Match, matches); unsigned n_matches; + + unsigned current_invalidate_counter, last_invalidate_counter; }; #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7d8b8e51c8..4c975d3e7c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -39,6 +39,7 @@ #include "build.h" #include "pager.h" #include "logs-show.h" +#include "strv.h" static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; @@ -50,6 +51,7 @@ static bool arg_new_id128 = false; static bool arg_quiet = false; static bool arg_local = false; static bool arg_this_boot = false; +static const char *arg_directory = NULL; static int help(void) { @@ -67,6 +69,7 @@ static int help(void) { " -q --quiet Don't show privilege warning\n" " -l --local Only local entries\n" " -b --this-boot Show data only from current boot\n" + " -D --directory=PATH Show journal files from directory\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); @@ -95,6 +98,7 @@ static int parse_argv(int argc, char *argv[]) { { "quiet", no_argument, NULL, 'q' }, { "local", no_argument, NULL, 'l' }, { "this-boot", no_argument, NULL, 'b' }, + { "directory", required_argument, NULL, 'D' }, { NULL, 0, NULL, 0 } }; @@ -103,7 +107,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:qlb", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:qlbD:", options, NULL)) >= 0) { switch (c) { @@ -166,6 +170,10 @@ static int parse_argv(int argc, char *argv[]) { arg_this_boot = true; break; + case 'D': + arg_directory = optarg; + break; + case '?': return -EINVAL; @@ -209,68 +217,26 @@ static int generate_new_id128(void) { return 0; } -int main(int argc, char *argv[]) { - int r, i; - sd_journal *j = NULL; - unsigned line = 0; - bool need_seek = false; - struct stat st; - - log_parse_environment(); - log_open(); - - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; - - if (arg_new_id128) { - r = generate_new_id128(); - goto finish; - } - -#ifdef HAVE_ACL - if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) - log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); -#endif - - r = sd_journal_open(&j, arg_local ? SD_JOURNAL_LOCAL_ONLY : 0); - if (r < 0) { - log_error("Failed to open journal: %s", strerror(-r)); - goto finish; - } - - if (arg_this_boot) { - char match[9+32+1] = "_BOOT_ID="; - sd_id128_t boot_id; +static int add_matches(sd_journal *j, char **args) { + char **i; + int r; - r = sd_id128_get_boot(&boot_id); - if (r < 0) { - log_error("Failed to get boot id: %s", strerror(-r)); - goto finish; - } + assert(j); - sd_id128_to_string(boot_id, match + 9); + STRV_FOREACH(i, args) { - r = sd_journal_add_match(j, match, strlen(match)); - if (r < 0) { - log_error("Failed to add match: %s", strerror(-r)); - goto finish; - } - } - - for (i = optind; i < argc; i++) { - if (path_is_absolute(argv[i])) { - char *p = NULL; + if (path_is_absolute(*i)) { + char *p; const char *path; + struct stat st; - p = canonicalize_file_name(argv[i]); - path = p ? p : argv[i]; + p = canonicalize_file_name(*i); + path = p ? p : *i; if (stat(path, &st) < 0) { free(p); log_error("Couldn't stat file: %m"); - r = -errno; - goto finish; + return -errno; } if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) { @@ -280,27 +246,95 @@ int main(int argc, char *argv[]) { if (!t) { free(p); log_error("Out of memory"); - goto finish; + return -ENOMEM; } r = sd_journal_add_match(j, t, strlen(t)); free(t); } else { free(p); - log_error("File is not a regular file or is not executable: %s", argv[i]); - goto finish; + log_error("File is not a regular file or is not executable: %s", *i); + return -EINVAL; } free(p); } else - r = sd_journal_add_match(j, argv[i], strlen(argv[i])); + r = sd_journal_add_match(j, *i, strlen(*i)); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); - goto finish; + return r; } } + return 0; +} + +static int add_this_boot(sd_journal *j) { + char match[9+32+1] = "_BOOT_ID="; + sd_id128_t boot_id; + int r; + + if (!arg_this_boot) + return 0; + + r = sd_id128_get_boot(&boot_id); + if (r < 0) { + log_error("Failed to get boot id: %s", strerror(-r)); + return r; + } + + sd_id128_to_string(boot_id, match + 9); + r = sd_journal_add_match(j, match, strlen(match)); + if (r < 0) { + log_error("Failed to add match: %s", strerror(-r)); + return r; + } + + return 0; +} + +int main(int argc, char *argv[]) { + int r; + sd_journal *j = NULL; + unsigned line = 0; + bool need_seek = false; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + if (arg_new_id128) { + r = generate_new_id128(); + goto finish; + } + +#ifdef HAVE_ACL + if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) + log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); +#endif + + if (arg_directory) + r = sd_journal_open_directory(&j, arg_directory, 0); + else + r = sd_journal_open(&j, arg_local ? SD_JOURNAL_LOCAL_ONLY : 0); + + if (r < 0) { + log_error("Failed to open journal: %s", strerror(-r)); + goto finish; + } + + r = add_this_boot(j); + if (r < 0) + goto finish; + + r = add_matches(j, argv + optind); + if (r < 0) + goto finish; + if (!arg_quiet) { usec_t start, end; char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index d1ba9e8e31..fa4519a682 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -61,4 +61,5 @@ global: LIBSYSTEMD_JOURNAL_187 { global: sd_journal_wait; + sd_journal_open_directory; } LIBSYSTEMD_JOURNAL_184; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 149dc10bdf..6331f042ce 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -935,8 +935,8 @@ _public_ int sd_journal_seek_tail(sd_journal *j) { return 0; } -static int add_file(sd_journal *j, const char *prefix, const char *dir, const char *filename) { - char *fn; +static int add_file(sd_journal *j, const char *prefix, const char *filename) { + char *path; int r; JournalFile *f; @@ -949,27 +949,23 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch (startswith(filename, "system@") && endswith(filename, ".journal")))) return 0; - if (dir) - fn = join(prefix, "/", dir, "/", filename, NULL); - else - fn = join(prefix, "/", filename, NULL); - - if (!fn) + path = join(prefix, "/", filename, NULL); + if (!path) return -ENOMEM; - if (hashmap_get(j->files, fn)) { - free(fn); + if (hashmap_get(j->files, path)) { + free(path); return 0; } if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) { - log_debug("Too many open journal files, not adding %s, ignoring.", fn); - free(fn); + log_debug("Too many open journal files, not adding %s, ignoring.", path); + free(path); return 0; } - r = journal_file_open(fn, O_RDONLY, 0, NULL, &f); - free(fn); + r = journal_file_open(path, O_RDONLY, 0, NULL, &f); + free(path); if (r < 0) { if (errno == ENOENT) @@ -986,166 +982,302 @@ static int add_file(sd_journal *j, const char *prefix, const char *dir, const ch return r; } + j->current_invalidate_counter ++; + log_debug("File %s got added.", f->path); return 0; } -static int remove_file(sd_journal *j, const char *prefix, const char *dir, const char *filename) { - char *fn; +static int remove_file(sd_journal *j, const char *prefix, const char *filename) { + char *path; JournalFile *f; assert(j); assert(prefix); assert(filename); - if (dir) - fn = join(prefix, "/", dir, "/", filename, NULL); - else - fn = join(prefix, "/", filename, NULL); - - if (!fn) + path = join(prefix, "/", filename, NULL); + if (!path) return -ENOMEM; - f = hashmap_get(j->files, fn); - free(fn); - + f = hashmap_get(j->files, path); + free(path); if (!f) return 0; hashmap_remove(j->files, f->path); journal_file_close(f); + j->current_invalidate_counter ++; + log_debug("File %s got removed.", f->path); return 0; } -static int add_directory(sd_journal *j, const char *prefix, const char *dir) { - char *fn; +static int add_directory(sd_journal *j, const char *prefix, const char *dirname) { + char *path; int r; DIR *d; - int wd; sd_id128_t id, mid; + Directory *m; assert(j); assert(prefix); - assert(dir); + assert(dirname); if ((j->flags & SD_JOURNAL_LOCAL_ONLY) && - (sd_id128_from_string(dir, &id) < 0 || + (sd_id128_from_string(dirname, &id) < 0 || sd_id128_get_machine(&mid) < 0 || !sd_id128_equal(id, mid))) return 0; - fn = join(prefix, "/", dir, NULL); - if (!fn) + path = join(prefix, "/", dirname, NULL); + if (!path) return -ENOMEM; - d = opendir(fn); - + d = opendir(path); if (!d) { - free(fn); + log_debug("Failed to open %s: %m", path); + free(path); + if (errno == ENOENT) return 0; - return -errno; } - wd = inotify_add_watch(j->inotify_fd, fn, - IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| - IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT| - IN_DONT_FOLLOW|IN_ONLYDIR); - if (wd > 0) { - if (hashmap_put(j->inotify_wd_dirs, INT_TO_PTR(wd), fn) < 0) - inotify_rm_watch(j->inotify_fd, wd); - else - fn = NULL; + m = hashmap_get(j->directories_by_path, path); + if (!m) { + m = new0(Directory, 1); + if (!m) { + closedir(d); + free(path); + return -ENOMEM; + } + + m->is_root = false; + m->path = path; + + if (hashmap_put(j->directories_by_path, m->path, m) < 0) { + closedir(d); + free(m->path); + free(m); + return -ENOMEM; + } + + j->current_invalidate_counter ++; + + log_debug("Directory %s got added.", m->path); + + } else if (m->is_root) { + free (path); + closedir(d); + return 0; + } else + free(path); + + if (m->wd <= 0 && j->inotify_fd >= 0) { + + m->wd = inotify_add_watch(j->inotify_fd, m->path, + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT| + IN_DONT_FOLLOW|IN_ONLYDIR); + + if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) + inotify_rm_watch(j->inotify_fd, m->wd); + } + + for (;;) { + struct dirent buf, *de; + + r = readdir_r(d, &buf, &de); + if (r != 0 || !de) + break; + + if (dirent_is_file_with_suffix(de, ".journal")) { + r = add_file(j, m->path, de->d_name); + if (r < 0) + log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r)); + } + } + + closedir(d); + + return 0; +} + +static int add_root_directory(sd_journal *j, const char *p) { + DIR *d; + Directory *m; + int r; + + assert(j); + assert(p); + + if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) && + !path_startswith(p, "/run")) + return -EINVAL; + + d = opendir(p); + if (!d) + return -errno; + + m = hashmap_get(j->directories_by_path, p); + if (!m) { + m = new0(Directory, 1); + if (!m) { + closedir(d); + return -ENOMEM; + } + + m->is_root = true; + m->path = strdup(p); + if (!m->path) { + closedir(d); + free(m); + return -ENOMEM; + } + + if (hashmap_put(j->directories_by_path, m->path, m) < 0) { + closedir(d); + free(m->path); + free(m); + return -ENOMEM; + } + + j->current_invalidate_counter ++; + + log_debug("Root directory %s got added.", m->path); + + } else if (!m->is_root) { + closedir(d); + return 0; } - free(fn); + if (m->wd <= 0 && j->inotify_fd >= 0) { + + m->wd = inotify_add_watch(j->inotify_fd, m->path, + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_DONT_FOLLOW|IN_ONLYDIR); + + if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0) + inotify_rm_watch(j->inotify_fd, m->wd); + } for (;;) { struct dirent buf, *de; + sd_id128_t id; r = readdir_r(d, &buf, &de); if (r != 0 || !de) break; - if (!dirent_is_file_with_suffix(de, ".journal")) - continue; + if (dirent_is_file_with_suffix(de, ".journal")) { + r = add_file(j, m->path, de->d_name); + if (r < 0) + log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r)); - r = add_file(j, prefix, dir, de->d_name); - if (r < 0) - log_debug("Failed to add file %s/%s/%s: %s", prefix, dir, de->d_name, strerror(-r)); + } else if ((de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) && + sd_id128_from_string(de->d_name, &id) >= 0) { + + r = add_directory(j, m->path, de->d_name); + if (r < 0) + log_debug("Failed to add directory %s/%s: %s", m->path, de->d_name, strerror(-r)); + } } closedir(d); - log_debug("Directory %s/%s got added.", prefix, dir); + return 0; +} + +static int remove_directory(sd_journal *j, Directory *d) { + assert(j); + + if (d->wd > 0) { + hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd)); + + if (j->inotify_fd >= 0) + inotify_rm_watch(j->inotify_fd, d->wd); + } + + hashmap_remove(j->directories_by_path, d->path); + + if (d->is_root) + log_debug("Root directory %s got removed.", d->path); + else + log_debug("Directory %s got removed.", d->path); + + free(d->path); + free(d); return 0; } -static void remove_directory_wd(sd_journal *j, int wd) { - char *p; +static int add_search_paths(sd_journal *j) { + + const char search_paths[] = + "/run/log/journal\0" + "/var/log/journal\0"; + const char *p; assert(j); - assert(wd > 0); - if (j->inotify_fd >= 0) - inotify_rm_watch(j->inotify_fd, wd); + /* We ignore most errors here, since the idea is to only open + * what's actually accessible, and ignore the rest. */ - p = hashmap_remove(j->inotify_wd_dirs, INT_TO_PTR(wd)); + NULSTR_FOREACH(p, search_paths) + add_root_directory(j, p); - if (p) { - log_debug("Directory %s got removed.", p); - free(p); - } + return 0; } -static void add_root_wd(sd_journal *j, const char *p) { - int wd; - char *k; - +static int allocate_inotify(sd_journal *j) { assert(j); - assert(p); - wd = inotify_add_watch(j->inotify_fd, p, - IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| - IN_DONT_FOLLOW|IN_ONLYDIR); - if (wd <= 0) - return; + if (j->inotify_fd < 0) { + j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (j->inotify_fd < 0) + return -errno; + } - k = strdup(p); - if (!k || hashmap_put(j->inotify_wd_roots, INT_TO_PTR(wd), k) < 0) { - inotify_rm_watch(j->inotify_fd, wd); - free(k); + if (!j->directories_by_wd) { + j->directories_by_wd = hashmap_new(trivial_hash_func, trivial_compare_func); + if (!j->directories_by_wd) + return -ENOMEM; } + + return 0; } -static void remove_root_wd(sd_journal *j, int wd) { - char *p; +static sd_journal *journal_new(int flags) { + sd_journal *j; - assert(j); - assert(wd > 0); + j = new0(sd_journal, 1); + if (!j) + return NULL; - if (j->inotify_fd >= 0) - inotify_rm_watch(j->inotify_fd, wd); + j->inotify_fd = -1; + j->flags = flags; - p = hashmap_remove(j->inotify_wd_roots, INT_TO_PTR(wd)); + j->files = hashmap_new(string_hash_func, string_compare_func); + if (!j->files) { + free(j); + return NULL; + } - if (p) { - log_debug("Root %s got removed.", p); - free(p); + j->directories_by_path = hashmap_new(string_hash_func, string_compare_func); + if (!j->directories_by_path) { + hashmap_free(j->files); + free(j); + return NULL; } + + return j; } _public_ int sd_journal_open(sd_journal **ret, int flags) { sd_journal *j; - const char *p; - const char search_paths[] = - "/run/log/journal\0" - "/var/log/journal\0"; int r; if (!ret) @@ -1156,75 +1288,43 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) { SD_JOURNAL_SYSTEM_ONLY)) return -EINVAL; - j = new0(sd_journal, 1); + j = journal_new(flags); if (!j) return -ENOMEM; - j->flags = flags; - - j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); - if (j->inotify_fd < 0) { - r = -errno; - goto fail; - } - - j->files = hashmap_new(string_hash_func, string_compare_func); - if (!j->files) { - r = -ENOMEM; - goto fail; - } - - j->inotify_wd_dirs = hashmap_new(trivial_hash_func, trivial_compare_func); - j->inotify_wd_roots = hashmap_new(trivial_hash_func, trivial_compare_func); - - if (!j->inotify_wd_dirs || !j->inotify_wd_roots) { - r = -ENOMEM; + r = add_search_paths(j); + if (r < 0) goto fail; - } - /* We ignore most errors here, since the idea is to only open - * what's actually accessible, and ignore the rest. */ - - NULSTR_FOREACH(p, search_paths) { - DIR *d; - - if ((flags & SD_JOURNAL_RUNTIME_ONLY) && - !path_startswith(p, "/run")) - continue; + *ret = j; + return 0; - d = opendir(p); - if (!d) { - if (errno != ENOENT) - log_debug("Failed to open %s: %m", p); - continue; - } +fail: + sd_journal_close(j); - add_root_wd(j, p); + return r; +} - for (;;) { - struct dirent buf, *de; - sd_id128_t id; +_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { + sd_journal *j; + int r; - r = readdir_r(d, &buf, &de); - if (r != 0 || !de) - break; + if (!ret) + return -EINVAL; - if (dirent_is_file_with_suffix(de, ".journal")) { - r = add_file(j, p, NULL, de->d_name); - if (r < 0) - log_debug("Failed to add file %s/%s: %s", p, de->d_name, strerror(-r)); + if (!path || !path_is_absolute(path)) + return -EINVAL; - } else if ((de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) && - sd_id128_from_string(de->d_name, &id) >= 0) { + if (flags != 0) + return -EINVAL; - r = add_directory(j, p, de->d_name); - if (r < 0) - log_debug("Failed to add directory %s/%s: %s", p, de->d_name, strerror(-r)); - } - } + j = journal_new(flags); + if (!j) + return -ENOMEM; - closedir(d); - } + r = add_root_directory(j, path); + if (r < 0) + goto fail; *ret = j; return 0; @@ -1233,44 +1333,34 @@ fail: sd_journal_close(j); return r; -}; +} _public_ void sd_journal_close(sd_journal *j) { + Directory *d; + JournalFile *f; + if (!j) return; - if (j->inotify_wd_dirs) { - void *k; - - while ((k = hashmap_first_key(j->inotify_wd_dirs))) - remove_directory_wd(j, PTR_TO_INT(k)); - - hashmap_free(j->inotify_wd_dirs); - } - - if (j->inotify_wd_roots) { - void *k; - - while ((k = hashmap_first_key(j->inotify_wd_roots))) - remove_root_wd(j, PTR_TO_INT(k)); - - hashmap_free(j->inotify_wd_roots); - } + while ((f = hashmap_steal_first(j->files))) + journal_file_close(f); - if (j->files) { - JournalFile *f; + hashmap_free(j->files); - while ((f = hashmap_steal_first(j->files))) - journal_file_close(f); + while ((d = hashmap_first(j->directories_by_path))) + remove_directory(j, d); - hashmap_free(j->files); - } + while ((d = hashmap_first(j->directories_by_wd))) + remove_directory(j, d); - sd_journal_flush_matches(j); + hashmap_free(j->directories_by_path); + hashmap_free(j->directories_by_wd); if (j->inotify_fd >= 0) close_nointr_nofail(j->inotify_fd); + sd_journal_flush_matches(j); + free(j); } @@ -1506,78 +1596,74 @@ _public_ void sd_journal_restart_data(sd_journal *j) { } _public_ int sd_journal_get_fd(sd_journal *j) { + int r; + if (!j) return -EINVAL; + if (j->inotify_fd >= 0) + return j->inotify_fd; + + r = allocate_inotify(j); + if (r < 0) + return r; + + /* Iterate through all dirs again, to add them to the + * inotify */ + r = add_search_paths(j); + if (r < 0) + return r; + return j->inotify_fd; } static void process_inotify_event(sd_journal *j, struct inotify_event *e) { - char *p; + Directory *d; int r; assert(j); assert(e); /* Is this a subdirectory we watch? */ - p = hashmap_get(j->inotify_wd_dirs, INT_TO_PTR(e->wd)); - if (p) { + d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd)); + if (d) { + sd_id128_t id; if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) { /* Event for a journal file */ if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { - r = add_file(j, p, NULL, e->name); + r = add_file(j, d->path, e->name); if (r < 0) - log_debug("Failed to add file %s/%s: %s", p, e->name, strerror(-r)); + log_debug("Failed to add file %s/%s: %s", d->path, e->name, strerror(-r)); + } else if (e->mask & (IN_DELETE|IN_UNMOUNT)) { - r = remove_file(j, p, NULL, e->name); + r = remove_file(j, d->path, e->name); if (r < 0) - log_debug("Failed to remove file %s/%s: %s", p, e->name, strerror(-r)); + log_debug("Failed to remove file %s/%s: %s", d->path, e->name, strerror(-r)); } - } else if (e->len == 0) { + } else if (!d->is_root && e->len == 0) { - /* Event for the directory itself */ - - if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) - remove_directory_wd(j, e->wd); - } - - return; - } - - /* Must be the root directory then? */ - p = hashmap_get(j->inotify_wd_roots, INT_TO_PTR(e->wd)); - if (p) { - sd_id128_t id; + /* Event for a subdirectory */ - if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) { - - /* Event for a journal file */ - - if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { - r = add_file(j, p, NULL, e->name); - if (r < 0) - log_debug("Failed to add file %s/%s: %s", p, e->name, strerror(-r)); - } else if (e->mask & (IN_DELETE|IN_UNMOUNT)) { - - r = remove_file(j, p, NULL, e->name); + if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) { + r = remove_directory(j, d); if (r < 0) - log_debug("Failed to remove file %s/%s: %s", p, e->name, strerror(-r)); + log_debug("Failed to remove directory %s: %s", d->path, strerror(-r)); } - } else if ((e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) { - /* Event for subdirectory */ + } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && sd_id128_from_string(e->name, &id) >= 0) { - if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { + /* Event for root directory */ - r = add_directory(j, p, e->name); + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) { + r = add_directory(j, d->path, e->name); if (r < 0) - log_debug("Failed to add directory %s/%s: %s", p, e->name, strerror(-r)); + log_debug("Failed to add directory %s/%s: %s", d->path, e->name, strerror(-r)); } } @@ -1590,8 +1676,20 @@ static void process_inotify_event(sd_journal *j, struct inotify_event *e) { log_warning("Unknown inotify event."); } +static int determine_change(sd_journal *j) { + bool b; + + assert(j); + + b = j->current_invalidate_counter != j->last_invalidate_counter; + j->last_invalidate_counter = j->current_invalidate_counter; + + return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND; +} + _public_ int sd_journal_process(sd_journal *j) { uint8_t buffer[sizeof(struct inotify_event) + FILENAME_MAX]; + bool got_something = false; if (!j) return -EINVAL; @@ -1602,12 +1700,14 @@ _public_ int sd_journal_process(sd_journal *j) { l = read(j->inotify_fd, buffer, sizeof(buffer)); if (l < 0) { - if (errno == EINTR || errno == EAGAIN) - return 0; + if (errno == EAGAIN || errno == EINTR) + return got_something ? determine_change(j) : SD_JOURNAL_NOP; return -errno; } + got_something = true; + e = (struct inotify_event*) buffer; while (l > 0) { size_t step; @@ -1621,20 +1721,38 @@ _public_ int sd_journal_process(sd_journal *j) { l -= step; } } + + return determine_change(j); } _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { - int r, k; + int r; assert(j); - r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec); - k = sd_journal_process(j); + if (j->inotify_fd < 0) { + + /* This is the first invocation, hence create the + * inotify watch */ + r = sd_journal_get_fd(j); + if (r < 0) + return r; + + /* The journal might have changed since the context + * object was created and we weren't watching before, + * hence don't wait for anything, and return + * immediately. */ + return determine_change(j); + } + + do { + r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec); + } while (r == -EINTR); if (r < 0) return r; - return k; + return sd_journal_process(j); } _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index ee4acffd65..ab968b9496 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -72,6 +72,7 @@ enum { }; int sd_journal_open(sd_journal **ret, int flags); +int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); void sd_journal_close(sd_journal *j); int sd_journal_previous(sd_journal *j); @@ -107,8 +108,7 @@ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id enum { SD_JOURNAL_NOP, SD_JOURNAL_APPEND, - SD_JOURNAL_INVALIDATE_ADD, - SD_JOURNAL_INVALIDATE_REMOVE + SD_JOURNAL_INVALIDATE }; int sd_journal_get_fd(sd_journal *j); -- cgit v1.2.3-54-g00ecf From 14a65d65a0c25ba4809b8d97f54ebf3e12eac84c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Jul 2012 01:36:55 +0200 Subject: journalctl: add a marker to log output for reboots With this we'll print a marker "----- Reboot -----" between two subsequent lines with different boot IDs. --- TODO | 2 -- man/journalctl.xml | 2 +- src/journal/journalctl.c | 14 ++++++++++++++ src/journal/sd-journal.c | 6 +++--- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 5df72cdc5e..0b646eaa2c 100644 --- a/TODO +++ b/TODO @@ -56,8 +56,6 @@ Features: * when running as user instance: implicitly default to WorkingDirectory=$HOME for all services. -* journalctl highlight reboots - * Merge KillUnit()'s mode and who params into one * load-fragment: when loading a unit file via a chain of symlinks diff --git a/man/journalctl.xml b/man/journalctl.xml index ffe988a619..bb964b01ed 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -223,7 +223,7 @@ Takes an absolute directory path as argument. If - specified will opearte on the + specified will operate on the specified journal directory instead of the default runtime and system journal paths. diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 4c975d3e7c..43cd2a3fef 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -299,6 +299,8 @@ int main(int argc, char *argv[]) { sd_journal *j = NULL; unsigned line = 0; bool need_seek = false; + sd_id128_t previous_boot_id; + bool previous_boot_id_valid = false; log_parse_environment(); log_open(); @@ -390,6 +392,8 @@ int main(int argc, char *argv[]) { for (;;) { for (;;) { + sd_id128_t boot_id; + if (need_seek) { r = sd_journal_next(j); if (r < 0) { @@ -401,6 +405,16 @@ int main(int argc, char *argv[]) { if (r == 0) break; + r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); + if (r >= 0) { + if (previous_boot_id_valid && + !sd_id128_equal(boot_id, previous_boot_id)) + printf(ANSI_HIGHLIGHT_ON "----- Reboot -----" ANSI_HIGHLIGHT_OFF "\n"); + + previous_boot_id = boot_id; + previous_boot_id_valid = true; + } + line ++; r = output_journal(j, arg_output, line, 0, arg_show_all); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 6331f042ce..5420be13ea 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1397,8 +1397,6 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 if (!j) return -EINVAL; - if (!ret) - return -EINVAL; f = j->current_file; if (!f) @@ -1422,7 +1420,9 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 return -ESTALE; } - *ret = le64toh(o->entry.monotonic); + if (ret) + *ret = le64toh(o->entry.monotonic); + return 0; } -- cgit v1.2.3-54-g00ecf From cbdca8525b4f36297cb9e5cb090a9648763ed1bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 13 Jul 2012 00:29:26 +0200 Subject: journal: beef up journal matches considerably we now can take multiple matches, and they will apply as AND if they apply to different fields and OR if they apply to the same fields. Also, terms of this kind can be combined with an overreaching OR. --- .gitignore | 2 + Makefile.am | 40 ++- man/journalctl.xml | 56 ++- man/systemd.journal-fields.xml | 7 +- src/journal/journal-file.c | 219 ++++++++++-- src/journal/journal-file.h | 4 + src/journal/journal-internal.h | 38 +- src/journal/journalctl.c | 10 +- src/journal/sd-journal.c | 704 +++++++++++++++++++++++--------------- src/journal/test-journal-match.c | 67 ++++ src/journal/test-journal-send.c | 4 + src/journal/test-journal-stream.c | 169 +++++++++ src/systemd/sd-journal.h | 1 + 13 files changed, 974 insertions(+), 347 deletions(-) create mode 100644 src/journal/test-journal-match.c create mode 100644 src/journal/test-journal-stream.c (limited to 'src/journal/journalctl.c') diff --git a/.gitignore b/.gitignore index 07321768a6..c4a7b0ddec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +/test-journal-match +/test-journal-stream /test-unit-name /systemd-system-update-generator /systemd-fstab-generator diff --git a/Makefile.am b/Makefile.am index aedd22052b..14f9455b51 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2232,29 +2232,13 @@ journalctl_LDADD = \ libsystemd-logs.la test_journal_SOURCES = \ - src/journal/test-journal.c \ - src/journal/sd-journal.c \ - src/journal/journal-file.c \ - src/journal/lookup3.c \ - src/journal/journal-send.c + src/journal/test-journal.c test_journal_LDADD = \ - libsystemd-label.la \ libsystemd-shared.la \ + libsystemd-journal-internal.la \ libsystemd-id128-internal.la -if HAVE_XZ -test_journal_SOURCES += \ - src/journal/compress.c - -test_journal_CFLAGS = \ - $(AM_CFLAGS) \ - $(XZ_CFLAGS) - -test_journal_LDADD += \ - $(XZ_LIBS) -endif - test_journal_send_SOURCES = \ src/journal/test-journal-send.c @@ -2263,6 +2247,22 @@ test_journal_send_LDADD = \ libsystemd-journal-internal.la \ libsystemd-id128-internal.la +test_journal_match_SOURCES = \ + src/journal/test-journal-match.c + +test_journal_match_LDADD = \ + libsystemd-shared.la \ + libsystemd-journal-internal.la \ + libsystemd-id128-internal.la + +test_journal_stream_SOURCES = \ + src/journal/test-journal-stream.c + +test_journal_stream_LDADD = \ + libsystemd-shared.la \ + libsystemd-journal-internal.la \ + libsystemd-id128-internal.la + libsystemd_journal_la_SOURCES = \ src/journal/sd-journal.c \ src/journal/journal-file.c \ @@ -2327,7 +2327,9 @@ UNINSTALL_EXEC_HOOKS += \ noinst_PROGRAMS += \ test-journal \ - test-journal-send + test-journal-send \ + test-journal-match \ + test-journal-stream pkginclude_HEADERS += \ src/systemd/sd-journal.h \ diff --git a/man/journalctl.xml b/man/journalctl.xml index bb964b01ed..f314fb6d26 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -49,7 +49,7 @@ - journalctl OPTIONS MATCH + journalctl OPTIONS MATCHES @@ -66,12 +66,25 @@ contents of the journal, starting with the oldest entry collected. - If a match argument is passed the output is - filtered accordingly. A match is in the format - FIELD=VALUE, - e.g. _SYSTEMD_UNIT=httpd.service. See + If one or more match arguments are passed the + output is filtered accordingly. A match is in the + format FIELD=VALUE, + e.g. _SYSTEMD_UNIT=httpd.service, + referring to the components of a structured journal + entry. See systemd.journal-fields7 - for a list of well-known fields. + for a list of well-known fields. If multiple matches + are specified matching different fields the log + entries are filtered by both, i.e. the resulting output + will show only entries matching all the specified + matches of this kind. If two matches apply to the same + field, then they are automatically matched as + alternatives, i.e. the resulting output will show + entries matching any of the specified matches for the + same field. Finally, if the character + "+" appears as separate word on the + command line all matches before and after are combined + in a disjunction (i.e. logical OR). Output is interleaved from all accessible journal files, whether they are rotated or currently @@ -271,6 +284,37 @@ + + Examples + + Without arguments all collected logs are shown + unfiltered: + + journalctl + + With one match specified all entries with a field matching the expression are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service + + If two different fields are matched only entries matching both expressions at the same time are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + + If two matches refer to the same field all entries matching either expression are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _SYSTEMD_UNIT=dbus.service + + If the separator "+" is used + two expression may be combined in a logical OR. The + following will show all messages from the Avahi + service process with the PID 28097 plus all messages + from the D-Bus service (from any of its + processes): + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + _SYSTEMD_UNIT=dbus.service + + + See Also diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml index fd0beb968f..4f664f43e5 100644 --- a/man/systemd.journal-fields.xml +++ b/man/systemd.journal-fields.xml @@ -299,7 +299,12 @@ addresses of journal entries are serialized into fields prefixed with double underscores. Note that these aren't proper fields when stored in the journal, - but addressing meta data of entries. + but addressing meta data of entries. They cannot be + written as part of structured log entries via calls + such as + sd_journal_send3. They + may also not be used as matches for + sd_journal_add_match3 diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 9665a0535b..0aada9c419 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1212,8 +1212,15 @@ static int generic_array_bisect(JournalFile *f, } } - if (k > n) + if (k > n) { + if (direction == DIRECTION_UP) { + i = n; + subtract_one = true; + goto found; + } + return 0; + } last_p = lp; @@ -1246,7 +1253,7 @@ found: *offset = p; if (idx) - *idx = t + i - (subtract_one ? 1 : 0); + *idx = t + i + (subtract_one ? -1 : 0); return 1; } @@ -1263,6 +1270,8 @@ static int generic_array_bisect_plus_one(JournalFile *f, uint64_t *idx) { int r; + bool step_back = false; + Object *o; assert(f); assert(test_object); @@ -1279,33 +1288,77 @@ static int generic_array_bisect_plus_one(JournalFile *f, if (r == TEST_FOUND) r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; - if (r == TEST_RIGHT) { - Object *o; - - r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); - if (r < 0) - return r; + /* if we are looking with DIRECTION_UP then we need to first + see if in the actual array there is a matching entry, and + return the last one of that. But if there isn't any we need + to return this one. Hence remember this, and return it + below. */ + if (r == TEST_LEFT) + step_back = direction == DIRECTION_UP; - if (ret) - *ret = o; - - if (offset) - *offset = extra; - - if (idx) - *idx = 0; - - return 1; + if (r == TEST_RIGHT) { + if (direction == DIRECTION_DOWN) + goto found; + else + return 0; } r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx); + if (r == 0 && step_back) + goto found; + if (r > 0 && idx) (*idx) ++; return r; + +found: + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = extra; + + if (idx) + *idx = 0; + + return 1; +} + +static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) { + assert(f); + assert(p > 0); + + if (p == needle) + return TEST_FOUND; + else if (p < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +int journal_file_move_to_entry_by_offset( + JournalFile *f, + uint64_t p, + direction_t direction, + Object **ret, + uint64_t *offset) { + + return generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + p, + test_object_offset, + direction, + ret, offset, NULL); } + static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) { Object *o; int r; @@ -1407,12 +1460,13 @@ int journal_file_move_to_entry_by_monotonic( Object *o; int r; - sd_id128_to_string(boot_id, t + 9); + assert(f); + sd_id128_to_string(boot_id, t + 9); r = journal_file_find_data_object(f, t, strlen(t), &o, NULL); if (r < 0) return r; - else if (r == 0) + if (r == 0) return -ENOENT; return generic_array_bisect_plus_one(f, @@ -1425,18 +1479,6 @@ int journal_file_move_to_entry_by_monotonic( ret, offset, NULL); } -static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) { - assert(f); - assert(p > 0); - - if (p == needle) - return TEST_FOUND; - else if (p < needle) - return TEST_LEFT; - else - return TEST_RIGHT; -} - int journal_file_next_entry( JournalFile *f, Object *o, uint64_t p, @@ -1601,6 +1643,119 @@ int journal_file_next_entry_for_data( ret, offset); } +int journal_file_move_to_entry_by_offset_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t p, + direction_t direction, + Object **ret, uint64_t *offset) { + + int r; + Object *d; + + assert(f); + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + p, + test_object_offset, + direction, + ret, offset, NULL); +} + +int journal_file_move_to_entry_by_monotonic_for_data( + JournalFile *f, + uint64_t data_offset, + sd_id128_t boot_id, + uint64_t monotonic, + direction_t direction, + Object **ret, uint64_t *offset) { + + char t[9+32+1] = "_BOOT_ID="; + Object *o, *d; + int r; + uint64_t b, z; + + assert(f); + + /* First, seek by time */ + sd_id128_to_string(boot_id, t + 9); + r = journal_file_find_data_object(f, t, strlen(t), &o, &b); + if (r < 0) + return r; + if (r == 0) + return -ENOENT; + + r = generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + monotonic, + test_object_monotonic, + direction, + NULL, &z, NULL); + if (r <= 0) + return r; + + /* And now, continue seeking until we find an entry that + * exists in both bisection arrays */ + + for (;;) { + Object *qo; + uint64_t p, q; + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + r = generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + z, + test_object_offset, + direction, + NULL, &p, NULL); + if (r <= 0) + return r; + + r = journal_file_move_to_object(f, OBJECT_DATA, b, &o); + if (r < 0) + return r; + + r = generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + p, + test_object_offset, + direction, + &qo, &q, NULL); + + if (r <= 0) + return r; + + if (p == q) { + if (ret) + *ret = qo; + if (offset) + *offset = q; + + return 1; + } + + z = q; + } + + return 0; +} + int journal_file_move_to_entry_by_seqnum_for_data( JournalFile *f, uint64_t data_offset, diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index a9925c0754..5c42ecdf6c 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -43,6 +43,7 @@ enum { WINDOW_DATA_HASH_TABLE = OBJECT_DATA_HASH_TABLE, WINDOW_FIELD_HASH_TABLE = OBJECT_FIELD_HASH_TABLE, WINDOW_ENTRY_ARRAY = OBJECT_ENTRY_ARRAY, + WINDOW_SIGNATURE = OBJECT_SIGNATURE, WINDOW_HEADER, _WINDOW_MAX }; @@ -106,12 +107,15 @@ int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_offset(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, uint64_t data_offset, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset); diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 929dfcdcb8..482ef61b9a 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -28,28 +28,46 @@ #include +#include "journal-def.h" #include "list.h" +#include "hashmap.h" +#include "journal-file.h" + +typedef enum MatchType MatchType; +typedef enum LocationType LocationType; typedef struct Match Match; typedef struct Location Location; typedef struct Directory Directory; -typedef enum location_type { - LOCATION_HEAD, - LOCATION_TAIL, - LOCATION_DISCRETE -} location_type_t; +typedef enum MatchType { + MATCH_DISCRETE, + MATCH_OR_TERM, + MATCH_AND_TERM +} MatchType; struct Match { + MatchType type; + Match *parent; + LIST_FIELDS(Match, matches); + + /* For concrete matches */ char *data; size_t size; le64_t le_hash; - LIST_FIELDS(Match, matches); + /* For terms */ + LIST_HEAD(Match, matches); }; +typedef enum LocationType { + LOCATION_HEAD, + LOCATION_TAIL, + LOCATION_DISCRETE +} LocationType; + struct Location { - location_type_t type; + LocationType type; uint64_t seqnum; sd_id128_t seqnum_id; @@ -78,6 +96,7 @@ struct sd_journal { Hashmap *files; Location current_location; + JournalFile *current_file; uint64_t current_field; @@ -86,10 +105,11 @@ struct sd_journal { int inotify_fd; - LIST_HEAD(Match, matches); - unsigned n_matches; + Match *level0, *level1; unsigned current_invalidate_counter, last_invalidate_counter; }; +char *journal_make_match_string(sd_journal *j); + #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 43cd2a3fef..65b3bd5a86 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -225,7 +225,9 @@ static int add_matches(sd_journal *j, char **args) { STRV_FOREACH(i, args) { - if (path_is_absolute(*i)) { + if (streq(*i, "+")) + r = sd_journal_add_disjunction(j); + else if (path_is_absolute(*i)) { char *p; const char *path; struct stat st; @@ -249,7 +251,7 @@ static int add_matches(sd_journal *j, char **args) { return -ENOMEM; } - r = sd_journal_add_match(j, t, strlen(t)); + r = sd_journal_add_match(j, t, 0); free(t); } else { free(p); @@ -259,10 +261,10 @@ static int add_matches(sd_journal *j, char **args) { free(p); } else - r = sd_journal_add_match(j, *i, strlen(*i)); + r = sd_journal_add_match(j, *i, 0); if (r < 0) { - log_error("Failed to add match: %s", strerror(-r)); + log_error("Failed to add match '%s': %s", *i, strerror(-r)); return r; } } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index f4ef1aea7c..4bcc65c5c7 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -87,102 +87,272 @@ static void set_location(sd_journal *j, JournalFile *f, Object *o, uint64_t offs f->current_offset = offset; } -static int same_field(const void *_a, size_t s, const void *_b, size_t t) { +static int match_is_valid(const void *data, size_t size) { + const char *b, *p; + + assert(data); + + if (size < 2) + return false; + + if (startswith(data, "__")) + return false; + + b = data; + for (p = b; p < b + size; p++) { + + if (*p == '=') + return p > b; + + if (*p == '_') + continue; + + if (*p >= 'A' && *p <= 'Z') + continue; + + if (*p >= '0' && *p <= '9') + continue; + + return false; + } + + return false; +} + +static bool same_field(const void *_a, size_t s, const void *_b, size_t t) { const uint8_t *a = _a, *b = _b; size_t j; - bool a_good = false, b_good = false, different = false; for (j = 0; j < s && j < t; j++) { - if (a[j] == '=') - a_good = true; - if (b[j] == '=') - b_good = true; if (a[j] != b[j]) - different = true; + return false; + + if (a[j] == '=') + return true; + } + + return true; +} + +static Match *match_new(Match *p, MatchType t) { + Match *m; - if (a_good && b_good) - return different ? 0 : 1; + m = new0(Match, 1); + if (!m) + return NULL; + + m->type = t; + + if (p) { + m->parent = p; + LIST_PREPEND(Match, matches, p->matches, m); } - return -EINVAL; + return m; +} + +static void match_free(Match *m) { + assert(m); + + while (m->matches) + match_free(m->matches); + + if (m->parent) + LIST_REMOVE(Match, matches, m->parent->matches, m); + + free(m->data); + free(m); +} + +static void match_free_if_empty(Match *m) { + assert(m); + + if (m->matches) + return; + + match_free(m); } _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { - Match *m, *after = NULL; + Match *l2, *l3, *add_here = NULL, *m; le64_t le_hash; if (!j) return -EINVAL; + if (!data) return -EINVAL; - if (size <= 1) - return -EINVAL; - if (!memchr(data, '=', size)) - return -EINVAL; - if (*(char*) data == '=') + + if (size == 0) + size = strlen(data); + + if (!match_is_valid(data, size)) return -EINVAL; - /* FIXME: iterating with multiple matches is currently - * broken */ - if (j->matches) - return -ENOTSUP; + /* level 0: OR term + * level 1: AND terms + * level 2: OR terms + * level 3: concrete matches */ + + if (!j->level0) { + j->level0 = match_new(NULL, MATCH_OR_TERM); + if (!j->level0) + return -ENOMEM; + } + + if (!j->level1) { + j->level1 = match_new(j->level0, MATCH_AND_TERM); + if (!j->level1) + return -ENOMEM; + } + + assert(j->level0->type == MATCH_OR_TERM); + assert(j->level1->type == MATCH_AND_TERM); le_hash = htole64(hash64(data, size)); - LIST_FOREACH(matches, m, j->matches) { - int r; + LIST_FOREACH(matches, l2, j->level1->matches) { + assert(l2->type == MATCH_OR_TERM); - if (m->le_hash == le_hash && - m->size == size && - memcmp(m->data, data, size) == 0) - return 0; + LIST_FOREACH(matches, l3, l2->matches) { + assert(l3->type == MATCH_DISCRETE); - r = same_field(data, size, m->data, m->size); - if (r < 0) - return r; - else if (r > 0) - after = m; + /* Exactly the same match already? Then ignore + * this addition */ + if (l3->le_hash == le_hash && + l3->size == size && + memcmp(l3->data, data, size) == 0) + return 0; + + /* Same field? Then let's add this to this OR term */ + if (same_field(data, size, l3->data, l3->size)) { + add_here = l2; + break; + } + } + + if (add_here) + break; } - m = new0(Match, 1); + if (!add_here) { + add_here = match_new(j->level1, MATCH_OR_TERM); + if (!add_here) + goto fail; + } + + m = match_new(add_here, MATCH_DISCRETE); if (!m) - return -ENOMEM; + goto fail; + m->le_hash = le_hash; m->size = size; + m->data = memdup(data, size); + if (!m->data) + goto fail; + + detach_location(j); + + return 0; + +fail: + if (add_here) + match_free_if_empty(add_here); + + if (j->level1) + match_free_if_empty(j->level1); + + if (j->level0) + match_free_if_empty(j->level0); + + return -ENOMEM; +} + +_public_ int sd_journal_add_disjunction(sd_journal *j) { + Match *m; + + assert(j); + + if (!j->level0) + return 0; + + if (!j->level1) + return 0; - m->data = malloc(m->size); - if (!m->data) { - free(m); + if (!j->level1->matches) + return 0; + + m = match_new(j->level0, MATCH_AND_TERM); + if (!m) return -ENOMEM; + + j->level1 = m; + return 0; +} + +static char *match_make_string(Match *m) { + char *p, *r; + Match *i; + bool enclose = false; + + if (!m) + return strdup(""); + + if (m->type == MATCH_DISCRETE) + return strndup(m->data, m->size); + + p = NULL; + LIST_FOREACH(matches, i, m->matches) { + char *t, *k; + + t = match_make_string(i); + if (!t) { + free(p); + return NULL; + } + + if (p) { + k = join(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL); + free(p); + free(t); + + if (!k) + return NULL; + + p = k; + + enclose = true; + } else { + free(p); + p = t; + } } - memcpy(m->data, data, size); - m->le_hash = le_hash; + if (enclose) { + r = join("(", p, ")", NULL); + free(p); + return r; + } - /* Matches for the same fields we order adjacent to each - * other */ - LIST_INSERT_AFTER(Match, matches, j->matches, after, m); - j->n_matches ++; + return p; +} - detach_location(j); +char *journal_make_match_string(sd_journal *j) { + assert(j); - return 0; + return match_make_string(j->level0); } _public_ void sd_journal_flush_matches(sd_journal *j) { + if (!j) return; - while (j->matches) { - Match *m = j->matches; + if (j->level0) + match_free(j->level0); - LIST_REMOVE(Match, matches, j->matches, m); - free(m->data); - free(m); - } - - j->n_matches = 0; + j->level0 = j->level1 = NULL; detach_location(j); } @@ -319,290 +489,270 @@ static int compare_with_location(JournalFile *af, Object *ao, Location *l) { return 0; } -static int find_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { - Object *o = NULL; - uint64_t p = 0; +static int next_for_match( + sd_journal *j, + Match *m, + JournalFile *f, + uint64_t after_offset, + direction_t direction, + Object **ret, + uint64_t *offset) { + int r; + uint64_t np = 0; + Object *n; assert(j); + assert(m); + assert(f); - if (!j->matches) { - /* No matches is simple */ - - if (j->current_location.type == LOCATION_HEAD) - r = journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p); - else if (j->current_location.type == LOCATION_TAIL) - r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, &p); - else if (j->current_location.seqnum_set && - sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) - r = journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, &o, &p); - else if (j->current_location.monotonic_set) { - r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, &o, &p); - - if (r == -ENOENT) { - /* boot id unknown in this file */ - if (j->current_location.realtime_set) - r = journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, &o, &p); - else - r = journal_file_next_entry(f, NULL, 0, direction, &o, &p); - } - } else if (j->current_location.realtime_set) - r = journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, &o, &p); - else - r = journal_file_next_entry(f, NULL, 0, direction, &o, &p); + if (m->type == MATCH_DISCRETE) { + uint64_t dp; + r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); if (r <= 0) return r; - } else { - Match *m, *term_match = NULL; - Object *to = NULL; - uint64_t tp = 0; + return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset); - /* We have matches, first, let's jump to the monotonic - * position if we have any, since it implies a - * match. */ + } else if (m->type == MATCH_OR_TERM) { + Match *i; - if (j->current_location.type == LOCATION_DISCRETE && - j->current_location.monotonic_set) { + /* Find the earliest match beyond after_offset */ - r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, &o, &p); - if (r <= 0) - return r == -ENOENT ? 0 : r; - } - - LIST_FOREACH(matches, m, j->matches) { - Object *c, *d; - uint64_t cp, dp; - - r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), &d, &dp); - if (r <= 0) - return r; - - if (j->current_location.type == LOCATION_HEAD) - r = journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, &c, &cp); - else if (j->current_location.type == LOCATION_TAIL) - r = journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, &c, &cp); - else if (j->current_location.seqnum_set && - sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) - r = journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, &c, &cp); - else if (j->current_location.realtime_set) - r = journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, &c, &cp); - else - r = journal_file_next_entry_for_data(f, NULL, 0, dp, direction, &c, &cp); + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; + r = next_for_match(j, i, f, after_offset, direction, NULL, &cp); if (r < 0) return r; + else if (r > 0) { + if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp)) + np = cp; + } + } - if (!term_match) { - term_match = m; - - if (r > 0) { - to = c; - tp = cp; - } - } else if (same_field(term_match->data, term_match->size, m->data, m->size)) { - - /* Same field as previous match... */ - if (r > 0) { - - /* Find the earliest of the OR matches */ + } else if (m->type == MATCH_AND_TERM) { + Match *i; + bool continue_looking; - if (!to || - (direction == DIRECTION_DOWN && cp < tp) || - (direction == DIRECTION_UP && cp > tp)) { - to = c; - tp = cp; - } + /* Always jump to the next matching entry and repeat + * this until we fine and offset that matches for all + * matches. */ - } + if (!m->matches) + return 0; - } else { + np = 0; + do { + continue_looking = false; - /* Previous term is finished, did anything match? */ - if (!to) - return 0; + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp, limit; - /* Find the last of the AND matches */ - if (!o || - (direction == DIRECTION_DOWN && tp > p) || - (direction == DIRECTION_UP && tp < p)) { - o = to; - p = tp; - } + if (np == 0) + limit = after_offset; + else if (direction == DIRECTION_DOWN) + limit = MAX(np, after_offset); + else + limit = MIN(np, after_offset); - term_match = m; + r = next_for_match(j, i, f, limit, direction, NULL, &cp); + if (r <= 0) + return r; - if (r > 0) { - to = c; - tp = cp; - } else { - to = NULL; - tp = 0; + if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) && + (np == 0 || (direction == DIRECTION_DOWN ? cp > np : np < cp))) { + np = cp; + continue_looking = true; } } - } - /* Last term is finished, did anything match? */ - if (!to) - return 0; + } while (continue_looking); + } - if (!o || - (direction == DIRECTION_DOWN && tp > p) || - (direction == DIRECTION_UP && tp < p)) { - o = to; - p = tp; - } + if (np == 0) + return 0; - if (!o) - return 0; - } + r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); + if (r < 0) + return r; if (ret) - *ret = o; - + *ret = n; if (offset) - *offset = p; + *offset = np; return 1; } -static int next_with_matches(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { +static int find_location_for_match( + sd_journal *j, + Match *m, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + int r; - uint64_t cp; - Object *c; assert(j); + assert(m); assert(f); - assert(ret); - assert(offset); - c = *ret; - cp = *offset; + if (m->type == MATCH_DISCRETE) { + uint64_t dp; - if (!j->matches) { - /* No matches is easy */ - - r = journal_file_next_entry(f, c, cp, direction, &c, &cp); + r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); if (r <= 0) return r; - if (ret) - *ret = c; - if (offset) - *offset = cp; - return 1; - } + /* FIXME: missing: find by monotonic */ + + if (j->current_location.type == LOCATION_HEAD) + return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset); + if (j->current_location.type == LOCATION_TAIL) + return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset); + if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset); + if (j->current_location.monotonic_set) { + r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); + if (r != -ENOENT) + return r; + } + if (j->current_location.realtime_set) + return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset); - /* So there are matches we have to adhere to, let's find the - * first entry that matches all of them */ + return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset); - for (;;) { - uint64_t np, n; - bool found, term_result = false; - Match *m, *term_match = NULL; - Object *npo = NULL; + } else if (m->type == MATCH_OR_TERM) { + uint64_t np = 0; + Object *n; + Match *i; - n = journal_file_entry_n_items(c); + /* Find the earliest match */ - /* Make sure we don't match the entry we are starting - * from. */ - found = cp != *offset; + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; - np = 0; - LIST_FOREACH(matches, m, j->matches) { - uint64_t q, k; - Object *qo = NULL; - - /* Let's check if this is the beginning of a - * new term, i.e. has a different field prefix - * as the preceeding match. */ - if (!term_match) { - term_match = m; - term_result = false; - } else if (!same_field(term_match->data, term_match->size, m->data, m->size)) { - if (!term_result) - found = false; - - term_match = m; - term_result = false; + r = find_location_for_match(j, i, f, direction, NULL, &cp); + if (r < 0) + return r; + else if (r > 0) { + if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp)) + np = cp; } + } - for (k = 0; k < n; k++) - if (c->entry.items[k].hash == m->le_hash) - break; + if (np == 0) + return 0; - if (k >= n) { - /* Hmm, didn't find any field that - * matched this rule, so ignore this - * match. Go on with next match */ - continue; - } + r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); + if (r < 0) + return r; + + if (ret) + *ret = n; + if (offset) + *offset = np; - term_result = true; + return 1; + + } else { + Match *i; + uint64_t np = 0; - /* Hmm, so, this field matched, let's remember - * where we'd have to try next, in case the other - * matches are not OK */ + assert(m->type == MATCH_AND_TERM); - r = journal_file_next_entry_for_data(f, c, cp, le64toh(c->entry.items[k].object_offset), direction, &qo, &q); - /* This pointer is invalidated if the window was - * remapped. May need to re-fetch it later */ - c = NULL; - if (r < 0) + /* First jump to the last match, and then find the + * next one where all matches match */ + + if (!m->matches) + return 0; + + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; + + r = find_location_for_match(j, i, f, direction, NULL, &cp); + if (r <= 0) return r; - if (r > 0) { - - if (direction == DIRECTION_DOWN) { - if (q > np) { - np = q; - npo = qo; - } - } else { - if (np == 0 || q < np) { - np = q; - npo = qo; - } - } - } + if (np == 0 || (direction == DIRECTION_DOWN ? np < cp : np > cp)) + np = cp; } - /* Check the last term */ - if (term_match && !term_result) - found = false; + return next_for_match(j, m, f, np, direction, ret, offset); + } +} - /* Did this entry match against all matches? */ - if (found) { - if (ret) { - if (c == NULL) { - /* Re-fetch the entry */ - r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c); - if (r < 0) - return r; - } - *ret = c; - } - if (offset) - *offset = cp; - return 1; +static int find_location_with_matches( + sd_journal *j, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + + int r; + + assert(j); + assert(f); + assert(ret); + assert(offset); + + if (!j->level0) { + /* No matches is simple */ + + if (j->current_location.type == LOCATION_HEAD) + return journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, ret, offset); + if (j->current_location.type == LOCATION_TAIL) + return journal_file_next_entry(f, NULL, 0, DIRECTION_UP, ret, offset); + if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset); + if (j->current_location.monotonic_set) { + r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); + if (r != -ENOENT) + return r; } + if (j->current_location.realtime_set) + return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset); - /* Did we find a subsequent entry? */ - if (np == 0) - return 0; + return journal_file_next_entry(f, NULL, 0, direction, ret, offset); + } else + return find_location_for_match(j, j->level0, f, direction, ret, offset); +} - /* Hmm, ok, this entry only matched partially, so - * let's try another one */ - cp = np; - c = npo; - } +static int next_with_matches( + sd_journal *j, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + + Object *c; + uint64_t cp; + + assert(j); + assert(f); + assert(ret); + assert(offset); + + c = *ret; + cp = *offset; + + /* No matches is easy. We simple advance the file + * pointer by one. */ + if (!j->level0) + return journal_file_next_entry(f, c, cp, direction, ret, offset); + + /* If we have a match then we look for the next matching entry + * wiht an offset at least one step larger */ + return next_for_match(j, j->level0, f, direction == DIRECTION_DOWN ? cp+1 : cp-1, direction, ret, offset); } static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction, Object **ret, uint64_t *offset) { Object *c; uint64_t cp; - int compare_value, r; + int r; assert(j); assert(f); @@ -617,16 +767,18 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc r = next_with_matches(j, f, direction, &c, &cp); if (r <= 0) return r; - - compare_value = 1; } else { - r = find_location(j, f, direction, &c, &cp); + r = find_location_with_matches(j, f, direction, &c, &cp); if (r <= 0) return r; - - compare_value = 0; } + /* OK, we found the spot, now let's advance until to an entry + * that is actually different from what we were previously + * looking at. This is necessary to handle entries which exist + * in two (or more) journal files, and which shall all be + * suppressed but one. */ + for (;;) { bool found; @@ -635,9 +787,9 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc k = compare_with_location(f, c, &j->current_location); if (direction == DIRECTION_DOWN) - found = k >= compare_value; + found = k > 0; else - found = k <= -compare_value; + found = k < 0; } else found = true; diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c new file mode 100644 index 0000000000..fa228144f5 --- /dev/null +++ b/src/journal/test-journal-match.c @@ -0,0 +1,67 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include + +#include "journal-internal.h" +#include "util.h" +#include "log.h" + +int main(int argc, char *argv[]) { + sd_journal *j; + char *t; + + log_set_max_level(LOG_DEBUG); + + assert_se(sd_journal_open(&j, 0) >= 0); + + assert_se(sd_journal_add_match(j, "foobar", 0) < 0); + assert_se(sd_journal_add_match(j, "foobar=waldo", 0) < 0); + assert_se(sd_journal_add_match(j, "", 0) < 0); + assert_se(sd_journal_add_match(j, "=", 0) < 0); + assert_se(sd_journal_add_match(j, "=xxxxx", 0) < 0); + assert_se(sd_journal_add_match(j, "HALLO=WALDO", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=mmmm", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); + assert_se(sd_journal_add_match(j, "HALLO=", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=yyyyy", 0) >= 0); + assert_se(sd_journal_add_match(j, "PIFF=paff", 0) >= 0); + + assert_se(sd_journal_add_disjunction(j) >= 0); + + assert_se(sd_journal_add_match(j, "ONE=one", 0) >= 0); + assert_se(sd_journal_add_match(j, "ONE=two", 0) >= 0); + assert_se(sd_journal_add_match(j, "TWO=two", 0) >= 0); + + assert_se(t = journal_make_match_string(j)); + + assert_se(streq(t, "((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO)))")); + + printf("resulting match expression is: %s\n", t); + free(t); + + sd_journal_close(j); + + return 0; +} diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c index d682abbf01..9d376d1e56 100644 --- a/src/journal/test-journal-send.c +++ b/src/journal/test-journal-send.c @@ -21,7 +21,11 @@ #include +#include "log.h" + int main(int argc, char *argv[]) { + log_set_max_level(LOG_DEBUG); + sd_journal_print(LOG_INFO, "piepapo"); sd_journal_send("MESSAGE=foobar", diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c new file mode 100644 index 0000000000..313606f9be --- /dev/null +++ b/src/journal/test-journal-stream.c @@ -0,0 +1,169 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include + +#include "journal-file.h" +#include "journal-internal.h" +#include "util.h" +#include "log.h" + +#define N_ENTRIES 200 + +static void verify_contents(sd_journal *j, unsigned skip) { + unsigned i; + + assert(j); + + i = 0; + SD_JOURNAL_FOREACH(j) { + const void *d; + char *k; + size_t l; + unsigned u; + + assert_se(sd_journal_get_cursor(j, &k) >= 0); + printf("cursor: %s\n", k); + free(k); + + assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) d); + + assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); + assert_se(k = strndup(d, l)); + printf("\t%s\n", k); + + if (skip > 0) { + assert_se(safe_atou(k + 7, &u) >= 0); + assert_se(i == u); + i += skip; + } + + free(k); + } + + if (skip > 0) + assert_se(i == N_ENTRIES); +} + +int main(int argc, char *argv[]) { + JournalFile *one, *two, *three; + char t[] = "/tmp/journal-stream-XXXXXX"; + unsigned i; + sd_journal *j; + char *z; + + log_set_max_level(LOG_DEBUG); + + assert_se(mkdtemp(t)); + assert_se(chdir(t) >= 0); + + assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, NULL, &one) == 0); + assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, NULL, &two) == 0); + assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, NULL, &three) == 0); + + for (i = 0; i < N_ENTRIES; i++) { + char *p, *q; + dual_timestamp ts; + struct iovec iovec[2]; + + dual_timestamp_get(&ts); + + assert_se(asprintf(&p, "NUMBER=%u", i) >= 0); + iovec[0].iov_base = p; + iovec[0].iov_len = strlen(p); + + assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0); + + iovec[1].iov_base = q; + iovec[1].iov_len = strlen(q); + + if (i % 10 == 0) + assert_se(journal_file_append_entry(three, &ts, iovec, 2, NULL, NULL, NULL) == 0); + else { + if (i % 3 == 0) + assert_se(journal_file_append_entry(two, &ts, iovec, 2, NULL, NULL, NULL) == 0); + + assert_se(journal_file_append_entry(one, &ts, iovec, 2, NULL, NULL, NULL) == 0); + } + + free(p); + free(q); + } + + journal_file_close(one); + journal_file_close(two); + journal_file_close(three); + + assert_se(sd_journal_open_directory(&j, t, 0) >= 0); + + assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); + SD_JOURNAL_FOREACH_BACKWARDS(j) { + const void *d; + size_t l; + + assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) d); + } + + SD_JOURNAL_FOREACH(j) { + const void *d; + size_t l; + + assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) d); + } + + sd_journal_flush_matches(j); + + verify_contents(j, 1); + + printf("NEXT TEST\n"); + assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); + + assert_se(z = journal_make_match_string(j)); + printf("resulting match expression is: %s\n", z); + free(z); + + verify_contents(j, 5); + + printf("NEXT TEST\n"); + sd_journal_flush_matches(j); + assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0); + + assert_se(z = journal_make_match_string(j)); + printf("resulting match expression is: %s\n", z); + free(z); + + verify_contents(j, 0); + + sd_journal_close(j); + + assert_se(rm_rf(t, false, true, false) >= 0); + + return 0; +} diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index ab968b9496..74e57f48e0 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -88,6 +88,7 @@ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); void sd_journal_restart_data(sd_journal *j); int sd_journal_add_match(sd_journal *j, const void *data, size_t size); +int sd_journal_add_disjunction(sd_journal *j); void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j); -- cgit v1.2.3-54-g00ecf From dca6219e04505e9fa10b32e71059ce2abfae1dad Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Jul 2012 22:24:02 +0200 Subject: journal: automatically rotate journal files if the data hash table is full > 75% Previously, when the main data hash table grows too full the performance simply started to decrease drastically. Instead, now simply rotate to a new journal file as the hash table gets to full, so that we can start with a new fresh empty hash table. --- man/journalctl.xml | 9 +++ src/journal/journal-def.h | 7 ++- src/journal/journal-file.c | 121 +++++++++++++++++++++++++++++++++-------- src/journal/journal-file.h | 3 + src/journal/journal-internal.h | 1 + src/journal/journalctl.c | 17 +++++- src/journal/journald.c | 87 ++++++++++++++++++----------- src/journal/sd-journal.c | 16 ++++++ 8 files changed, 201 insertions(+), 60 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index 05c8703d28..f9abbfb230 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -258,6 +258,15 @@ similar. + + + + Instead of showing + journal contents show internal header + information of the journal fiels + accessed. + + diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index b30ae79683..ac89e61d93 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -172,12 +172,15 @@ _packed_ struct Header { le64_t tail_object_offset; le64_t n_objects; le64_t n_entries; - le64_t seqnum; - le64_t first_seqnum; + le64_t tail_seqnum; + le64_t head_seqnum; le64_t entry_array_offset; le64_t head_entry_realtime; le64_t tail_entry_realtime; le64_t tail_entry_monotonic; + /* Added in 187 */ + le64_t n_data; + le64_t n_fields; }; #endif diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index a110a0090f..9128f0d642 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -58,10 +58,16 @@ * size */ #define DEFAULT_KEEP_FREE (1024ULL*1024ULL) /* 1 MB */ -static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; +/* n_data was the first entry we added after the initial file format design */ +#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data)) #define ALIGN64(x) (((x) + 7ULL) & ~7ULL) +#define JOURNAL_HEADER_CONTAINS(h, field) \ + (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) + +static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; + void journal_file_close(JournalFile *f) { int t; @@ -107,7 +113,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { if (template) { h.seqnum_id = template->header->seqnum_id; - h.seqnum = template->header->seqnum; + h.tail_seqnum = template->header->tail_seqnum; } else h.seqnum_id = h.file_id; @@ -161,7 +167,8 @@ static int journal_file_verify_header(JournalFile *f) { return -EPROTONOSUPPORT; #endif - if (f->header->header_size != htole64(ALIGN64(sizeof(*(f->header))))) + /* The first addition was n_data, so check that we are at least this large */ + if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) return -EBADMSG; if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size))) @@ -427,7 +434,7 @@ static uint64_t journal_file_seqnum(JournalFile *f, uint64_t *seqnum) { assert(f); - r = le64toh(f->header->seqnum) + 1; + r = le64toh(f->header->tail_seqnum) + 1; if (seqnum) { /* If an external seqnum counter was passed, we update @@ -440,10 +447,10 @@ static uint64_t journal_file_seqnum(JournalFile *f, uint64_t *seqnum) { *seqnum = r; } - f->header->seqnum = htole64(r); + f->header->tail_seqnum = htole64(r); - if (f->header->first_seqnum == 0) - f->header->first_seqnum = htole64(r); + if (f->header->head_seqnum == 0) + f->header->head_seqnum = htole64(r); return r; } @@ -614,6 +621,9 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui f->data_hash_table[h].tail_hash_offset = htole64(offset); + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + f->header->n_data = htole64(le64toh(f->header->n_data) + 1); + return 0; } @@ -1809,27 +1819,13 @@ int journal_file_move_to_entry_by_realtime_for_data( } void journal_file_dump(JournalFile *f) { - char a[33], b[33], c[33]; Object *o; int r; uint64_t p; assert(f); - printf("File Path: %s\n" - "File ID: %s\n" - "Machine ID: %s\n" - "Boot ID: %s\n" - "Arena size: %llu\n" - "Objects: %lu\n" - "Entries: %lu\n", - f->path, - sd_id128_to_string(f->header->file_id, a), - sd_id128_to_string(f->header->machine_id, b), - sd_id128_to_string(f->header->boot_id, c), - (unsigned long long) le64toh(f->header->arena_size), - (unsigned long) le64toh(f->header->n_objects), - (unsigned long) le64toh(f->header->n_entries)); + journal_file_print_header(f); p = le64toh(f->header->header_size); while (p != 0) { @@ -1885,6 +1881,58 @@ fail: log_error("File corrupt"); } +void journal_file_print_header(JournalFile *f) { + char a[33], b[33], c[33]; + char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX]; + + assert(f); + + printf("File Path: %s\n" + "File ID: %s\n" + "Machine ID: %s\n" + "Boot ID: %s\n" + "Sequential Number ID: %s\n" + "Header size: %llu\n" + "Arena size: %llu\n" + "Data Hash Table Size: %llu\n" + "Field Hash Table Size: %llu\n" + "Objects: %llu\n" + "Entry Objects: %llu\n" + "Rotate Suggested: %s\n" + "Head Sequential Number: %llu\n" + "Tail Sequential Number: %llu\n" + "Head Realtime Timestamp: %s\n" + "Tail Realtime Timestamp: %s\n", + f->path, + sd_id128_to_string(f->header->file_id, a), + sd_id128_to_string(f->header->machine_id, b), + sd_id128_to_string(f->header->boot_id, c), + sd_id128_to_string(f->header->seqnum_id, c), + (unsigned long long) le64toh(f->header->header_size), + (unsigned long long) le64toh(f->header->arena_size), + (unsigned long long) le64toh(f->header->data_hash_table_size) / sizeof(HashItem), + (unsigned long long) le64toh(f->header->field_hash_table_size) / sizeof(HashItem), + (unsigned long long) le64toh(f->header->n_objects), + (unsigned long long) le64toh(f->header->n_entries), + yes_no(journal_file_rotate_suggested(f)), + (unsigned long long) le64toh(f->header->head_seqnum), + (unsigned long long) le64toh(f->header->tail_seqnum), + format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)), + format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime))); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + printf("Data Objects: %llu\n" + "Data Hash Table Fill: %.1f%%\n", + (unsigned long long) le64toh(f->header->n_data), + 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)))); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + printf("Field Objects: %llu\n" + "Field Hash Table Fill: %.1f%%\n", + (unsigned long long) le64toh(f->header->n_fields), + 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)))); +} + int journal_file_open( const char *fname, int flags, @@ -1950,7 +1998,7 @@ int journal_file_open( } } - if (f->last_stat.st_size < (off_t) sizeof(Header)) { + if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) { r = -EIO; goto fail; } @@ -2032,7 +2080,7 @@ int journal_file_rotate(JournalFile **f) { sd_id128_to_string(old_file->header->seqnum_id, p + l - 8 + 1); snprintf(p + l - 8 + 1 + 32, 1 + 16 + 1 + 16 + 8 + 1, "-%016llx-%016llx.journal", - (unsigned long long) le64toh((*f)->header->seqnum), + (unsigned long long) le64toh((*f)->header->tail_seqnum), (unsigned long long) le64toh((*f)->header->tail_entry_realtime)); r = rename(old_file->path, p); @@ -2510,3 +2558,28 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, u return 1; } + +bool journal_file_rotate_suggested(JournalFile *f) { + assert(f); + + /* If we gained new header fields we gained new features, + * hence suggest a rotation */ + if (le64toh(f->header->header_size) < sizeof(Header)) + return true; + + /* Let's check if the hash tables grew over a certain fill + * level (75%, borrowing this value from Java's hash table + * implementation), and if so suggest a rotation. To calculate + * the fill level we need the n_data field, which only exists + * in newer versions. */ + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) + return true; + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) + return true; + + return false; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 5c42ecdf6c..62197429ae 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -120,6 +120,7 @@ int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t da int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset); void journal_file_dump(JournalFile *f); +void journal_file_print_header(JournalFile *f); int journal_file_rotate(JournalFile **f); @@ -132,4 +133,6 @@ void journal_default_metrics(JournalMetrics *m, int fd); int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); +bool journal_file_rotate_suggested(JournalFile *f); + #endif diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 64d05f0e1e..b767901432 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -108,5 +108,6 @@ struct sd_journal { }; char *journal_make_match_string(sd_journal *j); +void journal_print_header(sd_journal *j); #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 65b3bd5a86..0d37107874 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -40,6 +40,7 @@ #include "pager.h" #include "logs-show.h" #include "strv.h" +#include "journal-internal.h" static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; @@ -48,6 +49,7 @@ static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; static bool arg_new_id128 = false; +static bool arg_print_header = false; static bool arg_quiet = false; static bool arg_local = false; static bool arg_this_boot = false; @@ -70,6 +72,7 @@ static int help(void) { " -l --local Only local entries\n" " -b --this-boot Show data only from current boot\n" " -D --directory=PATH Show journal files from directory\n" + " --header Show journal header information\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); @@ -82,7 +85,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_TAIL, - ARG_NEW_ID128 + ARG_NEW_ID128, + ARG_HEADER }; static const struct option options[] = { @@ -99,6 +103,7 @@ static int parse_argv(int argc, char *argv[]) { { "local", no_argument, NULL, 'l' }, { "this-boot", no_argument, NULL, 'b' }, { "directory", required_argument, NULL, 'D' }, + { "header", no_argument, NULL, ARG_HEADER }, { NULL, 0, NULL, 0 } }; @@ -174,6 +179,10 @@ static int parse_argv(int argc, char *argv[]) { arg_directory = optarg; break; + case ARG_HEADER: + arg_print_header = true; + break; + case '?': return -EINVAL; @@ -331,6 +340,12 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_print_header) { + journal_print_header(j); + r = 0; + goto finish; + } + r = add_this_boot(j); if (r < 0) goto finish; diff --git a/src/journal/journald.c b/src/journal/journald.c index fd292f019e..e66bb07f84 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -460,6 +460,59 @@ static char *shortened_cgroup_path(pid_t pid) { return path; } +static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) { + JournalFile *f; + bool vacuumed = false; + int r; + + assert(s); + assert(iovec); + assert(n > 0); + + f = find_journal(s, uid); + if (!f) + return; + + if (journal_file_rotate_suggested(f)) { + log_info("Journal header limits reached or header out-of-date, rotating."); + server_rotate(s); + server_vacuum(s); + vacuumed = true; + } + + for (;;) { + r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); + if (r >= 0) + return; + + if (vacuumed || + (r != -E2BIG && /* hit limit */ + r != -EFBIG && /* hit fs limit */ + r != -EDQUOT && /* quota hit */ + r != -ENOSPC && /* disk full */ + r != -EBADMSG && /* corrupted */ + r != -ENODATA && /* truncated */ + r != -EHOSTDOWN && /* other machine */ + r != -EPROTONOSUPPORT /* unsupported feature */)) { + log_error("Failed to write entry, ignoring: %s", strerror(-r)); + return; + } + + if (r == -E2BIG || r == -EFBIG || r == EDQUOT || r == ENOSPC) + log_info("Allocation limit reached, rotating."); + else if (r == -EHOSTDOWN) + log_info("Journal file from other machine, rotating."); + else + log_warning("Journal file corrupted, rotating."); + + server_rotate(s); + server_vacuum(s); + vacuumed = true; + + log_info("Retrying write."); + } +} + static void dispatch_message_real( Server *s, struct iovec *iovec, unsigned n, unsigned m, @@ -480,8 +533,6 @@ static void dispatch_message_real( int r; char *t; uid_t loginuid = 0, realuid = 0; - JournalFile *f; - bool vacuumed = false; assert(s); assert(iovec); @@ -626,37 +677,7 @@ static void dispatch_message_real( assert(n <= m); -retry: - f = find_journal(s, realuid == 0 ? 0 : loginuid); - if (f) { - r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); - - if ((r == -E2BIG || /* hit limit */ - r == -EFBIG || /* hit fs limit */ - r == -EDQUOT || /* quota hit */ - r == -ENOSPC || /* disk full */ - r == -EBADMSG || /* corrupted */ - r == -ENODATA || /* truncated */ - r == -EHOSTDOWN || /* other machine */ - r == -EPROTONOSUPPORT) && /* unsupported feature */ - !vacuumed) { - - if (r == -E2BIG) - log_info("Allocation limit reached, rotating."); - else - log_warning("Journal file corrupted, rotating."); - - server_rotate(s); - server_vacuum(s); - vacuumed = true; - - log_info("Retrying write."); - goto retry; - } - - if (r < 0) - log_error("Failed to write entry, ignoring: %s", strerror(-r)); - } + write_to_journal(s, realuid == 0 ? 0 : loginuid, iovec, n); free(pid); free(uid); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 6befd8b3ce..77469e9ebd 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2009,6 +2009,22 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot return first ? 0 : 1; } +void journal_print_header(sd_journal *j) { + Iterator i; + JournalFile *f; + bool newline = false; + + assert(j); + + HASHMAP_FOREACH(f, j->files, i) { + if (newline) + putchar('\n'); + else + newline = true; + + journal_file_print_header(f); + } +} /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ /* if (!j) */ -- cgit v1.2.3-54-g00ecf From 25277cd7fbd77e4c8b20572570aa77c7da9abcc2 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 17 Jul 2012 07:35:06 +0200 Subject: logs: Adapt interface in log-show.c (output_journal) In preparation for adding more output switches, convert a series of flags arguments into one flag variable. --- src/journal/journalctl.c | 3 ++- src/shared/logs-show.c | 56 ++++++++++++++++++++++++++++++------------------ src/shared/logs-show.h | 8 ++++++- 3 files changed, 44 insertions(+), 23 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0d37107874..016750c201 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -434,7 +434,8 @@ int main(int argc, char *argv[]) { line ++; - r = output_journal(j, arg_output, line, 0, arg_show_all); + r = output_journal(j, arg_output, line, 0, + arg_show_all ? OUTPUT_SHOW_ALL : 0); if (r < 0) goto finish; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 426a9d617c..af9bcbd0f7 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -77,7 +77,8 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool show_all, bool monotonic_mode) { +static int output_short(sd_journal *j, unsigned line, unsigned n_columns, + OutputFlags flags) { int r; const void *data; size_t length; @@ -141,7 +142,7 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool s goto finish; } - if (monotonic_mode) { + if (flags & OUTPUT_MONOTONIC_MODE) { uint64_t t; sd_id128_t boot_id; @@ -193,29 +194,33 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool s n += strlen(buf); } - if (hostname && shall_print(show_all, hostname, hostname_len)) { + if (hostname && shall_print(flags & OUTPUT_SHOW_ALL, + hostname, hostname_len)) { printf(" %.*s", (int) hostname_len, hostname); n += hostname_len + 1; } - if (identifier && shall_print(show_all, identifier, identifier_len)) { + if (identifier && shall_print(flags & OUTPUT_SHOW_ALL, + identifier, identifier_len)) { printf(" %.*s", (int) identifier_len, identifier); n += identifier_len + 1; - } else if (comm && shall_print(show_all, comm, comm_len)) { + } else if (comm && shall_print(flags & OUTPUT_SHOW_ALL, + comm, comm_len)) { printf(" %.*s", (int) comm_len, comm); n += comm_len + 1; } else putchar(' '); - if (pid && shall_print(show_all, pid, pid_len)) { + if (pid && shall_print(flags & OUTPUT_SHOW_ALL, pid, pid_len)) { printf("[%.*s]", (int) pid_len, pid); n += pid_len + 2; - } else if (fake_pid && shall_print(show_all, fake_pid, fake_pid_len)) { + } else if (fake_pid && shall_print(flags & OUTPUT_SHOW_ALL, + fake_pid, fake_pid_len)) { printf("[%.*s]", (int) fake_pid_len, fake_pid); n += fake_pid_len + 2; } - if (show_all) + if (flags & OUTPUT_SHOW_ALL) printf(": %.*s\n", (int) message_len, message); else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; @@ -251,15 +256,18 @@ finish: return r; } -static int output_short_realtime(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { - return output_short(j, line, n_columns, show_all, false); +static int output_short_realtime(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { + return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE); } -static int output_short_monotonic(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { - return output_short(j, line, n_columns, show_all, true); +static int output_short_monotonic(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { + return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE); } -static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_verbose(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { const void *data; size_t length; char *cursor; @@ -288,7 +296,7 @@ static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { - if (!show_all && (length > PRINT_THRESHOLD || + if (!(flags & OUTPUT_SHOW_ALL) && (length > PRINT_THRESHOLD || !utf8_is_printable_n(data, length))) { const char *c; char bytes[FORMAT_BYTES_MAX]; @@ -310,7 +318,8 @@ static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool return 0; } -static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_export(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { sd_id128_t boot_id; char sid[33]; int r; @@ -421,7 +430,8 @@ static void json_escape(const char* p, size_t l) { } } -static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_json(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { uint64_t realtime, monotonic; char *cursor; const void *data; @@ -494,7 +504,8 @@ static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool sh return 0; } -static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) { +static int output_cat(sd_journal *j, unsigned line, + unsigned n_columns, OutputFlags flags) { const void *data; size_t l; int r; @@ -515,7 +526,8 @@ static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool sho return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsigned n_columns, bool show_all) = { +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, + unsigned n_columns, OutputFlags flags) = { [OUTPUT_SHORT] = output_short_realtime, [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, [OUTPUT_VERBOSE] = output_verbose, @@ -524,14 +536,15 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsign [OUTPUT_CAT] = output_cat }; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all) { +int output_journal(sd_journal *j, OutputMode mode, unsigned line, + unsigned n_columns, OutputFlags flags) { assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); if (n_columns <= 0) n_columns = columns(); - return output_funcs[mode](j, line, n_columns, show_all); + return output_funcs[mode](j, line, n_columns, flags); } int show_journal_by_unit( @@ -620,7 +633,8 @@ int show_journal_by_unit( line ++; - r = output_journal(j, mode, line, n_columns, show_all); + r = output_journal(j, mode, line, n_columns, + show_all ? OUTPUT_SHOW_ALL : 0); if (r < 0) goto finish; } diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index f8a9d406bd..beade06a78 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -39,7 +39,13 @@ typedef enum OutputMode { _OUTPUT_MODE_INVALID = -1 } OutputMode; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all); +typedef enum OutputFlags { + OUTPUT_SHOW_ALL = 1 << 0, + OUTPUT_MONOTONIC_MODE = 1 << 1, +} OutputFlags; + +int output_journal(sd_journal *j, OutputMode mode, unsigned line, + unsigned n_columns, OutputFlags flags); int show_journal_by_unit( const char *unit, -- cgit v1.2.3-54-g00ecf From 92a1fd9e95954a557d6fe27b56f5ef1b89fc2f5e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 17 Jul 2012 07:35:08 +0200 Subject: journalctl: do not ellipsize when using pager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a pager is used, ellipsization is redundant — the pager does that better by hiding the part that cannot be shown. Pager's advantage is that the user can press → to view the hidden part of a message, and then ← to return. --- src/journal/journalctl.c | 9 ++++++--- src/shared/logs-show.c | 3 ++- src/shared/logs-show.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 016750c201..e9810c9a3d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -312,6 +312,7 @@ int main(int argc, char *argv[]) { bool need_seek = false; sd_id128_t previous_boot_id; bool previous_boot_id_valid = false; + bool have_pager; log_parse_environment(); log_open(); @@ -397,7 +398,8 @@ int main(int argc, char *argv[]) { goto finish; } - if (!arg_no_pager && !arg_follow) { + have_pager = !arg_no_pager && !arg_follow; + if (have_pager) { columns(); pager_open(); } @@ -410,6 +412,8 @@ int main(int argc, char *argv[]) { for (;;) { for (;;) { sd_id128_t boot_id; + int flags = (arg_show_all*OUTPUT_SHOW_ALL | + have_pager*OUTPUT_FULL_WIDTH); if (need_seek) { r = sd_journal_next(j); @@ -434,8 +438,7 @@ int main(int argc, char *argv[]) { line ++; - r = output_journal(j, arg_output, line, 0, - arg_show_all ? OUTPUT_SHOW_ALL : 0); + r = output_journal(j, arg_output, line, 0, flags); if (r < 0) goto finish; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index bbfb74c2bd..43e42f7880 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -225,7 +225,8 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else if (message_len + n < n_columns) + } else if ((flags & OUTPUT_FULL_WIDTH) || + (message_len + n < n_columns)) printf(": %.*s\n", (int) message_len, message); else if (n < n_columns) { char *e; diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 44afaf306a..2e9cf63891 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -44,6 +44,7 @@ typedef enum OutputFlags { OUTPUT_MONOTONIC_MODE = 1 << 1, OUTPUT_FOLLOW = 1 << 2, OUTPUT_WARN_CUTOFF = 1 << 3, + OUTPUT_FULL_WIDTH = 1 << 4, } OutputFlags; int output_journal(sd_journal *j, OutputMode mode, unsigned line, -- cgit v1.2.3-54-g00ecf From fafb6eccc2c9e3f8d6ce0aad9cb428f8cc402b24 Mon Sep 17 00:00:00 2001 From: Zbigniew Jedrzejewski-Szmek Date: Fri, 20 Jul 2012 09:06:26 +0200 Subject: journalctl: fix ellipsization with PAGER=cat There are other reasons for not opening the pager then the --no-pager or --follow options (described below). If the pager is not used, messages must be ellipsized. On Fri, Jul 20, 2012 at 05:42:44AM +0000, Shawn Landen wrote: > "Pager to use when --no-pager is not given; overrides $PAGER. > Setting this to an empty string or the value cat is equivalent to passing --no-pager." --- src/journal/journalctl.c | 6 +----- src/shared/pager.c | 17 ++++++++++------- src/shared/pager.h | 4 +++- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e9810c9a3d..e633dd34d7 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -398,11 +398,7 @@ int main(int argc, char *argv[]) { goto finish; } - have_pager = !arg_no_pager && !arg_follow; - if (have_pager) { - columns(); - pager_open(); - } + have_pager = !arg_no_pager && !arg_follow && pager_open(); if (arg_output == OUTPUT_JSON) { fputc('[', stdout); diff --git a/src/shared/pager.c b/src/shared/pager.c index 6a85af33c4..36b409c070 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -44,20 +44,20 @@ _noreturn_ static void pager_fallback(void) { _exit(EXIT_SUCCESS); } -void pager_open(void) { +bool pager_open(void) { int fd[2]; const char *pager; pid_t parent_pid; if (pager_pid > 0) - return; + return false; if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER"))) if (!*pager || streq(pager, "cat")) - return; + return false; if (isatty(STDOUT_FILENO) <= 0) - return; + return false; /* Determine and cache number of columns before we spawn the * pager so that we get the value from the actual tty */ @@ -65,7 +65,7 @@ void pager_open(void) { if (pipe(fd) < 0) { log_error("Failed to create pager pipe: %m"); - return; + return false; } parent_pid = getpid(); @@ -74,7 +74,7 @@ void pager_open(void) { if (pager_pid < 0) { log_error("Failed to fork pager: %m"); close_pipe(fd); - return; + return false; } /* In the child start the pager */ @@ -115,10 +115,13 @@ void pager_open(void) { } /* Return in the parent */ - if (dup2(fd[1], STDOUT_FILENO) < 0) + if (dup2(fd[1], STDOUT_FILENO) < 0) { log_error("Failed to duplicate pager pipe: %m"); + return false; + } close_pipe(fd); + return true; } void pager_close(void) { diff --git a/src/shared/pager.h b/src/shared/pager.h index dcd61957ef..0b4afc04b8 100644 --- a/src/shared/pager.h +++ b/src/shared/pager.h @@ -21,5 +21,7 @@ along with systemd; If not, see . ***/ -void pager_open(void); +#include + +bool pager_open(void); void pager_close(void); -- cgit v1.2.3-54-g00ecf From 669241a076108e0483d7d8475beaa506106d077e Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Tue, 24 Jul 2012 21:12:43 -0700 Subject: use "Out of memory." consistantly (or with "\n") glibc/glib both use "out of memory" consistantly so maybe we should consider that instead of this. Eliminates one string out of a number of binaries. Also fixes extra newline in udev/scsi_id --- src/cgtop/cgtop.c | 2 +- src/core/cgroup.c | 2 +- src/core/dbus.c | 16 ++++++------ src/core/manager.c | 6 ++--- src/cryptsetup/cryptsetup-generator.c | 6 ++--- src/cryptsetup/cryptsetup.c | 6 ++--- src/fsck/fsck.c | 2 +- src/fstab-generator/fstab-generator.c | 30 +++++++++++----------- src/getty-generator/getty-generator.c | 6 ++--- src/hostname/hostnamed.c | 2 +- src/journal/coredump.c | 2 +- src/journal/journalctl.c | 2 +- src/journal/journald.c | 10 ++++---- src/locale/localed.c | 6 ++--- src/login/logind-button.c | 2 +- src/login/logind-session.c | 8 +++--- src/login/logind-user.c | 4 +-- src/login/logind.c | 4 +-- src/login/multi-seat-x.c | 2 +- src/modules-load/modules-load.c | 4 +-- src/nspawn/nspawn.c | 22 ++++++++-------- src/rc-local-generator/rc-local-generator.c | 2 +- src/readahead/readahead-collect.c | 6 ++--- src/readahead/readahead-replay.c | 2 +- src/shared/ask-password-api.c | 2 +- src/shared/dbus-common.c | 2 +- src/shared/logs-show.c | 2 +- src/shared/util.c | 6 ++--- src/shutdownd/shutdownd.c | 2 +- src/sysctl/sysctl.c | 4 +-- src/systemctl/systemctl.c | 20 +++++++-------- src/timedate/timedated.c | 10 ++++---- src/tmpfiles/tmpfiles.c | 10 ++++---- .../tty-ask-password-agent.c | 4 +-- src/udev/collect/collect.c | 2 +- src/udev/scsi_id/scsi_id.c | 4 +-- 36 files changed, 111 insertions(+), 111 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 5557094a4f..c3824c7979 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -608,7 +608,7 @@ int main(int argc, char *argv[]) { a = hashmap_new(string_hash_func, string_compare_func); b = hashmap_new(string_hash_func, string_compare_func); if (!a || !b) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index aaea96b820..1322f63eee 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -330,7 +330,7 @@ int manager_setup_cgroup(Manager *m) { /* We need a new root cgroup */ m->cgroup_hierarchy = NULL; if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/core/dbus.c b/src/core/dbus.c index 1bc83a2c2a..0c13517143 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -724,12 +724,12 @@ static int bus_setup_loop(Manager *m, DBusConnection *bus) { if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) || !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); return -ENOMEM; } if (set_put(m->bus_connections_for_dispatch, bus) < 0) { - log_error("Not enough memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -764,7 +764,7 @@ static void bus_new_connection( !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) || !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) || !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) { - log_error("Not enough memory."); + log_error("Out of memory."); return; } @@ -777,7 +777,7 @@ static int init_registered_system_bus(Manager *m) { char *id; if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -815,7 +815,7 @@ static int init_registered_api_bus(Manager *m) { !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) || !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) || !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -1090,7 +1090,7 @@ static int bus_init_private(Manager *m) { return 0; if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } @@ -1110,7 +1110,7 @@ static int bus_init_private(Manager *m) { if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) || !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) || !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } @@ -1158,7 +1158,7 @@ int bus_init(Manager *m, bool try_bus_connect) { return 0; oom: - log_error("Not enough memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/core/manager.c b/src/core/manager.c index 48305e373a..42a9490242 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1625,7 +1625,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { } if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } @@ -2074,7 +2074,7 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) p = strappend("/run/systemd/", name); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -2087,7 +2087,7 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) } else { p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index d0984242c8..fb6b4d25c0 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -303,7 +303,7 @@ static int parse_proc_cmdline(void) { t = strv_append(arg_proc_cmdline_disks, word + 10); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -317,7 +317,7 @@ static int parse_proc_cmdline(void) { t = strv_append(arg_proc_cmdline_disks, word + 13); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -380,7 +380,7 @@ int main(int argc, char *argv[]) { device = strappend("UUID=", *i); if (!name || !device) { - log_error("Out of memory"); + log_error("Out of memory."); r = EXIT_FAILURE; free(name); free(device); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index f570724b9d..9d4e77364d 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) { l = strcspn(opt_cipher, "-"); if (!(truncated_cipher = strndup(opt_cipher, l))) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } @@ -365,7 +365,7 @@ int main(int argc, char *argv[]) { char **p; if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } @@ -383,7 +383,7 @@ int main(int argc, char *argv[]) { assert(strv_length(passwords) == 1); if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 833f3f74a6..036d3c5b41 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -297,7 +297,7 @@ int main(int argc, char *argv[]) { } if (!(udev = udev_new())) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 3a59b85d66..89a4d13504 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -98,14 +98,14 @@ static int add_swap(const char *what, struct mntent *me) { name = unit_name_from_path(what, ".swap"); if (!name) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } unit = strjoin(arg_dest, "/", name, NULL); if (!unit) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -148,7 +148,7 @@ static int add_swap(const char *what, struct mntent *me) { if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -162,7 +162,7 @@ static int add_swap(const char *what, struct mntent *me) { r = device_name(what, &device); if (r < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -171,7 +171,7 @@ static int add_swap(const char *what, struct mntent *me) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -256,14 +256,14 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { name = unit_name_from_path(where, ".mount"); if (!name) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } unit = strjoin(arg_dest, "/", name, NULL); if (!unit) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -323,7 +323,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { if (!noauto) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -340,7 +340,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { r = device_name(what, &device); if (r < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -349,7 +349,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -367,14 +367,14 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { if (automount && !path_equal(where, "/")) { automount_name = unit_name_from_path(where, ".automount"); if (!name) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -410,7 +410,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -459,14 +459,14 @@ static int parse_fstab(void) { what = fstab_node_to_udev_node(me->mnt_fsname); if (!what) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } where = strdup(me->mnt_dir); if (!where) { - log_error("Out of memory"); + log_error("Out of memory."); free(what); r = -ENOMEM; goto finish; diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c index b2e3eb6393..9e46a47a9a 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -42,7 +42,7 @@ static int add_symlink(const char *fservice, const char *tservice) { to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL); if (!from || !to) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -78,7 +78,7 @@ static int add_serial_getty(const char *tty) { n = unit_name_replace_instance("serial-getty@.service", tty); if (!n) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { int k; if (asprintf(&p, "/sys/class/tty/%s", j) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = EXIT_FAILURE; goto finish; } diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 67c56f3313..7dab5f40df 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -532,7 +532,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } diff --git a/src/journal/coredump.c b/src/journal/coredump.c index fcd0d1e625..cfd3a910d9 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -239,7 +239,7 @@ int main(int argc, char* argv[]) { p = malloc(9 + COREDUMP_MAX); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e633dd34d7..a9cf9cd957 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -256,7 +256,7 @@ static int add_matches(sd_journal *j, char **args) { t = strappend("_EXE=", path); if (!t) { free(p); - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/journal/journald.c b/src/journal/journald.c index 36f9abe47e..ae1fbc4bd4 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -1270,7 +1270,7 @@ static void process_native_message( u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U); c = realloc(iovec, u * sizeof(struct iovec)); if (!c) { - log_error("Out of memory"); + log_error("Out of memory."); break; } @@ -1357,7 +1357,7 @@ static void process_native_message( k = malloc((e - p) + 1 + l); if (!k) { - log_error("Out of memory"); + log_error("Out of memory."); break; } @@ -1450,7 +1450,7 @@ static void process_native_file( p = malloc(st.st_size); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return; } @@ -1543,7 +1543,7 @@ static int stdout_stream_line(StdoutStream *s, char *p) { else { s->identifier = strdup(p); if (!s->identifier) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } @@ -1558,7 +1558,7 @@ static int stdout_stream_line(StdoutStream *s, char *p) { else { s->unit_id = strdup(p); if (!s->unit_id) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } diff --git a/src/locale/localed.c b/src/locale/localed.c index 56fb339e19..b8007d72fd 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -425,7 +425,7 @@ static void push_data(DBusConnection *bus) { l_set = new0(char*, _PROP_MAX); l_unset = new0(char*, _PROP_MAX); if (!l_set || !l_unset) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } @@ -438,7 +438,7 @@ static void push_data(DBusConnection *bus) { char *s; if (asprintf(&s, "%s=%s", names[p], data[p]) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); goto finish; } @@ -1344,7 +1344,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 8b59c2b0c3..62e0c3dbba 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -108,7 +108,7 @@ int button_open(Button *b) { p = strappend("/dev/input/", b->name); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 819596ddbe..a43ecad2b1 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -375,7 +375,7 @@ static int session_link_x11_socket(Session *s) { k = strspn(s->display+1, "0123456789"); f = new(char, sizeof("/tmp/.X11-unix/X") + k); if (!f) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -395,7 +395,7 @@ static int session_link_x11_socket(Session *s) { t = strappend(s->user->runtime_path, "/X11-display"); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); free(f); return -ENOMEM; } @@ -469,7 +469,7 @@ static int session_create_cgroup(Session *s) { if (!s->cgroup_path) { if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } else @@ -670,7 +670,7 @@ static int session_unlink_x11_socket(Session *s) { t = strappend(s->user->runtime_path, "/X11-display"); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 0a3f22ce99..fca68159a7 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -260,7 +260,7 @@ static int user_mkdir_runtime_path(User *u) { if (!u->runtime_path) { if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } else @@ -287,7 +287,7 @@ static int user_create_cgroup(User *u) { if (!u->cgroup_path) { if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } else diff --git a/src/login/logind.c b/src/login/logind.c index 0775583147..1cfb7fa9ac 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1176,7 +1176,7 @@ static int manager_connect_bus(Manager *m) { !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) || !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) || !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } @@ -1611,7 +1611,7 @@ int main(int argc, char *argv[]) { m = manager_new(); if (!m) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/login/multi-seat-x.c b/src/login/multi-seat-x.c index 92014f5316..a1fab86f6a 100644 --- a/src/login/multi-seat-x.c +++ b/src/login/multi-seat-x.c @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) { path = strappend("/run/systemd/multi-session-x/", seat); if (!path) { - log_error("Out of memory"); + log_error("Out of memory."); goto fail; } diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index d6bc16d340..e73ba7f241 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -50,14 +50,14 @@ static int add_modules(const char *p) { k = strv_split(p, ","); if (!k) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } t = strv_merge(arg_proc_cmdline_modules, k); strv_free(k); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 1d7511e2ab..355a103edf 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -289,7 +289,7 @@ static int mount_all(const char *dest) { int t; if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); if (r == 0) r = -ENOMEM; @@ -336,7 +336,7 @@ static int setup_timezone(const char *dest) { /* Fix the timezone, if possible */ if (asprintf(&where, "%s/etc/localtime", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -346,7 +346,7 @@ static int setup_timezone(const char *dest) { free(where); if (asprintf(&where, "%s/etc/timezone", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -368,7 +368,7 @@ static int setup_resolv_conf(const char *dest) { /* Fix resolv.conf, if possible */ if (asprintf(&where, "%s/etc/resolv.conf", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -480,7 +480,7 @@ static int setup_dev_console(const char *dest, const char *console) { } if (asprintf(&to, "%s/dev/console", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -535,13 +535,13 @@ static int setup_kmsg(const char *dest, int kmsg_socket) { * avoid any problems with containers deadlocking due to this * we simply make /dev/kmsg unavailable to the container. */ if (asprintf(&from, "%s/dev/kmsg", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } if (asprintf(&to, "%s/proc/kmsg", dest) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -639,7 +639,7 @@ static int setup_journal(const char *directory) { p = strappend(directory, "/etc/machine-id"); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -670,7 +670,7 @@ static int setup_journal(const char *directory) { p = strappend("/var/log/journal/", l); q = strjoin(directory, "/var/log/journal/", l, NULL); if (!p || !q) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -1296,13 +1296,13 @@ int main(int argc, char *argv[]) { if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) || (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) || (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) { - log_error("Out of memory"); + log_error("Out of memory."); goto child_fail; } if (arg_uuid) { if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); goto child_fail; } } diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c index f41a6bf265..9fafa29f22 100644 --- a/src/rc-local-generator/rc-local-generator.c +++ b/src/rc-local-generator/rc-local-generator.c @@ -48,7 +48,7 @@ static int add_symlink(const char *service, const char *where) { asprintf(&to, "%s/%s.wants/%s", arg_dest, where, service); if (!from || !to) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index 8dacf6af5c..45d489a60e 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -242,7 +242,7 @@ static int collect(const char *root) { assert(root); if (asprintf(&pack_fn, "%s/.readahead", root) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -477,7 +477,7 @@ done: log_debug("On btrfs: %s", yes_no(on_btrfs)); if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -510,7 +510,7 @@ done: n = hashmap_size(files); if (!(ordered = new(struct item, n))) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c index 7bd079aae5..f90821e831 100644 --- a/src/readahead/readahead-replay.c +++ b/src/readahead/readahead-replay.c @@ -150,7 +150,7 @@ static int replay(const char *root) { block_bump_request_nr(root); if (asprintf(&pack_fn, "%s/.readahead", root) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4333bfb564..005f40fef7 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -282,7 +282,7 @@ static int create_socket(char **name) { if (!(c = strdup(sa.un.sun_path))) { r = -ENOMEM; - log_error("Out of memory"); + log_error("Out of memory."); goto fail; } diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c index 7d57680cfc..ab1dc4d7e4 100644 --- a/src/shared/dbus-common.c +++ b/src/shared/dbus-common.c @@ -1161,7 +1161,7 @@ void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) { return; oom: - log_error("Out of memory"); + log_error("Out of memory."); if (pending) { dbus_pending_call_cancel(pending); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index a68cd3de57..f90f5a1f0d 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -53,7 +53,7 @@ static int parse_field(const void *data, size_t length, const char *field, char memcpy(buf, (const char*) data + fl, nl); ((char*)buf)[nl] = 0; if (!buf) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/shared/util.c b/src/shared/util.c index 43ec62eac6..2e7ae63db2 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -909,7 +909,7 @@ int load_env_file( continue; if (!(u = normalize_env_assignment(p))) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -918,7 +918,7 @@ int load_env_file( free(u); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -4278,7 +4278,7 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) { continue; if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); continue; } diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c index 6eb8ed9bf8..9dd1336133 100644 --- a/src/shutdownd/shutdownd.c +++ b/src/shutdownd/shutdownd.c @@ -213,7 +213,7 @@ static int update_schedule_file(struct sd_shutdown_command *c) { t = cescape(c->wall_message); if (!t) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 72a74f9e44..b463c7fac7 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -46,7 +46,7 @@ static int apply_sysctl(const char *property, const char *value) { p = new(char, sizeof(PROC_SYS_PREFIX) + strlen(property)); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -192,7 +192,7 @@ static int parse_argv(int argc, char *argv[]) { l = strv_append(arg_prefixes, optarg); if (!l) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index a13fc1a8f0..d493733761 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -658,7 +658,7 @@ static int list_unit_files(DBusConnection *bus, char **args) { h = hashmap_new(string_hash_func, string_compare_func); if (!h) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -673,7 +673,7 @@ static int list_unit_files(DBusConnection *bus, char **args) { units = new(UnitFileList, n_units); if (!units) { unit_file_list_free(h); - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -2637,7 +2637,7 @@ static void show_unit_help(UnitStatusInfo *i) { section = strndup(e + 1, *p + k - e - 2); if (!section) { free(page); - log_error("Out of memory"); + log_error("Out of memory."); return; } @@ -3283,7 +3283,7 @@ static int show(DBusConnection *bus, char **args) { p = unit_dbus_path_from_name(n ? n : *name); free(n); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -3299,7 +3299,7 @@ static int show(DBusConnection *bus, char **args) { char *p; if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -3974,7 +3974,7 @@ static int enable_sysv_units(char **args) { asprintf(&p, "%s/%s", *k, name); if (!p) { - log_error("No memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -3995,7 +3995,7 @@ static int enable_sysv_units(char **args) { else asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name); if (!p) { - log_error("No memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -4024,7 +4024,7 @@ static int enable_sysv_units(char **args) { l = strv_join((char**)argv, " "); if (!l) { - log_error("No memory."); + log_error("Out of memory."); free(q); free(p); r = -ENOMEM; @@ -4184,7 +4184,7 @@ static int enable_unit(DBusConnection *bus, char **args) { "org.freedesktop.systemd1.Manager", method); if (!m) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -4339,7 +4339,7 @@ static int unit_is_enabled(DBusConnection *bus, char **args) { "org.freedesktop.systemd1.Manager", "GetUnitFileState"); if (!m) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 237eb24894..3fef9e8844 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -153,7 +153,7 @@ static void verify_timezone(void) { p = strappend("/usr/share/zoneinfo/", tz.zone); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return; } @@ -220,7 +220,7 @@ static int write_data_timezone(void) { p = strappend("/usr/share/zoneinfo/", tz.zone); if (!p) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -341,7 +341,7 @@ static char** get_ntp_services(void) { q = strv_append(r, l); if (!q) { - log_error("Out of memory"); + log_error("Out of memory."); break; } @@ -379,7 +379,7 @@ static int read_ntp(DBusConnection *bus) { "org.freedesktop.systemd1.Manager", "GetUnitFileState"); if (!m) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -943,7 +943,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Not enough memory"); + log_error("Out of memory."); r = -ENOMEM; goto fail; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 45125b7b94..f8d89218c9 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -260,7 +260,7 @@ static int dir_cleanup( sub_path = NULL; if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -970,7 +970,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { i = new0(Item, 1); if (!i) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } @@ -999,7 +999,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) { i->argument = unquote(buffer+n, "\""); if (!i->argument) { - log_error("Out of memory"); + log_error("Out of memory."); return -ENOMEM; } } @@ -1302,7 +1302,7 @@ static char *resolve_fragment(const char *fragment, const char **search_paths) { STRV_FOREACH(p, search_paths) { resolved_path = strjoin(*p, "/", fragment, NULL); if (resolved_path == NULL) { - log_error("Out of memory"); + log_error("Out of memory."); return NULL; } @@ -1337,7 +1337,7 @@ int main(int argc, char *argv[]) { globs = hashmap_new(string_hash_func, string_compare_func); if (!items || !globs) { - log_error("Out of memory"); + log_error("Out of memory."); r = EXIT_FAILURE; goto finish; } diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 2ab3401e6f..403e8cd3c6 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -315,7 +315,7 @@ static int parse_password(const char *filename, char **wall) { *wall ? "\r\n\r\n" : "", message, pid) < 0) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } @@ -533,7 +533,7 @@ static int show_passwords(void) { continue; if (!(p = strappend("/run/systemd/ask-password/", de->d_name))) { - log_error("Out of memory"); + log_error("Out of memory."); r = -ENOMEM; goto finish; } diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c index 80f464aff0..4162c436b0 100644 --- a/src/udev/collect/collect.c +++ b/src/udev/collect/collect.c @@ -141,7 +141,7 @@ static int checkout(int fd) len = bufsize >> 1; buf = calloc(1,bufsize + 1); if (!buf) { - fprintf(stderr, "Out of memory\n"); + fprintf(stderr, "Out of memory.\n"); return -1; } memset(buf, ' ', bufsize); diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c index 6fc41e94fb..0bb1bc495a 100644 --- a/src/udev/scsi_id/scsi_id.c +++ b/src/udev/scsi_id/scsi_id.c @@ -198,7 +198,7 @@ static int get_file_options(struct udev *udev, buffer = malloc(MAX_BUFFER_LEN); if (!buffer) { fclose(fd); - log_error("can't allocate memory\n"); + log_error("Out of memory."); return -1; } @@ -294,7 +294,7 @@ static int get_file_options(struct udev *udev, c = argc_count(buffer) + 2; *newargv = calloc(c, sizeof(**newargv)); if (!*newargv) { - log_error("can't allocate memory\n"); + log_error("Out of memory."); retval = -1; } else { *argc = c; -- cgit v1.2.3-54-g00ecf From 0d0f0c50d3a1d90f03972a6abb82e6413daaa583 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Wed, 25 Jul 2012 14:55:59 -0700 Subject: log.h: new log_oom() -> int -ENOMEM, use it also a number of minor fixups and bug fixes: spelling, oom errors that didn't print errors, not properly forwarding error codes, few more consistency issues, et cetera --- src/cgtop/cgtop.c | 3 +- src/core/cgroup.c | 3 +- src/core/dbus.c | 41 ++++++---------- src/core/manager.c | 14 ++---- src/cryptsetup/cryptsetup-generator.c | 8 ++- src/cryptsetup/cryptsetup.c | 8 +-- src/fsck/fsck.c | 2 +- src/fstab-generator/fstab-generator.c | 57 ++++++++-------------- src/getty-generator/getty-generator.c | 11 ++--- src/hostname/hostnamed.c | 3 +- src/journal/cat.c | 6 +-- src/journal/coredump.c | 3 +- src/journal/journalctl.c | 3 +- src/journal/journald.c | 31 +++++------- src/locale/localed.c | 17 +++---- src/login/logind-button.c | 6 +-- src/login/logind-session.c | 21 +++----- src/login/logind-user.c | 12 ++--- src/login/logind.c | 18 +++---- src/login/multi-seat-x.c | 4 +- src/modules-load/modules-load.c | 12 ++--- src/nspawn/nspawn.c | 42 ++++++---------- src/rc-local-generator/rc-local-generator.c | 3 +- src/readahead/readahead-collect.c | 9 ++-- src/readahead/readahead-replay.c | 3 +- src/remount-fs/remount-fs.c | 2 +- src/shared/ask-password-api.c | 3 +- src/shared/dbus-common.c | 2 +- src/shared/log.h | 6 +++ src/shared/logs-show.c | 6 +-- src/shared/util.c | 8 ++- src/shutdownd/shutdownd.c | 6 +-- src/sysctl/sysctl.c | 12 ++--- .../system-update-generator.c | 6 +-- src/systemctl/systemctl.c | 40 ++++++--------- src/timedate/timedated.c | 19 +++----- src/tmpfiles/tmpfiles.c | 19 +++----- .../tty-ask-password-agent.c | 6 +-- src/udev/scsi_id/scsi_id.c | 12 ++--- src/vconsole/vconsole-setup.c | 6 +-- 40 files changed, 183 insertions(+), 310 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index c3824c7979..f0ca83fd45 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -608,8 +608,7 @@ int main(int argc, char *argv[]) { a = hashmap_new(string_hash_func, string_compare_func); b = hashmap_new(string_hash_func, string_compare_func); if (!a || !b) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 1322f63eee..8ddb1118ed 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -330,8 +330,7 @@ int manager_setup_cgroup(Manager *m) { /* We need a new root cgroup */ m->cgroup_hierarchy = NULL; if (asprintf(&m->cgroup_hierarchy, "%s%s", streq(current, "/") ? "" : current, suffix) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } } diff --git a/src/core/dbus.c b/src/core/dbus.c index 0c13517143..9db172b6e6 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -723,15 +723,11 @@ static int bus_setup_loop(Manager *m, DBusConnection *bus) { dbus_connection_set_exit_on_disconnect(bus, FALSE); if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) || - !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) { - log_error("Out of memory."); - return -ENOMEM; - } + !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) + return log_oom(); - if (set_put(m->bus_connections_for_dispatch, bus) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (set_put(m->bus_connections_for_dispatch, bus) < 0) + return log_oom(); dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL); return 0; @@ -764,7 +760,7 @@ static void bus_new_connection( !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) || !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) || !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) { - log_error("Out of memory."); + log_oom(); return; } @@ -776,10 +772,8 @@ static void bus_new_connection( static int init_registered_system_bus(Manager *m) { char *id; - if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL)) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL)) + return log_oom(); if (m->running_as != MANAGER_SYSTEM) { DBusError error; @@ -814,10 +808,8 @@ static int init_registered_api_bus(Manager *m) { if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) || !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) || !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) || - !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL)) { - log_error("Out of memory."); - return -ENOMEM; - } + !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL)) + return log_oom(); /* Get NameOwnerChange messages */ dbus_bus_add_match(m->api_bus, @@ -1090,8 +1082,7 @@ static int bus_init_private(Manager *m) { return 0; if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } @@ -1110,8 +1101,7 @@ static int bus_init_private(Manager *m) { if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) || !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) || !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } @@ -1158,8 +1148,7 @@ int bus_init(Manager *m, bool try_bus_connect) { return 0; oom: - log_error("Out of memory."); - return -ENOMEM; + return log_oom(); } static void shutdown_connection(Manager *m, DBusConnection *c) { @@ -1458,7 +1447,7 @@ void bus_broadcast_finished( message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished"); if (!message) { - log_error("Out of memory."); + log_oom(); return; } @@ -1469,13 +1458,13 @@ void bus_broadcast_finished( DBUS_TYPE_UINT64, &userspace_usec, DBUS_TYPE_UINT64, &total_usec, DBUS_TYPE_INVALID)) { - log_error("Out of memory."); + log_oom(); goto finish; } if (bus_broadcast(m, message) < 0) { - log_error("Out of memory."); + log_oom(); goto finish; } diff --git a/src/core/manager.c b/src/core/manager.c index 42a9490242..bcaf913b5a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1625,7 +1625,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { } if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -2073,10 +2073,8 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) if (m->running_as == MANAGER_SYSTEM && getpid() == 1) { p = strappend("/run/systemd/", name); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); r = mkdir_p_label(p, 0755); if (r < 0) { @@ -2086,10 +2084,8 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) } } else { p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); if (!mkdtemp(p)) { free(p); diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index fb6b4d25c0..c6bc65aecf 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -303,8 +303,7 @@ static int parse_proc_cmdline(void) { t = strv_append(arg_proc_cmdline_disks, word + 10); if (!t) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } strv_free(arg_proc_cmdline_disks); @@ -317,8 +316,7 @@ static int parse_proc_cmdline(void) { t = strv_append(arg_proc_cmdline_disks, word + 13); if (!t) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } strv_free(arg_proc_cmdline_disks); @@ -380,7 +378,7 @@ int main(int argc, char *argv[]) { device = strappend("UUID=", *i); if (!name || !device) { - log_error("Out of memory."); + log_oom(); r = EXIT_FAILURE; free(name); free(device); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 9d4e77364d..cc30e50003 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) { l = strcspn(opt_cipher, "-"); if (!(truncated_cipher = strndup(opt_cipher, l))) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -365,7 +365,7 @@ int main(int argc, char *argv[]) { char **p; if (asprintf(&text, "Please enter passphrase for disk %s!", name) < 0) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -383,7 +383,7 @@ int main(int argc, char *argv[]) { assert(strv_length(passwords) == 1); if (asprintf(&text, "Please enter passphrase for disk %s! (verification)", name) < 0) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -416,7 +416,7 @@ int main(int argc, char *argv[]) { /* Pad password if necessary */ if (!(c = new(char, opt_key_size))) { - log_error("Out of memory."); + log_oom(); goto finish; } diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 036d3c5b41..058f34d64f 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -297,7 +297,7 @@ int main(int argc, char *argv[]) { } if (!(udev = udev_new())) { - log_error("Out of memory."); + log_oom(); goto finish; } diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 89a4d13504..251a346c4d 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -47,7 +47,7 @@ static int device_name(const char *path, char **unit) { p = unit_name_from_path(path, ".device"); if (!p) - return -ENOMEM; + return log_oom(); *unit = p; return 1; @@ -98,15 +98,13 @@ static int add_swap(const char *what, struct mntent *me) { name = unit_name_from_path(what, ".swap"); if (!name) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } unit = strjoin(arg_dest, "/", name, NULL); if (!unit) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -148,8 +146,7 @@ static int add_swap(const char *what, struct mntent *me) { if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -161,18 +158,14 @@ static int add_swap(const char *what, struct mntent *me) { } r = device_name(what, &device); - if (r < 0) { - log_error("Out of memory."); - r = -ENOMEM; + if (r < 0) goto finish; - } if (r > 0) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -255,16 +248,14 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { } name = unit_name_from_path(where, ".mount"); - if (!name) { - log_error("Out of memory."); - r = -ENOMEM; + if (!name) { + r = log_oom(); goto finish; } unit = strjoin(arg_dest, "/", name, NULL); if (!unit) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -323,8 +314,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { if (!noauto) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -339,24 +329,20 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { !path_equal(where, "/")) { r = device_name(what, &device); - if (r < 0) { - log_error("Out of memory."); - r = -ENOMEM; + if (r < 0) goto finish; - } if (r > 0) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { - log_error("Failed to creat symlink: %m"); + log_error("Failed to create symlink: %m"); r = -errno; goto finish; } @@ -367,15 +353,13 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { if (automount && !path_equal(where, "/")) { automount_name = unit_name_from_path(where, ".automount"); if (!name) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -410,8 +394,7 @@ static int add_mount(const char *what, const char *where, struct mntent *me) { free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -459,16 +442,14 @@ static int parse_fstab(void) { what = fstab_node_to_udev_node(me->mnt_fsname); if (!what) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } where = strdup(me->mnt_dir); if (!where) { - log_error("Out of memory."); + r = log_oom(); free(what); - r = -ENOMEM; goto finish; } @@ -513,7 +494,7 @@ static int parse_proc_cmdline(void) { word = strndup(w, l); if (!word) { - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c index 9e46a47a9a..1cef6aeae9 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -42,8 +42,7 @@ static int add_symlink(const char *fservice, const char *tservice) { to = strjoin(arg_dest,"/getty.target.wants/", tservice, NULL); if (!from || !to) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -77,10 +76,8 @@ static int add_serial_getty(const char *tty) { log_debug("Automatically adding serial getty for /dev/%s.", tty); n = unit_name_replace_instance("serial-getty@.service", tty); - if (!n) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!n) + return log_oom(); r = add_symlink("serial-getty@.service", n); free(n); @@ -160,7 +157,7 @@ int main(int argc, char *argv[]) { int k; if (asprintf(&p, "/sys/class/tty/%s", j) < 0) { - log_error("Out of memory."); + log_oom(); r = EXIT_FAILURE; goto finish; } diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 7dab5f40df..8f9d5a04f5 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -532,8 +532,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } diff --git a/src/journal/cat.c b/src/journal/cat.c index cdd46bcf5b..523a7a2eda 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -91,10 +91,8 @@ static int parse_argv(int argc, char *argv[]) { arg_identifier = NULL; else { arg_identifier = strdup(optarg); - if (!arg_identifier) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!arg_identifier) + return log_oom(); } break; diff --git a/src/journal/coredump.c b/src/journal/coredump.c index cfd3a910d9..a507fc65f8 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -239,8 +239,7 @@ int main(int argc, char* argv[]) { p = malloc(9 + COREDUMP_MAX); if (!p) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index a9cf9cd957..c924afbccc 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -256,8 +256,7 @@ static int add_matches(sd_journal *j, char **args) { t = strappend("_EXE=", path); if (!t) { free(p); - log_error("Out of memory."); - return -ENOMEM; + return log_oom(); } r = sd_journal_add_match(j, t, 0); diff --git a/src/journal/journald.c b/src/journal/journald.c index ae1fbc4bd4..5602e362df 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -393,7 +393,7 @@ static void server_vacuum(Server *s) { if (s->system_journal) { if (asprintf(&p, "/var/log/journal/%s", ids) < 0) { - log_error("Out of memory."); + log_oom(); return; } @@ -405,7 +405,7 @@ static void server_vacuum(Server *s) { if (s->runtime_journal) { if (asprintf(&p, "/run/log/journal/%s", ids) < 0) { - log_error("Out of memory."); + log_oom(); return; } @@ -1270,7 +1270,7 @@ static void process_native_message( u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U); c = realloc(iovec, u * sizeof(struct iovec)); if (!c) { - log_error("Out of memory."); + log_oom(); break; } @@ -1357,7 +1357,7 @@ static void process_native_message( k = malloc((e - p) + 1 + l); if (!k) { - log_error("Out of memory."); + log_oom(); break; } @@ -1450,7 +1450,7 @@ static void process_native_file( p = malloc(st.st_size); if (!p) { - log_error("Out of memory."); + log_oom(); return; } @@ -1542,10 +1542,8 @@ static int stdout_stream_line(StdoutStream *s, char *p) { s->identifier = NULL; else { s->identifier = strdup(p); - if (!s->identifier) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!s->identifier) + return log_oom(); } s->state = STDOUT_STREAM_UNIT_ID; @@ -1557,10 +1555,8 @@ static int stdout_stream_line(StdoutStream *s, char *p) { s->unit_id = NULL; else { s->unit_id = strdup(p); - if (!s->unit_id) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!s->unit_id) + return log_oom(); } } @@ -1761,9 +1757,8 @@ static int stdout_stream_new(Server *s) { stream = new0(StdoutStream, 1); if (!stream) { - log_error("Out of memory."); close_nointr_nofail(fd); - return -ENOMEM; + return log_oom(); } stream->fd = fd; @@ -2753,10 +2748,8 @@ static int server_init(Server *s) { server_parse_proc_cmdline(s); s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func); - if (!s->user_journals) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!s->user_journals) + return log_oom(); s->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (s->epoll_fd < 0) { diff --git a/src/locale/localed.c b/src/locale/localed.c index b8007d72fd..22950a60a9 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -425,7 +425,7 @@ static void push_data(DBusConnection *bus) { l_set = new0(char*, _PROP_MAX); l_unset = new0(char*, _PROP_MAX); if (!l_set || !l_unset) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -438,7 +438,7 @@ static void push_data(DBusConnection *bus) { char *s; if (asprintf(&s, "%s=%s", names[p], data[p]) < 0) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -456,30 +456,30 @@ static void push_data(DBusConnection *bus) { dbus_message_iter_init_append(m, &iter); if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) { - log_error("Out of memory."); + log_oom(); goto finish; } STRV_FOREACH(t, l_unset) if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) { - log_error("Out of memory."); + log_oom(); goto finish; } if (!dbus_message_iter_close_container(&iter, &sub) || !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) { - log_error("Out of memory."); + log_oom(); goto finish; } STRV_FOREACH(t, l_set) if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, t)) { - log_error("Out of memory."); + log_oom(); goto finish; } if (!dbus_message_iter_close_container(&iter, &sub)) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -1344,8 +1344,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 62e0c3dbba..d023294a59 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -107,10 +107,8 @@ int button_open(Button *b) { } p = strappend("/dev/input/", b->name); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); free(p); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index a43ecad2b1..16d4955d5d 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -374,10 +374,8 @@ static int session_link_x11_socket(Session *s) { k = strspn(s->display+1, "0123456789"); f = new(char, sizeof("/tmp/.X11-unix/X") + k); - if (!f) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!f) + return log_oom(); c = stpcpy(f, "/tmp/.X11-unix/X"); memcpy(c, s->display+1, k); @@ -395,9 +393,8 @@ static int session_link_x11_socket(Session *s) { t = strappend(s->user->runtime_path, "/X11-display"); if (!t) { - log_error("Out of memory."); free(f); - return -ENOMEM; + return log_oom(); } if (link(f, t) < 0) { @@ -468,10 +465,8 @@ static int session_create_cgroup(Session *s) { assert(s->user->cgroup_path); if (!s->cgroup_path) { - if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) + return log_oom(); } else p = s->cgroup_path; @@ -669,10 +664,8 @@ static int session_unlink_x11_socket(Session *s) { s->user->display = NULL; t = strappend(s->user->runtime_path, "/X11-display"); - if (!t) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!t) + return log_oom(); r = unlink(t); free(t); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index fca68159a7..aa9c3f1a31 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -259,10 +259,8 @@ static int user_mkdir_runtime_path(User *u) { } if (!u->runtime_path) { - if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0) + return log_oom(); } else p = u->runtime_path; @@ -286,10 +284,8 @@ static int user_create_cgroup(User *u) { assert(u); if (!u->cgroup_path) { - if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) + return log_oom(); } else p = u->cgroup_path; diff --git a/src/login/logind.c b/src/login/logind.c index 1cfb7fa9ac..bae9a95f38 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1020,10 +1020,8 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess } p = strdup(cgroup); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); for (;;) { char *e; @@ -1061,10 +1059,8 @@ int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) { } p = strdup(cgroup); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); for (;;) { char *e; @@ -1176,8 +1172,7 @@ static int manager_connect_bus(Manager *m) { !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) || !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) || !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } @@ -1611,8 +1606,7 @@ int main(int argc, char *argv[]) { m = manager_new(); if (!m) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/login/multi-seat-x.c b/src/login/multi-seat-x.c index a1fab86f6a..59f70882d4 100644 --- a/src/login/multi-seat-x.c +++ b/src/login/multi-seat-x.c @@ -97,7 +97,7 @@ int main(int argc, char *argv[]) { device_node = strdup(dn); if (!device_node) { udev_device_unref(d); - log_error("Out of memory."); + log_oom(); goto fail; } } @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) { path = strappend("/run/systemd/multi-session-x/", seat); if (!path) { - log_error("Out of memory."); + log_oom(); goto fail; } diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index e73ba7f241..6aeaf459af 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -49,17 +49,13 @@ static int add_modules(const char *p) { char **t, **k; k = strv_split(p, ","); - if (!k) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!k) + return log_oom(); t = strv_merge(arg_proc_cmdline_modules, k); strv_free(k); - if (!t) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!t) + return log_oom(); strv_free(arg_proc_cmdline_modules); arg_proc_cmdline_modules = t; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 355a103edf..b9fa02dc76 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -205,10 +205,8 @@ static int parse_argv(int argc, char *argv[]) { char *t; t = strndup(word, length); - if (!t) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!t) + return log_oom(); if (cap_from_name(t, &cap) < 0) { log_error("Failed to parse capability %s.", t); @@ -289,7 +287,7 @@ static int mount_all(const char *dest) { int t; if (asprintf(&where, "%s/%s", dest, mount_table[k].where) < 0) { - log_error("Out of memory."); + log_oom(); if (r == 0) r = -ENOMEM; @@ -335,20 +333,16 @@ static int setup_timezone(const char *dest) { assert(dest); /* Fix the timezone, if possible */ - if (asprintf(&where, "%s/etc/localtime", dest) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&where, "%s/etc/localtime", dest) < 0) + return log_oom(); if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0) mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); free(where); - if (asprintf(&where, "%s/etc/timezone", dest) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&where, "%s/etc/timezone", dest) < 0) + return log_oom(); if (mount("/etc/timezone", where, "bind", MS_BIND, NULL) >= 0) mount("/etc/timezone", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); @@ -368,8 +362,7 @@ static int setup_resolv_conf(const char *dest) { /* Fix resolv.conf, if possible */ if (asprintf(&where, "%s/etc/resolv.conf", dest) < 0) { - log_error("Out of memory."); - return -ENOMEM; + return log_oom(); } if (mount("/etc/resolv.conf", where, "bind", MS_BIND, NULL) >= 0) @@ -480,8 +473,7 @@ static int setup_dev_console(const char *dest, const char *console) { } if (asprintf(&to, "%s/dev/console", dest) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -535,14 +527,12 @@ static int setup_kmsg(const char *dest, int kmsg_socket) { * avoid any problems with containers deadlocking due to this * we simply make /dev/kmsg unavailable to the container. */ if (asprintf(&from, "%s/dev/kmsg", dest) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } if (asprintf(&to, "%s/proc/kmsg", dest) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -639,8 +629,7 @@ static int setup_journal(const char *directory) { p = strappend(directory, "/etc/machine-id"); if (!p) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -670,8 +659,7 @@ static int setup_journal(const char *directory) { p = strappend("/var/log/journal/", l); q = strjoin(directory, "/var/log/journal/", l, NULL); if (!p || !q) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -1296,13 +1284,13 @@ int main(int argc, char *argv[]) { if ((asprintf((char**)(envp + 3), "HOME=%s", home ? home: "/root") < 0) || (asprintf((char**)(envp + 4), "USER=%s", arg_user ? arg_user : "root") < 0) || (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)) { - log_error("Out of memory."); + log_oom(); goto child_fail; } if (arg_uuid) { if (asprintf((char**)(envp + 6), "container_uuid=%s", arg_uuid) < 0) { - log_error("Out of memory."); + log_oom(); goto child_fail; } } diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c index 9fafa29f22..c219e77047 100644 --- a/src/rc-local-generator/rc-local-generator.c +++ b/src/rc-local-generator/rc-local-generator.c @@ -48,8 +48,7 @@ static int add_symlink(const char *service, const char *where) { asprintf(&to, "%s/%s.wants/%s", arg_dest, where, service); if (!from || !to) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index 45d489a60e..4fcf64c24d 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -242,8 +242,7 @@ static int collect(const char *root) { assert(root); if (asprintf(&pack_fn, "%s/.readahead", root) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -477,8 +476,7 @@ done: log_debug("On btrfs: %s", yes_no(on_btrfs)); if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -510,8 +508,7 @@ done: n = hashmap_size(files); if (!(ordered = new(struct item, n))) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c index f90821e831..a1ac6b0c91 100644 --- a/src/readahead/readahead-replay.c +++ b/src/readahead/readahead-replay.c @@ -150,8 +150,7 @@ static int replay(const char *root) { block_bump_request_nr(root); if (asprintf(&pack_fn, "%s/.readahead", root) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index 8b3aaeb32c..636c46f0f3 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) { s = strdup(me->mnt_dir); if (!s) { - log_error("Out of memory."); + log_oom(); ret = EXIT_FAILURE; continue; } diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 005f40fef7..8a0fb89a84 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -281,8 +281,7 @@ static int create_socket(char **name) { } if (!(c = strdup(sa.un.sun_path))) { - r = -ENOMEM; - log_error("Out of memory."); + r = log_oom(); goto fail; } diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c index ab1dc4d7e4..5d64568c34 100644 --- a/src/shared/dbus-common.c +++ b/src/shared/dbus-common.c @@ -1161,7 +1161,7 @@ void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) { return; oom: - log_error("Out of memory."); + log_oom(); if (pending) { dbus_pending_call_cancel(pending); diff --git a/src/shared/log.h b/src/shared/log.h index c986b2579d..7bdb3e0865 100644 --- a/src/shared/log.h +++ b/src/shared/log.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "macro.h" @@ -102,6 +103,11 @@ int log_dump_internal( #define log_warning(...) log_meta(LOG_WARNING, __FILE__, __LINE__, __func__, __VA_ARGS__) #define log_error(...) log_meta(LOG_ERR, __FILE__, __LINE__, __func__, __VA_ARGS__) +static inline int log_oom(void) { + log_error("Out of memory."); + return -ENOMEM; +} + /* This modifies the buffer passed! */ #define log_dump(level, buffer) log_dump_internal(level, __FILE__, __LINE__, __func__, buffer) diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index f90f5a1f0d..edb5a9cafb 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -52,10 +52,8 @@ static int parse_field(const void *data, size_t length, const char *field, char buf = malloc(nl+1); memcpy(buf, (const char*) data + fl, nl); ((char*)buf)[nl] = 0; - if (!buf) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!buf) + return log_oom(); free(*target); *target = buf; diff --git a/src/shared/util.c b/src/shared/util.c index 2e7ae63db2..5f360085a2 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -909,8 +909,7 @@ int load_env_file( continue; if (!(u = normalize_env_assignment(p))) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -918,8 +917,7 @@ int load_env_file( free(u); if (!t) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -4278,7 +4276,7 @@ void execute_directory(const char *directory, DIR *d, char *argv[]) { continue; if (asprintf(&path, "%s/%s", directory, de->d_name) < 0) { - log_error("Out of memory."); + log_oom(); continue; } diff --git a/src/shutdownd/shutdownd.c b/src/shutdownd/shutdownd.c index 9dd1336133..d426d9833d 100644 --- a/src/shutdownd/shutdownd.c +++ b/src/shutdownd/shutdownd.c @@ -212,10 +212,8 @@ static int update_schedule_file(struct sd_shutdown_command *c) { } t = cescape(c->wall_message); - if (!t) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!t) + return log_oom(); r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path); if (r < 0) { diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index b463c7fac7..3bfc454c04 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -45,10 +45,8 @@ static int apply_sysctl(const char *property, const char *value) { log_debug("Setting '%s' to '%s'", property, value); p = new(char, sizeof(PROC_SYS_PREFIX) + strlen(property)); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); n = stpcpy(p, PROC_SYS_PREFIX); strcpy(n, property); @@ -191,10 +189,8 @@ static int parse_argv(int argc, char *argv[]) { *p = '/'; l = strv_append(arg_prefixes, optarg); - if (!l) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!l) + return log_oom(); strv_free(arg_prefixes); arg_prefixes = l; diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c index abda5a0190..6660192f5e 100644 --- a/src/system-update-generator/system-update-generator.c +++ b/src/system-update-generator/system-update-generator.c @@ -47,10 +47,8 @@ static int generate_symlink(void) { } p = strappend(arg_dest, "/default.target"); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0) { free(p); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d493733761..ef8ab2dc14 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -657,10 +657,8 @@ static int list_unit_files(DBusConnection *bus, char **args) { Iterator i; h = hashmap_new(string_hash_func, string_compare_func); - if (!h) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!h) + return log_oom(); r = unit_file_get_list(arg_scope, arg_root, h); if (r < 0) { @@ -673,8 +671,7 @@ static int list_unit_files(DBusConnection *bus, char **args) { units = new(UnitFileList, n_units); if (!units) { unit_file_list_free(h); - log_error("Out of memory."); - return -ENOMEM; + return log_oom(); } HASHMAP_FOREACH(u, h, i) { @@ -2630,14 +2627,14 @@ static void show_unit_help(UnitStatusInfo *i) { if (e) { page = strndup((*p) + 4, e - *p - 4); if (!page) { - log_error("Out of memory."); + log_oom(); return; } section = strndup(e + 1, *p + k - e - 2); if (!section) { free(page); - log_error("Out of memory."); + log_oom(); return; } @@ -3282,10 +3279,8 @@ static int show(DBusConnection *bus, char **args) { n = unit_name_mangle(*name); p = unit_dbus_path_from_name(n ? n : *name); free(n); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); r = show_one(args[0], bus, p, show_properties, &new_line); free(p); @@ -3298,10 +3293,8 @@ static int show(DBusConnection *bus, char **args) { /* Interpret as job id */ char *p; - if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0) { - log_error("Out of memory."); - return -ENOMEM; - } + if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0) + return log_oom(); r = show_one(args[0], bus, p, show_properties, &new_line); free(p); @@ -3974,8 +3967,7 @@ static int enable_sysv_units(char **args) { asprintf(&p, "%s/%s", *k, name); if (!p) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -3995,8 +3987,7 @@ static int enable_sysv_units(char **args) { else asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name); if (!p) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -4024,10 +4015,9 @@ static int enable_sysv_units(char **args) { l = strv_join((char**)argv, " "); if (!l) { - log_error("Out of memory."); free(q); free(p); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -4184,8 +4174,7 @@ static int enable_unit(DBusConnection *bus, char **args) { "org.freedesktop.systemd1.Manager", method); if (!m) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -4339,8 +4328,7 @@ static int unit_is_enabled(DBusConnection *bus, char **args) { "org.freedesktop.systemd1.Manager", "GetUnitFileState"); if (!m) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 3fef9e8844..09fd808332 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -153,7 +153,7 @@ static void verify_timezone(void) { p = strappend("/usr/share/zoneinfo/", tz.zone); if (!p) { - log_error("Out of memory."); + log_oom(); return; } @@ -219,10 +219,8 @@ static int write_data_timezone(void) { } p = strappend("/usr/share/zoneinfo/", tz.zone); - if (!p) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!p) + return log_oom(); r = symlink_or_copy_atomic(p, "/etc/localtime"); free(p); @@ -341,7 +339,7 @@ static char** get_ntp_services(void) { q = strv_append(r, l); if (!q) { - log_error("Out of memory."); + log_oom(); break; } @@ -379,16 +377,14 @@ static int read_ntp(DBusConnection *bus) { "org.freedesktop.systemd1.Manager", "GetUnitFileState"); if (!m) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } if (!dbus_message_append_args(m, DBUS_TYPE_STRING, i, DBUS_TYPE_INVALID)) { - log_error("Could not append arguments to message."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -943,8 +939,7 @@ static int connect_bus(DBusConnection **_bus) { if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) || !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto fail; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index f8d89218c9..e70332ca06 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -260,8 +260,7 @@ static int dir_cleanup( sub_path = NULL; if (asprintf(&sub_path, "%s/%s", p, dent->d_name) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -969,10 +968,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { assert(buffer); i = new0(Item, 1); - if (!i) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!i) + return log_oom(); if (sscanf(buffer, "%c " @@ -998,10 +995,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { n += strspn(buffer+n, WHITESPACE); if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) { i->argument = unquote(buffer+n, "\""); - if (!i->argument) { - log_error("Out of memory."); - return -ENOMEM; - } + if (!i->argument) + return log_oom(); } } @@ -1302,7 +1297,7 @@ static char *resolve_fragment(const char *fragment, const char **search_paths) { STRV_FOREACH(p, search_paths) { resolved_path = strjoin(*p, "/", fragment, NULL); if (resolved_path == NULL) { - log_error("Out of memory."); + log_oom(); return NULL; } @@ -1337,7 +1332,7 @@ int main(int argc, char *argv[]) { globs = hashmap_new(string_hash_func, string_compare_func); if (!items || !globs) { - log_error("Out of memory."); + log_oom(); r = EXIT_FAILURE; goto finish; } diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 403e8cd3c6..052c10e7d5 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -315,8 +315,7 @@ static int parse_password(const char *filename, char **wall) { *wall ? "\r\n\r\n" : "", message, pid) < 0) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } @@ -533,8 +532,7 @@ static int show_passwords(void) { continue; if (!(p = strappend("/run/systemd/ask-password/", de->d_name))) { - log_error("Out of memory."); - r = -ENOMEM; + r = log_oom(); goto finish; } diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c index 0bb1bc495a..b1e089cb7c 100644 --- a/src/udev/scsi_id/scsi_id.c +++ b/src/udev/scsi_id/scsi_id.c @@ -198,8 +198,7 @@ static int get_file_options(struct udev *udev, buffer = malloc(MAX_BUFFER_LEN); if (!buffer) { fclose(fd); - log_error("Out of memory."); - return -1; + return log_oom(); } *newargv = NULL; @@ -231,7 +230,7 @@ static int get_file_options(struct udev *udev, if (str1 && strcasecmp(str1, "VENDOR") == 0) { str1 = get_value(&buf); if (!str1) { - retval = -1; + retval = log_oom(); break; } vendor_in = str1; @@ -240,7 +239,7 @@ static int get_file_options(struct udev *udev, if (str1 && strcasecmp(str1, "MODEL") == 0) { str1 = get_value(&buf); if (!str1) { - retval = -1; + retval = log_oom(); break; } model_in = str1; @@ -251,7 +250,7 @@ static int get_file_options(struct udev *udev, if (str1 && strcasecmp(str1, "OPTIONS") == 0) { str1 = get_value(&buf); if (!str1) { - retval = -1; + retval = log_oom(); break; } options_in = str1; @@ -294,8 +293,7 @@ static int get_file_options(struct udev *udev, c = argc_count(buffer) + 2; *newargv = calloc(c, sizeof(**newargv)); if (!*newargv) { - log_error("Out of memory."); - retval = -1; + retval = log_oom(); } else { *argc = c; c = 0; diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 7679d446e3..62d9c8d7b5 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -274,7 +274,7 @@ int main(int argc, char **argv) { t = strdup("/etc/sysconfig/console/default.kmap"); if (!t) { - log_error("Out of memory."); + log_oom(); goto finish; } @@ -415,7 +415,7 @@ int main(int argc, char **argv) { free(vc_keytable); if (!vc_keymap) { - log_error("Out of memory."); + log_oom(); goto finish; } } @@ -425,7 +425,7 @@ int main(int argc, char **argv) { t = strdup("/etc/sysconfig/console/default.kmap"); if (!t) { - log_error("Out of memory."); + log_oom(); goto finish; } -- cgit v1.2.3-54-g00ecf From 498261871dfa2a930ec84b13a176e3bdc43aa212 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 26 Jul 2012 16:50:35 +0200 Subject: journalctl: hightlight log lines by priority warn/notice = bright white < error = red --- src/journal/journalctl.c | 22 ++++++++++++++++++++-- src/shared/logs-show.c | 33 +++++++++++++++++++++++++++------ src/shared/logs-show.h | 9 +++++---- src/systemctl/systemctl.c | 9 ++++++--- 4 files changed, 58 insertions(+), 15 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index c924afbccc..abcfabe75d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -198,6 +198,21 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +static bool on_tty(void) { + static int t = -1; + + /* Note that this is invoked relatively early, before we start + * the pager. That means the value we return reflects whether + * we originally were started on a tty, not if we currently + * are. But this is intended, since we want colour and so on + * when run in our own pager. */ + + if (_unlikely_(t < 0)) + t = isatty(STDOUT_FILENO) > 0; + + return t; +} + static int generate_new_id128(void) { sd_id128_t id; int r; @@ -397,6 +412,7 @@ int main(int argc, char *argv[]) { goto finish; } + on_tty(); have_pager = !arg_no_pager && !arg_follow && pager_open(); if (arg_output == OUTPUT_JSON) { @@ -407,8 +423,10 @@ int main(int argc, char *argv[]) { for (;;) { for (;;) { sd_id128_t boot_id; - int flags = (arg_show_all*OUTPUT_SHOW_ALL | - have_pager*OUTPUT_FULL_WIDTH); + int flags = + arg_show_all * OUTPUT_SHOW_ALL | + have_pager * OUTPUT_FULL_WIDTH | + on_tty() * OUTPUT_COLOR; if (need_seek) { r = sd_journal_next(j); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 375ca543c1..c72ebc11f5 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -82,13 +82,21 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, const void *data; size_t length; size_t n = 0; - char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL; - size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0; + char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; + size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; + int p = LOG_INFO; + const char *color_on = "", *color_off = ""; assert(j); SD_JOURNAL_FOREACH_DATA(j, data, length) { + r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); + if (r < 0) + goto finish; + else if (r > 0) + continue; + r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); if (r < 0) goto finish; @@ -141,6 +149,9 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, goto finish; } + if (priority_len == 1 && *priority >= '0' && *priority <= '7') + p = *priority - '0'; + if (flags & OUTPUT_MONOTONIC_MODE) { uint64_t t; sd_id128_t boot_id; @@ -219,23 +230,33 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, n += fake_pid_len + 2; } + if (flags & OUTPUT_COLOR) { + if (p <= LOG_ERR) { + color_on = ANSI_HIGHLIGHT_RED_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } else if (p <= LOG_NOTICE) { + color_on = ANSI_HIGHLIGHT_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } + } + if (flags & OUTPUT_SHOW_ALL) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n < n_columns)) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (n < n_columns && n_columns - n - 2 >= 3) { char *e; e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); if (!e) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else - printf(": %s\n", e); + printf(": %s%s%s\n", color_on, e, color_off); free(e); } else diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 4e6743254b..58ff9e5760 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -39,11 +39,12 @@ typedef enum OutputMode { } OutputMode; typedef enum OutputFlags { - OUTPUT_SHOW_ALL = 1 << 0, + OUTPUT_SHOW_ALL = 1 << 0, OUTPUT_MONOTONIC_MODE = 1 << 1, - OUTPUT_FOLLOW = 1 << 2, - OUTPUT_WARN_CUTOFF = 1 << 3, - OUTPUT_FULL_WIDTH = 1 << 4, + OUTPUT_FOLLOW = 1 << 2, + OUTPUT_WARN_CUTOFF = 1 << 3, + OUTPUT_FULL_WIDTH = 1 << 4, + OUTPUT_COLOR = 1 << 5 } OutputFlags; int output_journal(sd_journal *j, OutputMode mode, unsigned line, diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index ef8ab2dc14..e74f18630d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2584,9 +2584,12 @@ static void print_status_info(UnitStatusInfo *i) { } if (i->id && arg_transport != TRANSPORT_SSH) { - int flags = (arg_lines*OUTPUT_SHOW_ALL | - arg_follow*OUTPUT_FOLLOW | - !arg_quiet*OUTPUT_WARN_CUTOFF); + int flags = + arg_lines * OUTPUT_SHOW_ALL | + arg_follow * OUTPUT_FOLLOW | + !arg_quiet * OUTPUT_WARN_CUTOFF | + on_tty() * OUTPUT_COLOR; + printf("\n"); show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, -- cgit v1.2.3-54-g00ecf From 941e990db1f2682abaa2966b1c48602901d0c599 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 27 Jul 2012 10:31:33 +0200 Subject: journalctl: add --priority= switch for filtering by priority --- TODO | 2 ++ man/journalctl.xml | 32 ++++++++++++++++++ src/journal/journalctl.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 3d075f17ec..2df612689c 100644 --- a/TODO +++ b/TODO @@ -39,6 +39,8 @@ Bugfixes: Features: +* logind: different policy actions for idle, suspend, shutdown blockers: allow idle blockers by default, don't allow suspend blockers by default + * install README to /etc/rc.d/init.d (if support for that is enabled) helping people who use "ls" there to figure out which services exist. * logind: ignore inactive login screens when checking whether power key should be handled diff --git a/man/journalctl.xml b/man/journalctl.xml index 922ff4fe06..cd17ca6ae7 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -270,6 +270,38 @@ accessed. + + + + + Filter output by + message priorities or priority + ranges. Takes either a single numeric + or textual log level (i.e. between + 0/emerg and + 7/debug), or a + range of numeric/text log levels in + the form FROM..TO. The log levels are + the usual syslog log levels as + documented in + syslog3, + i.e. emerg (0), + alert (1), + crit (2), + err (3), + warning (4), + notice (5), + info (6), + debug (7). If a + single log level is specified all + messages with this log levels or a + lower (hence more important) log level + are shown. If a range is specified all + messages within the range are shown, + including both the start and the end + value of the range. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index abcfabe75d..10959423f6 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -54,6 +54,7 @@ static bool arg_quiet = false; static bool arg_local = false; static bool arg_this_boot = false; static const char *arg_directory = NULL; +static int arg_priorities = 0xFF; static int help(void) { @@ -72,6 +73,7 @@ static int help(void) { " -l --local Only local entries\n" " -b --this-boot Show data only from current boot\n" " -D --directory=PATH Show journal files from directory\n" + " -p --priority=RANGE Show only messages within the specified priority range\n" " --header Show journal header information\n" " --new-id128 Generate a new 128 Bit id\n", program_invocation_short_name); @@ -104,6 +106,7 @@ static int parse_argv(int argc, char *argv[]) { { "this-boot", no_argument, NULL, 'b' }, { "directory", required_argument, NULL, 'D' }, { "header", no_argument, NULL, ARG_HEADER }, + { "priority", no_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; @@ -112,7 +115,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:qlbD:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:qlbD:p:", options, NULL)) >= 0) { switch (c) { @@ -183,6 +186,56 @@ static int parse_argv(int argc, char *argv[]) { arg_print_header = true; break; + case 'p': { + const char *dots; + + dots = strstr(optarg, ".."); + if (dots) { + char *a; + int from, to, i; + + /* a range */ + a = strndup(optarg, dots - optarg); + if (!a) + return log_oom(); + + from = log_level_from_string(a); + to = log_level_from_string(dots + 2); + free(a); + + if (from < 0 || to < 0) { + log_error("Failed to parse log level range %s", optarg); + return -EINVAL; + } + + arg_priorities = 0; + + if (from < to) { + for (i = from; i <= to; i++) + arg_priorities |= 1 << i; + } else { + for (i = to; i <= from; i++) + arg_priorities |= 1 << i; + } + + } else { + int p, i; + + p = log_level_from_string(optarg); + if (p < 0) { + log_error("Unknown log level %s", optarg); + return -EINVAL; + } + + arg_priorities = 0; + + for (i = 0; i <= p; i++) + arg_priorities |= 1 << i; + } + + break; + } + case '?': return -EINVAL; @@ -300,6 +353,8 @@ static int add_this_boot(sd_journal *j) { sd_id128_t boot_id; int r; + assert(j); + if (!arg_this_boot) return 0; @@ -319,6 +374,31 @@ static int add_this_boot(sd_journal *j) { return 0; } +static int add_priorities(sd_journal *j) { + char match[] = "PRIORITY=0"; + int i, r; + + assert(j); + + if (arg_priorities == 0xFF) + return 0; + + for (i = LOG_EMERG; i <= LOG_DEBUG; i++) + if (arg_priorities & (1 << i)) { + match[sizeof(match)-2] = '0' + i; + + log_info("adding match %s", match); + + r = sd_journal_add_match(j, match, strlen(match)); + if (r < 0) { + log_error("Failed to add match: %s", strerror(-r)); + return r; + } + } + + return 0; +} + int main(int argc, char *argv[]) { int r; sd_journal *j = NULL; @@ -369,6 +449,10 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; + r = add_priorities(j); + if (r < 0) + goto finish; + if (!arg_quiet) { usec_t start, end; char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; -- cgit v1.2.3-54-g00ecf From b6a345143bf6ffdc87a7149015f75c03be440b10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 9 Aug 2012 17:05:29 +0200 Subject: journalctl: support device node matches as shortcut --- man/journalctl.xml | 17 +++++++++++++++++ src/journal/journalctl.c | 27 ++++++++++++++------------- 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index cd17ca6ae7..3cfda5b84b 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -86,6 +86,15 @@ command line all matches before and after are combined in a disjunction (i.e. logical OR). + As shortcuts for a few types of field/value + matches file paths may be specified. If a file path + refers to an executable file, this is equivalent to an + _EXE= match for the canonicalized + binary path. Similar, if a path refers to a device + node, this is equivalent to a + _KERNEL_DEVICE= match for the + device. + Output is interleaved from all accessible journal files, whether they are rotated or currently being written, and regardless whether they belong to the @@ -357,6 +366,14 @@ journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + _SYSTEMD_UNIT=dbus.service + Show all logs generated by the D-Bus executable: + + journalctl /usr/bin/dbus-daemon + + Show all logs of the kernel device node /dev/sda: + + journalctl /dev/sda + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 10959423f6..62bb904dbe 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -305,7 +305,7 @@ static int add_matches(sd_journal *j, char **args) { if (streq(*i, "+")) r = sd_journal_add_disjunction(j); else if (path_is_absolute(*i)) { - char *p; + char *p, *t = NULL; const char *path; struct stat st; @@ -318,24 +318,25 @@ static int add_matches(sd_journal *j, char **args) { return -errno; } - if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) { - char *t; - + if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) t = strappend("_EXE=", path); - if (!t) { - free(p); - return log_oom(); - } - - r = sd_journal_add_match(j, t, 0); - free(t); - } else { + else if (S_ISCHR(st.st_mode)) + asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev)); + else if (S_ISBLK(st.st_mode)) + asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev)); + else { free(p); - log_error("File is not a regular file or is not executable: %s", *i); + log_error("File is not a device node, regular file or is not executable: %s", *i); return -EINVAL; } free(p); + + if (!t) + return log_oom(); + + r = sd_journal_add_match(j, t, 0); + free(t); } else r = sd_journal_add_match(j, *i, 0); -- cgit v1.2.3-54-g00ecf From 7560fffcd2531786b9c1ca657667a43e90331326 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Aug 2012 20:31:10 +0200 Subject: journald: initial version of FSPRG hookup This adds forward-secure authentication of journal files. This patch includes key generation as well as tagging of journal files, Verification of journal files will be added in a later patch. --- Makefile.am | 51 ++-- TODO | 2 + configure.ac | 34 +++ src/journal/fsprg.c | 384 +++++++++++++++++++++++++++++ src/journal/fsprg.h | 64 +++++ src/journal/journal-def.h | 42 +++- src/journal/journal-file.c | 502 ++++++++++++++++++++++++++++++++++++-- src/journal/journal-file.h | 26 +- src/journal/journalctl.c | 195 ++++++++++++++- src/journal/journald.c | 29 +-- src/journal/sd-journal.c | 2 +- src/journal/test-journal-stream.c | 6 +- src/journal/test-journal.c | 6 +- 13 files changed, 1250 insertions(+), 93 deletions(-) create mode 100644 src/journal/fsprg.c create mode 100644 src/journal/fsprg.h (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 9062dd65df..837bc6c5b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2323,14 +2323,13 @@ systemd_journald_SOURCES = \ nodist_systemd_journald_SOURCES = \ src/journal/journald-gperf.c -systemd_journald_CFLAGS = - systemd_journald_LDADD = \ libsystemd-label.la \ libsystemd-shared.la \ libsystemd-audit.la \ libsystemd-daemon.la \ - libsystemd-id128-internal.la + libsystemd-id128-internal.la \ + libsystemd-journal-internal.la if ENABLE_LOGIND systemd_journald_LDADD += \ @@ -2342,18 +2341,6 @@ systemd_journald_LDADD += \ libsystemd-acl.la endif -if HAVE_XZ -systemd_journald_SOURCES += \ - src/journal/compress.c - -systemd_journald_CFLAGS += \ - $(AM_CFLAGS) \ - $(XZ_CFLAGS) - -systemd_journald_LDADD += \ - $(XZ_LIBS) -endif - systemd_cat_SOURCES = \ src/journal/cat.c @@ -2364,6 +2351,9 @@ systemd_cat_LDADD = \ journalctl_SOURCES = \ src/journal/journalctl.c +journalctl_CFLAGS = \ + $(AM_CFLAGS) + journalctl_LDADD = \ libsystemd-shared.la \ libsystemd-journal-internal.la \ @@ -2425,26 +2415,49 @@ libsystemd_journal_la_LIBADD = \ libsystemd_journal_internal_la_SOURCES = \ $(libsystemd_journal_la_SOURCES) +libsystemd_journal_internal_la_CFLAGS = \ + $(AM_CFLAGS) + +libsystemd_journal_internal_la_LIBADD = + if HAVE_XZ libsystemd_journal_la_SOURCES += \ src/journal/compress.c libsystemd_journal_la_CFLAGS += \ - $(AM_CFLAGS) \ $(XZ_CFLAGS) libsystemd_journal_la_LIBADD += \ $(XZ_LIBS) -libsystemd_journal_internal_la_CFLAGS = \ - $(AM_CFLAGS) +libsystemd_journal_internal_la_CFLAGS += \ $(XZ_CFLAGS) -libsystemd_journal_internal_la_LIBADD = \ +libsystemd_journal_internal_la_LIBADD += \ $(XZ_LIBS) endif +if HAVE_GCRYPT +libsystemd_journal_la_SOURCES += \ + src/journal/fsprg.c \ + src/journal/fsprg.h + +libsystemd_journal_la_CFLAGS += \ + $(GCRYPT_CFLAGS) \ + -Wno-pointer-arith + +libsystemd_journal_la_LIBADD += \ + $(GCRYPT_LIBS) + +libsystemd_journal_internal_la_CFLAGS += \ + $(GCRYPT_CFLAGS) \ + -Wno-pointer-arith + +libsystemd_journal_internal_la_LIBADD += \ + $(GCRYPT_LIBS) +endif + # move lib from $(libdir) to $(rootlibdir) and update devel link, if needed libsystemd-journal-install-hook: if test "$(libdir)" != "$(rootlibdir)"; then \ diff --git a/TODO b/TODO index 2467ea839b..0a36aee643 100644 --- a/TODO +++ b/TODO @@ -49,6 +49,8 @@ Bugfixes: Features: +* shutdown: don't read-only mount anything when running in container + * nspawn: --read-only is not applied recursively to submounts * MountFlags=shared acts as MountFlags=slave right now. diff --git a/configure.ac b/configure.ac index 50176e1723..c1e88daa3f 100644 --- a/configure.ac +++ b/configure.ac @@ -301,6 +301,39 @@ fi AC_SUBST(ACL_LIBS) AM_CONDITIONAL([HAVE_ACL], [test "x$have_acl" != xno]) +# ------------------------------------------------------------------------------ +AC_ARG_ENABLE([], + AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]), + [case "${enableval}" in + yes) have_gcrypt=yes ;; + no) have_gcrypt=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-gcrypt) ;; + esac], + [have_gcrypt=auto]) + +if test "x${have_gcrypt}" != xno ; then + AM_PATH_LIBGCRYPT( + [1.4.5], + [have_gcrypt=yes], + [if test "x$have_gcrypt" = xyes ; then + AC_MSG_ERROR([*** GCRYPT headers not found.]) + fi]) + + if test "x$have_gcrypt" = xyes ; then + GCRYPT_LIBS="$LIBGCRYPT_LIBS" + GCRYPT_CFLAGS="$LIBGCRYPT_CFLAGS" + AC_DEFINE(HAVE_GCRYPT, 1, [GCRYPT available]) + else + have_gcrypt=no + fi +else + GCRYPT_LIBS= + GCRYPT_CFLAGS= +fi +AC_SUBST(GCRYPT_LIBS) +AC_SUBST(GCRYPT_CFLAGS) +AM_CONDITIONAL([HAVE_GCRYPT], [test "x$have_gcrypt" != xno]) + # ------------------------------------------------------------------------------ AC_ARG_ENABLE([audit], AS_HELP_STRING([--disable-audit],[Disable optional AUDIT support]), @@ -726,6 +759,7 @@ AC_MSG_RESULT([ SELinux: ${have_selinux} XZ: ${have_xz} ACL: ${have_acl} + GCRYPT: ${have_gcrypt} binfmt: ${have_binfmt} vconsole: ${have_vconsole} readahead: ${have_readahead} diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c new file mode 100644 index 0000000000..34ce3be96b --- /dev/null +++ b/src/journal/fsprg.c @@ -0,0 +1,384 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * fsprg v0.1 - (seekable) forward-secure pseudorandom generator + * Copyright (C) 2012 B. Poettering + * Contact: fsprg@point-at-infinity.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +#include "fsprg.h" + +#define ISVALID_SECPAR(secpar) (((secpar) % 16 == 0) && ((secpar) >= 16) && ((secpar) <= 16384)) +#define VALIDATE_SECPAR(secpar) assert(ISVALID_SECPAR(secpar)); + +#define RND_HASH GCRY_MD_SHA256 +#define RND_GEN_P 0x01 +#define RND_GEN_Q 0x02 +#define RND_GEN_X 0x03 + +/******************************************************************************/ + +static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) { + unsigned len; + size_t nwritten; + + assert(gcry_mpi_cmp_ui(x, 0) >= 0); + len = (gcry_mpi_get_nbits(x) + 7) / 8; + assert(len <= buflen); + memset(buf, 0, buflen); + gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x); + assert(nwritten == len); +} + +static gcry_mpi_t mpi_import(const void *buf, size_t buflen) { + gcry_mpi_t h; + unsigned len; + + gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL); + len = (gcry_mpi_get_nbits(h) + 7) / 8; + assert(len <= buflen); + assert(gcry_mpi_cmp_ui(h, 0) >= 0); + + return h; +} + +static void uint64_export(void *buf, size_t buflen, uint64_t x) { + assert(buflen == 8); + ((uint8_t*) buf)[0] = (x >> 56) & 0xff; + ((uint8_t*) buf)[1] = (x >> 48) & 0xff; + ((uint8_t*) buf)[2] = (x >> 40) & 0xff; + ((uint8_t*) buf)[3] = (x >> 32) & 0xff; + ((uint8_t*) buf)[4] = (x >> 24) & 0xff; + ((uint8_t*) buf)[5] = (x >> 16) & 0xff; + ((uint8_t*) buf)[6] = (x >> 8) & 0xff; + ((uint8_t*) buf)[7] = (x >> 0) & 0xff; +} + +static uint64_t uint64_import(const void *buf, size_t buflen) { + assert(buflen == 8); + return + (uint64_t)(((uint8_t*) buf)[0]) << 56 | + (uint64_t)(((uint8_t*) buf)[1]) << 48 | + (uint64_t)(((uint8_t*) buf)[2]) << 40 | + (uint64_t)(((uint8_t*) buf)[3]) << 32 | + (uint64_t)(((uint8_t*) buf)[4]) << 24 | + (uint64_t)(((uint8_t*) buf)[5]) << 16 | + (uint64_t)(((uint8_t*) buf)[6]) << 8 | + (uint64_t)(((uint8_t*) buf)[7]) << 0; +} + +/* deterministically generate from seed/idx a string of buflen pseudorandom bytes */ +static void det_randomize(void *buf, size_t buflen, const void *seed, size_t seedlen, uint32_t idx) { + gcry_md_hd_t hd, hd2; + size_t olen, cpylen; + uint32_t ctr; + + olen = gcry_md_get_algo_dlen(RND_HASH); + gcry_md_open(&hd, RND_HASH, 0); + gcry_md_write(hd, seed, seedlen); + gcry_md_putc(hd, (idx >> 24) & 0xff); + gcry_md_putc(hd, (idx >> 16) & 0xff); + gcry_md_putc(hd, (idx >> 8) & 0xff); + gcry_md_putc(hd, (idx >> 0) & 0xff); + + for (ctr = 0; buflen; ctr++) { + gcry_md_copy(&hd2, hd); + gcry_md_putc(hd2, (ctr >> 24) & 0xff); + gcry_md_putc(hd2, (ctr >> 16) & 0xff); + gcry_md_putc(hd2, (ctr >> 8) & 0xff); + gcry_md_putc(hd2, (ctr >> 0) & 0xff); + gcry_md_final(hd2); + cpylen = (buflen < olen) ? buflen : olen; + memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen); + gcry_md_close(hd2); + buf += cpylen; + buflen -= cpylen; + } + gcry_md_close(hd); +} + +/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */ +static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint32_t idx) { + size_t buflen = bits / 8; + uint8_t buf[buflen]; + gcry_mpi_t p; + + assert(bits % 8 == 0); + assert(buflen > 0); + + det_randomize(buf, buflen, seed, seedlen, idx); + buf[0] |= 0xc0; /* set upper two bits, so that n=pq has maximum size */ + buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */ + + p = mpi_import(buf, buflen); + while (gcry_prime_check(p, 0)) + gcry_mpi_add_ui(p, p, 4); + + return p; +} + +/* deterministically generate from seed/idx a quadratic residue (mod n) */ +static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen, uint32_t idx, unsigned secpar) { + size_t buflen = secpar / 8; + uint8_t buf[buflen]; + gcry_mpi_t x; + + det_randomize(buf, buflen, seed, seedlen, idx); + buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */ + x = mpi_import(buf, buflen); + assert(gcry_mpi_cmp(x, n) < 0); + gcry_mpi_mulm(x, x, x, n); + return x; +} + +/* compute 2^m (mod phi(p)), for a prime p */ +static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { + gcry_mpi_t phi, r; + int n; + + phi = gcry_mpi_new(0); + gcry_mpi_sub_ui(phi, p, 1); + + /* count number of used bits in m */ + for (n = 0; ((uint64_t)1 << n) <= m; n++) + ; + + r = gcry_mpi_new(0); + gcry_mpi_set_ui(r, 1); + while (n) { /* square and multiply algorithm for fast exponentiation */ + n--; + gcry_mpi_mulm(r, r, r, phi); + if (m & ((uint64_t)1 << n)) { + gcry_mpi_add(r, r, r); + if (gcry_mpi_cmp(r, phi) >= 0) + gcry_mpi_sub(r, r, phi); + } + } + + gcry_mpi_release(phi); + return r; +} + +/* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */ +static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) { + *xp = gcry_mpi_new(0); + *xq = gcry_mpi_new(0); + gcry_mpi_mod(*xp, x, p); + gcry_mpi_mod(*xq, x, q); +} + +/* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */ +static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) { + gcry_mpi_t a, u; + + a = gcry_mpi_new(0); + u = gcry_mpi_new(0); + *x = gcry_mpi_new(0); + gcry_mpi_subm(a, xq, xp, q); + gcry_mpi_invm(u, p, q); + gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ + gcry_mpi_mul(*x, p, a); + gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ + gcry_mpi_release(a); + gcry_mpi_release(u); +} + +static void initialize_libgcrypt(void) { + const char *p; + if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) + return; + + p = gcry_check_version("1.4.5"); + assert(p); + + /* Turn off "secmem". Clients which whish to make use of this + * feature should initialize the library manually */ + gcry_control(GCRYCTL_DISABLE_SECMEM); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +} + +/******************************************************************************/ + +size_t FSPRG_mskinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + 2 * (_secpar / 2) / 8; /* to store header,p,q */ +} + +size_t FSPRG_mpkinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + _secpar / 8; /* to store header,n */ +} + +size_t FSPRG_stateinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + 2 * _secpar / 8 + 8; /* to store header,n,x,epoch */ +} + +static void store_secpar(void *buf, uint16_t secpar) { + secpar = secpar / 16 - 1; + ((uint8_t*) buf)[0] = (secpar >> 8) & 0xff; + ((uint8_t*) buf)[1] = (secpar >> 0) & 0xff; +} + +static uint16_t read_secpar(const void *buf) { + uint16_t secpar; + secpar = + (uint16_t)(((uint8_t*) buf)[0]) << 8 | + (uint16_t)(((uint8_t*) buf)[1]) << 0; + return 16 * (secpar + 1); +} + +void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { + uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN]; + gcry_mpi_t n, p, q; + uint16_t secpar; + + VALIDATE_SECPAR(_secpar); + secpar = _secpar; + + initialize_libgcrypt(); + + if (!seed) { + gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); + seed = iseed; + seedlen = FSPRG_RECOMMENDED_SEEDLEN; + } + + p = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_P); + q = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_Q); + + if (msk) { + store_secpar(msk + 0, secpar); + mpi_export(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8, p); + mpi_export(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8, q); + } + + if (mpk) { + n = gcry_mpi_new(0); + gcry_mpi_mul(n, p, q); + assert(gcry_mpi_get_nbits(n) == secpar); + + store_secpar(mpk + 0, secpar); + mpi_export(mpk + 2, secpar / 8, n); + + gcry_mpi_release(n); + } + + gcry_mpi_release(p); + gcry_mpi_release(q); +} + +void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { + gcry_mpi_t n, x; + uint16_t secpar; + + initialize_libgcrypt(); + + secpar = read_secpar(mpk + 0); + n = mpi_import(mpk + 2, secpar / 8); + x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); + + memcpy(state, mpk, 2 + secpar / 8); + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); + memset(state + 2 + 2 * secpar / 8, 0, 8); + + gcry_mpi_release(n); + gcry_mpi_release(x); +} + +void FSPRG_Evolve(void *state) { + gcry_mpi_t n, x; + uint16_t secpar; + uint64_t epoch; + + initialize_libgcrypt(); + + secpar = read_secpar(state + 0); + n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8); + x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8); + epoch = uint64_import(state + 2 + 2 * secpar / 8, 8); + + gcry_mpi_mulm(x, x, x, n); + epoch++; + + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); + uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); + + gcry_mpi_release(n); + gcry_mpi_release(x); +} + +uint64_t FSPRG_GetEpoch(const void *state) { + uint16_t secpar; + secpar = read_secpar(state + 0); + return uint64_import(state + 2 + 2 * secpar / 8, 8); +} + +void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { + gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; + uint16_t secpar; + + initialize_libgcrypt(); + + secpar = read_secpar(msk + 0); + p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); + q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); + + n = gcry_mpi_new(0); + gcry_mpi_mul(n, p, q); + + x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); + CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ + + kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ + kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ + + gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ + gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ + + CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ + + store_secpar(state + 0, secpar); + mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n); + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); + uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); + + gcry_mpi_release(p); + gcry_mpi_release(q); + gcry_mpi_release(n); + gcry_mpi_release(x); + gcry_mpi_release(xp); + gcry_mpi_release(xq); + gcry_mpi_release(kp); + gcry_mpi_release(kq); + gcry_mpi_release(xm); +} + +void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) { + uint16_t secpar; + + initialize_libgcrypt(); + + secpar = read_secpar(state + 0); + det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx); +} diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h new file mode 100644 index 0000000000..306ef18d73 --- /dev/null +++ b/src/journal/fsprg.h @@ -0,0 +1,64 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef __fsprgh__ +#define __fsprgh__ + +/* + * fsprg v0.1 - (seekable) forward-secure pseudorandom generator + * Copyright (C) 2012 B. Poettering + * Contact: fsprg@point-at-infinity.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FSPRG_RECOMMENDED_SECPAR 1536 +#define FSPRG_RECOMMENDED_SEEDLEN (96/8) + +size_t FSPRG_mskinbytes(unsigned secpar); +size_t FSPRG_mpkinbytes(unsigned secpar); +size_t FSPRG_stateinbytes(unsigned secpar); + +/* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */ +void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar); + +/* Initialize state deterministically in dependence on seed. */ +/* Note: in case one wants to run only one GenState0 per GenMK it is safe to use + the same seed for both GenMK and GenState0. +*/ +void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen); + +void FSPRG_Evolve(void *state); + +uint64_t FSPRG_GetEpoch(const void *state); + +/* Seek to any arbitrary state (by providing msk together with seed from GenState0). */ +void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen); + +void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 096dd8ed83..af22e17822 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -37,11 +37,13 @@ typedef struct FieldObject FieldObject; typedef struct EntryObject EntryObject; typedef struct HashTableObject HashTableObject; typedef struct EntryArrayObject EntryArrayObject; -typedef struct SignatureObject SignatureObject; +typedef struct TagObject TagObject; typedef struct EntryItem EntryItem; typedef struct HashItem HashItem; +typedef struct FSPRGHeader FSPRGHeader; + /* Object types */ enum { OBJECT_UNUSED, @@ -51,7 +53,7 @@ enum { OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE, OBJECT_ENTRY_ARRAY, - OBJECT_SIGNATURE, + OBJECT_TAG, _OBJECT_TYPE_MAX }; @@ -84,7 +86,6 @@ _packed_ struct FieldObject { le64_t hash; le64_t next_hash_offset; le64_t head_data_offset; - le64_t tail_data_offset; uint8_t payload[]; }; @@ -119,12 +120,11 @@ _packed_ struct EntryArrayObject { le64_t items[]; }; -#define SIGNATURE_LENGTH 160 +#define TAG_LENGTH (256/8) -_packed_ struct SignatureObject { +_packed_ struct TagObject { ObjectHeader object; - le64_t from; - uint8_t signature[SIGNATURE_LENGTH]; + uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */ }; union Object { @@ -134,7 +134,7 @@ union Object { EntryObject entry; HashTableObject hash_table; EntryArrayObject entry_array; - SignatureObject signature; + TagObject tag; }; enum { @@ -149,17 +149,19 @@ enum { }; enum { - HEADER_COMPATIBLE_SIGNED = 1 + HEADER_COMPATIBLE_AUTHENTICATED = 1 }; +#define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }) + _packed_ struct Header { uint8_t signature[8]; /* "LPKSHHRH" */ - uint32_t compatible_flags; - uint32_t incompatible_flags; + le32_t compatible_flags; + le32_t incompatible_flags; uint8_t state; uint8_t reserved[7]; sd_id128_t file_id; - sd_id128_t machine_id; /* last writer */ + sd_id128_t machine_id; sd_id128_t boot_id; /* last writer */ sd_id128_t seqnum_id; le64_t header_size; @@ -181,3 +183,19 @@ _packed_ struct Header { le64_t n_data; le64_t n_fields; }; + +#define FSPRG_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) + +_packed_ struct FSPRGHeader { + uint8_t signature[8]; /* "KSHHRHLP" */ + le32_t compatible_flags; + le32_t incompatible_flags; + sd_id128_t machine_id; + sd_id128_t boot_id; /* last writer */ + le64_t header_size; + le64_t fsprg_start_usec; + le64_t fsprg_interval_usec; + le16_t secpar; + le16_t reserved[3]; + le64_t state_size; +}; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 718dc5d6ea..0e4889378c 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -31,6 +31,7 @@ #include "journal-file.h" #include "lookup3.h" #include "compress.h" +#include "fsprg.h" #define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) #define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem)) @@ -66,13 +67,21 @@ #define JOURNAL_HEADER_CONTAINS(h, field) \ (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) -static const char signature[] = { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }; +static int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); void journal_file_close(JournalFile *f) { int t; assert(f); + /* Sync everything to disk, before we mark the file offline */ + for (t = 0; t < _WINDOW_MAX; t++) + if (f->windows[t].ptr) + munmap(f->windows[t].ptr, f->windows[t].size); + + if (f->writable && f->fd >= 0) + fdatasync(f->fd); + if (f->header) { /* Mark the file offline. Don't override the archived state if it already is set */ if (f->writable && f->header->state == STATE_ONLINE) @@ -81,10 +90,6 @@ void journal_file_close(JournalFile *f) { munmap(f->header, PAGE_ALIGN(sizeof(Header))); } - for (t = 0; t < _WINDOW_MAX; t++) - if (f->windows[t].ptr) - munmap(f->windows[t].ptr, f->windows[t].size); - if (f->fd >= 0) close_nointr_nofail(f->fd); @@ -94,6 +99,14 @@ void journal_file_close(JournalFile *f) { free(f->compress_buffer); #endif +#ifdef HAVE_GCRYPT + if (f->fsprg_header) + munmap(f->fsprg_header, PAGE_ALIGN(f->fsprg_size)); + + if (f->hmac) + gcry_md_close(f->hmac); +#endif + free(f); } @@ -105,9 +118,15 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { assert(f); zero(h); - memcpy(h.signature, signature, 8); + memcpy(h.signature, HEADER_SIGNATURE, 8); h.header_size = htole64(ALIGN64(sizeof(h))); + h.incompatible_flags = + htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0); + + h.compatible_flags = + htole32(f->authenticate ? HEADER_COMPATIBLE_AUTHENTICATED : 0); + r = sd_id128_randomize(&h.file_id); if (r < 0) return r; @@ -149,7 +168,9 @@ static int journal_file_refresh_header(JournalFile *f) { f->header->state = STATE_ONLINE; - __sync_synchronize(); + /* Sync the online state to disk */ + msync(f->header, PAGE_ALIGN(sizeof(Header)), MS_SYNC); + fdatasync(f->fd); return 0; } @@ -157,17 +178,31 @@ static int journal_file_refresh_header(JournalFile *f) { static int journal_file_verify_header(JournalFile *f) { assert(f); - if (memcmp(f->header, signature, 8)) + if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) return -EBADMSG; + /* In both read and write mode we refuse to open files with + * incompatible flags we don't know */ #ifdef HAVE_XZ - if ((le64toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) != 0) + if ((le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_COMPRESSED) != 0) return -EPROTONOSUPPORT; #else if (f->header->incompatible_flags != 0) return -EPROTONOSUPPORT; #endif + /* When open for writing we refuse to open files with + * compatible flags, too */ + if (f->writable) { +#ifdef HAVE_GCRYPT + if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_AUTHENTICATED) != 0) + return -EPROTONOSUPPORT; +#else + if (f->header->compatible_flags != 0) + return -EPROTONOSUPPORT; +#endif + } + /* The first addition was n_data, so check that we are at least this large */ if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) return -EBADMSG; @@ -200,6 +235,9 @@ static int journal_file_verify_header(JournalFile *f) { } } + f->compress = !!(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED); + f->authenticate = !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED); + return 0; } @@ -781,8 +819,6 @@ static int journal_file_append_data( o->object.size = htole64(offsetof(Object, data.payload) + rsize); o->object.flags |= OBJECT_COMPRESSED; - f->header->incompatible_flags = htole32(le32toh(f->header->incompatible_flags) | HEADER_INCOMPATIBLE_COMPRESSED); - log_debug("Compressed data object %lu -> %lu", (unsigned long) size, (unsigned long) rsize); } } @@ -1057,6 +1093,10 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st ts->monotonic < le64toh(f->header->tail_entry_monotonic)) return -EINVAL; + r = journal_file_maybe_append_tag(f, ts->realtime); + if (r < 0) + return r; + /* alloca() can't take 0, hence let's allocate at least one */ items = alloca(sizeof(EntryItem) * MAX(1, n_iovec)); @@ -1832,6 +1872,394 @@ int journal_file_move_to_entry_by_realtime_for_data( ret, offset, NULL); } +static void *fsprg_state(JournalFile *f) { + uint64_t a, b; + assert(f); + + if (!f->authenticate) + return NULL; + + a = le64toh(f->fsprg_header->header_size); + b = le64toh(f->fsprg_header->state_size); + + if (a + b > f->fsprg_size) + return NULL; + + return (uint8_t*) f->fsprg_header + a; +} + +static int journal_file_append_tag(JournalFile *f) { + Object *o; + uint64_t p; + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + if (!f->hmac_running) + return 0; + + log_debug("Writing tag for epoch %llu\n", (unsigned long long) FSPRG_GetEpoch(fsprg_state(f))); + + assert(f->hmac); + + r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p); + if (r < 0) + return r; + + /* Get the HMAC tag and store it in the object */ + memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); + f->hmac_running = false; + + return 0; +} + +static int journal_file_hmac_start(JournalFile *f) { + uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ + + assert(f); + + if (!f->authenticate) + return 0; + + if (f->hmac_running) + return 0; + + /* Prepare HMAC for next cycle */ + gcry_md_reset(f->hmac); + FSPRG_GetKey(fsprg_state(f), key, sizeof(key), 0); + gcry_md_setkey(f->hmac, key, sizeof(key)); + + f->hmac_running = true; + + return 0; +} + +static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) { + uint64_t t; + + assert(f); + assert(epoch); + assert(f->authenticate); + + if (le64toh(f->fsprg_header->fsprg_start_usec) == 0 || + le64toh(f->fsprg_header->fsprg_interval_usec) == 0) + return -ENOTSUP; + + if (realtime < le64toh(f->fsprg_header->fsprg_start_usec)) + return -ESTALE; + + t = realtime - le64toh(f->fsprg_header->fsprg_start_usec); + t = t / le64toh(f->fsprg_header->fsprg_interval_usec); + + *epoch = t; + return 0; +} + +static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(fsprg_state(f)); + if (epoch > goal) + return -ESTALE; + + return epoch != goal; +} + +static int journal_file_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(fsprg_state(f)); + if (epoch < goal) + log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal); + + for (;;) { + if (epoch > goal) + return -ESTALE; + if (epoch == goal) + return 0; + + FSPRG_Evolve(fsprg_state(f)); + epoch = FSPRG_GetEpoch(fsprg_state(f)); + } +} + +static int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_need_evolve(f, realtime); + if (r <= 0) + return 0; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + r = journal_file_evolve(f, realtime); + if (r < 0) + return r; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + return 0; +} + +static int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { + int r; + Object *o; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + r = journal_file_move_to_object(f, type, p, &o); + if (r < 0) + return r; + + gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); + + switch (o->object.type) { + + case OBJECT_DATA: + /* All but: entry_array_offset, n_entries are mutable */ + gcry_md_write(f->hmac, &o->data.hash, offsetof(DataObject, entry_array_offset) - offsetof(DataObject, hash)); + gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); + break; + + case OBJECT_ENTRY: + /* All */ + gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); + break; + + case OBJECT_FIELD_HASH_TABLE: + case OBJECT_DATA_HASH_TABLE: + case OBJECT_ENTRY_ARRAY: + /* Nothing: everything is mutable */ + break; + + case OBJECT_TAG: + /* All */ + gcry_md_write(f->hmac, o->tag.tag, le64toh(o->object.size) - offsetof(TagObject, tag)); + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int journal_file_hmac_put_header(JournalFile *f) { + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + /* All but state+reserved, boot_id, arena_size, + * tail_object_offset, n_objects, n_entries, tail_seqnum, + * head_entry_realtime, tail_entry_realtime, + * tail_entry_monotonic, n_data, n_fields, header_tag */ + + gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); + gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); + gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); + gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); + gcry_md_write(f->hmac, &f->header->head_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_seqnum)); + + return 0; +} + +static int journal_file_load_fsprg(JournalFile *f) { + int r, fd = -1; + char *p = NULL; + struct stat st; + FSPRGHeader *m = NULL; + sd_id128_t machine; + + assert(f); + + if (!f->authenticate) + return 0; + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", + SD_ID128_FORMAT_VAL(machine)) < 0) + return -ENOMEM; + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); + if (fd < 0) { + log_error("Failed to open %s: %m", p); + r = -errno; + goto finish; + } + + if (fstat(fd, &st) < 0) { + r = -errno; + goto finish; + } + + if (st.st_size < (off_t) sizeof(FSPRGHeader)) { + r = -ENODATA; + goto finish; + } + + m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0); + if (m == MAP_FAILED) { + m = NULL; + r = -errno; + goto finish; + } + + if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) { + r = -EBADMSG; + goto finish; + } + + if (m->incompatible_flags != 0) { + r = -EPROTONOSUPPORT; + goto finish; + } + + if (le64toh(m->header_size) < sizeof(FSPRGHeader)) { + r = -EBADMSG; + goto finish; + } + + if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) { + r = -EBADMSG; + goto finish; + } + + f->fsprg_size = le64toh(m->header_size) + le64toh(m->state_size); + if ((uint64_t) st.st_size < f->fsprg_size) { + r = -ENODATA; + goto finish; + } + + if (!sd_id128_equal(machine, m->machine_id)) { + r = -EHOSTDOWN; + goto finish; + } + + if (le64toh(m->fsprg_start_usec) <= 0 || + le64toh(m->fsprg_interval_usec) <= 0) { + r = -EBADMSG; + goto finish; + } + + f->fsprg_header = mmap(NULL, PAGE_ALIGN(f->fsprg_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (f->fsprg_header == MAP_FAILED) { + f->fsprg_header = NULL; + r = -errno; + goto finish; + } + + r = 0; + +finish: + if (m) + munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader))); + + if (fd >= 0) + close_nointr_nofail(fd); + + free(p); + return r; +} + +static int journal_file_setup_hmac(JournalFile *f) { + gcry_error_t e; + + if (!f->authenticate) + return 0; + + e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if (e != 0) + return -ENOTSUP; + + return 0; +} + +static int journal_file_append_first_tag(JournalFile *f) { + int r; + uint64_t p; + + if (!f->authenticate) + return 0; + + log_debug("Calculating first tag..."); + + r = journal_file_hmac_put_header(f); + if (r < 0) + return r; + + p = le64toh(f->header->field_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, p); + if (r < 0) + return r; + + p = le64toh(f->header->data_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, p); + if (r < 0) + return r; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + return 0; +} + void journal_file_dump(JournalFile *f) { Object *o; int r; @@ -1876,8 +2304,8 @@ void journal_file_dump(JournalFile *f) { printf("Type: OBJECT_ENTRY_ARRAY\n"); break; - case OBJECT_SIGNATURE: - printf("Type: OBJECT_SIGNATURE\n"); + case OBJECT_TAG: + printf("Type: OBJECT_TAG\n"); break; } @@ -1928,8 +2356,8 @@ void journal_file_print_header(JournalFile *f) { f->header->state == STATE_OFFLINE ? "offline" : f->header->state == STATE_ONLINE ? "online" : f->header->state == STATE_ARCHIVED ? "archived" : "unknown", - (f->header->compatible_flags & HEADER_COMPATIBLE_SIGNED) ? " SIGNED" : "", - (f->header->compatible_flags & ~HEADER_COMPATIBLE_SIGNED) ? " ???" : "", + (f->header->compatible_flags & HEADER_COMPATIBLE_AUTHENTICATED) ? " AUTHENTICATED" : "", + (f->header->compatible_flags & ~HEADER_COMPATIBLE_AUTHENTICATED) ? " ???" : "", (f->header->incompatible_flags & HEADER_INCOMPATIBLE_COMPRESSED) ? " COMPRESSED" : "", (f->header->incompatible_flags & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "", (unsigned long long) le64toh(f->header->header_size), @@ -1961,6 +2389,8 @@ int journal_file_open( const char *fname, int flags, mode_t mode, + bool compress, + bool authenticate, JournalMetrics *metrics, JournalFile *template, JournalFile **ret) { @@ -1983,13 +2413,13 @@ int journal_file_open( return -ENOMEM; f->fd = -1; - f->flags = flags; f->mode = mode; - f->writable = (flags & O_ACCMODE) != O_RDONLY; - f->prot = prot_from_flags(flags); - if (template) - f->compress = template->compress; + f->flags = flags; + f->prot = prot_from_flags(flags); + f->writable = (flags & O_ACCMODE) != O_RDONLY; + f->compress = compress; + f->authenticate = authenticate; f->path = strdup(fname); if (!f->path) { @@ -2011,6 +2441,12 @@ int journal_file_open( if (f->last_stat.st_size == 0 && f->writable) { newly_created = true; + /* Try to load the FSPRG state, and if we can't, then + * just don't do authentication */ + r = journal_file_load_fsprg(f); + if (r < 0) + f->authenticate = false; + r = journal_file_init_header(f, template); if (r < 0) goto fail; @@ -2037,6 +2473,10 @@ int journal_file_open( r = journal_file_verify_header(f); if (r < 0) goto fail; + + r = journal_file_load_fsprg(f); + if (r < 0) + goto fail; } if (f->writable) { @@ -2049,10 +2489,13 @@ int journal_file_open( r = journal_file_refresh_header(f); if (r < 0) goto fail; + + r = journal_file_setup_hmac(f); + if (r < 0) + goto fail; } if (newly_created) { - r = journal_file_setup_field_hash_table(f); if (r < 0) goto fail; @@ -2060,6 +2503,10 @@ int journal_file_open( r = journal_file_setup_data_hash_table(f); if (r < 0) goto fail; + + r = journal_file_append_first_tag(f); + if (r < 0) + goto fail; } r = journal_file_map_field_hash_table(f); @@ -2081,7 +2528,7 @@ fail: return r; } -int journal_file_rotate(JournalFile **f) { +int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) { char *p; size_t l; JournalFile *old_file, *new_file = NULL; @@ -2120,7 +2567,7 @@ int journal_file_rotate(JournalFile **f) { old_file->header->state = STATE_ARCHIVED; - r = journal_file_open(old_file->path, old_file->flags, old_file->mode, NULL, old_file, &new_file); + r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, authenticate, NULL, old_file, &new_file); journal_file_close(old_file); *f = new_file; @@ -2131,6 +2578,8 @@ int journal_file_open_reliably( const char *fname, int flags, mode_t mode, + bool compress, + bool authenticate, JournalMetrics *metrics, JournalFile *template, JournalFile **ret) { @@ -2139,7 +2588,7 @@ int journal_file_open_reliably( size_t l; char *p; - r = journal_file_open(fname, flags, mode, metrics, template, ret); + r = journal_file_open(fname, flags, mode, compress, authenticate, metrics, template, ret); if (r != -EBADMSG && /* corrupted */ r != -ENODATA && /* truncated */ r != -EHOSTDOWN && /* other machine */ @@ -2154,6 +2603,9 @@ int journal_file_open_reliably( if (!(flags & O_CREAT)) return r; + if (!endswith(fname, ".journal")) + return r; + /* The file is corrupted. Rotate it away and try it again (but only once) */ l = strlen(fname); @@ -2170,7 +2622,7 @@ int journal_file_open_reliably( log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname); - return journal_file_open(fname, flags, mode, metrics, template, ret); + return journal_file_open(fname, flags, mode, compress, authenticate, metrics, template, ret); } struct vacuum_info { diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index eed49e062f..25d972040c 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -23,6 +23,10 @@ #include +#ifdef HAVE_GCRYPT +#include +#endif + #include #include "sparse-endian.h" @@ -42,7 +46,7 @@ enum { WINDOW_DATA_HASH_TABLE = OBJECT_DATA_HASH_TABLE, WINDOW_FIELD_HASH_TABLE = OBJECT_FIELD_HASH_TABLE, WINDOW_ENTRY_ARRAY = OBJECT_ENTRY_ARRAY, - WINDOW_SIGNATURE = OBJECT_SIGNATURE, + WINDOW_TAG = OBJECT_TAG, WINDOW_HEADER, _WINDOW_MAX }; @@ -59,9 +63,13 @@ typedef struct JournalFile { char *path; struct stat last_stat; mode_t mode; + int flags; int prot; bool writable; + bool compress; + bool authenticate; + bool tail_entry_monotonic_valid; Header *header; @@ -74,12 +82,18 @@ typedef struct JournalFile { JournalMetrics metrics; - bool compress; - #ifdef HAVE_XZ void *compress_buffer; uint64_t compress_buffer_size; #endif + +#ifdef HAVE_GCRYPT + gcry_md_hd_t hmac; + bool hmac_running; + + FSPRGHeader *fsprg_header; + size_t fsprg_size; +#endif } JournalFile; typedef enum direction { @@ -91,6 +105,8 @@ int journal_file_open( const char *fname, int flags, mode_t mode, + bool compress, + bool authenticate, JournalMetrics *metrics, JournalFile *template, JournalFile **ret); @@ -101,6 +117,8 @@ int journal_file_open_reliably( const char *fname, int flags, mode_t mode, + bool compress, + bool authenticate, JournalMetrics *metrics, JournalFile *template, JournalFile **ret); @@ -134,7 +152,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 void journal_file_dump(JournalFile *f); void journal_file_print_header(JournalFile *f); -int journal_file_rotate(JournalFile **f); +int journal_file_rotate(JournalFile **f, bool compress, bool authenticate); int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 62bb904dbe..138bf09d48 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -41,6 +41,10 @@ #include "logs-show.h" #include "strv.h" #include "journal-internal.h" +#include "fsprg.h" +#include "journal-def.h" + +#define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE) static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; @@ -48,14 +52,19 @@ static bool arg_show_all = false; static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; -static bool arg_new_id128 = false; -static bool arg_print_header = false; static bool arg_quiet = false; static bool arg_local = false; static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; +static enum { + ACTION_SHOW, + ACTION_NEW_ID128, + ACTION_PRINT_HEADER, + ACTION_SETUP_KEYS +} arg_action = ACTION_SHOW; + static int help(void) { printf("%s [OPTIONS...] [MATCH]\n\n" @@ -73,9 +82,11 @@ static int help(void) { " -l --local Only local entries\n" " -b --this-boot Show data only from current boot\n" " -D --directory=PATH Show journal files from directory\n" - " -p --priority=RANGE Show only messages within the specified priority range\n" + " -p --priority=RANGE Show only messages within the specified priority range\n\n" + "Commands:\n" + " --new-id128 Generate a new 128 Bit id\n" " --header Show journal header information\n" - " --new-id128 Generate a new 128 Bit id\n", + " --setup-keys Generate new FSPRG key pair\n", program_invocation_short_name); return 0; @@ -88,7 +99,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_PAGER, ARG_NO_TAIL, ARG_NEW_ID128, - ARG_HEADER + ARG_HEADER, + ARG_SETUP_KEYS }; static const struct option options[] = { @@ -107,6 +119,7 @@ static int parse_argv(int argc, char *argv[]) { { "directory", required_argument, NULL, 'D' }, { "header", no_argument, NULL, ARG_HEADER }, { "priority", no_argument, NULL, 'p' }, + { "setup-keys",no_argument, NULL, ARG_SETUP_KEYS}, { NULL, 0, NULL, 0 } }; @@ -163,7 +176,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_NEW_ID128: - arg_new_id128 = true; + arg_action = ACTION_NEW_ID128; break; case 'q': @@ -183,7 +196,11 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_HEADER: - arg_print_header = true; + arg_action = ACTION_PRINT_HEADER; + break; + + case ARG_SETUP_KEYS: + arg_action = ACTION_SETUP_KEYS; break; case 'p': { @@ -400,6 +417,161 @@ static int add_priorities(sd_journal *j) { return 0; } +static int setup_keys(void) { +#ifdef HAVE_GCRYPT + size_t mpk_size, seed_size, state_size, i; + uint8_t *mpk, *seed, *state; + ssize_t l; + int fd = -1, r; + sd_id128_t machine, boot; + char *p = NULL, *k = NULL; + struct FSPRGHeader h; + uint64_t n, interval; + + r = sd_id128_get_machine(&machine); + if (r < 0) { + log_error("Failed to get machine ID: %s", strerror(-r)); + return r; + } + + r = sd_id128_get_boot(&boot); + if (r < 0) { + log_error("Failed to get boot ID: %s", strerror(-r)); + return r; + } + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", + SD_ID128_FORMAT_VAL(machine)) < 0) + return log_oom(); + + if (access(p, F_OK) >= 0) { + log_error("Evolving key file %s exists already.", p); + r = -EEXIST; + goto finish; + } + + if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg.tmp.XXXXXX", + SD_ID128_FORMAT_VAL(machine)) < 0) { + r = log_oom(); + goto finish; + } + + mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR); + mpk = alloca(mpk_size); + + seed_size = FSPRG_RECOMMENDED_SEEDLEN; + seed = alloca(seed_size); + + state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); + state = alloca(state_size); + + fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + log_error("Failed to open /dev/random: %m"); + r = -errno; + goto finish; + } + + log_info("Generating seed..."); + l = loop_read(fd, seed, seed_size, true); + if (l < 0 || (size_t) l != seed_size) { + log_error("Failed to read random seed: %s", strerror(EIO)); + r = -EIO; + goto finish; + } + + log_info("Generating key pair..."); + FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); + + log_info("Generating evolving key..."); + FSPRG_GenState0(state, mpk, seed, seed_size); + + interval = DEFAULT_FSPRG_INTERVAL_USEC; + n = now(CLOCK_REALTIME); + n /= interval; + + close_nointr_nofail(fd); + fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + log_error("Failed to open %s: %m", k); + r = -errno; + goto finish; + } + + zero(h); + memcpy(h.signature, "KSHHRHLP", 8); + h.machine_id = machine; + h.boot_id = boot; + h.header_size = htole64(sizeof(h)); + h.fsprg_start_usec = htole64(n * interval); + h.fsprg_interval_usec = htole64(interval); + h.secpar = htole16(FSPRG_RECOMMENDED_SECPAR); + h.state_size = htole64(state_size); + + l = loop_write(fd, &h, sizeof(h), false); + if (l < 0 || (size_t) l != sizeof(h)) { + log_error("Failed to write header: %s", strerror(EIO)); + r = -EIO; + goto finish; + } + + l = loop_write(fd, state, state_size, false); + if (l < 0 || (size_t) l != state_size) { + log_error("Failed to write state: %s", strerror(EIO)); + r = -EIO; + goto finish; + } + + if (link(k, p) < 0) { + log_error("Failed to link file: %m"); + r = -errno; + goto finish; + } + + if (isatty(STDOUT_FILENO)) { + fprintf(stderr, + "\n" + "The new key pair has been generated. The evolving key has been written to the\n" + "following file. It will be used to protect local journal files. This file does\n" + "not need to be kept secret. It should not be used on multiple hosts.\n" + "\n" + "\t%s\n" + "\n" + "Please write down the following " ANSI_HIGHLIGHT_ON "secret" ANSI_HIGHLIGHT_OFF " seed value. It should not be stored\n" + "locally on disk, and may be used to verify journal files from this host.\n" + "\n\t" ANSI_HIGHLIGHT_RED_ON, p); + fflush(stderr); + } + for (i = 0; i < seed_size; i++) { + if (i > 0 && i % 3 == 0) + putchar('-'); + printf("%02x", ((uint8_t*) seed)[i]); + } + + printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) interval); + + if (isatty(STDOUT_FILENO)) + fputs(ANSI_HIGHLIGHT_OFF "\n", stderr); + + r = 0; + +finish: + if (fd >= 0) + close_nointr_nofail(fd); + + if (k) { + unlink(k); + free(k); + } + + free(p); + + return r; +#else + log_error("Forward-secure journal verification not available."); +#endif +} + int main(int argc, char *argv[]) { int r; sd_journal *j = NULL; @@ -416,11 +588,16 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - if (arg_new_id128) { + if (arg_action == ACTION_NEW_ID128) { r = generate_new_id128(); goto finish; } + if (arg_action == ACTION_SETUP_KEYS) { + r = setup_keys(); + goto finish; + } + #ifdef HAVE_ACL if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); @@ -436,7 +613,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_print_header) { + if (arg_action == ACTION_PRINT_HEADER) { journal_print_header(j); r = 0; goto finish; diff --git a/src/journal/journald.c b/src/journal/journald.c index 7c89689e84..8c41d9bab1 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -281,7 +281,6 @@ static JournalFile* find_journal(Server *s, uid_t uid) { char *p; int r; JournalFile *f; - char ids[33]; sd_id128_t machine; assert(s); @@ -305,7 +304,8 @@ static JournalFile* find_journal(Server *s, uid_t uid) { if (f) return f; - if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0) + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal", + SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0) return s->system_journal; while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) { @@ -315,7 +315,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { journal_file_close(f); } - r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, &s->system_metrics, s->system_journal, &f); + r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, false, &s->system_metrics, s->system_journal, &f); free(p); if (r < 0) @@ -341,7 +341,7 @@ static void server_rotate(Server *s) { log_info("Rotating..."); if (s->runtime_journal) { - r = journal_file_rotate(&s->runtime_journal); + r = journal_file_rotate(&s->runtime_journal, s->compress, false); if (r < 0) if (s->runtime_journal) log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r)); @@ -352,7 +352,7 @@ static void server_rotate(Server *s) { } if (s->system_journal) { - r = journal_file_rotate(&s->system_journal); + r = journal_file_rotate(&s->system_journal, s->compress, true); if (r < 0) if (s->system_journal) log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r)); @@ -364,7 +364,7 @@ static void server_rotate(Server *s) { } HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) { - r = journal_file_rotate(&f); + r = journal_file_rotate(&f, s->compress, false); if (r < 0) if (f->path) log_error("Failed to rotate %s: %s", f->path, strerror(-r)); @@ -2006,14 +2006,12 @@ static int system_journal_open(Server *s) { if (!fn) return -ENOMEM; - r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, &s->system_metrics, NULL, &s->system_journal); + r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, true, &s->system_metrics, NULL, &s->system_journal); free(fn); - if (r >= 0) { - s->system_journal->compress = s->compress; - + if (r >= 0) server_fix_perms(s, s->system_journal, 0); - } else if (r < 0) { + else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning("Failed to open system journal: %s", strerror(-r)); @@ -2035,7 +2033,7 @@ static int system_journal_open(Server *s) { * if it already exists, so that we can flush * it into the system journal */ - r = journal_file_open(fn, O_RDWR, 0640, &s->runtime_metrics, NULL, &s->runtime_journal); + r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, NULL, &s->runtime_journal); free(fn); if (r < 0) { @@ -2051,7 +2049,7 @@ static int system_journal_open(Server *s) { * it if necessary. */ (void) mkdir_parents(fn, 0755); - r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, &s->runtime_metrics, NULL, &s->runtime_journal); + r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, NULL, &s->runtime_journal); free(fn); if (r < 0) { @@ -2060,11 +2058,8 @@ static int system_journal_open(Server *s) { } } - if (s->runtime_journal) { - s->runtime_journal->compress = s->compress; - + if (s->runtime_journal) server_fix_perms(s, s->runtime_journal, 0); - } } return r; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 33686ed2b2..359a7cac3e 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1118,7 +1118,7 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) { return 0; } - r = journal_file_open(path, O_RDONLY, 0, NULL, NULL, &f); + r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, NULL, &f); free(path); if (r < 0) { diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c index fd448cb1ef..0925995fca 100644 --- a/src/journal/test-journal-stream.c +++ b/src/journal/test-journal-stream.c @@ -79,9 +79,9 @@ int main(int argc, char *argv[]) { assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); - assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, NULL, NULL, &one) == 0); - assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, NULL, NULL, &two) == 0); - assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, NULL, NULL, &three) == 0); + assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, &one) == 0); + assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, &two) == 0); + assert_se(journal_file_open("three.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, &three) == 0); for (i = 0; i < N_ENTRIES; i++) { char *p, *q; diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index ca3b4741f5..7b1583c889 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { assert_se(mkdtemp(t)); assert_se(chdir(t) >= 0); - assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, NULL, NULL, &f) == 0); + assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, false, NULL, NULL, &f) == 0); dual_timestamp_get(&ts); @@ -109,8 +109,8 @@ int main(int argc, char *argv[]) { assert(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0); - journal_file_rotate(&f); - journal_file_rotate(&f); + journal_file_rotate(&f, true, true); + journal_file_rotate(&f, true, true); journal_file_close(f); -- cgit v1.2.3-54-g00ecf From b0af6f41ea67c97b8beb16fd1d63042379bbf103 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Aug 2012 20:57:38 +0200 Subject: journal: add all objects we add to HMAC --- src/journal/journal-file.c | 21 ++++++++++++++++++++- src/journal/journal-file.h | 2 ++ src/journal/journalctl.c | 2 +- src/journal/test-journal.c | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 0e4889378c..7dd7256630 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -68,12 +68,17 @@ (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) static int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); +static int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); void journal_file_close(JournalFile *f) { int t; assert(f); + /* Write the final tag */ + if (f->authenticate) + journal_file_append_tag(f); + /* Sync everything to disk, before we mark the file offline */ for (t = 0; t < _WINDOW_MAX; t++) if (f->windows[t].ptr) @@ -831,6 +836,10 @@ static int journal_file_append_data( if (r < 0) return r; + r = journal_file_hmac_put_object(f, OBJECT_DATA, p); + if (r < 0) + return r; + /* The linking might have altered the window, so let's * refresh our pointer */ r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); @@ -907,6 +916,10 @@ static int link_entry_into_array(JournalFile *f, if (r < 0) return r; + r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, q); + if (r < 0) + return r; + o->entry_array.items[i] = htole64(p); if (ap == 0) @@ -1044,6 +1057,10 @@ static int journal_file_append_entry_internal( o->entry.xor_hash = htole64(xor_hash); o->entry.boot_id = f->header->boot_id; + r = journal_file_hmac_put_object(f, OBJECT_ENTRY, np); + if (r < 0) + return r; + r = journal_file_link_entry(f, o, np); if (r < 0) return r; @@ -1888,7 +1905,7 @@ static void *fsprg_state(JournalFile *f) { return (uint8_t*) f->fsprg_header + a; } -static int journal_file_append_tag(JournalFile *f) { +int journal_file_append_tag(JournalFile *f) { Object *o; uint64_t p; int r; @@ -2473,7 +2490,9 @@ int journal_file_open( r = journal_file_verify_header(f); if (r < 0) goto fail; + } + if (!newly_created && f->writable) { r = journal_file_load_fsprg(f); if (r < 0) goto fail; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 25d972040c..a16c8ffc3e 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -164,3 +164,5 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t * int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); bool journal_file_rotate_suggested(JournalFile *f); + +int journal_file_append_tag(JournalFile *f); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 138bf09d48..b4874a77be 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -84,7 +84,7 @@ static int help(void) { " -D --directory=PATH Show journal files from directory\n" " -p --priority=RANGE Show only messages within the specified priority range\n\n" "Commands:\n" - " --new-id128 Generate a new 128 Bit id\n" + " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" " --setup-keys Generate new FSPRG key pair\n", program_invocation_short_name); diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 7b1583c889..8f01b4d82e 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -57,6 +57,7 @@ int main(int argc, char *argv[]) { iovec.iov_len = strlen(test); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); + journal_file_append_tag(f); journal_file_dump(f); assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1); -- cgit v1.2.3-54-g00ecf From beec00856158b703f2125a3d936080346a8a8de1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 15 Aug 2012 01:54:09 +0200 Subject: journal: implement basic journal file verification logic --- Makefile.am | 14 +- src/journal/journal-def.h | 4 +- src/journal/journal-file.c | 421 ++++++++++++++++++++++++++++++++++++++++++++- src/journal/journal-file.h | 2 + src/journal/journalctl.c | 50 +++++- src/journal/mmap-cache.c | 3 +- 6 files changed, 471 insertions(+), 23 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index c90867c8da..f220b59c9c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2384,6 +2384,14 @@ test_journal_stream_LDADD = \ libsystemd-journal-internal.la \ libsystemd-id128-internal.la +test_journal_verify_SOURCES = \ + src/journal/test-journal-verify.c + +test_journal_verify_LDADD = \ + libsystemd-shared.la \ + libsystemd-journal-internal.la \ + libsystemd-id128-internal.la + libsystemd_journal_la_SOURCES = \ src/journal/sd-journal.c \ src/systemd/sd-journal.h \ @@ -2482,12 +2490,14 @@ noinst_PROGRAMS += \ test-journal \ test-journal-send \ test-journal-match \ - test-journal-stream + test-journal-stream \ + test-journal-verify TESTS += \ test-journal \ test-journal-match \ - test-journal-stream + test-journal-stream \ + test-journal-verify pkginclude_HEADERS += \ src/systemd/sd-journal.h \ diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 82210bfc46..a77f69edcb 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -174,8 +174,8 @@ _packed_ struct Header { le64_t tail_object_offset; le64_t n_objects; le64_t n_entries; - le64_t tail_seqnum; - le64_t head_seqnum; + le64_t tail_entry_seqnum; + le64_t head_entry_seqnum; le64_t entry_array_offset; le64_t head_entry_realtime; le64_t tail_entry_realtime; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 1f5e04d791..709e15eceb 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -136,7 +136,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { if (template) { h.seqnum_id = template->header->seqnum_id; - h.tail_seqnum = template->header->tail_seqnum; + h.tail_entry_seqnum = template->header->tail_entry_seqnum; } else h.seqnum_id = h.file_id; @@ -210,6 +210,10 @@ static int journal_file_verify_header(JournalFile *f) { if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) return -EBADMSG; + if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED) && + !JOURNAL_HEADER_CONTAINS(f->header, n_tags)) + return -EBADMSG; + if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size))) return -ENODATA; @@ -407,7 +411,7 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { assert(f); - r = le64toh(f->header->tail_seqnum) + 1; + r = le64toh(f->header->tail_entry_seqnum) + 1; if (seqnum) { /* If an external seqnum counter was passed, we update @@ -420,10 +424,10 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { *seqnum = r; } - f->header->tail_seqnum = htole64(r); + f->header->tail_entry_seqnum = htole64(r); - if (f->header->head_seqnum == 0) - f->header->head_seqnum = htole64(r); + if (f->header->head_entry_seqnum == 0) + f->header->head_entry_seqnum = htole64(r); return r; } @@ -2066,7 +2070,7 @@ static int journal_file_hmac_put_header(JournalFile *f) { gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); - gcry_md_write(f->hmac, &f->header->head_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_seqnum)); + gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum)); return 0; } @@ -2223,6 +2227,405 @@ static int journal_file_append_first_tag(JournalFile *f) { return 0; } +static int journal_file_object_verify(JournalFile *f, Object *o) { + assert(f); + assert(o); + + /* This does various superficial tests about the length an + * possible field values. It does not follow any references to + * other objects. */ + + switch (o->object.type) { + case OBJECT_DATA: + if (le64toh(o->data.entry_offset) <= 0 || + le64toh(o->data.n_entries) <= 0) + return -EBADMSG; + + if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) + return -EBADMSG; + break; + + case OBJECT_FIELD: + if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) + return -EBADMSG; + break; + + case OBJECT_ENTRY: + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) + return -EBADMSG; + + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) + return -EBADMSG; + + if (le64toh(o->entry.seqnum) <= 0 || + le64toh(o->entry.realtime) <= 0) + return -EBADMSG; + + break; + + case OBJECT_DATA_HASH_TABLE: + case OBJECT_FIELD_HASH_TABLE: + if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0) + return -EBADMSG; + + break; + + case OBJECT_ENTRY_ARRAY: + if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0) + return -EBADMSG; + + break; + + case OBJECT_TAG: + if (le64toh(o->object.size) != sizeof(TagObject)) + return -EBADMSG; + break; + } + + return 0; +} + +static void draw_progress(uint64_t p, usec_t *last_usec) { + unsigned n, i, j, k; + usec_t z, x; + + if (!isatty(STDOUT_FILENO)) + return; + + z = now(CLOCK_MONOTONIC); + x = *last_usec; + + if (x != 0 && x + 40 * USEC_PER_MSEC > z) + return; + + *last_usec = z; + + n = (3 * columns()) / 4; + j = (n * (unsigned) p) / 65535ULL; + k = n - j; + + fputs("\r\x1B[?25l", stdout); + + for (i = 0; i < j; i++) + fputs("\xe2\x96\x88", stdout); + + for (i = 0; i < k; i++) + fputs("\xe2\x96\x91", stdout); + + printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU); + + fputs("\r\x1B[?25h", stdout); + fflush(stdout); +} + +static void flush_progress(void) { + unsigned n, i; + + if (!isatty(STDOUT_FILENO)) + return; + + n = (3 * columns()) / 4; + + putchar('\r'); + + for (i = 0; i < n + 5; i++) + putchar(' '); + + putchar('\r'); + fflush(stdout); +} + +int journal_file_verify(JournalFile *f, const char *key) { + int r; + Object *o; + uint64_t p = 0, q = 0, e; + uint64_t tag_seqnum = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; + sd_id128_t entry_boot_id; + bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; + uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0; + usec_t last_usec = 0; + + assert(f); + + /* First iteration: we go through all objects, verify the + * superficial structure, headers, hashes. */ + + r = journal_file_hmac_put_header(f); + if (r < 0) { + log_error("Failed to calculate HMAC of header."); + goto fail; + } + + p = le64toh(f->header->header_size); + while (p != 0) { + draw_progress((65535ULL * p / le64toh(f->header->tail_object_offset)), &last_usec); + + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) { + log_error("Invalid object at %llu", (unsigned long long) p); + goto fail; + } + + if (le64toh(f->header->tail_object_offset) < p) { + log_error("Invalid tail object pointer."); + r = -EBADMSG; + goto fail; + } + + n_objects ++; + + r = journal_file_object_verify(f, o); + if (r < 0) { + log_error("Invalid object contents at %llu", (unsigned long long) p); + goto fail; + } + + r = journal_file_hmac_put_object(f, -1, p); + if (r < 0) { + log_error("Failed to calculate HMAC at %llu", (unsigned long long) p); + goto fail; + } + + if (o->object.flags & OBJECT_COMPRESSED && + !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) { + log_error("Compressed object without compression at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (o->object.flags & OBJECT_COMPRESSED && + o->object.type != OBJECT_DATA) { + log_error("Compressed non-data object at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (o->object.type == OBJECT_TAG) { + + if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) { + log_error("Tag object without authentication at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(o->tag.seqnum) != tag_seqnum) { + log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + } else if (o->object.type == OBJECT_ENTRY) { + + if (!entry_seqnum_set && + le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { + log_error("Head entry sequence number incorrect"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum >= le64toh(o->entry.seqnum)) { + log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + entry_seqnum = le64toh(o->entry.seqnum); + entry_seqnum_set = true; + + if (entry_monotonic_set && + sd_id128_equal(entry_boot_id, o->entry.boot_id) && + entry_monotonic > le64toh(o->entry.monotonic)) { + log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + entry_monotonic = le64toh(o->entry.monotonic); + entry_boot_id = o->entry.boot_id; + entry_monotonic_set = true; + + if (!entry_realtime_set && + le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { + log_error("Head entry realtime timestamp incorrect"); + r = -EBADMSG; + goto fail; + } + + entry_realtime = le64toh(o->entry.realtime); + entry_realtime_set = true; + + n_entries ++; + } else if (o->object.type == OBJECT_ENTRY_ARRAY) { + + if (p == le64toh(f->header->entry_array_offset)) { + if (found_main_entry_array) { + log_error("More than one main entry array at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + found_main_entry_array = true; + } + + } else if (o->object.type == OBJECT_DATA) + n_data++; + else if (o->object.type == OBJECT_FIELD) + n_fields++; + else if (o->object.type == OBJECT_DATA_HASH_TABLE) { + n_data_hash_tables++; + + if (n_data_hash_tables > 1) { + log_error("More than one data hash table at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + log_error("Header fields for data hash table invalid."); + r = -EBADMSG; + goto fail; + } + } else if (o->object.type == OBJECT_FIELD_HASH_TABLE) { + n_field_hash_tables++; + + if (n_field_hash_tables > 1) { + log_error("More than one field hash table at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + log_error("Header fields for field hash table invalid."); + r = -EBADMSG; + goto fail; + } + } + + if (o->object.type >= _OBJECT_TYPE_MAX) + n_weird ++; + else { + /* Write address to file... */ + + } + + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } + + if (n_objects != le64toh(f->header->n_objects)) { + log_error("Object number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (n_entries != le64toh(f->header->n_entries)) { + log_error("Entry number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && + n_data != le64toh(f->header->n_data)) { + log_error("Data number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && + n_fields != le64toh(f->header->n_fields)) { + log_error("Field number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && + tag_seqnum != le64toh(f->header->n_tags)) { + log_error("Tag number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (n_data_hash_tables != 1) { + log_error("Missing data hash table"); + r = -EBADMSG; + goto fail; + } + + if (n_field_hash_tables != 1) { + log_error("Missing field hash table"); + r = -EBADMSG; + goto fail; + } + + if (!found_main_entry_array) { + log_error("Missing entry array"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { + log_error("Invalid tail seqnum"); + r = -EBADMSG; + goto fail; + } + + if (entry_monotonic_set && + (!sd_id128_equal(entry_boot_id, f->header->boot_id) || + entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { + log_error("Invalid tail monotonic timestamp"); + r = -EBADMSG; + goto fail; + } + + if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { + log_error("Invalid tail realtime timestamp"); + r = -EBADMSG; + goto fail; + } + + /* Second iteration: we go through all objects again, this + * time verify all pointers. */ + + /* q = le64toh(f->header->header_size); */ + /* while (q != 0) { */ + /* r = journal_file_move_to_object(f, -1, q, &o); */ + /* if (r < 0) { */ + /* log_error("Invalid object at %llu", (unsigned long long) q); */ + /* goto fail; */ + /* } */ + + /* if (q == le64toh(f->header->tail_object_offset)) */ + /* q = 0; */ + /* else */ + /* q = q + ALIGN64(le64toh(o->object.size)); */ + /* } */ + + flush_progress(); + + return 0; + +fail: + e = p <= 0 ? q : + q <= 0 ? p : + MIN(p, q); + + flush_progress(); + + log_error("File corruption detected at %s:%llu (of %llu, %llu%%).", + f->path, + (unsigned long long) e, + (unsigned long long) f->last_stat.st_size, + (unsigned long long) (100 * e / f->last_stat.st_size)); + + return r; +} + void journal_file_dump(JournalFile *f) { Object *o; int r; @@ -2331,8 +2734,8 @@ void journal_file_print_header(JournalFile *f) { (unsigned long long) le64toh(f->header->n_objects), (unsigned long long) le64toh(f->header->n_entries), yes_no(journal_file_rotate_suggested(f)), - (unsigned long long) le64toh(f->header->head_seqnum), - (unsigned long long) le64toh(f->header->tail_seqnum), + (unsigned long long) le64toh(f->header->head_entry_seqnum), + (unsigned long long) le64toh(f->header->tail_entry_seqnum), format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)), format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime))); @@ -2536,7 +2939,7 @@ int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) { sd_id128_to_string(old_file->header->seqnum_id, p + l - 8 + 1); snprintf(p + l - 8 + 1 + 32, 1 + 16 + 1 + 16 + 8 + 1, "-%016llx-%016llx.journal", - (unsigned long long) le64toh((*f)->header->tail_seqnum), + (unsigned long long) le64toh((*f)->header->tail_entry_seqnum), (unsigned long long) le64toh((*f)->header->tail_entry_realtime)); r = rename(old_file->path, p); diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 11a1c7d641..0305c97134 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -150,3 +150,5 @@ int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec bool journal_file_rotate_suggested(JournalFile *f); int journal_file_append_tag(JournalFile *f); + +int journal_file_verify(JournalFile *f, const char *key); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b4874a77be..8e09ff115a 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -62,7 +62,8 @@ static enum { ACTION_SHOW, ACTION_NEW_ID128, ACTION_PRINT_HEADER, - ACTION_SETUP_KEYS + ACTION_SETUP_KEYS, + ACTION_VERIFY } arg_action = ACTION_SHOW; static int help(void) { @@ -86,7 +87,8 @@ static int help(void) { "Commands:\n" " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" - " --setup-keys Generate new FSPRG key pair\n", + " --setup-keys Generate new FSPRG key pair\n" + " --verify Verify journal file consistency\n", program_invocation_short_name); return 0; @@ -100,7 +102,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_TAIL, ARG_NEW_ID128, ARG_HEADER, - ARG_SETUP_KEYS + ARG_SETUP_KEYS, + ARG_VERIFY }; static const struct option options[] = { @@ -120,6 +123,7 @@ static int parse_argv(int argc, char *argv[]) { { "header", no_argument, NULL, ARG_HEADER }, { "priority", no_argument, NULL, 'p' }, { "setup-keys",no_argument, NULL, ARG_SETUP_KEYS}, + { "verify", no_argument, NULL, ARG_VERIFY }, { NULL, 0, NULL, 0 } }; @@ -203,6 +207,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_SETUP_KEYS; break; + case ARG_VERIFY: + arg_action = ACTION_VERIFY; + break; + case 'p': { const char *dots; @@ -572,6 +580,27 @@ finish: #endif } +static int verify(sd_journal *j) { + int r = 0; + Iterator i; + JournalFile *f; + + assert(j); + + HASHMAP_FOREACH(f, j->files, i) { + int k; + + k = journal_file_verify(f, NULL); + if (k < 0) { + log_warning("FAIL: %s (%s)", f->path, strerror(-k)); + r = -r; + } else + log_info("PASS: %s", f->path); + } + + return r; +} + int main(int argc, char *argv[]) { int r; sd_journal *j = NULL; @@ -598,11 +627,6 @@ int main(int argc, char *argv[]) { goto finish; } -#ifdef HAVE_ACL - if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) - log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); -#endif - if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, 0); else @@ -613,12 +637,22 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_action == ACTION_VERIFY) { + r = verify(j); + goto finish; + } + if (arg_action == ACTION_PRINT_HEADER) { journal_print_header(j); r = 0; goto finish; } +#ifdef HAVE_ACL + if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) + log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); +#endif + r = add_this_boot(j); if (r < 0) goto finish; diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 68dbe7015b..77710ff9bf 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -232,7 +232,6 @@ MMapCache* mmap_cache_new(unsigned contexts_max, unsigned fds_max) { mmap_cache_free(m); return NULL; } - memset(m->by_context, -1, m->contexts_max * sizeof(unsigned)); m->by_fd = new(FileDescriptor, m->fds_max); @@ -334,7 +333,7 @@ static int mmap_cache_put( if (wsize < WINDOW_SIZE) { uint64_t delta; - delta = (WINDOW_SIZE - wsize) / 2; + delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2); if (delta > offset) woffset = 0; -- cgit v1.2.3-54-g00ecf From 0284adc6a60ce0af1107cb0b50041a65d731f39e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Aug 2012 01:51:54 +0200 Subject: journal: split up journal-file.c --- .gitignore | 1 + Makefile.am | 6 + src/journal/journal-authenticate.c | 434 ++++++++++ src/journal/journal-authenticate.h | 35 + src/journal/journal-file.c | 1521 +++++------------------------------- src/journal/journal-file.h | 13 +- src/journal/journal-vacuum.c | 230 ++++++ src/journal/journal-vacuum.h | 26 + src/journal/journal-verify.c | 558 +++++++++++++ src/journal/journal-verify.h | 26 + src/journal/journalctl.c | 1 + src/journal/journald.c | 1 + src/journal/test-journal-verify.c | 78 ++ src/journal/test-journal.c | 4 +- 14 files changed, 1598 insertions(+), 1336 deletions(-) create mode 100644 src/journal/journal-authenticate.c create mode 100644 src/journal/journal-authenticate.h create mode 100644 src/journal/journal-vacuum.c create mode 100644 src/journal/journal-vacuum.h create mode 100644 src/journal/journal-verify.c create mode 100644 src/journal/journal-verify.h create mode 100644 src/journal/test-journal-verify.c (limited to 'src/journal/journalctl.c') diff --git a/.gitignore b/.gitignore index 8928071449..4c8bba8871 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/test-journal-verify /test-journal-match /test-journal-stream /test-unit-name diff --git a/Makefile.am b/Makefile.am index f220b59c9c..895dcfa334 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2397,6 +2397,12 @@ libsystemd_journal_la_SOURCES = \ src/systemd/sd-journal.h \ src/journal/journal-file.c \ src/journal/journal-file.h \ + src/journal/journal-vacuum.c \ + src/journal/journal-vacuum.h \ + src/journal/journal-verify.c \ + src/journal/journal-verify.h \ + src/journal/journal-authenticate.c \ + src/journal/journal-authenticate.h \ src/journal/lookup3.c \ src/journal/lookup3.h \ src/journal/journal-send.c \ diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c new file mode 100644 index 0000000000..827e4e4fb9 --- /dev/null +++ b/src/journal/journal-authenticate.c @@ -0,0 +1,434 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "journal-def.h" +#include "journal-file.h" +#include "journal-authenticate.h" +#include "fsprg.h" + +static void *fsprg_state(JournalFile *f) { + uint64_t a, b; + assert(f); + + if (!f->authenticate) + return NULL; + + a = le64toh(f->fsprg_header->header_size); + b = le64toh(f->fsprg_header->state_size); + + if (a + b > f->fsprg_size) + return NULL; + + return (uint8_t*) f->fsprg_header + a; +} + +static uint64_t journal_file_tag_seqnum(JournalFile *f) { + uint64_t r; + + assert(f); + + r = le64toh(f->header->n_tags) + 1; + f->header->n_tags = htole64(r); + + return r; +} + +int journal_file_append_tag(JournalFile *f) { + Object *o; + uint64_t p; + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + if (!f->hmac_running) + return 0; + + log_debug("Writing tag for epoch %llu\n", (unsigned long long) FSPRG_GetEpoch(fsprg_state(f))); + + assert(f->hmac); + + r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p); + if (r < 0) + return r; + + o->tag.seqnum = htole64(journal_file_tag_seqnum(f)); + + /* Add the tag object itself, so that we can protect its + * header. This will exclude the actual hash value in it */ + r = journal_file_hmac_put_object(f, OBJECT_TAG, p); + if (r < 0) + return r; + + /* Get the HMAC tag and store it in the object */ + memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); + f->hmac_running = false; + + return 0; +} + +static int journal_file_hmac_start(JournalFile *f) { + uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ + + assert(f); + + if (!f->authenticate) + return 0; + + if (f->hmac_running) + return 0; + + /* Prepare HMAC for next cycle */ + gcry_md_reset(f->hmac); + FSPRG_GetKey(fsprg_state(f), key, sizeof(key), 0); + gcry_md_setkey(f->hmac, key, sizeof(key)); + + f->hmac_running = true; + + return 0; +} + +static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) { + uint64_t t; + + assert(f); + assert(epoch); + assert(f->authenticate); + + if (le64toh(f->fsprg_header->fsprg_start_usec) == 0 || + le64toh(f->fsprg_header->fsprg_interval_usec) == 0) + return -ENOTSUP; + + if (realtime < le64toh(f->fsprg_header->fsprg_start_usec)) + return -ESTALE; + + t = realtime - le64toh(f->fsprg_header->fsprg_start_usec); + t = t / le64toh(f->fsprg_header->fsprg_interval_usec); + + *epoch = t; + return 0; +} + +static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(fsprg_state(f)); + if (epoch > goal) + return -ESTALE; + + return epoch != goal; +} + +static int journal_file_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(fsprg_state(f)); + if (epoch < goal) + log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal); + + for (;;) { + if (epoch > goal) + return -ESTALE; + if (epoch == goal) + return 0; + + FSPRG_Evolve(fsprg_state(f)); + epoch = FSPRG_GetEpoch(fsprg_state(f)); + } +} + +int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_need_evolve(f, realtime); + if (r <= 0) + return 0; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + r = journal_file_evolve(f, realtime); + if (r < 0) + return r; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + return 0; +} + +int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { + int r; + Object *o; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + r = journal_file_move_to_object(f, type, p, &o); + if (r < 0) + return r; + + gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); + + switch (o->object.type) { + + case OBJECT_DATA: + /* All but: hash and payload are mutable */ + gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); + gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); + break; + + case OBJECT_ENTRY: + /* All */ + gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); + break; + + case OBJECT_FIELD_HASH_TABLE: + case OBJECT_DATA_HASH_TABLE: + case OBJECT_ENTRY_ARRAY: + /* Nothing: everything is mutable */ + break; + + case OBJECT_TAG: + /* All but the tag itself */ + gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); + break; + default: + return -EINVAL; + } + + return 0; +} + +int journal_file_hmac_put_header(JournalFile *f) { + int r; + + assert(f); + + if (!f->authenticate) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + /* All but state+reserved, boot_id, arena_size, + * tail_object_offset, n_objects, n_entries, tail_seqnum, + * head_entry_realtime, tail_entry_realtime, + * tail_entry_monotonic, n_data, n_fields, header_tag */ + + gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); + gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); + gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); + gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); + gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum)); + + return 0; +} + +int journal_file_load_fsprg(JournalFile *f) { + int r, fd = -1; + char *p = NULL; + struct stat st; + FSPRGHeader *m = NULL; + sd_id128_t machine; + + assert(f); + + if (!f->authenticate) + return 0; + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", + SD_ID128_FORMAT_VAL(machine)) < 0) + return -ENOMEM; + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); + if (fd < 0) { + log_error("Failed to open %s: %m", p); + r = -errno; + goto finish; + } + + if (fstat(fd, &st) < 0) { + r = -errno; + goto finish; + } + + if (st.st_size < (off_t) sizeof(FSPRGHeader)) { + r = -ENODATA; + goto finish; + } + + m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0); + if (m == MAP_FAILED) { + m = NULL; + r = -errno; + goto finish; + } + + if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) { + r = -EBADMSG; + goto finish; + } + + if (m->incompatible_flags != 0) { + r = -EPROTONOSUPPORT; + goto finish; + } + + if (le64toh(m->header_size) < sizeof(FSPRGHeader)) { + r = -EBADMSG; + goto finish; + } + + if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) { + r = -EBADMSG; + goto finish; + } + + f->fsprg_size = le64toh(m->header_size) + le64toh(m->state_size); + if ((uint64_t) st.st_size < f->fsprg_size) { + r = -ENODATA; + goto finish; + } + + if (!sd_id128_equal(machine, m->machine_id)) { + r = -EHOSTDOWN; + goto finish; + } + + if (le64toh(m->fsprg_start_usec) <= 0 || + le64toh(m->fsprg_interval_usec) <= 0) { + r = -EBADMSG; + goto finish; + } + + f->fsprg_header = mmap(NULL, PAGE_ALIGN(f->fsprg_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (f->fsprg_header == MAP_FAILED) { + f->fsprg_header = NULL; + r = -errno; + goto finish; + } + + r = 0; + +finish: + if (m) + munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader))); + + if (fd >= 0) + close_nointr_nofail(fd); + + free(p); + return r; +} + +int journal_file_setup_hmac(JournalFile *f) { + gcry_error_t e; + + if (!f->authenticate) + return 0; + + e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if (e != 0) + return -ENOTSUP; + + return 0; +} + +int journal_file_append_first_tag(JournalFile *f) { + int r; + uint64_t p; + + if (!f->authenticate) + return 0; + + log_debug("Calculating first tag..."); + + r = journal_file_hmac_put_header(f); + if (r < 0) + return r; + + p = le64toh(f->header->field_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, p); + if (r < 0) + return r; + + p = le64toh(f->header->data_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, p); + if (r < 0) + return r; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + return 0; +} diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h new file mode 100644 index 0000000000..c991b22e4a --- /dev/null +++ b/src/journal/journal-authenticate.h @@ -0,0 +1,35 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "journal-file.h" + +int journal_file_append_tag(JournalFile *f); +int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); +int journal_file_append_first_tag(JournalFile *f); + +int journal_file_hmac_put_header(JournalFile *f); +int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); + +int journal_file_load_fsprg(JournalFile *f); + +int journal_file_setup_hmac(JournalFile *f); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 7beedb4a25..ff439f2474 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -29,6 +29,7 @@ #include "journal-def.h" #include "journal-file.h" +#include "journal-authenticate.h" #include "lookup3.h" #include "compress.h" #include "fsprg.h" @@ -60,14 +61,6 @@ /* n_data was the first entry we added after the initial file format design */ #define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data)) -#define ALIGN64(x) (((x) + 7ULL) & ~7ULL) - -#define JOURNAL_HEADER_CONTAINS(h, field) \ - (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) - -static int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); -static int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); - void journal_file_close(JournalFile *f) { assert(f); @@ -434,7 +427,7 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { return r; } -static int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) { +int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) { int r; uint64_t p; Object *tail, *o; @@ -796,7 +789,7 @@ uint64_t journal_file_entry_n_items(Object *o) { return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); } -static uint64_t journal_file_entry_array_n_items(Object *o) { +uint64_t journal_file_entry_array_n_items(Object *o) { assert(o); assert(o->object.type == OBJECT_ENTRY_ARRAY); @@ -1823,1174 +1816,241 @@ int journal_file_move_to_entry_by_realtime_for_data( ret, offset, NULL); } -static void *fsprg_state(JournalFile *f) { - uint64_t a, b; - assert(f); - - if (!f->authenticate) - return NULL; - - a = le64toh(f->fsprg_header->header_size); - b = le64toh(f->fsprg_header->state_size); - - if (a + b > f->fsprg_size) - return NULL; - - return (uint8_t*) f->fsprg_header + a; -} - -static uint64_t journal_file_tag_seqnum(JournalFile *f) { - uint64_t r; - - assert(f); - - r = le64toh(f->header->n_tags) + 1; - f->header->n_tags = htole64(r); - - return r; -} - -int journal_file_append_tag(JournalFile *f) { +void journal_file_dump(JournalFile *f) { Object *o; - uint64_t p; int r; + uint64_t p; assert(f); - if (!f->authenticate) - return 0; - - if (!f->hmac_running) - return 0; - - log_debug("Writing tag for epoch %llu\n", (unsigned long long) FSPRG_GetEpoch(fsprg_state(f))); - - assert(f->hmac); + journal_file_print_header(f); - r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p); - if (r < 0) - return r; + p = le64toh(f->header->header_size); + while (p != 0) { + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) + goto fail; - o->tag.seqnum = htole64(journal_file_tag_seqnum(f)); + switch (o->object.type) { - /* Add the tag object itself, so that we can protect its - * header. This will exclude the actual hash value in it */ - r = journal_file_hmac_put_object(f, OBJECT_TAG, p); - if (r < 0) - return r; + case OBJECT_UNUSED: + printf("Type: OBJECT_UNUSED\n"); + break; - /* Get the HMAC tag and store it in the object */ - memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); - f->hmac_running = false; + case OBJECT_DATA: + printf("Type: OBJECT_DATA\n"); + break; - return 0; -} + case OBJECT_ENTRY: + printf("Type: OBJECT_ENTRY %llu %llu %llu\n", + (unsigned long long) le64toh(o->entry.seqnum), + (unsigned long long) le64toh(o->entry.monotonic), + (unsigned long long) le64toh(o->entry.realtime)); + break; -static int journal_file_hmac_start(JournalFile *f) { - uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ + case OBJECT_FIELD_HASH_TABLE: + printf("Type: OBJECT_FIELD_HASH_TABLE\n"); + break; - assert(f); + case OBJECT_DATA_HASH_TABLE: + printf("Type: OBJECT_DATA_HASH_TABLE\n"); + break; - if (!f->authenticate) - return 0; + case OBJECT_ENTRY_ARRAY: + printf("Type: OBJECT_ENTRY_ARRAY\n"); + break; - if (f->hmac_running) - return 0; + case OBJECT_TAG: + printf("Type: OBJECT_TAG %llu\n", + (unsigned long long) le64toh(o->tag.seqnum)); + break; + } - /* Prepare HMAC for next cycle */ - gcry_md_reset(f->hmac); - FSPRG_GetKey(fsprg_state(f), key, sizeof(key), 0); - gcry_md_setkey(f->hmac, key, sizeof(key)); + if (o->object.flags & OBJECT_COMPRESSED) + printf("Flags: COMPRESSED\n"); - f->hmac_running = true; + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } - return 0; + return; +fail: + log_error("File corrupt"); } -static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) { - uint64_t t; +void journal_file_print_header(JournalFile *f) { + char a[33], b[33], c[33]; + char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX]; assert(f); - assert(epoch); - assert(f->authenticate); - if (le64toh(f->fsprg_header->fsprg_start_usec) == 0 || - le64toh(f->fsprg_header->fsprg_interval_usec) == 0) - return -ENOTSUP; - - if (realtime < le64toh(f->fsprg_header->fsprg_start_usec)) - return -ESTALE; + printf("File Path: %s\n" + "File ID: %s\n" + "Machine ID: %s\n" + "Boot ID: %s\n" + "Sequential Number ID: %s\n" + "State: %s\n" + "Compatible Flags:%s%s\n" + "Incompatible Flags:%s%s\n" + "Header size: %llu\n" + "Arena size: %llu\n" + "Data Hash Table Size: %llu\n" + "Field Hash Table Size: %llu\n" + "Objects: %llu\n" + "Entry Objects: %llu\n" + "Rotate Suggested: %s\n" + "Head Sequential Number: %llu\n" + "Tail Sequential Number: %llu\n" + "Head Realtime Timestamp: %s\n" + "Tail Realtime Timestamp: %s\n", + f->path, + sd_id128_to_string(f->header->file_id, a), + sd_id128_to_string(f->header->machine_id, b), + sd_id128_to_string(f->header->boot_id, c), + sd_id128_to_string(f->header->seqnum_id, c), + f->header->state == STATE_OFFLINE ? "offline" : + f->header->state == STATE_ONLINE ? "online" : + f->header->state == STATE_ARCHIVED ? "archived" : "unknown", + (f->header->compatible_flags & HEADER_COMPATIBLE_AUTHENTICATED) ? " AUTHENTICATED" : "", + (f->header->compatible_flags & ~HEADER_COMPATIBLE_AUTHENTICATED) ? " ???" : "", + (f->header->incompatible_flags & HEADER_INCOMPATIBLE_COMPRESSED) ? " COMPRESSED" : "", + (f->header->incompatible_flags & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "", + (unsigned long long) le64toh(f->header->header_size), + (unsigned long long) le64toh(f->header->arena_size), + (unsigned long long) le64toh(f->header->data_hash_table_size) / sizeof(HashItem), + (unsigned long long) le64toh(f->header->field_hash_table_size) / sizeof(HashItem), + (unsigned long long) le64toh(f->header->n_objects), + (unsigned long long) le64toh(f->header->n_entries), + yes_no(journal_file_rotate_suggested(f)), + (unsigned long long) le64toh(f->header->head_entry_seqnum), + (unsigned long long) le64toh(f->header->tail_entry_seqnum), + format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)), + format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime))); - t = realtime - le64toh(f->fsprg_header->fsprg_start_usec); - t = t / le64toh(f->fsprg_header->fsprg_interval_usec); + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + printf("Data Objects: %llu\n" + "Data Hash Table Fill: %.1f%%\n", + (unsigned long long) le64toh(f->header->n_data), + 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)))); - *epoch = t; - return 0; + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + printf("Field Objects: %llu\n" + "Field Hash Table Fill: %.1f%%\n", + (unsigned long long) le64toh(f->header->n_fields), + 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)))); } -static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) { - uint64_t goal, epoch; - int r; - assert(f); - - if (!f->authenticate) - return 0; +int journal_file_open( + const char *fname, + int flags, + mode_t mode, + bool compress, + bool authenticate, + JournalMetrics *metrics, + MMapCache *mmap_cache, + JournalFile *template, + JournalFile **ret) { - r = journal_file_get_epoch(f, realtime, &goal); - if (r < 0) - return r; + JournalFile *f; + int r; + bool newly_created = false; - epoch = FSPRG_GetEpoch(fsprg_state(f)); - if (epoch > goal) - return -ESTALE; + assert(fname); - return epoch != goal; -} + if ((flags & O_ACCMODE) != O_RDONLY && + (flags & O_ACCMODE) != O_RDWR) + return -EINVAL; -static int journal_file_evolve(JournalFile *f, uint64_t realtime) { - uint64_t goal, epoch; - int r; + if (!endswith(fname, ".journal")) + return -EINVAL; - assert(f); + f = new0(JournalFile, 1); + if (!f) + return -ENOMEM; - if (!f->authenticate) - return 0; + f->fd = -1; + f->mode = mode; - r = journal_file_get_epoch(f, realtime, &goal); - if (r < 0) - return r; + f->flags = flags; + f->prot = prot_from_flags(flags); + f->writable = (flags & O_ACCMODE) != O_RDONLY; + f->compress = compress; + f->authenticate = authenticate; - epoch = FSPRG_GetEpoch(fsprg_state(f)); - if (epoch < goal) - log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal); + if (mmap_cache) + f->mmap = mmap_cache_ref(mmap_cache); + else { + /* One context for each type, plus the zeroth catchall + * context. One fd for the file plus one for each type + * (which we need during verification */ + f->mmap = mmap_cache_new(_OBJECT_TYPE_MAX, 1 + _OBJECT_TYPE_MAX); + if (!f->mmap) { + r = -ENOMEM; + goto fail; + } + } - for (;;) { - if (epoch > goal) - return -ESTALE; - if (epoch == goal) - return 0; + f->path = strdup(fname); + if (!f->path) { + r = -ENOMEM; + goto fail; + } - FSPRG_Evolve(fsprg_state(f)); - epoch = FSPRG_GetEpoch(fsprg_state(f)); + f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode); + if (f->fd < 0) { + r = -errno; + goto fail; } -} -static int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { - int r; + if (fstat(f->fd, &f->last_stat) < 0) { + r = -errno; + goto fail; + } - assert(f); + if (f->last_stat.st_size == 0 && f->writable) { + newly_created = true; - if (!f->authenticate) - return 0; + /* Try to load the FSPRG state, and if we can't, then + * just don't do authentication */ + r = journal_file_load_fsprg(f); + if (r < 0) + f->authenticate = false; - r = journal_file_need_evolve(f, realtime); - if (r <= 0) - return 0; + r = journal_file_init_header(f, template); + if (r < 0) + goto fail; - r = journal_file_append_tag(f); - if (r < 0) - return r; + if (fstat(f->fd, &f->last_stat) < 0) { + r = -errno; + goto fail; + } + } - r = journal_file_evolve(f, realtime); - if (r < 0) - return r; + if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) { + r = -EIO; + goto fail; + } - r = journal_file_hmac_start(f); - if (r < 0) - return r; + f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0); + if (f->header == MAP_FAILED) { + f->header = NULL; + r = -errno; + goto fail; + } - return 0; -} + if (!newly_created) { + r = journal_file_verify_header(f); + if (r < 0) + goto fail; + } -static int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { - int r; - Object *o; - - assert(f); - - if (!f->authenticate) - return 0; - - r = journal_file_hmac_start(f); - if (r < 0) - return r; - - r = journal_file_move_to_object(f, type, p, &o); - if (r < 0) - return r; - - gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); - - switch (o->object.type) { - - case OBJECT_DATA: - /* All but: hash and payload are mutable */ - gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); - gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); - break; - - case OBJECT_ENTRY: - /* All */ - gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); - break; - - case OBJECT_FIELD_HASH_TABLE: - case OBJECT_DATA_HASH_TABLE: - case OBJECT_ENTRY_ARRAY: - /* Nothing: everything is mutable */ - break; - - case OBJECT_TAG: - /* All but the tag itself */ - gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int journal_file_hmac_put_header(JournalFile *f) { - int r; - - assert(f); - - if (!f->authenticate) - return 0; - - r = journal_file_hmac_start(f); - if (r < 0) - return r; - - /* All but state+reserved, boot_id, arena_size, - * tail_object_offset, n_objects, n_entries, tail_seqnum, - * head_entry_realtime, tail_entry_realtime, - * tail_entry_monotonic, n_data, n_fields, header_tag */ - - gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); - gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); - gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); - gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); - gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum)); - - return 0; -} - -static int journal_file_load_fsprg(JournalFile *f) { - int r, fd = -1; - char *p = NULL; - struct stat st; - FSPRGHeader *m = NULL; - sd_id128_t machine; - - assert(f); - - if (!f->authenticate) - return 0; - - r = sd_id128_get_machine(&machine); - if (r < 0) - return r; - - if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", - SD_ID128_FORMAT_VAL(machine)) < 0) - return -ENOMEM; - - fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); - if (fd < 0) { - log_error("Failed to open %s: %m", p); - r = -errno; - goto finish; - } - - if (fstat(fd, &st) < 0) { - r = -errno; - goto finish; - } - - if (st.st_size < (off_t) sizeof(FSPRGHeader)) { - r = -ENODATA; - goto finish; - } - - m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0); - if (m == MAP_FAILED) { - m = NULL; - r = -errno; - goto finish; - } - - if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) { - r = -EBADMSG; - goto finish; - } - - if (m->incompatible_flags != 0) { - r = -EPROTONOSUPPORT; - goto finish; - } - - if (le64toh(m->header_size) < sizeof(FSPRGHeader)) { - r = -EBADMSG; - goto finish; - } - - if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) { - r = -EBADMSG; - goto finish; - } - - f->fsprg_size = le64toh(m->header_size) + le64toh(m->state_size); - if ((uint64_t) st.st_size < f->fsprg_size) { - r = -ENODATA; - goto finish; - } - - if (!sd_id128_equal(machine, m->machine_id)) { - r = -EHOSTDOWN; - goto finish; - } - - if (le64toh(m->fsprg_start_usec) <= 0 || - le64toh(m->fsprg_interval_usec) <= 0) { - r = -EBADMSG; - goto finish; - } - - f->fsprg_header = mmap(NULL, PAGE_ALIGN(f->fsprg_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (f->fsprg_header == MAP_FAILED) { - f->fsprg_header = NULL; - r = -errno; - goto finish; - } - - r = 0; - -finish: - if (m) - munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader))); - - if (fd >= 0) - close_nointr_nofail(fd); - - free(p); - return r; -} - -static int journal_file_setup_hmac(JournalFile *f) { - gcry_error_t e; - - if (!f->authenticate) - return 0; - - e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); - if (e != 0) - return -ENOTSUP; - - return 0; -} - -static int journal_file_append_first_tag(JournalFile *f) { - int r; - uint64_t p; - - if (!f->authenticate) - return 0; - - log_debug("Calculating first tag..."); - - r = journal_file_hmac_put_header(f); - if (r < 0) - return r; - - p = le64toh(f->header->field_hash_table_offset); - if (p < offsetof(Object, hash_table.items)) - return -EINVAL; - p -= offsetof(Object, hash_table.items); - - r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, p); - if (r < 0) - return r; - - p = le64toh(f->header->data_hash_table_offset); - if (p < offsetof(Object, hash_table.items)) - return -EINVAL; - p -= offsetof(Object, hash_table.items); - - r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, p); - if (r < 0) - return r; - - r = journal_file_append_tag(f); - if (r < 0) - return r; - - return 0; -} - -static int journal_file_object_verify(JournalFile *f, Object *o) { - assert(f); - assert(o); - - /* This does various superficial tests about the length an - * possible field values. It does not follow any references to - * other objects. */ - - switch (o->object.type) { - case OBJECT_DATA: - if (le64toh(o->data.entry_offset) <= 0 || - le64toh(o->data.n_entries) <= 0) - return -EBADMSG; - - if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) - return -EBADMSG; - break; - - case OBJECT_FIELD: - if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) - return -EBADMSG; - break; - - case OBJECT_ENTRY: - if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) - return -EBADMSG; - - if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) - return -EBADMSG; - - if (le64toh(o->entry.seqnum) <= 0 || - le64toh(o->entry.realtime) <= 0) - return -EBADMSG; - - break; - - case OBJECT_DATA_HASH_TABLE: - case OBJECT_FIELD_HASH_TABLE: - if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0) - return -EBADMSG; - - break; - - case OBJECT_ENTRY_ARRAY: - if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0) - return -EBADMSG; - - break; - - case OBJECT_TAG: - if (le64toh(o->object.size) != sizeof(TagObject)) - return -EBADMSG; - break; - } - - return 0; -} - -static void draw_progress(uint64_t p, usec_t *last_usec) { - unsigned n, i, j, k; - usec_t z, x; - - if (!isatty(STDOUT_FILENO)) - return; - - z = now(CLOCK_MONOTONIC); - x = *last_usec; - - if (x != 0 && x + 40 * USEC_PER_MSEC > z) - return; - - *last_usec = z; - - n = (3 * columns()) / 4; - j = (n * (unsigned) p) / 65535ULL; - k = n - j; - - fputs("\r\x1B[?25l", stdout); - - for (i = 0; i < j; i++) - fputs("\xe2\x96\x88", stdout); - - for (i = 0; i < k; i++) - fputs("\xe2\x96\x91", stdout); - - printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU); - - fputs("\r\x1B[?25h", stdout); - fflush(stdout); -} - -static void flush_progress(void) { - unsigned n, i; - - if (!isatty(STDOUT_FILENO)) - return; - - n = (3 * columns()) / 4; - - putchar('\r'); - - for (i = 0; i < n + 5; i++) - putchar(' '); - - putchar('\r'); - fflush(stdout); -} - -static int write_uint64(int fd, uint64_t p) { - ssize_t k; - - k = write(fd, &p, sizeof(p)); - if (k < 0) - return -errno; - if (k != sizeof(p)) - return -EIO; - - return 0; -} - -static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { - uint64_t a, b; - int r; - - assert(m); - assert(fd >= 0); - - /* Bisection ... */ - - a = 0; b = n; - while (a < b) { - uint64_t c, *z; - - c = (a + b) / 2; - - r = mmap_cache_get(m, fd, PROT_READ, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z); - if (r < 0) - return r; - - if (*z == p) - return 1; - - if (p < *z) - b = c; - else - a = c; - } - - return 0; -} - -int journal_file_verify(JournalFile *f, const char *key) { - int r; - Object *o; - uint64_t p = 0; - uint64_t tag_seqnum = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; - sd_id128_t entry_boot_id; - bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; - uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0; - usec_t last_usec = 0; - int data_fd = -1, entry_fd = -1, entry_array_fd = -1; - char data_path[] = "/var/tmp/journal-data-XXXXXX", - entry_path[] = "/var/tmp/journal-entry-XXXXXX", - entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX"; - - assert(f); - - data_fd = mkostemp(data_path, O_CLOEXEC); - if (data_fd < 0) { - log_error("Failed to create data file: %m"); - goto fail; - } - unlink(data_path); - - entry_fd = mkostemp(entry_path, O_CLOEXEC); - if (entry_fd < 0) { - log_error("Failed to create entry file: %m"); - goto fail; - } - unlink(entry_path); - - entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC); - if (entry_array_fd < 0) { - log_error("Failed to create entry array file: %m"); - goto fail; - } - unlink(entry_array_path); - - /* First iteration: we go through all objects, verify the - * superficial structure, headers, hashes. */ - - r = journal_file_hmac_put_header(f); - if (r < 0) { - log_error("Failed to calculate HMAC of header."); - goto fail; - } - - p = le64toh(f->header->header_size); - while (p != 0) { - draw_progress((0x7FFF * p) / le64toh(f->header->tail_object_offset), &last_usec); - - r = journal_file_move_to_object(f, -1, p, &o); - if (r < 0) { - log_error("Invalid object at %llu", (unsigned long long) p); - goto fail; - } - - if (le64toh(f->header->tail_object_offset) < p) { - log_error("Invalid tail object pointer."); - r = -EBADMSG; - goto fail; - } - - n_objects ++; - - r = journal_file_object_verify(f, o); - if (r < 0) { - log_error("Invalid object contents at %llu", (unsigned long long) p); - goto fail; - } - - r = journal_file_hmac_put_object(f, -1, p); - if (r < 0) { - log_error("Failed to calculate HMAC at %llu", (unsigned long long) p); - goto fail; - } - - if (o->object.flags & OBJECT_COMPRESSED && - !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) { - log_error("Compressed object without compression at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - if (o->object.flags & OBJECT_COMPRESSED && - o->object.type != OBJECT_DATA) { - log_error("Compressed non-data object at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - if (o->object.type == OBJECT_TAG) { - - if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) { - log_error("Tag object without authentication at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - if (le64toh(o->tag.seqnum) != tag_seqnum) { - log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - } else if (o->object.type == OBJECT_ENTRY) { - - r = write_uint64(entry_fd, p); - if (r < 0) - goto fail; - - if (!entry_seqnum_set && - le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { - log_error("Head entry sequence number incorrect"); - r = -EBADMSG; - goto fail; - } - - if (entry_seqnum_set && - entry_seqnum >= le64toh(o->entry.seqnum)) { - log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - entry_seqnum = le64toh(o->entry.seqnum); - entry_seqnum_set = true; - - if (entry_monotonic_set && - sd_id128_equal(entry_boot_id, o->entry.boot_id) && - entry_monotonic > le64toh(o->entry.monotonic)) { - log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - entry_monotonic = le64toh(o->entry.monotonic); - entry_boot_id = o->entry.boot_id; - entry_monotonic_set = true; - - if (!entry_realtime_set && - le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { - log_error("Head entry realtime timestamp incorrect"); - r = -EBADMSG; - goto fail; - } - - entry_realtime = le64toh(o->entry.realtime); - entry_realtime_set = true; - - n_entries ++; - } else if (o->object.type == OBJECT_ENTRY_ARRAY) { - - r = write_uint64(entry_array_fd, p); - if (r < 0) - goto fail; - - if (p == le64toh(f->header->entry_array_offset)) { - if (found_main_entry_array) { - log_error("More than one main entry array at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - found_main_entry_array = true; - } - - n_entry_arrays++; - - } else if (o->object.type == OBJECT_DATA) { - - r = write_uint64(data_fd, p); - if (r < 0) - goto fail; - - n_data++; - - } else if (o->object.type == OBJECT_FIELD) - n_fields++; - else if (o->object.type == OBJECT_DATA_HASH_TABLE) { - n_data_hash_tables++; - - if (n_data_hash_tables > 1) { - log_error("More than one data hash table at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || - le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { - log_error("Header fields for data hash table invalid."); - r = -EBADMSG; - goto fail; - } - } else if (o->object.type == OBJECT_FIELD_HASH_TABLE) { - n_field_hash_tables++; - - if (n_field_hash_tables > 1) { - log_error("More than one field hash table at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || - le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { - log_error("Header fields for field hash table invalid."); - r = -EBADMSG; - goto fail; - } - } else if (o->object.type >= _OBJECT_TYPE_MAX) - n_weird ++; - - if (p == le64toh(f->header->tail_object_offset)) - p = 0; - else - p = p + ALIGN64(le64toh(o->object.size)); - } - - if (n_objects != le64toh(f->header->n_objects)) { - log_error("Object number mismatch"); - r = -EBADMSG; - goto fail; - } - - if (n_entries != le64toh(f->header->n_entries)) { - log_error("Entry number mismatch"); - r = -EBADMSG; - goto fail; - } - - if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && - n_data != le64toh(f->header->n_data)) { - log_error("Data number mismatch"); - r = -EBADMSG; - goto fail; - } - - if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && - n_fields != le64toh(f->header->n_fields)) { - log_error("Field number mismatch"); - r = -EBADMSG; - goto fail; - } - - if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && - tag_seqnum != le64toh(f->header->n_tags)) { - log_error("Tag number mismatch"); - r = -EBADMSG; - goto fail; - } - - if (n_data_hash_tables != 1) { - log_error("Missing data hash table"); - r = -EBADMSG; - goto fail; - } - - if (n_field_hash_tables != 1) { - log_error("Missing field hash table"); - r = -EBADMSG; - goto fail; - } - - if (!found_main_entry_array) { - log_error("Missing entry array"); - r = -EBADMSG; - goto fail; - } - - if (entry_seqnum_set && - entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { - log_error("Invalid tail seqnum"); - r = -EBADMSG; - goto fail; - } - - if (entry_monotonic_set && - (!sd_id128_equal(entry_boot_id, f->header->boot_id) || - entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { - log_error("Invalid tail monotonic timestamp"); - r = -EBADMSG; - goto fail; - } - - if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { - log_error("Invalid tail realtime timestamp"); - r = -EBADMSG; - goto fail; - } - - /* Second iteration: we go through all objects again, this - * time verify all pointers. */ - - p = le64toh(f->header->header_size); - while (p != 0) { - draw_progress(0x8000 + (0x7FFF * p) / le64toh(f->header->tail_object_offset), &last_usec); - - r = journal_file_move_to_object(f, -1, p, &o); - if (r < 0) { - log_error("Invalid object at %llu", (unsigned long long) p); - goto fail; - } - - if (o->object.type == OBJECT_ENTRY_ARRAY) { - uint64_t i = 0, n; - - if (le64toh(o->entry_array.next_entry_array_offset) != 0 && - !contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, le64toh(o->entry_array.next_entry_array_offset))) { - log_error("Entry array chains up to invalid next array at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - - n = journal_file_entry_array_n_items(o); - for (i = 0; i < n; i++) { - if (le64toh(o->entry_array.items[i]) != 0 && - !contains_uint64(f->mmap, entry_fd, n_entries, le64toh(o->entry_array.items[i]))) { - - log_error("Entry array points to invalid next array at %llu", (unsigned long long) p); - r = -EBADMSG; - goto fail; - } - } - - } - - r = journal_file_move_to_object(f, -1, p, &o); - if (r < 0) { - log_error("Invalid object at %llu", (unsigned long long) p); - goto fail; - } - - if (p == le64toh(f->header->tail_object_offset)) - p = 0; - else - p = p + ALIGN64(le64toh(o->object.size)); - } - - flush_progress(); - - mmap_cache_close_fd(f->mmap, data_fd); - mmap_cache_close_fd(f->mmap, entry_fd); - mmap_cache_close_fd(f->mmap, entry_array_fd); - - close_nointr_nofail(data_fd); - close_nointr_nofail(entry_fd); - close_nointr_nofail(entry_array_fd); - - return 0; - -fail: - flush_progress(); - - log_error("File corruption detected at %s:%llu (of %llu, %llu%%).", - f->path, - (unsigned long long) p, - (unsigned long long) f->last_stat.st_size, - (unsigned long long) (100 * p / f->last_stat.st_size)); - - if (data_fd >= 0) { - mmap_cache_close_fd(f->mmap, data_fd); - close_nointr_nofail(data_fd); - } - - if (entry_fd >= 0) { - mmap_cache_close_fd(f->mmap, entry_fd); - close_nointr_nofail(entry_fd); - } - - if (entry_array_fd >= 0) { - mmap_cache_close_fd(f->mmap, entry_array_fd); - close_nointr_nofail(entry_array_fd); - } - - return r; -} - -void journal_file_dump(JournalFile *f) { - Object *o; - int r; - uint64_t p; - - assert(f); - - journal_file_print_header(f); - - p = le64toh(f->header->header_size); - while (p != 0) { - r = journal_file_move_to_object(f, -1, p, &o); - if (r < 0) - goto fail; - - switch (o->object.type) { - - case OBJECT_UNUSED: - printf("Type: OBJECT_UNUSED\n"); - break; - - case OBJECT_DATA: - printf("Type: OBJECT_DATA\n"); - break; - - case OBJECT_ENTRY: - printf("Type: OBJECT_ENTRY %llu %llu %llu\n", - (unsigned long long) le64toh(o->entry.seqnum), - (unsigned long long) le64toh(o->entry.monotonic), - (unsigned long long) le64toh(o->entry.realtime)); - break; - - case OBJECT_FIELD_HASH_TABLE: - printf("Type: OBJECT_FIELD_HASH_TABLE\n"); - break; - - case OBJECT_DATA_HASH_TABLE: - printf("Type: OBJECT_DATA_HASH_TABLE\n"); - break; - - case OBJECT_ENTRY_ARRAY: - printf("Type: OBJECT_ENTRY_ARRAY\n"); - break; - - case OBJECT_TAG: - printf("Type: OBJECT_TAG %llu\n", - (unsigned long long) le64toh(o->tag.seqnum)); - break; - } - - if (o->object.flags & OBJECT_COMPRESSED) - printf("Flags: COMPRESSED\n"); - - if (p == le64toh(f->header->tail_object_offset)) - p = 0; - else - p = p + ALIGN64(le64toh(o->object.size)); - } - - return; -fail: - log_error("File corrupt"); -} - -void journal_file_print_header(JournalFile *f) { - char a[33], b[33], c[33]; - char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX]; - - assert(f); - - printf("File Path: %s\n" - "File ID: %s\n" - "Machine ID: %s\n" - "Boot ID: %s\n" - "Sequential Number ID: %s\n" - "State: %s\n" - "Compatible Flags:%s%s\n" - "Incompatible Flags:%s%s\n" - "Header size: %llu\n" - "Arena size: %llu\n" - "Data Hash Table Size: %llu\n" - "Field Hash Table Size: %llu\n" - "Objects: %llu\n" - "Entry Objects: %llu\n" - "Rotate Suggested: %s\n" - "Head Sequential Number: %llu\n" - "Tail Sequential Number: %llu\n" - "Head Realtime Timestamp: %s\n" - "Tail Realtime Timestamp: %s\n", - f->path, - sd_id128_to_string(f->header->file_id, a), - sd_id128_to_string(f->header->machine_id, b), - sd_id128_to_string(f->header->boot_id, c), - sd_id128_to_string(f->header->seqnum_id, c), - f->header->state == STATE_OFFLINE ? "offline" : - f->header->state == STATE_ONLINE ? "online" : - f->header->state == STATE_ARCHIVED ? "archived" : "unknown", - (f->header->compatible_flags & HEADER_COMPATIBLE_AUTHENTICATED) ? " AUTHENTICATED" : "", - (f->header->compatible_flags & ~HEADER_COMPATIBLE_AUTHENTICATED) ? " ???" : "", - (f->header->incompatible_flags & HEADER_INCOMPATIBLE_COMPRESSED) ? " COMPRESSED" : "", - (f->header->incompatible_flags & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "", - (unsigned long long) le64toh(f->header->header_size), - (unsigned long long) le64toh(f->header->arena_size), - (unsigned long long) le64toh(f->header->data_hash_table_size) / sizeof(HashItem), - (unsigned long long) le64toh(f->header->field_hash_table_size) / sizeof(HashItem), - (unsigned long long) le64toh(f->header->n_objects), - (unsigned long long) le64toh(f->header->n_entries), - yes_no(journal_file_rotate_suggested(f)), - (unsigned long long) le64toh(f->header->head_entry_seqnum), - (unsigned long long) le64toh(f->header->tail_entry_seqnum), - format_timestamp(x, sizeof(x), le64toh(f->header->head_entry_realtime)), - format_timestamp(y, sizeof(y), le64toh(f->header->tail_entry_realtime))); - - if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) - printf("Data Objects: %llu\n" - "Data Hash Table Fill: %.1f%%\n", - (unsigned long long) le64toh(f->header->n_data), - 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)))); - - if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) - printf("Field Objects: %llu\n" - "Field Hash Table Fill: %.1f%%\n", - (unsigned long long) le64toh(f->header->n_fields), - 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)))); -} - -int journal_file_open( - const char *fname, - int flags, - mode_t mode, - bool compress, - bool authenticate, - JournalMetrics *metrics, - MMapCache *mmap_cache, - JournalFile *template, - JournalFile **ret) { - - JournalFile *f; - int r; - bool newly_created = false; - - assert(fname); - - if ((flags & O_ACCMODE) != O_RDONLY && - (flags & O_ACCMODE) != O_RDWR) - return -EINVAL; - - if (!endswith(fname, ".journal")) - return -EINVAL; - - f = new0(JournalFile, 1); - if (!f) - return -ENOMEM; - - f->fd = -1; - f->mode = mode; - - f->flags = flags; - f->prot = prot_from_flags(flags); - f->writable = (flags & O_ACCMODE) != O_RDONLY; - f->compress = compress; - f->authenticate = authenticate; - - if (mmap_cache) - f->mmap = mmap_cache_ref(mmap_cache); - else { - /* One context for each type, plus the zeroth catchall - * context. One fd for the file plus one for each type - * (which we need during verification */ - f->mmap = mmap_cache_new(_OBJECT_TYPE_MAX, 1 + _OBJECT_TYPE_MAX); - if (!f->mmap) { - r = -ENOMEM; - goto fail; - } - } - - f->path = strdup(fname); - if (!f->path) { - r = -ENOMEM; - goto fail; - } - - f->fd = open(f->path, f->flags|O_CLOEXEC, f->mode); - if (f->fd < 0) { - r = -errno; - goto fail; - } - - if (fstat(f->fd, &f->last_stat) < 0) { - r = -errno; - goto fail; - } - - if (f->last_stat.st_size == 0 && f->writable) { - newly_created = true; - - /* Try to load the FSPRG state, and if we can't, then - * just don't do authentication */ - r = journal_file_load_fsprg(f); - if (r < 0) - f->authenticate = false; - - r = journal_file_init_header(f, template); - if (r < 0) - goto fail; - - if (fstat(f->fd, &f->last_stat) < 0) { - r = -errno; - goto fail; - } - } - - if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) { - r = -EIO; - goto fail; - } - - f->header = mmap(NULL, PAGE_ALIGN(sizeof(Header)), prot_from_flags(flags), MAP_SHARED, f->fd, 0); - if (f->header == MAP_FAILED) { - f->header = NULL; - r = -errno; - goto fail; - } - - if (!newly_created) { - r = journal_file_verify_header(f); - if (r < 0) - goto fail; - } - - if (!newly_created && f->writable) { - r = journal_file_load_fsprg(f); - if (r < 0) - goto fail; - } + if (!newly_created && f->writable) { + r = journal_file_load_fsprg(f); + if (r < 0) + goto fail; + } if (f->writable) { if (metrics) { @@ -3139,203 +2199,6 @@ int journal_file_open_reliably( return journal_file_open(fname, flags, mode, compress, authenticate, metrics, mmap, template, ret); } -struct vacuum_info { - off_t usage; - char *filename; - - uint64_t realtime; - sd_id128_t seqnum_id; - uint64_t seqnum; - - bool have_seqnum; -}; - -static int vacuum_compare(const void *_a, const void *_b) { - const struct vacuum_info *a, *b; - - a = _a; - b = _b; - - if (a->have_seqnum && b->have_seqnum && - sd_id128_equal(a->seqnum_id, b->seqnum_id)) { - if (a->seqnum < b->seqnum) - return -1; - else if (a->seqnum > b->seqnum) - return 1; - else - return 0; - } - - if (a->realtime < b->realtime) - return -1; - else if (a->realtime > b->realtime) - return 1; - else if (a->have_seqnum && b->have_seqnum) - return memcmp(&a->seqnum_id, &b->seqnum_id, 16); - else - return strcmp(a->filename, b->filename); -} - -int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free) { - DIR *d; - int r = 0; - struct vacuum_info *list = NULL; - unsigned n_list = 0, n_allocated = 0, i; - uint64_t sum = 0; - - assert(directory); - - if (max_use <= 0) - return 0; - - d = opendir(directory); - if (!d) - return -errno; - - for (;;) { - int k; - struct dirent buf, *de; - size_t q; - struct stat st; - char *p; - unsigned long long seqnum = 0, realtime; - sd_id128_t seqnum_id; - bool have_seqnum; - - k = readdir_r(d, &buf, &de); - if (k != 0) { - r = -k; - goto finish; - } - - if (!de) - break; - - if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) - continue; - - if (!S_ISREG(st.st_mode)) - continue; - - q = strlen(de->d_name); - - if (endswith(de->d_name, ".journal")) { - - /* Vacuum archived files */ - - if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) - continue; - - if (de->d_name[q-8-16-1] != '-' || - de->d_name[q-8-16-1-16-1] != '-' || - de->d_name[q-8-16-1-16-1-32-1] != '@') - continue; - - p = strdup(de->d_name); - if (!p) { - r = -ENOMEM; - goto finish; - } - - de->d_name[q-8-16-1-16-1] = 0; - if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { - free(p); - continue; - } - - if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { - free(p); - continue; - } - - have_seqnum = true; - - } else if (endswith(de->d_name, ".journal~")) { - unsigned long long tmp; - - /* Vacuum corrupted files */ - - if (q < 1 + 16 + 1 + 16 + 8 + 1) - continue; - - if (de->d_name[q-1-8-16-1] != '-' || - de->d_name[q-1-8-16-1-16-1] != '@') - continue; - - p = strdup(de->d_name); - if (!p) { - r = -ENOMEM; - goto finish; - } - - if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { - free(p); - continue; - } - - have_seqnum = false; - } else - continue; - - if (n_list >= n_allocated) { - struct vacuum_info *j; - - n_allocated = MAX(n_allocated * 2U, 8U); - j = realloc(list, n_allocated * sizeof(struct vacuum_info)); - if (!j) { - free(p); - r = -ENOMEM; - goto finish; - } - - list = j; - } - - list[n_list].filename = p; - list[n_list].usage = 512UL * (uint64_t) st.st_blocks; - list[n_list].seqnum = seqnum; - list[n_list].realtime = realtime; - list[n_list].seqnum_id = seqnum_id; - list[n_list].have_seqnum = have_seqnum; - - sum += list[n_list].usage; - - n_list ++; - } - - if (n_list > 0) - qsort(list, n_list, sizeof(struct vacuum_info), vacuum_compare); - - for(i = 0; i < n_list; i++) { - struct statvfs ss; - - if (fstatvfs(dirfd(d), &ss) < 0) { - r = -errno; - goto finish; - } - - if (sum <= max_use && - (uint64_t) ss.f_bavail * (uint64_t) ss.f_bsize >= min_free) - break; - - if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { - log_info("Deleted archived journal %s/%s.", directory, list[i].filename); - sum -= list[i].usage; - } else if (errno != ENOENT) - log_warning("Failed to delete %s/%s: %m", directory, list[i].filename); - } - -finish: - for (i = 0; i < n_list; i++) - free(list[i].filename); - - free(list); - - if (d) - closedir(d); - - return r; -} int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) { uint64_t i, n; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 0305c97134..aba3d9a9bd 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -107,10 +107,17 @@ int journal_file_open_reliably( JournalFile *template, JournalFile **ret); +#define ALIGN64(x) (((x) + 7ULL) & ~7ULL) + +#define JOURNAL_HEADER_CONTAINS(h, field) \ + (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) + int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret); uint64_t journal_file_entry_n_items(Object *o); +uint64_t journal_file_entry_array_n_items(Object *o); +int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset); int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const struct iovec iovec[], unsigned n_iovec, uint64_t *seqno, Object **ret, uint64_t *offset); int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); @@ -138,8 +145,6 @@ void journal_file_print_header(JournalFile *f); int journal_file_rotate(JournalFile **f, bool compress, bool authenticate); -int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); - void journal_file_post_change(JournalFile *f); void journal_default_metrics(JournalMetrics *m, int fd); @@ -148,7 +153,3 @@ int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t * int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); bool journal_file_rotate_suggested(JournalFile *f); - -int journal_file_append_tag(JournalFile *f); - -int journal_file_verify(JournalFile *f, const char *key); diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c new file mode 100644 index 0000000000..ff2cd3306d --- /dev/null +++ b/src/journal/journal-vacuum.c @@ -0,0 +1,230 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "journal-def.h" +#include "journal-file.h" +#include "journal-vacuum.h" +#include "sd-id128.h" +#include "util.h" + +struct vacuum_info { + off_t usage; + char *filename; + + uint64_t realtime; + sd_id128_t seqnum_id; + uint64_t seqnum; + + bool have_seqnum; +}; + +static int vacuum_compare(const void *_a, const void *_b) { + const struct vacuum_info *a, *b; + + a = _a; + b = _b; + + if (a->have_seqnum && b->have_seqnum && + sd_id128_equal(a->seqnum_id, b->seqnum_id)) { + if (a->seqnum < b->seqnum) + return -1; + else if (a->seqnum > b->seqnum) + return 1; + else + return 0; + } + + if (a->realtime < b->realtime) + return -1; + else if (a->realtime > b->realtime) + return 1; + else if (a->have_seqnum && b->have_seqnum) + return memcmp(&a->seqnum_id, &b->seqnum_id, 16); + else + return strcmp(a->filename, b->filename); +} + +int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free) { + DIR *d; + int r = 0; + struct vacuum_info *list = NULL; + unsigned n_list = 0, n_allocated = 0, i; + uint64_t sum = 0; + + assert(directory); + + if (max_use <= 0) + return 0; + + d = opendir(directory); + if (!d) + return -errno; + + for (;;) { + int k; + struct dirent buf, *de; + size_t q; + struct stat st; + char *p; + unsigned long long seqnum = 0, realtime; + sd_id128_t seqnum_id; + bool have_seqnum; + + k = readdir_r(d, &buf, &de); + if (k != 0) { + r = -k; + goto finish; + } + + if (!de) + break; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) + continue; + + if (!S_ISREG(st.st_mode)) + continue; + + q = strlen(de->d_name); + + if (endswith(de->d_name, ".journal")) { + + /* Vacuum archived files */ + + if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) + continue; + + if (de->d_name[q-8-16-1] != '-' || + de->d_name[q-8-16-1-16-1] != '-' || + de->d_name[q-8-16-1-16-1-32-1] != '@') + continue; + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + de->d_name[q-8-16-1-16-1] = 0; + if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { + free(p); + continue; + } + + if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { + free(p); + continue; + } + + have_seqnum = true; + + } else if (endswith(de->d_name, ".journal~")) { + unsigned long long tmp; + + /* Vacuum corrupted files */ + + if (q < 1 + 16 + 1 + 16 + 8 + 1) + continue; + + if (de->d_name[q-1-8-16-1] != '-' || + de->d_name[q-1-8-16-1-16-1] != '@') + continue; + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { + free(p); + continue; + } + + have_seqnum = false; + } else + continue; + + if (n_list >= n_allocated) { + struct vacuum_info *j; + + n_allocated = MAX(n_allocated * 2U, 8U); + j = realloc(list, n_allocated * sizeof(struct vacuum_info)); + if (!j) { + free(p); + r = -ENOMEM; + goto finish; + } + + list = j; + } + + list[n_list].filename = p; + list[n_list].usage = 512UL * (uint64_t) st.st_blocks; + list[n_list].seqnum = seqnum; + list[n_list].realtime = realtime; + list[n_list].seqnum_id = seqnum_id; + list[n_list].have_seqnum = have_seqnum; + + sum += list[n_list].usage; + + n_list ++; + } + + if (n_list > 0) + qsort(list, n_list, sizeof(struct vacuum_info), vacuum_compare); + + for(i = 0; i < n_list; i++) { + struct statvfs ss; + + if (fstatvfs(dirfd(d), &ss) < 0) { + r = -errno; + goto finish; + } + + if (sum <= max_use && + (uint64_t) ss.f_bavail * (uint64_t) ss.f_bsize >= min_free) + break; + + if (unlinkat(dirfd(d), list[i].filename, 0) >= 0) { + log_info("Deleted archived journal %s/%s.", directory, list[i].filename); + sum -= list[i].usage; + } else if (errno != ENOENT) + log_warning("Failed to delete %s/%s: %m", directory, list[i].filename); + } + +finish: + for (i = 0; i < n_list; i++) + free(list[i].filename); + + free(list); + + if (d) + closedir(d); + + return r; +} diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h new file mode 100644 index 0000000000..9841d72de8 --- /dev/null +++ b/src/journal/journal-vacuum.h @@ -0,0 +1,26 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t min_free); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c new file mode 100644 index 0000000000..f3182e876e --- /dev/null +++ b/src/journal/journal-verify.c @@ -0,0 +1,558 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "util.h" +#include "macro.h" +#include "journal-def.h" +#include "journal-file.h" +#include "journal-authenticate.h" +#include "journal-verify.h" + +static int journal_file_object_verify(JournalFile *f, Object *o) { + assert(f); + assert(o); + + /* This does various superficial tests about the length an + * possible field values. It does not follow any references to + * other objects. */ + + switch (o->object.type) { + case OBJECT_DATA: + if (le64toh(o->data.entry_offset) <= 0 || + le64toh(o->data.n_entries) <= 0) + return -EBADMSG; + + if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) + return -EBADMSG; + break; + + case OBJECT_FIELD: + if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) + return -EBADMSG; + break; + + case OBJECT_ENTRY: + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) + return -EBADMSG; + + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) + return -EBADMSG; + + if (le64toh(o->entry.seqnum) <= 0 || + le64toh(o->entry.realtime) <= 0) + return -EBADMSG; + + break; + + case OBJECT_DATA_HASH_TABLE: + case OBJECT_FIELD_HASH_TABLE: + if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0) + return -EBADMSG; + + break; + + case OBJECT_ENTRY_ARRAY: + if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0) + return -EBADMSG; + + break; + + case OBJECT_TAG: + if (le64toh(o->object.size) != sizeof(TagObject)) + return -EBADMSG; + break; + } + + return 0; +} + +static void draw_progress(uint64_t p, usec_t *last_usec) { + unsigned n, i, j, k; + usec_t z, x; + + if (!isatty(STDOUT_FILENO)) + return; + + z = now(CLOCK_MONOTONIC); + x = *last_usec; + + if (x != 0 && x + 40 * USEC_PER_MSEC > z) + return; + + *last_usec = z; + + n = (3 * columns()) / 4; + j = (n * (unsigned) p) / 65535ULL; + k = n - j; + + fputs("\r\x1B[?25l", stdout); + + for (i = 0; i < j; i++) + fputs("\xe2\x96\x88", stdout); + + for (i = 0; i < k; i++) + fputs("\xe2\x96\x91", stdout); + + printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU); + + fputs("\r\x1B[?25h", stdout); + fflush(stdout); +} + +static void flush_progress(void) { + unsigned n, i; + + if (!isatty(STDOUT_FILENO)) + return; + + n = (3 * columns()) / 4; + + putchar('\r'); + + for (i = 0; i < n + 5; i++) + putchar(' '); + + putchar('\r'); + fflush(stdout); +} + +static int write_uint64(int fd, uint64_t p) { + ssize_t k; + + k = write(fd, &p, sizeof(p)); + if (k < 0) + return -errno; + if (k != sizeof(p)) + return -EIO; + + return 0; +} + +static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) { + uint64_t a, b; + int r; + + assert(m); + assert(fd >= 0); + + /* Bisection ... */ + + a = 0; b = n; + while (a < b) { + uint64_t c, *z; + + c = (a + b) / 2; + + r = mmap_cache_get(m, fd, PROT_READ, 0, c * sizeof(uint64_t), sizeof(uint64_t), (void **) &z); + if (r < 0) + return r; + + if (*z == p) + return 1; + + if (p < *z) + b = c; + else + a = c; + } + + return 0; +} + +int journal_file_verify(JournalFile *f, const char *key) { + int r; + Object *o; + uint64_t p = 0; + uint64_t tag_seqnum = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; + sd_id128_t entry_boot_id; + bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; + uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0; + usec_t last_usec = 0; + int data_fd = -1, entry_fd = -1, entry_array_fd = -1; + char data_path[] = "/var/tmp/journal-data-XXXXXX", + entry_path[] = "/var/tmp/journal-entry-XXXXXX", + entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX"; + + assert(f); + + data_fd = mkostemp(data_path, O_CLOEXEC); + if (data_fd < 0) { + log_error("Failed to create data file: %m"); + goto fail; + } + unlink(data_path); + + entry_fd = mkostemp(entry_path, O_CLOEXEC); + if (entry_fd < 0) { + log_error("Failed to create entry file: %m"); + goto fail; + } + unlink(entry_path); + + entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC); + if (entry_array_fd < 0) { + log_error("Failed to create entry array file: %m"); + goto fail; + } + unlink(entry_array_path); + + /* First iteration: we go through all objects, verify the + * superficial structure, headers, hashes. */ + + r = journal_file_hmac_put_header(f); + if (r < 0) { + log_error("Failed to calculate HMAC of header."); + goto fail; + } + + p = le64toh(f->header->header_size); + while (p != 0) { + draw_progress((0x7FFF * p) / le64toh(f->header->tail_object_offset), &last_usec); + + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) { + log_error("Invalid object at %llu", (unsigned long long) p); + goto fail; + } + + if (le64toh(f->header->tail_object_offset) < p) { + log_error("Invalid tail object pointer."); + r = -EBADMSG; + goto fail; + } + + n_objects ++; + + r = journal_file_object_verify(f, o); + if (r < 0) { + log_error("Invalid object contents at %llu", (unsigned long long) p); + goto fail; + } + + r = journal_file_hmac_put_object(f, -1, p); + if (r < 0) { + log_error("Failed to calculate HMAC at %llu", (unsigned long long) p); + goto fail; + } + + if (o->object.flags & OBJECT_COMPRESSED && + !(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED)) { + log_error("Compressed object without compression at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (o->object.flags & OBJECT_COMPRESSED && + o->object.type != OBJECT_DATA) { + log_error("Compressed non-data object at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (o->object.type == OBJECT_TAG) { + + if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) { + log_error("Tag object without authentication at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(o->tag.seqnum) != tag_seqnum) { + log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + } else if (o->object.type == OBJECT_ENTRY) { + + r = write_uint64(entry_fd, p); + if (r < 0) + goto fail; + + if (!entry_seqnum_set && + le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { + log_error("Head entry sequence number incorrect"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum >= le64toh(o->entry.seqnum)) { + log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + entry_seqnum = le64toh(o->entry.seqnum); + entry_seqnum_set = true; + + if (entry_monotonic_set && + sd_id128_equal(entry_boot_id, o->entry.boot_id) && + entry_monotonic > le64toh(o->entry.monotonic)) { + log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + entry_monotonic = le64toh(o->entry.monotonic); + entry_boot_id = o->entry.boot_id; + entry_monotonic_set = true; + + if (!entry_realtime_set && + le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { + log_error("Head entry realtime timestamp incorrect"); + r = -EBADMSG; + goto fail; + } + + entry_realtime = le64toh(o->entry.realtime); + entry_realtime_set = true; + + n_entries ++; + } else if (o->object.type == OBJECT_ENTRY_ARRAY) { + + r = write_uint64(entry_array_fd, p); + if (r < 0) + goto fail; + + if (p == le64toh(f->header->entry_array_offset)) { + if (found_main_entry_array) { + log_error("More than one main entry array at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + found_main_entry_array = true; + } + + n_entry_arrays++; + + } else if (o->object.type == OBJECT_DATA) { + + r = write_uint64(data_fd, p); + if (r < 0) + goto fail; + + n_data++; + + } else if (o->object.type == OBJECT_FIELD) + n_fields++; + else if (o->object.type == OBJECT_DATA_HASH_TABLE) { + n_data_hash_tables++; + + if (n_data_hash_tables > 1) { + log_error("More than one data hash table at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + log_error("Header fields for data hash table invalid."); + r = -EBADMSG; + goto fail; + } + } else if (o->object.type == OBJECT_FIELD_HASH_TABLE) { + n_field_hash_tables++; + + if (n_field_hash_tables > 1) { + log_error("More than one field hash table at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + log_error("Header fields for field hash table invalid."); + r = -EBADMSG; + goto fail; + } + } else if (o->object.type >= _OBJECT_TYPE_MAX) + n_weird ++; + + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } + + if (n_objects != le64toh(f->header->n_objects)) { + log_error("Object number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (n_entries != le64toh(f->header->n_entries)) { + log_error("Entry number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && + n_data != le64toh(f->header->n_data)) { + log_error("Data number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && + n_fields != le64toh(f->header->n_fields)) { + log_error("Field number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && + tag_seqnum != le64toh(f->header->n_tags)) { + log_error("Tag number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (n_data_hash_tables != 1) { + log_error("Missing data hash table"); + r = -EBADMSG; + goto fail; + } + + if (n_field_hash_tables != 1) { + log_error("Missing field hash table"); + r = -EBADMSG; + goto fail; + } + + if (!found_main_entry_array) { + log_error("Missing entry array"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { + log_error("Invalid tail seqnum"); + r = -EBADMSG; + goto fail; + } + + if (entry_monotonic_set && + (!sd_id128_equal(entry_boot_id, f->header->boot_id) || + entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { + log_error("Invalid tail monotonic timestamp"); + r = -EBADMSG; + goto fail; + } + + if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { + log_error("Invalid tail realtime timestamp"); + r = -EBADMSG; + goto fail; + } + + /* Second iteration: we go through all objects again, this + * time verify all pointers. */ + + p = le64toh(f->header->header_size); + while (p != 0) { + draw_progress(0x8000 + (0x7FFF * p) / le64toh(f->header->tail_object_offset), &last_usec); + + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) { + log_error("Invalid object at %llu", (unsigned long long) p); + goto fail; + } + + if (o->object.type == OBJECT_ENTRY_ARRAY) { + uint64_t i = 0, n; + + if (le64toh(o->entry_array.next_entry_array_offset) != 0 && + !contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, le64toh(o->entry_array.next_entry_array_offset))) { + log_error("Entry array chains up to invalid next array at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + n = journal_file_entry_array_n_items(o); + for (i = 0; i < n; i++) { + if (le64toh(o->entry_array.items[i]) != 0 && + !contains_uint64(f->mmap, entry_fd, n_entries, le64toh(o->entry_array.items[i]))) { + + log_error("Entry array points to invalid next array at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + } + + } + + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) { + log_error("Invalid object at %llu", (unsigned long long) p); + goto fail; + } + + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } + + flush_progress(); + + mmap_cache_close_fd(f->mmap, data_fd); + mmap_cache_close_fd(f->mmap, entry_fd); + mmap_cache_close_fd(f->mmap, entry_array_fd); + + close_nointr_nofail(data_fd); + close_nointr_nofail(entry_fd); + close_nointr_nofail(entry_array_fd); + + return 0; + +fail: + flush_progress(); + + log_error("File corruption detected at %s:%llu (of %llu, %llu%%).", + f->path, + (unsigned long long) p, + (unsigned long long) f->last_stat.st_size, + (unsigned long long) (100 * p / f->last_stat.st_size)); + + if (data_fd >= 0) { + mmap_cache_close_fd(f->mmap, data_fd); + close_nointr_nofail(data_fd); + } + + if (entry_fd >= 0) { + mmap_cache_close_fd(f->mmap, entry_fd); + close_nointr_nofail(entry_fd); + } + + if (entry_array_fd >= 0) { + mmap_cache_close_fd(f->mmap, entry_array_fd); + close_nointr_nofail(entry_array_fd); + } + + return r; +} diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h new file mode 100644 index 0000000000..3ebdd5e7f2 --- /dev/null +++ b/src/journal/journal-verify.h @@ -0,0 +1,26 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2011 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "journal-file.h" + +int journal_file_verify(JournalFile *f, const char *key); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 8e09ff115a..a70de0684e 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -43,6 +43,7 @@ #include "journal-internal.h" #include "fsprg.h" #include "journal-def.h" +#include "journal-verify.h" #define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE) diff --git a/src/journal/journald.c b/src/journal/journald.c index 384ed90568..d431953f07 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -47,6 +47,7 @@ #include "list.h" #include "journal-rate-limit.h" #include "journal-internal.h" +#include "journal-vacuum.h" #include "conf-parser.h" #include "journald.h" #include "virt.h" diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c new file mode 100644 index 0000000000..bada498fab --- /dev/null +++ b/src/journal/test-journal-verify.c @@ -0,0 +1,78 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "util.h" +#include "log.h" +#include "journal-file.h" +#include "journal-verify.h" + +#define N_ENTRIES 6000 +#define RANDOM_RANGE 77 + +int main(int argc, char *argv[]) { + char t[] = "/tmp/journal-XXXXXX"; + unsigned n; + JournalFile *f; + + log_set_max_level(LOG_DEBUG); + + assert_se(mkdtemp(t)); + assert_se(chdir(t) >= 0); + + log_info("Generating..."); + + assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0); + + for (n = 0; n < N_ENTRIES; n++) { + struct iovec iovec; + struct dual_timestamp ts; + char *test; + + dual_timestamp_get(&ts); + + assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE)); + + iovec.iov_base = (void*) test; + iovec.iov_len = strlen(test); + + assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); + + free(test); + } + + journal_file_close(f); + + log_info("Verifying..."); + + assert_se(journal_file_open("test.journal", O_RDONLY, 0666, false, false, NULL, NULL, NULL, &f) == 0); + assert_se(journal_file_verify(f, NULL) >= 0); + journal_file_close(f); + + log_info("Exiting..."); + + assert_se(rm_rf_dangerous(t, false, true, false) >= 0); + + return 0; +} diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 2fd19a755b..05bb2ea8ed 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -24,8 +24,10 @@ #include -#include "journal-file.h" #include "log.h" +#include "journal-file.h" +#include "journal-authenticate.h" +#include "journal-vacuum.h" int main(int argc, char *argv[]) { dual_timestamp ts; -- cgit v1.2.3-54-g00ecf From 4da416aa20b956571d74720bc91222881443e24b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Aug 2012 02:14:34 +0200 Subject: journalctl: add --verify-seed= switch to specify seed value --- src/journal/journal-authenticate.c | 6 +++ src/journal/journal-authenticate.h | 5 ++ src/journal/journalctl.c | 95 ++++++++++++++++++++++---------------- 3 files changed, 65 insertions(+), 41 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index 827e4e4fb9..5a0314b4f6 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -432,3 +432,9 @@ int journal_file_append_first_tag(JournalFile *f) { return 0; } + +bool journal_file_fsprg_enabled(JournalFile *f) { + assert(f); + + return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED); +} diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h index c991b22e4a..566d7a81a9 100644 --- a/src/journal/journal-authenticate.h +++ b/src/journal/journal-authenticate.h @@ -21,6 +21,9 @@ along with systemd; If not, see . ***/ +#include +#include + #include "journal-file.h" int journal_file_append_tag(JournalFile *f); @@ -33,3 +36,5 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); int journal_file_load_fsprg(JournalFile *f); int journal_file_setup_hmac(JournalFile *f); + +bool journal_file_fsprg_enabled(JournalFile *f); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index a70de0684e..3d274c8eb5 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -41,9 +41,10 @@ #include "logs-show.h" #include "strv.h" #include "journal-internal.h" -#include "fsprg.h" #include "journal-def.h" #include "journal-verify.h" +#include "journal-authenticate.h" +#include "fsprg.h" #define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -58,6 +59,7 @@ static bool arg_local = false; static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; +static const char *arg_verify_seed = NULL; static enum { ACTION_SHOW, @@ -71,25 +73,26 @@ static int help(void) { printf("%s [OPTIONS...] [MATCH]\n\n" "Send control commands to or query the journal.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " -a --all Show all fields, including long and unprintable\n" - " -f --follow Follow journal\n" - " -n --lines=INTEGER Journal entries to show\n" - " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, cat)\n" - " -q --quiet Don't show privilege warning\n" - " -l --local Only local entries\n" - " -b --this-boot Show data only from current boot\n" - " -D --directory=PATH Show journal files from directory\n" - " -p --priority=RANGE Show only messages within the specified priority range\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -a --all Show all fields, including long and unprintable\n" + " -f --follow Follow journal\n" + " -n --lines=INTEGER Journal entries to show\n" + " --no-tail Show all lines, even in follow mode\n" + " -o --output=STRING Change journal output mode (short, short-monotonic,\n" + " verbose, export, json, cat)\n" + " -q --quiet Don't show privilege warning\n" + " -l --local Only local entries\n" + " -b --this-boot Show data only from current boot\n" + " -D --directory=PATH Show journal files from directory\n" + " -p --priority=RANGE Show only messages within the specified priority range\n\n" "Commands:\n" - " --new-id128 Generate a new 128 Bit ID\n" - " --header Show journal header information\n" - " --setup-keys Generate new FSPRG key pair\n" - " --verify Verify journal file consistency\n", + " --new-id128 Generate a new 128 Bit ID\n" + " --header Show journal header information\n" + " --verify Verify journal file consistency\n" + " --verify-seed=SEED Specify FSPRG seed for verification\n" + " --setup-keys Generate new FSPRG key and seed\n", program_invocation_short_name); return 0; @@ -104,28 +107,30 @@ static int parse_argv(int argc, char *argv[]) { ARG_NEW_ID128, ARG_HEADER, ARG_SETUP_KEYS, - ARG_VERIFY + ARG_VERIFY, + ARG_VERIFY_SEED }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version" , no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "follow", no_argument, NULL, 'f' }, - { "output", required_argument, NULL, 'o' }, - { "all", no_argument, NULL, 'a' }, - { "lines", required_argument, NULL, 'n' }, - { "no-tail", no_argument, NULL, ARG_NO_TAIL }, - { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, - { "quiet", no_argument, NULL, 'q' }, - { "local", no_argument, NULL, 'l' }, - { "this-boot", no_argument, NULL, 'b' }, - { "directory", required_argument, NULL, 'D' }, - { "header", no_argument, NULL, ARG_HEADER }, - { "priority", no_argument, NULL, 'p' }, - { "setup-keys",no_argument, NULL, ARG_SETUP_KEYS}, - { "verify", no_argument, NULL, ARG_VERIFY }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "follow", no_argument, NULL, 'f' }, + { "output", required_argument, NULL, 'o' }, + { "all", no_argument, NULL, 'a' }, + { "lines", required_argument, NULL, 'n' }, + { "no-tail", no_argument, NULL, ARG_NO_TAIL }, + { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, + { "quiet", no_argument, NULL, 'q' }, + { "local", no_argument, NULL, 'l' }, + { "this-boot", no_argument, NULL, 'b' }, + { "directory", required_argument, NULL, 'D' }, + { "header", no_argument, NULL, ARG_HEADER }, + { "priority", no_argument, NULL, 'p' }, + { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, + { "verify", no_argument, NULL, ARG_VERIFY }, + { "verify-seed", required_argument, NULL, ARG_VERIFY_SEED }, + { NULL, 0, NULL, 0 } }; int c, r; @@ -212,6 +217,11 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_VERIFY; break; + case ARG_VERIFY_SEED: + arg_action = ACTION_VERIFY; + arg_verify_seed = optarg; + break; + case 'p': { const char *dots; @@ -541,8 +551,8 @@ static int setup_keys(void) { fprintf(stderr, "\n" "The new key pair has been generated. The evolving key has been written to the\n" - "following file. It will be used to protect local journal files. This file does\n" - "not need to be kept secret. It should not be used on multiple hosts.\n" + "following file. It will be used to protect local journal files. This file\n" + "should be kept secret. It should not be used on multiple hosts.\n" "\n" "\t%s\n" "\n" @@ -591,7 +601,10 @@ static int verify(sd_journal *j) { HASHMAP_FOREACH(f, j->files, i) { int k; - k = journal_file_verify(f, NULL); + if (!arg_verify_seed && journal_file_fsprg_enabled(f)) + log_warning("Journal file %s has authentication enabled but verification seed has not been passed using --verify-seed=.", f->path); + + k = journal_file_verify(f, arg_verify_seed); if (k < 0) { log_warning("FAIL: %s (%s)", f->path, strerror(-k)); r = -r; -- cgit v1.2.3-54-g00ecf From 56e81f7ca8276e40f8c88c4c30713a5b54009613 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Aug 2012 21:00:34 +0200 Subject: journalctl: immeidately terminate on invalid seed --- src/journal/journal-verify.c | 2 +- src/journal/journalctl.c | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index f6cec1eb52..6871433402 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -667,7 +667,7 @@ int journal_file_verify(JournalFile *f, const char *seed) { r = journal_file_parse_seed(f, seed); if (r < 0) { log_error("Failed to parse seed."); - goto fail; + return r; } } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 3d274c8eb5..25e441b022 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -601,13 +601,18 @@ static int verify(sd_journal *j) { HASHMAP_FOREACH(f, j->files, i) { int k; +#ifdef HAVE_GCRYPT if (!arg_verify_seed && journal_file_fsprg_enabled(f)) log_warning("Journal file %s has authentication enabled but verification seed has not been passed using --verify-seed=.", f->path); +#endif k = journal_file_verify(f, arg_verify_seed); - if (k < 0) { + if (k == -EINVAL) { + /* If the seed was invalid give up right-away. */ + return k; + } else if (k < 0) { log_warning("FAIL: %s (%s)", f->path, strerror(-k)); - r = -r; + r = k; } else log_info("PASS: %s", f->path); } -- cgit v1.2.3-54-g00ecf From 14d10188de1fd58e663d73683a400d8d7dc67dba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 16 Aug 2012 23:58:14 +0200 Subject: journal: add FSPRG journal authentication --- src/journal/journal-authenticate.c | 52 +++++++++++++++++++++++++---- src/journal/journal-authenticate.h | 3 ++ src/journal/journal-def.h | 1 + src/journal/journal-file.c | 8 ++--- src/journal/journal-verify.c | 68 +++++++++++++++++++++++++++++++++++--- src/journal/journalctl.c | 63 ++++++++++++++++++++--------------- src/journal/test-journal-verify.c | 5 +-- 7 files changed, 157 insertions(+), 43 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index 809655e1ac..c087ad4c8b 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -60,6 +60,7 @@ int journal_file_append_tag(JournalFile *f) { return r; o->tag.seqnum = htole64(journal_file_tag_seqnum(f)); + o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state)); /* Add the tag object itself, so that we can protect its * header. This will exclude the actual hash value in it */ @@ -74,9 +75,8 @@ int journal_file_append_tag(JournalFile *f) { return 0; } -static int journal_file_hmac_start(JournalFile *f) { +int journal_file_hmac_start(JournalFile *f) { uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ - assert(f); if (!f->authenticate) @@ -163,6 +163,44 @@ static int journal_file_evolve(JournalFile *f, uint64_t realtime) { } } +int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { + void *msk; + uint64_t epoch; + + assert(f); + + if (!f->authenticate) + return 0; + + assert(f->fsprg_seed); + + if (f->fsprg_state) { + /* Cheaper... */ + + epoch = FSPRG_GetEpoch(f->fsprg_state); + if (goal == epoch) + return 0; + + if (goal == epoch+1) { + FSPRG_Evolve(f->fsprg_state); + return 0; + } + } else { + f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); + f->fsprg_state = malloc(f->fsprg_state_size); + + if (!f->fsprg_state) + return -ENOMEM; + } + + log_debug("Seeking FSPRG key to %llu.", (unsigned long long) goal); + + msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)); + FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR); + FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size); + return 0; +} + int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { int r; @@ -212,7 +250,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { switch (o->object.type) { case OBJECT_DATA: - /* All but: hash and payload are mutable */ + /* All but hash and payload are mutable */ gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); break; @@ -231,6 +269,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { case OBJECT_TAG: /* All but the tag itself */ gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); + gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch)); break; default: return -EINVAL; @@ -252,15 +291,16 @@ int journal_file_hmac_put_header(JournalFile *f) { return r; /* All but state+reserved, boot_id, arena_size, - * tail_object_offset, n_objects, n_entries, tail_seqnum, + * tail_object_offset, n_objects, n_entries, + * tail_entry_seqnum, head_entry_seqnum, entry_array_offset, * head_entry_realtime, tail_entry_realtime, - * tail_entry_monotonic, n_data, n_fields, header_tag */ + * tail_entry_monotonic, n_data, n_fields, n_tags, + * n_entry_arrays. */ gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); - gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum)); return 0; } diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h index 566d7a81a9..282c73f68c 100644 --- a/src/journal/journal-authenticate.h +++ b/src/journal/journal-authenticate.h @@ -30,6 +30,7 @@ int journal_file_append_tag(JournalFile *f); int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); int journal_file_append_first_tag(JournalFile *f); +int journal_file_hmac_start(JournalFile *f); int journal_file_hmac_put_header(JournalFile *f); int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); @@ -38,3 +39,5 @@ int journal_file_load_fsprg(JournalFile *f); int journal_file_setup_hmac(JournalFile *f); bool journal_file_fsprg_enabled(JournalFile *f); + +int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 660a92c147..ab4988037c 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -125,6 +125,7 @@ _packed_ struct EntryArrayObject { _packed_ struct TagObject { ObjectHeader object; uint64_t seqnum; + uint64_t epoch; uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */ }; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 3bb1e90fb3..274f22db17 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2049,12 +2049,12 @@ int journal_file_open( r = journal_file_refresh_header(f); if (r < 0) goto fail; - - r = journal_file_setup_hmac(f); - if (r < 0) - goto fail; } + r = journal_file_setup_hmac(f); + if (r < 0) + goto fail; + if (newly_created) { r = journal_file_setup_field_hash_table(f); if (r < 0) diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 94f90b670d..e646e38ddc 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -35,7 +35,10 @@ /* FIXME: * - * - verify FSPRG + * - write tag only if non-tag objects have been written + * - change terms + * - write bit mucking test + * * - Allow building without libgcrypt * - check with sparse * - 64bit conversions @@ -650,11 +653,11 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) { int journal_file_verify(JournalFile *f, const char *seed) { int r; Object *o; - uint64_t p = 0, last_tag = 0; - uint64_t n_tags = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; + uint64_t p = 0, last_tag = 0, last_epoch = 0; + uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; sd_id128_t entry_boot_id; bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; - uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0; + uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; usec_t last_usec = 0; int data_fd = -1, entry_fd = -1, entry_array_fd = -1; char data_path[] = "/var/tmp/journal-data-XXXXXX", @@ -842,7 +845,9 @@ int journal_file_verify(JournalFile *f, const char *seed) { n_entry_arrays++; break; - case OBJECT_TAG: + case OBJECT_TAG: { + uint64_t q; + if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) { log_error("Tag object without authentication at %llu", (unsigned long long) p); r = -EBADMSG; @@ -855,8 +860,61 @@ int journal_file_verify(JournalFile *f, const char *seed) { goto fail; } + if (le64toh(o->tag.epoch) < last_epoch) { + log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + /* OK, now we know the epoch. So let's now set + * it, and calculate the HMAC for everything + * since the last tag. */ + r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch)); + if (r < 0) + goto fail; + + r = journal_file_hmac_start(f); + if (r < 0) + goto fail; + + if (last_tag == 0) { + r = journal_file_hmac_put_header(f); + if (r < 0) + goto fail; + + q = le64toh(f->header->header_size); + } else + q = last_tag; + + while (q <= p) { + r = journal_file_move_to_object(f, -1, q, &o); + if (r < 0) + goto fail; + + r = journal_file_hmac_put_object(f, -1, q); + if (r < 0) + goto fail; + + q = q + ALIGN64(le64toh(o->object.size)); + } + + /* Position might have changed, let's reposition things */ + r = journal_file_move_to_object(f, -1, p, &o); + if (r < 0) + goto fail; + + if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { + log_error("Tag did not authenticate at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + + f->hmac_running = false; + + last_tag = p + ALIGN64(le64toh(o->object.size)); n_tags ++; break; + } default: n_weird ++; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 25e441b022..f0654fe4e8 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -60,6 +60,7 @@ static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; static const char *arg_verify_seed = NULL; +static usec_t arg_evolve = DEFAULT_FSPRG_INTERVAL_USEC; static enum { ACTION_SHOW, @@ -73,26 +74,27 @@ static int help(void) { printf("%s [OPTIONS...] [MATCH]\n\n" "Send control commands to or query the journal.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " -a --all Show all fields, including long and unprintable\n" - " -f --follow Follow journal\n" - " -n --lines=INTEGER Journal entries to show\n" - " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, cat)\n" - " -q --quiet Don't show privilege warning\n" - " -l --local Only local entries\n" - " -b --this-boot Show data only from current boot\n" - " -D --directory=PATH Show journal files from directory\n" - " -p --priority=RANGE Show only messages within the specified priority range\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -a --all Show all fields, including long and unprintable\n" + " -f --follow Follow journal\n" + " -n --lines=INTEGER Journal entries to show\n" + " --no-tail Show all lines, even in follow mode\n" + " -o --output=STRING Change journal output mode (short, short-monotonic,\n" + " verbose, export, json, cat)\n" + " -q --quiet Don't show privilege warning\n" + " -l --local Only local entries\n" + " -b --this-boot Show data only from current boot\n" + " -D --directory=PATH Show journal files from directory\n" + " -p --priority=RANGE Show only messages within the specified priority range\n\n" "Commands:\n" - " --new-id128 Generate a new 128 Bit ID\n" - " --header Show journal header information\n" - " --verify Verify journal file consistency\n" - " --verify-seed=SEED Specify FSPRG seed for verification\n" - " --setup-keys Generate new FSPRG key and seed\n", + " --new-id128 Generate a new 128 Bit ID\n" + " --header Show journal header information\n" + " --verify Verify journal file consistency\n" + " --verify-seed=SEED Specify FSPRG seed for verification\n" + " --setup-keys Generate new FSPRG key and seed\n" + " --evolve=TIME How of to evolve FSPRG keys\n", program_invocation_short_name); return 0; @@ -108,7 +110,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_HEADER, ARG_SETUP_KEYS, ARG_VERIFY, - ARG_VERIFY_SEED + ARG_VERIFY_SEED, + ARG_EVOLVE }; static const struct option options[] = { @@ -130,6 +133,7 @@ static int parse_argv(int argc, char *argv[]) { { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-seed", required_argument, NULL, ARG_VERIFY_SEED }, + { "evolve", required_argument, NULL, ARG_EVOLVE }, { NULL, 0, NULL, 0 } }; @@ -222,6 +226,14 @@ static int parse_argv(int argc, char *argv[]) { arg_verify_seed = optarg; break; + case ARG_EVOLVE: + r = parse_usec(optarg, &arg_evolve); + if (r < 0 || arg_evolve <= 0) { + log_error("Failed to parse evolve interval: %s", optarg); + return -EINVAL; + } + break; + case 'p': { const char *dots; @@ -445,7 +457,7 @@ static int setup_keys(void) { sd_id128_t machine, boot; char *p = NULL, *k = NULL; struct FSPRGHeader h; - uint64_t n, interval; + uint64_t n; r = sd_id128_get_machine(&machine); if (r < 0) { @@ -505,9 +517,8 @@ static int setup_keys(void) { log_info("Generating evolving key..."); FSPRG_GenState0(state, mpk, seed, seed_size); - interval = DEFAULT_FSPRG_INTERVAL_USEC; n = now(CLOCK_REALTIME); - n /= interval; + n /= arg_evolve; close_nointr_nofail(fd); fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY); @@ -522,8 +533,8 @@ static int setup_keys(void) { h.machine_id = machine; h.boot_id = boot; h.header_size = htole64(sizeof(h)); - h.fsprg_start_usec = htole64(n * interval); - h.fsprg_interval_usec = htole64(interval); + h.fsprg_start_usec = htole64(n * arg_evolve); + h.fsprg_interval_usec = htole64(arg_evolve); h.secpar = htole16(FSPRG_RECOMMENDED_SECPAR); h.state_size = htole64(state_size); @@ -567,7 +578,7 @@ static int setup_keys(void) { printf("%02x", ((uint8_t*) seed)[i]); } - printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) interval); + printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_evolve); if (isatty(STDOUT_FILENO)) fputs(ANSI_HIGHLIGHT_OFF "\n", stderr); diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c index bada498fab..8a7d998ff9 100644 --- a/src/journal/test-journal-verify.c +++ b/src/journal/test-journal-verify.c @@ -35,6 +35,7 @@ int main(int argc, char *argv[]) { char t[] = "/tmp/journal-XXXXXX"; unsigned n; JournalFile *f; + const char *verification_key = argv[1]; log_set_max_level(LOG_DEBUG); @@ -43,7 +44,7 @@ int main(int argc, char *argv[]) { log_info("Generating..."); - assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0); + assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0); for (n = 0; n < N_ENTRIES; n++) { struct iovec iovec; @@ -67,7 +68,7 @@ int main(int argc, char *argv[]) { log_info("Verifying..."); assert_se(journal_file_open("test.journal", O_RDONLY, 0666, false, false, NULL, NULL, NULL, &f) == 0); - assert_se(journal_file_verify(f, NULL) >= 0); + assert_se(journal_file_verify(f, verification_key) >= 0); journal_file_close(f); log_info("Exiting..."); -- cgit v1.2.3-54-g00ecf From baed47c3c20512507e497058d388782400a072f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Aug 2012 00:45:18 +0200 Subject: journal: rework terminology Let's clean up our terminology a bit. New terminology: FSS = Forward Secure Sealing FSPRG = Forward Secure Pseudo-Random Generator FSS is the combination of FSPRG and a HMAC. Sealing = process of adding authentication tags to the journal. Verification = process of checking authentication tags to the journal. Sealing Key = The key used for adding authentication tags to the journal. Verification Key = The key used for checking authentication tags of the journal. Key pair = The pair of Sealing Key and Verification Key Internally, the Sealing Key is the combination of the FSPRG State plus change interval/start time. Internally, the Verification Key is the combination of the FSPRG Seed plus change interval/start time. --- src/journal/journal-authenticate.c | 88 ++++++++++----------- src/journal/journal-authenticate.h | 9 +-- src/journal/journal-def.h | 16 ++-- src/journal/journal-file.c | 44 +++++------ src/journal/journal-file.h | 18 ++--- src/journal/journal-verify.c | 22 +++--- src/journal/journalctl.c | 151 +++++++++++++++++++------------------ 7 files changed, 178 insertions(+), 170 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index c087ad4c8b..ae64d3c8e0 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -45,7 +45,7 @@ int journal_file_append_tag(JournalFile *f) { assert(f); - if (!f->authenticate) + if (!f->seal) return 0; if (!f->hmac_running) @@ -79,7 +79,7 @@ int journal_file_hmac_start(JournalFile *f) { uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ assert(f); - if (!f->authenticate) + if (!f->seal) return 0; if (f->hmac_running) @@ -100,28 +100,28 @@ static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *e assert(f); assert(epoch); - assert(f->authenticate); + assert(f->seal); - if (f->fsprg_start_usec == 0 || - f->fsprg_interval_usec == 0) + if (f->fss_start_usec == 0 || + f->fss_interval_usec == 0) return -ENOTSUP; - if (realtime < f->fsprg_start_usec) + if (realtime < f->fss_start_usec) return -ESTALE; - t = realtime - f->fsprg_start_usec; - t = t / f->fsprg_interval_usec; + t = realtime - f->fss_start_usec; + t = t / f->fss_interval_usec; *epoch = t; return 0; } -static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) { +static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) { uint64_t goal, epoch; int r; assert(f); - if (!f->authenticate) + if (!f->seal) return 0; r = journal_file_get_epoch(f, realtime, &goal); @@ -135,13 +135,13 @@ static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) { return epoch != goal; } -static int journal_file_evolve(JournalFile *f, uint64_t realtime) { +int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) { uint64_t goal, epoch; int r; assert(f); - if (!f->authenticate) + if (!f->seal) return 0; r = journal_file_get_epoch(f, realtime, &goal); @@ -169,7 +169,7 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { assert(f); - if (!f->authenticate) + if (!f->seal) return 0; assert(f->fsprg_seed); @@ -206,10 +206,10 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { assert(f); - if (!f->authenticate) + if (!f->seal) return 0; - r = journal_file_need_evolve(f, realtime); + r = journal_file_fsprg_need_evolve(f, realtime); if (r <= 0) return 0; @@ -217,7 +217,7 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { if (r < 0) return r; - r = journal_file_evolve(f, realtime); + r = journal_file_fsprg_evolve(f, realtime); if (r < 0) return r; @@ -234,7 +234,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) { assert(f); - if (!f->authenticate) + if (!f->seal) return 0; r = journal_file_hmac_start(f); @@ -283,7 +283,7 @@ int journal_file_hmac_put_header(JournalFile *f) { assert(f); - if (!f->authenticate) + if (!f->seal) return 0; r = journal_file_hmac_start(f); @@ -305,23 +305,23 @@ int journal_file_hmac_put_header(JournalFile *f) { return 0; } -int journal_file_load_fsprg(JournalFile *f) { +int journal_file_fss_load(JournalFile *f) { int r, fd = -1; char *p = NULL; struct stat st; - FSPRGHeader *m = NULL; + FSSHeader *m = NULL; sd_id128_t machine; assert(f); - if (!f->authenticate) + if (!f->seal) return 0; r = sd_id128_get_machine(&machine); if (r < 0) return r; - if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return -ENOMEM; @@ -337,19 +337,19 @@ int journal_file_load_fsprg(JournalFile *f) { goto finish; } - if (st.st_size < (off_t) sizeof(FSPRGHeader)) { + if (st.st_size < (off_t) sizeof(FSSHeader)) { r = -ENODATA; goto finish; } - m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0); + m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { m = NULL; r = -errno; goto finish; } - if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) { + if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) { r = -EBADMSG; goto finish; } @@ -359,18 +359,18 @@ int journal_file_load_fsprg(JournalFile *f) { goto finish; } - if (le64toh(m->header_size) < sizeof(FSPRGHeader)) { + if (le64toh(m->header_size) < sizeof(FSSHeader)) { r = -EBADMSG; goto finish; } - if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) { + if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(m->fsprg_secpar)) { r = -EBADMSG; goto finish; } - f->fsprg_file_size = le64toh(m->header_size) + le64toh(m->state_size); - if ((uint64_t) st.st_size < f->fsprg_file_size) { + f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size); + if ((uint64_t) st.st_size < f->fss_file_size) { r = -ENODATA; goto finish; } @@ -380,30 +380,30 @@ int journal_file_load_fsprg(JournalFile *f) { goto finish; } - if (le64toh(m->fsprg_start_usec) <= 0 || - le64toh(m->fsprg_interval_usec) <= 0) { + if (le64toh(m->start_usec) <= 0 || + le64toh(m->interval_usec) <= 0) { r = -EBADMSG; goto finish; } - f->fsprg_file = mmap(NULL, PAGE_ALIGN(f->fsprg_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (f->fsprg_file == MAP_FAILED) { - f->fsprg_file = NULL; + f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (f->fss_file == MAP_FAILED) { + f->fss_file = NULL; r = -errno; goto finish; } - f->fsprg_start_usec = le64toh(f->fsprg_file->fsprg_start_usec); - f->fsprg_interval_usec = le64toh(f->fsprg_file->fsprg_interval_usec); + f->fss_start_usec = le64toh(f->fss_file->start_usec); + f->fss_interval_usec = le64toh(f->fss_file->interval_usec); - f->fsprg_state = (uint8_t*) f->fsprg_file + le64toh(f->fsprg_file->header_size); - f->fsprg_state_size = le64toh(f->fsprg_file->state_size); + f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size); + f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size); r = 0; finish: if (m) - munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader))); + munmap(m, PAGE_ALIGN(sizeof(FSSHeader))); if (fd >= 0) close_nointr_nofail(fd); @@ -412,10 +412,10 @@ finish: return r; } -int journal_file_setup_hmac(JournalFile *f) { +int journal_file_hmac_setup(JournalFile *f) { gcry_error_t e; - if (!f->authenticate) + if (!f->seal) return 0; e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); @@ -429,7 +429,7 @@ int journal_file_append_first_tag(JournalFile *f) { int r; uint64_t p; - if (!f->authenticate) + if (!f->seal) return 0; log_debug("Calculating first tag..."); @@ -463,8 +463,8 @@ int journal_file_append_first_tag(JournalFile *f) { return 0; } -bool journal_file_fsprg_enabled(JournalFile *f) { +bool journal_file_fss_enabled(JournalFile *f) { assert(f); - return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED); + return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED); } diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h index 282c73f68c..4f4f45b114 100644 --- a/src/journal/journal-authenticate.h +++ b/src/journal/journal-authenticate.h @@ -30,14 +30,13 @@ int journal_file_append_tag(JournalFile *f); int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); int journal_file_append_first_tag(JournalFile *f); +int journal_file_hmac_setup(JournalFile *f); int journal_file_hmac_start(JournalFile *f); int journal_file_hmac_put_header(JournalFile *f); int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); -int journal_file_load_fsprg(JournalFile *f); - -int journal_file_setup_hmac(JournalFile *f); - -bool journal_file_fsprg_enabled(JournalFile *f); +int journal_file_fss_load(JournalFile *f); +bool journal_file_fss_enabled(JournalFile *f); +int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime); int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index ab4988037c..52c55ab4bb 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -42,7 +42,7 @@ typedef struct TagObject TagObject; typedef struct EntryItem EntryItem; typedef struct HashItem HashItem; -typedef struct FSPRGHeader FSPRGHeader; +typedef struct FSSHeader FSSHeader; /* Object types */ enum { @@ -151,7 +151,7 @@ enum { }; enum { - HEADER_COMPATIBLE_AUTHENTICATED = 1 + HEADER_COMPATIBLE_SEALED = 1 }; #define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }) @@ -189,18 +189,18 @@ _packed_ struct Header { le64_t n_entry_arrays; }; -#define FSPRG_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) +#define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) -_packed_ struct FSPRGHeader { +_packed_ struct FSSHeader { uint8_t signature[8]; /* "KSHHRHLP" */ le32_t compatible_flags; le32_t incompatible_flags; sd_id128_t machine_id; sd_id128_t boot_id; /* last writer */ le64_t header_size; - le64_t fsprg_start_usec; - le64_t fsprg_interval_usec; - le16_t secpar; + le64_t start_usec; + le64_t interval_usec; + le16_t fsprg_secpar; le16_t reserved[3]; - le64_t state_size; + le64_t fsprg_state_size; }; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 274f22db17..76bf0e53ca 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -65,7 +65,7 @@ void journal_file_close(JournalFile *f) { assert(f); /* Write the final tag */ - if (f->authenticate) + if (f->seal) journal_file_append_tag(f); /* Sync everything to disk, before we mark the file offline */ @@ -96,8 +96,8 @@ void journal_file_close(JournalFile *f) { #endif #ifdef HAVE_GCRYPT - if (f->fsprg_file) - munmap(f->fsprg_file, PAGE_ALIGN(f->fsprg_file_size)); + if (f->fss_file) + munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size)); else if (f->fsprg_state) free(f->fsprg_state); @@ -125,7 +125,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) { htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0); h.compatible_flags = - htole32(f->authenticate ? HEADER_COMPATIBLE_AUTHENTICATED : 0); + htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0); r = sd_id128_randomize(&h.file_id); if (r < 0) @@ -195,7 +195,7 @@ static int journal_file_verify_header(JournalFile *f) { * compatible flags, too */ if (f->writable) { #ifdef HAVE_GCRYPT - if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_AUTHENTICATED) != 0) + if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0) return -EPROTONOSUPPORT; #else if (f->header->compatible_flags != 0) @@ -207,8 +207,8 @@ static int journal_file_verify_header(JournalFile *f) { if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) return -EBADMSG; - if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED) && - !JOURNAL_HEADER_CONTAINS(f->header, n_tags)) + if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED) && + !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) return -EBADMSG; if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size))) @@ -240,7 +240,7 @@ static int journal_file_verify_header(JournalFile *f) { } f->compress = !!(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED); - f->authenticate = !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED); + f->seal = !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED); return 0; } @@ -1900,8 +1900,8 @@ void journal_file_print_header(JournalFile *f) { f->header->state == STATE_OFFLINE ? "offline" : f->header->state == STATE_ONLINE ? "online" : f->header->state == STATE_ARCHIVED ? "archived" : "unknown", - (f->header->compatible_flags & HEADER_COMPATIBLE_AUTHENTICATED) ? " AUTHENTICATED" : "", - (f->header->compatible_flags & ~HEADER_COMPATIBLE_AUTHENTICATED) ? " ???" : "", + (f->header->compatible_flags & HEADER_COMPATIBLE_SEALED) ? " SEALED" : "", + (f->header->compatible_flags & ~HEADER_COMPATIBLE_SEALED) ? " ???" : "", (f->header->incompatible_flags & HEADER_INCOMPATIBLE_COMPRESSED) ? " COMPRESSED" : "", (f->header->incompatible_flags & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "", (unsigned long long) le64toh(f->header->header_size), @@ -1934,7 +1934,7 @@ int journal_file_open( int flags, mode_t mode, bool compress, - bool authenticate, + bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, @@ -1964,7 +1964,7 @@ int journal_file_open( f->prot = prot_from_flags(flags); f->writable = (flags & O_ACCMODE) != O_RDONLY; f->compress = compress; - f->authenticate = authenticate; + f->seal = seal; if (mmap_cache) f->mmap = mmap_cache_ref(mmap_cache); @@ -2000,10 +2000,10 @@ int journal_file_open( newly_created = true; /* Try to load the FSPRG state, and if we can't, then - * just don't do authentication */ - r = journal_file_load_fsprg(f); + * just don't do sealing */ + r = journal_file_fss_load(f); if (r < 0) - f->authenticate = false; + f->seal = false; r = journal_file_init_header(f, template); if (r < 0) @@ -2034,7 +2034,7 @@ int journal_file_open( } if (!newly_created && f->writable) { - r = journal_file_load_fsprg(f); + r = journal_file_fss_load(f); if (r < 0) goto fail; } @@ -2051,7 +2051,7 @@ int journal_file_open( goto fail; } - r = journal_file_setup_hmac(f); + r = journal_file_hmac_setup(f); if (r < 0) goto fail; @@ -2088,7 +2088,7 @@ fail: return r; } -int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) { +int journal_file_rotate(JournalFile **f, bool compress, bool seal) { char *p; size_t l; JournalFile *old_file, *new_file = NULL; @@ -2127,7 +2127,7 @@ int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) { old_file->header->state = STATE_ARCHIVED; - r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, authenticate, NULL, old_file->mmap, old_file, &new_file); + r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file); journal_file_close(old_file); *f = new_file; @@ -2139,7 +2139,7 @@ int journal_file_open_reliably( int flags, mode_t mode, bool compress, - bool authenticate, + bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, @@ -2149,7 +2149,7 @@ int journal_file_open_reliably( size_t l; char *p; - r = journal_file_open(fname, flags, mode, compress, authenticate, + r = journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret); if (r != -EBADMSG && /* corrupted */ r != -ENODATA && /* truncated */ @@ -2184,7 +2184,7 @@ int journal_file_open_reliably( log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname); - return journal_file_open(fname, flags, mode, compress, authenticate, + return journal_file_open(fname, flags, mode, compress, seal, metrics, mmap_cache, template, ret); } diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 9d437ae791..58de214359 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -51,7 +51,7 @@ typedef struct JournalFile { int prot; bool writable; bool compress; - bool authenticate; + bool seal; bool tail_entry_monotonic_valid; @@ -73,17 +73,17 @@ typedef struct JournalFile { gcry_md_hd_t hmac; bool hmac_running; - FSPRGHeader *fsprg_file; - size_t fsprg_file_size; + FSSHeader *fss_file; + size_t fss_file_size; + + uint64_t fss_start_usec; + uint64_t fss_interval_usec; void *fsprg_state; size_t fsprg_state_size; void *fsprg_seed; size_t fsprg_seed_size; - - uint64_t fsprg_start_usec; - uint64_t fsprg_interval_usec; #endif } JournalFile; @@ -97,7 +97,7 @@ int journal_file_open( int flags, mode_t mode, bool compress, - bool authenticate, + bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, @@ -110,7 +110,7 @@ int journal_file_open_reliably( int flags, mode_t mode, bool compress, - bool authenticate, + bool seal, JournalMetrics *metrics, MMapCache *mmap_cache, JournalFile *template, @@ -152,7 +152,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 void journal_file_dump(JournalFile *f); void journal_file_print_header(JournalFile *f); -int journal_file_rotate(JournalFile **f, bool compress, bool authenticate); +int journal_file_rotate(JournalFile **f, bool compress, bool seal); void journal_file_post_change(JournalFile *f); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index e646e38ddc..b7097e7b01 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -38,6 +38,7 @@ * - write tag only if non-tag objects have been written * - change terms * - write bit mucking test + * - tag timestamps should be between entry timestamps * * - Allow building without libgcrypt * - check with sparse @@ -595,7 +596,7 @@ static int verify_entry_array( return 0; } -static int journal_file_parse_seed(JournalFile *f, const char *s) { +static int journal_file_parse_verification_key(JournalFile *f, const char *key) { uint8_t *seed; size_t seed_size, c; const char *k; @@ -607,7 +608,7 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) { if (!seed) return -ENOMEM; - k = s; + k = key; for (c = 0; c < seed_size; c++) { int x, y; @@ -644,13 +645,14 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) { f->fsprg_seed = seed; f->fsprg_seed_size = seed_size; - f->fsprg_start_usec = start; - f->fsprg_interval_usec = interval; + + f->fss_start_usec = start; + f->fss_interval_usec = interval; return 0; } -int journal_file_verify(JournalFile *f, const char *seed) { +int journal_file_verify(JournalFile *f, const char *key) { int r; Object *o; uint64_t p = 0, last_tag = 0, last_epoch = 0; @@ -666,8 +668,8 @@ int journal_file_verify(JournalFile *f, const char *seed) { assert(f); - if (seed) { - r = journal_file_parse_seed(f, seed); + if (key) { + r = journal_file_parse_verification_key(f, key); if (r < 0) { log_error("Failed to parse seed."); return r; @@ -848,8 +850,8 @@ int journal_file_verify(JournalFile *f, const char *seed) { case OBJECT_TAG: { uint64_t q; - if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) { - log_error("Tag object without authentication at %llu", (unsigned long long) p); + if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) { + log_error("Tag object without sealing at %llu", (unsigned long long) p); r = -EBADMSG; goto fail; } @@ -904,7 +906,7 @@ int journal_file_verify(JournalFile *f, const char *seed) { goto fail; if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { - log_error("Tag did not authenticate at %llu", (unsigned long long) p); + log_error("Tag failed verification at %llu", (unsigned long long) p); r = -EBADMSG; goto fail; } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f0654fe4e8..0df8ce57fd 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -46,7 +46,7 @@ #include "journal-authenticate.h" #include "fsprg.h" -#define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE) +#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; @@ -59,8 +59,8 @@ static bool arg_local = false; static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; -static const char *arg_verify_seed = NULL; -static usec_t arg_evolve = DEFAULT_FSPRG_INTERVAL_USEC; +static const char *arg_verify_key = NULL; +static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; static enum { ACTION_SHOW, @@ -74,27 +74,27 @@ static int help(void) { printf("%s [OPTIONS...] [MATCH]\n\n" "Send control commands to or query the journal.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " -a --all Show all fields, including long and unprintable\n" - " -f --follow Follow journal\n" - " -n --lines=INTEGER Journal entries to show\n" - " --no-tail Show all lines, even in follow mode\n" - " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, cat)\n" - " -q --quiet Don't show privilege warning\n" - " -l --local Only local entries\n" - " -b --this-boot Show data only from current boot\n" - " -D --directory=PATH Show journal files from directory\n" - " -p --priority=RANGE Show only messages within the specified priority range\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -a --all Show all fields, including long and unprintable\n" + " -f --follow Follow journal\n" + " -n --lines=INTEGER Journal entries to show\n" + " --no-tail Show all lines, even in follow mode\n" + " -o --output=STRING Change journal output mode (short, short-monotonic,\n" + " verbose, export, json, cat)\n" + " -q --quiet Don't show privilege warning\n" + " -l --local Only local entries\n" + " -b --this-boot Show data only from current boot\n" + " -D --directory=PATH Show journal files from directory\n" + " -p --priority=RANGE Show only messages within the specified priority range\n\n" "Commands:\n" - " --new-id128 Generate a new 128 Bit ID\n" - " --header Show journal header information\n" - " --verify Verify journal file consistency\n" - " --verify-seed=SEED Specify FSPRG seed for verification\n" - " --setup-keys Generate new FSPRG key and seed\n" - " --evolve=TIME How of to evolve FSPRG keys\n", + " --new-id128 Generate a new 128 Bit ID\n" + " --header Show journal header information\n" + " --setup-keys Generate new FSS key pair\n" + " --interval=TIME Time interval for changing the FSS sealing key\n" + " --verify Verify journal file consistency\n" + " --verify-key=KEY Specify FSS verification key\n", program_invocation_short_name); return 0; @@ -109,32 +109,32 @@ static int parse_argv(int argc, char *argv[]) { ARG_NEW_ID128, ARG_HEADER, ARG_SETUP_KEYS, + ARG_INTERVAL, ARG_VERIFY, - ARG_VERIFY_SEED, - ARG_EVOLVE + ARG_VERIFY_KEY }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version" , no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "follow", no_argument, NULL, 'f' }, - { "output", required_argument, NULL, 'o' }, - { "all", no_argument, NULL, 'a' }, - { "lines", required_argument, NULL, 'n' }, - { "no-tail", no_argument, NULL, ARG_NO_TAIL }, - { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, - { "quiet", no_argument, NULL, 'q' }, - { "local", no_argument, NULL, 'l' }, - { "this-boot", no_argument, NULL, 'b' }, - { "directory", required_argument, NULL, 'D' }, - { "header", no_argument, NULL, ARG_HEADER }, - { "priority", no_argument, NULL, 'p' }, - { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, - { "verify", no_argument, NULL, ARG_VERIFY }, - { "verify-seed", required_argument, NULL, ARG_VERIFY_SEED }, - { "evolve", required_argument, NULL, ARG_EVOLVE }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "follow", no_argument, NULL, 'f' }, + { "output", required_argument, NULL, 'o' }, + { "all", no_argument, NULL, 'a' }, + { "lines", required_argument, NULL, 'n' }, + { "no-tail", no_argument, NULL, ARG_NO_TAIL }, + { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, + { "quiet", no_argument, NULL, 'q' }, + { "local", no_argument, NULL, 'l' }, + { "this-boot", no_argument, NULL, 'b' }, + { "directory", required_argument, NULL, 'D' }, + { "header", no_argument, NULL, ARG_HEADER }, + { "priority", no_argument, NULL, 'p' }, + { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, + { "interval", required_argument, NULL, ARG_INTERVAL }, + { "verify", no_argument, NULL, ARG_VERIFY }, + { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, + { NULL, 0, NULL, 0 } }; int c, r; @@ -221,15 +221,15 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_VERIFY; break; - case ARG_VERIFY_SEED: + case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; - arg_verify_seed = optarg; + arg_verify_key = optarg; break; - case ARG_EVOLVE: - r = parse_usec(optarg, &arg_evolve); - if (r < 0 || arg_evolve <= 0) { - log_error("Failed to parse evolve interval: %s", optarg); + case ARG_INTERVAL: + r = parse_usec(optarg, &arg_interval); + if (r < 0 || arg_interval <= 0) { + log_error("Failed to parse sealing key change interval: %s", optarg); return -EINVAL; } break; @@ -456,7 +456,7 @@ static int setup_keys(void) { int fd = -1, r; sd_id128_t machine, boot; char *p = NULL, *k = NULL; - struct FSPRGHeader h; + struct FSSHeader h; uint64_t n; r = sd_id128_get_machine(&machine); @@ -471,7 +471,7 @@ static int setup_keys(void) { return r; } - if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg", + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return log_oom(); @@ -481,7 +481,7 @@ static int setup_keys(void) { goto finish; } - if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg.tmp.XXXXXX", + if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX", SD_ID128_FORMAT_VAL(machine)) < 0) { r = log_oom(); goto finish; @@ -514,11 +514,13 @@ static int setup_keys(void) { log_info("Generating key pair..."); FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); - log_info("Generating evolving key..."); + log_info("Generating sealing key..."); FSPRG_GenState0(state, mpk, seed, seed_size); + assert(arg_interval > 0); + n = now(CLOCK_REALTIME); - n /= arg_evolve; + n /= arg_interval; close_nointr_nofail(fd); fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY); @@ -533,10 +535,10 @@ static int setup_keys(void) { h.machine_id = machine; h.boot_id = boot; h.header_size = htole64(sizeof(h)); - h.fsprg_start_usec = htole64(n * arg_evolve); - h.fsprg_interval_usec = htole64(arg_evolve); - h.secpar = htole16(FSPRG_RECOMMENDED_SECPAR); - h.state_size = htole64(state_size); + h.start_usec = htole64(n * arg_interval); + h.interval_usec = htole64(arg_interval); + h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR); + h.fsprg_state_size = htole64(state_size); l = loop_write(fd, &h, sizeof(h), false); if (l < 0 || (size_t) l != sizeof(h)) { @@ -561,14 +563,13 @@ static int setup_keys(void) { if (isatty(STDOUT_FILENO)) { fprintf(stderr, "\n" - "The new key pair has been generated. The evolving key has been written to the\n" - "following file. It will be used to protect local journal files. This file\n" - "should be kept secret. It should not be used on multiple hosts.\n" + "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n" + "the following local file. It should not be used on multiple hosts.\n" "\n" "\t%s\n" "\n" - "Please write down the following " ANSI_HIGHLIGHT_ON "secret" ANSI_HIGHLIGHT_OFF " seed value. It should not be stored\n" - "locally on disk, and may be used to verify journal files from this host.\n" + "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n" + "at a safe location and should not be saved locally on disk.\n" "\n\t" ANSI_HIGHLIGHT_RED_ON, p); fflush(stderr); } @@ -578,10 +579,16 @@ static int setup_keys(void) { printf("%02x", ((uint8_t*) seed)[i]); } - printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_evolve); + printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); + + if (isatty(STDOUT_FILENO)) { + char tsb[FORMAT_TIMESPAN_MAX]; - if (isatty(STDOUT_FILENO)) - fputs(ANSI_HIGHLIGHT_OFF "\n", stderr); + fprintf(stderr, + ANSI_HIGHLIGHT_OFF "\n" + "The sealing key is automatically changed every %s.\n", + format_timespan(tsb, sizeof(tsb), arg_interval)); + } r = 0; @@ -613,13 +620,13 @@ static int verify(sd_journal *j) { int k; #ifdef HAVE_GCRYPT - if (!arg_verify_seed && journal_file_fsprg_enabled(f)) - log_warning("Journal file %s has authentication enabled but verification seed has not been passed using --verify-seed=.", f->path); + if (!arg_verify_key && journal_file_fss_enabled(f)) + log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif - k = journal_file_verify(f, arg_verify_seed); + k = journal_file_verify(f, arg_verify_key); if (k == -EINVAL) { - /* If the seed was invalid give up right-away. */ + /* If the key was invalid give up right-away. */ return k; } else if (k < 0) { log_warning("FAIL: %s (%s)", f->path, strerror(-k)); -- cgit v1.2.3-54-g00ecf From 6c7be122acd666d4e93541179d89747aa12efb67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Aug 2012 03:30:22 +0200 Subject: journal: after verification output validated time range --- src/journal/journal-verify.c | 28 ++++++++++++++++++++++------ src/journal/journal-verify.h | 2 +- src/journal/journalctl.c | 13 +++++++++++-- src/journal/test-journal-verify.c | 12 +++++++++++- 4 files changed, 45 insertions(+), 10 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 598fc9bead..f9a930e42e 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -36,8 +36,6 @@ /* FIXME: * * - write bit mucking test - * - tag timestamps should be between entry timestamps - * - output validated time ranges * - evolve key even if nothing happened in regular intervals * * - Allow building without libgcrypt @@ -652,7 +650,10 @@ static int journal_file_parse_verification_key(JournalFile *f, const char *key) return 0; } -int journal_file_verify(JournalFile *f, const char *key) { +int journal_file_verify( + JournalFile *f, + const char *key, + usec_t *first_validated, usec_t *last_validated, usec_t *last_contained) { int r; Object *o; uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0; @@ -749,6 +750,12 @@ int journal_file_verify(JournalFile *f, const char *key) { break; case OBJECT_ENTRY: + if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED) && n_tags <= 0) { + log_error("First entry before first tag at %llu", (unsigned long long) p); + r = -EBADMSG; + goto fail; + } + r = write_uint64(entry_fd, p); if (r < 0) goto fail; @@ -854,7 +861,7 @@ int journal_file_verify(JournalFile *f, const char *key) { break; case OBJECT_TAG: { - uint64_t q; + uint64_t q, rt; if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) { log_error("Tag object in file without sealing at %llu", (unsigned long long) p); @@ -876,8 +883,8 @@ int journal_file_verify(JournalFile *f, const char *key) { goto fail; } - last_tag_realtime = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec; - if (entry_realtime_set && entry_realtime >= last_tag_realtime) { + rt = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec; + if (entry_realtime_set && entry_realtime >= rt) { log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p); r = -EBADMSG; goto fail; @@ -929,6 +936,8 @@ int journal_file_verify(JournalFile *f, const char *key) { f->hmac_running = false; last_tag = p + ALIGN64(le64toh(o->object.size)); + last_tag_realtime = rt; + n_tags ++; break; } @@ -1056,6 +1065,13 @@ int journal_file_verify(JournalFile *f, const char *key) { close_nointr_nofail(entry_fd); close_nointr_nofail(entry_array_fd); + if (first_validated) + *first_validated = le64toh(f->header->head_entry_realtime); + if (last_validated) + *last_validated = last_tag_realtime; + if (last_contained) + *last_contained = le64toh(f->header->tail_entry_realtime); + return 0; fail: diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h index 3ebdd5e7f2..e4449c6ad7 100644 --- a/src/journal/journal-verify.h +++ b/src/journal/journal-verify.h @@ -23,4 +23,4 @@ #include "journal-file.h" -int journal_file_verify(JournalFile *f, const char *key); +int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0df8ce57fd..5c21ab0adf 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -618,21 +618,30 @@ static int verify(sd_journal *j) { HASHMAP_FOREACH(f, j->files, i) { int k; + usec_t from, to, total; #ifdef HAVE_GCRYPT if (!arg_verify_key && journal_file_fss_enabled(f)) log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif - k = journal_file_verify(f, arg_verify_key); + k = journal_file_verify(f, arg_verify_key, &from, &to, &total); if (k == -EINVAL) { /* If the key was invalid give up right-away. */ return k; } else if (k < 0) { log_warning("FAIL: %s (%s)", f->path, strerror(-k)); r = k; - } else + } else { + char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; log_info("PASS: %s", f->path); + + if (journal_file_fss_enabled(f)) + log_info("=> Validated from %s to %s, %s missing", + format_timestamp(a, sizeof(a), from), + format_timestamp(b, sizeof(b), to), + format_timespan(c, sizeof(c), total > to ? total - to : 0)); + } } return r; diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c index 9a99bcba4b..df0a5ddef9 100644 --- a/src/journal/test-journal-verify.c +++ b/src/journal/test-journal-verify.c @@ -36,6 +36,10 @@ int main(int argc, char *argv[]) { unsigned n; JournalFile *f; const char *verification_key = argv[1]; + usec_t from, to, total; + char a[FORMAT_TIMESTAMP_MAX]; + char b[FORMAT_TIMESTAMP_MAX]; + char c[FORMAT_TIMESPAN_MAX]; log_set_max_level(LOG_DEBUG); @@ -71,7 +75,13 @@ int main(int argc, char *argv[]) { journal_file_print_header(f); - assert_se(journal_file_verify(f, verification_key) >= 0); + assert_se(journal_file_verify(f, verification_key, &from, &to, &total) >= 0); + + log_info("=> Validated from %s to %s, %s missing", + format_timestamp(a, sizeof(a), from), + format_timestamp(b, sizeof(b), to), + format_timespan(c, sizeof(c), total > to ? total - to : 0)); + journal_file_close(f); log_info("Exiting..."); -- cgit v1.2.3-54-g00ecf From f982e6f7612401a9a789bb8f40d2adca34c85c10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 17 Aug 2012 22:10:11 +0200 Subject: journal: set secure deletion flags for FSS file --- TODO | 2 ++ src/journal/journalctl.c | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 102a8138b9..875a3db4d6 100644 --- a/TODO +++ b/TODO @@ -49,6 +49,8 @@ Bugfixes: Features: +* man: document in ExecStart= explicitly that we don't take shell command lines, only executable names with arguments + * shutdown: don't read-only mount anything when running in container * nspawn: --read-only is not applied recursively to submounts diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5c21ab0adf..25f41f6322 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include @@ -453,7 +455,7 @@ static int setup_keys(void) { size_t mpk_size, seed_size, state_size, i; uint8_t *mpk, *seed, *state; ssize_t l; - int fd = -1, r; + int fd = -1, r, attr = 0; sd_id128_t machine, boot; char *p = NULL, *k = NULL; struct FSSHeader h; @@ -530,6 +532,16 @@ static int setup_keys(void) { goto finish; } + /* Enable secure remove, exclusion from dump, synchronous + * writing and in-place updating */ + if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0) + log_warning("FS_IOC_GETFLAGS failed: %m"); + + attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL; + + if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0) + log_warning("FS_IOC_SETFLAGS failed: %m"); + zero(h); memcpy(h.signature, "KSHHRHLP", 8); h.machine_id = machine; -- cgit v1.2.3-54-g00ecf From b72631e59c1b9f62bcfaf1ce3f7e72e4a3beee89 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Aug 2012 00:40:03 +0200 Subject: jounral: write bit fiddling test This test goes through every single bit in a journal file, toggles it, and checks if this change is detected by the verification. --- src/journal/journal-verify.c | 32 +++++++++++------- src/journal/journal-verify.h | 2 +- src/journal/journalctl.c | 4 +-- src/journal/test-journal-verify.c | 71 ++++++++++++++++++++++++++++++++++----- 4 files changed, 85 insertions(+), 24 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 39cf3a3313..f66b23556b 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -394,7 +394,8 @@ static int verify_hash_table( int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, - usec_t *last_usec) { + usec_t *last_usec, + bool show_progress) { uint64_t i, n; int r; @@ -409,7 +410,8 @@ static int verify_hash_table( for (i = 0; i < n; i++) { uint64_t last = 0, p; - draw_progress(0xC000 + (0x3FFF * i / n), last_usec); + if (show_progress) + draw_progress(0xC000 + (0x3FFF * i / n), last_usec); p = le64toh(f->data_hash_table[i].head_hash_offset); while (p != 0) { @@ -535,7 +537,8 @@ static int verify_entry_array( int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, - usec_t *last_usec) { + usec_t *last_usec, + bool show_progress) { uint64_t i = 0, a, n, last = 0; int r; @@ -552,7 +555,8 @@ static int verify_entry_array( uint64_t next, m, j; Object *o; - draw_progress(0x8000 + (0x3FFF * i / n), last_usec); + if (show_progress) + draw_progress(0x8000 + (0x3FFF * i / n), last_usec); if (a == 0) { log_error("Array chain too short at %llu of %llu", @@ -674,7 +678,8 @@ static int journal_file_parse_verification_key(JournalFile *f, const char *key) int journal_file_verify( JournalFile *f, const char *key, - usec_t *first_validated, usec_t *last_validated, usec_t *last_contained) { + usec_t *first_validated, usec_t *last_validated, usec_t *last_contained, + bool show_progress) { int r; Object *o; uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0; @@ -728,7 +733,8 @@ int journal_file_verify( p = le64toh(f->header->header_size); while (p != 0) { - draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec); + if (show_progress) + draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec); r = journal_file_move_to_object(f, -1, p, &o); if (r < 0) { @@ -891,8 +897,6 @@ int journal_file_verify( goto fail; } - log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum)); - if (le64toh(o->tag.seqnum) != n_tags + 1) { log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p); r = -EBADMSG; @@ -1070,7 +1074,8 @@ int journal_file_verify( data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, - &last_usec); + &last_usec, + show_progress); if (r < 0) goto fail; @@ -1078,11 +1083,13 @@ int journal_file_verify( data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, - &last_usec); + &last_usec, + show_progress); if (r < 0) goto fail; - flush_progress(); + if (show_progress) + flush_progress(); mmap_cache_close_fd(f->mmap, data_fd); mmap_cache_close_fd(f->mmap, entry_fd); @@ -1102,7 +1109,8 @@ int journal_file_verify( return 0; fail: - flush_progress(); + if (show_progress) + flush_progress(); log_error("File corruption detected at %s:%llu (of %llu, %llu%%).", f->path, diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h index e4449c6ad7..a4633adea9 100644 --- a/src/journal/journal-verify.h +++ b/src/journal/journal-verify.h @@ -23,4 +23,4 @@ #include "journal-file.h" -int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained); +int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained, bool show_progress); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 25f41f6322..ba678a289f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -637,7 +637,7 @@ static int verify(sd_journal *j) { log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif - k = journal_file_verify(f, arg_verify_key, &from, &to, &total); + k = journal_file_verify(f, arg_verify_key, &from, &to, &total, true); if (k == -EINVAL) { /* If the key was invalid give up right-away. */ return k; @@ -648,7 +648,7 @@ static int verify(sd_journal *j) { char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; log_info("PASS: %s", f->path); - if (journal_file_fss_enabled(f)) + if (arg_verify_key && journal_file_fss_enabled(f)) log_info("=> Validated from %s to %s, %s missing", format_timestamp(a, sizeof(a), from), format_timestamp(b, sizeof(b), to), diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c index df0a5ddef9..4e6c119b6d 100644 --- a/src/journal/test-journal-verify.c +++ b/src/journal/test-journal-verify.c @@ -27,19 +27,55 @@ #include "log.h" #include "journal-file.h" #include "journal-verify.h" +#include "journal-authenticate.h" #define N_ENTRIES 6000 #define RANDOM_RANGE 77 +static void bit_toggle(const char *fn, uint64_t p) { + uint8_t b; + ssize_t r; + int fd; + + fd = open(fn, O_RDWR|O_CLOEXEC); + assert(fd >= 0); + + r = pread(fd, &b, 1, p/8); + assert(r == 1); + + b ^= 1 << (p % 8); + + r = pwrite(fd, &b, 1, p/8); + assert(r == 1); + + close_nointr_nofail(fd); +} + +static int raw_verify(const char *fn, const char *verification_key) { + JournalFile *f; + int r; + + r = journal_file_open(fn, O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f); + if (r < 0) + return r; + + r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false); + journal_file_close(f); + + return r; +} + int main(int argc, char *argv[]) { char t[] = "/tmp/journal-XXXXXX"; unsigned n; JournalFile *f; const char *verification_key = argv[1]; - usec_t from, to, total; + usec_t from = 0, to = 0, total = 0; char a[FORMAT_TIMESTAMP_MAX]; char b[FORMAT_TIMESTAMP_MAX]; char c[FORMAT_TIMESPAN_MAX]; + struct stat st; + uint64_t p; log_set_max_level(LOG_DEBUG); @@ -71,19 +107,36 @@ int main(int argc, char *argv[]) { log_info("Verifying..."); - assert_se(journal_file_open("test.journal", O_RDONLY, 0666, false, false, NULL, NULL, NULL, &f) == 0); - + assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f) == 0); journal_file_print_header(f); - assert_se(journal_file_verify(f, verification_key, &from, &to, &total) >= 0); - - log_info("=> Validated from %s to %s, %s missing", - format_timestamp(a, sizeof(a), from), - format_timestamp(b, sizeof(b), to), - format_timespan(c, sizeof(c), total > to ? total - to : 0)); + assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0); + if (verification_key && journal_file_fss_enabled(f)) { + log_info("=> Validated from %s to %s, %s missing", + format_timestamp(a, sizeof(a), from), + format_timestamp(b, sizeof(b), to), + format_timespan(c, sizeof(c), total > to ? total - to : 0)); + } journal_file_close(f); + log_info("Toggling bits..."); + + assert_se(stat("test.journal", &st) >= 0); + + for (p = 240*8; p < ((uint64_t) st.st_size * 8); p ++) { + bit_toggle("test.journal", p); + + log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8); + + if (raw_verify("test.journal", verification_key) >= 0) { + log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8); + sleep(1); + } + + bit_toggle("test.journal", p); + } + log_info("Exiting..."); assert_se(rm_rf_dangerous(t, false, true, false) >= 0); -- cgit v1.2.3-54-g00ecf From f7fab8a5ae7a3b378040203821383f5a8fc91126 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Aug 2012 15:59:33 +0200 Subject: journal: fix tag ordering check --- src/journal/journal-file.c | 7 ++++--- src/journal/journal-verify.c | 11 ++++++----- src/journal/journalctl.c | 2 +- src/journal/test-journal-verify.c | 23 ++++++++++++----------- 4 files changed, 23 insertions(+), 20 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index c6b25ce54b..f419cf6b65 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1855,7 +1855,7 @@ void journal_file_dump(JournalFile *f) { break; case OBJECT_ENTRY: - printf("Type: OBJECT_ENTRY %llu %llu %llu\n", + printf("Type: OBJECT_ENTRY seqnum=%llu monotonic=%llu realtime=%llu\n", (unsigned long long) le64toh(o->entry.seqnum), (unsigned long long) le64toh(o->entry.monotonic), (unsigned long long) le64toh(o->entry.realtime)); @@ -1874,8 +1874,9 @@ void journal_file_dump(JournalFile *f) { break; case OBJECT_TAG: - printf("Type: OBJECT_TAG %llu\n", - (unsigned long long) le64toh(o->tag.seqnum)); + printf("Type: OBJECT_TAG seqnum=%llu epoch=%llu\n", + (unsigned long long) le64toh(o->tag.seqnum), + (unsigned long long) le64toh(o->tag.epoch)); break; } diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index e3c3ccdb20..08f3e16aa9 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -709,7 +709,7 @@ int journal_file_verify( bool show_progress) { int r; Object *o; - uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0; + uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0; uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; sd_id128_t entry_boot_id; bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; @@ -838,7 +838,7 @@ int journal_file_verify( if (r < 0) goto fail; - if (last_tag_realtime > le64toh(o->entry.realtime)) { + if (le64toh(o->entry.realtime) < last_tag_realtime) { log_error("Older entry after newer tag at %llu", (unsigned long long) p); r = -EBADMSG; goto fail; @@ -962,8 +962,8 @@ int journal_file_verify( if (f->seal) { log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum)); - rt = (o->tag.epoch + 1) * f->fss_interval_usec + f->fss_start_usec; - if (entry_realtime_set && entry_realtime >= rt) { + rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec; + if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) { log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p); r = -EBADMSG; goto fail; @@ -1014,6 +1014,7 @@ int journal_file_verify( f->hmac_running = false; last_tag_realtime = rt; + last_sealed_realtime = entry_realtime; } last_tag = p + ALIGN64(le64toh(o->object.size)); @@ -1158,7 +1159,7 @@ int journal_file_verify( if (first_validated) *first_validated = last_tag_realtime ? le64toh(f->header->head_entry_realtime) : 0; if (last_validated) - *last_validated = last_tag_realtime; + *last_validated = last_sealed_realtime; if (last_contained) *last_contained = le64toh(f->header->tail_entry_realtime); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ba678a289f..e61ddf6d92 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -478,7 +478,7 @@ static int setup_keys(void) { return log_oom(); if (access(p, F_OK) >= 0) { - log_error("Evolving key file %s exists already.", p); + log_error("Sealing key file %s exists already.", p); r = -EEXIST; goto finish; } diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c index 4e6c119b6d..ed6e21dc0c 100644 --- a/src/journal/test-journal-verify.c +++ b/src/journal/test-journal-verify.c @@ -108,7 +108,8 @@ int main(int argc, char *argv[]) { log_info("Verifying..."); assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f) == 0); - journal_file_print_header(f); + /* journal_file_print_header(f); */ + journal_file_dump(f); assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0); @@ -120,21 +121,21 @@ int main(int argc, char *argv[]) { } journal_file_close(f); - log_info("Toggling bits..."); + if (verification_key) { + log_info("Toggling bits..."); - assert_se(stat("test.journal", &st) >= 0); + assert_se(stat("test.journal", &st) >= 0); - for (p = 240*8; p < ((uint64_t) st.st_size * 8); p ++) { - bit_toggle("test.journal", p); + for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) { + bit_toggle("test.journal", p); - log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8); + log_info("[ %llu+%llu]", (unsigned long long) p / 8, (unsigned long long) p % 8); - if (raw_verify("test.journal", verification_key) >= 0) { - log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8); - sleep(1); - } + if (raw_verify("test.journal", verification_key) >= 0) + log_notice(ANSI_HIGHLIGHT_RED_ON ">>>> %llu (bit %llu) can be toggled without detection." ANSI_HIGHLIGHT_OFF, (unsigned long long) p / 8, (unsigned long long) p % 8); - bit_toggle("test.journal", p); + bit_toggle("test.journal", p); + } } log_info("Exiting..."); -- cgit v1.2.3-54-g00ecf From feb12d3ed2c7f9132c64773c7c41b9e3a608a814 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Aug 2012 16:51:46 +0200 Subject: journal: make libgcrypt dependency optional --- Makefile.am | 4 +-- README | 1 + TODO | 6 ---- configure.ac | 2 +- src/core/build.h | 20 ++++++++++- src/journal/journal-authenticate.c | 57 ++++++++++++++++++++++++++++-- src/journal/journal-authenticate.h | 2 +- src/journal/journal-file.c | 18 ++++++++++ src/journal/journal-verify.c | 71 ++++++-------------------------------- src/journal/journalctl.c | 30 +++++++++++----- src/journal/test-journal-verify.c | 7 ++-- src/journal/test-journal.c | 2 ++ 12 files changed, 134 insertions(+), 86 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 3eeb842afe..166c357db2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2402,8 +2402,6 @@ libsystemd_journal_la_SOURCES = \ src/journal/journal-vacuum.h \ src/journal/journal-verify.c \ src/journal/journal-verify.h \ - src/journal/journal-authenticate.c \ - src/journal/journal-authenticate.h \ src/journal/lookup3.c \ src/journal/lookup3.h \ src/journal/journal-send.c \ @@ -2455,6 +2453,8 @@ endif if HAVE_GCRYPT libsystemd_journal_la_SOURCES += \ + src/journal/journal-authenticate.c \ + src/journal/journal-authenticate.h \ src/journal/fsprg.c \ src/journal/fsprg.h diff --git a/README b/README index a5d569028d..334c597213 100644 --- a/README +++ b/README @@ -42,6 +42,7 @@ REQUIREMENTS: libcap PAM >= 1.1.2 (optional) libcryptsetup (optional) + libgcrypt (optional) libaudit (optional) libacl (optional) libselinux (optional) diff --git a/TODO b/TODO index 875a3db4d6..e16db6fa4d 100644 --- a/TODO +++ b/TODO @@ -254,8 +254,6 @@ Features: * cleanup syslog 'priority' vs. 'level' wording -* journal: if mmap() fails for mapping window try to unmap a a few older maps - * dbus upstream still refers to dbus.target and shouldn't * when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting @@ -300,8 +298,6 @@ Features: * journal: message catalog -* journal: forward-secure signatures - * document the exit codes when services fail before they are exec()ed * systemctl journal command @@ -503,6 +499,4 @@ Scheduled for removal (or fixing): * xxxOverridable dependencies -* journald.conf: ImportKernel= - * prefdm.service diff --git a/configure.ac b/configure.ac index c1e88daa3f..3df43b91fd 100644 --- a/configure.ac +++ b/configure.ac @@ -302,7 +302,7 @@ AC_SUBST(ACL_LIBS) AM_CONDITIONAL([HAVE_ACL], [test "x$have_acl" != xno]) # ------------------------------------------------------------------------------ -AC_ARG_ENABLE([], +AC_ARG_ENABLE([gcrypt], AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]), [case "${enableval}" in yes) have_gcrypt=yes ;; diff --git a/src/core/build.h b/src/core/build.h index 0b38050bd4..4513a0bad7 100644 --- a/src/core/build.h +++ b/src/core/build.h @@ -63,4 +63,22 @@ #define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP" #endif -#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ +#ifdef HAVE_GCRYPT +#define _GCRYPT_FEATURE_ "+GCRYPT" +#else +#define _GCRYPT_FEATURE_ "-GCRYPT" +#endif + +#ifdef HAVE_ACL +#define _ACL_FEATURE_ "+ACL" +#else +#define _ACL_FEATURE_ "-ACL" +#endif + +#ifdef HAVE_XZ +#define _XZ_FEATURE_ "+XZ" +#else +#define _XZ_FEATURE_ "-XZ" +#endif + +#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ " " _GCRYPT_FEATURE_ " " _ACL_FEATURE_ " " _XZ_FEATURE_ diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index ddcf856aec..93cc9d94a1 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -461,8 +461,59 @@ int journal_file_append_first_tag(JournalFile *f) { return 0; } -bool journal_file_fss_enabled(JournalFile *f) { - assert(f); - return JOURNAL_HEADER_SEALED(f->header); +int journal_file_parse_verification_key(JournalFile *f, const char *key) { + uint8_t *seed; + size_t seed_size, c; + const char *k; + int r; + unsigned long long start, interval; + + seed_size = FSPRG_RECOMMENDED_SEEDLEN; + seed = malloc(seed_size); + if (!seed) + return -ENOMEM; + + k = key; + for (c = 0; c < seed_size; c++) { + int x, y; + + while (*k == '-') + k++; + + x = unhexchar(*k); + if (x < 0) { + free(seed); + return -EINVAL; + } + k++; + y = unhexchar(*k); + if (y < 0) { + free(seed); + return -EINVAL; + } + k++; + + seed[c] = (uint8_t) (x * 16 + y); + } + + if (*k != '/') { + free(seed); + return -EINVAL; + } + k++; + + r = sscanf(k, "%llx-%llx", &start, &interval); + if (r != 2) { + free(seed); + return -EINVAL; + } + + f->fsprg_seed = seed; + f->fsprg_seed_size = seed_size; + + f->fss_start_usec = start * interval; + f->fss_interval_usec = interval; + + return 0; } diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h index 4f4f45b114..447c7b4657 100644 --- a/src/journal/journal-authenticate.h +++ b/src/journal/journal-authenticate.h @@ -36,7 +36,7 @@ int journal_file_hmac_put_header(JournalFile *f); int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p); int journal_file_fss_load(JournalFile *f); -bool journal_file_fss_enabled(JournalFile *f); +int journal_file_parse_verification_key(JournalFile *f, const char *key); int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime); int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 760efaebbb..f01f12496c 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -64,9 +64,11 @@ void journal_file_close(JournalFile *f) { assert(f); +#ifdef HAVE_GCRYPT /* Write the final tag */ if (f->seal && f->writable) journal_file_append_tag(f); +#endif /* Sync everything to disk, before we mark the file offline */ if (f->mmap && f->fd >= 0) @@ -764,9 +766,11 @@ static int journal_file_append_data( if (r < 0) return r; +#ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_DATA, p); if (r < 0) return r; +#endif /* The linking might have altered the window, so let's * refresh our pointer */ @@ -852,9 +856,11 @@ static int link_entry_into_array(JournalFile *f, if (r < 0) return r; +#ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, q); if (r < 0) return r; +#endif o->entry_array.items[i] = htole64(p); @@ -996,9 +1002,11 @@ static int journal_file_append_entry_internal( o->entry.xor_hash = htole64(xor_hash); o->entry.boot_id = f->header->boot_id; +#ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_ENTRY, np); if (r < 0) return r; +#endif r = journal_file_link_entry(f, o, np); if (r < 0) @@ -1049,9 +1057,11 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st ts->monotonic < le64toh(f->header->tail_entry_monotonic)) return -EINVAL; +#ifdef HAVE_GCRYPT r = journal_file_maybe_append_tag(f, ts->realtime); if (r < 0) return r; +#endif /* alloca() can't take 0, hence let's allocate at least one */ items = alloca(sizeof(EntryItem) * MAX(1, n_iovec)); @@ -2030,11 +2040,13 @@ int journal_file_open( if (f->last_stat.st_size == 0 && f->writable) { newly_created = true; +#ifdef HAVE_GCRYPT /* Try to load the FSPRG state, and if we can't, then * just don't do sealing */ r = journal_file_fss_load(f); if (r < 0) f->seal = false; +#endif r = journal_file_init_header(f, template); if (r < 0) @@ -2064,11 +2076,13 @@ int journal_file_open( goto fail; } +#ifdef HAVE_GCRYPT if (!newly_created && f->writable) { r = journal_file_fss_load(f); if (r < 0) goto fail; } +#endif if (f->writable) { if (metrics) { @@ -2082,9 +2096,11 @@ int journal_file_open( goto fail; } +#ifdef HAVE_GCRYPT r = journal_file_hmac_setup(f); if (r < 0) goto fail; +#endif if (newly_created) { r = journal_file_setup_field_hash_table(f); @@ -2095,9 +2111,11 @@ int journal_file_open( if (r < 0) goto fail; +#ifdef HAVE_GCRYPT r = journal_file_append_first_tag(f); if (r < 0) goto fail; +#endif } r = journal_file_map_field_hash_table(f); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 6afeab9a80..a76384bdb2 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "util.h" #include "macro.h" @@ -37,7 +38,6 @@ * * - evolve key even if nothing happened in regular intervals * - * - Allow building without libgcrypt * - check with sparse * - 64bit conversions * @@ -645,62 +645,6 @@ static int verify_entry_array( return 0; } -static int journal_file_parse_verification_key(JournalFile *f, const char *key) { - uint8_t *seed; - size_t seed_size, c; - const char *k; - int r; - unsigned long long start, interval; - - seed_size = FSPRG_RECOMMENDED_SEEDLEN; - seed = malloc(seed_size); - if (!seed) - return -ENOMEM; - - k = key; - for (c = 0; c < seed_size; c++) { - int x, y; - - while (*k == '-') - k++; - - x = unhexchar(*k); - if (x < 0) { - free(seed); - return -EINVAL; - } - k++; - y = unhexchar(*k); - if (y < 0) { - free(seed); - return -EINVAL; - } - k++; - - seed[c] = (uint8_t) (x * 16 + y); - } - - if (*k != '/') { - free(seed); - return -EINVAL; - } - k++; - - r = sscanf(k, "%llx-%llx", &start, &interval); - if (r != 2) { - free(seed); - return -EINVAL; - } - - f->fsprg_seed = seed; - f->fsprg_seed_size = seed_size; - - f->fss_start_usec = start * interval; - f->fss_interval_usec = interval; - - return 0; -} - int journal_file_verify( JournalFile *f, const char *key, @@ -724,11 +668,15 @@ int journal_file_verify( assert(f); if (key) { +#ifdef HAVE_GCRYPT r = journal_file_parse_verification_key(f, key); if (r < 0) { log_error("Failed to parse seed."); return r; } +#else + return -ENOTSUP; +#endif } else if (f->seal) return -ENOKEY; @@ -936,9 +884,7 @@ int journal_file_verify( n_entry_arrays++; break; - case OBJECT_TAG: { - uint64_t q, rt; - + case OBJECT_TAG: if (!JOURNAL_HEADER_SEALED(f->header)) { log_error("Tag object in file without sealing at %llu", (unsigned long long) p); r = -EBADMSG; @@ -957,7 +903,10 @@ int journal_file_verify( goto fail; } +#ifdef HAVE_GCRYPT if (f->seal) { + uint64_t q, rt; + log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum)); rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec; @@ -1014,13 +963,13 @@ int journal_file_verify( last_tag_realtime = rt; last_sealed_realtime = entry_realtime; } +#endif last_tag = p + ALIGN64(le64toh(o->object.size)); last_epoch = le64toh(o->tag.epoch); n_tags ++; break; - } default: n_weird ++; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e61ddf6d92..551cb311b5 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -62,7 +62,9 @@ static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; static const char *arg_verify_key = NULL; +#ifdef HAVE_GCRYPT static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; +#endif static enum { ACTION_SHOW, @@ -93,11 +95,13 @@ static int help(void) { "Commands:\n" " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" +#ifdef HAVE_GCRYPT " --setup-keys Generate new FSS key pair\n" " --interval=TIME Time interval for changing the FSS sealing key\n" " --verify Verify journal file consistency\n" - " --verify-key=KEY Specify FSS verification key\n", - program_invocation_short_name); + " --verify-key=KEY Specify FSS verification key\n" +#endif + , program_invocation_short_name); return 0; } @@ -215,13 +219,15 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_PRINT_HEADER; break; + case ARG_VERIFY: + arg_action = ACTION_VERIFY; + break; + +#ifdef HAVE_GCRYPT case ARG_SETUP_KEYS: arg_action = ACTION_SETUP_KEYS; break; - case ARG_VERIFY: - arg_action = ACTION_VERIFY; - break; case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; @@ -235,6 +241,13 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } break; +#else + case ARG_SETUP_KEYS: + case ARG_VERIFY_KEY: + case ARG_INTERVAL: + log_error("Forward-secure sealing not available."); + return -ENOTSUP; +#endif case 'p': { const char *dots; @@ -617,7 +630,8 @@ finish: return r; #else - log_error("Forward-secure journal verification not available."); + log_error("Forward-secure sealing not available."); + return -ENOTSUP; #endif } @@ -633,7 +647,7 @@ static int verify(sd_journal *j) { usec_t from, to, total; #ifdef HAVE_GCRYPT - if (!arg_verify_key && journal_file_fss_enabled(f)) + if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif @@ -648,7 +662,7 @@ static int verify(sd_journal *j) { char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; log_info("PASS: %s", f->path); - if (arg_verify_key && journal_file_fss_enabled(f)) + if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) log_info("=> Validated from %s to %s, %s missing", format_timestamp(a, sizeof(a), from), format_timestamp(b, sizeof(b), to), diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c index ed6e21dc0c..b6677215c0 100644 --- a/src/journal/test-journal-verify.c +++ b/src/journal/test-journal-verify.c @@ -55,7 +55,7 @@ static int raw_verify(const char *fn, const char *verification_key) { JournalFile *f; int r; - r = journal_file_open(fn, O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f); + r = journal_file_open(fn, O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f); if (r < 0) return r; @@ -107,18 +107,19 @@ int main(int argc, char *argv[]) { log_info("Verifying..."); - assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, true, NULL, NULL, NULL, &f) == 0); + assert_se(journal_file_open("test.journal", O_RDONLY, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0); /* journal_file_print_header(f); */ journal_file_dump(f); assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0); - if (verification_key && journal_file_fss_enabled(f)) { + if (verification_key && JOURNAL_HEADER_SEALED(f->header)) { log_info("=> Validated from %s to %s, %s missing", format_timestamp(a, sizeof(a), from), format_timestamp(b, sizeof(b), to), format_timespan(c, sizeof(c), total > to ? total - to : 0)); } + journal_file_close(f); if (verification_key) { diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 05bb2ea8ed..2273500100 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -59,7 +59,9 @@ int main(int argc, char *argv[]) { iovec.iov_len = strlen(test); assert_se(journal_file_append_entry(f, &ts, &iovec, 1, NULL, NULL, NULL) == 0); +#ifdef HAVE_GCRYPT journal_file_append_tag(f); +#endif journal_file_dump(f); assert(journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, &p) == 1); -- cgit v1.2.3-54-g00ecf From f6a971bc0bf1252e9614919ccca0d53db5fc53d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Aug 2012 22:02:19 +0200 Subject: journalctl: output FSS key as QR code on generating --- Makefile.am | 12 ++++ configure.ac | 13 +++++ src/journal/journal-qrcode.c | 127 +++++++++++++++++++++++++++++++++++++++++++ src/journal/journal-qrcode.h | 30 ++++++++++ src/journal/journalctl.c | 17 +++++- src/shared/util.c | 1 - 6 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 src/journal/journal-qrcode.c create mode 100644 src/journal/journal-qrcode.h (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index 166c357db2..69cdeb7145 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2353,6 +2353,18 @@ journalctl_LDADD = \ libsystemd-id128-internal.la \ libsystemd-logs.la +if HAVE_QRENCODE +journalctl_SOURCES += \ + src/journal/journal-qrcode.c \ + src/journal/journal-qrcode.h + +journalctl_CFLAGS += \ + $(QRENCODE_CFLAGS) + +journalctl_LDADD += \ + $(QRENCODE_LIBS) +endif + test_journal_SOURCES = \ src/journal/test-journal.c diff --git a/configure.ac b/configure.ac index 3df43b91fd..52adb20e0b 100644 --- a/configure.ac +++ b/configure.ac @@ -383,6 +383,18 @@ if test "x$enable_libcryptsetup" != "xno"; then fi AM_CONDITIONAL(HAVE_LIBCRYPTSETUP, [test "$have_libcryptsetup" = "yes"]) +# ------------------------------------------------------------------------------ +have_qrencode=no +AC_ARG_ENABLE(qrencode, AS_HELP_STRING([--disable-qrencode], [disable qrencode support])) +if test "x$enable_qrencode" != "xno"; then + PKG_CHECK_MODULES(QRENCODE, [ libqrencode ], + [AC_DEFINE(HAVE_QRENCODE, 1, [Define if qrencode is available]) have_qrencode=yes], have_qrencode=no) + if test "x$have_qrencode" = xno -a "x$enable_qrencode" = xyes; then + AC_MSG_ERROR([*** qrencode support requested but libraries not found]) + fi +fi +AM_CONDITIONAL(HAVE_QRENCODE, [test "$have_qrencode" = "yes"]) + # ------------------------------------------------------------------------------ have_binfmt=no AC_ARG_ENABLE(binfmt, AS_HELP_STRING([--disable-binfmt], [disable binfmt tool])) @@ -760,6 +772,7 @@ AC_MSG_RESULT([ XZ: ${have_xz} ACL: ${have_acl} GCRYPT: ${have_gcrypt} + QRENCODE: ${have_qrencode} binfmt: ${have_binfmt} vconsole: ${have_vconsole} readahead: ${have_readahead} diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c new file mode 100644 index 0000000000..b4dab8e86a --- /dev/null +++ b/src/journal/journal-qrcode.c @@ -0,0 +1,127 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include + +#include "journal-qrcode.h" + +#define WHITE_ON_BLACK "\033[40;37;1m" +#define NORMAL "\033[0m" + +static void print_border(FILE *output, unsigned width) { + unsigned x, y; + + /* Four rows of border */ + for (y = 0; y < 4; y += 2) { + fputs(WHITE_ON_BLACK, output); + + for (x = 0; x < 4 + width + 4; x++) + fputs("\342\226\210", output); + + fputs(NORMAL "\n", output); + } +} + +int print_qr_code(FILE *output, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t mahcine) { + FILE *f; + char *url = NULL; + size_t url_size = 0, i; + QRcode* qr; + unsigned x, y; + + assert(seed); + assert(seed_size > 0); + + f = open_memstream(&url, &url_size); + if (!f) + return -ENOMEM; + + fputs("fss://", f); + + for (i = 0; i < seed_size; i++) { + if (i > 0 && i % 3 == 0) + fputc('-', f); + fprintf(f, "%02x", ((uint8_t*) seed)[i]); + } + + fprintf(f, "/%llx-%llx\n", (unsigned long long) start, (unsigned long long) interval); + + if (hn) + fprintf(f, "?hostname=%s", hn); + + if (ferror(f)) { + fclose(f); + free(url); + return -ENOMEM; + } + + fclose(f); + + qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); + free(url); + + if (!qr) + return -ENOMEM; + + print_border(output, qr->width); + + for (y = 0; y < (unsigned) qr->width; y += 2) { + const uint8_t *row1, *row2; + + row1 = qr->data + qr->width * y; + row2 = row1 + qr->width; + + fputs(WHITE_ON_BLACK, output); + for (x = 0; x < 4; x++) + fputs("\342\226\210", output); + + for (x = 0; x < (unsigned) qr->width; x ++) { + bool a, b; + + a = row1[x] & 1; + b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; + + if (a && b) + fputc(' ', output); + else if (a) + fputs("\342\226\204", output); + else if (b) + fputs("\342\226\200", output); + else + fputs("\342\226\210", output); + } + + for (x = 0; x < 4; x++) + fputs("\342\226\210", output); + fputs(NORMAL "\n", output); + } + + print_border(output, qr->width); + + QRcode_free(qr); + return 0; +} diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h new file mode 100644 index 0000000000..da6244c160 --- /dev/null +++ b/src/journal/journal-qrcode.h @@ -0,0 +1,30 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include + +int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 551cb311b5..b0d8258dd2 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -46,6 +46,7 @@ #include "journal-def.h" #include "journal-verify.h" #include "journal-authenticate.h" +#include "journal-qrcode.h" #include "fsprg.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -607,12 +608,26 @@ static int setup_keys(void) { printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); if (isatty(STDOUT_FILENO)) { - char tsb[FORMAT_TIMESPAN_MAX]; + char tsb[FORMAT_TIMESPAN_MAX], *hn; fprintf(stderr, ANSI_HIGHLIGHT_OFF "\n" "The sealing key is automatically changed every %s.\n", format_timespan(tsb, sizeof(tsb), arg_interval)); + + hn = gethostname_malloc(); + + if (hn) { + hostname_cleanup(hn); + fprintf(stderr, "The keys have been generated for host %s (" SD_ID128_FORMAT_STR ").\n", hn, SD_ID128_FORMAT_VAL(machine)); + } else + fprintf(stderr, "The keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); + +#ifdef HAVE_QRENCODE + fputc('\n', stderr); + print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); +#endif + free(hn); } r = 0; diff --git a/src/shared/util.c b/src/shared/util.c index cbf44ebdfd..041b759287 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3089,7 +3089,6 @@ bool hostname_is_set(void) { return !isempty(u.nodename) && !streq(u.nodename, "(none)"); } - static char *lookup_uid(uid_t uid) { long bufsize; char *buf, *name; -- cgit v1.2.3-54-g00ecf From 197c0da22536121acc1377525458844a5ccabb7d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Aug 2012 22:11:55 +0200 Subject: journalctl: explain QR code use --- src/journal/journalctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b0d8258dd2..3fcdf4b4a2 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -626,6 +626,7 @@ static int setup_keys(void) { #ifdef HAVE_QRENCODE fputc('\n', stderr); print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); + fprintf(stderr, "\nScan this QR code with your mobile phone to transfer the verification key to it.\n"); #endif free(hn); } -- cgit v1.2.3-54-g00ecf From adac1c93ab355b8aa45ecbcf7879ec98b44d36f8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Aug 2012 22:22:05 +0200 Subject: journal: rearrange QR code output a bit to fi to 80x25 terminals --- src/journal/journalctl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 3fcdf4b4a2..7f25cdb9a2 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -619,14 +619,13 @@ static int setup_keys(void) { if (hn) { hostname_cleanup(hn); - fprintf(stderr, "The keys have been generated for host %s (" SD_ID128_FORMAT_STR ").\n", hn, SD_ID128_FORMAT_VAL(machine)); + fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine)); } else - fprintf(stderr, "The keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); + fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); #ifdef HAVE_QRENCODE - fputc('\n', stderr); + fprintf(stderr, "\nTo transfer the verification key to your phone please scan the QR code below:\n\n"); print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); - fprintf(stderr, "\nScan this QR code with your mobile phone to transfer the verification key to it.\n"); #endif free(hn); } -- cgit v1.2.3-54-g00ecf From c05276f23e216a706936f1ee45a7005f86b3599c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Aug 2012 01:02:08 +0200 Subject: journalctl: reword things a bit --- src/journal/journalctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7f25cdb9a2..1dee74a935 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -590,7 +590,8 @@ static int setup_keys(void) { fprintf(stderr, "\n" "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n" - "the following local file. It should not be used on multiple hosts.\n" + "the following local file. This key file is automatically updated when the\n" + "sealing key is advanced. It should not be used on multiple hosts.\n" "\n" "\t%s\n" "\n" -- cgit v1.2.3-54-g00ecf From 89fef99014662a5a63e7deaedd6292b7fb4ab2f8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Aug 2012 01:29:17 +0200 Subject: journal: automatically evolve FSS key even when nothing is logged --- src/journal/journal-authenticate.c | 19 ++++++++++++++++++ src/journal/journal-authenticate.h | 2 ++ src/journal/journal-verify.c | 8 -------- src/journal/journalctl.c | 1 + src/journal/journald.c | 41 ++++++++++++++++++++++++++++++-------- 5 files changed, 55 insertions(+), 16 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index 435481000d..fd81797cf9 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -211,6 +211,9 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { if (!f->seal) return 0; + if (realtime <= 0) + realtime = now(CLOCK_MONOTONIC); + r = journal_file_fsprg_need_evolve(f, realtime); if (r <= 0) return 0; @@ -517,3 +520,19 @@ int journal_file_parse_verification_key(JournalFile *f, const char *key) { return 0; } + +bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u) { + uint64_t epoch; + + assert(f); + assert(u); + + if (!f->seal) + return false; + + epoch = FSPRG_GetEpoch(f->fsprg_state); + + *u = (usec_t) (f->fss_start_usec + f->fss_interval_usec * epoch + f->fss_interval_usec); + + return true; +} diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h index 447c7b4657..3586464d1e 100644 --- a/src/journal/journal-authenticate.h +++ b/src/journal/journal-authenticate.h @@ -40,3 +40,5 @@ int journal_file_parse_verification_key(JournalFile *f, const char *key); int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime); int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); + +bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 29a9229e53..8604b6e7cb 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -34,14 +34,6 @@ #include "compress.h" #include "fsprg.h" -/* FIXME: - * - * - evolve key even if nothing happened in regular intervals - * - * - check with sparse - * - * */ - static int journal_file_object_verify(JournalFile *f, Object *o) { uint64_t i; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 1dee74a935..0bbf4a045d 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -233,6 +233,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; arg_verify_key = optarg; + arg_local = true; break; case ARG_INTERVAL: diff --git a/src/journal/journald.c b/src/journal/journald.c index 7b3b6471de..f2dd4050b6 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -48,6 +48,7 @@ #include "journal-rate-limit.h" #include "journal-internal.h" #include "journal-vacuum.h" +#include "journal-authenticate.h" #include "conf-parser.h" #include "journald.h" #include "virt.h" @@ -2969,8 +2970,26 @@ int main(int argc, char *argv[]) { for (;;) { struct epoll_event event; + int t; - r = epoll_wait(server.epoll_fd, &event, 1, -1); +#ifdef HAVE_GCRYPT + usec_t u; + + if (server.system_journal && + journal_file_next_evolve_usec(server.system_journal, &u)) { + usec_t n; + + n = now(CLOCK_MONOTONIC); + + if (n >= u) + t = 0; + else + t = (int) ((u - n + USEC_PER_MSEC - 1) / USEC_PER_MSEC); + } else +#endif + t = -1; + + r = epoll_wait(server.epoll_fd, &event, 1, t); if (r < 0) { if (errno == EINTR) @@ -2979,14 +2998,20 @@ int main(int argc, char *argv[]) { log_error("epoll_wait() failed: %m"); r = -errno; goto finish; - } else if (r == 0) - break; + } - r = process_event(&server, &event); - if (r < 0) - goto finish; - else if (r == 0) - break; + if (r > 0) { + r = process_event(&server, &event); + if (r < 0) + goto finish; + else if (r == 0) + break; + } + +#ifdef HAVE_GCRYPT + if (server.system_journal) + journal_file_maybe_append_tag(server.system_journal, 0); +#endif } log_debug("systemd-journald stopped as pid %lu", (unsigned long) getpid()); -- cgit v1.2.3-54-g00ecf From cedb42bb694ef866b18608b14ac269d1ef7513f8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Aug 2012 15:53:48 +0200 Subject: journalctl: add a bit of color to the output --- src/journal/journalctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0bbf4a045d..36c3d2b688 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -659,13 +659,15 @@ static int verify(sd_journal *j) { assert(j); + log_show_color(true); + HASHMAP_FOREACH(f, j->files, i) { int k; usec_t from, to, total; #ifdef HAVE_GCRYPT if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) - log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); + log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif k = journal_file_verify(f, arg_verify_key, &from, &to, &total, true); -- cgit v1.2.3-54-g00ecf From c0ca7aeec963207b6fa5ee39bd204cb26cba4023 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Aug 2012 23:03:20 +0200 Subject: journalctl: be more friendly when informing about seal verification --- TODO | 6 ++++++ src/journal/journal-verify.c | 2 +- src/journal/journalctl.c | 17 ++++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 56e264ce42..7f53535401 100644 --- a/TODO +++ b/TODO @@ -49,6 +49,12 @@ Bugfixes: Features: +* cleanup ellipsation for log output in journalctl and systemctl status: have a sane way to disable ellipsation, and disable it by default when invoked in less/more + +* enforce limits on fds openened by socket units + +* proper service failure code for services which hit the restart limit + * explore multiple service instances per listening socket idea * testing tool for socket activation: some binary that listens on a socket and passes it on using the usual socket activation protocol to some server. diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 9156fd5dc0..24012931d4 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -1118,7 +1118,7 @@ int journal_file_verify( close_nointr_nofail(entry_array_fd); if (first_validated) - *first_validated = last_tag_realtime ? le64toh(f->header->head_entry_realtime) : 0; + *first_validated = last_sealed_realtime > 0 ? le64toh(f->header->head_entry_realtime) : 0; if (last_validated) *last_validated = last_sealed_realtime; if (last_contained) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 36c3d2b688..bee26fd769 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -681,11 +681,18 @@ static int verify(sd_journal *j) { char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; log_info("PASS: %s", f->path); - if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) - log_info("=> Validated from %s to %s, %s missing", - format_timestamp(a, sizeof(a), from), - format_timestamp(b, sizeof(b), to), - format_timespan(c, sizeof(c), total > to ? total - to : 0)); + if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) { + if (from > 0) { + log_info("=> Validated from %s to %s, final %s entries not sealed.", + format_timestamp(a, sizeof(a), from), + format_timestamp(b, sizeof(b), to), + format_timespan(c, sizeof(c), total > to ? total - to : 0)); + } else if (total > 0) + log_info("=> No sealing yet, %s of entries not sealed.", + format_timespan(c, sizeof(c), total)); + else + log_info("=> No sealing yet, no entries in file."); + } } } -- cgit v1.2.3-54-g00ecf From 99add6fd0b8f4307ed79256e25f38da318e795c4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Aug 2012 04:45:17 +0200 Subject: journalctl: complain if unprivileged users attempt to access the journal and persistant logging is off --- TODO | 10 +--------- src/journal/journalctl.c | 14 +++++++++++++- src/journal/journald.c | 10 ++++++---- 3 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 28141ec68c..ee90aee739 100644 --- a/TODO +++ b/TODO @@ -61,14 +61,10 @@ Features: * testing tool for socket activation: some binary that listens on a socket and passes it on using the usual socket activation protocol to some server. -* journald: add symlinks and device names to kernel messages - * maybe make systemd-detect-virt suid? or use fscaps? * consider using __secure_getenv() instead of getenv() in libs -* journald: automatic rekeying with no log messages doesn't appear to work - * man: document in ExecStart= explicitly that we don't take shell command lines, only executable names with arguments * shutdown: don't read-only mount anything when running in container @@ -135,14 +131,10 @@ Features: * switch-root: sockets need relabelling -* segfault in journalctl during /var migration - * systemd-analyze post-boot is broken for initrd * man: clarify that time-sync.target is not only sysv compat but also useful otherwise. Same for similar targets -* journalctl should complain if run with uid != 0 and no persistent logs exist - * .device aliases need to be implemented with the "following" logic, probably. * refuse taking lower-case variable names in sd_journal_send() and friends. @@ -188,7 +180,7 @@ Features: * systemctl: when stopping a service which has triggres and warning about it actually check the TriggeredBy= deps fields -* journal: hook up with EFI firmware log, new kmsg logic +* journal: hook up with EFI firmware log * handle C-A-Del in logind, like the power/suspend buttons? diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index bee26fd769..6aff1f1ba3 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -747,8 +747,20 @@ int main(int argc, char *argv[]) { } #ifdef HAVE_ACL + if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) { + log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages."); + r = -EACCES; + goto finish; + } + if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) - log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this message off."); + log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off."); +#else + if (geteuid() != 0 && in_group("adm") <= 0) { + log_error("No access to messages. Only users in the group 'adm' can see messages."); + r = -EACCES; + goto finish; + } #endif r = add_this_boot(j); diff --git a/src/journal/journald.c b/src/journal/journald.c index 476d682fda..a1deceabdf 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -360,7 +360,8 @@ static void server_vacuum(Server *s) { sd_id128_to_string(machine, ids); if (s->system_journal) { - if (asprintf(&p, "/var/log/journal/%s", ids) < 0) { + p = strappend("/var/log/journal/", ids); + if (!p) { log_oom(); return; } @@ -372,7 +373,8 @@ static void server_vacuum(Server *s) { } if (s->runtime_journal) { - if (asprintf(&p, "/run/log/journal/%s", ids) < 0) { + p = strappend("/run/log/journal/", ids); + if (!p) { log_oom(); return; } @@ -1394,7 +1396,7 @@ static int server_init(Server *s) { return 0; } -static void maybe_append_tags(Server *s) { +static void server_maybe_append_tags(Server *s) { #ifdef HAVE_GCRYPT JournalFile *f; Iterator i; @@ -1539,7 +1541,7 @@ int main(int argc, char *argv[]) { break; } - maybe_append_tags(&server); + server_maybe_append_tags(&server); } log_debug("systemd-journald stopped as pid %lu", (unsigned long) getpid()); -- cgit v1.2.3-54-g00ecf From a6e87e90ede66815989ba2db92a07102a69906fe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 5 Sep 2012 15:25:32 -0700 Subject: journalctl: rework JSON output mode This splits the JSON output mode into different modes: json and json-pretty. The former printing one entry per line, the latter showing JSON objects nicely indented and in multiple lines to make it easier to read for humans. --- TODO | 6 ++-- man/journalctl.xml | 9 +++++- src/journal/journal-send.c | 2 +- src/journal/journalctl.c | 10 +------ src/shared/logs-show.c | 75 ++++++++++++++++++++++++---------------------- src/shared/logs-show.h | 10 +++---- src/systemctl/systemctl.c | 2 +- 7 files changed, 59 insertions(+), 55 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index 92d709ee4e..e683eeaebf 100644 --- a/TODO +++ b/TODO @@ -49,6 +49,8 @@ Bugfixes: Features: +* log fewer journal internal messages to the kernel kmsg + * move keymaps to /usr/lib/... rather than /usr/lib/udev/... * journald: check whether it is OK if the client can still modify delivered journal entries @@ -72,7 +74,7 @@ Features: * securityfs: don't mount in container -* slave/shared remount root fs in container +* slave/shared remount root fs in container might clash with CAP_SYS_MOUNTS * ability to pass fds into systemd @@ -327,7 +329,7 @@ Features: * dbus: in fedora, make the machine a symlink to /etc/machine-id -* dbus: on fedora, move dbus to early boot +* dbus: move dbus to early boot * journald: reuse XZ context diff --git a/man/journalctl.xml b/man/journalctl.xml index 1ea004fc81..b5950c94ce 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -189,6 +189,7 @@ verbose, export, json, + json-pretty, cat. short is the default and generates an output that is mostly identical to the @@ -209,7 +210,13 @@ Export Format for more information). json formats entries as JSON data - structures. cat + structures, one per + line. json-pretty + also formats entries as JSON data + structures, but formats them in + multiple lines in order to make them + more readable for + humans. cat generates a very terse output only showing the actual message of each journal entry with no meta data, not diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index d0f3b725ff..b192f1fb88 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -439,7 +439,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve memcpy(header, identifier, l); header[l++] = '\n'; - header[l++] = '\n'; + header[l++] = '\n'; /* unit id */ header[l++] = '0' + priority; header[l++] = '\n'; header[l++] = '0' + !!level_prefix; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6aff1f1ba3..56a8abea57 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -87,7 +87,7 @@ static int help(void) { " -n --lines=INTEGER Journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, cat)\n" + " verbose, export, json, json-pretty, cat)\n" " -q --quiet Don't show privilege warning\n" " -l --local Only local entries\n" " -b --this-boot Show data only from current boot\n" @@ -821,11 +821,6 @@ int main(int argc, char *argv[]) { on_tty(); have_pager = !arg_no_pager && !arg_follow && pager_open(); - if (arg_output == OUTPUT_JSON) { - fputc('[', stdout); - fflush(stdout); - } - for (;;) { for (;;) { sd_id128_t boot_id; @@ -874,9 +869,6 @@ int main(int argc, char *argv[]) { } } - if (arg_output == OUTPUT_JSON) - fputs("\n]\n", stdout); - finish: if (j) sd_journal_close(j); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 67b20563df..d60e5e5308 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -76,7 +76,7 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, unsigned line, unsigned n_columns, +static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { int r; const void *data; @@ -152,7 +152,7 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; - if (flags & OUTPUT_MONOTONIC_MODE) { + if (mode == OUTPUT_SHORT_MONOTONIC) { uint64_t t; sd_id128_t boot_id; @@ -278,17 +278,7 @@ finish: return r; } -static int output_short_realtime(sd_journal *j, unsigned line, - unsigned n_columns, OutputFlags flags) { - return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE); -} - -static int output_short_monotonic(sd_journal *j, unsigned line, - unsigned n_columns, OutputFlags flags) { - return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE); -} - -static int output_verbose(sd_journal *j, unsigned line, +static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { const void *data; size_t length; @@ -340,7 +330,7 @@ static int output_verbose(sd_journal *j, unsigned line, return 0; } -static int output_export(sd_journal *j, unsigned line, +static int output_export(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { sd_id128_t boot_id; char sid[33]; @@ -452,7 +442,7 @@ static void json_escape(const char* p, size_t l) { } } -static int output_json(sd_journal *j, unsigned line, +static int output_json(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { uint64_t realtime, monotonic; char *cursor; @@ -482,21 +472,25 @@ static int output_json(sd_journal *j, unsigned line, return r; } - if (line == 1) - fputc('\n', stdout); + if (mode == OUTPUT_JSON_PRETTY) + printf("{\n" + "\t\"__CURSOR\" : \"%s\",\n" + "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" + "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" + "\t\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); else - fputs(",\n", stdout); - - printf("{\n" - "\t\"__CURSOR\" : \"%s\",\n" - "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" - "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" - "\t\"_BOOT_ID\" : \"%s\"", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); - + printf("{ \"__CURSOR\" : \"%s\", " + "\"__REALTIME_TIMESTAMP\" : \"%llu\", " + "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", " + "\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { @@ -514,18 +508,25 @@ static int output_json(sd_journal *j, unsigned line, return -EINVAL; } - fputs(",\n\t", stdout); + if (mode == OUTPUT_JSON_PRETTY) + fputs(",\n\t", stdout); + else + fputs(", ", stdout); + json_escape(data, c - (const char*) data); fputs(" : ", stdout); json_escape(c + 1, length - (c - (const char*) data) - 1); } - fputs("\n}", stdout); + if (mode == OUTPUT_JSON_PRETTY) + fputs("\n}\n", stdout); + else + fputs(" }\n", stdout); return 0; } -static int output_cat(sd_journal *j, unsigned line, +static int output_cat(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { const void *data; size_t l; @@ -547,13 +548,14 @@ static int output_cat(sd_journal *j, unsigned line, return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) = { - [OUTPUT_SHORT] = output_short_realtime, - [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, + [OUTPUT_SHORT] = output_short, + [OUTPUT_SHORT_MONOTONIC] = output_short, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json, + [OUTPUT_JSON_PRETTY] = output_json, [OUTPUT_CAT] = output_cat }; @@ -566,7 +568,7 @@ int output_journal(sd_journal *j, OutputMode mode, unsigned line, if (n_columns <= 0) n_columns = columns(); - ret = output_funcs[mode](j, line, n_columns, flags); + ret = output_funcs[mode](j, mode, line, n_columns, flags); fflush(stdout); return ret; } @@ -736,6 +738,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_VERBOSE] = "verbose", [OUTPUT_EXPORT] = "export", [OUTPUT_JSON] = "json", + [OUTPUT_JSON_PRETTY] = "json-pretty", [OUTPUT_CAT] = "cat" }; diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 58ff9e5760..3e6b6e0f64 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -33,6 +33,7 @@ typedef enum OutputMode { OUTPUT_VERBOSE, OUTPUT_EXPORT, OUTPUT_JSON, + OUTPUT_JSON_PRETTY, OUTPUT_CAT, _OUTPUT_MODE_MAX, _OUTPUT_MODE_INVALID = -1 @@ -40,11 +41,10 @@ typedef enum OutputMode { typedef enum OutputFlags { OUTPUT_SHOW_ALL = 1 << 0, - OUTPUT_MONOTONIC_MODE = 1 << 1, - OUTPUT_FOLLOW = 1 << 2, - OUTPUT_WARN_CUTOFF = 1 << 3, - OUTPUT_FULL_WIDTH = 1 << 4, - OUTPUT_COLOR = 1 << 5 + OUTPUT_FOLLOW = 1 << 1, + OUTPUT_WARN_CUTOFF = 1 << 2, + OUTPUT_FULL_WIDTH = 1 << 3, + OUTPUT_COLOR = 1 << 4 } OutputFlags; int output_journal(sd_journal *j, OutputMode mode, unsigned line, diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2481849232..871a04bc1b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3871,7 +3871,7 @@ static int systemctl_help(void) { " -n --lines=INTEGER Journal entries to show\n" " --follow Follow journal\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, cat)\n\n" + " verbose, export, json, json-pretty, cat)\n\n" "Unit Commands:\n" " list-units List loaded units\n" " start [NAME...] Start (activate) one or more units\n" -- cgit v1.2.3-54-g00ecf From 9e8a535faa370bab283cb2c3c52b0a0d44e9d193 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 5 Sep 2012 16:49:00 -0700 Subject: journalctl: replace --local by --merge, i.e. don't interleave remote journals by default --- man/journalctl.xml | 10 ++++++---- src/journal/journalctl.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index b5950c94ce..296e3fd2ff 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -234,11 +234,13 @@ - - + + - Show only locally - generated messages. + Show entries + interleaved from all available + journals, including remote + ones. diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 56a8abea57..73e8cb8809 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -58,7 +58,7 @@ static bool arg_no_pager = false; static int arg_lines = -1; static bool arg_no_tail = false; static bool arg_quiet = false; -static bool arg_local = false; +static bool arg_merge = false; static bool arg_this_boot = false; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; @@ -89,7 +89,7 @@ static int help(void) { " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, json-pretty, cat)\n" " -q --quiet Don't show privilege warning\n" - " -l --local Only local entries\n" + " -m --merge Show entries from all available journals\n" " -b --this-boot Show data only from current boot\n" " -D --directory=PATH Show journal files from directory\n" " -p --priority=RANGE Show only messages within the specified priority range\n\n" @@ -132,7 +132,7 @@ static int parse_argv(int argc, char *argv[]) { { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, - { "local", no_argument, NULL, 'l' }, + { "merge", no_argument, NULL, 'm' }, { "this-boot", no_argument, NULL, 'b' }, { "directory", required_argument, NULL, 'D' }, { "header", no_argument, NULL, ARG_HEADER }, @@ -149,7 +149,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:qlbD:p:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an:qmbD:p:", options, NULL)) >= 0) { switch (c) { @@ -204,8 +204,8 @@ static int parse_argv(int argc, char *argv[]) { arg_quiet = true; break; - case 'l': - arg_local = true; + case 'm': + arg_merge = true; break; case 'b': @@ -233,7 +233,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; arg_verify_key = optarg; - arg_local = true; + arg_merge = false; break; case ARG_INTERVAL: @@ -728,7 +728,7 @@ int main(int argc, char *argv[]) { if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, 0); else - r = sd_journal_open(&j, arg_local ? SD_JOURNAL_LOCAL_ONLY : 0); + r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY); if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); -- cgit v1.2.3-54-g00ecf From cd931c0a464da9d0555e6a8e83c1aba176c0971b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 5 Sep 2012 16:52:46 -0700 Subject: journalctl: show "Reboot" markers in output only when showing local-only entries --- src/journal/journalctl.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 73e8cb8809..1a6464d5e7 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -823,7 +823,6 @@ int main(int argc, char *argv[]) { for (;;) { for (;;) { - sd_id128_t boot_id; int flags = arg_show_all * OUTPUT_SHOW_ALL | have_pager * OUTPUT_FULL_WIDTH | @@ -840,14 +839,18 @@ int main(int argc, char *argv[]) { if (r == 0) break; - r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); - if (r >= 0) { - if (previous_boot_id_valid && - !sd_id128_equal(boot_id, previous_boot_id)) - printf(ANSI_HIGHLIGHT_ON "----- Reboot -----" ANSI_HIGHLIGHT_OFF "\n"); + if (!arg_merge) { + sd_id128_t boot_id; - previous_boot_id = boot_id; - previous_boot_id_valid = true; + r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); + if (r >= 0) { + if (previous_boot_id_valid && + !sd_id128_equal(boot_id, previous_boot_id)) + printf(ANSI_HIGHLIGHT_ON "----- Reboot -----" ANSI_HIGHLIGHT_OFF "\n"); + + previous_boot_id = boot_id; + previous_boot_id_valid = true; + } } line ++; -- cgit v1.2.3-54-g00ecf From a1a03e3075316e2376176fc54c74e071adc9d71a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Sep 2012 23:20:28 +0200 Subject: journal: add call to determine current journal file disk usage --- Makefile.am | 1 + TODO | 2 - man/journalctl.xml | 8 +++ man/sd-journal.xml | 4 +- man/sd_journal_get_usage.xml | 104 +++++++++++++++++++++++++++++++++++++ src/journal/journal-file.c | 5 ++ src/journal/journalctl.c | 25 ++++++++- src/journal/libsystemd-journal.sym | 5 ++ src/journal/sd-journal.c | 23 ++++++++ src/systemd/sd-journal.h | 2 + 10 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 man/sd_journal_get_usage.xml (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index f88d193b41..7ccec67133 100644 --- a/Makefile.am +++ b/Makefile.am @@ -513,6 +513,7 @@ MANPAGES = \ man/sd_journal_get_cutoff_realtime_usec.3 \ man/sd_journal_get_cursor.3 \ man/sd_journal_get_fd.3 \ + man/sd_journal_get_usage.3 \ man/sd_journal_add_match.3 \ man/sd_journal_seek_head.3 diff --git a/TODO b/TODO index 30e2f8e248..de7639e863 100644 --- a/TODO +++ b/TODO @@ -126,8 +126,6 @@ Features: * add _SYSTEMD_USER_UNIT= field to journal entries -* journal: expose current disk usage - * dracut-shutdown needs to be ordered before unmounting /boot * wiki: document new logind LockSessions() call diff --git a/man/journalctl.xml b/man/journalctl.xml index 296e3fd2ff..9800cf30ed 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -320,6 +320,14 @@ accessed. + + + + Shows the current disk + usage of all + journal files. + + diff --git a/man/sd-journal.xml b/man/sd-journal.xml index b6241a1767..773689c692 100644 --- a/man/sd-journal.xml +++ b/man/sd-journal.xml @@ -78,7 +78,8 @@ sd_journal_add_match3, sd_journal_seek_head3, sd_journal_get_cursor3, - sd_journal_cutoff_realtime_usec3 + sd_journal_cutoff_realtime_usec3, + sd_journal_get_usage3 and sd_journal_get_fd3 for more information about the functions @@ -116,6 +117,7 @@ sd_journal_seek_head3, sd_journal_get_cursor3, sd_journal_cutoff_realtime_usec3, + sd_journal_get_usage3, journalctl1, sd-id1283, pkg-config1 diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml new file mode 100644 index 0000000000..14eb1e2b79 --- /dev/null +++ b/man/sd_journal_get_usage.xml @@ -0,0 +1,104 @@ + + + + + + + + + sd_journal_get_usage + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + sd_journal_get_usage + 3 + + + + sd_journal_get_usage + Journal disk usage + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_usage + sd_journal* j + uint64_t* bytes + + + + + + + Description + + sd_journal_get_usage() + determines the total disk space currently used up by + journal files. If + SD_JOURNAL_LOCAL_ONLY has been + passed when opening the journal files this value will + only reflect the size of journal files of the local + host, otherwise of all hosts. + + + + Return Value + + sd_journal_get_usage() + returns 0 on success or a negative errno-style error + code. + + + + Notes + + The sd_journal_get_usage() + interface is available as shared library, which can be + compiled and linked to with the + libsystemd-journal + pkg-config1 + file. + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + + + + diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 697e7f3606..06de2acc50 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1906,6 +1906,8 @@ fail: void journal_file_print_header(JournalFile *f) { char a[33], b[33], c[33]; char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX]; + struct stat st; + char bytes[FORMAT_BYTES_MAX]; assert(f); @@ -1970,6 +1972,9 @@ void journal_file_print_header(JournalFile *f) { if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) printf("Entry Array Objects: %llu\n", (unsigned long long) le64toh(f->header->n_entry_arrays)); + + if (fstat(f->fd, &st) >= 0) + printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (off_t) st.st_blocks * 512ULL)); } int journal_file_open( diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 1a6464d5e7..e2600542fc 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -72,7 +72,8 @@ static enum { ACTION_NEW_ID128, ACTION_PRINT_HEADER, ACTION_SETUP_KEYS, - ACTION_VERIFY + ACTION_VERIFY, + ACTION_DISK_USAGE, } arg_action = ACTION_SHOW; static int help(void) { @@ -96,6 +97,7 @@ static int help(void) { "Commands:\n" " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" + " --disk-usage Show total disk usage\n" #ifdef HAVE_GCRYPT " --setup-keys Generate new FSS key pair\n" " --interval=TIME Time interval for changing the FSS sealing key\n" @@ -118,7 +120,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_SETUP_KEYS, ARG_INTERVAL, ARG_VERIFY, - ARG_VERIFY_KEY + ARG_VERIFY_KEY, + ARG_DISK_USAGE }; static const struct option options[] = { @@ -141,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) { { "interval", required_argument, NULL, ARG_INTERVAL }, { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, + { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, { NULL, 0, NULL, 0 } }; @@ -224,6 +228,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_VERIFY; break; + case ARG_DISK_USAGE: + arg_action = ACTION_DISK_USAGE; + break; + #ifdef HAVE_GCRYPT case ARG_SETUP_KEYS: arg_action = ACTION_SETUP_KEYS; @@ -746,6 +754,19 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_action == ACTION_DISK_USAGE) { + uint64_t bytes; + char sbytes[FORMAT_BYTES_MAX]; + + r = sd_journal_get_usage(j, &bytes); + if (r < 0) + goto finish; + + printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes)); + r = 0; + goto finish; + } + #ifdef HAVE_ACL if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) { log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages."); diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 27fdcdda0e..7dfae2625f 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -70,3 +70,8 @@ global: sd_journal_perror; sd_journal_perror_with_location; } LIBSYSTEMD_JOURNAL_187; + +LIBSYSTEMD_JOURNAL_190 { +global: + sd_journal_get_usage; +} LIBSYSTEMD_JOURNAL_188; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 0f7c02ce69..b4d35eebaf 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2062,6 +2062,29 @@ void journal_print_header(sd_journal *j) { } } +_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { + Iterator i; + JournalFile *f; + uint64_t sum = 0; + + if (!j) + return -EINVAL; + if (!bytes) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + struct stat st; + + if (fstat(f->fd, &st) < 0) + return -errno; + + sum += (uint64_t) st.st_blocks * 512ULL; + } + + *bytes = sum; + return 0; +} + /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ /* if (!j) */ /* return -EINVAL; */ diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index de1c8f38f2..6c18c89425 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -108,6 +108,8 @@ int sd_journal_get_cursor(sd_journal *j, char **cursor); int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to); int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to); +int sd_journal_get_usage(sd_journal *j, uint64_t *bytes); + /* int sd_journal_query_unique(sd_journal *j, const char *field); /\* missing *\/ */ /* int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /\* missing *\/ */ /* void sd_journal_restart_unique(sd_journal *j); /\* missing *\/ */ -- cgit v1.2.3-54-g00ecf From cf5a3432117cfbe4249919d2e947295aa19879d3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Sep 2012 09:23:38 +0200 Subject: journalctl: print QR code only if we are running on an UTF-8 system --- src/journal/journalctl.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e2600542fc..8e52dd522b 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include @@ -634,8 +636,13 @@ static int setup_keys(void) { fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); #ifdef HAVE_QRENCODE - fprintf(stderr, "\nTo transfer the verification key to your phone please scan the QR code below:\n\n"); - print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); + /* If this is not an UTF-8 system don't print any QR codes */ + setlocale(LC_CTYPE, ""); + + if (streq_ptr(nl_langinfo(CODESET), "UTF-8")) { + fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); + print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); + } #endif free(hn); } -- cgit v1.2.3-54-g00ecf From 1705594f597ed12f38bee309b3fdb3f691e2021b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Sep 2012 22:33:02 +0200 Subject: journalctl: make the argument to -n optional --- man/journalctl.xml | 13 ++++++++----- src/journal/journalctl.c | 22 +++++++++++++--------- 2 files changed, 21 insertions(+), 14 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index 83ddf5c3d6..50c915d590 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -161,11 +161,14 @@ Controls the number of journal lines to show, counting from - the most recent ones. Takes a positive - integer argument. In follow mode - defaults to 10, otherwise is unset - thus not limiting how many lines are - shown. + the most recent ones. The argument is + optional, and if specified is a + positive integer. If not specified and + in follow mode defaults to 10. If this + option is not passed and follow mode + is not enabled, how many lines are + shown is not + limited. diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 8e52dd522b..6b580d4307 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -87,7 +87,7 @@ static int help(void) { " --no-pager Do not pipe output into a pager\n" " -a --all Show all fields, including long and unprintable\n" " -f --follow Follow journal\n" - " -n --lines=INTEGER Journal entries to show\n" + " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, json-pretty, cat)\n" @@ -133,7 +133,7 @@ static int parse_argv(int argc, char *argv[]) { { "follow", no_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, - { "lines", required_argument, NULL, 'n' }, + { "lines", optional_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, @@ -155,7 +155,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an:qmbD:p:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:", options, NULL)) >= 0) { switch (c) { @@ -178,7 +178,7 @@ static int parse_argv(int argc, char *argv[]) { break; case 'o': - arg_output = output_mode_from_string(optarg); + arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; @@ -191,11 +191,15 @@ static int parse_argv(int argc, char *argv[]) { break; case 'n': - r = safe_atoi(optarg, &arg_lines); - if (r < 0 || arg_lines < 0) { - log_error("Failed to parse lines '%s'", optarg); - return -EINVAL; - } + if (optarg) { + r = safe_atoi(optarg, &arg_lines); + if (r < 0 || arg_lines < 0) { + log_error("Failed to parse lines '%s'", optarg); + return -EINVAL; + } + } else + arg_lines = 10; + break; case ARG_NO_TAIL: -- cgit v1.2.3-54-g00ecf From 585314e84c1a2e8941309874088963985e063213 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sat, 22 Sep 2012 12:50:27 -0400 Subject: journalctl: reset cached column count on SIGWINCH This requires a little bit of tip-toeing around to explicitly avoid touching the environment from a sig handler. Instead, simply create a function to reset the var to its "unset" state, allowing the next call to columns() to recalculate and cache the new value. --- src/journal/journalctl.c | 2 ++ src/shared/util.c | 8 +++++++- src/shared/util.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6b580d4307..e491c27662 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -175,6 +176,7 @@ static int parse_argv(int argc, char *argv[]) { case 'f': arg_follow = true; + signal(SIGWINCH, columns_cache_reset); break; case 'o': diff --git a/src/shared/util.c b/src/shared/util.c index 97f766c33c..e0156868ad 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -70,6 +70,7 @@ int saved_argc = 0; char **saved_argv = NULL; +int parsed_columns = 0; size_t page_size(void) { static __thread size_t pgsz = 0; @@ -3740,7 +3741,7 @@ int fd_columns(int fd) { } static unsigned columns_cached(bool cached) { - static __thread int parsed_columns = 0, env_columns = -1; + static __thread int env_columns = -1; const char *e; if (_likely_(parsed_columns > 0 && cached)) @@ -3776,6 +3777,11 @@ unsigned columns_uncached(void) { return columns_cached(false); } +/* intended to be used as a SIGWINCH sighandler */ +void columns_cache_reset(int signum) { + parsed_columns = 0; +} + int fd_lines(int fd) { struct winsize ws; zero(ws); diff --git a/src/shared/util.h b/src/shared/util.h index e1d4735ee3..61b88a8b2e 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -385,6 +385,7 @@ int status_welcome(void); int fd_columns(int fd); unsigned columns(void); unsigned columns_uncached(void); +void columns_cache_reset(int _unused_ signum); int fd_lines(int fd); unsigned lines(void); -- cgit v1.2.3-54-g00ecf From 73726ac8983f46f9a39ad76c395e86d9bbfb470c Mon Sep 17 00:00:00 2001 From: Mirco Tischler Date: Sat, 22 Sep 2012 21:45:31 +0200 Subject: journalctl: print correct timespan in verify The old code used a timestamp to print a timespan for unsealed journalfiles, incorrectly showing things like 2230 days of unsealed entries. Print the timespan between the first and last entry instead. --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index e491c27662..b9be0c6ef7 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -710,7 +710,7 @@ static int verify(sd_journal *j) { format_timespan(c, sizeof(c), total > to ? total - to : 0)); } else if (total > 0) log_info("=> No sealing yet, %s of entries not sealed.", - format_timespan(c, sizeof(c), total)); + format_timespan(c, sizeof(c), total - f->header->head_entry_realtime)); else log_info("=> No sealing yet, no entries in file."); } -- cgit v1.2.3-54-g00ecf From 2a7b539a82a45202c0e990c45da25ccdc487d633 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Sep 2012 15:02:43 +0200 Subject: journald: always pass first entry timestamp back from journal_file_verify() --- src/journal/journal-verify.c | 6 +++--- src/journal/journal-verify.h | 2 +- src/journal/journalctl.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 629b2389bc..7d2e5eb1c2 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -666,7 +666,7 @@ static int verify_entry_array( int journal_file_verify( JournalFile *f, const char *key, - usec_t *first_validated, usec_t *last_validated, usec_t *last_contained, + usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress) { int r; Object *o; @@ -1121,8 +1121,8 @@ int journal_file_verify( close_nointr_nofail(entry_fd); close_nointr_nofail(entry_array_fd); - if (first_validated) - *first_validated = last_sealed_realtime > 0 ? le64toh(f->header->head_entry_realtime) : 0; + if (first_contained) + *first_contained = le64toh(f->header->head_entry_realtime); if (last_validated) *last_validated = last_sealed_realtime; if (last_contained) diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h index a4633adea9..e392ab61d7 100644 --- a/src/journal/journal-verify.h +++ b/src/journal/journal-verify.h @@ -23,4 +23,4 @@ #include "journal-file.h" -int journal_file_verify(JournalFile *f, const char *key, usec_t *first_validated, usec_t *last_validated, usec_t *last_contained, bool show_progress); +int journal_file_verify(JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b9be0c6ef7..62bdcb7c68 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -684,14 +684,14 @@ static int verify(sd_journal *j) { HASHMAP_FOREACH(f, j->files, i) { int k; - usec_t from, to, total; + usec_t first, validated, last; #ifdef HAVE_GCRYPT if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); #endif - k = journal_file_verify(f, arg_verify_key, &from, &to, &total, true); + k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true); if (k == -EINVAL) { /* If the key was invalid give up right-away. */ return k; @@ -703,14 +703,14 @@ static int verify(sd_journal *j) { log_info("PASS: %s", f->path); if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) { - if (from > 0) { + if (validated > 0) { log_info("=> Validated from %s to %s, final %s entries not sealed.", - format_timestamp(a, sizeof(a), from), - format_timestamp(b, sizeof(b), to), - format_timespan(c, sizeof(c), total > to ? total - to : 0)); - } else if (total > 0) + format_timestamp(a, sizeof(a), first), + format_timestamp(b, sizeof(b), validated), + format_timespan(c, sizeof(c), last > validated ? last - validated : 0)); + } else if (last > 0) log_info("=> No sealing yet, %s of entries not sealed.", - format_timespan(c, sizeof(c), total - f->header->head_entry_realtime)); + format_timespan(c, sizeof(c), last - first)); else log_info("=> No sealing yet, no entries in file."); } -- cgit v1.2.3-54-g00ecf From 8f14c8327b1c2b578bbf1235723a77931c3d0223 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Sep 2012 23:25:23 +0200 Subject: journalctl: add --cursor switch --- man/journalctl.xml | 9 +++++++++ src/journal/journalctl.c | 21 +++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index 50c915d590..651a8a56ad 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -254,6 +254,15 @@ current boot. + + + + + Jump to the location + in the journal specified by the passed + cursor. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 62bdcb7c68..bac8729494 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -63,6 +63,7 @@ static bool arg_no_tail = false; static bool arg_quiet = false; static bool arg_merge = false; static bool arg_this_boot = false; +static const char *arg_cursor = NULL; static const char *arg_directory = NULL; static int arg_priorities = 0xFF; static const char *arg_verify_key = NULL; @@ -87,6 +88,7 @@ static int help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all fields, including long and unprintable\n" + " -c --cursor=CURSOR Jump to the specified cursor\n" " -f --follow Follow journal\n" " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" @@ -148,6 +150,7 @@ static int parse_argv(int argc, char *argv[]) { { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, + { "cursor", no_argument, NULL, 'c' }, { NULL, 0, NULL, 0 } }; @@ -156,7 +159,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:", options, NULL)) >= 0) { switch (c) { @@ -228,6 +231,10 @@ static int parse_argv(int argc, char *argv[]) { arg_directory = optarg; break; + case 'c': + arg_cursor = optarg; + break; + case ARG_HEADER: arg_action = ACTION_PRINT_HEADER; break; @@ -829,7 +836,16 @@ int main(int argc, char *argv[]) { } } - if (arg_lines >= 0) { + if (arg_cursor) { + r = sd_journal_seek_cursor(j, arg_cursor); + if (r < 0) { + log_error("Failed to seek to cursor: %s", strerror(-r)); + goto finish; + } + + r = sd_journal_next(j); + + } else if (arg_lines >= 0) { r = sd_journal_seek_tail(j); if (r < 0) { log_error("Failed to seek to tail: %s", strerror(-r)); @@ -837,6 +853,7 @@ int main(int argc, char *argv[]) { } r = sd_journal_previous_skip(j, arg_lines); + } else { r = sd_journal_seek_head(j); if (r < 0) { -- cgit v1.2.3-54-g00ecf From 08ace05beb1d09b6ebc5e9cafc2b972b39fa2437 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Sep 2012 23:27:10 +0200 Subject: logs-show: various cleanups Among other cleanups this introduces a threshold for the size of binary blobs we serialize as integer arrays in the JSON output. THis can be disabled via --all. --- src/journal/journalctl.c | 5 +- src/shared/logs-show.c | 328 +++++++++++++++++++++++++--------------------- src/shared/logs-show.h | 9 +- src/shared/util.c | 3 +- src/systemctl/systemctl.c | 8 +- 5 files changed, 193 insertions(+), 160 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index bac8729494..cbf9833184 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -730,7 +730,6 @@ static int verify(sd_journal *j) { int main(int argc, char *argv[]) { int r; sd_journal *j = NULL; - unsigned line = 0; bool need_seek = false; sd_id128_t previous_boot_id; bool previous_boot_id_valid = false; @@ -904,9 +903,7 @@ int main(int argc, char *argv[]) { } } - line ++; - - r = output_journal(j, arg_output, line, 0, flags); + r = output_journal(stdout, j, arg_output, 0, flags); if (r < 0) goto finish; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 2ddff15bdb..725adb6451 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -31,6 +31,7 @@ #include "utf8.h" #define PRINT_THRESHOLD 128 +#define JSON_THRESHOLD 4096 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) { size_t fl, nl; @@ -63,8 +64,10 @@ static int parse_field(const void *data, size_t length, const char *field, char return 1; } -static bool shall_print(bool show_all, char *p, size_t l) { - if (show_all) +static bool shall_print(const char *p, size_t l, OutputFlags flags) { + assert(p); + + if (flags & OUTPUT_SHOW_ALL) return true; if (l > PRINT_THRESHOLD) @@ -76,78 +79,82 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, - OutputFlags flags) { +static int output_short( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + int r; const void *data; size_t length; size_t n = 0; - char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; + _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; int p = LOG_INFO; const char *color_on = "", *color_off = ""; + assert(f); assert(j); SD_JOURNAL_FOREACH_DATA(j, data, length) { r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "_COMM=", &comm, &comm_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "_PID=", &pid, &pid_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len); if (r < 0) - goto finish; + return r; else if (r > 0) continue; r = parse_field(data, length, "MESSAGE=", &message, &message_len); if (r < 0) - goto finish; + return r; } - if (!message) { - r = 0; - goto finish; - } + if (!message) + return 0; if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; @@ -166,12 +173,12 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned if (r < 0) { log_error("Failed to get monotonic: %s", strerror(-r)); - goto finish; + return r; } - printf("[%5llu.%06llu]", - (unsigned long long) (t / USEC_PER_SEC), - (unsigned long long) (t % USEC_PER_SEC)); + fprintf(f, "[%5llu.%06llu]", + (unsigned long long) (t / USEC_PER_SEC), + (unsigned long long) (t % USEC_PER_SEC)); n += 1 + 5 + 1 + 6 + 1; @@ -191,42 +198,38 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned if (r < 0) { log_error("Failed to get realtime: %s", strerror(-r)); - goto finish; + return r; } t = (time_t) (x / USEC_PER_SEC); if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) { log_error("Failed to format time."); - goto finish; + return r; } - fputs(buf, stdout); + fputs(buf, f); n += strlen(buf); } - if (hostname && shall_print(flags & OUTPUT_SHOW_ALL, - hostname, hostname_len)) { - printf(" %.*s", (int) hostname_len, hostname); + if (hostname && shall_print(hostname, hostname_len, flags)) { + fprintf(f, " %.*s", (int) hostname_len, hostname); n += hostname_len + 1; } - if (identifier && shall_print(flags & OUTPUT_SHOW_ALL, - identifier, identifier_len)) { - printf(" %.*s", (int) identifier_len, identifier); + if (identifier && shall_print(identifier, identifier_len, flags)) { + fprintf(f, " %.*s", (int) identifier_len, identifier); n += identifier_len + 1; - } else if (comm && shall_print(flags & OUTPUT_SHOW_ALL, - comm, comm_len)) { - printf(" %.*s", (int) comm_len, comm); + } else if (comm && shall_print(comm, comm_len, flags)) { + fprintf(f, " %.*s", (int) comm_len, comm); n += comm_len + 1; } else - putchar(' '); + fputc(' ', f); - if (pid && shall_print(flags & OUTPUT_SHOW_ALL, pid, pid_len)) { - printf("[%.*s]", (int) pid_len, pid); + if (pid && shall_print(pid, pid_len, flags)) { + fprintf(f, "[%.*s]", (int) pid_len, pid); n += pid_len + 2; - } else if (fake_pid && shall_print(flags & OUTPUT_SHOW_ALL, - fake_pid, fake_pid_len)) { - printf("[%.*s]", (int) fake_pid_len, fake_pid); + } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) { + fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid); n += fake_pid_len + 2; } @@ -240,46 +243,37 @@ static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned } } - if (flags & OUTPUT_SHOW_ALL) - printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + if (flags) + fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; - printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); - } else if ((flags & OUTPUT_FULL_WIDTH) || - (message_len + n + 1 < n_columns)) - printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); + } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns)) + fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (n < n_columns && n_columns - n - 2 >= 3) { char *e; e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); if (!e) - printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else - printf(": %s%s%s\n", color_on, e, color_off); + fprintf(f, ": %s%s%s\n", color_on, e, color_off); free(e); } else - fputs("\n", stdout); - - r = 0; + fputs("\n", f); -finish: - free(hostname); - free(identifier); - free(comm); - free(pid); - free(fake_pid); - free(message); - free(monotonic); - free(realtime); - free(priority); - - return r; + return 0; } -static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) { +static int output_verbose( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + const void *data; size_t length; char *cursor; @@ -287,6 +281,7 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, char ts[FORMAT_TIMESTAMP_MAX]; int r; + assert(f); assert(j); r = sd_journal_get_realtime_usec(j, &realtime); @@ -301,15 +296,14 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, return r; } - printf("%s [%s]\n", - format_timestamp(ts, sizeof(ts), realtime), - cursor); + fprintf(f, "%s [%s]\n", + format_timestamp(ts, sizeof(ts), realtime), + cursor); free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { - if (!(flags & OUTPUT_SHOW_ALL) && (length > PRINT_THRESHOLD || - !utf8_is_printable_n(data, length))) { + if (!shall_print(data, length, flags)) { const char *c; char bytes[FORMAT_BYTES_MAX]; @@ -319,19 +313,24 @@ static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, return -EINVAL; } - printf("\t%.*s=[%s blob data]\n", + fprintf(f, "\t%.*s=[%s blob data]\n", (int) (c - (const char*) data), (const char*) data, format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1)); } else - printf("\t%.*s\n", (int) length, (const char*) data); + fprintf(f, "\t%.*s\n", (int) length, (const char*) data); } return 0; } -static int output_export(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) { +static int output_export( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + sd_id128_t boot_id; char sid[33]; int r; @@ -360,14 +359,15 @@ static int output_export(sd_journal *j, OutputMode mode, unsigned line, return r; } - printf("__CURSOR=%s\n" - "__REALTIME_TIMESTAMP=%llu\n" - "__MONOTONIC_TIMESTAMP=%llu\n" - "_BOOT_ID=%s\n", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); + fprintf(f, + "__CURSOR=%s\n" + "__REALTIME_TIMESTAMP=%llu\n" + "__MONOTONIC_TIMESTAMP=%llu\n" + "_BOOT_ID=%s\n", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); free(cursor); @@ -389,61 +389,80 @@ static int output_export(sd_journal *j, OutputMode mode, unsigned line, return -EINVAL; } - fwrite(data, c - (const char*) data, 1, stdout); - fputc('\n', stdout); + fwrite(data, c - (const char*) data, 1, f); + fputc('\n', f); le64 = htole64(length - (c - (const char*) data) - 1); - fwrite(&le64, sizeof(le64), 1, stdout); - fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout); + fwrite(&le64, sizeof(le64), 1, f); + fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f); } else - fwrite(data, length, 1, stdout); + fwrite(data, length, 1, f); - fputc('\n', stdout); + fputc('\n', f); } - fputc('\n', stdout); + fputc('\n', f); return 0; } -static void json_escape(const char* p, size_t l) { - if (!utf8_is_printable_n(p, l)) { +static void json_escape( + FILE *f, + const char* p, + size_t l, + OutputFlags flags) { + + assert(f); + assert(p); + + if (!(flags & OUTPUT_SHOW_ALL) && l > JSON_THRESHOLD) + + fputs("null", f); + + else if (!utf8_is_printable_n(p, l)) { bool not_first = false; - fputs("[ ", stdout); + fputs("[ ", f); while (l > 0) { if (not_first) - printf(", %u", (uint8_t) *p); + fprintf(f, ", %u", (uint8_t) *p); else { not_first = true; - printf("%u", (uint8_t) *p); + fprintf(f, "%u", (uint8_t) *p); } p++; l--; } - fputs(" ]", stdout); + fputs(" ]", f); } else { - fputc('\"', stdout); + fputc('\"', f); while (l > 0) { if (*p == '"' || *p == '\\') { - fputc('\\', stdout); - fputc(*p, stdout); - } else - fputc(*p, stdout); + fputc('\\', f); + fputc(*p, f); + } else if (*p < ' ') + fprintf(f, "\\u%04x", *p); + else + fputc(*p, f); p++; l--; } - fputc('\"', stdout); + fputc('\"', f); } } -static int output_json(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) { +static int output_json( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + uint64_t realtime, monotonic; char *cursor; const void *data; @@ -473,24 +492,26 @@ static int output_json(sd_journal *j, OutputMode mode, unsigned line, } if (mode == OUTPUT_JSON_PRETTY) - printf("{\n" - "\t\"__CURSOR\" : \"%s\",\n" - "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" - "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" - "\t\"_BOOT_ID\" : \"%s\"", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); + fprintf(f, + "{\n" + "\t\"__CURSOR\" : \"%s\",\n" + "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" + "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" + "\t\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); else - printf("{ \"__CURSOR\" : \"%s\", " - "\"__REALTIME_TIMESTAMP\" : \"%llu\", " - "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", " - "\"_BOOT_ID\" : \"%s\"", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); + fprintf(f, + "{ \"__CURSOR\" : \"%s\", " + "\"__REALTIME_TIMESTAMP\" : \"%llu\", " + "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", " + "\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { @@ -509,30 +530,36 @@ static int output_json(sd_journal *j, OutputMode mode, unsigned line, } if (mode == OUTPUT_JSON_PRETTY) - fputs(",\n\t", stdout); + fputs(",\n\t", f); else - fputs(", ", stdout); + fputs(", ", f); - json_escape(data, c - (const char*) data); - fputs(" : ", stdout); - json_escape(c + 1, length - (c - (const char*) data) - 1); + json_escape(f, data, c - (const char*) data, flags); + fputs(" : ", f); + json_escape(f, c + 1, length - (c - (const char*) data) - 1, flags); } if (mode == OUTPUT_JSON_PRETTY) - fputs("\n}\n", stdout); + fputs("\n}\n", f); else - fputs(" }\n", stdout); + fputs(" }\n", f); return 0; } -static int output_cat(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) { +static int output_cat( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + const void *data; size_t l; int r; assert(j); + assert(f); r = sd_journal_get_data(j, "MESSAGE", &data, &l); if (r < 0) { @@ -546,14 +573,19 @@ static int output_cat(sd_journal *j, OutputMode mode, unsigned line, assert(l >= 8); - fwrite((const char*) data + 8, 1, l - 8, stdout); - putchar('\n'); + fwrite((const char*) data + 8, 1, l - 8, f); + fputc('\n', f); return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) = { +static int (*output_funcs[_OUTPUT_MODE_MAX])( + FILE *f, + sd_journal*j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) = { + [OUTPUT_SHORT] = output_short, [OUTPUT_SHORT_MONOTONIC] = output_short, [OUTPUT_VERBOSE] = output_verbose, @@ -563,8 +595,13 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsi [OUTPUT_CAT] = output_cat }; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags) { +int output_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags) { + int ret; assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); @@ -572,12 +609,13 @@ int output_journal(sd_journal *j, OutputMode mode, unsigned line, if (n_columns <= 0) n_columns = columns(); - ret = output_funcs[mode](j, mode, line, n_columns, flags); + ret = output_funcs[mode](f, j, mode, n_columns, flags); fflush(stdout); return ret; } int show_journal_by_unit( + FILE *f, const char *unit, OutputMode mode, unsigned n_columns, @@ -585,7 +623,7 @@ int show_journal_by_unit( unsigned how_many, OutputFlags flags) { - char *m1 = NULL, *m2 = NULL, *m3 = NULL; + _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL; sd_journal *j = NULL; int r; unsigned line = 0; @@ -652,11 +690,6 @@ int show_journal_by_unit( if (r < 0) goto finish; - if (mode == OUTPUT_JSON) { - fputc('[', stdout); - fflush(stdout); - } - for (;;) { for (;;) { usec_t usec; @@ -688,7 +721,7 @@ int show_journal_by_unit( line ++; - r = output_journal(j, mode, line, n_columns, flags); + r = output_journal(f, j, mode, n_columns, flags); if (r < 0) goto finish; } @@ -708,7 +741,7 @@ int show_journal_by_unit( goto finish; if (r > 0 && not_before < cutoff) - printf("Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); + fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); warn_cutoff = false; } @@ -722,14 +755,7 @@ int show_journal_by_unit( } - if (mode == OUTPUT_JSON) - fputs("\n]\n", stdout); - finish: - free(m1); - free(m2); - free(m3); - if (j) sd_journal_close(j); diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index 3e6b6e0f64..ea0f51fbf0 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -47,10 +47,15 @@ typedef enum OutputFlags { OUTPUT_COLOR = 1 << 4 } OutputFlags; -int output_journal(sd_journal *j, OutputMode mode, unsigned line, - unsigned n_columns, OutputFlags flags); +int output_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags); int show_journal_by_unit( + FILE *f, const char *unit, OutputMode mode, unsigned n_columns, diff --git a/src/shared/util.c b/src/shared/util.c index ed9b56e18e..d2ca3fc783 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1688,7 +1688,8 @@ char *xescape(const char *s, const char *bad) { * chars, in \xFF style escaping. May be reversed with * cunescape. */ - if (!(r = new(char, strlen(s)*4+1))) + r = new(char, strlen(s) * 4 + 1); + if (!r) return NULL; for (f = s, t = r; *f; f++) { diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index cc9c775251..62c32cd31a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2279,9 +2279,13 @@ static void print_status_info(UnitStatusInfo *i) { on_tty() * OUTPUT_COLOR; printf("\n"); - show_journal_by_unit(i->id, arg_output, 0, + show_journal_by_unit(stdout, + i->id, + arg_output, + 0, i->inactive_exit_timestamp_monotonic, - arg_lines, flags); + arg_lines, + flags); } if (i->need_daemon_reload) -- cgit v1.2.3-54-g00ecf From 7a69007a24cfff30158ea80665cb6c3c9d3251b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 9 Oct 2012 01:31:27 +0200 Subject: journal: implement follow mode for HTTP GET in gatewayd --- src/journal/journal-gatewayd.c | 32 +++++++++++++++++++++++++++++++- src/journal/journalctl.c | 2 +- 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journal-gatewayd.c b/src/journal/journal-gatewayd.c index 9599e891da..b6a9a2a281 100644 --- a/src/journal/journal-gatewayd.c +++ b/src/journal/journal-gatewayd.c @@ -47,6 +47,8 @@ typedef struct RequestMeta { uint64_t delta, size; int argument_parse_error; + + bool follow; } RequestMeta; static const char* const mime_types[_OUTPUT_MODE_MAX] = { @@ -194,8 +196,20 @@ static ssize_t request_reader_entries( if (r < 0) { log_error("Failed to advance journal pointer: %s", strerror(-r)); return MHD_CONTENT_READER_END_WITH_ERROR; - } else if (r == 0) + } else if (r == 0) { + + if (m->follow) { + r = sd_journal_wait(m->journal, (uint64_t) -1); + if (r < 0) { + log_error("Couldn't wait for journal event: %s", strerror(-r)); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + continue; + } + return MHD_CONTENT_READER_END_OF_STREAM; + } pos -= m->size; m->delta += m->size; @@ -356,6 +370,22 @@ static int request_parse_arguments_iterator( return MHD_NO; } + if (streq(key, "follow")) { + if (isempty(value)) { + m->follow = true; + return MHD_YES; + } + + r = parse_boolean(value); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + + m->follow = r; + return MHD_YES; + } + p = strjoin(key, "=", strempty(value), NULL); if (!p) { m->argument_parse_error = log_oom(); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index cbf9833184..b6f9b2f222 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -915,7 +915,7 @@ int main(int argc, char *argv[]) { r = sd_journal_wait(j, (uint64_t) -1); if (r < 0) { - log_error("Couldn't wait for log event: %s", strerror(-r)); + log_error("Couldn't wait for journal event: %s", strerror(-r)); goto finish; } } -- cgit v1.2.3-54-g00ecf From ad9eafab9fb182388777bab4bc7d32fd84702198 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 10 Oct 2012 01:35:24 +0200 Subject: journalctl: properly parse --cursor= long getopt in addition to short -c --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b6f9b2f222..ec05c160be 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -150,7 +150,7 @@ static int parse_argv(int argc, char *argv[]) { { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, - { "cursor", no_argument, NULL, 'c' }, + { "cursor", required_argument, NULL, 'c' }, { NULL, 0, NULL, 0 } }; -- cgit v1.2.3-54-g00ecf From 48383c251185c4596e9098878b28334c69e7bfd9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 Oct 2012 02:37:10 +0200 Subject: journal: support epxorting the journal in a format suitable for text/event-stream --- man/journalctl.xml | 8 +++++++- src/journal/journal-gatewayd.c | 5 ++++- src/journal/journalctl.c | 2 +- src/shared/logs-show.c | 10 +++++++++- src/shared/logs-show.h | 1 + src/systemctl/systemctl.c | 2 +- 6 files changed, 23 insertions(+), 5 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index 651a8a56ad..62373d88ab 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -193,6 +193,7 @@ export, json, json-pretty, + json-sse, cat. short is the default and generates an output that is mostly identical to the @@ -219,7 +220,12 @@ structures, but formats them in multiple lines in order to make them more readable for - humans. cat + humans. json-sse + also formats entries as JSON data + structures, but wraps them in a format + suitable for Server-Sent + Events. cat generates a very terse output only showing the actual message of each journal entry with no meta data, not diff --git a/src/journal/journal-gatewayd.c b/src/journal/journal-gatewayd.c index 33dda266b6..b2d4abf4fe 100644 --- a/src/journal/journal-gatewayd.c +++ b/src/journal/journal-gatewayd.c @@ -55,7 +55,8 @@ typedef struct RequestMeta { static const char* const mime_types[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT] = "text/plain", [OUTPUT_JSON] = "application/json", - [OUTPUT_EXPORT] = "application/vnd.fdo.journal" + [OUTPUT_JSON_SSE] = "text/event-stream", + [OUTPUT_EXPORT] = "application/vnd.fdo.journal", }; static RequestMeta *request_meta(void **connection_cls) { @@ -286,6 +287,8 @@ static int request_parse_accept( if (streq(accept, mime_types[OUTPUT_JSON])) m->mode = OUTPUT_JSON; + else if (streq(accept, mime_types[OUTPUT_JSON_SSE])) + m->mode = OUTPUT_JSON_SSE; else if (streq(accept, mime_types[OUTPUT_EXPORT])) m->mode = OUTPUT_EXPORT; else diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ec05c160be..04cebff547 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -93,7 +93,7 @@ static int help(void) { " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, json-pretty, cat)\n" + " verbose, export, json, json-pretty, json-sse, cat)\n" " -q --quiet Don't show privilege warning\n" " -m --merge Show entries from all available journals\n" " -b --this-boot Show data only from current boot\n" diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 725adb6451..28d12d3d4a 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -502,7 +502,10 @@ static int output_json( (unsigned long long) realtime, (unsigned long long) monotonic, sd_id128_to_string(boot_id, sid)); - else + else { + if (mode == OUTPUT_JSON_SSE) + fputs("data: ", f); + fprintf(f, "{ \"__CURSOR\" : \"%s\", " "\"__REALTIME_TIMESTAMP\" : \"%llu\", " @@ -512,6 +515,7 @@ static int output_json( (unsigned long long) realtime, (unsigned long long) monotonic, sd_id128_to_string(boot_id, sid)); + } free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { @@ -541,6 +545,8 @@ static int output_json( if (mode == OUTPUT_JSON_PRETTY) fputs("\n}\n", f); + else if (mode == OUTPUT_JSON_SSE) + fputs("}\n\n", f); else fputs(" }\n", f); @@ -592,6 +598,7 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])( [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json, [OUTPUT_JSON_PRETTY] = output_json, + [OUTPUT_JSON_SSE] = output_json, [OUTPUT_CAT] = output_cat }; @@ -769,6 +776,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_EXPORT] = "export", [OUTPUT_JSON] = "json", [OUTPUT_JSON_PRETTY] = "json-pretty", + [OUTPUT_JSON_SSE] = "json-sse", [OUTPUT_CAT] = "cat" }; diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index ea0f51fbf0..1b67876d8f 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -34,6 +34,7 @@ typedef enum OutputMode { OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, + OUTPUT_JSON_SSE, OUTPUT_CAT, _OUTPUT_MODE_MAX, _OUTPUT_MODE_INVALID = -1 diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index a4290c4754..d1fbb78e63 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3939,7 +3939,7 @@ static int systemctl_help(void) { " -n --lines=INTEGER Journal entries to show\n" " --follow Follow journal\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" - " verbose, export, json, json-pretty, cat)\n\n" + " verbose, export, json, json-pretty, json-sse, cat)\n\n" "Unit Commands:\n" " list-units List loaded units\n" " start [NAME...] Start (activate) one or more units\n" -- cgit v1.2.3-54-g00ecf From cfbc22abd0525570a6e58968d518ea9a7d0403ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 11 Oct 2012 16:42:46 +0200 Subject: journalctl: implement --since= and --until for filtering by time --- .gitignore | 1 + Makefile.am | 12 +++- TODO | 2 + man/journalctl.xml | 35 +++++++++- src/journal/journalctl.c | 125 ++++++++++++++++++++++++--------- src/shared/util.c | 175 +++++++++++++++++++++++++++++++++++++++++++++-- src/shared/util.h | 2 + src/test/test-date.c | 69 +++++++++++++++++++ 8 files changed, 380 insertions(+), 41 deletions(-) create mode 100644 src/test/test-date.c (limited to 'src/journal/journalctl.c') diff --git a/.gitignore b/.gitignore index 13d2df4652..71359ce6f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/test-date /install-tree /systemd-journal-gatewayd /test-mmap-cache diff --git a/Makefile.am b/Makefile.am index c23afdf173..e332183a64 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1157,14 +1157,16 @@ noinst_PROGRAMS += \ test-watchdog \ test-unit-name \ test-log \ - test-unit-file + test-unit-file \ + test-date TESTS += \ test-job-type \ test-env-replace \ test-strv \ test-unit-name \ - test-unit-file + test-unit-file \ + test-data test_engine_SOURCES = \ src/test/test-engine.c @@ -1226,6 +1228,12 @@ test_log_SOURCES = \ test_log_LDADD = \ libsystemd-core.la +test_date_SOURCES = \ + src/test/test-date.c + +test_date_LDADD = \ + libsystemd-core.la + test_daemon_SOURCES = \ src/test/test-daemon.c diff --git a/TODO b/TODO index 5943c9a48f..f3f66ff9a1 100644 --- a/TODO +++ b/TODO @@ -19,6 +19,8 @@ F18: Features: +* _SOURCE_MONOTONIC_TIMESTAMP entries from the kernel seem to be off by 1000000 + * document unit_name_mangle() * add new command to systemctl: "systemctl system-reexec" which reexecs as many daemons as virtually possible diff --git a/man/journalctl.xml b/man/journalctl.xml index 62373d88ab..3786fdf514 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -264,11 +264,42 @@ - Jump to the location - in the journal specified by the passed + Start showing entries + from the location in the journal + specified by the passed cursor. + + + + + Start showing entries + newer or of the specified date, + resp. older or of the specified + date. Date specifications should be of + the format "2012-10-30 18:17:16". If + the time part is omitted, 00:00:00 is + assumed. If only the seconds component + is omitted, :00 is assumed. If the + date component is ommitted, the + current day is assumed. Alternatively + the strings + yesterday, + today, + tomorrow are + understood, which refer to 00:00:00 of + the day before the current day, the + current day, resp the day after the + current day. now + refers to the current time. Finally, + relative times may be specified, + prefixed with - or + +, referring to + times before resp. after the current + time. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 04cebff547..54ee6d8cc8 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -58,7 +58,7 @@ static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; static bool arg_show_all = false; static bool arg_no_pager = false; -static int arg_lines = -1; +static unsigned arg_lines = 0; static bool arg_no_tail = false; static bool arg_quiet = false; static bool arg_merge = false; @@ -70,6 +70,8 @@ static const char *arg_verify_key = NULL; #ifdef HAVE_GCRYPT static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; #endif +static usec_t arg_since, arg_until; +static bool arg_since_set = false, arg_until_set = false; static enum { ACTION_SHOW, @@ -88,7 +90,9 @@ static int help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all fields, including long and unprintable\n" - " -c --cursor=CURSOR Jump to the specified cursor\n" + " -c --cursor=CURSOR Start showing entries from specified cursor\n" + " --since=DATE Start showing entries newer or of the specified date\n" + " --until=DATE Stop showing entries older or of the specified date\n" " -f --follow Follow journal\n" " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" @@ -126,7 +130,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_INTERVAL, ARG_VERIFY, ARG_VERIFY_KEY, - ARG_DISK_USAGE + ARG_DISK_USAGE, + ARG_SINCE, + ARG_UNTIL }; static const struct option options[] = { @@ -151,6 +157,8 @@ static int parse_argv(int argc, char *argv[]) { { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, { "cursor", required_argument, NULL, 'c' }, + { "since", required_argument, NULL, ARG_SINCE }, + { "until", required_argument, NULL, ARG_UNTIL }, { NULL, 0, NULL, 0 } }; @@ -197,8 +205,8 @@ static int parse_argv(int argc, char *argv[]) { case 'n': if (optarg) { - r = safe_atoi(optarg, &arg_lines); - if (r < 0 || arg_lines < 0) { + r = safe_atou(optarg, &arg_lines); + if (r < 0 || arg_lines <= 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } @@ -324,6 +332,24 @@ static int parse_argv(int argc, char *argv[]) { break; } + case ARG_SINCE: + r = parse_timestamp(optarg, &arg_since); + if (r < 0) { + log_error("Failed to parse timestamp: %s", optarg); + return -EINVAL; + } + arg_since_set = true; + break; + + case ARG_UNTIL: + r = parse_timestamp(optarg, &arg_until); + if (r < 0) { + log_error("Failed to parse timestamp: %s", optarg); + return -EINVAL; + } + arg_until_set = true; + break; + case '?': return -EINVAL; @@ -333,9 +359,19 @@ static int parse_argv(int argc, char *argv[]) { } } - if (arg_follow && !arg_no_tail && arg_lines < 0) + if (arg_follow && !arg_no_tail && arg_lines <= 0) arg_lines = 10; + if (arg_since_set && arg_until_set && arg_since_set > arg_until_set) { + log_error("--since= must be before --until=."); + return -EINVAL; + } + + if (arg_cursor && arg_since_set) { + log_error("Please specify either --since= or --cursor=, not both."); + return -EINVAL; + } + return 1; } @@ -734,6 +770,7 @@ int main(int argc, char *argv[]) { sd_id128_t previous_boot_id; bool previous_boot_id_valid = false; bool have_pager; + unsigned n_shown = 0; log_parse_environment(); log_open(); @@ -815,36 +852,24 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - if (!arg_quiet) { - usec_t start, end; - char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; - - r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); + if (arg_cursor) { + r = sd_journal_seek_cursor(j, arg_cursor); if (r < 0) { - log_error("Failed to get cutoff: %s", strerror(-r)); + log_error("Failed to seek to cursor: %s", strerror(-r)); goto finish; } - if (r > 0) { - if (arg_follow) - printf("Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start)); - else - printf("Logs begin at %s, end at %s.\n", - format_timestamp(start_buf, sizeof(start_buf), start), - format_timestamp(end_buf, sizeof(end_buf), end)); - } - } + r = sd_journal_next(j); - if (arg_cursor) { - r = sd_journal_seek_cursor(j, arg_cursor); + } else if (arg_since_set) { + r = sd_journal_seek_realtime_usec(j, arg_since); if (r < 0) { - log_error("Failed to seek to cursor: %s", strerror(-r)); + log_error("Failed to seek to date: %s", strerror(-r)); goto finish; } - r = sd_journal_next(j); - } else if (arg_lines >= 0) { + } else if (arg_lines > 0) { r = sd_journal_seek_tail(j); if (r < 0) { log_error("Failed to seek to tail: %s", strerror(-r)); @@ -871,12 +896,34 @@ int main(int argc, char *argv[]) { on_tty(); have_pager = !arg_no_pager && !arg_follow && pager_open(); + if (!arg_quiet) { + usec_t start, end; + char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; + + r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); + if (r < 0) { + log_error("Failed to get cutoff: %s", strerror(-r)); + goto finish; + } + + if (r > 0) { + if (arg_follow) + printf("---- Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start)); + else + printf("---- Logs begin at %s, end at %s.\n", + format_timestamp(start_buf, sizeof(start_buf), start), + format_timestamp(end_buf, sizeof(end_buf), end)); + } + } + for (;;) { for (;;) { - int flags = - arg_show_all * OUTPUT_SHOW_ALL | - have_pager * OUTPUT_FULL_WIDTH | - on_tty() * OUTPUT_COLOR; + int flags; + + if (arg_lines > 0 && n_shown >= arg_lines) { + r = 0; + goto finish; + } if (need_seek) { r = sd_journal_next(j); @@ -889,6 +936,16 @@ int main(int argc, char *argv[]) { if (r == 0) break; + if (arg_until_set) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) { + log_error("Failed to determine timestamp: %s", strerror(-r)); + goto finish; + } + } + if (!arg_merge) { sd_id128_t boot_id; @@ -896,18 +953,24 @@ int main(int argc, char *argv[]) { if (r >= 0) { if (previous_boot_id_valid && !sd_id128_equal(boot_id, previous_boot_id)) - printf(ANSI_HIGHLIGHT_ON "----- Reboot -----" ANSI_HIGHLIGHT_OFF "\n"); + printf(ANSI_HIGHLIGHT_ON "---- Reboot ----" ANSI_HIGHLIGHT_OFF "\n"); previous_boot_id = boot_id; previous_boot_id_valid = true; } } + flags = + arg_show_all * OUTPUT_SHOW_ALL | + have_pager * OUTPUT_FULL_WIDTH | + on_tty() * OUTPUT_COLOR; + r = output_journal(stdout, j, arg_output, 0, flags); if (r < 0) goto finish; need_seek = true; + n_shown++; } if (!arg_follow) diff --git a/src/shared/util.c b/src/shared/util.c index 6310aec8aa..15481b6b9d 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2733,16 +2733,31 @@ int parse_usec(const char *t, usec_t *usec) { const char *suffix; usec_t usec; } table[] = { + { "seconds", USEC_PER_SEC }, + { "second", USEC_PER_SEC }, { "sec", USEC_PER_SEC }, { "s", USEC_PER_SEC }, + { "minutes", USEC_PER_MINUTE }, + { "minute", USEC_PER_MINUTE }, { "min", USEC_PER_MINUTE }, + { "months", USEC_PER_MONTH }, + { "month", USEC_PER_MONTH }, + { "msec", USEC_PER_MSEC }, + { "ms", USEC_PER_MSEC }, + { "m", USEC_PER_MINUTE }, + { "hours", USEC_PER_HOUR }, + { "hour", USEC_PER_HOUR }, { "hr", USEC_PER_HOUR }, { "h", USEC_PER_HOUR }, + { "days", USEC_PER_DAY }, + { "day", USEC_PER_DAY }, { "d", USEC_PER_DAY }, + { "weeks", USEC_PER_WEEK }, + { "week", USEC_PER_WEEK }, { "w", USEC_PER_WEEK }, - { "msec", USEC_PER_MSEC }, - { "ms", USEC_PER_MSEC }, - { "m", USEC_PER_MINUTE }, + { "years", USEC_PER_YEAR }, + { "year", USEC_PER_YEAR }, + { "y", USEC_PER_YEAR }, { "usec", 1ULL }, { "us", 1ULL }, { "", USEC_PER_SEC }, /* default is sec */ @@ -2796,16 +2811,31 @@ int parse_nsec(const char *t, nsec_t *nsec) { const char *suffix; nsec_t nsec; } table[] = { + { "seconds", NSEC_PER_SEC }, + { "second", NSEC_PER_SEC }, { "sec", NSEC_PER_SEC }, { "s", NSEC_PER_SEC }, + { "minutes", NSEC_PER_MINUTE }, + { "minute", NSEC_PER_MINUTE }, { "min", NSEC_PER_MINUTE }, + { "months", NSEC_PER_MONTH }, + { "month", NSEC_PER_MONTH }, + { "msec", NSEC_PER_MSEC }, + { "ms", NSEC_PER_MSEC }, + { "m", NSEC_PER_MINUTE }, + { "hours", NSEC_PER_HOUR }, + { "hour", NSEC_PER_HOUR }, { "hr", NSEC_PER_HOUR }, { "h", NSEC_PER_HOUR }, + { "days", NSEC_PER_DAY }, + { "day", NSEC_PER_DAY }, { "d", NSEC_PER_DAY }, + { "weeks", NSEC_PER_WEEK }, + { "week", NSEC_PER_WEEK }, { "w", NSEC_PER_WEEK }, - { "msec", NSEC_PER_MSEC }, - { "ms", NSEC_PER_MSEC }, - { "m", NSEC_PER_MINUTE }, + { "years", NSEC_PER_YEAR }, + { "year", NSEC_PER_YEAR }, + { "y", NSEC_PER_YEAR }, { "usec", NSEC_PER_USEC }, { "us", NSEC_PER_USEC }, { "nsec", 1ULL }, @@ -5888,3 +5918,136 @@ bool string_is_safe(const char *p) { return true; } + +int parse_timestamp(const char *t, usec_t *usec) { + const char *k; + struct tm tm, copy; + time_t x; + usec_t plus = 0, minus = 0, ret; + int r; + + /* + * Allowed syntaxes: + * + * 2012-09-22 16:34:22 + * 2012-09-22 16:34 (seconds will be set to 0) + * 2012-09-22 (time will be set to 00:00:00) + * 16:34:22 (date will be set to today) + * 16:34 (date will be set to today, seconds to 0) + * now + * yesterday (time is set to 00:00:00) + * today (time is set to 00:00:00) + * tomorrow (time is set to 00:00:00) + * +5min + * -5days + * + */ + + assert(t); + assert(usec); + + x = time(NULL); + assert_se(localtime_r(&x, &tm)); + + if (streq(t, "now")) + goto finish; + + else if (streq(t, "today")) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto finish; + + } else if (streq(t, "yesterday")) { + tm.tm_mday --; + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto finish; + + } else if (streq(t, "tomorrow")) { + tm.tm_mday ++; + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto finish; + + } else if (t[0] == '+') { + + r = parse_usec(t+1, &plus); + if (r < 0) + return r; + + goto finish; + } else if (t[0] == '-') { + + r = parse_usec(t+1, &minus); + if (r < 0) + return r; + + goto finish; + } + + copy = tm; + k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); + if (k && *k == 0) + goto finish; + + tm = copy; + k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); + if (k && *k == 0) + goto finish; + + tm = copy; + k = strptime(t, "%y-%m-%d %H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto finish; + } + + tm = copy; + k = strptime(t, "%Y-%m-%d %H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto finish; + } + + tm = copy; + k = strptime(t, "%y-%m-%d", &tm); + if (k && *k == 0) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto finish; + } + + tm = copy; + k = strptime(t, "%Y-%m-%d", &tm); + if (k && *k == 0) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto finish; + } + + tm = copy; + k = strptime(t, "%H:%M:%S", &tm); + if (k && *k == 0) + goto finish; + + tm = copy; + k = strptime(t, "%H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto finish; + } + + return -EINVAL; + +finish: + x = mktime(&tm); + if (x == (time_t) -1) + return -EINVAL; + + ret = (usec_t) x * USEC_PER_SEC; + + ret += plus; + if (ret > minus) + ret -= minus; + else + ret = 0; + + *usec = ret; + + return 0; +} diff --git a/src/shared/util.h b/src/shared/util.h index cbded08617..50911ebb34 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -561,3 +561,5 @@ _malloc_ static inline void *memdup_multiply(const void *p, size_t a, size_t b) bool filename_is_safe(const char *p); bool string_is_safe(const char *p); + +int parse_timestamp(const char *t, usec_t *usec); diff --git a/src/test/test-date.c b/src/test/test-date.c new file mode 100644 index 0000000000..57f8b371d3 --- /dev/null +++ b/src/test/test-date.c @@ -0,0 +1,69 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "util.h" + +int main(int argc, char *argv[]) { + + usec_t t; + char buf[FORMAT_TIMESTAMP_MAX]; + + assert_se(parse_timestamp("17:41", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("18:42:44", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("12-10-02 12:13:14", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("12-10-2 12:13:14", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("12-10-03 12:13", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("2012-12-30 18:42", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("2012-10-02", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("now", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("yesterday", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("today", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("tomorrow", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("+2d", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(parse_timestamp("+2y 4d", &t) >= 0); + log_info("%s", format_timestamp(buf, sizeof(buf), t)); + + return 0; +} -- cgit v1.2.3-54-g00ecf From e3ed66c52ede243081a18f7bc99bf6ba3f885b86 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Oct 2012 19:21:07 +0000 Subject: journalctl: make --follow work again Stopped working after cfbc22ab 'journalctl: implement --since= and --until for filtering by time'. --- src/journal/journalctl.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 54ee6d8cc8..58ca8071fc 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -917,14 +917,9 @@ int main(int argc, char *argv[]) { } for (;;) { - for (;;) { + while (arg_lines == 0 || n_shown < arg_lines) { int flags; - if (arg_lines > 0 && n_shown >= arg_lines) { - r = 0; - goto finish; - } - if (need_seek) { r = sd_journal_next(j); if (r < 0) { -- cgit v1.2.3-54-g00ecf From c3eba2ab4e70fc7aed902b1d5b1fcb978ef98dfa Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 14 Oct 2012 15:29:38 +0000 Subject: journalctl: make --follow really work --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 58ca8071fc..34017484be 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -917,7 +917,7 @@ int main(int argc, char *argv[]) { } for (;;) { - while (arg_lines == 0 || n_shown < arg_lines) { + while (arg_lines == 0 || arg_follow || n_shown < arg_lines) { int flags; if (need_seek) { -- cgit v1.2.3-54-g00ecf From edfb521a21c44f7b4c91d4ef6bffd84f2c241363 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 15 Oct 2012 16:14:09 +0000 Subject: journalctl: skip informational messages in export/json modes --- src/journal/journalctl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 34017484be..9fbc9a3489 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -193,10 +193,17 @@ static int parse_argv(int argc, char *argv[]) { case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { - log_error("Unknown output '%s'.", optarg); + log_error("Unknown output format '%s'.", optarg); return -EINVAL; } + if (arg_output == OUTPUT_EXPORT || + arg_output == OUTPUT_JSON || + arg_output == OUTPUT_JSON_PRETTY || + arg_output == OUTPUT_JSON_SSE || + arg_output == OUTPUT_CAT) + arg_quiet = true; + break; case 'a': -- cgit v1.2.3-54-g00ecf From 9048b11f8b0173a3fbbbf6ce2716abba05d202ed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 Oct 2012 01:09:09 +0200 Subject: journalctl: harmonise in-stream comments From now on, always use ANSI-SQL-style comments in log streams, i.e. prefix with --. We also suffix things with this, just to be nice... --- src/journal/journalctl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 9fbc9a3489..0498f294ae 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -915,9 +915,10 @@ int main(int argc, char *argv[]) { if (r > 0) { if (arg_follow) - printf("---- Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start)); + printf("-- Logs begin at %s. --\n", + format_timestamp(start_buf, sizeof(start_buf), start)); else - printf("---- Logs begin at %s, end at %s.\n", + printf("-- Logs begin at %s, end at %s. --\n", format_timestamp(start_buf, sizeof(start_buf), start), format_timestamp(end_buf, sizeof(end_buf), end)); } @@ -955,7 +956,7 @@ int main(int argc, char *argv[]) { if (r >= 0) { if (previous_boot_id_valid && !sd_id128_equal(boot_id, previous_boot_id)) - printf(ANSI_HIGHLIGHT_ON "---- Reboot ----" ANSI_HIGHLIGHT_OFF "\n"); + printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n"); previous_boot_id = boot_id; previous_boot_id_valid = true; -- cgit v1.2.3-54-g00ecf From c3f60ec54da2a5d1ba00cec6bb2c282f079aa3f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 16 Oct 2012 02:59:27 +0200 Subject: journalctl: add --unit=/-u to match by unit name This applies unit_name_mangle() to the specified unit names and hence can handle weird characters nicely and will add unit suffixes as necessary. --- man/journalctl.xml | 83 +++++++++++++++++++++++++++++------------------- src/journal/journalctl.c | 48 +++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 38 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index 0bbcee33ab..a533f4d0ea 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -257,7 +257,56 @@ Show data only from - current boot. + current boot. This will add a match + for _BOOT_ID= for + the current boot ID of the + kernel. + + + + + + + Show data only of the + specified unit. This will add a match + for _SYSTEMD_UNIT= + for the specified + unit. + + + + + + + Filter output by + message priorities or priority + ranges. Takes either a single numeric + or textual log level (i.e. between + 0/emerg and + 7/debug), or a + range of numeric/text log levels in + the form FROM..TO. The log levels are + the usual syslog log levels as + documented in + syslog3, + i.e. emerg (0), + alert (1), + crit (2), + err (3), + warning (4), + notice (5), + info (6), + debug (7). If a + single log level is specified all + messages with this log level or a + lower (hence more important) log level + are shown. If a range is specified all + messages within the range are shown, + including both the start and the end + value of the range. This will add + PRIORITY= matches + for the specified + priorities. @@ -312,38 +361,6 @@ paths. - - - - - Filter output by - message priorities or priority - ranges. Takes either a single numeric - or textual log level (i.e. between - 0/emerg and - 7/debug), or a - range of numeric/text log levels in - the form FROM..TO. The log levels are - the usual syslog log levels as - documented in - syslog3, - i.e. emerg (0), - alert (1), - crit (2), - err (3), - warning (4), - notice (5), - info (6), - debug (7). If a - single log level is specified all - messages with this log level or a - lower (hence more important) log level - are shown. If a range is specified all - messages within the range are shown, - including both the start and the end - value of the range. - - diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0498f294ae..665b325a94 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -51,6 +51,7 @@ #include "journal-authenticate.h" #include "journal-qrcode.h" #include "fsprg.h" +#include "unit-name.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -72,6 +73,7 @@ static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; #endif static usec_t arg_since, arg_until; static bool arg_since_set = false, arg_until_set = false; +static const char *arg_unit = NULL; static enum { ACTION_SHOW, @@ -88,21 +90,22 @@ static int help(void) { "Send control commands to or query the journal.\n\n" " -h --help Show this help\n" " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " -a --all Show all fields, including long and unprintable\n" " -c --cursor=CURSOR Start showing entries from specified cursor\n" " --since=DATE Start showing entries newer or of the specified date\n" " --until=DATE Stop showing entries older or of the specified date\n" + " -b --this-boot Show data only from current boot\n" + " -u --unit=UNIT Show data only from the specified unit\n" + " -p --priority=RANGE Show only messages within the specified priority range\n\n" " -f --follow Follow journal\n" " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, json-pretty, json-sse, cat)\n" + " -a --all Show all fields, including long and unprintable\n" " -q --quiet Don't show privilege warning\n" + " --no-pager Do not pipe output into a pager\n" " -m --merge Show entries from all available journals\n" - " -b --this-boot Show data only from current boot\n" " -D --directory=PATH Show journal files from directory\n" - " -p --priority=RANGE Show only messages within the specified priority range\n\n" "Commands:\n" " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" @@ -159,6 +162,7 @@ static int parse_argv(int argc, char *argv[]) { { "cursor", required_argument, NULL, 'c' }, { "since", required_argument, NULL, ARG_SINCE }, { "until", required_argument, NULL, ARG_UNTIL }, + { "unit", required_argument, NULL, 'u' }, { NULL, 0, NULL, 0 } }; @@ -167,7 +171,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:", options, NULL)) >= 0) { switch (c) { @@ -357,6 +361,10 @@ static int parse_argv(int argc, char *argv[]) { arg_until_set = true; break; + case 'u': + arg_unit = optarg; + break; + case '?': return -EINVAL; @@ -506,6 +514,32 @@ static int add_this_boot(sd_journal *j) { return 0; } +static int add_unit(sd_journal *j) { + _cleanup_free_ char *m = NULL, *u = NULL; + int r; + + assert(j); + + if (isempty(arg_unit)) + return 0; + + u = unit_name_mangle(arg_unit); + if (!u) + return log_oom(); + + m = strappend("_SYSTEMD_UNIT=", u); + if (!m) + return log_oom(); + + r = sd_journal_add_match(j, m, strlen(m)); + if (r < 0) { + log_error("Failed to add match: %s", strerror(-r)); + return r; + } + + return 0; +} + static int add_priorities(sd_journal *j) { char match[] = "PRIORITY=0"; int i, r; @@ -851,6 +885,10 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; + r = add_unit(j); + if (r < 0) + goto finish; + r = add_matches(j, argv + optind); if (r < 0) goto finish; -- cgit v1.2.3-54-g00ecf From 3c1668da6202f1ead3d4d3981b89e9da1a0e98e3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 03:29:19 +0200 Subject: journal: add ability to list values a specified field can take in all entries of the journal The new 'unique' API allows listing all unique field values that a field specified by a field name can take in all entries of the journal. This allows answering queries such as "What units logged to the journal?", "What hosts have logged into the journal?", "Which boot IDs have logged into the journal?". Ultimately this allows implementation of tools similar to lastlog based on journal data. Note that listing these field values will not work for journal files created with older journald, as the field values are not indexed in older files. --- Makefile.am | 11 +- man/sd-journal.xml | 3 + man/sd_journal_get_data.xml | 7 +- src/journal/journal-authenticate.c | 7 +- src/journal/journal-file.c | 201 ++++++++++++++++++++++++++++++++- src/journal/journal-file.h | 3 + src/journal/journal-internal.h | 4 + src/journal/journalctl.c | 1 + src/journal/libsystemd-journal.sym | 3 + src/journal/sd-journal.c | 222 +++++++++++++++++++++++++++++-------- src/journal/test-journal-stream.c | 18 +-- src/journal/test-journal.c | 2 +- src/shared/hashmap.c | 22 ++++ src/shared/hashmap.h | 2 + src/systemd/sd-journal.h | 24 ++-- 15 files changed, 455 insertions(+), 75 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/Makefile.am b/Makefile.am index e1eb03408d..4c650765cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -513,7 +513,8 @@ MANPAGES = \ man/sd_journal_get_fd.3 \ man/sd_journal_get_usage.3 \ man/sd_journal_add_match.3 \ - man/sd_journal_seek_head.3 + man/sd_journal_seek_head.3 \ + man/sd_journal_query_unique.3 MANPAGES_ALIAS = \ man/reboot.8 \ @@ -584,7 +585,10 @@ MANPAGES_ALIAS = \ man/sd_journal_seek_monotonic_usec.3 \ man/sd_journal_seek_realtime_usec.3 \ man/sd_journal_seek_cursor.3 \ - man/sd_journal_test_cursor.3 + man/sd_journal_test_cursor.3 \ + man/sd_journal_enumerate_unique.3 \ + man/sd_journal_restart_unique.3 \ + man/SD_JOURNAL_FOREACH_UNIQUE.3 man/reboot.8: man/halt.8 man/poweroff.8: man/halt.8 @@ -655,6 +659,9 @@ man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3 man/sd_journal_seek_realtime_usec.3: man/sd_journal_seek_head.3 man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3 man/sd_journal_test_cursor.3: man/sd_journal_get_cursor.3 +man/sd_journal_enumerate_unique.3: man/sd_journal_query_unique.3 +man/sd_journal_restart_unique.3: man/sd_journal_query_unique.3 +man/SD_JOURNAL_FOREACH_UNIQUE.3: man/sd_journal_query_unique.3 XML_FILES = \ ${patsubst %.1,%.xml,${patsubst %.3,%.xml,${patsubst %.5,%.xml,${patsubst %.7,%.xml,${patsubst %.8,%.xml,$(MANPAGES)}}}}} diff --git a/man/sd-journal.xml b/man/sd-journal.xml index 773689c692..1beb9a5c7d 100644 --- a/man/sd-journal.xml +++ b/man/sd-journal.xml @@ -112,12 +112,15 @@ sd_journal_stream_fd3, sd_journal_open3, sd_journal_next3, + sd_journal_get_data3, sd_journal_get_realtime_usec3, sd_journal_add_match3, sd_journal_seek_head3, sd_journal_get_cursor3, sd_journal_cutoff_realtime_usec3, sd_journal_get_usage3, + sd_journal_get_fd3, + sd_journal_query_unique3, journalctl1, sd-id1283, pkg-config1 diff --git a/man/sd_journal_get_data.xml b/man/sd_journal_get_data.xml index a7754129f0..6470f19cc6 100644 --- a/man/sd_journal_get_data.xml +++ b/man/sd_journal_get_data.xml @@ -70,7 +70,7 @@ - int sd_journal_restart_data + void sd_journal_restart_data sd_journal* j @@ -120,7 +120,7 @@ Note that the SD_JOURNAL_FOREACH_DATA() macro - may be used as a wrapper around + may be used as a handy wrapper around sd_journal_restart_data() and sd_journal_enumerate_data(). @@ -193,7 +193,8 @@ int print_fields(sd_journal *j) { sd-journal3, sd_journal_open3, sd_journal_next3, - sd_journal_get_realtime_usec3 + sd_journal_get_realtime_usec3, + sd_journal_query_unique3 diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c index 674f81218f..64bf96874e 100644 --- a/src/journal/journal-authenticate.c +++ b/src/journal/journal-authenticate.c @@ -260,6 +260,12 @@ int journal_file_hmac_put_object(JournalFile *f, int type, Object *o, uint64_t p gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); break; + case OBJECT_FIELD: + /* Same here */ + gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash)); + gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(FieldObject, payload)); + break; + case OBJECT_ENTRY: /* All */ gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); @@ -484,7 +490,6 @@ int journal_file_append_first_tag(JournalFile *f) { return 0; } - int journal_file_parse_verification_key(JournalFile *f, const char *key) { uint8_t *seed; size_t seed_size, c; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index ae01e5df50..43fd4453a4 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -399,7 +399,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec if (s < minimum_header_size(o)) return -EBADMSG; - if (type >= 0 && o->object.type != type) + if (type > 0 && o->object.type != type) return -EBADMSG; if (s > sizeof(ObjectHeader)) { @@ -526,6 +526,9 @@ static int journal_file_setup_field_hash_table(JournalFile *f) { assert(f); + /* We use a fixed size hash table for the fields as this + * number should grow very slowly only */ + s = DEFAULT_FIELD_HASH_TABLE_SIZE; r = journal_file_append_object(f, OBJECT_FIELD_HASH_TABLE, @@ -586,7 +589,52 @@ static int journal_file_map_field_hash_table(JournalFile *f) { return 0; } -static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, uint64_t hash) { +static int journal_file_link_field( + JournalFile *f, + Object *o, + uint64_t offset, + uint64_t hash) { + + uint64_t p, h; + int r; + + assert(f); + assert(o); + assert(offset > 0); + + if (o->object.type != OBJECT_FIELD) + return -EINVAL; + + /* This might alter the window we are looking at */ + + o->field.next_hash_offset = o->field.head_data_offset = 0; + + h = hash % (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); + p = le64toh(f->field_hash_table[h].tail_hash_offset); + if (p == 0) + f->field_hash_table[h].head_hash_offset = htole64(offset); + else { + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + + o->field.next_hash_offset = htole64(offset); + } + + f->field_hash_table[h].tail_hash_offset = htole64(offset); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + f->header->n_fields = htole64(le64toh(f->header->n_fields) + 1); + + return 0; +} + +static int journal_file_link_data( + JournalFile *f, + Object *o, + uint64_t offset, + uint64_t hash) { + uint64_t p, h; int r; @@ -605,10 +653,10 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)); p = le64toh(f->data_hash_table[h].tail_hash_offset); - if (p == 0) { + if (p == 0) /* Only entry in the hash table is easy */ f->data_hash_table[h].head_hash_offset = htole64(offset); - } else { + else { /* Move back to the previous data object, to patch in * pointer */ @@ -627,6 +675,67 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui return 0; } +int journal_file_find_field_object_with_hash( + JournalFile *f, + const void *field, uint64_t size, uint64_t hash, + Object **ret, uint64_t *offset) { + + uint64_t p, osize, h; + int r; + + assert(f); + assert(field && size > 0); + + osize = offsetof(Object, field.payload) + size; + + if (f->header->field_hash_table_size == 0) + return -EBADMSG; + + h = hash % (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); + p = le64toh(f->field_hash_table[h].head_hash_offset); + + while (p > 0) { + Object *o; + + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + + if (le64toh(o->field.hash) == hash && + le64toh(o->object.size) == osize && + memcmp(o->field.payload, field, size) == 0) { + + if (ret) + *ret = o; + if (offset) + *offset = p; + + return 1; + } + + p = le64toh(o->field.next_hash_offset); + } + + return 0; +} + +int journal_file_find_field_object( + JournalFile *f, + const void *field, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash; + + assert(f); + assert(field && size > 0); + + hash = hash64(field, size); + + return journal_file_find_field_object_with_hash(f, + field, size, hash, + ret, offset); +} + int journal_file_find_data_object_with_hash( JournalFile *f, const void *data, uint64_t size, uint64_t hash, @@ -720,6 +829,66 @@ int journal_file_find_data_object( ret, offset); } +static int journal_file_append_field( + JournalFile *f, + const void *field, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash, p; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(field && size > 0); + + hash = hash64(field, size); + + r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p); + if (r < 0) + return r; + else if (r > 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; + } + + osize = offsetof(Object, field.payload) + size; + r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p); + + o->field.hash = htole64(hash); + memcpy(o->field.payload, field, size); + + r = journal_file_link_field(f, o, p, hash); + if (r < 0) + return r; + + /* The linking might have altered the window, so let's + * refresh our pointer */ + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + +#ifdef HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p); + if (r < 0) + return r; +#endif + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; +} + static int journal_file_append_data( JournalFile *f, const void *data, uint64_t size, @@ -730,6 +899,7 @@ static int journal_file_append_data( Object *o; int r; bool compressed = false; + const void *eq; assert(f); assert(data || size == 0); @@ -786,6 +956,21 @@ static int journal_file_append_data( if (r < 0) return r; + eq = memchr(data, '=', size); + if (eq && eq > data) { + uint64_t fp; + Object *fo; + + /* Create field object ... */ + r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp); + if (r < 0) + return r; + + /* ... and link it in. */ + o->data.next_field_offset = fo->field.head_data_offset; + fo->field.head_data_offset = le64toh(p); + } + #ifdef HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); if (r < 0) @@ -1899,6 +2084,10 @@ void journal_file_dump(JournalFile *f) { printf("Type: OBJECT_DATA\n"); break; + case OBJECT_FIELD: + printf("Type: OBJECT_FIELD\n"); + break; + case OBJECT_ENTRY: printf("Type: OBJECT_ENTRY seqnum=%llu monotonic=%llu realtime=%llu\n", (unsigned long long) le64toh(o->entry.seqnum), @@ -1923,6 +2112,10 @@ void journal_file_dump(JournalFile *f) { (unsigned long long) le64toh(o->tag.seqnum), (unsigned long long) le64toh(o->tag.epoch)); break; + + default: + printf("Type: unknown (%u)\n", o->object.type); + break; } if (o->object.flags & OBJECT_COMPRESSED) diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index f52ee8c538..d87cbe4876 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -155,6 +155,9 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); +int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); + int journal_file_next_entry(JournalFile *f, Object *o, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); int journal_file_skip_entry(JournalFile *f, Object *o, uint64_t p, int64_t skip, Object **ret, uint64_t *offset); diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index edd4f23baf..f68ca996a8 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -115,6 +115,10 @@ struct sd_journal { Match *level0, *level1; unsigned current_invalidate_counter, last_invalidate_counter; + + char *unique_field; + JournalFile *unique_file; + uint64_t unique_offset; }; char *journal_make_match_string(sd_journal *j); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 665b325a94..ebb88e053e 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -74,6 +74,7 @@ static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; static usec_t arg_since, arg_until; static bool arg_since_set = false, arg_until_set = false; static const char *arg_unit = NULL; +static const char *arg_field = NULL; static enum { ACTION_SHOW, diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 77de862dcb..a1a8472906 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -79,4 +79,7 @@ global: LIBSYSTEMD_JOURNAL_195 { global: sd_journal_test_cursor; + sd_journal_query_unique; + sd_journal_enumerate_unique; + sd_journal_restart_unique; } LIBSYSTEMD_JOURNAL_190; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 16ed4239ce..99bbf08be6 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1261,6 +1261,16 @@ static int remove_file(sd_journal *j, const char *prefix, const char *filename) log_debug("File %s got removed.", f->path); + if (j->current_file == f) { + j->current_file = NULL; + j->current_field = 0; + } + + if (j->unique_file == f) { + j->unique_file = NULL; + j->unique_offset = 0; + } + journal_file_close(f); j->current_invalidate_counter ++; @@ -1641,6 +1651,7 @@ _public_ void sd_journal_close(sd_journal *j) { mmap_cache_unref(j->mmap); free(j->path); + free(j->unique_field); free(j); } @@ -1828,13 +1839,43 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** return -ENOENT; } +static int return_data(JournalFile *f, Object *o, const void **data, size_t *size) { + size_t t; + uint64_t l; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + t = (size_t) l; + + /* We can't read objects larger than 4G on a 32bit machine */ + if ((uint64_t) t != l) + return -E2BIG; + + if (o->object.flags & OBJECT_COMPRESSED) { +#ifdef HAVE_XZ + uint64_t rsize; + + if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize)) + return -EBADMSG; + + *data = f->compress_buffer; + *size = (size_t) rsize; +#else + return -EPROTONOSUPPORT; +#endif + } else { + *data = o->data.payload; + *size = t; + } + + return 0; +} + _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { JournalFile *f; - uint64_t p, l, n; + uint64_t p, n; le64_t le_hash; int r; Object *o; - size_t t; if (!j) return -EINVAL; @@ -1867,29 +1908,9 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t if (le_hash != o->data.hash) return -EBADMSG; - l = le64toh(o->object.size) - offsetof(Object, data.payload); - t = (size_t) l; - - /* We can't read objects larger than 4G on a 32bit machine */ - if ((uint64_t) t != l) - return -E2BIG; - - if (o->object.flags & OBJECT_COMPRESSED) { -#ifdef HAVE_XZ - uint64_t rsize; - - if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize)) - return -EBADMSG; - - *data = f->compress_buffer; - *size = (size_t) rsize; -#else - return -EPROTONOSUPPORT; -#endif - } else { - *data = o->data.payload; - *size = t; - } + r = return_data(f, o, data, size); + if (r < 0) + return r; j->current_field ++; @@ -2186,27 +2207,138 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { return 0; } -/* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ -/* if (!j) */ -/* return -EINVAL; */ -/* if (!field) */ -/* return -EINVAL; */ +_public_ int sd_journal_query_unique(sd_journal *j, const char *field) { + char *f; + + if (!j) + return -EINVAL; + if (isempty(field)) + return -EINVAL; + + f = strdup(field); + if (!f) + return -ENOMEM; + + free(j->unique_field); + j->unique_field = f; + j->unique_file = NULL; + j->unique_offset = 0; + + return 0; +} + +_public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { + Object *o; + size_t k; + int r; -/* return -ENOTSUP; */ -/* } */ + if (!j) + return -EINVAL; + if (!data) + return -EINVAL; + if (!l) + return -EINVAL; + if (!j->unique_field) + return -EINVAL; -/* _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { */ -/* if (!j) */ -/* return -EINVAL; */ -/* if (!data) */ -/* return -EINVAL; */ -/* if (!l) */ -/* return -EINVAL; */ + k = strlen(j->unique_field); -/* return -ENOTSUP; */ -/* } */ + if (!j->unique_file) { + j->unique_file = hashmap_first(j->files); + if (!j->unique_file) + return 0; + j->unique_offset = 0; + } -/* _public_ void sd_journal_restart_unique(sd_journal *j) { */ -/* if (!j) */ -/* return; */ -/* } */ + for (;;) { + JournalFile *of; + Iterator i; + const void *odata; + size_t ol; + bool found; + + /* Proceed to next data object in list the field's linked list */ + if (j->unique_offset == 0) { + r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL); + if (r < 0) + return r; + + j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0; + } else { + r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o); + if (r < 0) + return r; + + j->unique_offset = le64toh(o->data.next_field_offset); + } + + /* We reached the end of the list? Then start again, with the next file */ + if (j->unique_offset == 0) { + JournalFile *n; + + n = hashmap_next(j->files, j->unique_file->path); + if (!n) + return 0; + + j->unique_file = n; + continue; + } + + /* We do not use the type context here, but 0 instead, + * so that we can look at this data object at the same + * time as one on another file */ + r = journal_file_move_to_object(j->unique_file, 0, j->unique_offset, &o); + if (r < 0) + return r; + + /* Let's do the type check by hand, since we used 0 context above. */ + if (o->object.type != OBJECT_DATA) + return -EBADMSG; + + r = return_data(j->unique_file, o, &odata, &ol); + if (r < 0) + return r; + + /* OK, now let's see if we already returned this data + * object by checking if it exists in the earlier + * traversed files. */ + found = false; + HASHMAP_FOREACH(of, j->files, i) { + Object *oo; + uint64_t op; + + if (of == j->unique_file) + break; + + /* Skip this file it didn't have any fields + * indexed */ + if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && + le64toh(of->header->n_fields) <= 0) + continue; + + r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), &oo, &op); + if (r < 0) + return r; + + if (r > 0) + found = true; + } + + if (found) + continue; + + r = return_data(j->unique_file, o, data, l); + if (r < 0) + return r; + + return 1; + } +} + +void sd_journal_restart_unique(sd_journal *j) { + if (!j) + return; + + j->unique_file = NULL; + j->unique_offset = 0; +} diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c index caea2b2c63..b3e816db70 100644 --- a/src/journal/test-journal-stream.c +++ b/src/journal/test-journal-stream.c @@ -77,6 +77,8 @@ int main(int argc, char *argv[]) { unsigned i; sd_journal *j; char *z; + const void *data; + size_t l; log_set_max_level(LOG_DEBUG); @@ -124,12 +126,10 @@ int main(int argc, char *argv[]) { assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); SD_JOURNAL_FOREACH_BACKWARDS(j) { - const void *d; - size_t l; char *c; - assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); - printf("\t%.*s\n", (int) l, (const char*) d); + assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) data); assert_se(sd_journal_get_cursor(j, &c) >= 0); assert_se(sd_journal_test_cursor(j, c) > 0); @@ -137,12 +137,10 @@ int main(int argc, char *argv[]) { } SD_JOURNAL_FOREACH(j) { - const void *d; - size_t l; char *c; - assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); - printf("\t%.*s\n", (int) l, (const char*) d); + assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) data); assert_se(sd_journal_get_cursor(j, &c) >= 0); assert_se(sd_journal_test_cursor(j, c) > 0); @@ -175,6 +173,10 @@ int main(int argc, char *argv[]) { verify_contents(j, 0); + assert_se(sd_journal_query_unique(j, "NUMBER") >= 0); + SD_JOURNAL_FOREACH_UNIQUE(j, data, l) + printf("%.*s\n", (int) l, (const char*) data); + sd_journal_close(j); assert_se(rm_rf_dangerous(t, false, true, false) >= 0); diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 2fd49c17fc..f4dc52cd81 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { dual_timestamp ts; JournalFile *f; struct iovec iovec; - static const char test[] = "test", test2[] = "test2"; + static const char test[] = "TEST1=1", test2[] = "TEST2=2"; Object *o; uint64_t p; char t[] = "/tmp/journal-XXXXXX"; diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index eb5c549e40..26a4eff07f 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -758,3 +758,25 @@ char **hashmap_get_strv(Hashmap *h) { return sv; } + +void *hashmap_next(Hashmap *h, const void *key) { + unsigned hash; + struct hashmap_entry *e; + + assert(h); + assert(key); + + if (!h) + return NULL; + + hash = h->hash_func(key) % NBUCKETS; + e = hash_scan(h, hash, key); + if (!e) + return NULL; + + e = e->iterate_next; + if (!e) + return NULL; + + return e->value; +} diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h index 504f0b7637..ed41817dda 100644 --- a/src/shared/hashmap.h +++ b/src/shared/hashmap.h @@ -79,6 +79,8 @@ void* hashmap_first(Hashmap *h); void* hashmap_first_key(Hashmap *h); void* hashmap_last(Hashmap *h); +void *hashmap_next(Hashmap *h, const void *key); + char **hashmap_get_strv(Hashmap *h); #define HASHMAP_FOREACH(e, h, i) \ diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index 9a2aab923a..55281b1346 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -70,12 +70,20 @@ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) typedef struct sd_journal sd_journal; +/* Open flags */ enum { SD_JOURNAL_LOCAL_ONLY = 1, SD_JOURNAL_RUNTIME_ONLY = 2, SD_JOURNAL_SYSTEM_ONLY = 4 }; +/* Wakeup event types */ +enum { + SD_JOURNAL_NOP, + SD_JOURNAL_APPEND, + SD_JOURNAL_INVALIDATE +}; + int sd_journal_open(sd_journal **ret, int flags); int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); void sd_journal_close(sd_journal *j); @@ -111,15 +119,9 @@ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id int sd_journal_get_usage(sd_journal *j, uint64_t *bytes); -/* int sd_journal_query_unique(sd_journal *j, const char *field); /\* missing *\/ */ -/* int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); /\* missing *\/ */ -/* void sd_journal_restart_unique(sd_journal *j); /\* missing *\/ */ - -enum { - SD_JOURNAL_NOP, - SD_JOURNAL_APPEND, - SD_JOURNAL_INVALIDATE -}; +int sd_journal_query_unique(sd_journal *j, const char *field); +int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); +void sd_journal_restart_unique(sd_journal *j); int sd_journal_get_fd(sd_journal *j); int sd_journal_process(sd_journal *j); @@ -136,8 +138,8 @@ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec); #define SD_JOURNAL_FOREACH_DATA(j, data, l) \ for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) -/* #define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ */ -/* for (sd_journal_restart_unique(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) */ +#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ + for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; ) #ifdef __cplusplus } -- cgit v1.2.3-54-g00ecf From 15119c160268ce4ba9da4be67ed8adc412220b7d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 03:33:44 +0200 Subject: journalctl: implement quering field values with new -F switch Example: journalctl -F _SYSTEMD_UNIT will list all units that ever logged to the journal. --- man/journalctl.xml | 10 ++++++++++ src/journal/journalctl.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 7 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/man/journalctl.xml b/man/journalctl.xml index a533f4d0ea..4208fb4edc 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -349,6 +349,16 @@ time, respectively. + + + + + Print all possible + data values the specified field can + take in all entries of the + journal. + + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ebb88e053e..7d954e8367 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -88,9 +88,8 @@ static enum { static int help(void) { printf("%s [OPTIONS...] [MATCH]\n\n" - "Send control commands to or query the journal.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" + "Query the journal.\n\n" + "Flags:\n" " -c --cursor=CURSOR Start showing entries from specified cursor\n" " --since=DATE Start showing entries newer or of the specified date\n" " --until=DATE Stop showing entries older or of the specified date\n" @@ -107,15 +106,20 @@ static int help(void) { " --no-pager Do not pipe output into a pager\n" " -m --merge Show entries from all available journals\n" " -D --directory=PATH Show journal files from directory\n" - "Commands:\n" +#ifdef HAVE_GCRYPT + " --interval=TIME Time interval for changing the FSS sealing key\n" + " --verify-key=KEY Specify FSS verification key\n" +#endif + "\nCommands:\n" + " -h --help Show this help\n" + " --version Show package version\n" " --new-id128 Generate a new 128 Bit ID\n" " --header Show journal header information\n" " --disk-usage Show total disk usage\n" + " -F --field=FIELD List all values a certain field takes\n" #ifdef HAVE_GCRYPT " --setup-keys Generate new FSS key pair\n" - " --interval=TIME Time interval for changing the FSS sealing key\n" " --verify Verify journal file consistency\n" - " --verify-key=KEY Specify FSS verification key\n" #endif , program_invocation_short_name); @@ -164,6 +168,7 @@ static int parse_argv(int argc, char *argv[]) { { "since", required_argument, NULL, ARG_SINCE }, { "until", required_argument, NULL, ARG_UNTIL }, { "unit", required_argument, NULL, 'u' }, + { "field", required_argument, NULL, 'F' }, { NULL, 0, NULL, 0 } }; @@ -172,7 +177,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:", options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:", options, NULL)) >= 0) { switch (c) { @@ -369,6 +374,10 @@ static int parse_argv(int argc, char *argv[]) { case '?': return -EINVAL; + case 'F': + arg_field = optarg; + break; + default: log_error("Unknown option code %c", c); return -EINVAL; @@ -898,6 +907,30 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; + if (arg_field) { + const void *data; + size_t size; + + r = sd_journal_query_unique(j, arg_field); + if (r < 0) { + log_error("Failed to query unique data objects: %s", strerror(-r)); + goto finish; + } + + SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { + const void *eq; + + eq = memchr(data, '=', size); + if (eq) + printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1); + else + printf("%.*s\n", (int) size, (const char*) data); + } + + r = 0; + goto finish; + } + if (arg_cursor) { r = sd_journal_seek_cursor(j, arg_cursor); if (r < 0) { -- cgit v1.2.3-54-g00ecf From 15804cebfdf7bef91db1374967ee813cd4a93588 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 03:34:43 +0200 Subject: journalctl: move access check before the first access to the journal files --- src/journal/journalctl.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7d954e8367..5980eb0b48 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -814,6 +814,26 @@ static int verify(sd_journal *j) { return r; } +static int access_check(void) { + +#ifdef HAVE_ACL + if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) { + log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages."); + return -EACCES; + } + + if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) + log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off."); +#else + if (geteuid() != 0 && in_group("adm") <= 0) { + log_error("No access to messages. Only users in the group 'adm' can see messages."); + return -EACCES; + } +#endif + + return 0; +} + int main(int argc, char *argv[]) { int r; sd_journal *j = NULL; @@ -840,11 +860,14 @@ int main(int argc, char *argv[]) { goto finish; } + r = access_check(); + if (r < 0) + goto finish; + if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, 0); else r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY); - if (r < 0) { log_error("Failed to open journal: %s", strerror(-r)); goto finish; @@ -874,23 +897,6 @@ int main(int argc, char *argv[]) { goto finish; } -#ifdef HAVE_ACL - if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) { - log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages."); - r = -EACCES; - goto finish; - } - - if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0) - log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off."); -#else - if (geteuid() != 0 && in_group("adm") <= 0) { - log_error("No access to messages. Only users in the group 'adm' can see messages."); - r = -EACCES; - goto finish; - } -#endif - r = add_this_boot(j); if (r < 0) goto finish; -- cgit v1.2.3-54-g00ecf From fd6e88753716d8136037277c7db2196e0f979675 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 22:55:12 +0200 Subject: journalctl: honour -n if -F is used --- src/journal/journalctl.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5980eb0b48..7564c48e1f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -926,11 +926,16 @@ int main(int argc, char *argv[]) { SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { const void *eq; + if (arg_lines > 0 && n_shown >= arg_lines) + break; + eq = memchr(data, '=', size); if (eq) printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1); else printf("%.*s\n", (int) size, (const char*) data); + + n_shown ++; } r = 0; -- cgit v1.2.3-54-g00ecf From cd4b13e0bfe9281a0d2c0c3bef1c589d0684950b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 23:22:56 +0200 Subject: journalctl: don't ellipsize unless on a tty --- src/journal/journalctl.c | 14 +++++++------- src/shared/logs-show.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 7564c48e1f..5185b4b398 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -57,7 +57,7 @@ static OutputMode arg_output = OUTPUT_SHORT; static bool arg_follow = false; -static bool arg_show_all = false; +static bool arg_all = false; static bool arg_no_pager = false; static unsigned arg_lines = 0; static bool arg_no_tail = false; @@ -87,15 +87,15 @@ static enum { static int help(void) { - printf("%s [OPTIONS...] [MATCH]\n\n" + printf("%s [OPTIONS...] [MATCHES...]\n\n" "Query the journal.\n\n" "Flags:\n" - " -c --cursor=CURSOR Start showing entries from specified cursor\n" " --since=DATE Start showing entries newer or of the specified date\n" " --until=DATE Stop showing entries older or of the specified date\n" + " -c --cursor=CURSOR Start showing entries from specified cursor\n" " -b --this-boot Show data only from current boot\n" " -u --unit=UNIT Show data only from the specified unit\n" - " -p --priority=RANGE Show only messages within the specified priority range\n\n" + " -p --priority=RANGE Show only messages within the specified priority range\n" " -f --follow Follow journal\n" " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" @@ -217,7 +217,7 @@ static int parse_argv(int argc, char *argv[]) { break; case 'a': - arg_show_all = true; + arg_all = true; break; case 'n': @@ -1047,8 +1047,8 @@ int main(int argc, char *argv[]) { } flags = - arg_show_all * OUTPUT_SHOW_ALL | - have_pager * OUTPUT_FULL_WIDTH | + arg_all * OUTPUT_SHOW_ALL | + (!on_tty() || have_pager) * OUTPUT_FULL_WIDTH | on_tty() * OUTPUT_COLOR; r = output_journal(stdout, j, arg_output, 0, flags); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 05895366e2..63a48e4552 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -243,7 +243,7 @@ static int output_short( } } - if (flags) + if (flags & OUTPUT_SHOW_ALL) fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; -- cgit v1.2.3-54-g00ecf From f89a3b6f5bf695186e7b9e6cc63993b1272e7569 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 23:34:37 +0200 Subject: journalctl: unify ellipsation handling between journalctl and systemctl --- src/journal/journalctl.c | 7 ++++--- src/shared/pager.c | 22 ++++++++++++++-------- src/shared/pager.h | 3 ++- src/systemctl/systemctl.c | 5 +++-- 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 5185b4b398..d6f19e900a 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -840,7 +840,6 @@ int main(int argc, char *argv[]) { bool need_seek = false; sd_id128_t previous_boot_id; bool previous_boot_id_valid = false; - bool have_pager; unsigned n_shown = 0; log_parse_environment(); @@ -984,7 +983,9 @@ int main(int argc, char *argv[]) { } on_tty(); - have_pager = !arg_no_pager && !arg_follow && pager_open(); + + if (!arg_no_pager && !arg_follow) + pager_open(); if (!arg_quiet) { usec_t start, end; @@ -1048,7 +1049,7 @@ int main(int argc, char *argv[]) { flags = arg_all * OUTPUT_SHOW_ALL | - (!on_tty() || have_pager) * OUTPUT_FULL_WIDTH | + (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | on_tty() * OUTPUT_COLOR; r = output_journal(stdout, j, arg_output, 0, flags); diff --git a/src/shared/pager.c b/src/shared/pager.c index 36b409c070..6799787e85 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -44,20 +44,21 @@ _noreturn_ static void pager_fallback(void) { _exit(EXIT_SUCCESS); } -bool pager_open(void) { +int pager_open(void) { int fd[2]; const char *pager; pid_t parent_pid; + int r; if (pager_pid > 0) - return false; + return 1; if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER"))) if (!*pager || streq(pager, "cat")) - return false; + return 0; if (isatty(STDOUT_FILENO) <= 0) - return false; + return 0; /* Determine and cache number of columns before we spawn the * pager so that we get the value from the actual tty */ @@ -65,16 +66,17 @@ bool pager_open(void) { if (pipe(fd) < 0) { log_error("Failed to create pager pipe: %m"); - return false; + return -errno; } parent_pid = getpid(); pager_pid = fork(); if (pager_pid < 0) { + r = -errno; log_error("Failed to fork pager: %m"); close_pipe(fd); - return false; + return r; } /* In the child start the pager */ @@ -117,11 +119,11 @@ bool pager_open(void) { /* Return in the parent */ if (dup2(fd[1], STDOUT_FILENO) < 0) { log_error("Failed to duplicate pager pipe: %m"); - return false; + return -errno; } close_pipe(fd); - return true; + return 1; } void pager_close(void) { @@ -135,3 +137,7 @@ void pager_close(void) { wait_for_terminate(pager_pid, NULL); pager_pid = 0; } + +bool pager_have(void) { + return pager_pid > 0; +} diff --git a/src/shared/pager.h b/src/shared/pager.h index 0b4afc04b8..5e7b5ab91e 100644 --- a/src/shared/pager.h +++ b/src/shared/pager.h @@ -23,5 +23,6 @@ #include -bool pager_open(void); +int pager_open(void); void pager_close(void); +bool pager_have(void); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7d6a6a24f3..82c801e4d9 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2293,9 +2293,10 @@ static void print_status_info(UnitStatusInfo *i) { if (i->id && arg_transport != TRANSPORT_SSH) { int flags = arg_all * OUTPUT_SHOW_ALL | + (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | + on_tty() * OUTPUT_COLOR | arg_follow * OUTPUT_FOLLOW | - !arg_quiet * OUTPUT_WARN_CUTOFF | - on_tty() * OUTPUT_COLOR; + !arg_quiet * OUTPUT_WARN_CUTOFF; printf("\n"); show_journal_by_unit(stdout, -- cgit v1.2.3-54-g00ecf From 8481248b9fbddc6d5e6ff26eb23505ef13dc85f7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Oct 2012 23:59:41 +0200 Subject: util: unify usage of on_tty() in util.c --- TODO | 2 ++ src/journal/journal-verify.c | 4 ++-- src/journal/journalctl.c | 21 ++------------------- src/login/loginctl.c | 17 ----------------- src/shared/pager.c | 2 +- src/shared/util.c | 16 +++++++++++----- src/shared/util.h | 1 + src/systemctl/systemctl.c | 18 ------------------ 8 files changed, 19 insertions(+), 62 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/TODO b/TODO index bb7d8eea21..1c33ead227 100644 --- a/TODO +++ b/TODO @@ -19,6 +19,8 @@ F18: Features: +* drop --follow from systemctl + * don't show cgroup in "systemctl status" if empty/non-existant, especially for foreign .mount units * timedated: export boolean that clarifies whether NTP is even available diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 551f04af35..1a67d5a04b 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -178,7 +178,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) { unsigned n, i, j, k; usec_t z, x; - if (!isatty(STDOUT_FILENO)) + if (!on_tty()) return; z = now(CLOCK_MONOTONIC); @@ -212,7 +212,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) { static void flush_progress(void) { unsigned n, i; - if (!isatty(STDOUT_FILENO)) + if (!on_tty()) return; n = (3 * columns()) / 4; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index d6f19e900a..f4b6518557 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -400,21 +400,6 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static bool on_tty(void) { - static int t = -1; - - /* Note that this is invoked relatively early, before we start - * the pager. That means the value we return reflects whether - * we originally were started on a tty, not if we currently - * are. But this is intended, since we want colour and so on - * when run in our own pager. */ - - if (_unlikely_(t < 0)) - t = isatty(STDOUT_FILENO) > 0; - - return t; -} - static int generate_new_id128(void) { sd_id128_t id; int r; @@ -697,7 +682,7 @@ static int setup_keys(void) { goto finish; } - if (isatty(STDOUT_FILENO)) { + if (on_tty()) { fprintf(stderr, "\n" "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n" @@ -719,7 +704,7 @@ static int setup_keys(void) { printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); - if (isatty(STDOUT_FILENO)) { + if (on_tty()) { char tsb[FORMAT_TIMESPAN_MAX], *hn; fprintf(stderr, @@ -982,8 +967,6 @@ int main(int argc, char *argv[]) { goto finish; } - on_tty(); - if (!arg_no_pager && !arg_follow) pager_open(); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 97c6617d7d..24941fef34 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -50,26 +50,9 @@ static enum transport { static bool arg_ask_password = true; static const char *arg_host = NULL; -static bool on_tty(void) { - static int t = -1; - - /* Note that this is invoked relatively early, before we start - * the pager. That means the value we return reflects whether - * we originally were started on a tty, not if we currently - * are. But this is intended, since we want colour and so on - * when run in our own pager. */ - - if (_unlikely_(t < 0)) - t = isatty(STDOUT_FILENO) > 0; - - return t; -} - static void pager_open_if_enabled(void) { /* Cache result before we open the pager */ - on_tty(); - if (arg_no_pager) return; diff --git a/src/shared/pager.c b/src/shared/pager.c index 6799787e85..488a12c763 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -57,7 +57,7 @@ int pager_open(void) { if (!*pager || streq(pager, "cat")) return 0; - if (isatty(STDOUT_FILENO) <= 0) + if (!on_tty()) return 0; /* Determine and cache number of columns before we spawn the diff --git a/src/shared/util.c b/src/shared/util.c index 462b541b41..527a5800fe 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2175,28 +2175,25 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { } int ask(char *ret, const char *replies, const char *text, ...) { - bool on_tty; assert(ret); assert(replies); assert(text); - on_tty = isatty(STDOUT_FILENO); - for (;;) { va_list ap; char c; int r; bool need_nl = true; - if (on_tty) + if (on_tty()) fputs(ANSI_HIGHLIGHT_ON, stdout); va_start(ap, text); vprintf(text, ap); va_end(ap); - if (on_tty) + if (on_tty()) fputs(ANSI_HIGHLIGHT_OFF, stdout); fflush(stdout); @@ -3820,6 +3817,15 @@ void columns_cache_reset(int signum) { cached_columns = 0; } +bool on_tty(void) { + static int cached_on_tty = -1; + + if (_unlikely_(cached_on_tty < 0)) + cached_on_tty = isatty(STDOUT_FILENO) > 0; + + return cached_on_tty; +} + int fd_lines(int fd) { struct winsize ws; zero(ws); diff --git a/src/shared/util.h b/src/shared/util.h index 662c3d1f39..e19f76c1ea 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -385,6 +385,7 @@ int status_welcome(void); int fd_columns(int fd); unsigned columns(void); void columns_cache_reset(int _unused_ signum); +bool on_tty(void); int fd_lines(int fd); unsigned lines(void); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 82c801e4d9..d77d534e0b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -132,26 +132,8 @@ static bool private_bus = false; static int daemon_reload(DBusConnection *bus, char **args); static void halt_now(enum action a); -static bool on_tty(void) { - static int t = -1; - - /* Note that this is invoked relatively early, before we start - * the pager. That means the value we return reflects whether - * we originally were started on a tty, not if we currently - * are. But this is intended, since we want colour and so on - * when run in our own pager. */ - - if (_unlikely_(t < 0)) - t = isatty(STDOUT_FILENO) > 0; - - return t; -} - static void pager_open_if_enabled(void) { - /* Cache result before we open the pager */ - on_tty(); - if (arg_no_pager) return; -- cgit v1.2.3-54-g00ecf From ed757c0cb03eef50e8d9aeb4682401c3e9486f0b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Oct 2012 00:06:47 +0200 Subject: util: unify line caching and column caching --- src/cgtop/cgtop.c | 8 ++++---- src/journal/journalctl.c | 3 ++- src/shared/util.c | 50 ++++++++++++++++++++++++++---------------------- src/shared/util.h | 6 +++--- 4 files changed, 36 insertions(+), 31 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index ee421e383b..f2e62761f1 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -443,9 +443,9 @@ static int display(Hashmap *a) { qsort(array, n, sizeof(Group*), group_compare); - rows = fd_lines(STDOUT_FILENO); - if (rows <= 0) - rows = 25; + rows = lines(); + if (rows <= 10) + rows = 10; path_columns = columns() - 42; if (path_columns < 10) @@ -653,7 +653,7 @@ int main(int argc, char *argv[]) { goto finish; } - signal(SIGWINCH, columns_cache_reset); + signal(SIGWINCH, columns_lines_cache_reset); while (!quit) { Hashmap *c; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f4b6518557..d1338d2b7c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -197,7 +197,6 @@ static int parse_argv(int argc, char *argv[]) { case 'f': arg_follow = true; - signal(SIGWINCH, columns_cache_reset); break; case 'o': @@ -834,6 +833,8 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; + signal(SIGWINCH, columns_lines_cache_reset); + if (arg_action == ACTION_NEW_ID128) { r = generate_new_id128(); goto finish; diff --git a/src/shared/util.c b/src/shared/util.c index 527a5800fe..ef30cb2dab 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -73,6 +73,7 @@ int saved_argc = 0; char **saved_argv = NULL; static volatile unsigned cached_columns = 0; +static volatile unsigned cached_lines = 0; size_t page_size(void) { static __thread size_t pgsz = 0; @@ -3812,20 +3813,6 @@ unsigned columns(void) { return c; } -/* intended to be used as a SIGWINCH sighandler */ -void columns_cache_reset(int signum) { - cached_columns = 0; -} - -bool on_tty(void) { - static int cached_on_tty = -1; - - if (_unlikely_(cached_on_tty < 0)) - cached_on_tty = isatty(STDOUT_FILENO) > 0; - - return cached_on_tty; -} - int fd_lines(int fd) { struct winsize ws; zero(ws); @@ -3840,23 +3827,40 @@ int fd_lines(int fd) { } unsigned lines(void) { - static __thread int parsed_lines = 0; const char *e; + unsigned l; - if (_likely_(parsed_lines > 0)) - return parsed_lines; + if (_likely_(cached_lines > 0)) + return cached_lines; + l = 0; e = getenv("LINES"); if (e) - parsed_lines = atoi(e); + safe_atou(e, &l); - if (parsed_lines <= 0) - parsed_lines = fd_lines(STDOUT_FILENO); + if (l <= 0) + l = fd_lines(STDOUT_FILENO); - if (parsed_lines <= 0) - parsed_lines = 25; + if (l <= 0) + l = 24; - return parsed_lines; + cached_lines = l; + return cached_lines; +} + +/* intended to be used as a SIGWINCH sighandler */ +void columns_lines_cache_reset(int signum) { + cached_columns = 0; + cached_lines = 0; +} + +bool on_tty(void) { + static int cached_on_tty = -1; + + if (_unlikely_(cached_on_tty < 0)) + cached_on_tty = isatty(STDOUT_FILENO) > 0; + + return cached_on_tty; } int running_in_chroot(void) { diff --git a/src/shared/util.h b/src/shared/util.h index e19f76c1ea..affb66998c 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -384,11 +384,11 @@ int status_welcome(void); int fd_columns(int fd); unsigned columns(void); -void columns_cache_reset(int _unused_ signum); -bool on_tty(void); - int fd_lines(int fd); unsigned lines(void); +void columns_lines_cache_reset(int _unused_ signum); + +bool on_tty(void); int running_in_chroot(void); -- cgit v1.2.3-54-g00ecf From db87a36e74ff26d1046a451ee086c9a2c4113d12 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Oct 2012 01:05:55 +0200 Subject: journalctl: remove left-over log message --- src/journal/journalctl.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index d1338d2b7c..0f20448bf0 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -547,8 +547,6 @@ static int add_priorities(sd_journal *j) { if (arg_priorities & (1 << i)) { match[sizeof(match)-2] = '0' + i; - log_info("adding match %s", match); - r = sd_journal_add_match(j, match, strlen(match)); if (r < 0) { log_error("Failed to add match: %s", strerror(-r)); -- cgit v1.2.3-54-g00ecf From 0901758558506273c0b7553dc3cae587f2b94290 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Fri, 2 Nov 2012 17:27:15 +0100 Subject: util: add is_locale_utf8() journalctl and vconsole-setup both implement utf8 locale detection. Let's have a common function for it. The next patch will add another use. --- src/journal/journalctl.c | 6 +----- src/shared/util.c | 25 +++++++++++++++++++++++++ src/shared/util.h | 2 ++ src/vconsole/vconsole-setup.c | 15 --------------- 4 files changed, 28 insertions(+), 20 deletions(-) (limited to 'src/journal/journalctl.c') diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 0f20448bf0..d1407abd9e 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include @@ -719,9 +717,7 @@ static int setup_keys(void) { #ifdef HAVE_QRENCODE /* If this is not an UTF-8 system don't print any QR codes */ - setlocale(LC_CTYPE, ""); - - if (streq_ptr(nl_langinfo(CODESET), "UTF-8")) { + if (is_locale_utf8()) { fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); } diff --git a/src/shared/util.c b/src/shared/util.c index 402b7caa3f..3ac67505f0 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -57,6 +57,8 @@ #include #include #include +#include +#include #include "macro.h" #include "util.h" @@ -6115,3 +6117,26 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, } return NULL; } + +bool is_locale_utf8(void) { + const char *set; + static int cached_answer = -1; + + if (cached_answer >= 0) + goto out; + + if (!setlocale(LC_ALL, "")) { + cached_answer = true; + goto out; + } + + set = nl_langinfo(CODESET); + if (!set) { + cached_answer = true; + goto out; + } + + cached_answer = streq(set, "UTF-8"); +out: + return (bool)cached_answer; +} diff --git a/src/shared/util.h b/src/shared/util.h index 284035c33b..b979b0e89f 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -598,3 +598,5 @@ int parse_timestamp(const char *t, usec_t *usec); void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg); + +bool is_locale_utf8(void); diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 6e016ad338..cb7ade0d24 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include #include @@ -48,19 +46,6 @@ static bool is_vconsole(int fd) { return ioctl(fd, TIOCLINUX, data) >= 0; } -static bool is_locale_utf8(void) { - const char *set; - - if (!setlocale(LC_ALL, "")) - return true; - - set = nl_langinfo(CODESET); - if (!set) - return true; - - return streq(set, "UTF-8"); -} - static int disable_utf8(int fd) { int r = 0, k; -- cgit v1.2.3-54-g00ecf From a9cdc94f7ff40f22a3cf9472f612a80730a1b010 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Mon, 12 Nov 2012 14:16:07 -0500 Subject: enable localization for common *ctl commands --- src/hostname/hostnamectl.c | 2 ++ src/journal/coredumpctl.c | 2 ++ src/journal/journalctl.c | 2 ++ src/locale/localectl.c | 2 ++ src/login/loginctl.c | 2 ++ src/systemctl/systemctl.c | 2 ++ src/timedate/timedatectl.c | 2 ++ 7 files changed, 14 insertions(+) (limited to 'src/journal/journalctl.c') diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index e7b2b49f29..b7ae5ccc6c 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -507,6 +508,7 @@ int main(int argc, char *argv[]) { dbus_error_init(&error); + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index bdea8ed057..4adc9236f1 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -19,6 +19,7 @@ along with systemd; If not, see . ***/ +#include #include #include #include @@ -514,6 +515,7 @@ int main(int argc, char *argv[]) { Iterator it; int r = 0; + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index d1407abd9e..cccd8a7692 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -19,6 +19,7 @@ along with systemd; If not, see . ***/ +#include #include #include #include @@ -820,6 +821,7 @@ int main(int argc, char *argv[]) { bool previous_boot_id_valid = false; unsigned n_shown = 0; + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 7d3ac0ad2f..fa73bcaac6 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -19,6 +19,7 @@ along with systemd; If not, see . ***/ +#include #include #include #include @@ -740,6 +741,7 @@ int main(int argc, char *argv[]) { dbus_error_init(&error); + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 24941fef34..146986b46e 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "log.h" #include "util.h" @@ -1568,6 +1569,7 @@ int main(int argc, char*argv[]) { dbus_error_init(&error); + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index a85a6baf76..b82c79435d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -5240,6 +5241,7 @@ int main(int argc, char*argv[]) { dbus_error_init(&error); + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 06b98b1061..caa5bc7dfb 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -677,6 +678,7 @@ int main(int argc, char *argv[]) { dbus_error_init(&error); + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); -- cgit v1.2.3-54-g00ecf