From e9deec4c62b6e47e0152c0dcf858f8c6f768a1b2 Mon Sep 17 00:00:00 2001 From: Marc Hartmayer Date: Thu, 11 Nov 2021 09:40:24 +0100 Subject: [PATCH] zdump: copy: add support for file output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is unusual to write the file output from a tool to stdout. Therefore add a positional argument to the zgetdump convert action where the output file can be specified. If no positional argument is given the output is written to stdout as before and therefore there is no change in the default behavior. If the file output already exists an error is returned. The reason for this is to avoid the situation where an existing dump is accidentally overwritten by the user. Reviewed-by: Alexander Egorenkov Signed-off-by: Marc Hartmayer Signed-off-by: Jan Höppner --- zdump/Makefile | 2 +- zdump/opts.c | 18 ++++++++++++++++++ zdump/opts.h | 2 ++ zdump/{stdout.c => output.c} | 11 +++++++---- zdump/{stdout.h => output.h} | 8 ++++---- zdump/zgetdump.8 | 2 ++ zdump/zgetdump.c | 37 ++++++++++++++++++++++++++++-------- 7 files changed, 63 insertions(+), 17 deletions(-) rename zdump/{stdout.c => output.c} (84%) rename zdump/{stdout.h => output.h} (68%) diff --git a/zdump/Makefile b/zdump/Makefile index 9120048b..1e822933 100644 --- a/zdump/Makefile +++ b/zdump/Makefile @@ -52,7 +52,7 @@ OBJECTS = zgetdump.o opts.o zg.o \ df_elf.o df_s390.o \ dt.o dt_s390sv.o dt_s390sv_ext.o \ dt_s390mv.o dt_s390mv_ext.o \ - dt_scsi.o stdout.o \ + dt_scsi.o output.o ifeq ("$(HAVE_FUSE)","0") FUSE_CFLAGS = -DHAVE_FUSE=0 -D_FILE_OFFSET_BITS=64 diff --git a/zdump/opts.c b/zdump/opts.c index f3ed219f..b82ab236 100644 --- a/zdump/opts.c +++ b/zdump/opts.c @@ -40,6 +40,7 @@ static const char optstr[] = "hvVidmus:f:X"; */ static const char help_text[] = "Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n" + " DUMP [-s SYS] [-f FMT] DUMP_FILE\n" " -m DUMP [-s SYS] [-f FMT] DIR\n" " -i DUMP [-s SYS]\n" " -d DUMPDEV\n" @@ -86,6 +87,7 @@ static void init_defaults(struct options *opts) { opts->prog_name = "zgetdump"; opts->action = ZG_ACTION_COPY; + opts->output_path = NULL; #ifdef __s390x__ opts->fmt = "elf"; #else @@ -166,6 +168,14 @@ static void device_set(struct options *opts, const char *path) opts->device = zg_strdup(path); } +/* + * Set output path + */ +static void output_set(struct options *opts, const char *path) +{ + opts->output_path = zg_strdup(path); +} + /* * Set FUSE debug options */ @@ -229,6 +239,14 @@ static void parse_pos_args(struct options *opts, char *argv[], int argc) switch (opts->action) { case ZG_ACTION_COPY: + if (pos_args == 0) + ERR_EXIT("No device or dump specified"); + if (pos_args > 2) + ERR_EXIT("Too many positional parameters specified"); + device_set(opts, argv[optind]); + if (pos_args > 1) + output_set(opts, argv[optind + 1]); + break; case ZG_ACTION_DUMP_INFO: case ZG_ACTION_DEVICE_INFO: if (pos_args == 0) diff --git a/zdump/opts.h b/zdump/opts.h index 43ddf1dd..39f1043f 100644 --- a/zdump/opts.h +++ b/zdump/opts.h @@ -18,6 +18,8 @@ struct options { int action_specified; enum zg_action action; char *device; + /* If `output_path == NULL` the output is written to `stdout` */ + const char *output_path; char *mount_point; int fmt_specified; const char *fmt; diff --git a/zdump/stdout.c b/zdump/output.c similarity index 84% rename from zdump/stdout.c rename to zdump/output.c index 1270fbf1..d2b54436 100644 --- a/zdump/stdout.c +++ b/zdump/output.c @@ -1,7 +1,7 @@ /* * zgetdump - Tool for copying and converting System z dumps * - * Write dump to standard output (stdout) + * Write dump to the file descriptor (fd) * * Copyright IBM Corp. 2001, 2017 * @@ -12,14 +12,17 @@ #include "zg.h" #include "dfi.h" #include "dfo.h" -#include "stdout.h" +#include "output.h" -int stdout_write_dump(void) +int write_dump(int fd) { const u64 output_size = dfo_size(); char buf[8UL * PAGE_SIZE]; u64 written = 0; + if (fd < 0) + ERR_EXIT("fd must be a valid file descriptor"); + if (!dfi_feat_copy()) ERR_EXIT("Copying not possible for %s dumps", dfi_name()); STDERR("Format Info:\n"); @@ -32,7 +35,7 @@ int stdout_write_dump(void) u64 cnt; cnt = dfo_read(buf, sizeof(buf)); - rc = write(STDOUT_FILENO, buf, cnt); + rc = write(fd, buf, cnt); if (rc == -1) ERR_EXIT_ERRNO("Error: Write failed"); if (rc != (ssize_t) cnt) diff --git a/zdump/stdout.h b/zdump/output.h similarity index 68% rename from zdump/stdout.h rename to zdump/output.h index aaf23b21..054fe7be 100644 --- a/zdump/stdout.h +++ b/zdump/output.h @@ -5,9 +5,9 @@ * it under the terms of the MIT license. See LICENSE for details. */ -#ifndef STDOUT_H -#define STDOUT_H +#ifndef OUTPUT_H +#define OUTPUT_H -int stdout_write_dump(void); +int write_dump(int fd); -#endif /* STDOUT_H */ +#endif /* OUTPUT_H */ diff --git a/zdump/zgetdump.8 b/zdump/zgetdump.8 index a8ca81cc..a7fd3733 100644 --- a/zdump/zgetdump.8 +++ b/zdump/zgetdump.8 @@ -8,6 +8,8 @@ zgetdump \- Tool for copying and converting System z dumps .SH SYNOPSIS \fBzgetdump\fR DUMP [-s SYS] [-f FMT] > DUMP_FILE +.br + DUMP [-s SYS] [-f FMT] DUMP_FILE .br -m DUMP [-s SYS] [-f FMT] DIR .br diff --git a/zdump/zgetdump.c b/zdump/zgetdump.c index c645e5bf..259ef0e9 100644 --- a/zdump/zgetdump.c +++ b/zdump/zgetdump.c @@ -30,7 +30,7 @@ #include "dt.h" #include "dfi.h" #include "dfo.h" -#include "stdout.h" +#include "output.h" #include "zfuse.h" /* @@ -156,18 +156,39 @@ static int do_mount(void) return rc; } -/* - * Run "copy to stdout" action - */ -static int do_copy(void) +static int open_file_for_writing(const char *output) { - int rc; + int fd; + + if (output) { + fd = open(output, + O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC, + 0600); + if (fd == -1) + ERR_EXIT_ERRNO("Could not open '%s' exclusively", output); + } else { + fd = dup(STDOUT_FILENO); + if (fd == -1) + ERR_EXIT_ERRNO("Could not dup() stdout"); + } + + return fd; +} + +/* + * Run "copy to output" action + */ +static int do_copy(const char *output) +{ + int rc, fd; if (dfi_init() != 0) ERR_EXIT("Dump cannot be processed (is not complete)"); dfo_init(); kdump_select_check(); - rc = stdout_write_dump(); + fd = open_file_for_writing(output); + rc = write_dump(fd); + close(fd); dfi_exit(); return rc; } @@ -185,7 +206,7 @@ int main(int argc, char *argv[]) switch (g.opts.action) { case ZG_ACTION_COPY: - return do_copy(); + return do_copy(g.opts.output_path); case ZG_ACTION_DUMP_INFO: return do_dump_info(); case ZG_ACTION_DEVICE_INFO: