diff options
Diffstat (limited to 'src/libsystemd/sd-journal')
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); |