#include "hashmap.h"
#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;
(direction == DIRECTION_DOWN && cp < tp) ||
(direction == DIRECTION_UP && cp > tp)) {
to = c;
- tp = tp;
+ tp = cp;
}
}
uint64_t np, n;
bool found, term_result = false;
Match *m, *term_match = NULL;
+ Object *npo = NULL;
n = journal_file_entry_n_items(c);
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
* where we'd have to try next, in case the other
* matches are not OK */
- r = journal_file_next_entry_for_data(f, c, cp, le64toh(c->entry.items[k].object_offset), direction, NULL, &q);
+ r = journal_file_next_entry_for_data(f, c, cp, le64toh(c->entry.items[k].object_offset), direction, &qo, &q);
if (r > 0) {
if (direction == DIRECTION_DOWN) {
- if (q > np)
+ if (q > np) {
np = q;
+ npo = qo;
+ }
} else {
- if (np == 0 || q < np)
+ if (np == 0 || q < np) {
np = q;
+ npo = qo;
+ }
}
}
}
/* Check the last term */
- if (term_match && term_result)
- found = true;
+ if (term_match && !term_result)
+ found = false;
/* Did this entry match against all matches? */
if (found) {
/* Hmm, ok, this entry only matched partially, so
* let's try another one */
cp = np;
+ c = npo;
}
}
assert(f);
if (f->current_offset > 0) {
- r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &c);
+ cp = f->current_offset;
+
+ r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
if (r < 0)
return r;
- cp = f->current_offset;
-
r = next_with_matches(j, f, direction, &c, &cp);
if (r <= 0)
return r;
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
return r;
}
- journal_file_dump(f);
+ /* journal_file_dump(f); */
r = hashmap_put(j->files, f->path, f);
if (r < 0) {
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;
}
}
-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[] =
if (!j)
return -ENOMEM;
+ j->flags = flags;
+
j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
if (j->inotify_fd < 0) {
r = -errno;
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)
size_t t;
p = le64toh(o->entry.items[i].object_offset);
- le_hash = o->entry.items[j->current_field].hash;
+ le_hash = o->entry.items[i].hash;
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
if (r < 0)
return r;
l = le64toh(o->object.size) - offsetof(Object, data.payload);
- if (l >= field_length+1 &&
- memcmp(o->data.payload, field, field_length) == 0 &&
- o->data.payload[field_length] == '=') {
+ if (o->object.flags & OBJECT_COMPRESSED) {
+
+#ifdef HAVE_XZ
+ if (uncompress_startswith(o->data.payload, l,
+ &f->compress_buffer, &f->compress_buffer_size,
+ field, field_length, '=')) {
+
+ 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;
+
+ return 0;
+ }
+#else
+ return -EPROTONOSUPPORT;
+#endif
+
+ } else if (l >= field_length+1 &&
+ memcmp(o->data.payload, field, field_length) == 0 &&
+ o->data.payload[field_length] == '=') {
t = (size_t) l;
if ((uint64_t) t != l)
return -E2BIG;
- *data = o->data.payload;
- *size = t;
+ 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;
+ }
j->current_field ++;
}
}
}
+
+int sd_journal_query_unique(sd_journal *j, const char *field) {
+ assert(j);
+ assert(field);
+
+ return -ENOTSUP;
+}
+
+int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) {
+ assert(j);
+
+ return -ENOTSUP;
+}
+
+void sd_journal_restart_unique(sd_journal *j) {
+ assert(j);
+}