Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libkdumpfile for openSUSE:Factory 
checked in at 2023-11-06 21:14:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libkdumpfile (Old)
 and      /work/SRC/openSUSE:Factory/.libkdumpfile.new.17445 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libkdumpfile"

Mon Nov  6 21:14:40 2023 rev:23 rq:1123600 version:0.5.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/libkdumpfile/libkdumpfile.changes        
2023-07-18 22:07:33.762800604 +0200
+++ /work/SRC/openSUSE:Factory/.libkdumpfile.new.17445/libkdumpfile.changes     
2023-11-06 21:14:53.452617513 +0100
@@ -1,0 +2,6 @@
+Mon Nov  6 14:27:10 UTC 2023 - Petr Tesařík <p...@tesarici.cz>
+
+- Upgrade to libkdumpfile version 0.5.3
+  * Support flattened KDUMP format.
+
+-------------------------------------------------------------------

Old:
----
  libkdumpfile-0.5.2.tar.xz

New:
----
  libkdumpfile-0.5.3.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libkdumpfile.spec ++++++
--- /var/tmp/diff_new_pack.Zfg7W2/_old  2023-11-06 21:14:54.092641073 +0100
+++ /var/tmp/diff_new_pack.Zfg7W2/_new  2023-11-06 21:14:54.092641073 +0100
@@ -48,7 +48,7 @@
 %define oldpython python
 
 Name:           libkdumpfile
-Version:        0.5.2
+Version:        0.5.3
 Release:        0
 %if "%name" == "libkdumpfile"
 Summary:        Kernel dump file access library

++++++ libkdumpfile-0.5.2.tar.xz -> libkdumpfile-0.5.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/NEWS new/libkdumpfile-0.5.3/NEWS
--- old/libkdumpfile-0.5.2/NEWS 2023-07-17 11:30:50.000000000 +0200
+++ new/libkdumpfile-0.5.3/NEWS 2023-11-06 14:59:42.000000000 +0100
@@ -1,3 +1,7 @@
+0.5.3
+-----
+  * Support flattened KDUMP format.
+
 0.5.2
 -----
   * Full support for 32-bit Arm.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/configure.ac 
new/libkdumpfile-0.5.3/configure.ac
--- old/libkdumpfile-0.5.2/configure.ac 2023-07-17 11:30:50.000000000 +0200
+++ new/libkdumpfile-0.5.3/configure.ac 2023-11-06 14:59:42.000000000 +0100
@@ -20,7 +20,7 @@
 dnl Package release versioning
 m4_define([pkg_major_version], [0])
 m4_define([pkg_minor_version], [5])
-m4_define([pkg_micro_version], [2])
+m4_define([pkg_micro_version], [3])
 m4_define([pkg_version],
           [pkg_major_version.pkg_minor_version.pkg_micro_version])
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/src/kdumpfile/Makefile.am 
new/libkdumpfile-0.5.3/src/kdumpfile/Makefile.am
--- old/libkdumpfile-0.5.2/src/kdumpfile/Makefile.am    2023-07-17 
11:30:50.000000000 +0200
+++ new/libkdumpfile-0.5.3/src/kdumpfile/Makefile.am    2023-11-06 
14:59:42.000000000 +0100
@@ -62,7 +62,7 @@
        $(SNAPPY_LIBS)  \
        $(ZSTD_LIBS)
 
-libkdumpfile_la_LDFLAGS = -version-info 10:1:0
+libkdumpfile_la_LDFLAGS = -version-info 10:2:0
 
 if HAVE_LD_VERSION_SCRIPT
 libkdumpfile_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libkdumpfile.map
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/src/kdumpfile/diskdump.c 
new/libkdumpfile-0.5.3/src/kdumpfile/diskdump.c
--- old/libkdumpfile-0.5.2/src/kdumpfile/diskdump.c     2023-07-17 
11:30:50.000000000 +0200
+++ new/libkdumpfile-0.5.3/src/kdumpfile/diskdump.c     2023-11-06 
14:59:42.000000000 +0100
@@ -50,6 +50,27 @@
 
 /** @cond TARGET_ABI */
 
+#define MDF_SIGNATURE          "makedumpfile"
+#define MDF_SIG_LEN            16
+#define MDF_TYPE_FLAT_HEADER   1
+#define MDF_VERSION_FLAT_HEADER        1
+#define MDF_HEADER_SIZE                4096
+
+/* Flattened format header. */
+struct makedumpfile_header {
+       char    signature[MDF_SIG_LEN];
+       int64_t type;
+       int64_t version;
+} __attribute__((packed));
+
+/* Flattened segment header */
+struct makedumpfile_data_header {
+        int64_t offset;
+        int64_t buf_size;
+} __attribute__((packed));
+
+#define MDF_OFFSET_END_FLAG    (-(int64_t)1)
+
 /* The header is architecture-dependent, unfortunately */
 struct disk_dump_header_32 {
        char                    signature[SIG_LEN];     /* = "DISKDUMP" */
@@ -198,6 +219,12 @@
        /** Memory region mapping. */
        struct pfn_file_map mem_pagemap;
 
+       /** File offset mapping for flattened files. */
+       addrxlat_map_t **flatmap;
+
+       /** Differences between flattened and rearranged file offsets. */
+       off_t **flatoffs;
+
        /** Page descriptor mapping. */
        struct pfn_file_map pdmap[];
 };
@@ -226,6 +253,126 @@
 
 static void diskdump_cleanup(struct kdump_shared *shared);
 
