chiark / gitweb /
journal: add LZ4 as optional compressor
[elogind.git] / src / journal / journal-verify.c
index 340581153425cb67c979d18877404b65c95700c3..c063d12210eb8aeb486626a0cf00774375f9279e 100644 (file)
 #include "compress.h"
 #include "fsprg.h"
 
-/* Use six characters to cover the offsets common in smallish journal
- * files without adding to many zeros. */
-#define OFSfmt "%06"PRIx64
-
 static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
         uint64_t i;
 
@@ -49,7 +45,7 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
          * possible field values. It does not follow any references to
          * other objects. */
 
-        if ((o->object.flags & OBJECT_COMPRESSED) &&
+        if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
             o->object.type != OBJECT_DATA)
                 return -EBADMSG;
 
@@ -76,22 +72,38 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
 
                 h1 = le64toh(o->data.hash);
 
-                if (o->object.flags & OBJECT_COMPRESSED) {
+                if (o->object.flags & OBJECT_COMPRESSED_XZ) {
 #ifdef HAVE_XZ
-                        void *b = NULL;
+                        _cleanup_free_ void *b = NULL;
                         uint64_t alloc = 0, b_size;
 
-                        if (!uncompress_blob(o->data.payload,
-                                             le64toh(o->object.size) - offsetof(Object, data.payload),
-                                             &b, &alloc, &b_size, 0)) {
-                                log_error(OFSfmt": uncompression failed", offset);
+                        if (!decompress_blob_xz(o->data.payload,
+                                                le64toh(o->object.size) - offsetof(Object, data.payload),
+                                                &b, &alloc, &b_size, 0)) {
+                                log_error(OFSfmt": XZ decompression failed", offset);
                                 return -EBADMSG;
                         }
 
                         h2 = hash64(b, b_size);
-                        free(b);
 #else
-                        log_error("Compression is not supported");
+                        log_error("XZ compression is not supported");
+                        return -EPROTONOSUPPORT;
+#endif
+                } else if (o->object.flags & OBJECT_COMPRESSED_LZ4) {
+#ifdef HAVE_XZ
+                        _cleanup_free_ void *b = NULL;
+                        uint64_t alloc = 0, b_size;
+
+                        if (!decompress_blob_xz(o->data.payload,
+                                                le64toh(o->object.size) - offsetof(Object, data.payload),
+                                                &b, &alloc, &b_size, 0)) {
+                                log_error(OFSfmt": LZ4 decompression failed", offset);
+                                return -EBADMSG;
+                        }
+
+                        h2 = hash64(b, b_size);
+#else
+                        log_error("XZ compression is not supported");
                         return -EPROTONOSUPPORT;
 #endif
                 } else
@@ -249,12 +261,12 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
                 }
 
                 for (i = 0; i < journal_file_entry_array_n_items(o); i++)
-                        if (o->entry_array.items[i] != 0 &&
-                            !VALID64(o->entry_array.items[i])) {
+                        if (le64toh(o->entry_array.items[i]) != 0 &&
+                            !VALID64(le64toh(o->entry_array.items[i]))) {
                                 log_error(OFSfmt": invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt,
                                           offset,
                                           i, journal_file_entry_array_n_items(o),
-                                          o->entry_array.items[i]);
+                                          le64toh(o->entry_array.items[i]));
                                 return -EBADMSG;
                         }
 
@@ -789,9 +801,6 @@ int journal_file_verify(
         uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
         usec_t last_usec = 0;
         int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
-        char data_path[] = "/var/tmp/journal-data-XXXXXX",
-                entry_path[] = "/var/tmp/journal-entry-XXXXXX",
-                entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
         unsigned i;
         bool found_last;
 #ifdef HAVE_GCRYPT
@@ -812,29 +821,26 @@ int journal_file_verify(
         } else if (f->seal)
                 return -ENOKEY;
 
-        data_fd = mkostemp(data_path, O_CLOEXEC);
+        data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
         if (data_fd < 0) {
                 log_error("Failed to create data file: %m");
                 r = -errno;
                 goto fail;
         }
-        unlink(data_path);
 
-        entry_fd = mkostemp(entry_path, O_CLOEXEC);
+        entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
         if (entry_fd < 0) {
                 log_error("Failed to create entry file: %m");
                 r = -errno;
                 goto fail;
         }
-        unlink(entry_path);
 
-        entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC);
+        entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
         if (entry_array_fd < 0) {
                 log_error("Failed to create entry array file: %m");
                 r = -errno;
                 goto fail;
         }
-        unlink(entry_array_path);
 
 #ifdef HAVE_GCRYPT
         if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
@@ -885,8 +891,21 @@ int journal_file_verify(
                         goto fail;
                 }
 
-                if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
-                        log_error("Compressed object in file without compression at "OFSfmt, p);
+                if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
+                    (o->object.flags & OBJECT_COMPRESSED_LZ4)) {
+                        log_error("Objected with double compression at "OFSfmt, p);
+                        r = -EBADMSG;
+                        goto fail;
+                }
+
+                if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) {
+                        log_error("XZ compressed object in file without XZ compression at "OFSfmt, p);
+                        r = -EBADMSG;
+                        goto fail;
+                }
+
+                if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) {
+                        log_error("LZ4 compressed object in file without LZ4 compression at "OFSfmt, p);
                         r = -EBADMSG;
                         goto fail;
                 }
@@ -1232,9 +1251,9 @@ int journal_file_verify(
         mmap_cache_close_fd(f->mmap, entry_fd);
         mmap_cache_close_fd(f->mmap, entry_array_fd);
 
-        close_nointr_nofail(data_fd);
-        close_nointr_nofail(entry_fd);
-        close_nointr_nofail(entry_array_fd);
+        safe_close(data_fd);
+        safe_close(entry_fd);
+        safe_close(entry_array_fd);
 
         if (first_contained)
                 *first_contained = le64toh(f->header->head_entry_realtime);
@@ -1257,17 +1276,17 @@ fail:
 
         if (data_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, data_fd);
-                close_nointr_nofail(data_fd);
+                safe_close(data_fd);
         }
 
         if (entry_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, entry_fd);
-                close_nointr_nofail(entry_fd);
+                safe_close(entry_fd);
         }
 
         if (entry_array_fd >= 0) {
                 mmap_cache_close_fd(f->mmap, entry_array_fd);
-                close_nointr_nofail(entry_array_fd);
+                safe_close(entry_array_fd);
         }
 
         return r;