3 * Description: The zgetdump tool takes as input the dump device
4 * and writes its contents to standard output,
5 * which you can redirect to a specific file.
7 * Copyright IBM Corp. 2001, 2006.
8 * Author(s): Despina Papadopoulou
9 * Frank Munzert <munzert@de.ibm.com>
13 #include "zt_common.h"
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
21 #include <sys/utsname.h>
33 #define BLKSSZGET _IO(0x12,104)
34 #define BLKFLSBUF _IO(0x12,97)
36 #define HEADER_SIZE 4096
37 #define BLOCK_SIZE 32768
38 #define MVDUMPER_SIZE 4096
39 #define PARTN_MASK ((1 << 2) - 1)
40 #define MAGIC_BLOCK_OFFSET_ECKD 3
41 #define MAGIC_OFFSET_FBA -0x1000
42 #define HEXINSTR "\x0d\x10\x47\xf0" /* BASR + 1st halfword of BC */
45 #define VERSION_NO_DUMP_DEVICE -1
47 #define SYSFS_BUSDIR "/sys/bus/ccw/devices"
49 #if defined(__s390x__)
58 "The zgetdump tool takes as input the dump device and writes its contents\n"\
59 "to standard output, which you can redirect to a specific file.\n"\
60 "zgetdump can also check, whether a DASD device contains a valid dumper.\n\n"\
62 "Copy dump from <dumpdevice> to stdout:\n"\
63 " > zgetdump <dumpdevice>\n"\
64 "Print dump header and check if dump is valid - for single tape or DASD:\n"\
65 " > zgetdump [-i | --info] <dumpdevice>\n"\
66 "Print dump header and check if dump is valid - for all volumes of a\n"
67 "multi-volume tape dump:\n"\
68 " > zgetdump [-i | --info] [-a | --all] <dumpdevice>\n"\
69 "Check dump device:\n"\
70 " > zgetdump [-d | --device] <dasd_device>\n"\
71 "Print version info:\n"\
72 " > zgetdump [-v | --version]\n"\
74 " > zgetdump [-h | --help]\n\n"\
75 "Examples for single-volume DASD:\n"\
76 "> zgetdump -d /dev/dasdc\n"\
77 "> zgetdump -i /dev/dasdc1\n"\
78 "> zgetdump /dev/dasdc1 > dump_file\n";
82 "> zgetdump <dumpdevice>\n"\
83 "> zgetdump -i <dumpdevice>\n"\
84 "> zgetdump -i -a <dumpdevice>\n"\
85 "> zgetdump -d <device>\n"\
90 static const char version_text
[] = "zgetdump: version "RELEASE_STRING
;
92 /* Copyright notice */
93 static const char copyright_notice
[] = "Copyright IBM Corp. 2001, 2008";
95 /* global variables */
97 s390_dump_header_t header
;
98 s390_dump_end_marker_t end_marker
;
99 char read_buffer
[BLOCK_SIZE
];
100 struct timeval h_time_begin
, h_time_end
;
105 char dump_device
[PATH_MAX
];
107 /* end of definitions */
109 /* Use uname to check whether we run s390x kernel */
110 int check_kernel_mode()
112 struct utsname uname_struct
;
113 if (uname(&uname_struct
)) {
114 fprintf(stderr
, "Unable to get name and information about "
115 "current kernel. \n");
119 if (strncmp(uname_struct
.machine
, "s390x", 5) == 0) {
120 fprintf(stderr
, "=========================================="
122 fprintf(stderr
, "WARNING: You are running an s390x (ESAME) "
124 fprintf(stderr
, " Your dump tool however is s390 "
126 fprintf(stderr
, "=========================================="
132 /* Read dump tool from DASD device */
133 int read_dumper(int fd
, int32_t offset
, struct dump_tool
*buffer
, int whence
)
135 if (lseek(fd
, offset
, whence
) == -1) {
136 perror("Cannot seek on device");
139 if (read(fd
, buffer
, sizeof(struct dump_tool
)) !=
140 sizeof(struct dump_tool
)) {
141 perror("Cannot read dump tool from device");
147 /* Use stat to check whether user provided input is a block device or a
149 enum devnode_type
check_device(char *device
, int print
)
151 struct stat stat_struct
;
153 if (stat(device
, &stat_struct
)) {
154 fprintf(stderr
, "Unable to get device status for "
159 if (!(S_ISBLK(stat_struct
.st_mode
))) {
160 fprintf(stderr
, "'%s' is not a block device. \n", dump_device
);
163 if (minor(stat_struct
.st_rdev
) & PARTN_MASK
) {
165 fprintf(stderr
, "Partition '%s' (%d/%d) specified where"
166 " device is required.\n", dump_device
,
167 (unsigned short) major(stat_struct
.st_rdev
),
168 (unsigned short) minor(stat_struct
.st_rdev
));
174 /* Allocate SIZE bytes of memory. Upon success, return pointer to memory.
175 * Return NULL otherwise. */
176 void *misc_malloc(size_t size
)
180 result
= malloc(size
);
181 if (result
== NULL
) {
182 fprintf(stderr
, "Could not allocate %lld bytes of memory",
183 (unsigned long long) size
);
188 char* misc_make_path(char* dirname
, char* filename
)
193 len
= strlen(dirname
) + strlen(filename
) + 2;
194 result
= (char *) misc_malloc(len
);
197 sprintf(result
, "%s/%s", dirname
, filename
);
201 #define TEMP_DEV_MAX_RETRIES 1000
203 /* Make temporary device node for input device identified by its dev_t */
204 int make_temp_devnode(dev_t dev
, char** device_node
)
207 char* pathname
[] = { getenv("TMPDIR"), "/tmp",
208 getenv("HOME"), "." , "/"};
209 char filename
[] = "zgetdump0000";
216 mode
= S_IFBLK
| S_IRWXU
;
217 /* Try several locations as directory for the temporary device
219 for (path
=0; path
< sizeof(pathname
) / sizeof(pathname
[0]); path
++) {
220 if (pathname
[path
] == NULL
)
222 for (retry
=0; retry
< TEMP_DEV_MAX_RETRIES
; retry
++) {
223 sprintf(filename
, "zgetdump%04d", retry
);
224 result
= misc_make_path(pathname
[path
], filename
);
227 rc
= mknod(result
, mode
, dev
);
229 /* Need this test to cover 'nodev'-mounted
231 fd
= open(result
, O_RDWR
);
234 *device_node
= result
;
238 retry
= TEMP_DEV_MAX_RETRIES
;
239 } else if (errno
!= EEXIST
)
240 retry
= TEMP_DEV_MAX_RETRIES
;
244 fprintf(stderr
, "Unable to create temporary device node: %s",
249 /* Delete temporary device node and free memory allocated for device name. */
250 void free_temp_devnode(char* device_node
)
252 if (remove(device_node
)) {
253 fprintf(stderr
, "Warning: Could not remove "
254 "temporary file %s: %s",
255 device_node
, strerror(errno
));
261 int open_block_device(char *device
)
265 if (check_device(device
, 1) != IS_DEVICE
)
267 fd
= open(device
, O_RDONLY
);
269 fprintf(stderr
, "Cannot open device '%s'. \n", device
);
275 /* Check sysfs, whether a device specified by its bus id is defined and online.
276 * Find out the corresponding dev_t */
277 enum device_status
get_device_from_busid(char* bus_id
, dev_t
*device
)
279 char dev_file
[PATH_MAX
];
280 char temp_file
[PATH_MAX
];
282 struct dirent
*direntp
;
283 int fd
, minor
, major
;
286 fd1
= opendir(SYSFS_BUSDIR
);
288 fprintf(stderr
, "Could not open %s (err = %i).\n",
289 SYSFS_BUSDIR
, errno
);
290 exit(1); /* sysfs info not available */
293 snprintf(dev_file
, PATH_MAX
, "%s/%s", SYSFS_BUSDIR
, bus_id
);
294 fd1
= opendir(dev_file
);
296 return UNDEFINED
; /* device with devno does not exist */
297 snprintf(temp_file
, PATH_MAX
, "%s/online", dev_file
);
298 fd
= open(temp_file
, O_RDONLY
);
299 if (read(fd
, buffer
, 1) == -1) {
300 perror("Could not read online attribute.");
304 if (buffer
[0] != '1')
305 return OFFLINE
; /* device with devno is not online */
306 while ((direntp
= readdir(fd1
)))
307 if (strncmp(direntp
->d_name
, "block:", 6) == 0)
310 if (direntp
== NULL
) {
311 snprintf(dev_file
, PATH_MAX
, "%s/%s/block", SYSFS_BUSDIR
,
313 fd1
= opendir(dev_file
);
315 fprintf(stderr
, "Could not open %s (err = %i).\n",
319 while ((direntp
= readdir(fd1
)))
320 if (strncmp(direntp
->d_name
, "dasd", 4) == 0)
323 if (direntp
== NULL
) {
324 fprintf(stderr
, "Problem with contents of %s.\n",
329 snprintf(temp_file
, PATH_MAX
, "%s/%s/dev", dev_file
, direntp
->d_name
);
330 fd
= open(temp_file
, O_RDONLY
);
331 if (read(fd
, buffer
, sizeof(buffer
)) == -1) {
332 perror("Could not read dev file.");
336 if (sscanf(buffer
, "%i:%i", &major
, &minor
) != 2) {
337 fprintf(stderr
, "Malformed content of %s: %s\n",
341 *device
= makedev(major
, minor
);
345 /* Read dump tool, multi-volume dump parameter table, and dump header from the
346 * input dump volume. Check input dump volume for
347 * - identical dump parameter table (that is it belongs to the same dump set)
348 * - valid magic number in the dump tool
349 * - valid dump signature in the dump header
350 * and set the volume's signature accordingly */
351 int get_mvdump_volume_info(struct disk_info
*vol
, uint32_t vol_nr
, off_t offset
,
352 struct mvdump_parm_table
*table
)
357 struct dump_tool dumper
;
358 struct mvdump_parm_table vol_table
;
360 vol
->signature
= INVALID
;
361 rc
= make_temp_devnode(vol
->device
, &temp_devnode
);
364 fd
= open_block_device(temp_devnode
);
366 free_temp_devnode(temp_devnode
);
369 /* We read partition data via the device node. If another process
370 * has changed partition data via the partition node, the corresponding
371 * device node might still have old data in its buffers. Flush buffers
372 * to keep things in sync */
373 if (ioctl(fd
, BLKFLSBUF
, 0)) {
374 perror("BLKFLSBUF failed");
377 if (read_dumper(fd
, offset
, &dumper
, SEEK_SET
))
379 if (lseek(fd
, offset
+ MVDUMPER_SIZE
, SEEK_SET
) !=
380 offset
+ MVDUMPER_SIZE
) {
381 perror("Cannot seek on device");
384 n_read
= read(fd
, &vol_table
, sizeof(vol_table
));
386 perror("Cannot read multi-volume dump table");
389 /* Check whether dump table on user specified dump device is
390 * identical to the one found on this device */
391 if (memcmp(&vol_table
, table
, sizeof(vol_table
))) {
392 printf("ERROR: Orphaned multi-volume dump device '%s'\n",
396 if (lseek(fd
, vol
->start_offset
, SEEK_SET
) != vol
->start_offset
) {
397 perror("Cannot seek on device");
400 n_read
= read(fd
, &header
, HEADER_SIZE
);
402 perror("Cannot read dump header");
405 free_temp_devnode(temp_devnode
);
407 if ((header
.dh_mvdump_signature
== DUMP_MAGIC_S390
) &&
408 (strncmp(dumper
.magic
, "ZMULT64", 7) == 0)) {
409 vol
->signature
= VALID
;
410 if ((header
.dh_volnr
== vol_nr
) && (header
.dh_memory_size
!= 0))
411 vol
->signature
= ACTIVE
;
415 free_temp_devnode(temp_devnode
);
420 /* Read multi-volume dump parameter table from dump device and fill in the
421 * fields of the disk_info array */
422 int get_mvdump_info(int fd
, int block_size
, int *count
,
423 struct disk_info vol
[])
428 struct mvdump_parm_table table
;
430 offset
= MAGIC_BLOCK_OFFSET_ECKD
* block_size
+ MVDUMPER_SIZE
;
431 if (lseek(fd
, offset
, SEEK_SET
) != offset
) {
432 fprintf(stderr
, "Cannot seek on device '%s'.\n",
437 n_read
= read(fd
, &table
, sizeof(table
));
439 perror("Cannot read multi-volume dump table");
442 *count
= table
.num_param
;
443 for (i
= 0; i
< table
.num_param
; i
++) {
444 sprintf(vol
[i
].bus_id
, "0.0.%04x", table
.param
[i
].devno
);
445 vol
[i
].start_offset
= table
.param
[i
].start_blk
;
446 vol
[i
].start_offset
*= table
.param
[i
].blocksize
<< 8;
447 vol
[i
].part_size
= (table
.param
[i
].end_blk
-
448 table
.param
[i
].start_blk
+ 1);
449 vol
[i
].part_size
*= table
.param
[i
].blocksize
<< 8;
450 vol
[i
].status
= get_device_from_busid(vol
[i
].bus_id
,
452 if (vol
[i
].status
== ONLINE
) {
453 offset
= MAGIC_BLOCK_OFFSET_ECKD
*
454 table
.param
[i
].blocksize
<< 8;
455 rc
= get_mvdump_volume_info(&vol
[i
], i
, offset
,
464 /* Print dump size limit as specified in zipl -d or zipm -M */
465 void print_size_limit_info(uint64_t memory
)
467 fprintf(stderr
, "Dump size limit: ");
468 if (memory
== (uint64_t) -1)
469 fprintf(stderr
, "none\n");
471 fprintf(stderr
, "%lldMB\n", (unsigned long long) memory
/
475 /* Print multi-volume dump device information for --device option */
476 void print_mvdump_info(int version
, int count
, struct disk_info vol
[],
477 uint64_t memory
, int force
)
481 fprintf(stderr
, "'%s' is part of Version %i multi-volume dump,\n"
482 "which is spread along the following DASD volumes:\n",
483 dump_device
, version
);
484 for (i
= 0; i
< count
; i
++) {
485 switch(vol
[i
].status
) {
487 fprintf(stderr
, "%s (not defined)\n", vol
[i
].bus_id
);
490 fprintf(stderr
, "%s (offline)\n", vol
[i
].bus_id
);
493 fprintf(stderr
, "%s (online, ", vol
[i
].bus_id
);
494 if (vol
[i
].signature
== INVALID
)
495 fprintf(stderr
, "invalid)\n");
497 fprintf(stderr
, "valid)\n");
501 print_size_limit_info(memory
);
502 fprintf(stderr
, "Force option specified: ");
504 fprintf(stderr
, "yes\n");
506 fprintf(stderr
, "no\n");
509 /* Print single-volume dump device information for --device option */
510 int print_dump_info(int version
, int dumper_arch
, uint64_t memory
)
515 if (dumper_arch
== ARCH_S390
) {
516 fprintf(stderr
, "'%s' is Version %i s390 (ESA) "
517 "dump device.\n", dump_device
, version
);
518 if (check_kernel_mode())
521 fprintf(stderr
, "'%s' is Version %i s390x (ESAME) "
522 "dump device.\n", dump_device
, version
);
524 fprintf(stderr
, "'%s' is Version 0 dump device. \n",
526 print_size_limit_info(memory
);
530 /* Read dump tool on FBA disk and check its magic number */
531 int check_dump_tool_fba(int fd
, int *version
, int *arch
, uint64_t *memory
)
533 struct dump_tool dumper
;
535 if (read_dumper(fd
, MAGIC_OFFSET_FBA
, &dumper
, SEEK_END
))
537 *memory
= dumper
.mem
;
538 if (strncmp(dumper
.magic
, "ZDFBA31", 7) == 0) {
539 *version
= dumper
.version
;
541 } else if (strncmp(dumper
.magic
, "ZDFBA64", 7) == 0) {
542 *version
= dumper
.version
;
544 } else if ((memcmp(dumper
.magic
, HEXINSTR
, 4) == 0) &&
545 (dumper
.code
[0] == '\x0d') && (dumper
.code
[1] == '\xd0'))
546 /* We found basr r13,0 (old dumper) */
549 *version
= VERSION_NO_DUMP_DEVICE
;
553 /* Read dump tool on ECKD disk and check its magic number */
554 int check_dump_tool_eckd(int fd
, int *version
, int *arch
, int *dasd_mv_flag
,
555 int *block_size
, int *force_specified
,
558 struct dump_tool dumper
;
560 if (ioctl(fd
, BLKSSZGET
, block_size
)) {
561 fprintf(stderr
, "Cannot get blocksize of device %s.\n",
566 if (read_dumper(fd
, MAGIC_BLOCK_OFFSET_ECKD
* *block_size
, &dumper
,
569 *memory
= dumper
.mem
;
570 if (strncmp(dumper
.magic
, "ZECKD31", 7) == 0) {
571 *version
= dumper
.version
;
573 } else if (strncmp(dumper
.magic
, "ZECKD64", 7) == 0) {
574 *version
= dumper
.version
;
576 } else if (strncmp(dumper
.magic
, "ZMULT64", 7) == 0) {
577 *version
= dumper
.version
;
580 *force_specified
= dumper
.force
;
581 } else if ((memcmp(dumper
.magic
, HEXINSTR
, 4) == 0) &&
582 (dumper
.code
[0] == '\x0d') && (dumper
.code
[1] == '\xd0'))
583 /* We found basr r13,0 (old dumper) */
586 *version
= VERSION_NO_DUMP_DEVICE
;
590 void s390_tod_to_timeval(uint64_t todval
, struct timeval
*xtime
)
592 /* adjust todclock to 1970 */
593 todval
-= 0x8126d60e46000000LL
- (0x3c26700LL
* 1000000 * 4096);
596 xtime
->tv_sec
= todval
/ 1000000;
597 xtime
->tv_usec
= todval
% 1000000;
601 int open_dump(char *pathname
)
605 fd
= open(pathname
, O_RDONLY
);
607 perror("Cannot open dump device");
610 fprintf(stderr
, "Dump device: %s\n", pathname
);
615 /* check if device is dasd or tape */
616 enum dump_type
dev_type(int fd
)
618 struct mtget mymtget
;
620 if (ioctl(fd
, MTIOCGET
, &mymtget
) == -1)
626 /* print lkcd header information */
627 void print_lkcd_header(int fd
)
629 dump_header_4_1_t dump_header
;
631 lseek(fd
, 0, SEEK_SET
);
632 if (read(fd
, &dump_header
, sizeof(dump_header
)) == -1) {
633 perror("Could not read dump header.");
636 fprintf(stderr
, "\nThis is a lkcd dump:\n\n");
638 "Memory start : 0x%"FMT64
"x\n", dump_header
.dh_memory_start
);
640 "Memory end : 0x%"FMT64
"x\n", dump_header
.dh_memory_end
);
642 "Physical memory: %"FMT64
"d\n", dump_header
.dh_memory_size
);
644 "Panic string : %s\n", dump_header
.dh_panic_string
);
646 "Number of pages: %d\n", dump_header
.dh_num_dump_pages
);
648 "Page size : %d\n", dump_header
.dh_dump_page_size
);
650 "Magic number : 0x%"FMT64
"x\n", dump_header
.dh_magic_number
);
652 "Version number : %d\n", dump_header
.dh_version
);
655 void print_s390_header(enum dump_type d_type
)
657 s390_tod_to_timeval(header
.dh_tod
, &h_time_begin
);
659 /* as from version 2 of the dump tools */
660 /* volume numbers are used */
662 if ((d_type
== IS_TAPE
) && (header
.dh_version
>= 2)) {
663 fprintf(stderr
, "\nTape Volume %i", header
.dh_volnr
);
664 if (header
.dh_volnr
!= 0)
665 fprintf(stderr
, " of a multi volume dump.\n");
667 fprintf(stderr
, "\n");
670 /* don't print header */
671 /* for all subsequent tapes/disks */
672 /* of a multi-volume tape/disk dump */
674 if ((d_type
== IS_DASD
) || (header
.dh_volnr
== 0)) {
675 if (header
.dh_magic_number
!= DUMP_MAGIC_S390
) {
676 fprintf(stderr
, "===================================="
677 "===============\n");
678 fprintf(stderr
, "WARNING: This does not look like a "
679 "valid s390 dump!\n");
680 fprintf(stderr
, "===================================="
681 "===============\n");
683 fprintf(stderr
, "\n>>> Dump header information <<<\n");
684 fprintf(stderr
, "Dump created on: %s\n",
685 ctime(&h_time_begin
.tv_sec
));
686 fprintf(stderr
, "Magic number:\t 0x%"FMT64
"x\n",
687 header
.dh_magic_number
);
688 fprintf(stderr
, "Version number:\t %d\n", header
.dh_version
);
689 fprintf(stderr
, "Header size:\t %d\n", header
.dh_header_size
);
690 fprintf(stderr
, "Page size:\t %d\n", header
.dh_page_size
);
691 fprintf(stderr
, "Dumped memory:\t %"FMT64
"d\n",
692 header
.dh_memory_size
);
693 fprintf(stderr
, "Dumped pages:\t %u\n", header
.dh_num_pages
);
694 if (header
.dh_version
>= 3) {
695 fprintf(stderr
, "Real memory:\t %"FMT64
"d\n",
696 header
.dh_real_memory_size
);
698 fprintf(stderr
, "cpu id:\t\t 0x%"FMT64
"x\n", header
.dh_cpu_id
);
699 if (header
.dh_version
>= 2) {
700 switch (header
.dh_arch
) {
701 case 1: fprintf(stderr
, "System Arch:\t s390 (ESA)\n");
703 case 2: fprintf(stderr
,
704 "System Arch:\t s390x (ESAME)\n");
707 fprintf(stderr
, "System Arch:\t <unknown>\n");
710 switch (header
.dh_build_arch
) {
711 case 1: fprintf(stderr
, "Build Arch:\t s390 (ESA)\n");
713 case 2: fprintf(stderr
,
714 "Build Arch:\t s390x (ESAME)\n");
717 fprintf(stderr
, "Build Arch:\t <unknown>\n");
721 fprintf(stderr
, ">>> End of Dump header <<<\n\n");
725 /* print header information */
726 void get_header(int fd
)
730 n_read
= read(fd
, &header
, HEADER_SIZE
);
732 perror("Cannot read dump header");
738 /* copy header to stdout */
743 memcpy(read_buffer
, &header
, sizeof(header
));
744 rc
= write(STDOUT_FILENO
, read_buffer
, header
.dh_header_size
);
746 perror("\nwrite failed");
749 if (rc
< header
.dh_header_size
) {
750 fprintf(stderr
, "\nwrite failed: No space left on device\n");
755 /* copy partition containing multi-volume dump data to stdout */
756 int mvdump_copy(int fd
, uint64_t partsize
, uint64_t *totalsize
)
758 ssize_t n_read
, n_written
;
759 uint64_t part_offset
;
763 part_offset
= HEADER_SIZE
;
765 count
= MIN(header
.dh_memory_size
- *totalsize
, BLOCK_SIZE
);
766 if (count
< BLOCK_SIZE
)
768 if (partsize
- part_offset
< count
) {
769 count
= partsize
- part_offset
;
772 n_read
= read(fd
, read_buffer
, count
);
774 perror("\nread failed");
777 n_read
= (n_read
>> 12) << 12;
778 n_written
= write(STDOUT_FILENO
, read_buffer
, n_read
);
779 if (n_written
== -1) {
780 perror("\nwrite failed");
783 if (n_written
< n_read
) {
784 fprintf(stderr
, "\nwrite failed: "
785 "No space left on device\n");
788 part_offset
+= n_written
;
789 *totalsize
+= n_written
;
790 if (part_offset
% (header
.dh_memory_size
/ 32) == HEADER_SIZE
)
791 fprintf(stderr
, ".");
793 fprintf(stderr
, "\n");
797 /* copy the dump to stdout */
798 int get_dump(int fd
, int d_type
)
801 ssize_t n_read
, n_written
;
806 if (d_type
== IS_DASD
) {
809 n_read
= read(fd
, read_buffer
, BLOCK_SIZE
);
810 n_written
= write(STDOUT_FILENO
, read_buffer
, n_read
);
811 if (n_written
== -1) {
812 perror("\nwrite failed");
815 if (n_written
< n_read
) {
816 fprintf(stderr
, "\nwrite failed: "
817 "No space left on device\n");
821 if (i
% (header
.dh_memory_size
/ 32) == 0)
822 fprintf(stderr
, ".");
823 } while (i
< header
.dh_memory_size
&& n_read
!= 0
825 } else if (d_type
== IS_TAPE
) {
826 /* write to stdout while not ENDOFVOL or DUMP_END */
827 if (header
.dh_volnr
!= 0)
828 fprintf(stderr
, "Reading dump content ");
829 for (i
= 0; i
< (header
.dh_memory_size
/BLOCK_SIZE
); i
++) {
830 n_read
= read(fd
, read_buffer
, BLOCK_SIZE
);
831 if (i
% ((header
.dh_memory_size
/BLOCK_SIZE
) / 32) == 0)
832 fprintf(stderr
, ".");
833 if (strncmp(read_buffer
, "ENDOFVOL", 8) == 0) {
834 fprintf(stderr
, "\nEnd of Volume reached.\n");
837 } else if (strncmp(read_buffer
, "DUMP_END", 8) == 0) {
841 n_written
= write(STDOUT_FILENO
, read_buffer
,
843 if (n_written
== -1) {
844 perror("\nwrite failed");
847 if (n_written
< n_read
) {
848 fprintf(stderr
, "\nwrite failed: "
849 "No space left on device\n");
855 /* we go back a record, so dump_end_times gets called */
857 mymtop
.mt_op
= MTBSR
;
858 bsr
= ioctl(fd
, MTIOCTOP
, &mymtop
);
861 "Tape operation MTBSR failed.\n");
869 /* check for DUMP_END and see */
870 /* if dump ended after it started (!!!) */
871 int dump_end_times(int fd
)
875 if (read(fd
, &end_marker
, sizeof(end_marker
)) == -1) {
876 perror("Could not read end marker.");
879 s390_tod_to_timeval(end_marker
.end_time
, &h_time_end
);
880 if ((strncmp(end_marker
.end_string
, "DUMP_END", 8) == 0) &&
881 ((h_time_end
.tv_sec
- h_time_begin
.tv_sec
) >= 0)) {
882 fprintf(stderr
, "\nDump ended on:\t %s\n",
883 ctime(&h_time_end
.tv_sec
));
890 int check_and_write_end_marker(int fd
)
892 if (dump_end_times(fd
) == 0) {
894 rc
= write(STDOUT_FILENO
, &end_marker
,
897 perror("\nwrite failed");
900 if (rc
< (ssize_t
) sizeof(end_marker
)) {
901 fprintf(stderr
, "\nwrite failed: "
902 "No space left on device\n");
905 fprintf(stderr
, "\nDump End Marker found: "
906 "this dump is valid.\n");
909 fprintf(stderr
, "\nThis dump is NOT valid.\n");
914 /* if a tape is part of the dump (not the last) */
915 /* it should have and ENDOFVOL marker */
920 ret
= strncmp(end_marker
.end_string
, "ENDOFVOL", 8);
924 /* position the tape in front of an end marker */
925 /* with FSFM and BSR */
926 void tape_forwards(int fd
)
932 mymtop
.mt_op
= MTFSFM
;
933 ret
= ioctl(fd
, MTIOCTOP
, &mymtop
);
935 fprintf(stderr
, "Tape operation FSFM failed.\n");
940 mymtop
.mt_op
= MTBSR
;
941 ret
= ioctl(fd
, MTIOCTOP
, &mymtop
);
943 fprintf(stderr
, "Tape operation BSR failed.\n");
948 /* put current tape offline */
949 /* load & rewind next tape */
950 void load_next(int fd
)
956 mymtop
.mt_op
= MTOFFL
;
957 ret
= ioctl(fd
, MTIOCTOP
, &mymtop
);
959 fprintf(stderr
, "Tape operation OFFL failed.\n");
964 mymtop
.mt_op
= MTLOAD
;
965 ret
= ioctl(fd
, MTIOCTOP
, &mymtop
);
967 fprintf(stderr
, "Tape operation LOAD failed.\n");
970 fprintf(stderr
, "done\n");
973 mymtop
.mt_op
= MTREW
;
974 ret
= ioctl(fd
, MTIOCTOP
, &mymtop
);
976 fprintf(stderr
, "Tape operation REW failed.\n");
981 /* parse the commandline options */
982 void parse_opts(int argc
, char *argv
[])
985 static struct option long_options
[] = {
986 {"info", no_argument
, 0, 'i'},
987 {"help", no_argument
, 0, 'h'},
988 {"version", no_argument
, 0, 'v'},
989 {"all", no_argument
, 0, 'a'},
990 {"device", no_argument
, 0, 'd'},
993 static const char option_string
[] = "iavhd";
995 while ((opt
= getopt_long(argc
, argv
, option_string
, long_options
,
1011 printf("%s\n", version_text
);
1012 printf("%s\n", copyright_notice
);
1015 fprintf(stderr
, "Try 'zgetdump --help' for more"
1021 /* check if -a and -i options are used correctly and check */
1022 /* if devicename has been specified */
1024 if ((option_a_set
&& !option_i_set
) || (optind
!= argc
-1)
1025 || (option_d_set
&& option_i_set
)) {
1031 strcpy(dump_device
, argv
[optind
]);
1034 /* Loop along all involved volumes (dump partitions) and either check (for
1035 * option --info) or pick up dump data */
1036 int mvdump_check_or_copy(int vol_count
, struct disk_info vol
[])
1039 uint64_t data_size
, total_size
= 0;
1042 for (i
= 0; i
< vol_count
; i
++) {
1043 if (vol
[i
].status
!= ONLINE
) {
1044 fprintf(stderr
, "============================="
1045 "=======================\n");
1046 fprintf(stderr
, "ERROR: Dump device %s is not "
1047 "available.\n", vol
[i
].bus_id
);
1048 fprintf(stderr
, "============================="
1049 "=======================\n");
1052 if (vol
[i
].signature
!= ACTIVE
) {
1053 fprintf(stderr
, "============================="
1054 "=======================\n");
1055 fprintf(stderr
, "ERROR: Invalid dump data on "
1056 "%s.\n", vol
[i
].bus_id
);
1057 fprintf(stderr
, "============================="
1058 "=======================\n");
1061 if (make_temp_devnode(vol
[i
].device
, &temp_devnode
))
1063 fd
= open_block_device(temp_devnode
);
1065 free_temp_devnode(temp_devnode
);
1068 if (lseek(fd
, vol
[i
].start_offset
, SEEK_SET
) !=
1069 vol
[i
].start_offset
) {
1070 perror("Cannot seek on device");
1074 print_s390_header(IS_MULT_DASD
);
1075 fprintf(stderr
, "\nMulti-volume dump: Disk %i (of %i)\n",
1078 data_size
= ((vol
[i
].part_size
>> 12) << 12) -
1080 if (total_size
+ data_size
> header
.dh_memory_size
) {
1081 if (lseek(fd
, header
.dh_memory_size
-
1082 total_size
, SEEK_CUR
) == -1) {
1083 perror("Cannot seek on device");
1086 fprintf(stderr
, "Checking dump contents on "
1087 "%s\n", vol
[i
].bus_id
);
1088 if (dump_end_times(fd
) == 0) {
1089 fprintf(stderr
, "Dump End Marker "
1091 "this dump is valid.\n\n");
1095 fprintf(stderr
, "Dump End Marker not "
1097 "this dump is NOT valid.\n\n");
1100 } else if (i
== vol_count
- 1) {
1101 fprintf(stderr
, "Dump End Marker not found: "
1102 "this dump is NOT valid.\n\n");
1105 total_size
+= data_size
;
1106 fprintf(stderr
, "Skipping dump contents on %s\n",
1111 fprintf(stderr
, "Reading dump contents from %s",
1113 if (mvdump_copy(fd
, vol
[i
].part_size
, &total_size
))
1115 if ((i
== vol_count
- 1) ||
1116 (total_size
== header
.dh_memory_size
)) {
1117 rc
= check_and_write_end_marker(fd
);
1121 free_temp_devnode(temp_devnode
);
1126 free_temp_devnode(temp_devnode
);
1131 int main(int argc
, char *argv
[])
1133 uint64_t cur_time
, size_limit
;
1134 int vol_count
, fd
= -1;
1135 int version
, dumper_arch
, dasd_mv_flag
= 0, block_size
, rc
;
1136 int force_specified
= 0;
1137 enum dump_type d_type
;
1138 enum devnode_type type
;
1139 struct disk_info vol
[MAX_DUMP_VOLUMES
];
1143 parse_opts(argc
, argv
);
1146 fd
= open_block_device(dump_device
);
1151 rc
= check_dump_tool_fba(fd
, &version
, &dumper_arch
,
1156 goto is_dump_device
;
1158 rc
= check_dump_tool_eckd(fd
, &version
, &dumper_arch
,
1159 &dasd_mv_flag
, &block_size
,
1165 goto is_dump_device
;
1166 fprintf(stderr
, "'%s' is no dump device.\n", dump_device
);
1172 rc
= get_mvdump_info(fd
, block_size
, &vol_count
, vol
);
1175 print_mvdump_info(version
, vol_count
, vol
, size_limit
,
1178 rc
= print_dump_info(version
, dumper_arch
,
1180 goto out
; /* do not consider any other options */
1183 fd
= open_dump(dump_device
);
1185 d_type
= dev_type(fd
);
1186 if ((d_type
== IS_DASD
) &&
1187 ((header
.dh_magic_number
== DUMP_MAGIC_LKCD
)
1188 || (header
.dh_magic_number
== DUMP_MAGIC_LIVE
))) {
1189 print_lkcd_header(fd
);
1192 if (d_type
!= IS_TAPE
) {
1193 type
= check_device(dump_device
, 0);
1194 if (type
== IS_DEVICE
) {
1195 /* This is a valid block device node, no partition */
1196 rc
= check_dump_tool_eckd(fd
, &version
, &dumper_arch
,
1197 &dasd_mv_flag
, &block_size
,
1202 if (!dasd_mv_flag
) {
1203 fprintf(stderr
, "Device '%s' specified where"
1204 " partition is required.\n", dump_device
);
1208 d_type
= IS_MULT_DASD
;
1209 } else if ((type
== IS_PARTITION
) &&
1210 (header
.dh_mvdump_signature
== DUMP_MAGIC_S390
)) {
1211 fprintf(stderr
, "'%s' is a multi-volume dump "
1212 "partition.\nSpecify the corresponding device "
1213 "node instead.\n", dump_device
);
1220 rc
= get_mvdump_info(fd
, block_size
, &vol_count
, vol
);
1223 rc
= mvdump_check_or_copy(vol_count
, vol
);
1227 if (!option_i_set
) { /* copy the dump to stdout */
1228 print_s390_header(d_type
);
1230 fprintf(stderr
, "Reading dump content ");
1232 /* now get_dump returns 1 for all */
1233 /* except the last tape of a multi-volume dump */
1235 while (get_dump(fd
, d_type
) == 1) {
1236 fprintf(stderr
, "\nWaiting for next volume to be "
1240 print_s390_header(d_type
);
1243 /* if dev is DASD and dump is copied */
1244 /* check if the dump is valid */
1246 if (d_type
== IS_DASD
)
1247 lseek(fd
, header
.dh_header_size
+ header
.dh_memory_size
,
1250 if (!check_and_write_end_marker(fd
))
1252 } else if (!option_a_set
) { /* "-i" option */
1253 fprintf(stderr
, "\n> \"zgetdump -i\" checks if a dump on "
1255 fprintf(stderr
, "> a dasd volume or single tape is valid.\n");
1256 fprintf(stderr
, "> If the tape is part of a multi-volume tape "
1258 fprintf(stderr
, "> it checks if it is a valid portion of "
1260 print_s390_header(d_type
);
1261 if (d_type
== IS_DASD
)
1263 header
.dh_header_size
+ header
.dh_memory_size
,
1266 fprintf(stderr
, "Checking if the dump is valid - "
1267 "this might take a while...\n");
1270 if (dump_end_times(fd
) == 0) {
1271 fprintf(stderr
, "Dump End Marker found: ");
1272 if (header
.dh_volnr
!= 0)
1273 fprintf(stderr
, "this is a valid part of "
1276 fprintf(stderr
, "this dump is valid.\n\n");
1278 } else if (d_type
== IS_DASD
) {
1279 fprintf(stderr
, "Dump End Marker not found: "
1280 "this dump is NOT valid.\n\n");
1284 fprintf(stderr
, "Checking for End of Volume...\n");
1285 if (vol_end() != 0) {
1286 fprintf(stderr
, "End of Volume not found: "
1287 "this dump is NOT valid.\n\n");
1291 fprintf(stderr
, "Reached End of Volume %i of a "
1292 "multi-volume tape dump.\n", header
.dh_volnr
);
1293 fprintf(stderr
, "This part of the dump is valid.\n\n");
1296 } else { /* "-i -a" option */
1297 fprintf(stderr
, "\n> \"zgetdump -i -a\" checks if a "
1298 "multi-volume tape dump is valid.\n");
1299 fprintf(stderr
, "> Please make sure that all volumes are "
1300 "loaded in sequence.\n");
1301 if (d_type
== IS_DASD
) {
1302 fprintf(stderr
, "\"-i -a\" is used for validation of "
1303 "multi-volume tape dumps.\n\n");
1307 print_s390_header(d_type
);
1308 cur_volnr
= header
.dh_volnr
;
1309 cur_time
= header
.dh_tod
;
1310 fprintf(stderr
, "\nChecking if the dump is valid - "
1311 "this might take a while...\n");
1313 if (dump_end_times(fd
) == 0) {
1314 fprintf(stderr
, "Dump End Marker found: "
1315 "this dump is valid.\n\n");
1317 } else if (vol_end() != 0) {
1318 fprintf(stderr
, "End of Volume not found: "
1319 "this dump is NOT valid.\n\n");
1323 while (vol_end() == 0) {
1325 fprintf(stderr
, "Reached End of Volume %i.\n",
1327 fprintf(stderr
, "Waiting for Volume %i to be "
1328 "loaded... ", cur_volnr
);
1331 print_s390_header(d_type
);
1332 if (header
.dh_volnr
!= cur_volnr
) {
1333 fprintf(stderr
, "This is not Volume %i\n",
1337 } else if (header
.dh_tod
!= cur_time
) {
1338 fprintf(stderr
, "Time stamp of this volume "
1339 "does not match the previous one.\n");
1344 if (dump_end_times(fd
) == 0) {
1345 fprintf(stderr
, "Dump End found: "
1346 "this dump is valid.\n\n");
1348 } else if (vol_end() != 0) {
1349 fprintf(stderr
, "End of Volume not found: "
1350 "this dump is NOT valid.\n\n");