From 5a468f2b1288a45102f736c88926270877fa2bb2 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 11 Nov 2023 17:42:43 +0100 Subject: [PATCH] Add kdump_set_filenames() as an easy API to set multiple names Provide an easier-to-use API to set descriptive file names. Signed-off-by: Petr Tesarik --- include/libkdumpfile/kdumpfile.h.in | 12 ++++ src/kdumpfile/Makefile.am | 2 +- src/kdumpfile/libkdumpfile.map | 1 + src/kdumpfile/open.c | 40 ++++++++++++ tests/fdset.c | 97 +++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) diff --git a/include/libkdumpfile/kdumpfile.h.in b/include/libkdumpfile/kdumpfile.h.in index 69fa0ad8..1379851d 100644 --- a/include/libkdumpfile/kdumpfile.h.in +++ b/include/libkdumpfile/kdumpfile.h.in @@ -317,6 +317,18 @@ uint_fast32_t kdump_d32toh(kdump_ctx_t *ctx, uint_fast32_t val); */ uint_fast64_t kdump_d64toh(kdump_ctx_t *ctx, uint_fast64_t val); +/** Set descriptive file names. + * @param ctx Dump file object. + * @param n Number of names in @p names. + * @param names Names. @c NULL means clear the name. + * @returns Error status. + * + * Set the optional file names. These names are used in error messages to give + * humans a clue which file of a multi-file dump the error is related. + */ +kdump_status kdump_set_filenames(kdump_ctx_t *ctx, unsigned n, + const char *const *names); + /** Open a set of dump files. * @param ctx Dump file object. * @param nfds Number of file descriptors in @p fds. diff --git a/src/kdumpfile/Makefile.am b/src/kdumpfile/Makefile.am index 8b57d1cb..5460a657 100644 --- a/src/kdumpfile/Makefile.am +++ b/src/kdumpfile/Makefile.am @@ -62,7 +62,7 @@ libkdumpfile_la_LIBADD = \ $(SNAPPY_LIBS) \ $(ZSTD_LIBS) -libkdumpfile_la_LDFLAGS = -version-info 10:2:0 +libkdumpfile_la_LDFLAGS = -version-info 11:0:1 if HAVE_LD_VERSION_SCRIPT libkdumpfile_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libkdumpfile.map diff --git a/src/kdumpfile/libkdumpfile.map b/src/kdumpfile/libkdumpfile.map index 2acb3f7b..4771b7aa 100644 --- a/src/kdumpfile/libkdumpfile.map +++ b/src/kdumpfile/libkdumpfile.map @@ -12,6 +12,7 @@ LIBKDUMPFILE_0 { kdump_d32toh; kdump_d64toh; + kdump_set_filenames; kdump_open_fdset; kdump_read; kdump_read_string; diff --git a/src/kdumpfile/open.c b/src/kdumpfile/open.c index bb64fd85..96f733fb 100644 --- a/src/kdumpfile/open.c +++ b/src/kdumpfile/open.c @@ -376,6 +376,46 @@ clear_all_fds(kdump_ctx_t *ctx) } } +kdump_status +kdump_set_filenames(kdump_ctx_t *ctx, unsigned n, const char *const *names) +{ + struct attr_data *dir; + kdump_status status; + + clear_error(ctx); + + if (get_num_files(ctx) < n && + (status = set_attr_number(ctx, gattr(ctx, GKI_num_files), + ATTR_PERSIST, n)) != KDUMP_OK) + return set_error(ctx, status, + "Cannot initialize file set size"); + + for (dir = gattr(ctx, GKI_dir_file_set)->dir; dir; dir = dir->next) { + struct attr_data *child; + unsigned fidx; + + if (dir->template->type != KDUMP_DIRECTORY) + continue; + fidx = dir->template->fidx; + if (fidx >= n) + continue; + child = lookup_dir_attr(ctx->dict, dir, "name", 4); + if (!child) + continue; + + if (names[fidx]) { + status = set_attr_string(ctx, child, ATTR_PERSIST, + names[fidx]); + if (status != KDUMP_OK) + return set_error(ctx, status, "%s", + err_filename(ctx, fidx)); + } else + clear_attr(ctx, child); + } + + return KDUMP_OK; +} + DEFINE_ALIAS(open_fdset); kdump_status diff --git a/tests/fdset.c b/tests/fdset.c index 8383cb67..c9dc54a8 100644 --- a/tests/fdset.c +++ b/tests/fdset.c @@ -205,6 +205,7 @@ main(int argc, char **argv) kdump_attr_t attr; kdump_ctx_t *ctx; kdump_status status; + const char *names[2]; int fd; int ret; int rc; @@ -555,6 +556,102 @@ main(int argc, char **argv) else if (rc != TEST_OK) ret = rc; + /************************************************************* + * RESET. + */ + attr.type = KDUMP_NUMBER; + attr.val.number = 0; + status = kdump_attr_ref_set(ctx, &number, &attr); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot clean up the file set: %s\n", + kdump_get_err(ctx)); + rc = TEST_FAIL; + } + + /************************************************************* + * Unset file names. + */ + names[0] = NULL; + names[1] = NULL; + status = kdump_set_filenames(ctx, 2, names); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot set file names: %s\n", + kdump_get_err(ctx)); + rc = TEST_FAIL; + } + + /* Check that fdset size is two. */ + rc = check_fileset_size(ctx, 2); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + + /* Check that file.set.0.name and file.set.1.name are unset */ + rc = check_unset_file(ctx, &fileset, "0.name", KDUMP_STRING); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + rc = check_unset_file(ctx, &fileset, "1.name", KDUMP_STRING); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + + /************************************************************* + * Real file names. + */ + names[0] = FILENAME_0; + names[1] = FILENAME_1; + status = kdump_set_filenames(ctx, 2, names); + if (status != KDUMP_OK) { + fprintf(stderr, "Cannot set file names: %s\n", + kdump_get_err(ctx)); + rc = TEST_FAIL; + } + + /* Check that fdset size is two. */ + rc = check_fileset_size(ctx, 2); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + + /* Verify file.set.0.name and file.set.1.name. */ + rc = check_filename(ctx, &fileset, "0.name", FILENAME_0); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + rc = check_filename(ctx, &fileset, "1.name", FILENAME_1); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + + /* Set the file descriptor and reduce the set to one file. */ + status = kdump_open_fd(ctx, fd); + if (status != KDUMP_OK && status != KDUMP_ERR_NOTIMPL) { + fprintf(stderr, "Cannot set dump file descriptor: %s\n", + kdump_get_err(ctx)); + return TEST_ERR; + } + + /* Verify file.set.0.name is still set. */ + rc = check_filename(ctx, &fileset, "0.name", FILENAME_0); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + + /* But file.set.1.name no longer exists. */ + rc = check_not_exist(ctx, &fileset, "1.name"); + if (rc == TEST_ERR) + return rc; + else if (rc != TEST_OK) + ret = rc; + /************************************************************* * Clean up. */