+/** Read buffer from a flattened dump file.
+ * @param ctx   Dump file object.
+ * @param buf   Target I/O buffer.
+ * @param len   Length of data.
+ * @param fidx  Index of the file to read from.
+ * @param pos   File position.
+ * @returns     Error status.
+ *
+ * Read data from the flattened segment(s) which contain(s) @p len bytes
+ * at position @p pos after rearrangement.
+ */
+static kdump_status
+flattened_pread(kdump_ctx_t *ctx, void *buf, size_t len,
+               unsigned fidx, off_t pos)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;
+       const addrxlat_range_t *range, *end;
+       off_t off;
+
+       range = addrxlat_map_ranges(ddp->flatmap[fidx]);
+       end = range + addrxlat_map_len(ddp->flatmap[fidx]);
+       for (off = pos; range < end && off > range->endoff; ++range)
+               off -= range->endoff + 1;
+       while (range < end && len) {
+               size_t seglen;
+
+               seglen = range->endoff + 1 - off;
+               if (seglen > len)
+                       seglen = len;
+
+               if (range->meth != ADDRXLAT_SYS_METH_NONE) {
+                       off_t *flatoffs = ddp->flatoffs[fidx];
+                       kdump_status ret;
+
+                       ret = fcache_pread(ctx->shared->fcache, buf, seglen,
+                                          fidx, pos + flatoffs[range->meth]);
+                       if (ret != KDUMP_OK)
+                               return ret;
+               } else
+                       memset(buf, 0, seglen);
+
+               buf += seglen;
+               len -= seglen;
+               pos += seglen;
+               ++range;
+               off = 0;
+       }
+
+       if (len)
+               memset(buf, 0, len);
+       return KDUMP_OK;
+}
+
+/** Read buffer from a diskdump file.
+ * @param ctx   Dump file object.
+ * @param buf   Target I/O buffer.
+ * @param len   Length of data.
+ * @param fidx  Index of the file to read from.
+ * @param pos   File position.
+ * @returns     Error status.
+ *
+ * Read data from a diskdump file. If the file is flattened, interpret
+ * @p pos as if it was already rearranged.
+ */
+static inline kdump_status
+diskdump_pread(kdump_ctx_t *ctx, void *buf, size_t len,
+              unsigned fidx, off_t pos)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;
+
+       return ddp->flatmap
+               ? flattened_pread(ctx, buf, len, fidx, pos)
+               : fcache_pread(ctx->shared->fcache, buf, len, fidx, pos);
+}
+
+/** Get a contiguous data chunk from a flattened dump file.
+ * @param ctx   Dump file object.
+ * @param fch   File cache chunk, updated on success.
+ * @param len   Length of data.
+ * @param fidx  Index of the file to read from.
+ * @param pos   File position.
+ * @returns     Error status.
+ *
+ * Get a contiguous data chunk from a flattened dump file. Currently, this is
+ * implemented using a dynamically allocated buffer, even if the underlying
+ * file cache buffer might be used.
+ */
+static inline kdump_status
+flattened_get_chunk(kdump_ctx_t *ctx, struct fcache_chunk *fch,
+                   size_t len, unsigned fidx, off_t pos)
+{
+       fch->data = malloc(len);
+       if (!fch->data)
+               return KDUMP_ERR_SYSTEM;
+       fch->nent = 0;
+       return flattened_pread(ctx, fch->data, len, fidx, pos);
+}
+
+/** Get a contiguous data chunk from a diskdump file.
+ * @param ctx   Dump file object.
+ * @param fch   File cache chunk, updated on success.
+ * @param len   Length of data.
+ * @param fidx  Index of the file to read from.
+ * @param pos   File position.
+ * @returns     Error status.
+ *
+ * Get a contiguous data chunk from a diskdump file. If the file is
+ * flattened, interpret @p pos as if it was already rearranged.
+ */
+static inline kdump_status
+diskdump_get_chunk(kdump_ctx_t *ctx, struct fcache_chunk *fch,
+                  size_t len, unsigned fidx, off_t pos)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;
+
+       return ddp->flatmap
+               ? flattened_get_chunk(ctx, fch, len, fidx, pos)
+               : fcache_get_chunk(ctx->shared->fcache, fch, len, fidx, pos);
+}
+
 /** Convert a PFN to a page descriptor file offset.
  * @param pdmap  Page descriptor mapping.
  * @param pfn    Page frame number.
@@ -382,8 +529,8 @@
        }
 
        mutex_lock(&ctx->shared->cache_lock);
-       ret = fcache_pread(ctx->shared->fcache, &pd, sizeof pd,
-                          pdmap->fidx, pd_pos);
+       ret = diskdump_pread(ctx, &pd, sizeof pd,
+                            pdmap->fidx, pd_pos);
        mutex_unlock(&ctx->shared->cache_lock);
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
@@ -411,8 +558,8 @@
 
        /* read page data */
        mutex_lock(&ctx->shared->cache_lock);
-       ret = fcache_pread(ctx->shared->fcache, buf, pd.size,
-                          pdmap->fidx, pd.offset);
+       ret = diskdump_pread(ctx, buf, pd.size,
+                            pdmap->fidx, pd.offset);
        mutex_unlock(&ctx->shared->cache_lock);
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
@@ -548,7 +695,7 @@
        struct fcache_chunk fch;
        kdump_status ret;
 
-       ret = fcache_get_chunk(ctx->shared->fcache, &fch, size, 0, off);
+       ret = diskdump_get_chunk(ctx, &fch, size, 0, off);
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
                                 "Cannot read %zu note bytes at %llu",
@@ -609,8 +756,7 @@
        if (get_max_pfn(ctx) > max_bitmap_pfn)
                set_max_pfn(ctx, max_bitmap_pfn);
 
-       ret = fcache_get_chunk(ctx->shared->fcache,
-                              &fch, bitmapsize, pdmap->fidx, off);
+       ret = diskdump_get_chunk(ctx, &fch, bitmapsize, pdmap->fidx, off);
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
                                 "Cannot read %zu bytes of page bitmap"
@@ -769,8 +915,8 @@
        if (sdp->header_version < 1)
                return KDUMP_OK;
 
-       ret = fcache_pread(ctx->shared->fcache, &subhdr, sizeof subhdr,
-                          pdmap->fidx, get_page_size(ctx));
+       ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
+                            pdmap->fidx, get_page_size(ctx));
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
                                 "Cannot read subheader");
@@ -808,8 +954,8 @@
                struct pfn_file_map *pdmap = &ddp->pdmap[fidx];
                pdmap->fidx = fidx;
 
-               ret = fcache_pread(ctx->shared->fcache, dh, sizeof *dh,
-                                  fidx, 0);
+               ret = diskdump_pread(ctx, dh, sizeof *dh,
+                                    fidx, 0);
                if (ret != KDUMP_OK) {
                        ret = set_error(ctx, ret, "Cannot read header");
                        break;
@@ -875,8 +1021,8 @@
        if (sdp->header_version < 1)
                return KDUMP_OK;
 
-       ret = fcache_pread(ctx->shared->fcache, &subhdr, sizeof subhdr,
-                          pdmap->fidx, get_page_size(ctx));
+       ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
+                            pdmap->fidx, get_page_size(ctx));
        if (ret != KDUMP_OK)
                return set_error(ctx, ret,
                                 "Cannot read subheader");
@@ -937,8 +1083,8 @@
                struct pfn_file_map *pdmap = &ddp->pdmap[fidx];
                pdmap->fidx = fidx;
 
-               ret = fcache_pread(ctx->shared->fcache, dh, sizeof *dh,
-                                  fidx, 0);
+               ret = diskdump_pread(ctx, dh, sizeof *dh,
+                                    fidx, 0);
                if (ret != KDUMP_OK) {
                        ret = set_error(ctx, ret, "Cannot read header");
                        break;
@@ -999,9 +1145,8 @@
        kdump_pfn_t maxpfn;
        kdump_status status;
 
-       status = fcache_get_chunk(ctx->shared->fcache, &fch,
-                                 ddp->mem_pagemap_size, 0,
-                                 ddp->mem_pagemap_off);
+       status = diskdump_get_chunk(ctx, &fch, ddp->mem_pagemap_size,
+                                   0, ddp->mem_pagemap_off);
        if (status != KDUMP_OK)
                return set_error(ctx, status,
                                 "Cannot read %zu bytes of page bitmap"
@@ -1046,18 +1191,17 @@
        return set_attr(ctx, attr, ATTR_INVALID, &val);
 }
 
+/** Initialize diskdump private data.
+ * @param ctx  Dump file object.
+ * @returns    Error status.
+ *
+ * Allocate and initialize diskdump format private data. The private data
+ * should be eventually cleaned up by @ref diskdump_cleanup().
+ */
 static kdump_status
-open_common(kdump_ctx_t *ctx, void *hdr)
+init_private(kdump_ctx_t *ctx)
 {
-       struct disk_dump_header_32 *dh32 = hdr;
-       struct disk_dump_header_64 *dh64 = hdr;
        struct disk_dump_priv *ddp;
-       struct setup_data sd;
-       kdump_bmp_t *bmp;
-       kdump_status ret;
-
-       memset(&sd, 0, sizeof sd);
-       sd.ctx = ctx;
 
        ddp = calloc(1, sizeof(*ddp) +
                     get_num_files(ctx) * sizeof(ddp->pdmap[0]));
@@ -1072,6 +1216,21 @@
        ddp->cbuf_slot = -1;
 
        ctx->shared->fmtdata = ddp;
+       return KDUMP_OK;
+}
+
+static kdump_status
+open_common(kdump_ctx_t *ctx, void *hdr)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;;
+       struct disk_dump_header_32 *dh32 = hdr;
+       struct disk_dump_header_64 *dh64 = hdr;
+       struct setup_data sd;
+       kdump_bmp_t *bmp;
+       kdump_status ret;
+
+       memset(&sd, 0, sizeof sd);
+       sd.ctx = ctx;
 
        set_addrspace_caps(ctx->xlat, ADDRXLAT_CAPS(ADDRXLAT_MACHPHYSADDR));
 
@@ -1122,29 +1281,179 @@
        return ret;
 }
 
+#define FLATOFFS_ALLOC_INC     32
+
+/** Initialize flattened dump maps for one file.
+ * @param ctx   Dump file object.
+ * @param fidx  File index.
+ * @returns     Error status.
+ *
+ * Read all flattened segment headers from file @p fidx and initialize
+ * @p flatmap and @p flatoffs.
+ */
+static kdump_status
+init_flattened_file(kdump_ctx_t *ctx, unsigned fidx)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;
+       struct makedumpfile_data_header hdr;
+       addrxlat_map_t *flatmap;
+       off_t *flatoffs = NULL;
+       addrxlat_range_t range;
+       int64_t pos, size;
+       unsigned segidx;
+       off_t flatpos;
+       kdump_status status;
+
+       flatmap = addrxlat_map_new();
+       if (!flatmap)
+               return set_error(ctx, KDUMP_ERR_SYSTEM,
+                                "Cannot allocate %s", "flattened map");
+       ddp->flatmap[fidx] = flatmap;
+
+       segidx = 0;
+       flatpos = MDF_HEADER_SIZE;
+       for (;;) {
+               status = fcache_pread(ctx->shared->fcache, &hdr, sizeof(hdr),
+                                     fidx, flatpos);
+               if (status != KDUMP_OK)
+                       return set_error(ctx, status,
+                                        "Cannot read flattened header at %llu",
+                                        (unsigned long long) flatpos);
+               pos = be64toh(hdr.offset);
+               if (pos == MDF_OFFSET_END_FLAG)
+                       break;
+                if (pos < 0)
+                       return set_error(ctx, KDUMP_ERR_CORRUPT,
+                                        "Wrong flattened %s %"PRId64" at %llu",
+                                        "offset", pos,
+                                        (unsigned long long) flatpos);
+               size = be64toh(hdr.buf_size);
+               if (size <= 0)
+                       return set_error(ctx, KDUMP_ERR_CORRUPT,
+                                        "Wrong flattened %s %"PRId64" at %llu",
+                                        "segment size", size,
+                                        (unsigned long long) flatpos);
+
+               if ((segidx % FLATOFFS_ALLOC_INC) == 0) {
+                       unsigned newlen = segidx + FLATOFFS_ALLOC_INC;
+
+                       flatoffs = realloc(flatoffs,
+                                        sizeof(*flatoffs) * newlen);
+                       if (!flatoffs)
+                               return set_error(ctx, KDUMP_ERR_SYSTEM,
+                                                "Cannot allocate %s",
+                                                "flattened offset array");
+                       ddp->flatoffs[fidx] = flatoffs;
+               }
+               flatpos += sizeof(hdr);
+               flatoffs[segidx] = flatpos - pos;
+
+               range.endoff = size - 1;
+               range.meth = segidx;
+               if (addrxlat_map_set(flatmap, pos, &range) != ADDRXLAT_OK)
+                       return set_error(ctx, KDUMP_ERR_SYSTEM,
+                                        "Cannot allocate %s",
+                                        "flattened map entry");
+
+               ++segidx;
+               flatpos += size;
+       }
+       return KDUMP_OK;
+}
+
+/** Initialize flattened dump maps for all files.
+ * @param ctx  Dump file object.
+ * @returns    Error status.
+ *
+ * Initialize flattened dump maps for all files.
+ */
+static kdump_status
+init_flattened_maps(kdump_ctx_t *ctx)
+{
+       struct disk_dump_priv *ddp = ctx->shared->fmtdata;
+       unsigned fidx;
+       kdump_status status;
+
+       ddp->flatmap = calloc(ddp->num_files, sizeof(addrxlat_map_t *));
+       if (!ddp->flatmap)
+               return set_error(ctx, KDUMP_ERR_SYSTEM,
+                                "Cannot allocate %s", "flatmap array");
+       ddp->flatoffs = calloc(ddp->num_files, sizeof(off_t *));
+       if (!ddp->flatoffs)
+               return set_error(ctx, KDUMP_ERR_SYSTEM,
+                                "Cannot allocate %s", "flatoffs array");
+
+       for (fidx = 0; fidx < get_num_files(ctx); ++fidx) {
+               status = init_flattened_file(ctx, fidx);
+               if (status != KDUMP_OK)
+                       return set_error(ctx, status,
+                                        "Cannot rearrange file #%u", fidx);
+       }
+
+       return KDUMP_OK;
+}
+
 static kdump_status
 diskdump_probe(kdump_ctx_t *ctx)
 {
+       static const char magic_flattened[MDF_SIG_LEN] = MDF_SIGNATURE;
        static const char magic_diskdump[] =
                { 'D', 'I', 'S', 'K', 'D', 'U', 'M', 'P' };
        static const char magic_kdump[] =
                { 'K', 'D', 'U', 'M', 'P', ' ', ' ', ' ' };
 
        char hdr[sizeof(struct disk_dump_header_64)];
+       char desc[32];
        kdump_status status;
 
        status = fcache_pread(ctx->shared->fcache, hdr, sizeof hdr, 0, 0);
        if (status != KDUMP_OK)
                return set_error(ctx, status, "Cannot read dump header");
 
+       if (!memcmp(hdr, magic_flattened, sizeof magic_flattened)) {
+               struct makedumpfile_header *flathdr =
+                       (struct makedumpfile_header*) hdr;
+
+               if (be64toh(flathdr->type) != MDF_TYPE_FLAT_HEADER)
+                       return set_error(ctx, KDUMP_ERR_NOTIMPL,
+                                        "Unknown flattened %s: %" PRId64 "\n",
+                                        "type", be64toh(flathdr->type));
+               if (be64toh(flathdr->version) != MDF_VERSION_FLAT_HEADER)
+                       return set_error(ctx, KDUMP_ERR_NOTIMPL,
+                                        "Unknown flattened %s: %" PRId64 "\n",
+                                        "version", be64toh(flathdr->version));
+
+               status = init_private(ctx);
+               if (status != KDUMP_OK)
+                       return status;
+
+               status = init_flattened_maps(ctx);
+               if (status != KDUMP_OK)
+                       return status;
+
+               status = flattened_pread(ctx, &hdr, sizeof hdr, 0, 0);
+               if (status != KDUMP_OK)
+                       return set_error(ctx, status, "Cannot read dump 
header");
+               strcpy(desc, "Flattened ");
+       } else
+               desc[0] = '\0';
+
        if (!memcmp(hdr, magic_diskdump, sizeof magic_diskdump))
-               set_file_description(ctx, "Diskdump");
+               strcat(desc, "Diskdump");
        else if (!memcmp(hdr, magic_kdump, sizeof magic_kdump))
-               set_file_description(ctx, "Compressed KDUMP");
+               strcat(desc, "Compressed KDUMP");
        else
                return set_error(ctx, KDUMP_NOPROBE,
                                 "Unrecognized diskdump signature");
 
+       set_file_description(ctx, desc);
+
+       if (!ctx->shared->fmtdata) {
+               status = init_private(ctx);
+               if (status != KDUMP_OK)
+                       return status;
+       }
+
        return open_common(ctx, hdr);
 }
 
@@ -1173,6 +1482,22 @@
                }
                if (ddp->cbuf_slot >= 0)
                        per_ctx_free(shared, ddp->cbuf_slot);
+               if (ddp->flatmap) {
+                       for (fidx = 0; fidx < ddp->num_files; ++fidx) {
+                               addrxlat_map_t *flatmap = ddp->flatmap[fidx];
+                               if (flatmap)
+                                       addrxlat_map_decref(flatmap);
+                       }
+                       free(ddp->flatmap);
+               }
+               if (ddp->flatoffs) {
+                       for (fidx = 0; fidx < ddp->num_files; ++fidx) {
+                               off_t *flatoffs = ddp->flatoffs[fidx];
+                               if (flatoffs)
+                                       free(flatoffs);
+                       }
+                       free(ddp->flatoffs);
+               }
                free(ddp);
                shared->fmtdata = NULL;
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/Makefile.am 
new/libkdumpfile-0.5.3/tests/Makefile.am
--- old/libkdumpfile-0.5.2/tests/Makefile.am    2023-07-17 11:30:50.000000000 
+0200
+++ new/libkdumpfile-0.5.3/tests/Makefile.am    2023-11-06 14:59:42.000000000 
+0100
@@ -197,9 +197,11 @@
        diskdump-basic-lzo \
        diskdump-basic-snappy \
        diskdump-basic-zstd \
+       diskdump-flat-raw \
        diskdump-multiread \
        diskdump-excluded \
        diskdump-split \
+       diskdump-split-flat \
        diskdump-v6-arm \
        diskdump-v6-ia32 \
        early-version-code \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-basic 
new/libkdumpfile-0.5.3/tests/diskdump-basic
--- old/libkdumpfile-0.5.2/tests/diskdump-basic 2023-07-17 11:30:50.000000000 
+0200
+++ new/libkdumpfile-0.5.3/tests/diskdump-basic 2023-11-06 14:59:42.000000000 
+0100
@@ -14,6 +14,7 @@
 cat "$expectfile" >> "$datafile"
 
 ./mkdiskdump "$dumpfile" <<EOF
+$extraparam
 version = 6
 arch_name = x86_64
 block_size = 4096
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-flat-raw 
new/libkdumpfile-0.5.3/tests/diskdump-flat-raw
--- old/libkdumpfile-0.5.2/tests/diskdump-flat-raw      1970-01-01 
01:00:00.000000000 +0100
+++ new/libkdumpfile-0.5.3/tests/diskdump-flat-raw      2023-11-06 
14:59:42.000000000 +0100
@@ -0,0 +1,5 @@
+#! /bin/sh
+extraparam="flattened = yes"
+pageflags=raw
+. "$srcdir"/diskdump-basic
+exit 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split 
new/libkdumpfile-0.5.3/tests/diskdump-split
--- old/libkdumpfile-0.5.2/tests/diskdump-split 2023-07-17 11:30:50.000000000 
+0200
+++ new/libkdumpfile-0.5.3/tests/diskdump-split 2023-11-06 14:59:42.000000000 
+0100
@@ -1,3 +1,5 @@
+#! /bin/sh
+
 #
 # Check reading data from a split dump file
 #
@@ -142,7 +144,7 @@
 echo "Check combined page map"
 ./checkattr "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" <<EOF
 file.pagemap = bitmap: 0x1e
-memory.pagemap = bitmap: 0x1f
+memory.pagemap = bitmap: 0x3f
 EOF
 rc=$?
 if [ $rc -ne 0 ]; then
@@ -153,7 +155,7 @@
 echo "Check combined page map with files out of order"
 ./checkattr "$dumpfile.2" "$dumpfile.3" "$dumpfile.1" <<EOF
 file.pagemap = bitmap: 0x1e
-memory.pagemap = bitmap: 0x1f
+memory.pagemap = bitmap: 0x3f
 EOF
 rc=$?
 if [ $rc -ne 0 ]; then
@@ -164,7 +166,7 @@
 echo "Check combined page map with one file missing"
 ./checkattr "$dumpfile.3" "$dumpfile.1" <<EOF
 file.pagemap = bitmap: 0x1a
-memory.pagemap = bitmap: 0x1f
+memory.pagemap = bitmap: 0x3f
 EOF
 rc=$?
 if [ $rc -ne 0 ]; then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split-flat 
new/libkdumpfile-0.5.3/tests/diskdump-split-flat
--- old/libkdumpfile-0.5.2/tests/diskdump-split-flat    1970-01-01 
01:00:00.000000000 +0100
+++ new/libkdumpfile-0.5.3/tests/diskdump-split-flat    2023-11-06 
14:59:42.000000000 +0100
@@ -0,0 +1,177 @@
+#! /bin/sh
+
+#
+# Check reading data from a flattened split dump file
+#
+
+mkdir -p out || exit 99
+
+name=$( basename "$0" )
+dumpfile="out/${name}.dump"
+resultfile="out/${name}.result"
+name=${name%-flat}
+datafile="$srcdir/${name}.data"
+expectfile="$srcdir/${name}.expect"
+
+desc="
+flattened = yes
+version = 6
+arch_name = x86_64
+block_size = 4096
+phys_base = 0
+max_mapnr = 0x100
+sub_hdr_size = 1
+
+uts.sysname = Linux
+uts.nodename = test-node
+uts.release = 3.4.5-test
+uts.version = #1 SMP Fri Jan 22 14:02:42 UTC 2016 (1234567)
+uts.machine = x86_64
+uts.domainname = (none)
+
+nr_cpus = 1
+
+split = 1
+
+DATA = $datafile
+"
+
+# Create three split dump files
+
+./mkdiskdump "$dumpfile.1" <<EOF
+$desc
+start_pfn = 1
+end_pfn = 2
+DATA = $datafile
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot create diskdump file" >&2
+    exit $rc
+fi
+echo "Created split diskdump dump: $dumpfile.1"
+
+./mkdiskdump "$dumpfile.2" <<EOF
+$desc
+start_pfn = 2
+end_pfn = 3
+DATA = $datafile
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot create diskdump file" >&2
+    exit $rc
+fi
+echo "Created split diskdump dump: $dumpfile.2"
+
+./mkdiskdump "$dumpfile.3" <<EOF
+$desc
+start_pfn = 3
+end_pfn = 6
+DATA = $datafile
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot create diskdump file" >&2
+    exit $rc
+fi
+echo "Created split diskdump dump: $dumpfile.3"
+
+echo "Check that file 1 only contains PFN 1"
+./dumpdata "$dumpfile.1" 0x1000 8 > "$resultfile.1"
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot dump DISKDUMP data" >&2
+    exit $rc
+fi
+if ! diff "$expectfile.1" "$resultfile.1"; then
+    echo "Results do not match" >&2
+    exit 1
+fi
+./dumpdata "$dumpfile.1" 0x2000 8 > "$resultfile.1.err" 2>/dev/null
+rc=$?
+if [ $rc -eq 0 ]; then
+    echo "Unexpected success!" >&2
+    exit 1
+fi
+
+echo "Check that file 2 only contains PFN 2"
+./dumpdata "$dumpfile.2" 0x2000 8 > "$resultfile.2"
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot dump DISKDUMP data" >&2
+    exit $rc
+fi
+if ! diff "$expectfile.2" "$resultfile.2"; then
+    echo "Results do not match" >&2
+    exit 1
+fi
+./dumpdata "$dumpfile.2" 0x1000 8 > "$resultfile.2.err" 2>/dev/null
+rc=$?
+if [ $rc -eq 0 ]; then
+    echo "Unexpected success!" >&2
+    exit 1
+fi
+
+echo "Check that file 3 contains PFN 3 and PFN 4"
+./dumpdata "$dumpfile.3" 0x3ffc 8 > "$resultfile.3"
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot dump DISKDUMP data" >&2
+    exit $rc
+fi
+if ! diff "$expectfile.3" "$resultfile.3"; then
+    echo "Results do not match" >&2
+    exit 1
+fi
+./dumpdata "$dumpfile.3" 0x2000 8 > "$resultfile.3.err" 2>/dev/null
+rc=$?
+if [ $rc -eq 0 ]; then
+    echo "Unexpected success!" >&2
+    exit 1
+fi
+
+echo "Check that data from all three files is combined"
+./dumpdata -n3 "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" 0x1ffc 8 0x2ffc 8 
0x3ffc 8 > "$resultfile"
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Cannot dump DISKDUMP data" >&2
+    exit $rc
+fi
+if ! diff "$expectfile" "$resultfile"; then
+    echo "Results do not match" >&2
+    exit 1
+fi
+
+echo "Check combined page map"
+./checkattr "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" <<EOF
+file.pagemap = bitmap: 0x3e
+memory.pagemap = bitmap: 0x3f
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Attribute check failed" >&2
+    exit $rc
+fi
+
+echo "Check combined page map with files out of order"
+./checkattr "$dumpfile.2" "$dumpfile.3" "$dumpfile.1" <<EOF
+file.pagemap = bitmap: 0x3e
+memory.pagemap = bitmap: 0x3f
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Attribute check failed" >&2
+    exit $rc
+fi
+
+echo "Check combined page map with one file missing"
+./checkattr "$dumpfile.3" "$dumpfile.1" <<EOF
+file.pagemap = bitmap: 0x3a
+memory.pagemap = bitmap: 0x3f
+EOF
+rc=$?
+if [ $rc -ne 0 ]; then
+    echo "Attribute check failed" >&2
+    exit $rc
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split.data 
new/libkdumpfile-0.5.3/tests/diskdump-split.data
--- old/libkdumpfile-0.5.2/tests/diskdump-split.data    2023-07-17 
11:30:50.000000000 +0200
+++ new/libkdumpfile-0.5.3/tests/diskdump-split.data    2023-11-06 
14:59:42.000000000 +0100
@@ -1,3 +1,5 @@
+@0x5000 raw
+dead*2048
 @0x0000 raw
 ff*4096
 @0x1000 raw
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump.h 
new/libkdumpfile-0.5.3/tests/diskdump.h
--- old/libkdumpfile-0.5.2/tests/diskdump.h     2023-07-17 11:30:50.000000000 
+0200
+++ new/libkdumpfile-0.5.3/tests/diskdump.h     2023-11-06 14:59:42.000000000 
+0100
@@ -31,6 +31,27 @@
 
 #include <stdint.h>
 
