mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zdump/opts: Make parsing of command line arguments testable
Make the C module responsible for the parsing of command-line arguments independent of other global variables. This improves its testability. Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
1005e7be7e
commit
df338a3bac
226
zdump/opts.c
226
zdump/opts.c
@@ -17,43 +17,59 @@
|
||||
#include "lib/zt_common.h"
|
||||
#include "lib/util_log.h"
|
||||
|
||||
#include "zgetdump.h"
|
||||
#include "opts.h"
|
||||
#include "dfo.h"
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"info", no_argument, NULL, 'i'},
|
||||
{"device", no_argument, NULL, 'd'},
|
||||
{"mount", no_argument, NULL, 'm'},
|
||||
{"umount", no_argument, NULL, 'u'},
|
||||
{"fmt", required_argument, NULL, 'f'},
|
||||
{"select", required_argument, NULL, 's'},
|
||||
{"debug", no_argument, NULL, 'X'},
|
||||
{"verbose", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
static const char optstr[] = "hvVidmus:f:X";
|
||||
|
||||
/*
|
||||
* Text for --help option
|
||||
*/
|
||||
static char help_text[] =
|
||||
"Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n"
|
||||
" -m DUMP [-s SYS] [-f FMT] DIR\n"
|
||||
" -i DUMP [-s SYS]\n"
|
||||
" -d DUMPDEV\n"
|
||||
" -u DIR\n"
|
||||
"\n"
|
||||
"The zgetdump tool can read different dump formats from a dump device or from\n"
|
||||
"a dump file. You can use zgetdump to:\n"
|
||||
"\n"
|
||||
" - Write the dump content to standard output or to a file\n"
|
||||
" - Mount the dump content to a Linux directory\n"
|
||||
" - Convert a dump to a different dump format\n"
|
||||
" - Check if a dump is valid\n"
|
||||
" - Check if a DASD contains a valid dump tool.\n"
|
||||
"\n"
|
||||
"In the syntax description, DUMP specifies a dump device or dump file to be\n"
|
||||
"read. The following options are available:\n"
|
||||
"\n"
|
||||
"-m, --mount Mount DUMP to mount point DIR\n"
|
||||
"-u, --umount Unmount dump from mount point DIR\n"
|
||||
"-i, --info Print DUMP information\n"
|
||||
"-f, --fmt Specify target dump format FMT (\"elf\" or \"s390\")\n"
|
||||
"-s, --select Select system data SYS (\"kdump\", \"prod\", or \"all\")\n"
|
||||
"-d, --device Print DUMPDEV (dump device) information\n"
|
||||
"-v, --version Print version information, then exit\n"
|
||||
"-V, --verbose Print verbose messages to stdout. Repeat this option\n"
|
||||
" for increased verbosity from just error messages to\n"
|
||||
" also include warning, information, debug, and trace\n"
|
||||
" messages. This option is intended for debugging\n"
|
||||
"-h, --help Print this help, then exit\n";
|
||||
static const char help_text[] =
|
||||
"Usage: zgetdump DUMP [-s SYS] [-f FMT] > DUMP_FILE\n"
|
||||
" -m DUMP [-s SYS] [-f FMT] DIR\n"
|
||||
" -i DUMP [-s SYS]\n"
|
||||
" -d DUMPDEV\n"
|
||||
" -u DIR\n"
|
||||
"\n"
|
||||
"The zgetdump tool can read different dump formats from a dump device or from\n"
|
||||
"a dump file. You can use zgetdump to:\n"
|
||||
"\n"
|
||||
" - Write the dump content to standard output or to a file\n"
|
||||
" - Mount the dump content to a Linux directory\n"
|
||||
" - Convert a dump to a different dump format\n"
|
||||
" - Check if a dump is valid\n"
|
||||
" - Check if a DASD contains a valid dump tool.\n"
|
||||
"\n"
|
||||
"In the syntax description, DUMP specifies a dump device or dump file to be\n"
|
||||
"read. The following options are available:\n"
|
||||
"\n"
|
||||
"-m, --mount Mount DUMP to mount point DIR\n"
|
||||
"-u, --umount Unmount dump from mount point DIR\n"
|
||||
"-i, --info Print DUMP information\n"
|
||||
"-f, --fmt Specify target dump format FMT (\"elf\" or \"s390\")\n"
|
||||
"-s, --select Select system data SYS (\"kdump\", \"prod\", or \"all\")\n"
|
||||
"-d, --device Print DUMPDEV (dump device) information\n"
|
||||
"-v, --version Print version information, then exit\n"
|
||||
"-V, --verbose Print verbose messages to stdout. Repeat this option\n"
|
||||
" for increased verbosity from just error messages to\n"
|
||||
" also include warning, information, debug, and trace\n"
|
||||
" messages. This option is intended for debugging\n"
|
||||
"-h, --help Print this help, then exit\n";
|
||||
|
||||
static const char copyright_str[] = "Copyright IBM Corp. 2001, 2018";
|
||||
|
||||
@@ -67,27 +83,27 @@ const char *OPTS_SELECT_ALL = "all";
|
||||
/*
|
||||
* Initialize default settings
|
||||
*/
|
||||
static void init_defaults(void)
|
||||
static void init_defaults(struct options *opts)
|
||||
{
|
||||
g.prog_name = "zgetdump";
|
||||
g.opts.action = ZG_ACTION_STDOUT;
|
||||
opts->prog_name = "zgetdump";
|
||||
opts->action = ZG_ACTION_STDOUT;
|
||||
#ifdef __s390x__
|
||||
g.opts.fmt = "elf";
|
||||
opts->fmt = "elf";
|
||||
#else
|
||||
g.opts.fmt = "s390";
|
||||
opts->fmt = "s390";
|
||||
#endif
|
||||
dfo_set(g.opts.fmt);
|
||||
dfo_set(opts->fmt);
|
||||
/* Verbose logging */
|
||||
g.opts.verbose = UTIL_LOG_ERROR;
|
||||
util_log_set_level(g.opts.verbose);
|
||||
opts->verbose = UTIL_LOG_ERROR;
|
||||
util_log_set_level(opts->verbose);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print "help" hint
|
||||
*/
|
||||
static void __noreturn print_usage_exit(void)
|
||||
static void __noreturn print_usage_exit(const char *prog_name)
|
||||
{
|
||||
STDERR("Try '%s --help' for more information.\n", g.prog_name);
|
||||
STDERR("Try '%s --help' for more information.\n", prog_name);
|
||||
zg_exit(1);
|
||||
}
|
||||
|
||||
@@ -103,10 +119,10 @@ static void __noreturn print_help_exit(void)
|
||||
/*
|
||||
* Print version information
|
||||
*/
|
||||
static void __noreturn print_version_exit(void)
|
||||
static void __noreturn print_version_exit(const char *prog_name)
|
||||
{
|
||||
STDOUT("%s: Tool for copying and converting dumps version %s\n",
|
||||
g.prog_name, RELEASE_STRING);
|
||||
prog_name, RELEASE_STRING);
|
||||
STDOUT("%s\n", copyright_str);
|
||||
zg_exit(0);
|
||||
}
|
||||
@@ -114,96 +130,96 @@ static void __noreturn print_version_exit(void)
|
||||
/*
|
||||
* Set "--fmt" option
|
||||
*/
|
||||
static void fmt_set(const char *fmt)
|
||||
static void fmt_set(struct options *opts, const char *fmt)
|
||||
{
|
||||
if (dfo_set(fmt) != 0)
|
||||
ERR_EXIT("Invalid target format \"%s\" specified", fmt);
|
||||
g.opts.fmt_specified = 1;
|
||||
g.opts.fmt = fmt;
|
||||
opts->fmt_specified = 1;
|
||||
opts->fmt = fmt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set "--select" option
|
||||
*/
|
||||
static void select_set(const char *select)
|
||||
static void select_set(struct options *opts, const char *select)
|
||||
{
|
||||
if (strcmp(select, OPTS_SELECT_KDUMP) == 0)
|
||||
g.opts.select = OPTS_SELECT_KDUMP;
|
||||
opts->select = OPTS_SELECT_KDUMP;
|
||||
else if (strcmp(select, OPTS_SELECT_PROD) == 0)
|
||||
g.opts.select = OPTS_SELECT_PROD;
|
||||
opts->select = OPTS_SELECT_PROD;
|
||||
else if (strcmp(select, OPTS_SELECT_ALL) == 0)
|
||||
g.opts.select = OPTS_SELECT_ALL;
|
||||
opts->select = OPTS_SELECT_ALL;
|
||||
else
|
||||
ERR_EXIT("Invalid select argument \"%s\" specified", select);
|
||||
g.opts.select_specified = 1;
|
||||
opts->select_specified = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set mount point
|
||||
*/
|
||||
static void mount_point_set(const char *mount_point)
|
||||
static void mount_point_set(struct options *opts, const char *mount_point)
|
||||
{
|
||||
g.opts.mount_point = zg_strdup(mount_point);
|
||||
opts->mount_point = zg_strdup(mount_point);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set device
|
||||
*/
|
||||
static void device_set(const char *path)
|
||||
static void device_set(struct options *opts, const char *path)
|
||||
{
|
||||
g.opts.device = zg_strdup(path);
|
||||
opts->device = zg_strdup(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set FUSE debug options
|
||||
*/
|
||||
static void argv_fuse_set(char **argv, int argc)
|
||||
static void argv_fuse_set(struct options *opts, char **argv, int argc)
|
||||
{
|
||||
int i;
|
||||
|
||||
g.opts.argv_fuse = argv;
|
||||
g.opts.argc_fuse = argc;
|
||||
opts->argv_fuse = argv;
|
||||
opts->argc_fuse = argc;
|
||||
|
||||
STDERR_PR("Fuse Options: ");
|
||||
for (i = 0; i < argc; i++)
|
||||
STDERR("%s ", g.opts.argv_fuse[i]);
|
||||
STDERR("%s ", opts->argv_fuse[i]);
|
||||
STDERR("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Set action
|
||||
*/
|
||||
static void action_set(enum zg_action action)
|
||||
static void action_set(struct options *opts, enum zg_action action)
|
||||
{
|
||||
if (g.opts.action_specified)
|
||||
if (opts->action_specified)
|
||||
ERR_EXIT("Please specify only one of the \"-i\", \"-d\", "
|
||||
"\"-m\" or \"-u\" option");
|
||||
g.opts.action = action;
|
||||
g.opts.action_specified = 1;
|
||||
opts->action = action;
|
||||
opts->action_specified = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify option combinations
|
||||
*/
|
||||
static void verify_opts(void)
|
||||
static void verify_opts(struct options *opts)
|
||||
{
|
||||
if (g.opts.select_specified) {
|
||||
if (g.opts.action != ZG_ACTION_MOUNT &&
|
||||
g.opts.action != ZG_ACTION_STDOUT &&
|
||||
g.opts.action != ZG_ACTION_DUMP_INFO)
|
||||
if (opts->select_specified) {
|
||||
if (opts->action != ZG_ACTION_MOUNT &&
|
||||
opts->action != ZG_ACTION_STDOUT &&
|
||||
opts->action != ZG_ACTION_DUMP_INFO)
|
||||
ERR_EXIT("The \"--select\" option can only be "
|
||||
"specified for info, mount, or copy");
|
||||
}
|
||||
if (!g.opts.fmt_specified)
|
||||
if (!opts->fmt_specified)
|
||||
return;
|
||||
|
||||
if (g.opts.action == ZG_ACTION_DUMP_INFO)
|
||||
if (opts->action == ZG_ACTION_DUMP_INFO)
|
||||
ERR_EXIT("The \"--fmt\" option cannot be specified "
|
||||
"together with \"--info\"");
|
||||
if (g.opts.action == ZG_ACTION_DEVICE_INFO)
|
||||
if (opts->action == ZG_ACTION_DEVICE_INFO)
|
||||
ERR_EXIT("The \"--fmt\" option cannot be specified "
|
||||
"together with \"--device\"");
|
||||
if (g.opts.action == ZG_ACTION_UMOUNT)
|
||||
if (opts->action == ZG_ACTION_UMOUNT)
|
||||
ERR_EXIT("The \"--fmt\" option cannot be specified "
|
||||
"together with \"--umount\"");
|
||||
}
|
||||
@@ -211,36 +227,36 @@ static void verify_opts(void)
|
||||
/*
|
||||
* Parse positional arguments
|
||||
*/
|
||||
static void parse_pos_args(char *argv[], int argc)
|
||||
static void parse_pos_args(struct options *opts, char *argv[], int argc)
|
||||
{
|
||||
int pos_args = argc - optind;
|
||||
|
||||
switch (g.opts.action) {
|
||||
switch (opts->action) {
|
||||
case ZG_ACTION_STDOUT:
|
||||
case ZG_ACTION_DUMP_INFO:
|
||||
case ZG_ACTION_DEVICE_INFO:
|
||||
if (pos_args == 0)
|
||||
ERR_EXIT("No device or dump specified");
|
||||
if (pos_args > 1 && !g.opts.debug_specified)
|
||||
if (pos_args > 1 && !opts->debug_specified)
|
||||
ERR_EXIT("Too many positional parameters specified");
|
||||
device_set(argv[optind]);
|
||||
device_set(opts, argv[optind]);
|
||||
break;
|
||||
case ZG_ACTION_MOUNT:
|
||||
if (pos_args == 0)
|
||||
ERR_EXIT("No dump specified");
|
||||
if (pos_args == 1)
|
||||
ERR_EXIT("No mount point specified");
|
||||
if (pos_args > 2 && !g.opts.debug_specified)
|
||||
if (pos_args > 2 && !opts->debug_specified)
|
||||
ERR_EXIT("Too many positional parameters specified");
|
||||
device_set(argv[optind]);
|
||||
mount_point_set(argv[optind + 1]);
|
||||
if (g.opts.debug_specified && pos_args > 2)
|
||||
argv_fuse_set(&argv[optind + 2], pos_args - 2);
|
||||
device_set(opts, argv[optind]);
|
||||
mount_point_set(opts, argv[optind + 1]);
|
||||
if (opts->debug_specified && pos_args > 2)
|
||||
argv_fuse_set(opts, &argv[optind + 2], pos_args - 2);
|
||||
break;
|
||||
case ZG_ACTION_UMOUNT:
|
||||
if (pos_args == 0)
|
||||
ERR_EXIT("No mount point specified");
|
||||
mount_point_set(argv[optind]);
|
||||
mount_point_set(opts, argv[optind]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -248,60 +264,46 @@ static void parse_pos_args(char *argv[], int argc)
|
||||
/*
|
||||
* Main command line parsing function
|
||||
*/
|
||||
void opts_parse(int argc, char *argv[])
|
||||
void opts_parse(int argc, char *argv[], struct options *opts)
|
||||
{
|
||||
int opt, idx;
|
||||
static struct option long_opts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"info", no_argument, NULL, 'i'},
|
||||
{"device", no_argument, NULL, 'd'},
|
||||
{"mount", no_argument, NULL, 'm'},
|
||||
{"umount", no_argument, NULL, 'u'},
|
||||
{"fmt", required_argument, NULL, 'f'},
|
||||
{"select", required_argument, NULL, 's'},
|
||||
{"debug", no_argument, NULL, 'X'},
|
||||
{"verbose", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
};
|
||||
static const char optstr[] = "hvVidmus:f:X";
|
||||
|
||||
init_defaults();
|
||||
init_defaults(opts);
|
||||
while ((opt = getopt_long(argc, argv, optstr, long_opts, &idx)) != -1) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_help_exit();
|
||||
case 'v':
|
||||
print_version_exit();
|
||||
print_version_exit(opts->prog_name);
|
||||
case 'V':
|
||||
g.opts.verbose++;
|
||||
util_log_set_level(g.opts.verbose);
|
||||
opts->verbose++;
|
||||
util_log_set_level(opts->verbose);
|
||||
break;
|
||||
case 'i':
|
||||
action_set(ZG_ACTION_DUMP_INFO);
|
||||
action_set(opts, ZG_ACTION_DUMP_INFO);
|
||||
break;
|
||||
case 'd':
|
||||
action_set(ZG_ACTION_DEVICE_INFO);
|
||||
action_set(opts, ZG_ACTION_DEVICE_INFO);
|
||||
break;
|
||||
case 'm':
|
||||
action_set(ZG_ACTION_MOUNT);
|
||||
action_set(opts, ZG_ACTION_MOUNT);
|
||||
break;
|
||||
case 'u':
|
||||
action_set(ZG_ACTION_UMOUNT);
|
||||
action_set(opts, ZG_ACTION_UMOUNT);
|
||||
break;
|
||||
case 'f':
|
||||
fmt_set(optarg);
|
||||
fmt_set(opts, optarg);
|
||||
break;
|
||||
case 's':
|
||||
select_set(optarg);
|
||||
select_set(opts, optarg);
|
||||
break;
|
||||
case 'X':
|
||||
g.opts.debug_specified = 1;
|
||||
opts->debug_specified = 1;
|
||||
break;
|
||||
default:
|
||||
print_usage_exit();
|
||||
print_usage_exit(opts->prog_name);
|
||||
}
|
||||
}
|
||||
parse_pos_args(argv, argc);
|
||||
verify_opts();
|
||||
parse_pos_args(opts, argv, argc);
|
||||
verify_opts(opts);
|
||||
}
|
||||
|
||||
38
zdump/opts.h
Normal file
38
zdump/opts.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright IBM Corp. 2001, 2018
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef OPTS_H
|
||||
#define OPTS_H
|
||||
|
||||
#include "zg.h"
|
||||
|
||||
/*
|
||||
* zgetdump options
|
||||
*/
|
||||
struct options {
|
||||
const char *prog_name;
|
||||
int action_specified;
|
||||
enum zg_action action;
|
||||
char *device;
|
||||
char *mount_point;
|
||||
int fmt_specified;
|
||||
const char *fmt;
|
||||
int debug_specified;
|
||||
char **argv_fuse;
|
||||
int argc_fuse;
|
||||
const char *select;
|
||||
int select_specified;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
extern const char *OPTS_SELECT_KDUMP;
|
||||
extern const char *OPTS_SELECT_PROD;
|
||||
extern const char *OPTS_SELECT_ALL;
|
||||
|
||||
void opts_parse(int argc, char *argv[], struct options *opts);
|
||||
|
||||
#endif /* OPTS_H */
|
||||
@@ -177,7 +177,7 @@ static int do_stdout(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
sig_handler_init();
|
||||
opts_parse(argc, argv);
|
||||
opts_parse(argc, argv, &g.opts);
|
||||
|
||||
switch (g.opts.action) {
|
||||
case ZG_ACTION_STDOUT:
|
||||
|
||||
@@ -12,43 +12,16 @@
|
||||
#ifndef ZGETDUMP_H
|
||||
#define ZGETDUMP_H
|
||||
|
||||
#include "zg.h"
|
||||
|
||||
/*
|
||||
* zgetdump options
|
||||
*/
|
||||
struct options {
|
||||
int action_specified;
|
||||
enum zg_action action;
|
||||
char *device;
|
||||
char *mount_point;
|
||||
int fmt_specified;
|
||||
const char *fmt;
|
||||
int debug_specified;
|
||||
char **argv_fuse;
|
||||
int argc_fuse;
|
||||
const char *select;
|
||||
int select_specified;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
extern const char *OPTS_SELECT_KDUMP;
|
||||
extern const char *OPTS_SELECT_PROD;
|
||||
extern const char *OPTS_SELECT_ALL;
|
||||
#include "opts.h"
|
||||
|
||||
/*
|
||||
* zgetdump globals
|
||||
*/
|
||||
extern struct zgetdump_globals {
|
||||
struct zg_fh *fh;
|
||||
const char *prog_name;
|
||||
struct options opts;
|
||||
} g;
|
||||
|
||||
/*
|
||||
* Misc fuctions
|
||||
*/
|
||||
extern void opts_parse(int argc, char *argv[]);
|
||||
extern int stdout_write_dump(void);
|
||||
int stdout_write_dump(void);
|
||||
|
||||
#endif /* ZGETDUMP_H */
|
||||
|
||||
Reference in New Issue
Block a user