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: