summaryrefslogtreecommitdiffstats
path: root/src/libsystemd/sd-journal
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-journal')
-rw-r--r--src/libsystemd/sd-journal/catalog.c91
-rw-r--r--src/libsystemd/sd-journal/catalog.h2
-rw-r--r--src/libsystemd/sd-journal/fsprg.c208
-rw-r--r--src/libsystemd/sd-journal/fsprg.h25
-rw-r--r--src/libsystemd/sd-journal/journal-authenticate.c68
-rw-r--r--src/libsystemd/sd-journal/journal-file.c104
-rw-r--r--src/libsystemd/sd-journal/journal-file.h4
-rw-r--r--src/libsystemd/sd-journal/journal-internal.h18
-rw-r--r--src/libsystemd/sd-journal/journal-send.c27
-rw-r--r--src/libsystemd/sd-journal/journal-send.h17
-rw-r--r--src/libsystemd/sd-journal/journal-verify.c3
-rw-r--r--src/libsystemd/sd-journal/sd-journal.c566
-rw-r--r--src/libsystemd/sd-journal/test-journal-append.c4
-rw-r--r--src/libsystemd/sd-journal/test-journal-enum.c6
-rw-r--r--src/libsystemd/sd-journal/test-journal-flush.c92
-rw-r--r--src/libsystemd/sd-journal/test-journal-init.c11
-rw-r--r--src/libsystemd/sd-journal/test-journal-interleaving.c279
-rw-r--r--src/libsystemd/sd-journal/test-journal-match.c44
-rw-r--r--src/libsystemd/sd-journal/test-journal-stream.c20
-rw-r--r--src/libsystemd/sd-journal/test-journal-verify.c6
-rw-r--r--src/libsystemd/sd-journal/test-journal.c12
21 files changed, 1011 insertions, 596 deletions
diff --git a/src/libsystemd/sd-journal/catalog.c b/src/libsystemd/sd-journal/catalog.c
index ae91534..a0b673f 100644
--- a/src/libsystemd/sd-journal/catalog.c
+++ b/src/libsystemd/sd-journal/catalog.c
@@ -16,6 +16,7 @@
#include "conf-files.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "log.h"
#include "memory-util.h"
@@ -54,7 +55,7 @@ typedef struct CatalogItem {
} CatalogItem;
static void catalog_hash_func(const CatalogItem *i, struct siphash *state) {
- siphash24_compress(&i->id, sizeof(i->id), state);
+ siphash24_compress_typesafe(i->id, state);
siphash24_compress_string(i->language, state);
}
@@ -222,10 +223,7 @@ static int catalog_entry_lang(
const char* deflang,
char **ret) {
- size_t c;
- char *z;
-
- c = strlen(t);
+ size_t c = strlen(t);
if (c < 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"[%s:%u] Language too short.", filename, line);
@@ -242,12 +240,7 @@ static int catalog_entry_lang(
log_warning("[%s:%u] language differs from default for file", filename, line);
}
- z = strdup(t);
- if (!z)
- return -ENOMEM;
-
- *ret = z;
- return 0;
+ return strdup_to(ret, t);
}
int catalog_import_file(OrderedHashmap *h, const char *path) {
@@ -382,10 +375,8 @@ static int64_t write_catalog(
CatalogItem *items,
size_t n) {
+ _cleanup_(unlink_and_freep) char *p = NULL;
_cleanup_fclose_ FILE *w = NULL;
- _cleanup_free_ char *p = NULL;
- CatalogHeader header;
- size_t k;
int r;
r = mkdir_parents(database, 0755);
@@ -394,54 +385,35 @@ static int64_t write_catalog(
r = fopen_temporary(database, &w, &p);
if (r < 0)
- return log_error_errno(r, "Failed to open database for writing: %s: %m",
- database);
+ return log_error_errno(r, "Failed to open database for writing: %s: %m", database);
- header = (CatalogHeader) {
+ CatalogHeader header = {
.signature = CATALOG_SIGNATURE,
.header_size = htole64(CONST_ALIGN_TO(sizeof(CatalogHeader), 8)),
.catalog_item_size = htole64(sizeof(CatalogItem)),
.n_items = htole64(n),
};
- r = -EIO;
+ if (fwrite(&header, sizeof(header), 1, w) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "%s: failed to write header.", p);
- k = fwrite(&header, 1, sizeof(header), w);
- if (k != sizeof(header)) {
- log_error("%s: failed to write header.", p);
- goto error;
- }
+ if (fwrite(items, sizeof(CatalogItem), n, w) != n)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "%s: failed to write database.", p);
- k = fwrite(items, 1, n * sizeof(CatalogItem), w);
- if (k != n * sizeof(CatalogItem)) {
- log_error("%s: failed to write database.", p);
- goto error;
- }
-
- k = fwrite(sb->buf, 1, sb->len, w);
- if (k != sb->len) {
- log_error("%s: failed to write strings.", p);
- goto error;
- }
+ if (fwrite(sb->buf, sb->len, 1, w) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "%s: failed to write strings.", p);
r = fflush_and_check(w);
- if (r < 0) {
- log_error_errno(r, "%s: failed to write database: %m", p);
- goto error;
- }
+ if (r < 0)
+ return log_error_errno(r, "%s: failed to write database: %m", p);
(void) fchmod(fileno(w), 0644);
- if (rename(p, database) < 0) {
- r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database);
- goto error;
- }
+ if (rename(p, database) < 0)
+ return log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database);
+ p = mfree(p); /* free without unlinking */
return ftello(w);
-
-error:
- (void) unlink(p);
- return r;
}
int catalog_update(const char* database, const char* root, const char* const* dirs) {
@@ -472,11 +444,12 @@ int catalog_update(const char* database, const char* root, const char* const* di
return log_error_errno(r, "Failed to import file '%s': %m", *f);
}
- if (ordered_hashmap_size(h) <= 0) {
+ if (ordered_hashmap_isempty(h)) {
log_info("No items in catalog.");
return 0;
- } else
- log_debug("Found %u items in catalog.", ordered_hashmap_size(h));
+ }
+
+ log_debug("Found %u items in catalog.", ordered_hashmap_size(h));
items = new(CatalogItem, ordered_hashmap_size(h));
if (!items)
@@ -607,15 +580,14 @@ static const char *find_id(void *p, sd_id128_t id) {
le64toh(f->offset);
}
-int catalog_get(const char* database, sd_id128_t id, char **_text) {
+int catalog_get(const char* database, sd_id128_t id, char **ret_text) {
_cleanup_close_ int fd = -EBADF;
void *p = NULL;
- struct stat st = {};
- char *text = NULL;
+ struct stat st;
int r;
const char *s;
- assert(_text);
+ assert(ret_text);
r = open_mmap(database, &fd, &st, &p);
if (r < 0)
@@ -627,18 +599,9 @@ int catalog_get(const char* database, sd_id128_t id, char **_text) {
goto finish;
}
- text = strdup(s);
- if (!text) {
- r = -ENOMEM;
- goto finish;
- }
-
- *_text = text;
- r = 0;
-
+ r = strdup_to(ret_text, s);
finish:
- if (p)
- munmap(p, st.st_size);
+ (void) munmap(p, st.st_size);
return r;
}
diff --git a/src/libsystemd/sd-journal/catalog.h b/src/libsystemd/sd-journal/catalog.h
index df27869..b5a97fa 100644
--- a/src/libsystemd/sd-journal/catalog.h
+++ b/src/libsystemd/sd-journal/catalog.h
@@ -11,7 +11,7 @@
int catalog_import_file(OrderedHashmap *h, const char *path);
int catalog_update(const char* database, const char* root, const char* const* dirs);
-int catalog_get(const char* database, sd_id128_t id, char **data);
+int catalog_get(const char* database, sd_id128_t id, char **ret_text);
int catalog_list(FILE *f, const char* database, bool oneline);
int catalog_list_items(FILE *f, const char* database, bool oneline, char **items);
int catalog_file_lang(const char *filename, char **lang);
diff --git a/src/libsystemd/sd-journal/fsprg.c b/src/libsystemd/sd-journal/fsprg.c
index e86be6a..85632b0 100644
--- a/src/libsystemd/sd-journal/fsprg.c
+++ b/src/libsystemd/sd-journal/fsprg.c
@@ -3,21 +3,6 @@
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
* Copyright © 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
*/
/*
@@ -50,11 +35,11 @@ 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(sym_gcry_mpi_cmp_ui(x, 0) >= 0);
+ len = (sym_gcry_mpi_get_nbits(x) + 7) / 8;
assert(len <= buflen);
memzero(buf, buflen);
- gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x);
+ sym_gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x);
assert(nwritten == len);
}
@@ -62,10 +47,10 @@ static gcry_mpi_t mpi_import(const void *buf, size_t buflen) {
gcry_mpi_t h;
_unused_ unsigned len;
- assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0);
- len = (gcry_mpi_get_nbits(h) + 7) / 8;
+ assert_se(sym_gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0);
+ len = (sym_gcry_mpi_get_nbits(h) + 7) / 8;
assert(len <= buflen);
- assert(gcry_mpi_cmp_ui(h, 0) >= 0);
+ assert(sym_gcry_mpi_cmp_ui(h, 0) >= 0);
return h;
}
@@ -102,30 +87,30 @@ static void det_randomize(void *buf, size_t buflen, const void *seed, size_t see
gcry_error_t err;
uint32_t ctr;
- olen = gcry_md_get_algo_dlen(RND_HASH);
- err = gcry_md_open(&hd, RND_HASH, 0);
+ olen = sym_gcry_md_get_algo_dlen(RND_HASH);
+ err = sym_gcry_md_open(&hd, RND_HASH, 0);
assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
- 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);
+ sym_gcry_md_write(hd, seed, seedlen);
+ sym_gcry_md_putc(hd, (idx >> 24) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 16) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 8) & 0xff);
+ sym_gcry_md_putc(hd, (idx >> 0) & 0xff);
for (ctr = 0; buflen; ctr++) {
- err = gcry_md_copy(&hd2, hd);
+ err = sym_gcry_md_copy(&hd2, hd);
assert_se(gcry_err_code(err) == GPG_ERR_NO_ERROR); /* This shouldn't happen */
- 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);
+ sym_gcry_md_putc(hd2, (ctr >> 24) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 16) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 8) & 0xff);
+ sym_gcry_md_putc(hd2, (ctr >> 0) & 0xff);
+ sym_gcry_md_ctl(hd2, GCRYCTL_FINALIZE, NULL, 0);
cpylen = (buflen < olen) ? buflen : olen;
- memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen);
- gcry_md_close(hd2);
+ memcpy(buf, sym_gcry_md_read(hd2, RND_HASH), cpylen);
+ sym_gcry_md_close(hd2);
buf += cpylen;
buflen -= cpylen;
}
- gcry_md_close(hd);
+ sym_gcry_md_close(hd);
}
/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */
@@ -142,8 +127,8 @@ static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint
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);
+ while (sym_gcry_prime_check(p, 0))
+ sym_gcry_mpi_add_ui(p, p, 4);
return p;
}
@@ -157,8 +142,8 @@ static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen
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);
+ assert(sym_gcry_mpi_cmp(x, n) < 0);
+ sym_gcry_mpi_mulm(x, x, x, n);
return x;
}
@@ -167,51 +152,51 @@ 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);
+ phi = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_sub_ui(phi, p, 1);
/* count number of used bits in m */
for (n = 0; (1ULL << n) <= m; n++)
;
- r = gcry_mpi_new(0);
- gcry_mpi_set_ui(r, 1);
+ r = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_set_ui(r, 1);
while (n) { /* square and multiply algorithm for fast exponentiation */
n--;
- gcry_mpi_mulm(r, r, r, phi);
+ sym_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);
+ sym_gcry_mpi_add(r, r, r);
+ if (sym_gcry_mpi_cmp(r, phi) >= 0)
+ sym_gcry_mpi_sub(r, r, phi);
}
}
- gcry_mpi_release(phi);
+ sym_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);
+ *xp = sym_gcry_mpi_new(0);
+ *xq = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_mod(*xp, x, p);
+ sym_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);
+ a = sym_gcry_mpi_new(0);
+ u = sym_gcry_mpi_new(0);
+ *x = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_subm(a, xq, xp, q);
+ sym_gcry_mpi_invm(u, p, q);
+ sym_gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */
+ sym_gcry_mpi_mul(*x, p, a);
+ sym_gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */
+ sym_gcry_mpi_release(a);
+ sym_gcry_mpi_release(u);
}
/******************************************************************************/
@@ -245,18 +230,21 @@ static uint16_t read_secpar(const void *buf) {
return 16 * (secpar + 1);
}
-void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) {
+int 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;
+ int r;
VALIDATE_SECPAR(_secpar);
secpar = _secpar;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
if (!seed) {
- gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM);
+ sym_gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM);
seed = iseed;
seedlen = FSPRG_RECOMMENDED_SEEDLEN;
}
@@ -271,25 +259,30 @@ void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigne
}
if (mpk) {
- n = gcry_mpi_new(0);
- gcry_mpi_mul(n, p, q);
- assert(gcry_mpi_get_nbits(n) == secpar);
+ n = sym_gcry_mpi_new(0);
+ sym_gcry_mpi_mul(n, p, q);
+ assert(sym_gcry_mpi_get_nbits(n) == secpar);
store_secpar(mpk + 0, secpar);
mpi_export(mpk + 2, secpar / 8, n);
- gcry_mpi_release(n);
+ sym_gcry_mpi_release(n);
}
- gcry_mpi_release(p);
- gcry_mpi_release(q);
+ sym_gcry_mpi_release(p);
+ sym_gcry_mpi_release(q);
+
+ return 0;
}
-void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) {
+int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) {
gcry_mpi_t n, x;
uint16_t secpar;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(mpk + 0);
n = mpi_import(mpk + 2, secpar / 8);
@@ -299,30 +292,37 @@ void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seed
mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x);
memzero(state + 2 + 2 * secpar / 8, 8);
- gcry_mpi_release(n);
- gcry_mpi_release(x);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+
+ return 0;
}
-void FSPRG_Evolve(void *state) {
+int FSPRG_Evolve(void *state) {
gcry_mpi_t n, x;
uint16_t secpar;
uint64_t epoch;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
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);
+ sym_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);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+
+ return 0;
}
uint64_t FSPRG_GetEpoch(const void *state) {
@@ -331,18 +331,21 @@ uint64_t FSPRG_GetEpoch(const void *state) {
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) {
+int 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;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
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);
+ n = sym_gcry_mpi_new(0);
+ sym_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 */
@@ -350,8 +353,8 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed,
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) */
+ sym_gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */
+ sym_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 */
@@ -360,22 +363,29 @@ void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed,
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);
+ sym_gcry_mpi_release(p);
+ sym_gcry_mpi_release(q);
+ sym_gcry_mpi_release(n);
+ sym_gcry_mpi_release(x);
+ sym_gcry_mpi_release(xp);
+ sym_gcry_mpi_release(xq);
+ sym_gcry_mpi_release(kp);
+ sym_gcry_mpi_release(kq);
+ sym_gcry_mpi_release(xm);
+
+ return 0;
}
-void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) {
+int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) {
uint16_t secpar;
+ int r;
- initialize_libgcrypt(false);
+ r = initialize_libgcrypt(false);
+ if (r < 0)
+ return r;
secpar = read_secpar(state + 0);
det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx);
+
+ return 0;
}
diff --git a/src/libsystemd/sd-journal/fsprg.h b/src/libsystemd/sd-journal/fsprg.h
index d3d88aa..a0594cd 100644
--- a/src/libsystemd/sd-journal/fsprg.h
+++ b/src/libsystemd/sd-journal/fsprg.h
@@ -5,21 +5,6 @@
* fsprg v0.1 - (seekable) forward-secure pseudorandom generator
* Copyright © 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 <inttypes.h>
@@ -39,22 +24,22 @@ size_t FSPRG_mpkinbytes(unsigned secpar) _const_;
size_t FSPRG_stateinbytes(unsigned secpar) _const_;
/* 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);
+int 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);
+int FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen);
-void FSPRG_Evolve(void *state);
+int FSPRG_Evolve(void *state);
uint64_t FSPRG_GetEpoch(const void *state) _pure_;
/* 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);
+int 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);
+int FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx);
#ifdef __cplusplus
}
diff --git a/src/libsystemd/sd-journal/journal-authenticate.c b/src/libsystemd/sd-journal/journal-authenticate.c
index 8e7533e..64f5739 100644
--- a/src/libsystemd/sd-journal/journal-authenticate.c
+++ b/src/libsystemd/sd-journal/journal-authenticate.c
@@ -71,7 +71,7 @@ int journal_file_append_tag(JournalFile *f) {
return r;
/* Get the HMAC tag and store it in the object */
- memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH);
+ memcpy(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH);
f->hmac_running = false;
return 0;
@@ -80,6 +80,7 @@ int journal_file_append_tag(JournalFile *f) {
int journal_file_hmac_start(JournalFile *f) {
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
gcry_error_t err;
+ int r;
assert(f);
@@ -90,13 +91,17 @@ int journal_file_hmac_start(JournalFile *f) {
return 0;
/* Prepare HMAC for next cycle */
- gcry_md_reset(f->hmac);
- FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
- err = gcry_md_setkey(f->hmac, key, sizeof(key));
+ sym_gcry_md_reset(f->hmac);
+
+ r = FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0);
+ if (r < 0)
+ return r;
+
+ err = sym_gcry_md_setkey(f->hmac, key, sizeof(key));
if (gcry_err_code(err) != GPG_ERR_NO_ERROR)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
- "gcry_md_setkey() failed with error code: %s",
- gcry_strerror(err));
+ "sym_gcry_md_setkey() failed with error code: %s",
+ sym_gcry_strerror(err));
f->hmac_running = true;
@@ -167,7 +172,10 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
if (epoch == goal)
return 0;
- FSPRG_Evolve(f->fsprg_state);
+ r = FSPRG_Evolve(f->fsprg_state);
+ if (r < 0)
+ return r;
+
epoch = FSPRG_GetEpoch(f->fsprg_state);
if (epoch < goal) {
r = journal_file_append_tag(f);
@@ -180,6 +188,7 @@ int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
void *msk;
uint64_t epoch;
+ int r;
assert(f);
@@ -195,10 +204,8 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
if (goal == epoch)
return 0;
- if (goal == epoch + 1) {
- FSPRG_Evolve(f->fsprg_state);
- return 0;
- }
+ if (goal == epoch + 1)
+ return FSPRG_Evolve(f->fsprg_state);
} else {
f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
f->fsprg_state = malloc(f->fsprg_state_size);
@@ -209,10 +216,12 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
log_debug("Seeking FSPRG key to %"PRIu64".", goal);
msk = alloca_safe(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;
+ r = FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
+ if (r < 0)
+ return r;
+
+ return FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
}
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
@@ -260,25 +269,25 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin
} else if (type > OBJECT_UNUSED && o->object.type != type)
return -EBADMSG;
- gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
+ sym_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, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f));
+ sym_gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
+ sym_gcry_md_write(f->hmac, journal_file_data_payload_field(f, o), le64toh(o->object.size) - journal_file_data_payload_offset(f));
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(Object, field.payload));
+ sym_gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash));
+ sym_gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(Object, field.payload));
break;
case OBJECT_ENTRY:
/* All */
- gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum));
+ sym_gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(Object, entry.seqnum));
break;
case OBJECT_FIELD_HASH_TABLE:
@@ -289,8 +298,8 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin
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));
+ sym_gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
+ sym_gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch));
break;
default:
return -EINVAL;
@@ -318,10 +327,10 @@ int journal_file_hmac_put_header(JournalFile *f) {
* 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, tail_entry_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));
+ sym_gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
+ sym_gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
+ sym_gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
+ sym_gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
return 0;
}
@@ -406,13 +415,16 @@ int journal_file_fss_load(JournalFile *f) {
int journal_file_hmac_setup(JournalFile *f) {
gcry_error_t e;
+ int r;
if (!JOURNAL_HEADER_SEALED(f->header))
return 0;
- initialize_libgcrypt(true);
+ r = initialize_libgcrypt(true);
+ if (r < 0)
+ return r;
- e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+ e = sym_gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
if (e != 0)
return -EOPNOTSUPP;
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index 08cbf86..7e941ed 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -20,6 +20,7 @@
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
+#include "gcrypt-util.h"
#include "id128-util.h"
#include "journal-authenticate.h"
#include "journal-def.h"
@@ -47,10 +48,6 @@
#define DEFAULT_COMPRESS_THRESHOLD (512ULL)
#define MIN_COMPRESS_THRESHOLD (8ULL)
-#define U64_KB UINT64_C(1024)
-#define U64_MB (UINT64_C(1024) * U64_KB)
-#define U64_GB (UINT64_C(1024) * U64_MB)
-
/* This is the minimum journal file size */
#define JOURNAL_FILE_SIZE_MIN (512 * U64_KB) /* 512 KiB */
#define JOURNAL_COMPACT_SIZE_MAX ((uint64_t) UINT32_MAX) /* 4 GiB */
@@ -285,6 +282,8 @@ JournalFile* journal_file_close(JournalFile *f) {
assert(f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL);
+ sd_event_source_disable_unref(f->post_change_timer);
+
if (f->cache_fd)
mmap_cache_fd_free(f->cache_fd);
@@ -309,7 +308,7 @@ JournalFile* journal_file_close(JournalFile *f) {
free(f->fsprg_seed);
if (f->hmac)
- gcry_md_close(f->hmac);
+ sym_gcry_md_close(f->hmac);
#endif
return mfree(f);
@@ -2249,7 +2248,6 @@ static int journal_file_link_entry(
f->header->tail_entry_monotonic = o->entry.monotonic;
if (JOURNAL_HEADER_CONTAINS(f->header, tail_entry_offset))
f->header->tail_entry_offset = htole64(offset);
- f->newest_mtime = 0; /* we have a new tail entry now, explicitly invalidate newest boot id/timestamp info */
/* Link up the items */
for (uint64_t i = 0; i < n_items; i++) {
@@ -2762,7 +2760,7 @@ static int generic_array_get(
Object **ret_object, /* The found object. */
uint64_t *ret_offset) { /* The offset of the found object. */
- uint64_t a, t = 0, k;
+ uint64_t a, t = 0, k = 0; /* Explicit initialization of k to appease gcc */
ChainCacheItem *ci;
Object *o = NULL;
int r;
@@ -3052,7 +3050,7 @@ static int generic_array_bisect(
left = 0;
right = m - 1;
- if (direction == DIRECTION_UP) {
+ if (direction == DIRECTION_UP && left < right) {
/* If we're going upwards, the last entry of the previous array may pass the test,
* and the first entry of the current array may not pass. In that case, the last
* entry of the previous array must be returned. Hence, we need to test the first
@@ -3167,10 +3165,21 @@ previous:
if (direction == DIRECTION_DOWN)
return 0;
- /* Indicate to go to the previous array later. Note, do not move to the previous array here,
- * as that may invalidate the current array object in the mmap cache and
- * journal_file_entry_array_item() below may read invalid address. */
- i = UINT64_MAX;
+ /* Get the last entry of the previous array. */
+ r = bump_entry_array(f, NULL, a, first, DIRECTION_UP, &a);
+ if (r <= 0)
+ return r;
+
+ r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
+ if (r < 0)
+ return r;
+
+ p = journal_file_entry_array_n_items(f, array);
+ if (p == 0 || t < p)
+ return -EBADMSG;
+
+ t -= p;
+ i = p - 1;
found:
p = journal_file_entry_array_item(f, array, 0);
@@ -3180,27 +3189,6 @@ found:
/* Let's cache this item for the next invocation */
chain_cache_put(f->chain_cache, ci, first, a, p, t, i);
- if (i == UINT64_MAX) {
- uint64_t m;
-
- /* Get the last entry of the previous array. */
-
- r = bump_entry_array(f, NULL, a, first, DIRECTION_UP, &a);
- if (r <= 0)
- return r;
-
- r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
- if (r < 0)
- return r;
-
- m = journal_file_entry_array_n_items(f, array);
- if (m == 0 || t < m)
- return -EBADMSG;
-
- t -= m;
- i = m - 1;
- }
-
p = journal_file_entry_array_item(f, array, i);
if (p == 0)
return -EBADMSG;
@@ -3267,7 +3255,7 @@ static int generic_array_bisect_for_data(
} else {
/* If we are going upwards, then we need to return the last object that passes the test.
- * When there is no object that passes the test, we need to return the the last object that
+ * When there is no object that passes the test, we need to return the last object that
* test_object() returns TEST_LEFT for. */
if (r == TEST_RIGHT)
return 0; /* Not only the 'extra' object, but also all objects in the chained arrays
@@ -3554,7 +3542,8 @@ int journal_file_next_entry(
p,
test_object_offset,
direction,
- ret_object ? &o : NULL, &q, &i);
+ NULL, &q, &i); /* Here, do not read entry object, as the result object
+ * may not be the one we want, and it may be broken. */
if (r <= 0)
return r;
@@ -3564,12 +3553,11 @@ int journal_file_next_entry(
* the same offset, and the index needs to be shifted. Otherwise, use the found object as is,
* as it is the nearest entry object from the input offset 'p'. */
- if (p != q)
- goto found;
-
- r = bump_array_index(&i, direction, n);
- if (r <= 0)
- return r;
+ if (p == q) {
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
+ }
/* And jump to it */
r = generic_array_get(f, le64toh(f->header->entry_array_offset), i, direction, ret_object ? &o : NULL, &q);
@@ -3581,7 +3569,7 @@ int journal_file_next_entry(
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"%s: entry array not properly ordered at entry index %" PRIu64,
f->path, i);
-found:
+
if (ret_object)
*ret_object = o;
if (ret_offset)
@@ -3813,35 +3801,35 @@ void journal_file_dump(JournalFile *f) {
case OBJECT_ENTRY:
assert(s);
- printf("Type: %s seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n",
- s,
- le64toh(o->entry.seqnum),
- le64toh(o->entry.monotonic),
- le64toh(o->entry.realtime));
+ log_info("Type: %s seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n",
+ s,
+ le64toh(o->entry.seqnum),
+ le64toh(o->entry.monotonic),
+ le64toh(o->entry.realtime));
break;
case OBJECT_TAG:
assert(s);
- printf("Type: %s seqnum=%"PRIu64" epoch=%"PRIu64"\n",
- s,
- le64toh(o->tag.seqnum),
- le64toh(o->tag.epoch));
+ log_info("Type: %s seqnum=%"PRIu64" epoch=%"PRIu64"\n",
+ s,
+ le64toh(o->tag.seqnum),
+ le64toh(o->tag.epoch));
break;
default:
if (s)
- printf("Type: %s \n", s);
+ log_info("Type: %s \n", s);
else
- printf("Type: unknown (%i)", o->object.type);
+ log_info("Type: unknown (%i)", o->object.type);
break;
}
c = COMPRESSION_FROM_OBJECT(o);
if (c > COMPRESSION_NONE)
- printf("Flags: %s\n",
- compression_to_string(c));
+ log_info("Flags: %s\n",
+ compression_to_string(c));
if (p == le64toh(f->header->tail_object_offset))
p = 0;
@@ -4374,11 +4362,9 @@ int journal_file_archive(JournalFile *f, char **ret_previous_path) {
(void) fsync_directory_of_file(f->fd);
if (ret_previous_path)
- *ret_previous_path = f->path;
- else
- free(f->path);
+ *ret_previous_path = TAKE_PTR(f->path);
- f->path = TAKE_PTR(p);
+ free_and_replace(f->path, p);
/* Set as archive so offlining commits w/state=STATE_ARCHIVED. Previously we would set old_file->header->state
* to STATE_ARCHIVED directly here, but journal_file_set_offline() short-circuits when state != STATE_ONLINE,
diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h
index 81fafb9..8100388 100644
--- a/src/libsystemd/sd-journal/journal-file.h
+++ b/src/libsystemd/sd-journal/journal-file.h
@@ -129,7 +129,8 @@ typedef struct JournalFile {
uint64_t newest_monotonic_usec;
uint64_t newest_realtime_usec;
unsigned newest_boot_id_prioq_idx;
- usec_t newest_mtime;
+ uint64_t newest_entry_offset;
+ uint8_t newest_state;
} JournalFile;
typedef enum JournalFileFlags {
@@ -309,7 +310,6 @@ void journal_file_print_header(JournalFile *f);
int journal_file_archive(JournalFile *f, char **ret_previous_path);
int journal_file_parse_uid_from_filename(const char *path, uid_t *uid);
-JournalFile* journal_initiate_close(JournalFile *f, Set *deferred_closes);
int journal_file_dispose(int dir_fd, const char *fname);
diff --git a/src/libsystemd/sd-journal/journal-internal.h b/src/libsystemd/sd-journal/journal-internal.h
index 259aac8..b95080c 100644
--- a/src/libsystemd/sd-journal/journal-internal.h
+++ b/src/libsystemd/sd-journal/journal-internal.h
@@ -12,7 +12,7 @@
#include "journal-def.h"
#include "journal-file.h"
#include "list.h"
-#include "set.h"
+#include "prioq.h"
#define JOURNAL_FILES_MAX 7168u
@@ -62,12 +62,18 @@ struct Location {
};
struct Directory {
+ sd_journal *journal;
char *path;
int wd;
bool is_root;
unsigned last_seen_generation;
};
+typedef struct NewestByBootId {
+ sd_id128_t boot_id;
+ Prioq *prioq; /* JournalFile objects ordered by monotonic timestamp of last update. */
+} NewestByBootId;
+
struct sd_journal {
int toplevel_fd;
@@ -78,7 +84,10 @@ struct sd_journal {
OrderedHashmap *files;
IteratedCache *files_cache;
MMapCache *mmap;
- Hashmap *newest_by_boot_id; /* key: boot_id, value: prioq, ordered by monotonic timestamp of last update */
+
+ /* a bisectable array of NewestByBootId, ordered by boot id. */
+ NewestByBootId *newest_by_boot_id;
+ size_t n_newest_by_boot_id;
Location current_location;
@@ -86,6 +95,7 @@ struct sd_journal {
uint64_t current_field;
Match *level0, *level1, *level2;
+ Set *exclude_syslog_identifiers;
uint64_t origin_id;
@@ -128,6 +138,10 @@ struct sd_journal {
char *journal_make_match_string(sd_journal *j);
void journal_print_header(sd_journal *j);
+int journal_get_directories(sd_journal *j, char ***ret);
+
+int journal_add_match_pair(sd_journal *j, const char *field, const char *value);
+int journal_add_matchf(sd_journal *j, const char *format, ...) _printf_(2, 3);
#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \
for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; )
diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c
index be23b2f..7d02b57 100644
--- a/src/libsystemd/sd-journal/journal-send.c
+++ b/src/libsystemd/sd-journal/journal-send.c
@@ -121,7 +121,7 @@ _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
assert_return(priority <= 7, -EINVAL);
assert_return(format, -EINVAL);
- xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
+ xsprintf(p, "PRIORITY=%i", LOG_PRI(priority));
va_copy(aq, ap);
len = vsnprintf(buffer + 8, LINE_MAX, format, aq);
@@ -398,20 +398,28 @@ _public_ int sd_journal_perror(const char *message) {
return fill_iovec_perror_and_send(message, 0, iovec);
}
-_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
+_public_ int sd_journal_stream_fd_with_namespace(
+ const char *name_space,
+ const char *identifier,
+ int priority,
+ int level_prefix) {
+
_cleanup_close_ int fd = -EBADF;
- char *header;
- size_t l;
+ const char *path;
int r;
assert_return(priority >= 0, -EINVAL);
assert_return(priority <= 7, -EINVAL);
+ path = journal_stream_path(name_space);
+ if (!path)
+ return -EINVAL;
+
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (fd < 0)
return -errno;
- r = connect_unix_path(fd, AT_FDCWD, "/run/systemd/journal/stdout");
+ r = connect_unix_path(fd, AT_FDCWD, path);
if (r < 0)
return r;
@@ -422,6 +430,9 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
identifier = strempty(identifier);
+ char *header;
+ size_t l;
+
l = strlen(identifier);
header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
@@ -446,6 +457,10 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve
return TAKE_FD(fd);
}
+_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
+ return sd_journal_stream_fd_with_namespace(NULL, identifier, priority, level_prefix);
+}
+
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
int r;
va_list ap;
@@ -470,7 +485,7 @@ _public_ int sd_journal_printv_with_location(int priority, const char *file, con
assert_return(priority <= 7, -EINVAL);
assert_return(format, -EINVAL);
- xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
+ xsprintf(p, "PRIORITY=%i", LOG_PRI(priority));
va_copy(aq, ap);
len = vsnprintf(buffer + 8, LINE_MAX, format, aq);
diff --git a/src/libsystemd/sd-journal/journal-send.h b/src/libsystemd/sd-journal/journal-send.h
index 24315e2..6fe6325 100644
--- a/src/libsystemd/sd-journal/journal-send.h
+++ b/src/libsystemd/sd-journal/journal-send.h
@@ -2,6 +2,23 @@
#pragma once
#include <stdbool.h>
+#include <stddef.h>
+
+#include "syslog-util.h"
int journal_fd_nonblock(bool nonblock);
void close_journal_fd(void);
+
+/* We declare sd_journal_stream_fd() as async-signal-safe. So instead of strjoin(), which calls malloc()
+ * internally, use a macro + alloca(). */
+#define journal_stream_path(log_namespace) \
+ ({ \
+ const char *_ns = (log_namespace), *_ret; \
+ if (!_ns) \
+ _ret = "/run/systemd/journal/stdout"; \
+ else if (log_namespace_name_valid(_ns)) \
+ _ret = strjoina("/run/systemd/journal.", _ns, "/stdout"); \
+ else \
+ _ret = NULL; \
+ _ret; \
+ })
diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c
index b5ce55a..e852591 100644
--- a/src/libsystemd/sd-journal/journal-verify.c
+++ b/src/libsystemd/sd-journal/journal-verify.c
@@ -10,6 +10,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "gcrypt-util.h"
#include "journal-authenticate.h"
#include "journal-def.h"
#include "journal-file.h"
@@ -1224,7 +1225,7 @@ int journal_file_verify(
if (r < 0)
goto fail;
- if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
+ if (memcmp(o->tag.tag, sym_gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
error(p, "Tag failed verification");
r = -EBADMSG;
goto fail;
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index ca1ef0c..0aa3726 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -38,12 +38,13 @@
#include "prioq.h"
#include "process-util.h"
#include "replace-var.h"
+#include "sort-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "syslog-util.h"
-#include "uid-alloc-range.h"
+#include "uid-classification.h"
#define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC)
@@ -232,7 +233,11 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
assert_return(!journal_origin_changed(j), -ECHILD);
assert_return(data, -EINVAL);
- if (size == 0)
+ /* If the size is unspecified, assume it's a string. Note: 0 is the public value we document for
+ * this, for historical reasons. Internally, we pretty widely started using SIZE_MAX for this in
+ * similar cases however, hence accept that too. And internally we actually prefer it, to make things
+ * less surprising. */
+ if (IN_SET(size, 0, SIZE_MAX))
size = strlen(data);
if (!match_is_valid(data, size))
@@ -324,6 +329,37 @@ fail:
return -ENOMEM;
}
+int journal_add_match_pair(sd_journal *j, const char *field, const char *value) {
+ _cleanup_free_ char *s = NULL;
+
+ assert(j);
+ assert(field);
+ assert(value);
+
+ s = strjoin(field, "=", value);
+ if (!s)
+ return -ENOMEM;
+
+ return sd_journal_add_match(j, s, SIZE_MAX);
+}
+
+int journal_add_matchf(sd_journal *j, const char *format, ...) {
+ _cleanup_free_ char *s = NULL;
+ va_list ap;
+ int r;
+
+ assert(j);
+ assert(format);
+
+ va_start(ap, format);
+ r = vasprintf(&s, format, ap);
+ va_end(ap);
+ if (r < 0)
+ return -ENOMEM;
+
+ return sd_journal_add_match(j, s, SIZE_MAX);
+}
+
_public_ int sd_journal_add_conjunction(sd_journal *j) {
assert_return(j, -EINVAL);
assert_return(!journal_origin_changed(j), -ECHILD);
@@ -413,6 +449,99 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
detach_location(j);
}
+static int newest_by_boot_id_compare(const NewestByBootId *a, const NewestByBootId *b) {
+ return id128_compare_func(&a->boot_id, &b->boot_id);
+}
+
+static void journal_file_unlink_newest_by_boot_id(sd_journal *j, JournalFile *f) {
+ NewestByBootId *found;
+
+ assert(j);
+ assert(f);
+
+ if (f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL) /* not linked currently, hence this is a NOP */
+ return;
+
+ found = typesafe_bsearch(&(NewestByBootId) { .boot_id = f->newest_boot_id },
+ j->newest_by_boot_id, j->n_newest_by_boot_id, newest_by_boot_id_compare);
+ assert(found);
+
+ assert_se(prioq_remove(found->prioq, f, &f->newest_boot_id_prioq_idx) > 0);
+ f->newest_boot_id_prioq_idx = PRIOQ_IDX_NULL;
+
+ /* The prioq may be empty, but that should not cause any issue. Let's keep it. */
+}
+
+static void journal_clear_newest_by_boot_id(sd_journal *j) {
+ FOREACH_ARRAY(i, j->newest_by_boot_id, j->n_newest_by_boot_id) {
+ JournalFile *f;
+
+ while ((f = prioq_peek(i->prioq)))
+ journal_file_unlink_newest_by_boot_id(j, f);
+
+ prioq_free(i->prioq);
+ }
+
+ j->newest_by_boot_id = mfree(j->newest_by_boot_id);
+ j->n_newest_by_boot_id = 0;
+}
+
+static int journal_file_newest_monotonic_compare(const void *a, const void *b) {
+ const JournalFile *x = a, *y = b;
+
+ return -CMP(x->newest_monotonic_usec, y->newest_monotonic_usec); /* Invert order, we want newest first! */
+}
+
+static int journal_file_reshuffle_newest_by_boot_id(sd_journal *j, JournalFile *f) {
+ NewestByBootId *found;
+ int r;
+
+ assert(j);
+ assert(f);
+
+ found = typesafe_bsearch(&(NewestByBootId) { .boot_id = f->newest_boot_id },
+ j->newest_by_boot_id, j->n_newest_by_boot_id, newest_by_boot_id_compare);
+ if (found) {
+ /* There's already a priority queue for this boot ID */
+
+ if (f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL) {
+ r = prioq_put(found->prioq, f, &f->newest_boot_id_prioq_idx); /* Insert if we aren't in there yet */
+ if (r < 0)
+ return r;
+ } else
+ prioq_reshuffle(found->prioq, f, &f->newest_boot_id_prioq_idx); /* Reshuffle otherwise */
+
+ } else {
+ _cleanup_(prioq_freep) Prioq *q = NULL;
+
+ /* No priority queue yet, then allocate one */
+
+ assert(f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL); /* we can't be a member either */
+
+ q = prioq_new(journal_file_newest_monotonic_compare);
+ if (!q)
+ return -ENOMEM;
+
+ r = prioq_put(q, f, &f->newest_boot_id_prioq_idx);
+ if (r < 0)
+ return r;
+
+ if (!GREEDY_REALLOC(j->newest_by_boot_id, j->n_newest_by_boot_id + 1)) {
+ f->newest_boot_id_prioq_idx = PRIOQ_IDX_NULL;
+ return -ENOMEM;
+ }
+
+ j->newest_by_boot_id[j->n_newest_by_boot_id++] = (NewestByBootId) {
+ .boot_id = f->newest_boot_id,
+ .prioq = TAKE_PTR(q),
+ };
+
+ typesafe_qsort(j->newest_by_boot_id, j->n_newest_by_boot_id, newest_by_boot_id_compare);
+ }
+
+ return 0;
+}
+
static int journal_file_find_newest_for_boot_id(
sd_journal *j,
sd_id128_t id,
@@ -427,16 +556,17 @@ static int journal_file_find_newest_for_boot_id(
/* Before we use it, let's refresh the timestamp from the header, and reshuffle our prioq
* accordingly. We do this only a bunch of times, to not be caught in some update loop. */
for (unsigned n_tries = 0;; n_tries++) {
+ NewestByBootId *found;
JournalFile *f;
- Prioq *q;
- q = hashmap_get(j->newest_by_boot_id, &id);
- if (!q)
+ found = typesafe_bsearch(&(NewestByBootId) { .boot_id = id },
+ j->newest_by_boot_id, j->n_newest_by_boot_id, newest_by_boot_id_compare);
+
+ f = found ? prioq_peek(found->prioq) : NULL;
+ if (!f)
return log_debug_errno(SYNTHETIC_ERRNO(ENODATA),
"Requested delta for boot ID %s, but we have no information about that boot ID.", SD_ID128_TO_STRING(id));
- assert_se(f = prioq_peek(q)); /* we delete hashmap entries once the prioq is empty, so this must hold */
-
if (f == prev || n_tries >= 5) {
/* This was already the best answer in the previous run, or we tried too often, use it */
*ret = f;
@@ -449,6 +579,11 @@ static int journal_file_find_newest_for_boot_id(
r = journal_file_read_tail_timestamp(j, f);
if (r < 0)
return log_debug_errno(r, "Failed to read tail timestamp while trying to find newest journal file for boot ID %s.", SD_ID128_TO_STRING(id));
+ if (r == 0) {
+ /* No new entry found. */
+ *ret = f;
+ return 0;
+ }
/* Refreshing the timestamp we read might have reshuffled the prioq, hence let's check the
* prioq again and only use the information once we reached an equilibrium or hit a limit */
@@ -932,8 +1067,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
if (r < 0)
return r;
- for (unsigned i = 0; i < n_files; i++) {
- JournalFile *f = (JournalFile *)files[i];
+ FOREACH_ARRAY(_f, files, n_files) {
+ JournalFile *f = (JournalFile*) *_f;
bool found;
r = next_beyond_location(j, f, direction);
@@ -1373,17 +1508,6 @@ static void track_file_disposition(sd_journal *j, JournalFile *f) {
j->has_persistent_files = true;
}
-static const char *skip_slash(const char *p) {
-
- if (!p)
- return NULL;
-
- while (*p == '/')
- p++;
-
- return p;
-}
-
static int add_any_file(
sd_journal *j,
int fd,
@@ -1403,7 +1527,7 @@ static int add_any_file(
/* If there's a top-level fd defined make the path relative, explicitly, since otherwise
* openat() ignores the first argument. */
- fd = our_fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+ fd = our_fd = openat(j->toplevel_fd, skip_leading_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK);
else
fd = our_fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0) {
@@ -1494,6 +1618,41 @@ error:
return r;
}
+int journal_get_directories(sd_journal *j, char ***ret) {
+ _cleanup_strv_free_ char **paths = NULL;
+ JournalFile *f;
+ const char *p;
+ size_t n = SIZE_MAX;
+ int r;
+
+ assert(j);
+ assert(ret);
+
+ /* This returns parent directories of opened journal files. */
+
+ ORDERED_HASHMAP_FOREACH_KEY(f, p, j->files) {
+ _cleanup_free_ char *d = NULL;
+
+ /* Ignore paths generated from fd. */
+ if (path_startswith(p, "/proc/"))
+ continue;
+
+ r = path_extract_directory(p, &d);
+ if (r < 0)
+ return r;
+
+ if (path_strv_contains(paths, d))
+ continue;
+
+ r = strv_extend_with_size(&paths, &n, d);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(paths);
+ return 0;
+}
+
static int add_file_by_name(
sd_journal *j,
const char *prefix,
@@ -1676,7 +1835,7 @@ static int directory_open(sd_journal *j, const char *path, DIR **ret) {
else
/* Open the specified directory relative to the toplevel fd. Enforce that the path specified is
* relative, by dropping the initial slash */
- d = xopendirat(j->toplevel_fd, skip_slash(path), 0);
+ d = xopendirat(j->toplevel_fd, skip_leading_slash(path), 0);
if (!d)
return -errno;
@@ -1684,6 +1843,100 @@ static int directory_open(sd_journal *j, const char *path, DIR **ret) {
return 0;
}
+static Directory* directory_free(Directory *d) {
+ if (!d)
+ return NULL;
+
+ if (d->journal) {
+ if (d->wd > 0 &&
+ hashmap_remove_value(d->journal->directories_by_wd, INT_TO_PTR(d->wd), d) &&
+ d->journal->inotify_fd >= 0)
+ (void) inotify_rm_watch(d->journal->inotify_fd, d->wd);
+
+ if (d->path)
+ hashmap_remove_value(d->journal->directories_by_path, d->path, d);
+ }
+
+ if (d->path) {
+ if (d->is_root)
+ log_debug("Root directory %s removed.", d->path);
+ else
+ log_debug("Directory %s removed.", d->path);
+
+ free(d->path);
+ }
+
+ return mfree(d);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Directory*, directory_free);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ directories_by_path_hash_ops,
+ char,
+ path_hash_func,
+ path_compare,
+ Directory,
+ directory_free);
+
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ directories_by_wd_hash_ops,
+ void,
+ trivial_hash_func,
+ trivial_compare_func,
+ Directory,
+ directory_free);
+
+static int add_directory_impl(sd_journal *j, const char *path, bool is_root, Directory **ret) {
+ _cleanup_(directory_freep) Directory *m = NULL;
+ Directory *existing;
+ int r;
+
+ assert(j);
+ assert(path);
+ assert(ret);
+
+ existing = hashmap_get(j->directories_by_path, path);
+ if (existing) {
+ if (existing->is_root != is_root) {
+ /* Don't 'downgrade' from root directory */
+ *ret = NULL;
+ return 0;
+ }
+
+ *ret = existing;
+ return 1;
+ }
+
+ m = new(Directory, 1);
+ if (!m)
+ return -ENOMEM;
+
+ *m = (Directory) {
+ .journal = j,
+ .is_root = is_root,
+ .path = strdup(path),
+ .wd = -1,
+ };
+
+ if (!m->path)
+ return -ENOMEM;
+
+ r = hashmap_ensure_put(&j->directories_by_path, &directories_by_path_hash_ops, m->path, m);
+ if (r < 0)
+ return r;
+
+ j->current_invalidate_counter++;
+
+ if (is_root)
+ log_debug("Root directory %s added.", m->path);
+ else
+ log_debug("Directory %s added.", m->path);
+
+ *ret = TAKE_PTR(m);
+ return 1;
+}
+
static int add_directory(sd_journal *j, const char *prefix, const char *dirname);
static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) {
@@ -1724,12 +1977,14 @@ static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask)
return;
}
- r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m);
- if (r == -EEXIST)
- log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
+ r = hashmap_ensure_put(&j->directories_by_wd, &directories_by_wd_hash_ops, INT_TO_PTR(m->wd), m);
if (r < 0) {
- log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
- (void) inotify_rm_watch(j->inotify_fd, m->wd);
+ if (r == -EEXIST)
+ log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path);
+ else {
+ log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path);
+ (void) inotify_rm_watch(j->inotify_fd, m->wd);
+ }
m->wd = -1;
}
}
@@ -1775,32 +2030,11 @@ static int add_directory(
goto fail;
}
- m = hashmap_get(j->directories_by_path, path);
- if (!m) {
- m = new(Directory, 1);
- if (!m) {
- r = -ENOMEM;
- goto fail;
- }
-
- *m = (Directory) {
- .is_root = false,
- .path = path,
- };
-
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- free(m);
- r = -ENOMEM;
- goto fail;
- }
-
- path = NULL; /* avoid freeing in cleanup */
- j->current_invalidate_counter++;
-
- log_debug("Directory %s added.", m->path);
-
- } else if (m->is_root)
- return 0; /* Don't 'downgrade' from root directory */
+ r = add_directory_impl(j, path, /* is_root = */ false, &m);
+ if (r < 0)
+ goto fail;
+ if (r == 0)
+ return 0;
m->last_seen_generation = j->generation;
@@ -1878,35 +2112,10 @@ static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) {
rewinddir(d);
}
- m = hashmap_get(j->directories_by_path, p);
- if (!m) {
- m = new0(Directory, 1);
- if (!m) {
- r = -ENOMEM;
- goto fail;
- }
-
- m->is_root = true;
-
- m->path = strdup(p);
- if (!m->path) {
- free(m);
- r = -ENOMEM;
- goto fail;
- }
-
- if (hashmap_put(j->directories_by_path, m->path, m) < 0) {
- free(m->path);
- free(m);
- r = -ENOMEM;
- goto fail;
- }
-
- j->current_invalidate_counter++;
-
- log_debug("Root directory %s added.", m->path);
-
- } else if (!m->is_root)
+ r = add_directory_impl(j, p, /* is_root = */ true, &m);
+ if (r < 0)
+ goto fail;
+ if (r == 0)
return 0;
directory_watch(j, m, dirfd(d),
@@ -1928,27 +2137,6 @@ fail:
return r;
}
-static void 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)
- (void) 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 removed.", d->path);
- else
- log_debug("Directory %s removed.", d->path);
-
- free(d->path);
- free(d);
-}
-
static int add_search_paths(sd_journal *j) {
static const char search_paths[] =
@@ -2003,7 +2191,7 @@ static int allocate_inotify(sd_journal *j) {
return -errno;
}
- return hashmap_ensure_allocated(&j->directories_by_wd, NULL);
+ return 0;
}
static sd_journal *journal_new(int flags, const char *path, const char *namespace) {
@@ -2045,9 +2233,8 @@ static sd_journal *journal_new(int flags, const char *path, const char *namespac
return NULL;
j->files_cache = ordered_hashmap_iterated_cache_new(j->files);
- j->directories_by_path = hashmap_new(&path_hash_ops);
j->mmap = mmap_cache_new();
- if (!j->files_cache || !j->directories_by_path || !j->mmap)
+ if (!j->files_cache || !j->mmap)
return NULL;
return TAKE_PTR(j);
@@ -2059,7 +2246,8 @@ static sd_journal *journal_new(int flags, const char *path, const char *namespac
SD_JOURNAL_SYSTEM | \
SD_JOURNAL_CURRENT_USER | \
SD_JOURNAL_ALL_NAMESPACES | \
- SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE)
+ SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE | \
+ SD_JOURNAL_ASSUME_IMMUTABLE)
_public_ int sd_journal_open_namespace(sd_journal **ret, const char *namespace, int flags) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2085,7 +2273,9 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
}
#define OPEN_CONTAINER_ALLOWED_FLAGS \
- (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
+ (SD_JOURNAL_LOCAL_ONLY | \
+ SD_JOURNAL_SYSTEM | \
+ SD_JOURNAL_ASSUME_IMMUTABLE)
_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
_cleanup_free_ char *root = NULL, *class = NULL;
@@ -2129,7 +2319,9 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
#define OPEN_DIRECTORY_ALLOWED_FLAGS \
(SD_JOURNAL_OS_ROOT | \
- SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+ SD_JOURNAL_SYSTEM | \
+ SD_JOURNAL_CURRENT_USER | \
+ SD_JOURNAL_ASSUME_IMMUTABLE)
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2154,12 +2346,15 @@ _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int f
return 0;
}
+#define OPEN_FILES_ALLOWED_FLAGS \
+ (SD_JOURNAL_ASSUME_IMMUTABLE)
+
_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert_return(ret, -EINVAL);
- assert_return(flags == 0, -EINVAL);
+ assert_return((flags & ~OPEN_FILES_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, NULL, NULL);
if (!j)
@@ -2181,7 +2376,8 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
(SD_JOURNAL_OS_ROOT | \
SD_JOURNAL_SYSTEM | \
SD_JOURNAL_CURRENT_USER | \
- SD_JOURNAL_TAKE_DIRECTORY_FD)
+ SD_JOURNAL_TAKE_DIRECTORY_FD | \
+ SD_JOURNAL_ASSUME_IMMUTABLE)
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2219,6 +2415,9 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
return 0;
}
+#define OPEN_FILES_FD_ALLOWED_FLAGS \
+ (SD_JOURNAL_ASSUME_IMMUTABLE)
+
_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
JournalFile *f;
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
@@ -2226,7 +2425,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd
assert_return(ret, -EINVAL);
assert_return(n_fds > 0, -EBADF);
- assert_return(flags == 0, -EINVAL);
+ assert_return((flags & ~OPEN_FILES_FD_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, NULL, NULL);
if (!j)
@@ -2270,27 +2469,16 @@ fail:
}
_public_ void sd_journal_close(sd_journal *j) {
- Directory *d;
- Prioq *p;
-
if (!j || journal_origin_changed(j))
return;
- while ((p = hashmap_first(j->newest_by_boot_id)))
- journal_file_unlink_newest_by_boot_id(j, prioq_peek(p));
- hashmap_free(j->newest_by_boot_id);
+ journal_clear_newest_by_boot_id(j);
sd_journal_flush_matches(j);
ordered_hashmap_free_with_destructor(j->files, journal_file_close);
iterated_cache_free(j->files_cache);
- while ((d = hashmap_first(j->directories_by_path)))
- remove_directory(j, d);
-
- while ((d = hashmap_first(j->directories_by_wd)))
- remove_directory(j, d);
-
hashmap_free(j->directories_by_path);
hashmap_free(j->directories_by_wd);
@@ -2306,6 +2494,8 @@ _public_ void sd_journal_close(sd_journal *j) {
hashmap_free_free(j->errors);
+ set_free(j->exclude_syslog_identifiers);
+
free(j->path);
free(j->prefix);
free(j->namespace);
@@ -2314,84 +2504,6 @@ _public_ void sd_journal_close(sd_journal *j) {
free(j);
}
-static void journal_file_unlink_newest_by_boot_id(sd_journal *j, JournalFile *f) {
- JournalFile *nf;
- Prioq *p;
-
- assert(j);
- assert(f);
-
- if (f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL) /* not linked currently, hence this is a NOP */
- return;
-
- assert_se(p = hashmap_get(j->newest_by_boot_id, &f->newest_boot_id));
- assert_se(prioq_remove(p, f, &f->newest_boot_id_prioq_idx) > 0);
-
- nf = prioq_peek(p);
- if (nf)
- /* There's still a member in the prioq? Then make sure the hashmap key now points to its
- * .newest_boot_id field (and not ours!). Not we only replace the memory of the key here, the
- * value of the key (and the data associated with it) remain the same. */
- assert_se(hashmap_replace(j->newest_by_boot_id, &nf->newest_boot_id, p) >= 0);
- else {
- assert_se(hashmap_remove(j->newest_by_boot_id, &f->newest_boot_id) == p);
- prioq_free(p);
- }
-
- f->newest_boot_id_prioq_idx = PRIOQ_IDX_NULL;
-}
-
-static int journal_file_newest_monotonic_compare(const void *a, const void *b) {
- const JournalFile *x = a, *y = b;
-
- return -CMP(x->newest_monotonic_usec, y->newest_monotonic_usec); /* Invert order, we want newest first! */
-}
-
-static int journal_file_reshuffle_newest_by_boot_id(sd_journal *j, JournalFile *f) {
- Prioq *p;
- int r;
-
- assert(j);
- assert(f);
-
- p = hashmap_get(j->newest_by_boot_id, &f->newest_boot_id);
- if (p) {
- /* There's already a priority queue for this boot ID */
-
- if (f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL) {
- r = prioq_put(p, f, &f->newest_boot_id_prioq_idx); /* Insert if we aren't in there yet */
- if (r < 0)
- return r;
- } else
- prioq_reshuffle(p, f, &f->newest_boot_id_prioq_idx); /* Reshuffle otherwise */
-
- } else {
- _cleanup_(prioq_freep) Prioq *q = NULL;
-
- /* No priority queue yet, then allocate one */
-
- assert(f->newest_boot_id_prioq_idx == PRIOQ_IDX_NULL); /* we can't be a member either */
-
- q = prioq_new(journal_file_newest_monotonic_compare);
- if (!q)
- return -ENOMEM;
-
- r = prioq_put(q, f, &f->newest_boot_id_prioq_idx);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_put(&j->newest_by_boot_id, &id128_hash_ops, &f->newest_boot_id, q);
- if (r < 0) {
- f->newest_boot_id_prioq_idx = PRIOQ_IDX_NULL;
- return r;
- }
-
- TAKE_PTR(q);
- }
-
- return 0;
-}
-
static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
uint64_t offset, mo, rt;
sd_id128_t id;
@@ -2405,11 +2517,13 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
/* Tries to read the timestamp of the most recently written entry. */
- r = journal_file_fstat(f);
- if (r < 0)
- return r;
- if (f->newest_mtime == timespec_load(&f->last_stat.st_mtim))
- return 0; /* mtime didn't change since last time, don't bother */
+ if (FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE) && f->newest_entry_offset != 0)
+ return 0; /* We have already read the file, and we assume that the file is immutable. */
+
+ if (f->header->state == f->newest_state &&
+ f->header->state == STATE_ARCHIVED &&
+ f->newest_entry_offset != 0)
+ return 0; /* We have already read archived file. */
if (JOURNAL_HEADER_CONTAINS(f->header, tail_entry_offset)) {
offset = le64toh(READ_NOW(f->header->tail_entry_offset));
@@ -2420,6 +2534,8 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
}
if (offset == 0)
return -ENODATA; /* not a single object/entry, hence no tail timestamp */
+ if (offset == f->newest_entry_offset)
+ return 0; /* No new entry is added after we read last time. */
/* Move to the last object in the journal file, in the hope it is an entry (which it usually will
* be). If we lack the "tail_entry_offset" field in the header, we specify the type as OBJECT_UNUSED
@@ -2429,6 +2545,7 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
if (r < 0) {
log_debug_errno(r, "Failed to move to last object in journal file, ignoring: %m");
o = NULL;
+ offset = 0;
}
if (o && o->object.type == OBJECT_ENTRY) {
/* Yay, last object is an entry, let's use the data. */
@@ -2446,10 +2563,11 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
mo = le64toh(f->header->tail_entry_monotonic);
rt = le64toh(f->header->tail_entry_realtime);
id = f->header->tail_entry_boot_id;
+ offset = UINT64_MAX;
} else {
/* Otherwise let's find the last entry manually (this possibly means traversing the
* chain of entry arrays, till the end */
- r = journal_file_next_entry(f, 0, DIRECTION_UP, &o, NULL);
+ r = journal_file_next_entry(f, 0, DIRECTION_UP, &o, offset == 0 ? &offset : NULL);
if (r < 0)
return r;
if (r == 0)
@@ -2464,6 +2582,17 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
if (mo > rt) /* monotonic clock is further ahead than realtime? that's weird, refuse to use the data */
return -ENODATA;
+ if (offset == f->newest_entry_offset) {
+ /* Cached data and the current one should be equivalent. */
+ if (!sd_id128_equal(f->newest_machine_id, f->header->machine_id) ||
+ !sd_id128_equal(f->newest_boot_id, id) ||
+ f->newest_monotonic_usec != mo ||
+ f->newest_realtime_usec != rt)
+ return -EBADMSG;
+
+ return 0; /* No new entry is added after we read last time. */
+ }
+
if (!sd_id128_equal(f->newest_boot_id, id))
journal_file_unlink_newest_by_boot_id(j, f);
@@ -2471,13 +2600,14 @@ static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f) {
f->newest_monotonic_usec = mo;
f->newest_realtime_usec = rt;
f->newest_machine_id = f->header->machine_id;
- f->newest_mtime = timespec_load(&f->last_stat.st_mtim);
+ f->newest_entry_offset = offset;
+ f->newest_state = f->header->state;
r = journal_file_reshuffle_newest_by_boot_id(j, f);
if (r < 0)
return r;
- return 0;
+ return 1; /* Updated. */
}
_public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
@@ -2526,9 +2656,7 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12
if (r < 0)
return r;
- if (ret_boot_id)
- *ret_boot_id = o->entry.boot_id;
- else {
+ if (!ret_boot_id) {
sd_id128_t id;
r = sd_id128_get_boot(&id);
@@ -2545,6 +2673,8 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12
if (ret)
*ret = t;
+ if (ret_boot_id)
+ *ret_boot_id = o->entry.boot_id;
return 0;
}
@@ -2748,6 +2878,7 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
assert_return(j, -EINVAL);
assert_return(!journal_origin_changed(j), -ECHILD);
+ assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
if (j->no_inotify)
return -EMEDIUMTYPE;
@@ -2774,6 +2905,7 @@ _public_ int sd_journal_get_events(sd_journal *j) {
assert_return(j, -EINVAL);
assert_return(!journal_origin_changed(j), -ECHILD);
+ assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
fd = sd_journal_get_fd(j);
if (fd < 0)
@@ -2787,6 +2919,7 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
assert_return(j, -EINVAL);
assert_return(!journal_origin_changed(j), -ECHILD);
+ assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
assert_return(timeout_usec, -EINVAL);
fd = sd_journal_get_fd(j);
@@ -2839,7 +2972,7 @@ static void process_q_overflow(sd_journal *j) {
continue;
log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path);
- remove_directory(j, m);
+ directory_free(m);
}
log_debug("Reiteration complete.");
@@ -2875,7 +3008,7 @@ static void process_inotify_event(sd_journal *j, const struct inotify_event *e)
/* Event for a subdirectory */
if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT))
- remove_directory(j, d);
+ directory_free(d);
} else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && id128_is_valid(e->name)) {
@@ -2914,6 +3047,8 @@ _public_ int sd_journal_process(sd_journal *j) {
if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */
return 0;
+ assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
+
j->last_process_usec = now(CLOCK_MONOTONIC);
j->last_invalidate_counter = j->current_invalidate_counter;
@@ -2942,6 +3077,7 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
assert_return(j, -EINVAL);
assert_return(!journal_origin_changed(j), -ECHILD);
+ assert_return(!FLAGS_SET(j->flags, SD_JOURNAL_ASSUME_IMMUTABLE), -EUNATCH);
if (j->inotify_fd < 0) {
JournalFile *f;
diff --git a/src/libsystemd/sd-journal/test-journal-append.c b/src/libsystemd/sd-journal/test-journal-append.c
index 24b98c8..b7e7c78 100644
--- a/src/libsystemd/sd-journal/test-journal-append.c
+++ b/src/libsystemd/sd-journal/test-journal-append.c
@@ -62,7 +62,7 @@ static int journal_corrupt_and_append(uint64_t start_offset, uint64_t step) {
log_debug("Opening journal %s/system.journal", tempdir);
r = journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
"system.journal",
O_RDWR|O_CREAT,
JOURNAL_COMPRESS,
@@ -114,7 +114,7 @@ static int journal_corrupt_and_append(uint64_t start_offset, uint64_t step) {
* the corrupted journal */
mj = journal_file_offline_close(mj);
r = journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
"system.journal",
O_RDWR|O_CREAT,
JOURNAL_COMPRESS,
diff --git a/src/libsystemd/sd-journal/test-journal-enum.c b/src/libsystemd/sd-journal/test-journal-enum.c
index 03fe8e2..d101fe7 100644
--- a/src/libsystemd/sd-journal/test-journal-enum.c
+++ b/src/libsystemd/sd-journal/test-journal-enum.c
@@ -15,10 +15,10 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
- assert_se(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY) >= 0);
+ assert_se(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_ASSUME_IMMUTABLE) >= 0);
- assert_se(sd_journal_add_match(j, "_TRANSPORT=syslog", 0) >= 0);
- assert_se(sd_journal_add_match(j, "_UID=0", 0) >= 0);
+ assert_se(sd_journal_add_match(j, "_TRANSPORT=syslog", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "_UID=0", SIZE_MAX) >= 0);
SD_JOURNAL_FOREACH_BACKWARDS(j) {
const void *d;
diff --git a/src/libsystemd/sd-journal/test-journal-flush.c b/src/libsystemd/sd-journal/test-journal-flush.c
index 3f07835..b06645a 100644
--- a/src/libsystemd/sd-journal/test-journal-flush.c
+++ b/src/libsystemd/sd-journal/test-journal-flush.c
@@ -7,6 +7,8 @@
#include "alloc-util.h"
#include "chattr-util.h"
+#include "dirent-util.h"
+#include "fd-util.h"
#include "journal-file-util.h"
#include "journal-internal.h"
#include "logs-show.h"
@@ -17,6 +19,83 @@
#include "tests.h"
#include "tmpfile-util.h"
+static int open_archive_file(sd_journal **ret) {
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_close_ int newest_fd = -EBADF;
+ unsigned long long newest_realtime = 0;
+ bool newest_is_system = false;
+ sd_id128_t machine_id;
+ const char *p;
+ int r;
+
+ r = sd_id128_get_machine(&machine_id);
+ if (r < 0)
+ return r;
+
+ p = strjoina("/var/log/journal/", SD_ID128_TO_STRING(machine_id), "/");
+
+ d = opendir(p);
+ if (!d)
+ return -errno;
+
+ FOREACH_DIRENT_ALL(de, d, return -errno) {
+ unsigned long long realtime;
+ bool is_system;
+ size_t q;
+ int fd;
+
+ if (!dirent_is_file_with_suffix(de, ".journal"))
+ continue;
+
+ is_system = startswith(de->d_name, "system@");
+ if (newest_is_system && !is_system)
+ 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 (sscanf(de->d_name + q-8-16, "%16llx.journal", &realtime) != 1)
+ continue;
+
+ if (newest_realtime >= realtime)
+ continue;
+
+ fd = openat(dirfd(d), de->d_name, O_CLOEXEC | O_NONBLOCK | O_RDONLY);
+ if (fd < 0) {
+ log_info_errno(errno, "Failed to open /var/log/journal/%s, ignoring: %m", de->d_name);
+ continue;
+ }
+
+ close_and_replace(newest_fd, fd);
+ newest_realtime = realtime;
+ newest_is_system = is_system;
+ }
+
+ if (newest_fd < 0)
+ return log_info_errno(SYNTHETIC_ERRNO(ENOENT), "No archive journal found.");
+
+ r = sd_journal_open_files_fd(ret, &newest_fd, 1, SD_JOURNAL_ASSUME_IMMUTABLE);
+
+ _cleanup_free_ char *path = NULL;
+ (void) fd_get_path(newest_fd, &path);
+
+ if (r < 0)
+ log_info_errno(r, "Failed to open %s, ignoring: %m", strna(path));
+ else {
+ log_info("Opened %s.", strna(path));
+ TAKE_FD(newest_fd);
+ }
+
+ return r;
+}
+
static void test_journal_flush_one(int argc, char *argv[]) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
_cleanup_free_ char *fn = NULL;
@@ -32,13 +111,16 @@ static void test_journal_flush_one(int argc, char *argv[]) {
assert_se(fn = path_join(dn, "test.journal"));
- r = journal_file_open(-1, fn, O_CREAT|O_RDWR, 0, 0644, 0, NULL, m, NULL, &new_journal);
+ r = journal_file_open(-EBADF, fn, O_CREAT|O_RDWR, 0, 0644, 0, NULL, m, NULL, &new_journal);
assert_se(r >= 0);
if (argc > 1)
- r = sd_journal_open_files(&j, (const char **) strv_skip(argv, 1), 0);
- else
- r = sd_journal_open(&j, 0);
+ r = sd_journal_open_files(&j, (const char **) strv_skip(argv, 1), SD_JOURNAL_ASSUME_IMMUTABLE);
+ else {
+ r = open_archive_file(&j);
+ if (r < 0)
+ r = sd_journal_open(&j, SD_JOURNAL_ASSUME_IMMUTABLE);
+ }
assert_se(r == 0);
sd_journal_set_data_threshold(j, 0);
@@ -75,7 +157,7 @@ static void test_journal_flush_one(int argc, char *argv[]) {
/* Open the new journal before archiving and offlining the file. */
sd_journal_close(j);
- assert_se(sd_journal_open_directory(&j, dn, 0) >= 0);
+ assert_se(sd_journal_open_directory(&j, dn, SD_JOURNAL_ASSUME_IMMUTABLE) >= 0);
/* Read the online journal. */
assert_se(sd_journal_seek_tail(j) >= 0);
diff --git a/src/libsystemd/sd-journal/test-journal-init.c b/src/libsystemd/sd-journal/test-journal-init.c
index c8a1977..ef66efd 100644
--- a/src/libsystemd/sd-journal/test-journal-init.c
+++ b/src/libsystemd/sd-journal/test-journal-init.c
@@ -31,12 +31,12 @@ int main(int argc, char *argv[]) {
(void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
for (i = 0; i < I; i++) {
- r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_ASSUME_IMMUTABLE);
assert_se(r == 0);
sd_journal_close(j);
- r = sd_journal_open_directory(&j, t, 0);
+ r = sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE);
assert_se(r == 0);
assert_se(sd_journal_seek_head(j) == 0);
@@ -45,8 +45,8 @@ int main(int argc, char *argv[]) {
r = safe_fork("(journal-fork-test)", FORK_WAIT|FORK_LOG, NULL);
if (r == 0) {
assert_se(j);
- assert_se(sd_journal_get_realtime_usec(j, NULL) == -ECHILD);
- assert_se(sd_journal_seek_tail(j) == -ECHILD);
+ ASSERT_RETURN_EXPECTED_SE(sd_journal_get_realtime_usec(j, NULL) == -ECHILD);
+ ASSERT_RETURN_EXPECTED_SE(sd_journal_seek_tail(j) == -ECHILD);
assert_se(j->current_location.type == LOCATION_HEAD);
sd_journal_close(j);
_exit(EXIT_SUCCESS);
@@ -57,8 +57,7 @@ int main(int argc, char *argv[]) {
sd_journal_close(j);
j = NULL;
- r = sd_journal_open_directory(&j, t, SD_JOURNAL_LOCAL_ONLY);
- assert_se(r == -EINVAL);
+ ASSERT_RETURN_EXPECTED(assert_se(sd_journal_open_directory(&j, t, SD_JOURNAL_LOCAL_ONLY) == -EINVAL));
assert_se(j == NULL);
}
diff --git a/src/libsystemd/sd-journal/test-journal-interleaving.c b/src/libsystemd/sd-journal/test-journal-interleaving.c
index 8aeef8f..d98b3ce 100644
--- a/src/libsystemd/sd-journal/test-journal-interleaving.c
+++ b/src/libsystemd/sd-journal/test-journal-interleaving.c
@@ -43,7 +43,7 @@ static JournalFile *test_open_internal(const char *name, JournalFileFlags flags)
m = mmap_cache_new();
assert_se(m != NULL);
- assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, flags, 0644, UINT64_MAX, NULL, m, NULL, &f));
+ assert_ret(journal_file_open(-EBADF, name, O_RDWR|O_CREAT, flags, 0644, UINT64_MAX, NULL, m, NULL, &f));
return f;
}
@@ -74,9 +74,9 @@ static void test_done(const char *t) {
}
static void append_number(JournalFile *f, int n, const sd_id128_t *boot_id, uint64_t *seqnum, uint64_t *ret_offset) {
- _cleanup_free_ char *p = NULL, *q = NULL;
+ _cleanup_free_ char *p = NULL, *q = NULL, *s = NULL;
dual_timestamp ts;
- struct iovec iovec[2];
+ struct iovec iovec[3];
size_t n_iov = 0;
dual_timestamp_now(&ts);
@@ -92,6 +92,9 @@ static void append_number(JournalFile *f, int n, const sd_id128_t *boot_id, uint
assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
iovec[n_iov++] = IOVEC_MAKE_STRING(p);
+ assert_se(s = strjoin("LESS_THAN_FIVE=%d", yes_no(n < 5)));
+ iovec[n_iov++] = IOVEC_MAKE_STRING(s);
+
if (boot_id) {
assert_se(q = strjoin("_BOOT_ID=", SD_ID128_TO_STRING(*boot_id)));
iovec[n_iov++] = IOVEC_MAKE_STRING(q);
@@ -250,6 +253,37 @@ static void mkdtemp_chdir_chattr(char *path) {
(void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
}
+static void test_cursor(sd_journal *j) {
+ _cleanup_strv_free_ char **cursors = NULL;
+ int r;
+
+ assert_se(sd_journal_seek_head(j) >= 0);
+
+ for (;;) {
+ r = sd_journal_next(j);
+ assert_se(r >= 0);
+ if (r == 0)
+ break;
+
+ _cleanup_free_ char *cursor = NULL;
+ assert_se(sd_journal_get_cursor(j, &cursor) >= 0);
+ assert_se(sd_journal_test_cursor(j, cursor) > 0);
+ assert_se(strv_consume(&cursors, TAKE_PTR(cursor)) >= 0);
+ }
+
+ STRV_FOREACH(c, cursors) {
+ assert_se(sd_journal_seek_cursor(j, *c) >= 0);
+ assert_se(sd_journal_next(j) >= 0);
+ assert_se(sd_journal_test_cursor(j, *c) > 0);
+ }
+
+ assert_se(sd_journal_seek_head(j) >= 0);
+ STRV_FOREACH(c, cursors) {
+ assert_se(sd_journal_next(j) >= 0);
+ assert_se(sd_journal_test_cursor(j, *c) > 0);
+ }
+}
+
static void test_skip_one(void (*setup)(void)) {
char t[] = "/var/tmp/journal-skip-XXXXXX";
sd_journal *j;
@@ -260,14 +294,14 @@ static void test_skip_one(void (*setup)(void)) {
setup();
/* Seek to head, iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */
test_check_numbers_down(j, 9);
sd_journal_close(j);
/* Seek to head, iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */
assert_se(sd_journal_previous(j) == 0); /* no-op */
@@ -275,7 +309,7 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to head twice, iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */
assert_ret(sd_journal_seek_head(j));
@@ -284,7 +318,7 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to head, move to previous, then iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_previous(j) == 0); /* no-op */
assert_se(sd_journal_next(j) == 1); /* pointing to the first entry */
@@ -292,7 +326,7 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to head, walk several steps, then iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_previous(j) == 0); /* no-op */
assert_se(sd_journal_previous(j) == 0); /* no-op */
@@ -304,14 +338,14 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to tail, iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */
test_check_numbers_up(j, 9);
sd_journal_close(j);
/* Seek to tail twice, iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */
assert_ret(sd_journal_seek_tail(j));
@@ -320,7 +354,7 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to tail, move to next, then iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_next(j) == 0); /* no-op */
assert_se(sd_journal_previous(j) == 1); /* pointing to the last entry */
@@ -328,7 +362,7 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to tail, walk several steps, then iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_next(j) == 0); /* no-op */
assert_se(sd_journal_next(j) == 0); /* no-op */
@@ -340,14 +374,14 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to tail, skip to head, iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_previous_skip(j, 9) == 9); /* pointing to the first entry. */
test_check_numbers_down(j, 9);
sd_journal_close(j);
/* Seek to tail, skip to head in a more complex way, then iterate down. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_tail(j));
assert_se(sd_journal_next(j) == 0);
assert_se(sd_journal_previous_skip(j, 4) == 4);
@@ -366,14 +400,14 @@ static void test_skip_one(void (*setup)(void)) {
sd_journal_close(j);
/* Seek to head, skip to tail, iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_next_skip(j, 9) == 9);
test_check_numbers_up(j, 9);
sd_journal_close(j);
/* Seek to head, skip to tail in a more complex way, then iterate up. */
- assert_ret(sd_journal_open_directory(&j, t, 0));
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
assert_ret(sd_journal_seek_head(j));
assert_se(sd_journal_previous(j) == 0);
assert_se(sd_journal_next_skip(j, 4) == 4);
@@ -391,6 +425,30 @@ static void test_skip_one(void (*setup)(void)) {
test_check_numbers_up(j, 9);
sd_journal_close(j);
+ /* For issue #31516. */
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
+ test_cursor(j);
+ sd_journal_flush_matches(j);
+ assert_se(sd_journal_add_match(j, "LESS_THAN_FIVE=yes", SIZE_MAX) >= 0);
+ test_cursor(j);
+ sd_journal_flush_matches(j);
+ assert_se(sd_journal_add_match(j, "LESS_THAN_FIVE=no", SIZE_MAX) >= 0);
+ test_cursor(j);
+ sd_journal_flush_matches(j);
+ assert_se(sd_journal_add_match(j, "LESS_THAN_FIVE=hoge", SIZE_MAX) >= 0);
+ test_cursor(j);
+ sd_journal_flush_matches(j);
+ assert_se(sd_journal_add_match(j, "LESS_THAN_FIVE=yes", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=3", SIZE_MAX) >= 0);
+ test_cursor(j);
+ sd_journal_flush_matches(j);
+ assert_se(sd_journal_add_match(j, "LESS_THAN_FIVE=yes", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=3", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=4", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=5", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=6", SIZE_MAX) >= 0);
+ test_cursor(j);
+
test_done(t);
}
@@ -401,7 +459,7 @@ TEST(skip) {
static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) {
char t[] = "/var/tmp/journal-boot-id-XXXXXX";
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
_cleanup_free_ BootId *boots = NULL;
size_t n_boots;
@@ -409,28 +467,59 @@ static void test_boot_id_one(void (*setup)(void), size_t n_boots_expected) {
setup();
- assert_ret(sd_journal_open_directory(&j, t, 0));
- assert_se(journal_get_boots(j, &boots, &n_boots) >= 0);
+ assert_ret(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE));
+ assert_se(journal_get_boots(
+ j,
+ /* advance_older = */ false, /* max_ids = */ SIZE_MAX,
+ &boots, &n_boots) >= 0);
assert_se(boots);
assert_se(n_boots == n_boots_expected);
- sd_journal_close(j);
- FOREACH_ARRAY(b, boots, n_boots) {
- assert_ret(sd_journal_open_directory(&j, t, 0));
- assert_se(journal_find_boot_by_id(j, b->id) == 1);
- sd_journal_close(j);
+ for (size_t i = 0; i < n_boots; i++) {
+ sd_id128_t id;
+
+ /* positive offset */
+ assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1), &id) == 1);
+ assert_se(sd_id128_equal(id, boots[i].id));
+
+ /* negative offset */
+ assert_se(journal_find_boot(j, SD_ID128_NULL, (int) (i + 1) - (int) n_boots, &id) == 1);
+ assert_se(sd_id128_equal(id, boots[i].id));
+
+ for (size_t k = 0; k < n_boots; k++) {
+ int offset = (int) k - (int) i;
+
+ /* relative offset */
+ assert_se(journal_find_boot(j, boots[i].id, offset, &id) == 1);
+ assert_se(sd_id128_equal(id, boots[k].id));
+ }
}
- for (int i = - (int) n_boots + 1; i <= (int) n_boots; i++) {
- sd_id128_t id;
+ for (size_t i = 0; i <= n_boots_expected + 1; i++) {
+ _cleanup_free_ BootId *boots_limited = NULL;
+ size_t n_boots_limited;
+
+ assert_se(journal_get_boots(
+ j,
+ /* advance_older = */ false, /* max_ids = */ i,
+ &boots_limited, &n_boots_limited) >= 0);
+ assert_se(boots_limited || i == 0);
+ assert_se(n_boots_limited == MIN(i, n_boots_expected));
+ assert_se(memcmp_safe(boots, boots_limited, n_boots_limited * sizeof(BootId)) == 0);
+ }
- assert_ret(sd_journal_open_directory(&j, t, 0));
- assert_se(journal_find_boot_by_offset(j, i, &id) == 1);
- if (i <= 0)
- assert_se(sd_id128_equal(id, boots[n_boots + i - 1].id));
- else
- assert_se(sd_id128_equal(id, boots[i - 1].id));
- sd_journal_close(j);
+ for (size_t i = 0; i <= n_boots_expected + 1; i++) {
+ _cleanup_free_ BootId *boots_limited = NULL;
+ size_t n_boots_limited;
+
+ assert_se(journal_get_boots(
+ j,
+ /* advance_older = */ true, /* max_ids = */ i,
+ &boots_limited, &n_boots_limited) >= 0);
+ assert_se(boots_limited || i == 0);
+ assert_se(n_boots_limited == MIN(i, n_boots_expected));
+ for (size_t k = 0; k < n_boots_limited; k++)
+ assert_se(memcmp(&boots[n_boots - k - 1], &boots_limited[k], sizeof(BootId)) == 0);
}
test_done(t);
@@ -453,7 +542,7 @@ static void test_sequence_numbers_one(void) {
mkdtemp_chdir_chattr(t);
- assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
+ assert_se(journal_file_open(-EBADF, "one.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
UINT64_MAX, NULL, m, NULL, &one) == 0);
append_number(one, 1, NULL, &seqnum, NULL);
@@ -470,7 +559,7 @@ static void test_sequence_numbers_one(void) {
memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
- assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
+ assert_se(journal_file_open(-EBADF, "two.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
UINT64_MAX, NULL, m, one, &two) == 0);
assert_se(two->header->state == STATE_ONLINE);
@@ -502,12 +591,12 @@ static void test_sequence_numbers_one(void) {
test_close(one);
/* If the machine-id is not initialized, the header file verification
- * (which happens when re-opening a journal file) will fail. */
+ * (which happens when reopening a journal file) will fail. */
if (sd_id128_get_machine(NULL) >= 0) {
/* restart server */
seqnum = 0;
- assert_se(journal_file_open(-1, "two.journal", O_RDWR, JOURNAL_COMPRESS, 0,
+ assert_se(journal_file_open(-EBADF, "two.journal", O_RDWR, JOURNAL_COMPRESS, 0,
UINT64_MAX, NULL, m, NULL, &two) == 0);
assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
@@ -567,7 +656,41 @@ static int expected_result(uint64_t needle, const uint64_t *candidates, const ui
}
}
-static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offset, size_t n) {
+static int expected_result_next(uint64_t needle, const uint64_t *candidates, const uint64_t *offset, size_t n, direction_t direction, uint64_t *ret) {
+ switch (direction) {
+ case DIRECTION_DOWN:
+ for (size_t i = 0; i < n; i++)
+ if (needle < offset[i]) {
+ *ret = candidates[i];
+ return candidates[i] > 0;
+ }
+ *ret = 0;
+ return 0;
+
+ case DIRECTION_UP:
+ for (size_t i = 0; i < n; i++)
+ if (needle <= offset[i]) {
+ n = i;
+ break;
+ }
+
+ for (; n > 0 && candidates[n - 1] == 0; n--)
+ ;
+
+ if (n == 0) {
+ *ret = 0;
+ return 0;
+ }
+
+ *ret = candidates[n - 1];
+ return candidates[n - 1] > 0;
+
+ default:
+ assert_not_reached();
+ }
+}
+
+static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offset_candidates, const uint64_t *offset, size_t n) {
uint64_t p, q;
int r, e;
@@ -664,12 +787,81 @@ static void verify(JournalFile *f, const uint64_t *seqnum, const uint64_t *offse
assert_se(r == e);
assert_se(p == q);
}
+
+ /* by journal_file_next_entry() */
+ for (size_t i = 0; i < n; i++) {
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] - 2, DIRECTION_DOWN, NULL, &p);
+ e = expected_result_next(offset[i] - 2, offset_candidates, offset, n, DIRECTION_DOWN, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] - 1, DIRECTION_DOWN, NULL, &p);
+ e = expected_result_next(offset[i] - 1, offset_candidates, offset, n, DIRECTION_DOWN, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i], DIRECTION_DOWN, NULL, &p);
+ e = expected_result_next(offset[i], offset_candidates, offset, n, DIRECTION_DOWN, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] + 1, DIRECTION_DOWN, NULL, &p);
+ e = expected_result_next(offset[i] + 1, offset_candidates, offset, n, DIRECTION_DOWN, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] - 1, DIRECTION_UP, NULL, &p);
+ e = expected_result_next(offset[i] - 1, offset_candidates, offset, n, DIRECTION_UP, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i], DIRECTION_UP, NULL, &p);
+ e = expected_result_next(offset[i], offset_candidates, offset, n, DIRECTION_UP, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] + 1, DIRECTION_UP, NULL, &p);
+ e = expected_result_next(offset[i] + 1, offset_candidates, offset, n, DIRECTION_UP, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+
+ p = 0;
+ r = journal_file_next_entry(f, offset[i] + 2, DIRECTION_UP, NULL, &p);
+ e = expected_result_next(offset[i] + 2, offset_candidates, offset, n, DIRECTION_UP, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+ }
+ for (size_t trial = 0; trial < 3 * n; trial++) {
+ uint64_t i = offset[0] - 1 + random_u64_range(offset[n-1] - offset[0] + 2);
+
+ p = 0;
+ r = journal_file_next_entry(f, i, DIRECTION_DOWN, NULL, &p);
+ e = expected_result_next(i, offset_candidates, offset, n, DIRECTION_DOWN, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+ }
+ for (size_t trial = 0; trial < 3 * n; trial++) {
+ uint64_t i = offset[0] - 1 + random_u64_range(offset[n-1] - offset[0] + 2);
+
+ p = 0;
+ r = journal_file_next_entry(f, i, DIRECTION_UP, NULL, &p);
+ e = expected_result_next(i, offset_candidates, offset, n, DIRECTION_UP, &q);
+ assert_se(e == 0 ? r <= 0 : r > 0);
+ assert_se(p == q);
+ }
}
static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
_cleanup_(mmap_cache_unrefp) MMapCache *m = NULL;
char t[] = "/var/tmp/journal-seq-XXXXXX";
- _cleanup_free_ uint64_t *seqnum = NULL, *offset = NULL;
+ _cleanup_free_ uint64_t *seqnum = NULL, *offset = NULL, *offset_candidates = NULL;
JournalFile *f;
log_info("/* %s(%zu, %zu) */", __func__, n, num_corrupted);
@@ -678,7 +870,7 @@ static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
mkdtemp_chdir_chattr(t);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
+ assert_se(journal_file_open(-EBADF, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0644,
UINT64_MAX, NULL, m, NULL, &f) == 0);
assert_se(seqnum = new0(uint64_t, n));
@@ -695,7 +887,9 @@ static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
}
}
- verify(f, seqnum, offset, n);
+ assert_se(offset_candidates = newdup(uint64_t, offset, n));
+
+ verify(f, seqnum, offset_candidates, offset, n);
/* Reset chain cache. */
assert_se(journal_file_move_to_entry_by_offset(f, offset[0], DIRECTION_DOWN, NULL, NULL) > 0);
@@ -708,9 +902,10 @@ static void test_generic_array_bisect_one(size_t n, size_t num_corrupted) {
assert_se(o);
o->entry.seqnum = 0;
seqnum[i] = 0;
+ offset_candidates[i] = 0;
}
- verify(f, seqnum, offset, n);
+ verify(f, seqnum, offset_candidates, offset, n);
test_close(f);
test_done(t);
diff --git a/src/libsystemd/sd-journal/test-journal-match.c b/src/libsystemd/sd-journal/test-journal-match.c
index 571a88c..c2c345f 100644
--- a/src/libsystemd/sd-journal/test-journal-match.c
+++ b/src/libsystemd/sd-journal/test-journal-match.c
@@ -16,40 +16,40 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
- assert_se(sd_journal_open(&j, 0) >= 0);
+ assert_se(sd_journal_open(&j, SD_JOURNAL_ASSUME_IMMUTABLE) >= 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, "foobar", SIZE_MAX) < 0);
+ assert_se(sd_journal_add_match(j, "foobar=waldo", SIZE_MAX) < 0);
+ assert_se(sd_journal_add_match(j, "", SIZE_MAX) < 0);
+ assert_se(sd_journal_add_match(j, "=", SIZE_MAX) < 0);
+ assert_se(sd_journal_add_match(j, "=xxxxx", SIZE_MAX) < 0);
assert_se(sd_journal_add_match(j, (uint8_t[4]){'A', '=', '\1', '\2'}, 4) >= 0);
assert_se(sd_journal_add_match(j, (uint8_t[5]){'B', '=', 'C', '\0', 'D'}, 5) >= 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_match(j, "HALLO=WALDO", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "QUUX=mmmm", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "QUUX=xxxxx", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "HALLO=", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "QUUX=xxxxx", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "QUUX=yyyyy", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "PIFF=paff", SIZE_MAX) >= 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(sd_journal_add_match(j, "ONE=one", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "ONE=two", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "TWO=two", SIZE_MAX) >= 0);
assert_se(sd_journal_add_conjunction(j) >= 0);
- assert_se(sd_journal_add_match(j, "L4_1=yes", 0) >= 0);
- assert_se(sd_journal_add_match(j, "L4_1=ok", 0) >= 0);
- assert_se(sd_journal_add_match(j, "L4_2=yes", 0) >= 0);
- assert_se(sd_journal_add_match(j, "L4_2=ok", 0) >= 0);
+ assert_se(sd_journal_add_match(j, "L4_1=yes", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "L4_1=ok", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "L4_2=yes", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "L4_2=ok", SIZE_MAX) >= 0);
assert_se(sd_journal_add_disjunction(j) >= 0);
- assert_se(sd_journal_add_match(j, "L3=yes", 0) >= 0);
- assert_se(sd_journal_add_match(j, "L3=ok", 0) >= 0);
+ assert_se(sd_journal_add_match(j, "L3=yes", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "L3=ok", SIZE_MAX) >= 0);
assert_se(t = journal_make_match_string(j));
diff --git a/src/libsystemd/sd-journal/test-journal-stream.c b/src/libsystemd/sd-journal/test-journal-stream.c
index 3a370ef..00c0435 100644
--- a/src/libsystemd/sd-journal/test-journal-stream.c
+++ b/src/libsystemd/sd-journal/test-journal-stream.c
@@ -76,9 +76,9 @@ static void run_test(void) {
assert_se(chdir(t) >= 0);
(void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
- assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &one) == 0);
- assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &two) == 0);
- assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &three) == 0);
+ assert_se(journal_file_open(-EBADF, "one.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &one) == 0);
+ assert_se(journal_file_open(-EBADF, "two.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &two) == 0);
+ assert_se(journal_file_open(-EBADF, "three.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &three) == 0);
for (i = 0; i < N_ENTRIES; i++) {
char *p, *q;
@@ -119,9 +119,9 @@ static void run_test(void) {
(void) journal_file_offline_close(two);
(void) journal_file_offline_close(three);
- assert_se(sd_journal_open_directory(&j, t, 0) >= 0);
+ assert_se(sd_journal_open_directory(&j, t, SD_JOURNAL_ASSUME_IMMUTABLE) >= 0);
- assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
+ assert_se(sd_journal_add_match(j, "MAGIC=quux", SIZE_MAX) >= 0);
SD_JOURNAL_FOREACH_BACKWARDS(j) {
_cleanup_free_ char *c;
@@ -147,7 +147,7 @@ static void run_test(void) {
verify_contents(j, 1);
printf("NEXT TEST\n");
- assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0);
+ assert_se(sd_journal_add_match(j, "MAGIC=quux", SIZE_MAX) >= 0);
assert_se(z = journal_make_match_string(j));
printf("resulting match expression is: %s\n", z);
@@ -157,10 +157,10 @@ static void run_test(void) {
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(sd_journal_add_match(j, "MAGIC=waldo", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=10", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=11", SIZE_MAX) >= 0);
+ assert_se(sd_journal_add_match(j, "NUMBER=12", SIZE_MAX) >= 0);
assert_se(z = journal_make_match_string(j));
printf("resulting match expression is: %s\n", z);
diff --git a/src/libsystemd/sd-journal/test-journal-verify.c b/src/libsystemd/sd-journal/test-journal-verify.c
index edce440..396ebe1 100644
--- a/src/libsystemd/sd-journal/test-journal-verify.c
+++ b/src/libsystemd/sd-journal/test-journal-verify.c
@@ -47,7 +47,7 @@ static int raw_verify(const char *fn, const char *verification_key) {
assert_se(m != NULL);
r = journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
fn,
O_RDONLY,
JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
@@ -92,7 +92,7 @@ static int run_test(const char *verification_key, ssize_t max_iterations) {
log_info("Generating a test journal");
assert_se(journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
"test.journal",
O_RDWR|O_CREAT,
JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
@@ -128,7 +128,7 @@ static int run_test(const char *verification_key, ssize_t max_iterations) {
log_info("Verifying with key: %s", strna(verification_key));
assert_se(journal_file_open(
- /* fd= */ -1,
+ /* fd= */ -EBADF,
"test.journal",
O_RDONLY,
JOURNAL_COMPRESS|(verification_key ? JOURNAL_SEAL : 0),
diff --git a/src/libsystemd/sd-journal/test-journal.c b/src/libsystemd/sd-journal/test-journal.c
index 96f2b67..19a6d2d 100644
--- a/src/libsystemd/sd-journal/test-journal.c
+++ b/src/libsystemd/sd-journal/test-journal.c
@@ -39,7 +39,7 @@ static void test_non_empty_one(void) {
mkdtemp_chdir_chattr(t);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f) == 0);
+ assert_se(journal_file_open(-EBADF, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f) == 0);
assert_se(dual_timestamp_now(&ts));
assert_se(sd_id128_randomize(&fake_boot_id) == 0);
@@ -136,10 +136,10 @@ static void test_empty_one(void) {
mkdtemp_chdir_chattr(t);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0, 0666, UINT64_MAX, NULL, m, NULL, &f1) == 0);
- assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &f2) == 0);
- assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f3) == 0);
- assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f4) == 0);
+ assert_se(journal_file_open(-EBADF, "test.journal", O_RDWR|O_CREAT, 0, 0666, UINT64_MAX, NULL, m, NULL, &f1) == 0);
+ assert_se(journal_file_open(-EBADF, "test-compress.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS, 0666, UINT64_MAX, NULL, m, NULL, &f2) == 0);
+ assert_se(journal_file_open(-EBADF, "test-seal.journal", O_RDWR|O_CREAT, JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f3) == 0);
+ assert_se(journal_file_open(-EBADF, "test-seal-compress.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, UINT64_MAX, NULL, m, NULL, &f4) == 0);
journal_file_print_header(f1);
puts("");
@@ -194,7 +194,7 @@ static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) {
mkdtemp_chdir_chattr(t);
- assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, compress_threshold, NULL, m, NULL, &f) == 0);
+ assert_se(journal_file_open(-EBADF, "test.journal", O_RDWR|O_CREAT, JOURNAL_COMPRESS|JOURNAL_SEAL, 0666, compress_threshold, NULL, m, NULL, &f) == 0);
dual_timestamp_now(&ts);