/* * zgetdump - Tool for copying and converting System z dumps * * Main functions * * Copyright IBM Corp. 2001, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lib/zt_common.h" #include "opts.h" #include "zgetdump.h" #include "dt.h" #include "dfi.h" #include "dfo.h" #include "output.h" #include "zfuse.h" /* * Globals */ struct zgetdump_globals g; /* * Signal handler for exiting zgetdump (the atexit handler will do the work) */ static void sig_exit(int sig) { (void) sig; STDERR("\n"); /* E.g. to get newline after '^C' */ ERR_EXIT("Got signal %i, exiting...", sig); } /* * Install signal handler */ static void sig_handler_init(void) { struct sigaction sigact = { 0 }; /* Ignore signals SIGUSR1 and SIGUSR2 */ if (sigemptyset(&sigact.sa_mask) < 0) goto fail; sigact.sa_handler = SIG_IGN; if (sigaction(SIGUSR1, &sigact, NULL) < 0) goto fail; if (sigaction(SIGUSR2, &sigact, NULL) < 0) goto fail; /* Exit on SIGINT, SIGTERM, SIGHUP, ... */ if (sigemptyset(&sigact.sa_mask) < 0) goto fail; sigact.sa_handler = sig_exit; if (sigaction(SIGINT, &sigact, NULL) < 0) goto fail; if (sigaction(SIGTERM, &sigact, NULL) < 0) goto fail; if (sigaction(SIGHUP, &sigact, NULL) < 0) goto fail; if (sigaction(SIGQUIT, &sigact, NULL) < 0) goto fail; if (sigaction(SIGALRM, &sigact, NULL) < 0) goto fail; if (sigaction(SIGPIPE, &sigact, NULL) < 0) goto fail; return; fail: ERR_EXIT_ERRNO("Could not initialize signal handler"); } /* * Check if dump contains kdump dump and production system dump */ static void kdump_select_check(void) { static char *msg = "The dump contains \"kdump\" and \"production system\"\n" " Access \"production system\" with \"-s prod\"\n" " Access \"kdump\" with \"-s kdump\"\n" " Access the complete dump with \"-s all\"\n" " Send both dumps to your service organization"; if (g.opts.select_specified) return; if (!dfi_kdump_base()) return; ERR_EXIT("%s", msg); } static int dfi_init_error(int rc) { if (rc == -ENOKEY) { if (g.opts.key_path) ERR("Cannot read key: '%s'", g.opts.key_path); else ERR("No key for dump decryption provided."); opts_print_usage(g.opts.prog_name); } else { STDERR("Dump cannot be processed (is not complete)\n"); } return 1; } /* * Run "--umount" action */ static int do_umount(void) { zfuse_umount(); return 0; } /* * Run "--device" action */ static int do_device_info(void) { dt_init(); dt_info_print(); return 0; } /* * Run "--info" action */ static int do_dump_info(void) { int rc; rc = dfi_init(); if (rc != 0) { dfi_info_print(); STDERR("\n"); return dfi_init_error(rc); } kdump_select_check(); dfi_info_print(); dfi_exit(); return 0; } /* * Run "--mount" action */ static int do_mount(void) { int rc; rc = dfi_init(); if (rc != 0) return dfi_init_error(rc); dfo_init(); kdump_select_check(); rc = zfuse_mount_dump(); dfi_exit(); return rc; } static FILE *open_file_for_writing(const char *output) { FILE *stream; 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"); } stream = fdopen(fd, "w"); if (!stream) ERR_EXIT_ERRNO("Could not fdopen()"); fd = -1; return stream; } /* * Run "copy to output" action */ static int do_copy(const char *output) { FILE *stream; int rc; rc = dfi_init(); if (rc != 0) return dfi_init_error(rc); dfo_init(); kdump_select_check(); stream = open_file_for_writing(output); rc = write_dump(stream); fclose(stream); dfi_exit(); return rc; } /* * The zgetdump main function */ int main(int argc, char *argv[]) { sig_handler_init(); opts_parse(argc, argv, &g.opts); if (dfo_set(g.opts.fmt) != 0) ERR_EXIT("Invalid target format \"%s\" specified", g.opts.fmt); switch (g.opts.action) { case ZG_ACTION_COPY: return do_copy(g.opts.output_path); case ZG_ACTION_DUMP_INFO: return do_dump_info(); case ZG_ACTION_DEVICE_INFO: return do_device_info(); case ZG_ACTION_MOUNT: return do_mount(); case ZG_ACTION_UMOUNT: return do_umount(); } ABORT("Invalid action: %i", g.opts.action); }