+#define MDF_SIGNATURE          "makedumpfile"
+#define MDF_SIG_LEN            16
+#define MDF_TYPE_FLAT_HEADER   1
+#define MDF_VERSION_FLAT_HEADER        1
+#define MDF_HEADER_SIZE                4096
+
+/* Flattened format header. */
+struct makedumpfile_header {
+       char    signature[MDF_SIG_LEN];
+       int64_t type;
+       int64_t version;
+} __attribute__((packed));
+
+/* Flattened segment header */
+struct makedumpfile_data_header {
+        int64_t offset;
+        int64_t buf_size;
+} __attribute__((packed));
+
+#define MDF_OFFSET_END_FLAG    (-(int64_t)1)
+
 #define DISKDUMP_SIGNATURE             "DISKDUMP"
 #define KDUMP_SIGNATURE                        "KDUMP   "
 #define SIGNATURE_LEN                  8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/mkdiskdump.c 
new/libkdumpfile-0.5.3/tests/mkdiskdump.c
--- old/libkdumpfile-0.5.2/tests/mkdiskdump.c   2023-07-17 11:30:50.000000000 
+0200
+++ new/libkdumpfile-0.5.3/tests/mkdiskdump.c   2023-11-06 14:59:42.000000000 
+0100
@@ -32,6 +32,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <errno.h>
 
 #include "config.h"
 #include "testutil.h"
@@ -68,8 +69,6 @@
 #if USE_LZO
        lzo_bytep lzo_wrkmem;
 #endif
-
-       unsigned long skip;
 };
 
 static endian_t be;
@@ -91,6 +90,9 @@
        struct blob *blob;
 };
 
+static bool flattened;
+static unsigned long long flattened_type = MDF_TYPE_FLAT_HEADER;
+static unsigned long long flattened_version = MDF_VERSION_FLAT_HEADER;
 static char *arch_name;
 static unsigned long long compression;
 static char *signature;
@@ -134,6 +136,9 @@
 
 static const struct param param_array[] = {
        /* meta-data */
+       PARAM_YESNO("flattened", flattened),
+       PARAM_NUMBER("flattened.type", flattened_type),
+       PARAM_NUMBER("flattened.version", flattened_version),
        PARAM_STRING("arch_name", arch_name),
        PARAM_NUMBER("compression", compression),
 
@@ -218,6 +223,29 @@
 }
 
 static int
+write_chunk(FILE *f, off_t off, const void *ptr, size_t sz, const char *what)
+{
+       if (flattened) {
+               struct makedumpfile_data_header hdr = {
+                       .offset = htobe64(off),
+                       .buf_size = htobe64(sz),
+               };
+               if (fwrite(&hdr, sizeof hdr, 1, f) != 1) {
+                       perror("flattened segment header");
+                       return -1;
+               }
+       } else if (fseek(f, off, SEEK_SET) != 0) {
+               fprintf(stderr, "seek %s: %s\n", what, strerror(errno));
+               return -1;
+       }
+       if (fwrite(ptr, sz, 1, f) != 1) {
+               fprintf(stderr, "write %s: %s\n", what, strerror(errno));
+               return -1;
+       }
+       return 0;
+}
+
+static int
 writeheader_32(FILE *f)
 {
        struct timeval tv;
@@ -226,7 +254,7 @@
 
        if (gettimeofday(&tv, NULL) != 0) {
                perror("gettimeofday");
-               return -1;
+               return TEST_ERR;
        }
 
        /* initialize dump header to zero */
@@ -259,15 +287,8 @@
        hdr.current_cpu = htodump32(be, current_cpu);
        hdr.nr_cpus = htodump32(be, nr_cpus);
 
-       if (fseek(f, 0, SEEK_SET) != 0) {
-               perror("seek header");
-               return -1;
-       }
-
-       if (fwrite(&hdr, sizeof hdr, 1, f) != 1) {
-               perror("write header");
-               return -1;
-       }
+       if (write_chunk(f, 0, &hdr, sizeof hdr, "header"))
+               return TEST_ERR;
 
        subhdr.phys_base = htodump32(be, phys_base);
        subhdr.dump_level = htodump32(be, dump_level);
@@ -290,17 +311,11 @@
        subhdr.end_pfn_64 = htodump64(be, end_pfn);
        subhdr.max_mapnr_64 = htodump64(be, max_mapnr);
 
-       if (fseek(f, DISKDUMP_HEADER_BLOCKS * block_size, SEEK_SET) != 0) {
-               perror("seek subheader");
-               return -1;
-       }
-
-       if (fwrite(&subhdr, sizeof subhdr, 1, f) != 1) {
-               perror("write subheader");
-               return -1;
-       }
+       if (write_chunk(f, DISKDUMP_HEADER_BLOCKS * block_size,
+                       &subhdr, sizeof subhdr, "subheader"))
+               return TEST_ERR;
 
-       return 0;
+       return TEST_OK;
 }
 
 static int
@@ -312,7 +327,7 @@
 
        if (gettimeofday(&tv, NULL) != 0) {
                perror("gettimeofday");
-               return -1;
+               return TEST_ERR;
        }
 
        /* initialize dump header to zero */
@@ -345,15 +360,8 @@
        hdr.current_cpu = htodump32(be, current_cpu);
        hdr.nr_cpus = htodump32(be, nr_cpus);
 
-       if (fseek(f, 0, SEEK_SET) != 0) {
-               perror("seek header");
-               return -1;
-       }
-
-       if (fwrite(&hdr, sizeof hdr, 1, f) != 1) {
-               perror("write header");
-               return -1;
-       }
+       if (write_chunk(f, 0, &hdr, sizeof hdr, "header"))
+               return TEST_ERR;
 
        subhdr.phys_base = htodump64(be, phys_base);
        subhdr.dump_level = htodump32(be, dump_level);
@@ -376,17 +384,11 @@
        subhdr.end_pfn_64 = htodump64(be, end_pfn);
        subhdr.max_mapnr_64 = htodump64(be, max_mapnr);
 
-       if (fseek(f, DISKDUMP_HEADER_BLOCKS * block_size, SEEK_SET) != 0) {
-               perror("seek subheader");
-               return -1;
-       }
-
-       if (fwrite(&subhdr, sizeof subhdr, 1, f) != 1) {
-               perror("write subheader");
-               return -1;
-       }
+       if (write_chunk(f, DISKDUMP_HEADER_BLOCKS * block_size,
+                       &subhdr, sizeof subhdr, "subheader"))
+               return TEST_ERR;
 
-       return 0;
+       return TEST_OK;
 }
 
 static int
@@ -409,24 +411,11 @@
 
        pgkdump->flags = 0;
        pgkdump->compress = compress_auto;
-       pgkdump->skip = 0;
 
        p = endp;
        while (*p && isspace(*p))
                ++p;
 
-       if (!strncmp(p, "skip=", 5)) {
-               p += 5;
-               pgkdump->skip = strtoul(p, &endp, 0);
-               if (*endp && !isspace(*endp)) {
-                       fprintf(stderr, "Invalid skip: %s\n", p);
-                       return TEST_FAIL;
-               }
-               p = endp;
-               while (*p && isspace(*p))
-                       ++p;
-       }
-
        if (!*p)
                return TEST_OK;
 
@@ -682,36 +671,19 @@
                buf = pg->buf;
        }
        pd.offset = htodump64(be, dataoff);
-       pd.size = htodump32(be, buflen + pgkdump->skip);
+       pd.size = htodump32(be, buflen);
        pd.flags = htodump32(be, flags);
        pd.page_flags = htodump64(be, 0);
 
        pdidx = bitmap_index(bitmap2, pfn) - start_pdidx;
-       if (fseek(pgkdump->f, pdoff + pdidx * sizeof pd, SEEK_SET) != 0) {
-               perror("seek page desc");
+       if (write_chunk(pgkdump->f, pdoff + pdidx * sizeof pd,
+                       &pd, sizeof pd, "page desc"))
                return TEST_ERR;
-       }
-       if (fwrite(&pd, sizeof pd, 1, pgkdump->f) != 1) {
-               perror("write page desc");
-               return TEST_ERR;
-       }
 
-       if (fseek(pgkdump->f, dataoff, SEEK_SET) != 0) {
-               perror("seek page data");
+       if (write_chunk(pgkdump->f, dataoff, buf, buflen, "page data"))
                return TEST_ERR;
-       }
-       if (fwrite(buf, 1, buflen, pgkdump->f) != buflen) {
-               perror("write page data");
-               return TEST_ERR;
-       }
        dataoff += buflen;
 
-       if (pgkdump->skip &&
-           fseek(pgkdump->f, pgkdump->skip, SEEK_CUR) != 0) {
-               perror("skip page data");
-               return TEST_ERR;
-       }
-
        return TEST_OK;
 }
 
@@ -724,7 +696,7 @@
        int rc;
 
        if (!data_file)
-               return TEST_OK;
+               return writeheader(f);
 
        pgkdump.f = f;
        pgkdump.addr = 0;
@@ -779,18 +751,17 @@
        if (rc != TEST_OK)
                goto out_bitmap2;
 
-       if (fseek(f, (1 + sub_hdr_size) * block_size, SEEK_SET) != 0) {
-               perror("seek bitmap");
-               rc = TEST_ERR;
+       rc = writeheader(f);
+       if (rc != TEST_OK)
                goto out_bitmap2;
-       }
-       if (fwrite(bitmap1, block_size, bmp_blocks1, f) != bmp_blocks1) {
-               perror("write 1st bitmap");
+
+       if (write_chunk(f, (1 + sub_hdr_size) * block_size,
+                       bitmap1, block_size * bmp_blocks1, "1st bitmap")) {
                rc = TEST_ERR;
                goto out_bitmap2;
        }
-       if (fwrite(bitmap2, block_size, bmp_blocks1, f) != bmp_blocks1) {
-               perror("write 2nd bitmap");
+       if (write_chunk(f, (1 + sub_hdr_size + bmp_blocks1) * block_size,
+                       bitmap2, block_size * bmp_blocks1, "2nd bitmap")) {
                rc = TEST_ERR;
                goto out_bitmap2;
        }
@@ -827,13 +798,41 @@
 {
        int rc;
 
+       if (flattened) {
+               struct makedumpfile_header hdr = {
+                       .signature = MDF_SIGNATURE,
+                       .type = htobe64(flattened_type),
+                       .version = htobe64(flattened_version),
+               };
+               size_t remain;
+
+               if (fwrite(&hdr, sizeof hdr, 1, f) != 1) {
+                       perror("flattened header");
+                       return TEST_ERR;
+               }
+               remain = MDF_HEADER_SIZE - sizeof hdr;
+               while (remain--) {
+                       if (putc(0, f) != 0) {
+                               perror("flattened header padding");
+                               return TEST_ERR;
+                       }
+               }
+       }
+
        rc = writedata(f);
        if (rc != 0)
                return rc;
 
-       rc = writeheader(f);
-       if (rc != 0)
-               return rc;
+       if (flattened) {
+               struct makedumpfile_data_header hdr = {
+                       .offset = htobe64(MDF_OFFSET_END_FLAG),
+                       .buf_size = htobe64(MDF_OFFSET_END_FLAG),
+               };
+               if (fwrite(&hdr, sizeof hdr, 1, f) != 1) {
+                       perror("end segment header");
+                       return TEST_ERR;
+               }
+       }
 
        return 0;
 }

Reply via email to