journal-file.c   journal-file.c 
skipping to change at line 141 skipping to change at line 141
munmap(f->header, PAGE_ALIGN(sizeof(Header))); munmap(f->header, PAGE_ALIGN(sizeof(Header)));
safe_close(f->fd); safe_close(f->fd);
free(f->path); free(f->path);
if (f->mmap) if (f->mmap)
mmap_cache_unref(f->mmap); mmap_cache_unref(f->mmap);
hashmap_free_free(f->chain_cache); hashmap_free_free(f->chain_cache);
#ifdef HAVE_XZ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
free(f->compress_buffer); free(f->compress_buffer);
#endif #endif
#ifdef HAVE_GCRYPT #ifdef HAVE_GCRYPT
if (f->fss_file) if (f->fss_file)
munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size)); munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
else if (f->fsprg_state) else if (f->fsprg_state)
free(f->fsprg_state); free(f->fsprg_state);
free(f->fsprg_seed); free(f->fsprg_seed);
if (f->hmac) if (f->hmac)
gcry_md_close(f->hmac); gcry_md_close(f->hmac);
#endif #endif
free(f); free(f);
} }
static int journal_file_init_header(JournalFile *f, JournalFile *template) { static int journal_file_init_header(JournalFile *f, JournalFile *template) {
Header h; Header h = {};
ssize_t k; ssize_t k;
int r; int r;
assert(f); assert(f);
zero(h);
memcpy(h.signature, HEADER_SIGNATURE, 8); memcpy(h.signature, HEADER_SIGNATURE, 8);
h.header_size = htole64(ALIGN64(sizeof(h))); h.header_size = htole64(ALIGN64(sizeof(h)));
h.incompatible_flags = h.incompatible_flags |= htole32(
htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0); f->compress_xz * HEADER_INCOMPATIBLE_COMPRESSED_XZ |
f->compress_lz4 * HEADER_INCOMPATIBLE_COMPRESSED_LZ4);
h.compatible_flags = h.compatible_flags = htole32(
htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0); f->seal * HEADER_COMPATIBLE_SEALED);
r = sd_id128_randomize(&h.file_id); r = sd_id128_randomize(&h.file_id);
if (r < 0) if (r < 0)
return r; return r;
if (template) { if (template) {
h.seqnum_id = template->header->seqnum_id; h.seqnum_id = template->header->seqnum_id;
h.tail_entry_seqnum = template->header->tail_entry_seqnum; h.tail_entry_seqnum = template->header->tail_entry_seqnum;
} else } else
h.seqnum_id = h.file_id; h.seqnum_id = h.file_id;
skipping to change at line 225 skipping to change at line 225
journal_file_set_online(f); journal_file_set_online(f);
/* Sync the online state to disk */ /* Sync the online state to disk */
fsync(f->fd); fsync(f->fd);
return 0; return 0;
} }
static int journal_file_verify_header(JournalFile *f) { static int journal_file_verify_header(JournalFile *f) {
uint32_t flags;
assert(f); assert(f);
if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) if (memcmp(f->header->signature, HEADER_SIGNATURE, 8))
return -EBADMSG; return -EBADMSG;
/* In both read and write mode we refuse to open files with /* In both read and write mode we refuse to open files with
* incompatible flags we don't know */ * incompatible flags we don't know */
#ifdef HAVE_XZ flags = le32toh(f->header->incompatible_flags);
if ((le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_ if (flags & ~HEADER_INCOMPATIBLE_SUPPORTED) {
COMPRESSED) != 0) if (flags & ~HEADER_INCOMPATIBLE_ANY)
return -EPROTONOSUPPORT; log_debug("Journal file %s has unknown incompatible
#else flags %"PRIx32,
if (f->header->incompatible_flags != 0) f->path, flags & ~HEADER_INCOMPATIBLE_ANY
);
flags = (flags & HEADER_INCOMPATIBLE_ANY) & ~HEADER_INCOMPA
TIBLE_SUPPORTED;
if (flags)
log_debug("Journal file %s uses incompatible flags
%"PRIx32
" disabled at compilation time.", f->path
, flags);
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
#endif }
/* When open for writing we refuse to open files with /* When open for writing we refuse to open files with
* compatible flags, too */ * compatible flags, too */
if (f->writable) { flags = le32toh(f->header->compatible_flags);
#ifdef HAVE_GCRYPT if (f->writable && (flags & ~HEADER_COMPATIBLE_SUPPORTED)) {
if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATI if (flags & ~HEADER_COMPATIBLE_ANY)
BLE_SEALED) != 0) log_debug("Journal file %s has unknown compatible f
return -EPROTONOSUPPORT; lags %"PRIx32,
#else f->path, flags & ~HEADER_COMPATIBLE_ANY);
if (f->header->compatible_flags != 0) flags = (flags & HEADER_COMPATIBLE_ANY) & ~HEADER_COMPATIBL
return -EPROTONOSUPPORT; E_SUPPORTED;
#endif if (flags)
log_debug("Journal file %s uses compatible flags %"
PRIx32
" disabled at compilation time.", f->path
, flags);
return -EPROTONOSUPPORT;
} }
if (f->header->state >= _STATE_MAX) if (f->header->state >= _STATE_MAX)
return -EBADMSG; return -EBADMSG;
/* The first addition was n_data, so check that we are at least thi s large */ /* The first addition was n_data, so check that we are at least thi s large */
if (le64toh(f->header->header_size) < HEADER_SIZE_MIN) if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
return -EBADMSG; return -EBADMSG;
if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f- >header, n_entry_arrays)) if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f- >header, n_entry_arrays))
skipping to change at line 274 skipping to change at line 282
if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->he ader_size) + le64toh(f->header->arena_size))) if (le64toh(f->header->tail_object_offset) > (le64toh(f->header->he ader_size) + le64toh(f->header->arena_size)))
return -ENODATA; return -ENODATA;
if (!VALID64(le64toh(f->header->data_hash_table_offset)) || if (!VALID64(le64toh(f->header->data_hash_table_offset)) ||
!VALID64(le64toh(f->header->field_hash_table_offset)) || !VALID64(le64toh(f->header->field_hash_table_offset)) ||
!VALID64(le64toh(f->header->tail_object_offset)) || !VALID64(le64toh(f->header->tail_object_offset)) ||
!VALID64(le64toh(f->header->entry_array_offset))) !VALID64(le64toh(f->header->entry_array_offset)))
return -ENODATA; return -ENODATA;
if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header-
>header_size) ||
le64toh(f->header->field_hash_table_offset) < le64toh(f->header
->header_size) ||
le64toh(f->header->tail_object_offset) < le64toh(f->header->hea
der_size) ||
le64toh(f->header->entry_array_offset) < le64toh(f->header->hea
der_size))
return -ENODATA;
if (f->writable) { if (f->writable) {
uint8_t state; uint8_t state;
sd_id128_t machine_id; sd_id128_t machine_id;
int r; int r;
r = sd_id128_get_machine(&machine_id); r = sd_id128_get_machine(&machine_id);
if (r < 0) if (r < 0)
return r; return r;
if (!sd_id128_equal(machine_id, f->header->machine_id)) if (!sd_id128_equal(machine_id, f->header->machine_id))
skipping to change at line 305 skipping to change at line 307
log_debug("Journal file %s is already online. Assum ing unclean closing.", f->path); log_debug("Journal file %s is already online. Assum ing unclean closing.", f->path);
return -EBUSY; return -EBUSY;
} else if (state == STATE_ARCHIVED) } else if (state == STATE_ARCHIVED)
return -ESHUTDOWN; return -ESHUTDOWN;
else if (state != STATE_OFFLINE) { else if (state != STATE_OFFLINE) {
log_debug("Journal file %s has unknown state %u.", f->path, state); log_debug("Journal file %s has unknown state %u.", f->path, state);
return -EBUSY; return -EBUSY;
} }
} }
f->compress = JOURNAL_HEADER_COMPRESSED(f->header); f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header);
f->compress_lz4 = JOURNAL_HEADER_COMPRESSED_LZ4(f->header);
f->seal = JOURNAL_HEADER_SEALED(f->header); f->seal = JOURNAL_HEADER_SEALED(f->header);
return 0; return 0;
} }
static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
uint64_t old_size, new_size; uint64_t old_size, new_size;
int r; int r;
skipping to change at line 811 skipping to change at line 814
while (p > 0) { while (p > 0) {
Object *o; Object *o;
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
if (r < 0) if (r < 0)
return r; return r;
if (le64toh(o->data.hash) != hash) if (le64toh(o->data.hash) != hash)
goto next; goto next;
if (o->object.flags & OBJECT_COMPRESSED) { if (o->object.flags & OBJECT_COMPRESSION_MASK) {
#ifdef HAVE_XZ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
uint64_t l, rsize; uint64_t l;
size_t rsize;
l = le64toh(o->object.size); l = le64toh(o->object.size);
if (l <= offsetof(Object, data.payload)) if (l <= offsetof(Object, data.payload))
return -EBADMSG; return -EBADMSG;
l -= offsetof(Object, data.payload); l -= offsetof(Object, data.payload);
if (!uncompress_blob(o->data.payload, l, &f->compre r = decompress_blob(o->object.flags & OBJECT_COMPRE
ss_buffer, &f->compress_buffer_size, &rsize, 0)) SSION_MASK,
return -EBADMSG; o->data.payload, l, &f->compres
s_buffer, &f->compress_buffer_size, &rsize, 0);
if (r < 0)
return r;
if (rsize == size && if (rsize == size &&
memcmp(f->compress_buffer, data, size) == 0) { memcmp(f->compress_buffer, data, size) == 0) {
if (ret) if (ret)
*ret = o; *ret = o;
if (offset) if (offset)
*offset = p; *offset = p;
return 1; return 1;
} }
#else #else
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
#endif #endif
} else if (le64toh(o->object.size) == osize && } else if (le64toh(o->object.size) == osize &&
memcmp(o->data.payload, data, size) == 0) { memcmp(o->data.payload, data, size) == 0) {
if (ret) if (ret)
*ret = o; *ret = o;
if (offset) if (offset)
*offset = p; *offset = p;
return 1; return 1;
skipping to change at line 945 skipping to change at line 950
} }
static int journal_file_append_data( static int journal_file_append_data(
JournalFile *f, JournalFile *f,
const void *data, uint64_t size, const void *data, uint64_t size,
Object **ret, uint64_t *offset) { Object **ret, uint64_t *offset) {
uint64_t hash, p; uint64_t hash, p;
uint64_t osize; uint64_t osize;
Object *o; Object *o;
int r; int r, compression = 0;
bool compressed = false;
const void *eq; const void *eq;
assert(f); assert(f);
assert(data || size == 0); assert(data || size == 0);
hash = hash64(data, size); hash = hash64(data, size);
r = journal_file_find_data_object_with_hash(f, data, size, hash, &o , &p); r = journal_file_find_data_object_with_hash(f, data, size, hash, &o , &p);
if (r < 0) if (r < 0)
return r; return r;
skipping to change at line 975 skipping to change at line 979
return 0; return 0;
} }
osize = offsetof(Object, data.payload) + size; osize = offsetof(Object, data.payload) + size;
r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p); r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p);
if (r < 0) if (r < 0)
return r; return r;
o->data.hash = htole64(hash); o->data.hash = htole64(hash);
#ifdef HAVE_XZ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
if (f->compress && if (f->compress_xz &&
size >= COMPRESSION_SIZE_THRESHOLD) { size >= COMPRESSION_SIZE_THRESHOLD) {
uint64_t rsize; size_t rsize;
compressed = compress_blob(data, size, o->data.payload, &rs ize); compression = compress_blob(data, size, o->data.payload, &r size);
if (compressed) { if (compression) {
o->object.size = htole64(offsetof(Object, data.payl oad) + rsize); o->object.size = htole64(offsetof(Object, data.payl oad) + rsize);
o->object.flags |= OBJECT_COMPRESSED; o->object.flags |= compression;
log_debug("Compressed data object %"PRIu64" -> %"PR log_debug("Compressed data object %"PRIu64" -> %zu
Iu64, size, rsize); using %s",
size, rsize, object_compressed_to_string(
compression));
} }
} }
#endif #endif
if (!compressed && size > 0) if (!compression && size > 0)
memcpy(o->data.payload, data, size); memcpy(o->data.payload, data, size);
r = journal_file_link_data(f, o, p, hash); r = journal_file_link_data(f, o, p, hash);
if (r < 0) if (r < 0)
return r; return r;
/* The linking might have altered the window, so let's /* The linking might have altered the window, so let's
* refresh our pointer */ * refresh our pointer */
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
if (r < 0) if (r < 0)
skipping to change at line 2332 skipping to change at line 2337
printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"P RIu64"\n", printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"P RIu64"\n",
le64toh(o->tag.seqnum), le64toh(o->tag.seqnum),
le64toh(o->tag.epoch)); le64toh(o->tag.epoch));
break; break;
default: default:
printf("Type: unknown (%u)\n", o->object.type); printf("Type: unknown (%u)\n", o->object.type);
break; break;
} }
if (o->object.flags & OBJECT_COMPRESSED) if (o->object.flags & OBJECT_COMPRESSION_MASK)
printf("Flags: COMPRESSED\n"); printf("Flags: %s\n",
object_compressed_to_string(o->object.flags
& OBJECT_COMPRESSION_MASK));
if (p == le64toh(f->header->tail_object_offset)) if (p == le64toh(f->header->tail_object_offset))
p = 0; p = 0;
else else
p = p + ALIGN64(le64toh(o->object.size)); p = p + ALIGN64(le64toh(o->object.size));
} }
return; return;
fail: fail:
log_error("File corrupt"); log_error("File corrupt");
skipping to change at line 2370 skipping to change at line 2376
assert(f); assert(f);
printf("File Path: %s\n" printf("File Path: %s\n"
"File ID: %s\n" "File ID: %s\n"
"Machine ID: %s\n" "Machine ID: %s\n"
"Boot ID: %s\n" "Boot ID: %s\n"
"Sequential Number ID: %s\n" "Sequential Number ID: %s\n"
"State: %s\n" "State: %s\n"
"Compatible Flags:%s%s\n" "Compatible Flags:%s%s\n"
"Incompatible Flags:%s%s\n" "Incompatible Flags:%s%s%s\n"
"Header size: %"PRIu64"\n" "Header size: %"PRIu64"\n"
"Arena size: %"PRIu64"\n" "Arena size: %"PRIu64"\n"
"Data Hash Table Size: %"PRIu64"\n" "Data Hash Table Size: %"PRIu64"\n"
"Field Hash Table Size: %"PRIu64"\n" "Field Hash Table Size: %"PRIu64"\n"
"Rotate Suggested: %s\n" "Rotate Suggested: %s\n"
"Head Sequential Number: %"PRIu64"\n" "Head Sequential Number: %"PRIu64"\n"
"Tail Sequential Number: %"PRIu64"\n" "Tail Sequential Number: %"PRIu64"\n"
"Head Realtime Timestamp: %s\n" "Head Realtime Timestamp: %s\n"
"Tail Realtime Timestamp: %s\n" "Tail Realtime Timestamp: %s\n"
"Tail Monotonic Timestamp: %s\n" "Tail Monotonic Timestamp: %s\n"
skipping to change at line 2392 skipping to change at line 2398
"Entry Objects: %"PRIu64"\n", "Entry Objects: %"PRIu64"\n",
f->path, f->path,
sd_id128_to_string(f->header->file_id, a), sd_id128_to_string(f->header->file_id, a),
sd_id128_to_string(f->header->machine_id, b), sd_id128_to_string(f->header->machine_id, b),
sd_id128_to_string(f->header->boot_id, c), sd_id128_to_string(f->header->boot_id, c),
sd_id128_to_string(f->header->seqnum_id, d), sd_id128_to_string(f->header->seqnum_id, d),
f->header->state == STATE_OFFLINE ? "OFFLINE" : f->header->state == STATE_OFFLINE ? "OFFLINE" :
f->header->state == STATE_ONLINE ? "ONLINE" : f->header->state == STATE_ONLINE ? "ONLINE" :
f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN", f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "", JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "",
(le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_S (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_A
EALED) ? " ???" : "", NY) ? " ???" : "",
JOURNAL_HEADER_COMPRESSED(f->header) ? " COMPRESSED" : "", JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" :
(le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIB "",
LE_COMPRESSED) ? " ???" : "", JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4"
: "",
(le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIB
LE_ANY) ? " ???" : "",
le64toh(f->header->header_size), le64toh(f->header->header_size),
le64toh(f->header->arena_size), le64toh(f->header->arena_size),
le64toh(f->header->data_hash_table_size) / sizeof(HashItem), le64toh(f->header->data_hash_table_size) / sizeof(HashItem),
le64toh(f->header->field_hash_table_size) / sizeof(HashItem) , le64toh(f->header->field_hash_table_size) / sizeof(HashItem) ,
yes_no(journal_file_rotate_suggested(f, 0)), yes_no(journal_file_rotate_suggested(f, 0)),
le64toh(f->header->head_entry_seqnum), le64toh(f->header->head_entry_seqnum),
le64toh(f->header->tail_entry_seqnum), le64toh(f->header->tail_entry_seqnum),
format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_ entry_realtime)), format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_ entry_realtime)),
format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_ entry_realtime)), format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_ entry_realtime)),
format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_ monotonic), USEC_PER_MSEC), format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_ monotonic), USEC_PER_MSEC),
skipping to change at line 2467 skipping to change at line 2474
f = new0(JournalFile, 1); f = new0(JournalFile, 1);
if (!f) if (!f)
return -ENOMEM; return -ENOMEM;
f->fd = -1; f->fd = -1;
f->mode = mode; f->mode = mode;
f->flags = flags; f->flags = flags;
f->prot = prot_from_flags(flags); f->prot = prot_from_flags(flags);
f->writable = (flags & O_ACCMODE) != O_RDONLY; f->writable = (flags & O_ACCMODE) != O_RDONLY;
#ifdef HAVE_XZ #if defined(HAVE_LZ4)
f->compress = compress; f->compress_lz4 = compress;
#elif defined(HAVE_XZ)
f->compress_xz = compress;
#endif #endif
#ifdef HAVE_GCRYPT #ifdef HAVE_GCRYPT
f->seal = seal; f->seal = seal;
#endif #endif
if (mmap_cache) if (mmap_cache)
f->mmap = mmap_cache_ref(mmap_cache); f->mmap = mmap_cache_ref(mmap_cache);
else { else {
f->mmap = mmap_cache_new(); f->mmap = mmap_cache_new();
if (!f->mmap) { if (!f->mmap) {
skipping to change at line 2760 skipping to change at line 2769
if (le_hash != o->data.hash) if (le_hash != o->data.hash)
return -EBADMSG; return -EBADMSG;
l = le64toh(o->object.size) - offsetof(Object, data.payload ); l = le64toh(o->object.size) - offsetof(Object, data.payload );
t = (size_t) l; t = (size_t) l;
/* We hit the limit on 32bit machines */ /* We hit the limit on 32bit machines */
if ((uint64_t) t != l) if ((uint64_t) t != l)
return -E2BIG; return -E2BIG;
if (o->object.flags & OBJECT_COMPRESSED) { if (o->object.flags & OBJECT_COMPRESSION_MASK) {
#ifdef HAVE_XZ #if defined(HAVE_XZ) || defined(HAVE_LZ4)
uint64_t rsize; size_t rsize;
if (!uncompress_blob(o->data.payload, l, &from->com r = decompress_blob(o->object.flags & OBJECT_COMPRE
press_buffer, &from->compress_buffer_size, &rsize, 0)) SSION_MASK,
return -EBADMSG; o->data.payload, l, &from->comp
ress_buffer, &from->compress_buffer_size, &rsize, 0);
if (r < 0)
return r;
data = from->compress_buffer; data = from->compress_buffer;
l = rsize; l = rsize;
#else #else
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
#endif #endif
} else } else
data = o->data.payload; data = o->data.payload;
r = journal_file_append_data(to, data, l, &u, &h); r = journal_file_append_data(to, data, l, &u, &h);
 End of changes. 28 change blocks. 
68 lines changed or deleted 88 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/