zdump: copy: add support for file output

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 <egorenar@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Marc Hartmayer
2021-11-11 09:40:24 +01:00
committed by Jan Höppner
parent d60b7770fd
commit e9deec4c62
7 changed files with 63 additions and 17 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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

View File

@@ -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: