Files
s390-tools/dasdview/dasdview.c
Jan Höppner 75e3afb6a0 libdasd: Move get_host_access_count() to libdasd
Reading DASD specific sysfs attributes should be collected in one
library. Move get_host_access_count() to libdasd/dasd_sys.

Remove the old implementation and update any user accordingly.
Also, fix the build order for zdsfs.

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2019-05-21 14:16:53 +02:00

2389 lines
68 KiB
C

/*
* dasdview - Display DASD and VTOC information or dump the contents of a DASD
*
* 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.
*/
#define _LARGEFILE64_SOURCE /* needed for unistd.h */
#define _FILE_OFFSET_BITS 64 /* needed for unistd.h */
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/version.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
#include "lib/libzds.h"
#include "lib/util_base.h"
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_sys.h"
#include "lib/vtoc.h"
#include "lib/zt_common.h"
#include "dasdview.h"
/* Characters per line */
#define DASDVIEW_CPL 16
static const struct util_prg prg = {
.desc = "Display DASD and VTOC information and dump the content of "
"a DASD to the console.\n"
"DEVICE is the node of the device (e.g. '/dev/dasda').",
.args = "DEVICE",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2001,
.pub_last = 2006,
},
UTIL_PRG_COPYRIGHT_END
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DUMP OPTIONS"),
{
.option = { NULL, no_argument, NULL, '1' },
.desc = "Show DASD content in short Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { NULL, no_argument, NULL, '2' },
.desc = "Show DASD content in detailed Hex/EBCDIC/ASCII format",
.flags = UTIL_OPT_FLAG_NOLONG,
},
{
.option = { "begin", required_argument, NULL, 'b' },
.argument = "BEGIN",
.desc = "Specify start of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
{
.option = { "size", required_argument, NULL, 's' },
.argument = "SIZE",
.desc = "Specify size of dump in kilobytes (suffix k), "
"megabytes (m), blocks (b), tracks (t), or cylinders (c)",
},
UTIL_OPT_SECTION("MISC"),
{
.option = { "characteristic", no_argument, NULL, 'c' },
.desc = "Print the characteristics of a device",
},
{
.option = { "info", no_argument, NULL, 'i' },
.desc = "Print general DASD information and geometry",
},
{
.option = { "volser", no_argument, NULL, 'j' },
.desc = "Print the volume serial number",
},
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print information about the volume label",
},
{
.option = { "vtoc", required_argument, NULL, 't' },
.argument = "SPEC",
.desc = "Print the table of content (VTOC)",
},
{
.option = { "extended", no_argument, NULL, 'x' },
.desc = "Print extended DASD information",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
/*
* Generate and print an error message based on the formatted
* text string FMT and a variable amount of extra arguments.
*/
static void zt_error_print(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(error_str, ERROR_STRING_SIZE, fmt, args);
va_end(args);
fprintf(stderr, "Error: %s\n", error_str);
}
/*
* replace special characters with dots and question marks
*/
static void dot(char label[])
{
int i;
char c;
for (i = 0; i < 16; i++) {
c = label[i];
if (c <= 0x20)
label[i] = '?';
if (c == 0x00)
label[i] = '.';
if (c == 0x60)
label[i] = '?';
if (c >= 0x7f)
label[i] = '?';
}
}
static void
dasdview_get_info(dasdview_info_t *info)
{
struct dasd_eckd_characteristics *characteristics;
int err;
err = dasd_get_geo(info->device, &info->geo);
if (err != 0) {
/* Test for unknown device in the first call to libdasd to avoid
* spitting out two different error messages to the user
*/
if (err != EBADF)
zt_error_print("dasdview: "
"Could not retrieve geo information!\n");
exit(-1);
}
if (dasd_get_blocksize(info->device, &info->blksize) != 0) {
zt_error_print("dasdview: "
"Could not retrieve blocksize information!\n");
exit(-1);
}
if (dasd_get_info(info->device, &info->dasd_info) != 0) {
zt_error_print("dasdview: "
"Could not retrieve disk information!\n");
exit(-1);
}
characteristics = (struct dasd_eckd_characteristics *)
&info->dasd_info.characteristics;
if (characteristics->no_cyl == LV_COMPAT_CYL &&
characteristics->long_no_cyl)
info->hw_cylinders = characteristics->long_no_cyl;
else
info->hw_cylinders = characteristics->no_cyl;
if (util_sys_get_dev_addr(info->device, info->busid) != 0)
info->busid_valid = 0;
else
info->busid_valid = 1;
info->raw_track_access = dasd_sys_raw_track_access(info->device);
}
static void
dasdview_parse_input(unsigned long long *p, dasdview_info_t *info, char *s)
{
unsigned long long l;
char *endp;
char suffix;
l = strtoull(s, &endp, 0);
if ((endp == s) || ((l + 1) == 0))
goto error;
if (*endp) {
if (!strchr("kmtbcKMTBC", *endp) || *(endp + 1))
goto error;
suffix = tolower(*endp);
} else {
suffix = 0;
}
if (info->raw_track_access) {
switch (suffix) {
case 't':
l *= RAWTRACKSIZE;
break;
case 'c':
l *= (unsigned long long)info->geo.heads * RAWTRACKSIZE;
break;
case 0:
if (l % RAWTRACKSIZE) {
zt_error_print("dasdview: only full tracks can"
" be accessd on devices with "
" raw_track_access enabled.\n", s);
goto error;
}
break;
default:
zt_error_print("dasdview: only types t and c are"
" allowed for devices with"
" raw_track_access enabled.\n", s);
goto error;
}
} else {
switch (suffix) {
case 'k':
l *= 1024LL;
break;
case 'm':
l *= 1024LL * 1024LL;
break;
case 't':
l *= (unsigned long long)info->blksize *
(unsigned long long)info->geo.sectors;
break;
case 'b':
l *= (unsigned long long)info->blksize;
break;
case 'c':
l *= (unsigned long long)info->blksize *
(unsigned long long)info->geo.sectors *
(unsigned long long)info->geo.heads;
break;
default:
break;
}
}
*p = l;
return;
error:
zt_error_print("dasdview: usage error\n"
"%s is not a valid begin/size value!", s);
exit(-1);
}
/*
* Print general DASD information.
*/
static void
dasdview_print_general_info(dasdview_info_t *info)
{
printf("\n--- general DASD information -----------------"
"---------------------------------\n");
printf("device node : %s\n", info->device);
#ifdef SYSFS
struct utsname buf;
unsigned char a, b, c;
char suffix[sizeof(buf.release)];
int rc;
rc = uname(&buf);
if (!rc) {
sscanf(buf.release, "%c.%c.%c-%s", &a, &b, &c, suffix);
if (KERNEL_VERSION(2, 5, 0) <= KERNEL_VERSION(a, b, c)) {
if (info->busid_valid)
printf("busid : %s\n",
info->busid);
else
printf("busid :"
" <not found>\n");
} else {
#endif
printf("device number : hex %x \tdec %d\n",
info->dasd_info.devno,
info->dasd_info.devno);
#ifdef SYSFS
}
}
#endif
printf("type : %4s\n", info->dasd_info.type);
printf("device type : hex %x \tdec %d\n",
info->dasd_info.dev_type,
info->dasd_info.dev_type);
printf("\n--- DASD geometry ----------------------------"
"---------------------------------\n");
printf("number of cylinders : hex %x \tdec %d\n",
info->hw_cylinders,
info->hw_cylinders);
printf("tracks per cylinder : hex %x \tdec %d\n",
info->geo.heads,
info->geo.heads);
printf("blocks per track : hex %x \tdec %d\n",
info->geo.sectors,
info->geo.sectors);
printf("blocksize : hex %x \tdec %d\n",
info->blksize,
info->blksize);
}
/*
* Loop over the given character array and HEXdump the content.
*/
static inline void
dasdview_dump_array(char *name, int size, unsigned char *addr)
{
int i;
for (i = 0; i < size; i++) {
if (i % DASDVIEW_CPL == 0) {
if (i == 0)
printf("%-23.23s: ", name);
else
printf("\n%25s", "");
} else {
if (i % 8 == 0)
printf(" ");
if (i % 4 == 0)
printf(" ");
}
printf("%02x", addr[i]);
}
printf("\n");
}
/*
* Print extended DASD information.
*/
static void
dasdview_print_extended_info(dasdview_info_t *info)
{
unsigned int i;
struct dasd_information2_t *dasd_info;
struct {
unsigned int mask;
char *name;
} flist[2] = { {DASD_FEATURE_READONLY, "ro" },
{DASD_FEATURE_USEDIAG, "diag"} };
dasd_info = &info->dasd_info;
printf("\n--- extended DASD information ----------------"
"---------------------------------\n");
printf("real device number : hex %x \tdec %d\n",
dasd_info->real_devno, dasd_info->real_devno);
printf("subchannel identifier : hex %x \tdec %d\n",
dasd_info->schid, dasd_info->schid);
printf("CU type (SenseID) : hex %x \tdec %d\n",
dasd_info->cu_type, dasd_info->cu_type);
printf("CU model (SenseID) : hex %x \tdec %d\n",
dasd_info->cu_model, dasd_info->cu_model);
printf("device type (SenseID) : hex %x \tdec %d\n",
dasd_info->dev_type, dasd_info->dev_type);
printf("device model (SenseID) : hex %x \tdec %d\n",
dasd_info->dev_model, dasd_info->dev_model);
printf("open count : hex %x \tdec %d\n",
dasd_info->open_count, dasd_info->open_count);
printf("req_queue_len : hex %x \tdec %d\n",
dasd_info->req_queue_len, dasd_info->req_queue_len);
printf("chanq_len : hex %x \tdec %d\n",
dasd_info->chanq_len, dasd_info->chanq_len);
printf("status : hex %x \tdec %d\n",
dasd_info->status, dasd_info->status);
printf("label_block : hex %x \tdec %d\n",
dasd_info->label_block, dasd_info->label_block);
printf("FBA_layout : hex %x \tdec %d\n",
dasd_info->FBA_layout, dasd_info->FBA_layout);
printf("characteristics_size : hex %x \tdec %d\n",
dasd_info->characteristics_size,
dasd_info->characteristics_size);
printf("confdata_size : hex %x \tdec %d\n",
dasd_info->confdata_size, dasd_info->confdata_size);
printf("format : hex %x \tdec %d \t%s\n",
dasd_info->format, dasd_info->format,
dasd_info->format == DASD_FORMAT_NONE ?
"NOT formatted" :
dasd_info->format == DASD_FORMAT_LDL ?
"LDL formatted" :
dasd_info->format == DASD_FORMAT_CDL ?
"CDL formatted" : "unknown format");
printf("features : hex %x \tdec %d \t",
dasd_info->features, dasd_info->features);
if (dasd_info->features == DASD_FEATURE_DEFAULT) {
printf("default\n");
} else {
for (i = 0; i < UTIL_ARRAY_SIZE(flist); i++)
if (dasd_info->features & flist[i].mask)
printf("%s ", flist[i].name);
printf("\n");
}
printf("\n");
dasdview_dump_array("characteristics",
dasd_info->characteristics_size,
dasd_info->characteristics);
printf("\n");
dasdview_dump_array("configuration_data",
dasd_info->confdata_size,
dasd_info->configuration_data);
}
static void
dasdview_read_vlabel(dasdview_info_t *info, volume_label_t *vlabel)
{
volume_label_t tmp;
unsigned long pos;
pos = info->dasd_info.label_block * info->blksize;
bzero(vlabel, sizeof(volume_label_t));
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
!info->dasd_info.FBA_layout) {
/* OS/390 and zOS compatible disk layout */
vtoc_read_volume_label(info->device, pos, vlabel);
} else {
/* standard LINUX disk layout */
vtoc_read_volume_label(info->device, pos, &tmp);
memcpy(vlabel->vollbl, &tmp, sizeof(tmp) - 4);
}
}
static void
dasdview_print_vlabel(dasdview_info_t *info)
{
volume_label_t vlabel;
volume_label_t *tmpvlabel;
int rc;
unsigned char s4[5], t4[5], s5[6], t5[6], s6[7], t6[7];
char s14[15], t14[15], s29[30], t29[30];
int i;
if (info->raw_track_access) {
rc = lzds_dasd_read_vlabel(info->dasd);
if (rc) {
zt_error_print("error when reading label from device:"
" rc=%d\n", rc);
exit(-1);
}
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
} else {
dasdview_read_vlabel(info, &vlabel);
}
printf("\n--- volume label -----------------------------"
"---------------------------------\n");
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.volkey, 4);
printf("volume label key : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s4, 5); bzero(s4, 5); strncpy((char *)s4, vlabel.vollbl, 4);
printf("\n\nvolume label identifier : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s6, 7); bzero(t6, 7); strncpy((char *)s6, vlabel.volid, 6);
printf("\n\nvolume identifier : ascii '%6s'\n", s6);
vtoc_ebcdic_dec((char *)s6, (char *)t6, 6);
printf(" : ebcdic '%6s'\n", t6);
printf(" : hex ");
for (i = 0; i < 6; i++)
printf("%02x", s6[i]);
printf("\n\nsecurity byte : hex %02x\n", vlabel.security);
printf("\n\nVTOC pointer : hex %04x%04x%02x ",
vlabel.vtoc.cc, vlabel.vtoc.hh, vlabel.vtoc.b);
if ((vlabel.vtoc.cc == 0x4040) && (vlabel.vtoc.hh == 0x4040) &&
(vlabel.vtoc.b == 0x40))
printf("\n");
else
printf("\n "
"(cyl %d, trk %d, blk %d)\n\n",
vtoc_get_cyl_from_cchhb(&vlabel.vtoc),
vtoc_get_head_from_cchhb(&vlabel.vtoc), vlabel.vtoc.b);
bzero(s5, 6); bzero(t5, 6); strncpy((char *)s5, vlabel.res1, 5);
printf("reserved : ascii '%5s'\n", s5);
vtoc_ebcdic_dec((char *)s5, (char *)t5, 5);
printf(" : ebcdic '%5s'\n", t5);
printf(" : hex ");
for (i = 0; i < 5; i++)
printf("%02x", s5[i]);
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.cisize, 4);
printf("\n\nCI size for FBA : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.blkperci, 4);
printf("\n\nblocks per CI (FBA) : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.labperci, 4);
printf("\n\nlabels per CI (FBA) : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.res2, 4);
printf("\n\nreserved : ascii '%4s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
printf(" : ebcdic '%4s'\n", t4);
printf(" : hex ");
for (i = 0; i < 4; i++)
printf("%02x", s4[i]);
bzero(s14, 15); bzero(t14, 15); strncpy(s14, vlabel.lvtoc, 14);
printf("\n\nowner code for VTOC : ascii '%14s'\n", s14);
vtoc_ebcdic_dec(s14, t14, 14);
printf(" ebcdic '%14s'\n", t14);
printf(" hex ");
for (i = 0; i < 14; i++) {
printf("%02x", s14[i]);
if ((i + 1) % 4 == 0)
printf(" ");
if ((i + 1) % 8 == 0)
printf(" ");
}
bzero(s29, 30); strncpy(s29, vlabel.res3, 28);
printf("\n\nreserved : ascii '%28s'\n", s29);
bzero(t29, 30);
vtoc_ebcdic_dec(s29, t29, 28);
printf(" ebcdic '%28s'\n", t29);
printf(" hex ");
for (i = 0; i < 28; i++) {
printf("%02x", s29[i]);
if ((i + 1) % 4 == 0)
printf(" ");
if ((i + 1) % 8 == 0)
printf(" ");
if ((i + 1) % 16 == 0)
printf("\n "
" ");
}
bzero(s4, 5); bzero(t4, 5); s4[0] = vlabel.ldl_version;
printf("\n\nldl_version : ascii '%1s'\n", s4);
vtoc_ebcdic_dec((char *)s4, (char *)t4, 1);
printf(" : ebcdic '%1s'\n", t4);
printf(" : hex %02x", s4[0]);
printf("\n\nformatted_blocks : dec %llu",
vlabel.formatted_blocks);
printf("\n : hex %016llx",
vlabel.formatted_blocks);
printf("\n");
}
static void
dasdview_print_volser(dasdview_info_t *info)
{
volume_label_t vlabel;
volume_label_t *tmpvlabel;
char volser[7];
char vollbl[5];
int rc;
if (info->raw_track_access) {
rc = lzds_dasd_read_vlabel(info->dasd);
if (rc) {
zt_error_print("error when reading label from device:"
" rc=%d\n", rc);
exit(-1);
}
lzds_dasd_get_vlabel(info->dasd, &tmpvlabel);
memcpy(&vlabel, tmpvlabel, sizeof(vlabel));
} else {
dasdview_read_vlabel(info, &vlabel);
}
bzero(vollbl, 5);
bzero(volser, 7);
strncpy(vollbl, vlabel.vollbl, 4);
vtoc_ebcdic_dec(vollbl, vollbl, 4);
if ((strncmp(vollbl, "VOL1", 4) == 0) ||
(strncmp(vollbl, "LNX1", 4) == 0)) {
strncpy(volser, vlabel.volid, 6);
vtoc_ebcdic_dec(volser, volser, 6);
} else {
memcpy(volser, " ", 6);
}
printf("%6.6s\n", volser);
}
static void
dasdview_read_vtoc(dasdview_info_t *info)
{
volume_label_t vlabel;
format1_label_t tmp;
unsigned long maxblk, pos;
u_int64_t vtocblk;
int i;
pos = info->dasd_info.label_block * info->blksize;
bzero(&vlabel, sizeof(vlabel));
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
!info->dasd_info.FBA_layout) {
/* OS/390 and zOS compatible disk layout */
vtoc_read_volume_label(info->device, pos, &vlabel);
} else {
zt_error_print("dasdview: disk layout error\n"
"%s is not formatted with the z/OS "
"compatible disk layout!\n", info->device);
exit(-1);
}
vtocblk = (u_int64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
info->geo.heads * info->geo.sectors +
vtoc_get_head_from_cchhb(&vlabel.vtoc) * info->geo.sectors +
vlabel.vtoc.b;
/*
* geo.cylinders is the minimum of hw_cylinders and LV_COMPAT_CYL
* Actually the vtoc should be located in in the first 65k-1 tracks
* so this check could be even more restrictive, but it doesn't
* hurt the way it is. Linux cdl format restricts the vtoc to
* the first two tracks anyway.
*/
maxblk = info->geo.cylinders * info->geo.heads * info->geo.sectors;
if ((vtocblk <= 0) || (vtocblk > maxblk)) {
zt_error_print("dasdview: VTOC error\n"
"Volume label VTOC pointer is not valid!\n");
exit(-1);
}
vtoc_read_label(info->device, (vtocblk - 1) * info->blksize,
NULL, &info->f4, NULL, NULL);
if ((info->f4.DS4KEYCD[0] != 0x04) ||
(info->f4.DS4KEYCD[43] != 0x04) ||
(info->f4.DS4IDFMT != 0xf4)) {
/* format4 DSCB is invalid */
zt_error_print("dasdview: VTOC error\n"
"Format 4 DSCB is invalid!\n");
exit(-1);
}
info->f4c++;
pos = (vtocblk - 1) * info->blksize;
for (i = 1; i < info->geo.sectors; i++) {
pos += info->blksize;
vtoc_read_label(info->device, pos, &tmp, NULL, NULL, NULL);
switch (tmp.DS1FMTID) {
case 0xf1:
memcpy(&info->f1[info->f1c], &tmp,
sizeof(format1_label_t));
info->f1c++;
break;
case 0xf4:
info->f4c++;
break;
case 0xf5:
memcpy(&info->f5, &tmp, sizeof(format1_label_t));
info->f5c++;
break;
case 0xf7:
memcpy(&info->f7, &tmp, sizeof(format1_label_t));
info->f7c++;
break;
case 0xf8:
memcpy(&info->f8[info->f8c], &tmp,
sizeof(format1_label_t));
info->f8c++;
break;
case 0xf9:
memcpy(&info->f9[info->f9c], &tmp,
sizeof(format1_label_t));
info->f9c++;
break;
case 0x00:
break;
default:
printf("Unknown label in VTOC detected (id=%x)\n",
tmp.DS1FMTID);
}
}
if (info->f4c > 1) {
zt_error_print("dasdview: VTOC error\n"
"More than one FMT4 DSCB!\n");
exit(-1);
}
if (info->f5c > 1) {
zt_error_print("dasdview: VTOC error\n"
"More than one FMT5 DSCB!\n");
exit(-1);
}
if (info->f7c > 1) {
zt_error_print("dasdview: VTOC error\n"
"More than one FMT7 DSCB!\n");
exit(-1);
}
}
static void dasdview_print_format1_8_short_info(format1_label_t *f1,
struct hd_geometry *geo)
{
char s6[7], s13[14], s44[45];
unsigned long track_low, track_up;
bzero(s44, 45);
strncpy(s44, f1->DS1DSNAM, 44);
vtoc_ebcdic_dec(s44, s44, 44);
bzero(s6, 7);
strncpy(s6, (char *)f1->DS1DSSN, 6);
vtoc_ebcdic_dec(s6, s6, 6);
bzero(s13, 14);
strncpy(s13, (char *)f1->DS1SYSCD, 13);
vtoc_ebcdic_dec(s13, s13, 13);
track_low = cchh2trk(&f1->DS1EXT1.llimit, geo);
track_up = cchh2trk(&f1->DS1EXT1.ulimit, geo);
printf(" | %44s | trk | trk |\n",
s44);
printf(" | data set serial number :"
" '%6s' |"
" %12ld | %12ld |\n", s6, track_low, track_up);
printf(" | system code :"
" '%13s' |"
" cyl/trk | cyl/trk |\n", s13);
printf(" | creation date :"
" year %4d, day %3d |"
" %8d/%3d | %8d/%3d |\n",
f1->DS1CREDT.year + 1900,
f1->DS1CREDT.day,
vtoc_get_cyl_from_cchh(&f1->DS1EXT1.llimit),
vtoc_get_head_from_cchh(&f1->DS1EXT1.llimit),
vtoc_get_cyl_from_cchh(&f1->DS1EXT1.ulimit),
vtoc_get_head_from_cchh(&f1->DS1EXT1.ulimit));
printf(" +-----------------------------------------"
"-----+--------------+--------------+\n");
}
static void dasdview_print_vtoc_info(dasdview_info_t *info)
{
int i;
printf("--- VTOC info --------------------------------"
"---------------------------------\n");
printf("The VTOC contains:\n");
printf(" %d format 1 label(s)\n", info->f1c);
printf(" %d format 4 label(s)\n", info->f4c);
printf(" %d format 5 label(s)\n", info->f5c);
printf(" %d format 7 label(s)\n", info->f7c);
printf(" %d format 8 label(s)\n", info->f8c);
printf(" %d format 9 label(s)\n", info->f9c);
if ((info->f1c < 1) && (info->f8c < 1)) {
printf("There are no partitions defined.\n");
} else {
printf("Other mainframe operating systems would see "
"the following data sets:\n");
printf(" +----------------------------------------------+"
"--------------+--------------+\n");
printf(" | data set |"
" start | end |\n");
printf(" +----------------------------------------------+"
"--------------+--------------+\n");
for (i = 0; i < info->f1c; i++)
dasdview_print_format1_8_short_info(&info->f1[i],
&info->geo);
for (i = 0; i < info->f8c; i++)
dasdview_print_format1_8_short_info(&info->f8[i],
&info->geo);
}
}
static void dasdview_print_short_info_extent_raw(extent_t *ext)
{
if (ext->typeind > 0x00)
printf(" %3d (%5d,%5d) (%5d,%5d)\n",
ext->seqno,
vtoc_get_cyl_from_cchh(&ext->llimit),
vtoc_get_head_from_cchh(&ext->llimit),
vtoc_get_cyl_from_cchh(&ext->ulimit),
vtoc_get_head_from_cchh(&ext->ulimit));
}
static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
dasdview_info_t *info)
{
char s6[7], s13[14], s44[45];
unsigned long long j;
format3_label_t *f3;
format9_label_t *f9;
struct dscb *dscb;
int rc;
bzero(s44, 45);
strncpy(s44, f1->DS1DSNAM, 44);
vtoc_ebcdic_dec(s44, s44, 44);
bzero(s6, 7);
strncpy(s6, (char *)f1->DS1DSSN, 6);
vtoc_ebcdic_dec(s6, s6, 6);
bzero(s13, 14);
strncpy(s13, (char *)f1->DS1SYSCD, 13);
vtoc_ebcdic_dec(s13, s13, 13);
printf("data set name : '%44s'\n", s44);
printf("data set serial number : '%6s'\n", s6);
printf("system code : '%13s'\n", s13);
printf("creation date : year %4d, day %3d\n",
f1->DS1CREDT.year + 1900, f1->DS1CREDT.day);
printf("flags : ");
if (f1->DS1FLAG1 & 0x80)
printf("DS1COMPR ");
if (f1->DS1FLAG1 & 0x40)
printf("DS1CPOIT ");
if (f1->DS1FLAG1 & 0x20)
printf("DS1EXPBY ");
if (f1->DS1FLAG1 & 0x10)
printf("DS1RECAL ");
if (f1->DS1FLAG1 & 0x08)
printf("DS1LARGE ");
if (f1->DS1FLAG1 & 0x04)
printf("unknown ");
if ((f1->DS1FLAG1 & 0x01) && (f1->DS1FLAG1 & 0x02))
printf("DS1EATTR=not used ");
if (!(f1->DS1FLAG1 & 0x01) && (f1->DS1FLAG1 & 0x02))
printf("DS1EATTR=optional ");
if ((f1->DS1FLAG1 & 0x01) && !(f1->DS1FLAG1 & 0x02))
printf("DS1EATTR=no ");
if (f1->DS1FLAG1 & 0x00)
printf("DS1EATTR=default ");
printf("\n");
printf("SMS flags : ");
if (f1->DS1SMSFG & 0x80)
printf("DS1SMSDS ");
if (f1->DS1SMSFG & 0x40)
printf("DS1SMSUC ");
if (f1->DS1SMSFG & 0x20)
printf("DS1REBLK ");
if (f1->DS1SMSFG & 0x10)
printf("DS1CRSDB ");
if (f1->DS1SMSFG & 0x08)
printf("DS1PDSE ");
if (f1->DS1SMSFG & 0x04)
printf("DS1STRP ");
if (f1->DS1SMSFG & 0x02)
printf("DS1PDSEX ");
if (f1->DS1SMSFG & 0x01)
printf("DS1DSAE ");
printf("\n");
printf("organisation : ");
if (f1->DS1DSRG1 & 0x80)
printf("DS1DSGIS ");
if (f1->DS1DSRG1 & 0x40)
printf("DS1DSGPS ");
if (f1->DS1DSRG1 & 0x20)
printf("DS1DSGDA ");
if (f1->DS1DSRG1 & 0x10)
printf("DS1DSGCX ");
if (f1->DS1DSRG1 & 0x08)
printf("reserved ");
if (f1->DS1DSRG1 & 0x04)
printf("reserved ");
if (f1->DS1DSRG1 & 0x02)
printf("DS1DSGPO ");
if (f1->DS1DSRG1 & 0x01)
printf("DS1DSGU ");
if (f1->DS1DSRG2 & 0x80)
printf("DS1DSGGS ");
if (f1->DS1DSRG2 & 0x40)
printf("DS1DSGTX ");
if (f1->DS1DSRG2 & 0x20)
printf("DS1DSGTQ ");
if (f1->DS1DSRG2 & 0x10)
printf("reserved ");
if (f1->DS1DSRG2 & 0x08)
printf("DS1ACBM ");
if (f1->DS1DSRG2 & 0x04)
printf("DS1DSGTR ");
if (f1->DS1DSRG2 & 0x02)
printf("reserved ");
if (f1->DS1DSRG2 & 0x01)
printf("reserved");
printf("\n");
printf("record format : ");
if ((f1->DS1RECFM & 0x80) && !(f1->DS1RECFM & 0x40))
printf("DS1RECFF ");
if (!(f1->DS1RECFM & 0x80) && (f1->DS1RECFM & 0x40))
printf("DS1RECFV ");
if ((f1->DS1RECFM & 0x80) && (f1->DS1RECFM & 0x40))
printf("DS1RECFU ");
if (f1->DS1RECFM & 0x20)
printf("DS1RECFT ");
if (f1->DS1RECFM & 0x10)
printf("DS1RECFB ");
if (f1->DS1RECFM & 0x08)
printf("DS1RECFS ");
if (f1->DS1RECFM & 0x04)
printf("DS1RECFA ");
if (f1->DS1RECFM & 0x02)
printf("DS1RECMC ");
if (f1->DS1RECFM & 0x01)
printf("reserved");
printf("\n");
printf("(max) block length : %u\n", f1->DS1BLKL);
printf("logical record length : %u\n", f1->DS1LRECL);
printf("extents belonging to this dataset:\n");
printf(" seqno llimit (cyl, trk) ulimit (cyl, trk)\n");
/* The format 1 label can point to a chain of f3 labels
* The format 8 label points to a (chain of) f9 labels
* The format 9 label may contain several format 3 labels, but as
* far as I know, it is still OK to follow the 'next dscb' chain.
* So for a format 9 label I have to follow this chain until I
* find the first format 3 dscb and then I can follow the format 3
* dscbs to the end of the chain.
*/
rc = lzds_raw_vtoc_get_dscb_from_cchhb(info->rawvtoc, &f1->DS1PTRDS,
&dscb);
/* The first f9 label contains extra data that we may want to print here
*/
while (!rc && dscb && dscb->fmtid == 0xf9) {
f9 = (format9_label_t *)dscb;
rc = lzds_raw_vtoc_get_dscb_from_cchhb(info->rawvtoc,
&f9->DS9PTRDS, &dscb);
}
if (rc) {
zt_error_print("dasdview: Broken format 3 DSCB chain \n");
exit(-1);
}
f3 = (dscb && dscb->fmtid == 0xf3) ? (format3_label_t *)dscb : NULL;
/* first print the extents that are part of the f1/f8 label itself */
dasdview_print_short_info_extent_raw(&f1->DS1EXT1);
dasdview_print_short_info_extent_raw(&f1->DS1EXT2);
dasdview_print_short_info_extent_raw(&f1->DS1EXT3);
/* now follow the f3 chain into the rabbit hole */
while (f3) {
/* sanity check */
if (f3->DS3FMTID != 0xf3) {
zt_error_print("dasdview: Broken format 3 DSCB"
" chain \n");
exit(-1);
}
for (j = 0; j < 4; ++j)
dasdview_print_short_info_extent_raw(&f3->DS3EXTNT[j]);
for (j = 0; j < 9; ++j)
dasdview_print_short_info_extent_raw(&f3->DS3ADEXT[j]);
rc = lzds_raw_vtoc_get_dscb_from_cchhb(info->rawvtoc,
&f3->DS3PTRDS,
(struct dscb **)&f3);
if (rc) {
zt_error_print("dasdview: Broken format 3 DSCB"
" chain \n");
exit(-1);
}
}
printf("\n");
}
static void dasdview_print_vtoc_info_raw(dasdview_info_t *info)
{
struct dscbiterator *it;
struct dscb *dscb;
int rc;
int f1c, f3c, f4c, f5c, f7c, f8c, f9c;
f1c = 0;
f3c = 0;
f4c = 0;
f5c = 0;
f7c = 0;
f8c = 0;
f9c = 0;
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
if (rc) {
zt_error_print("dasdview: could not allocate DSCB iterator \n");
exit(-1);
}
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
if (dscb->fmtid == 0xf1)
++f1c;
else if (dscb->fmtid == 0xf3)
++f3c;
else if (dscb->fmtid == 0xf4)
++f4c;
else if (dscb->fmtid == 0xf5)
++f5c;
else if (dscb->fmtid == 0xf7)
++f7c;
else if (dscb->fmtid == 0xf8)
++f8c;
else if (dscb->fmtid == 0xf9)
++f9c;
}
lzds_dscbiterator_free(it);
printf("--- VTOC info --------------------------------"
"---------------------------------\n");
printf("The VTOC contains:\n");
printf(" %d format 1 label(s)\n", f1c);
printf(" %d format 3 label(s)\n", f3c);
printf(" %d format 4 label(s)\n", f4c);
printf(" %d format 5 label(s)\n", f5c);
printf(" %d format 7 label(s)\n", f7c);
printf(" %d format 8 label(s)\n", f8c);
printf(" %d format 9 label(s)\n", f9c);
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
if (rc) {
zt_error_print("dasdview: could not allocate DSCB iterator \n");
exit(-1);
}
while (!lzds_dscbiterator_get_next_dscb(it, &dscb)) {
if (dscb->fmtid == 0xf1 || dscb->fmtid == 0xf8)
dasdview_print_format1_8_short_info_raw(
(format1_label_t *)dscb, info);
}
lzds_dscbiterator_free(it);
}
/*
* Note: the explicit cylinder/head conversion for large volume
* adresses should not be necessary for entries that point to
* vtoc labels, as those must be located in the first 65K-1 tracks,
* but we do it anyway to be on the safe side.
*/
static void dasdview_print_format1_8_no_head(format1_label_t *f1)
{
char s6[7], s13[14], s44[45];
int i;
bzero(s6, 7);
bzero(s13, 14);
bzero(s44, 45);
strncpy(s44, f1->DS1DSNAM, 44);
printf("DS1DSNAM : ascii '%44s'\n", s44);
vtoc_ebcdic_dec(s44, s44, 44);
printf(" ebcdic '%44s'\n", s44);
printf("DS1FMTID : dec %d, hex %02x\n",
f1->DS1FMTID, f1->DS1FMTID);
printf("DS1DSSN : hex ");
for (i = 0; i < 6; i++)
printf("%02x", f1->DS1DSSN[i]);
strncpy(s6, (char *)f1->DS1DSSN, 6);
printf("\n ascii '%6s'\n", s6);
vtoc_ebcdic_dec(s6, s6, 6);
printf(" ebcdic '%6s'\n", s6);
printf("DS1VOLSQ : dec %d, hex %04x\n",
f1->DS1VOLSQ, f1->DS1VOLSQ);
printf("DS1CREDT : hex %02x%04x "
"(year %d, day %d)\n",
f1->DS1CREDT.year, f1->DS1CREDT.day,
f1->DS1CREDT.year + 1900,
f1->DS1CREDT.day);
printf("DS1EXPDT : hex %02x%04x "
"(year %d, day %d)\n",
f1->DS1EXPDT.year, f1->DS1EXPDT.day,
f1->DS1EXPDT.year + 1900,
f1->DS1EXPDT.day);
printf("DS1NOEPV : dec %d, hex %02x\n",
f1->DS1NOEPV, f1->DS1NOEPV);
printf("DS1NOBDB : dec %d, hex %02x\n",
f1->DS1NOBDB, f1->DS1NOBDB);
printf("DS1FLAG1 : dec %d, hex %02x\n",
f1->DS1FLAG1, f1->DS1FLAG1);
printf("DS1SYSCD : hex ");
for (i = 0; i < 13; i++)
printf("%02x", f1->DS1SYSCD[i]);
strncpy(s13, (char *)f1->DS1SYSCD, 13);
printf("\n ascii '%13s'\n", s13);
vtoc_ebcdic_dec(s13, s13, 13);
printf(" ebcdic '%13s'\n", s13);
printf("DS1REFD : hex %02x%04x "
"(year %d, day %d)\n",
f1->DS1REFD.year, f1->DS1REFD.day,
f1->DS1REFD.year + 1900,
f1->DS1REFD.day);
printf("DS1SMSFG : dec %d, hex %02x\n",
f1->DS1SMSFG, f1->DS1SMSFG);
printf("DS1SCXTF : dec %d, hex %02x\n",
f1->DS1SCXTF, f1->DS1SCXTF);
printf("DS1SCXTV : dec %d, hex %04x\n",
f1->DS1SCXTV, f1->DS1SCXTV);
printf("DS1DSRG1 : dec %d, hex %02x\n",
f1->DS1DSRG1, f1->DS1DSRG1);
printf("DS1DSRG2 : dec %d, hex %02x\n",
f1->DS1DSRG2, f1->DS1DSRG2);
printf("DS1RECFM : dec %d, hex %02x\n",
f1->DS1RECFM, f1->DS1RECFM);
printf("DS1OPTCD : dec %d, hex %02x\n",
f1->DS1OPTCD, f1->DS1OPTCD);
printf("DS1BLKL : dec %d, hex %04x\n",
f1->DS1BLKL, f1->DS1BLKL);
printf("DS1LRECL : dec %d, hex %04x\n",
f1->DS1LRECL, f1->DS1LRECL);
printf("DS1KEYL : dec %d, hex %02x\n",
f1->DS1KEYL, f1->DS1KEYL);
printf("DS1RKP : dec %d, hex %04x\n",
f1->DS1RKP, f1->DS1RKP);
printf("DS1DSIND : dec %d, hex %02x\n",
f1->DS1DSIND, f1->DS1DSIND);
printf("DS1SCAL1 : dec %d, hex %02x\n",
f1->DS1SCAL1, f1->DS1SCAL1);
printf("DS1SCAL3 : hex ");
for (i = 0; i < 3; i++)
printf("%02x", f1->DS1SCAL3[i]);
printf("\nDS1LSTAR : hex %04x%02x "
"(trk %d, blk %d)\n",
f1->DS1LSTAR.tt, f1->DS1LSTAR.r,
f1->DS1LSTAR.tt, f1->DS1LSTAR.r);
printf("DS1TRBAL : dec %d, hex %04x\n",
f1->DS1TRBAL, f1->DS1TRBAL);
printf("reserved : dec %d, hex %04x\n",
f1->res1, f1->res1);
printf("DS1EXT1 : hex %02x%02x%04x%04x%04x%04x\n",
f1->DS1EXT1.typeind,
f1->DS1EXT1.seqno,
f1->DS1EXT1.llimit.cc,
f1->DS1EXT1.llimit.hh,
f1->DS1EXT1.ulimit.cc,
f1->DS1EXT1.ulimit.hh);
printf(" typeind : dec %d, hex %02x\n",
f1->DS1EXT1.typeind,
f1->DS1EXT1.typeind);
printf(" seqno : dec %d, hex %02x\n",
f1->DS1EXT1.seqno, f1->DS1EXT1.seqno);
printf(" llimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT1.llimit.cc,
f1->DS1EXT1.llimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT1.llimit),
vtoc_get_head_from_cchh(&f1->DS1EXT1.llimit));
printf(" ulimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT1.ulimit.cc,
f1->DS1EXT1.ulimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT1.ulimit),
vtoc_get_head_from_cchh(&f1->DS1EXT1.ulimit));
printf("DS1EXT2 : hex %02x%02x%04x%04x%04x%04x\n",
f1->DS1EXT2.typeind,
f1->DS1EXT2.seqno,
f1->DS1EXT2.llimit.cc,
f1->DS1EXT2.llimit.hh,
f1->DS1EXT2.ulimit.cc,
f1->DS1EXT2.ulimit.hh);
printf(" typeind : dec %d, hex %02x\n",
f1->DS1EXT2.typeind,
f1->DS1EXT2.typeind);
printf(" seqno : dec %d, hex %02x\n",
f1->DS1EXT2.seqno, f1->DS1EXT2.seqno);
printf(" llimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT2.llimit.cc,
f1->DS1EXT2.llimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT2.llimit),
vtoc_get_head_from_cchh(&f1->DS1EXT2.llimit));
printf(" ulimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT2.ulimit.cc,
f1->DS1EXT2.ulimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT2.ulimit),
vtoc_get_head_from_cchh(&f1->DS1EXT2.ulimit));
printf("DS1EXT3 : hex %02x%02x%04x%04x%04x%04x\n",
f1->DS1EXT3.typeind,
f1->DS1EXT3.seqno,
f1->DS1EXT3.llimit.cc,
f1->DS1EXT3.llimit.hh,
f1->DS1EXT3.ulimit.cc,
f1->DS1EXT3.ulimit.hh);
printf(" typeind : dec %d, hex %02x\n",
f1->DS1EXT3.typeind,
f1->DS1EXT3.typeind);
printf(" seqno : dec %d, hex %02x\n",
f1->DS1EXT3.seqno, f1->DS1EXT3.seqno);
printf(" llimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT3.llimit.cc,
f1->DS1EXT3.llimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT3.llimit),
vtoc_get_head_from_cchh(&f1->DS1EXT3.llimit));
printf(" ulimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
f1->DS1EXT3.ulimit.cc,
f1->DS1EXT3.ulimit.hh,
vtoc_get_cyl_from_cchh(&f1->DS1EXT3.ulimit),
vtoc_get_head_from_cchh(&f1->DS1EXT3.ulimit));
printf("DS1PTRDS : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f1->DS1PTRDS.cc, f1->DS1PTRDS.hh,
f1->DS1PTRDS.b,
vtoc_get_cyl_from_cchhb(&f1->DS1PTRDS),
vtoc_get_head_from_cchhb(&f1->DS1PTRDS),
f1->DS1PTRDS.b);
}
static void dasdview_print_vtoc_f1_raw(format1_label_t *f1)
{
printf("\n--- VTOC format 1 label -----------------------"
"---------------------------------\n");
dasdview_print_format1_8_no_head(f1);
}
/* Note: A format 8 label uses the same type as format 1 */
static void dasdview_print_vtoc_f8_raw(format1_label_t *f8)
{
printf("\n--- VTOC format 8 label -----------------------"
"---------------------------------\n");
dasdview_print_format1_8_no_head(f8);
}
static void dasdview_print_extent(extent_t *ext, char *name, int index)
{
printf("%s[%d] : hex %02x%02x%04x%04x%04x%04x\n",
name,
index,
ext->typeind,
ext->seqno,
ext->llimit.cc,
ext->llimit.hh,
ext->ulimit.cc,
ext->ulimit.hh);
printf(" typeind : dec %d, hex %02x\n",
ext->typeind,
ext->typeind);
printf(" seqno : dec %d, hex %02x\n",
ext->seqno, ext->seqno);
printf(" llimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
ext->llimit.cc,
ext->llimit.hh,
vtoc_get_cyl_from_cchh(&ext->llimit),
vtoc_get_head_from_cchh(&ext->llimit));
printf(" ulimit : hex %04x%04x "
"(cyl %d, trk %d)\n",
ext->ulimit.cc,
ext->ulimit.hh,
vtoc_get_cyl_from_cchh(&ext->ulimit),
vtoc_get_head_from_cchh(&ext->ulimit));
}
static void dasdview_print_vtoc_f3_raw(format3_label_t *f3)
{
int i;
printf("\n--- VTOC format 3 label ----------------------"
"---------------------------------\n");
printf("DS3KEYID : ");
for (i = 0; i < 4; i++)
printf("%02x", f3->DS3KEYID[i]);
printf("\n");
for (i = 0; i < 4; ++i)
dasdview_print_extent(&f3->DS3EXTNT[i], "DS3EXTNT", i);
printf("DS3FMTID : dec %d, hex %02x\n",
f3->DS3FMTID, f3->DS3FMTID);
for (i = 0; i < 9; ++i)
dasdview_print_extent(&f3->DS3ADEXT[i], "DS3ADEXT", i);
printf("DS3PTRDS : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f3->DS3PTRDS.cc, f3->DS3PTRDS.hh,
f3->DS3PTRDS.b,
vtoc_get_cyl_from_cchhb(&f3->DS3PTRDS),
vtoc_get_head_from_cchhb(&f3->DS3PTRDS),
f3->DS3PTRDS.b);
}
static void dasdview_print_vtoc_f4_raw(format4_label_t *f4)
{
int i;
printf("\n--- VTOC format 4 label ----------------------"
"---------------------------------\n");
printf("DS4KEYCD : ");
for (i = 0; i < 44; i++)
printf("%02x", f4->DS4KEYCD[i]);
printf("\nDS4IDFMT : dec %d, hex %02x\n",
f4->DS4IDFMT, f4->DS4IDFMT);
printf("DS4HPCHR : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f4->DS4HPCHR.cc, f4->DS4HPCHR.hh,
f4->DS4HPCHR.b,
vtoc_get_cyl_from_cchhb(&f4->DS4HPCHR),
vtoc_get_head_from_cchhb(&f4->DS4HPCHR),
f4->DS4HPCHR.b);
printf("DS4DSREC : dec %d, hex %04x\n",
f4->DS4DSREC, f4->DS4DSREC);
printf("DS4HCCHH : %04x%04x (cyl %d, trk %d)\n",
f4->DS4HCCHH.cc, f4->DS4HCCHH.hh,
vtoc_get_cyl_from_cchh(&f4->DS4HCCHH),
vtoc_get_head_from_cchh(&f4->DS4HCCHH));
printf("DS4NOATK : dec %d, hex %04x\n",
f4->DS4NOATK, f4->DS4NOATK);
printf("DS4VTOCI : dec %d, hex %02x\n",
f4->DS4VTOCI, f4->DS4VTOCI);
printf("DS4NOEXT : dec %d, hex %02x\n",
f4->DS4NOEXT, f4->DS4NOEXT);
printf("DS4SMSFG : dec %d, hex %02x\n",
f4->DS4SMSFG, f4->DS4SMSFG);
printf("DS4DEVAC : dec %d, hex %02x\n",
f4->DS4DEVAC, f4->DS4DEVAC);
printf("DS4DSCYL : dec %d, hex %04x\n",
f4->DS4DEVCT.DS4DSCYL, f4->DS4DEVCT.DS4DSCYL);
printf("DS4DSTRK : dec %d, hex %04x\n",
f4->DS4DEVCT.DS4DSTRK, f4->DS4DEVCT.DS4DSTRK);
printf("DS4DEVTK : dec %d, hex %04x\n",
f4->DS4DEVCT.DS4DEVTK, f4->DS4DEVCT.DS4DEVTK);
printf("DS4DEVI : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVI, f4->DS4DEVCT.DS4DEVI);
printf("DS4DEVL : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVL, f4->DS4DEVCT.DS4DEVL);
printf("DS4DEVK : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVK, f4->DS4DEVCT.DS4DEVK);
printf("DS4DEVFG : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVFG, f4->DS4DEVCT.DS4DEVFG);
printf("DS4DEVTL : dec %d, hex %04x\n",
f4->DS4DEVCT.DS4DEVTL, f4->DS4DEVCT.DS4DEVTL);
printf("DS4DEVDT : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVDT, f4->DS4DEVCT.DS4DEVDT);
printf("DS4DEVDB : dec %d, hex %02x\n",
f4->DS4DEVCT.DS4DEVDB, f4->DS4DEVCT.DS4DEVDB);
printf("DS4AMTIM : hex ");
for (i = 0; i < 8; i++)
printf("%02x", f4->DS4AMTIM[i]);
printf("\nDS4AMCAT : hex ");
for (i = 0; i < 3; i++)
printf("%02x", f4->DS4AMCAT[i]);
printf("\nDS4R2TIM : hex ");
for (i = 0; i < 8; i++)
printf("%02x", f4->DS4R2TIM[i]);
printf("\nres1 : hex ");
for (i = 0; i < 5; i++)
printf("%02x", f4->res1[i]);
printf("\nDS4F6PTR : hex ");
for (i = 0; i < 5; i++)
printf("%02x", f4->DS4F6PTR[i]);
printf("\nDS4VTOCE : hex %02x%02x%04x%04x%04x%04x\n",
f4->DS4VTOCE.typeind, f4->DS4VTOCE.seqno,
f4->DS4VTOCE.llimit.cc, f4->DS4VTOCE.llimit.hh,
f4->DS4VTOCE.ulimit.cc, f4->DS4VTOCE.ulimit.hh);
printf(" typeind : dec %d, hex %02x\n",
f4->DS4VTOCE.typeind, f4->DS4VTOCE.typeind);
printf(" seqno : dec %d, hex %02x\n",
f4->DS4VTOCE.seqno, f4->DS4VTOCE.seqno);
printf(" llimit : hex %04x%04x (cyl %d, trk %d)\n",
f4->DS4VTOCE.llimit.cc, f4->DS4VTOCE.llimit.hh,
vtoc_get_cyl_from_cchh(&f4->DS4VTOCE.llimit),
vtoc_get_head_from_cchh(&f4->DS4VTOCE.llimit));
printf(" ulimit : hex %04x%04x (cyl %d, trk %d)\n",
f4->DS4VTOCE.ulimit.cc, f4->DS4VTOCE.ulimit.hh,
vtoc_get_cyl_from_cchh(&f4->DS4VTOCE.ulimit),
vtoc_get_head_from_cchh(&f4->DS4VTOCE.ulimit));
printf("res2 : hex ");
for (i = 0; i < 10; i++)
printf("%02x", f4->res2[i]);
printf("\nDS4EFLVL : dec %d, hex %02x\n",
f4->DS4EFLVL, f4->DS4EFLVL);
printf("DS4EFPTR : hex %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f4->DS4EFPTR.cc, f4->DS4EFPTR.hh,
f4->DS4EFPTR.b,
vtoc_get_cyl_from_cchhb(&f4->DS4EFPTR),
vtoc_get_head_from_cchhb(&f4->DS4EFPTR),
f4->DS4EFPTR.b);
printf("res3 : hex %02x\n", f4->res3);
printf("DS4DCYL : dec %d, hex %08x\n",
f4->DS4DCYL, f4->DS4DCYL);
printf("res4 : hex ");
for (i = 0; i < 2; i++)
printf("%02x", f4->res4[i]);
printf("\nDS4DEVF2 : dec %d, hex %02x\n",
f4->DS4DEVF2, f4->DS4DEVF2);
printf("res5 : hex %02x\n", f4->res5);
}
static void dasdview_print_vtoc_f5_raw(format5_label_t *f5)
{
int i;
printf("\n--- VTOC format 5 label ----------------------"
"---------------------------------\n");
printf("key identifier\n DS5KEYID : ");
for (i = 0; i < 4; i++)
printf("%02x", f5->DS5KEYID[i]);
printf("\nfirst extent description\n");
printf(" DS5AVEXT : %04x%04x%02x "
"(start trk: %d, length: %d cyl, %d trk)\n",
f5->DS5AVEXT.t, f5->DS5AVEXT.fc,
f5->DS5AVEXT.ft, f5->DS5AVEXT.t,
f5->DS5AVEXT.fc, f5->DS5AVEXT.ft);
printf("next 7 extent descriptions\n");
for (i = 0; i < 7; i++) {
printf(" DS5EXTAV[%d] : %04x%04x%02x "
"(start trk: %d, length: %d cyl, %d trk)\n", i + 2,
f5->DS5EXTAV[i].t, f5->DS5EXTAV[i].fc,
f5->DS5EXTAV[i].ft, f5->DS5EXTAV[i].t,
f5->DS5EXTAV[i].fc, f5->DS5EXTAV[i].ft);
}
printf("format identifier\n"
" DS5FMTID : dec %d, hex %02x\n",
f5->DS5FMTID, f5->DS5FMTID);
printf("next 18 extent descriptions\n");
for (i = 0; i < 18; i++) {
printf(" DS5MAVET[%d] : %04x%04x%02x "
"(start trk: %d, length: %d cyl, %d trk)\n", i + 9,
f5->DS5MAVET[i].t, f5->DS5MAVET[i].fc,
f5->DS5MAVET[i].ft, f5->DS5MAVET[i].t,
f5->DS5MAVET[i].fc, f5->DS5MAVET[i].ft);
}
printf("pointer to next format 5 label\n"
" DS5PTRDS : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f5->DS5PTRDS.cc, f5->DS5PTRDS.hh,
f5->DS5PTRDS.b,
vtoc_get_cyl_from_cchhb(&f5->DS5PTRDS),
vtoc_get_head_from_cchhb(&f5->DS5PTRDS),
f5->DS5PTRDS.b);
}
static void dasdview_print_vtoc_f7_raw(format7_label_t *f7)
{
int i;
printf("\n--- VTOC format 7 label ----------------------"
"---------------------------------\n");
printf("key identifier\n DS7KEYID : ");
for (i = 0; i < 4; i++)
printf("%02x", f7->DS7KEYID[i]);
printf("\nfirst 5 extent descriptions\n");
for (i = 0; i < 5; i++) {
printf(" DS7EXTNT[%d] : %08x %08x "
"(start trk %d, end trk %d)\n", i + 1,
f7->DS7EXTNT[i].a, f7->DS7EXTNT[i].b,
f7->DS7EXTNT[i].a, f7->DS7EXTNT[i].b);
}
printf("format identifier\n"
" DS7FMTID : dec %d, hex %02x\n",
f7->DS7FMTID, f7->DS7FMTID);
printf("next 11 extent descriptions\n");
for (i = 0; i < 11; i++) {
printf(" DS7ADEXT[%d] : %08x %08x "
"(start trk %d, end trk %d)\n", i + 6,
f7->DS7ADEXT[i].a, f7->DS7ADEXT[i].b,
f7->DS7ADEXT[i].a, f7->DS7ADEXT[i].b);
}
printf("reserved field\n res1 : ");
for (i = 0; i < 2; i++)
printf("%02x", f7->res1[i]);
printf("\npointer to next format 7 label\n"
" DS7PTRDS : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f7->DS7PTRDS.cc, f7->DS7PTRDS.hh,
f7->DS7PTRDS.b,
vtoc_get_cyl_from_cchhb(&f7->DS7PTRDS),
vtoc_get_head_from_cchhb(&f7->DS7PTRDS),
f7->DS7PTRDS.b);
}
static void dasdview_print_vtoc_f9_nohead(format9_label_t *f9)
{
unsigned int i;
printf("DS9KEYID : dec %d, hex %02x\n",
f9->DS9KEYID, f9->DS9KEYID);
printf("DS9SUBTY : dec %d, hex %02x\n",
f9->DS9SUBTY, f9->DS9SUBTY);
printf("DS9NUMF9 : dec %d, hex %02x\n",
f9->DS9NUMF9, f9->DS9NUMF9);
printf("res1 : hex ");
for (i = 0; i < sizeof(f9->res1); i++) {
if ((i > 0) && (i % 16 == 0))
printf("\n ");
printf("%02x", f9->res1[i]);
if ((i + 9) % 16 == 0)
printf(" ");
}
printf("\n");
printf("DS9FMTID : dec %d, hex %02x\n",
f9->DS9FMTID, f9->DS9FMTID);
printf("res2 : hex ");
for (i = 0; i < sizeof(f9->res2); i++) {
if ((i > 0) && (i % 16 == 0))
printf("\n ");
printf("%02x", f9->res2[i]);
if ((i + 9) % 16 == 0)
printf(" ");
}
printf("\n");
printf("pointer to next format 9 label\n"
" DS9PTRDS : %04x%04x%02x "
"(cyl %d, trk %d, blk %d)\n",
f9->DS9PTRDS.cc, f9->DS9PTRDS.hh,
f9->DS9PTRDS.b,
vtoc_get_cyl_from_cchhb(&f9->DS9PTRDS),
vtoc_get_head_from_cchhb(&f9->DS9PTRDS),
f9->DS9PTRDS.b);
}
static void dasdview_print_vtoc_f9_raw(format9_label_t *f9)
{
printf("\n--- VTOC format 9 label ----------------------"
"---------------------------------\n");
dasdview_print_vtoc_f9_nohead(f9);
}
static void dasdview_print_vtoc_dscb(dasdview_info_t *info, void *dscb)
{
format1_label_t *tmp = dscb;
switch (tmp->DS1FMTID) {
case 0x00:
break;
case 0xf1:
if (info->vtoc_f1 || info->vtoc_all)
dasdview_print_vtoc_f1_raw(dscb);
break;
case 0xf3:
if (info->vtoc_f3 || info->vtoc_all)
dasdview_print_vtoc_f3_raw(dscb);
break;
case 0xf4:
if (info->vtoc_f4 || info->vtoc_all)
dasdview_print_vtoc_f4_raw(dscb);
break;
case 0xf5:
if (info->vtoc_f5 || info->vtoc_all)
dasdview_print_vtoc_f5_raw(dscb);
break;
case 0xf7:
if (info->vtoc_f7 || info->vtoc_all)
dasdview_print_vtoc_f7_raw(dscb);
break;
case 0xf8:
if (info->vtoc_f8 || info->vtoc_all)
dasdview_print_vtoc_f8_raw(dscb);
break;
case 0xf9:
if (info->vtoc_f9 || info->vtoc_all)
dasdview_print_vtoc_f9_raw(dscb);
break;
default:
printf("unrecognized DSCB of type: %x \n\n", tmp->DS1FMTID);
break;
}
}
static void dasdview_print_vtoc_f1(dasdview_info_t *info)
{
int j;
printf("--- VTOC format 1 labels ----------------------"
"---------------------------------\n");
if (info->f1c < 1) {
printf("This VTOC doesn't contain a format 1 label.\n");
return;
}
for (j = 0; j < info->f1c; j++) {
printf("\n--- format 1 DSCB number %d ---\n", j + 1);
dasdview_print_format1_8_no_head(&info->f1[j]);
}
}
static void dasdview_print_vtoc_f8(dasdview_info_t *info)
{
int j;
printf("--- VTOC format 8 labels ----------------------"
"---------------------------------\n");
if (info->f8c < 1) {
printf("This VTOC doesn't contain a format 8 label.\n");
return;
}
for (j = 0; j < info->f8c; j++) {
printf("\n--- format 8 DSCB number %d ---\n", j + 1);
dasdview_print_format1_8_no_head(&info->f8[j]);
}
}
static void dasdview_print_vtoc_f4(dasdview_info_t *info)
{
if (info->f4c < 1) {
printf("\n--- VTOC format 4 label ----------------------"
"---------------------------------\n");
printf("This VTOC doesn't contain a format 4 label.\n");
return;
}
dasdview_print_vtoc_f4_raw(&info->f4);
}
static void dasdview_print_vtoc_f5(dasdview_info_t *info)
{
if (info->f5c < 1) {
printf("\n--- VTOC format 5 label ----------------------"
"---------------------------------\n");
printf("This VTOC doesn't contain a format 5 label.\n");
return;
}
dasdview_print_vtoc_f5_raw(&info->f5);
}
static void dasdview_print_vtoc_f7(dasdview_info_t *info)
{
if (info->f7c < 1) {
printf("\n--- VTOC format 7 label ----------------------"
"---------------------------------\n");
printf("This VTOC doesn't contain a format 7 label.\n");
return;
}
dasdview_print_vtoc_f7_raw(&info->f7);
}
static void dasdview_print_vtoc_f9(dasdview_info_t *info)
{
int j;
printf("\n--- VTOC format 9 label ----------------------"
"---------------------------------\n");
if (info->f9c < 1) {
printf("This VTOC doesn't contain a format 9 label.\n");
return;
}
for (j = 0; j < info->f9c; j++) {
printf("\n--- format 9 DSCB number %d ---\n", j + 1);
dasdview_print_vtoc_f9_nohead(&info->f9[j]);
}
}
static void dasdview_print_vtoc_f3(void)
{
/* dasdfmt formatted DASD devices have no format3 labels, but since the
* option exists for raw DASDs, we need to have some sensible message
*/
printf("\n--- VTOC format 3 label ----------------------"
"---------------------------------\n");
printf("This VTOC doesn't contain a format 3 label.\n");
}
static void dasdview_print_vtoc_standard(dasdview_info_t *info)
{
dasdview_read_vtoc(info);
if (info->vtoc_info || info->vtoc_all)
dasdview_print_vtoc_info(info);
if (info->vtoc_f4 || info->vtoc_all)
dasdview_print_vtoc_f4(info);
if (info->vtoc_f5 || info->vtoc_all)
dasdview_print_vtoc_f5(info);
if (info->vtoc_f7 || info->vtoc_all)
dasdview_print_vtoc_f7(info);
if (info->vtoc_f1 || info->vtoc_all)
dasdview_print_vtoc_f1(info);
if (info->vtoc_f8 || info->vtoc_all)
dasdview_print_vtoc_f8(info);
if (info->vtoc_f9 || info->vtoc_all)
dasdview_print_vtoc_f9(info);
if (info->vtoc_f3 || info->vtoc_all)
dasdview_print_vtoc_f3();
}
/* a simple routine to print all records in the vtoc */
static void dasdview_print_vtoc_raw(dasdview_info_t *info)
{
struct dscbiterator *it;
struct dscb *record;
int rc;
rc = lzds_dasd_read_vlabel(info->dasd);
if (rc) {
zt_error_print("error when reading label from device:"
" rc=%d\n", rc);
exit(-1);
}
rc = lzds_dasd_alloc_rawvtoc(info->dasd);
if (rc == EINVAL) {
zt_error_print("dasdview: Cannot read VTOC because disk does"
" not contain valid VOL1 label.\n",
info->device);
exit(-1);
} else if (rc) {
zt_error_print("error when reading vtoc from device:"
" rc=%d\n", rc);
exit(-1);
}
rc = lzds_dasd_get_rawvtoc(info->dasd, &info->rawvtoc);
if (rc || !info->rawvtoc) {
zt_error_print("dasdview: libvtoc could not read vtoc\n");
exit(-1);
}
if (info->vtoc_info || info->vtoc_all)
dasdview_print_vtoc_info_raw(info);
rc = lzds_raw_vtoc_alloc_dscbiterator(info->rawvtoc, &it);
if (rc) {
zt_error_print("dasdview: could not allocate DSCB iterator\n");
exit(-1);
}
while (!lzds_dscbiterator_get_next_dscb(it, &record))
dasdview_print_vtoc_dscb(info, record);
lzds_dscbiterator_free(it);
}
static void dasdview_print_vtoc(dasdview_info_t *info)
{
if (info->raw_track_access)
dasdview_print_vtoc_raw(info);
else
dasdview_print_vtoc_standard(info);
}
static int
dasdview_print_format1(unsigned int size, unsigned char *dumpstr)
{
unsigned int i;
char asc[17], ebc[17];
for (i = 0; i < size; i++) {
if ((i / 16) * 16 == i) {
printf("\n| ");
strncpy(asc, (char *)dumpstr + i, 16);
strncpy(ebc, (char *)dumpstr + i, 16);
asc[16] = '\0';
ebc[16] = '\0';
}
printf("%02X", dumpstr[i]);
if (((i + 1) / 4) * 4 == i + 1)
printf(" ");
if (((i + 1) / 8) * 8 == i + 1)
printf(" ");
if (((i + 1) / 16) * 16 == i + 1) {
vtoc_ebcdic_dec(asc, asc, 16);
dot(asc);
dot(ebc);
printf("| %16.16s | %16.16s |", asc, ebc);
}
}
return 0;
}
static int
dasdview_print_format2(unsigned int size, unsigned char *dumpstr,
unsigned long long begin)
{
unsigned int i;
char asc[17], ebc[17];
for (i = 0; i < size; i++) {
if ((i / 8) * 8 == i) {
printf("\n | %13llu | %13llX | ",
begin + (unsigned long long)i,
begin + (unsigned long long)i);
strncpy(asc, (char *)dumpstr + i, 8);
strncpy(ebc, (char *)dumpstr + i, 8);
}
printf("%02X", dumpstr[i]);
if (((i + 1) / 4) * 4 == i + 1)
printf(" ");
if (((i + 1) / 8) * 8 == i + 1) {
vtoc_ebcdic_dec(asc, asc, 8);
dot(asc);
dot(ebc);
printf("| %8.8s | %8.8s |", asc, ebc);
}
}
return 0;
}
static void dasdview_view_standard(dasdview_info_t *info)
{
unsigned char dumpstr[DUMP_STRING_SIZE];
unsigned long long i = 0, j = 0, k = 0, count = 0;
int fd, rc;
unsigned long long a = 0;
int b = 0;
k = ((info->size) % 16LL);
if (k != 0)
info->size += (16LL - k);
fd = open(info->device, O_RDONLY);
if (fd == -1) {
zt_error_print("dasdview: open error\n"
"Unable to open device %s in read-only mode!\n",
info->device);
exit(-1);
}
j = (info->begin / SEEK_STEP);
k = (info->begin % SEEK_STEP);
/* seek in SEEK_STEP steps */
for (i = 1; i <= j; i++) {
rc = lseek64(fd, SEEK_STEP, SEEK_CUR);
if (rc == -1) {
printf("*** rc: %d (%d) ***\n", rc, errno);
printf("*** j: %llu ***\n", j);
printf("*** k: %llu ***\n", k);
printf("*** a: %llu ***\n", a);
printf("*** b: %d ***\n", b);
close(fd);
zt_error_print("dasdview: seek error\n"
"Unable to seek in device %s!\n",
info->device);
exit(-1);
}
b++;
a += SEEK_STEP;
}
if (k > 0) {
rc = lseek(fd, k, SEEK_CUR);
if (rc == -1) {
close(fd);
zt_error_print("dasdview: seek error\n"
"Unable to seek in device %s!\n",
info->device);
exit(-1);
}
}
j = info->size / DUMP_STRING_SIZE;
k = info->size % DUMP_STRING_SIZE;
if (info->format1) {
printf("+----------------------------------------+"
"------------------+------------------+\n");
printf("| HEXADECIMAL |"
" EBCDIC | ASCII |\n");
printf("| 01....04 05....08 09....12 13....16 |"
" 1.............16 | 1.............16 |\n");
printf("+----------------------------------------+"
"------------------+------------------+");
} else if (info->format2) {
printf(" +---------------+---------------+----------------"
"------+----------+----------+\n");
printf(" | BYTE | BYTE | HEXADECIMAL"
" | EBCDIC | ASCII |\n");
printf(" | DECIMAL | HEXADECIMAL | 1 2 3 4 5 6 "
"7 8 | 12345678 | 12345678 |\n");
printf(" +---------------+---------------+----------------"
"------+----------+----------+");
}
count = info->begin;
for (i = 1; i <= j; i++) {
bzero(dumpstr, DUMP_STRING_SIZE);
rc = read(fd, &dumpstr, DUMP_STRING_SIZE);
if (rc != DUMP_STRING_SIZE) {
close(fd);
zt_error_print("dasdview: read error\n"
"Unable to read from device %s!\n",
info->device);
exit(-1);
}
if (info->format1)
dasdview_print_format1(DUMP_STRING_SIZE, dumpstr);
else if (info->format2)
dasdview_print_format2(DUMP_STRING_SIZE, dumpstr,
count);
count += DUMP_STRING_SIZE;
}
if (k > 0) {
bzero(dumpstr, DUMP_STRING_SIZE);
rc = read(fd, &dumpstr, k);
if (rc != (int)k) {
close(fd);
zt_error_print("dasdview: read error\n"
"Unable to read from device %s!\n",
info->device);
exit(-1);
}
if (info->format1)
dasdview_print_format1((unsigned int)k, dumpstr);
else if (info->format2)
dasdview_print_format2((unsigned int)k, dumpstr,
count);
}
close(fd);
if (info->format1)
printf("\n+----------------------------------------+"
"------------------+------------------+\n\n");
else if (info->format2)
printf("\n +---------------+---------------+----------------"
"------+----------+----------+\n\n");
}
static void dasdview_print_format_raw(unsigned int size, char *dumpstr)
{
unsigned int i;
char asc[17], ebc[17];
unsigned int residual, count;
char *data;
data = dumpstr;
residual = size;
while (residual) {
/* we handle at most 16 bytes per line */
count = MIN(residual, 16u);
bzero(asc, 17);
bzero(ebc, 17);
printf("|");
memcpy(asc, data, count);
memcpy(ebc, data, count);
for (i = 0; i < 16; ++i) {
if ((i % 4) == 0)
printf(" ");
if ((i % 8) == 0)
printf(" ");
if (i < count)
printf("%02X", data[i]);
else
printf(" ");
}
vtoc_ebcdic_dec(asc, asc, count);
dot(asc);
dot(ebc);
printf(" | %16.16s | %16.16s |\n", asc, ebc);
data += count;
residual -= count;
}
}
/* gets the pointer to an eckd record structure in memory and
* prints a hex/ascii/ebcdic dump for it
*/
static void dasdview_print_raw_record(char *rec)
{
struct eckd_count *ecount;
unsigned int cyl, head;
ecount = (struct eckd_count *)rec;
/* Note: the first 5 bytes of the count area are the
* record ID and by convention these bytes are interpreted
* as CCHHR (or ccccCCChR for large volumes)
*/
cyl = vtoc_get_cyl_from_cchhb(&ecount->recid);
head = vtoc_get_head_from_cchhb(&ecount->recid);
printf("+-----------------------------------------"
"-------------------------------------+\n");
printf("| count area: "
" |\n");
printf("| hex: %016llX "
" |\n",
*((unsigned long long *)ecount));
printf("| cylinder: %9d "
" |\n", cyl);
printf("| head: %9d "
" |\n", head);
printf("| record: %9d "
" |\n", ecount->recid.b);
printf("| key length: %9d "
" |\n", ecount->kl);
printf("| data length: %9d "
" |\n", ecount->dl);
printf("+-----------------------------------------"
"-------------------------------------+\n");
printf("| key area: "
" |\n");
printf("| HEXADECIMAL |"
" EBCDIC | ASCII |\n");
printf("| 01....04 05....08 09....12 13....16 |"
" 1.............16 | 1.............16 |\n");
printf("+----------------------------------------+"
"------------------+------------------+\n");
dasdview_print_format_raw(ecount->kl, rec + sizeof(*ecount));
printf("+----------------------------------------+"
"------------------+------------------+\n");
printf("| data area: "
" |\n");
printf("| HEXADECIMAL |"
" EBCDIC | ASCII |\n");
printf("| 01....04 05....08 09....12 13....16 |"
" 1.............16 | 1.............16 |\n");
printf("+----------------------------------------+"
"------------------+------------------+\n");
dasdview_print_format_raw(ecount->dl,
rec + sizeof(*ecount) + ecount->kl);
printf("+----------------------------------------+"
"------------------+------------------+\n");
}
static void dasdview_print_raw_track(char *trackdata,
unsigned int cyl,
unsigned int head)
{
struct eckd_count *ecount;
char *data;
u_int32_t record;
record = 0;
data = trackdata;
do {
printf("cylinder %u, head %u, record %u\n",
cyl, head, record);
dasdview_print_raw_record(data);
printf("\n");
ecount = (struct eckd_count *)data;
data += sizeof(*ecount) + ecount->kl + ecount->dl;
++record;
if ((*(unsigned long long *)data) == ENDTOKEN)
break;
if ((unsigned long)data >=
(unsigned long)trackdata + RAWTRACKSIZE)
break;
} while (1);
}
static void dasdview_view_raw(dasdview_info_t *info)
{
u_int64_t residual, trckstart, trckend, track, trckbuffsize;
u_int64_t tracks_to_read, trckcount, i;
char *trackdata;
char *data;
int rc;
struct dasdhandle *dasdh;
trckstart = info->begin / RAWTRACKSIZE;
tracks_to_read = info->size / RAWTRACKSIZE;
/* TODO: how large should we make our buffer?
* The DASD device driver cannot read more than 16 tracks at once
* but we can read a larger blob and the block layer will split up
* the requests for us.
*/
trckbuffsize = MIN(tracks_to_read, 16u);
/* track data must be page aligned for O_DIRECT */
trackdata = memalign(4096, trckbuffsize * RAWTRACKSIZE);
if (!trackdata) {
zt_error_print("failed to allocate memory\n");
exit(-1);
}
rc = lzds_dasd_alloc_dasdhandle(info->dasd, &dasdh);
if (rc) {
zt_error_print("failed to allocate memory\n");
exit(-1);
}
rc = lzds_dasdhandle_open(dasdh);
if (rc) {
lzds_dasdhandle_free(dasdh);
zt_error_print("failed to open device\n");
exit(-1);
}
/* residual is the number of tracks we still have to read */
residual = tracks_to_read;
track = trckstart;
while (residual) {
trckcount = MIN(trckbuffsize, residual);
trckend = track + trckcount - 1;
rc = lzds_dasdhandle_read_tracks_to_buffer(dasdh, track,
trckend, trackdata);
if (rc) {
perror("Error on read");
exit(-1);
}
data = trackdata;
for (i = 0; i < trckcount; ++i) {
dasdview_print_raw_track(data, track / info->geo.heads,
track % info->geo.heads);
data += RAWTRACKSIZE;
++track;
}
residual -= trckcount;
}
free(trackdata);
rc = lzds_dasdhandle_close(dasdh);
lzds_dasdhandle_free(dasdh);
if (rc < 0) {
perror("Error on closing file");
exit(-1);
}
}
static void dasdview_view(dasdview_info_t *info)
{
if (info->raw_track_access)
dasdview_view_raw(info);
else
dasdview_view_standard(info);
}
static void
dasdview_print_characteristic(dasdview_info_t *info)
{
dasd_information2_t dasd_info = info->dasd_info;
printf("encrypted disk : %s\n",
(dasd_info.characteristics[46] & 0x80) ? "yes" : "no");
printf("solid state device : %s\n",
(dasd_info.characteristics[46] & 0x40) ? "yes" : "no");
}
int main(int argc, char *argv[])
{
dasdview_info_t info;
int oc;
unsigned long long max = 0LL;
char *begin_param_str = NULL;
char *size_param_str = NULL;
int rc;
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
bzero(&info, sizeof(info));
while (1) {
oc = util_opt_getopt_long(argc, argv);
switch (oc) {
case 'h':
util_prg_print_help();
util_opt_print_help();
exit(EXIT_SUCCESS);
case 'v':
util_prg_print_version();
exit(EXIT_SUCCESS);
case 'b':
begin_param_str = optarg;
info.action_specified = 1;
info.begin_specified = 1;
break;
case 's':
size_param_str = optarg;
info.action_specified = 1;
info.size_specified = 1;
break;
case '1':
info.format1 = 1;
info.format2 = 0;
break;
case '2':
info.format1 = 0;
info.format2 = 1;
break;
case 'i': /* print general DASD information and geometry */
info.action_specified = 1;
info.general_info = 1;
break;
case 'x': /* print extended DASD information */
info.action_specified = 1;
info.extended_info = 1;
break;
case 'j':
info.action_specified = 1;
info.volser = 1;
break;
case 't':
if (strcmp(optarg, "info") == 0) {
info.vtoc_info = 1;
} else if (strcmp(optarg, "f1") == 0) {
info.vtoc_f1 = 1;
} else if (strcmp(optarg, "f3") == 0) {
info.vtoc_f3 = 1;
} else if (strcmp(optarg, "f4") == 0) {
info.vtoc_f4 = 1;
} else if (strcmp(optarg, "f5") == 0) {
info.vtoc_f5 = 1;
} else if (strcmp(optarg, "f7") == 0) {
info.vtoc_f7 = 1;
} else if (strcmp(optarg, "f8") == 0) {
info.vtoc_f8 = 1;
} else if (strcmp(optarg, "f9") == 0) {
info.vtoc_f9 = 1;
} else if (strcmp(optarg, "all") == 0) {
info.vtoc_all = 1;
} else {
zt_error_print("dasdview: usage error\n"
"%s is no valid argument for"
" option -t/--vtoc\n", optarg);
exit(-1);
}
info.vtoc = 1;
info.action_specified = 1;
break;
case 'l':
info.action_specified = 1;
info.vlabel_info = 1;
break;
case 'c':
info.action_specified = 1;
info.characteristic_specified = 1;
break;
case -1:
/* End of options string - start of devices list */
info.device_id = optind;
break;
default:
fprintf(stderr, "Try 'dasdview --help' for more"
" information.\n");
exit(1);
}
if (oc == -1)
break;
}
/* do some tests */
if (info.device_id >= argc) {
zt_error_print("dasdview: usage error\n"
"No device specified!");
exit(EXIT_FAILURE);
}
if (info.device_id + 1 < argc) {
zt_error_print("dasdview: usage error\n"
"More than one device specified!");
exit(EXIT_FAILURE);
}
if (info.device_id < argc)
strcpy(info.device, argv[info.device_id]);
dasdview_get_info(&info);
if (info.raw_track_access) {
rc = lzds_zdsroot_alloc(&info.zdsroot);
if (rc) {
zt_error_print("Could not allocate index\n");
exit(-1);
}
rc = lzds_zdsroot_add_device(info.zdsroot, info.device,
&info.dasd);
if (rc) {
zt_error_print("Could not add device to index\n");
exit(-1);
}
}
if (info.begin_specified)
dasdview_parse_input(&info.begin, &info, begin_param_str);
else
info.begin = DEFAULT_BEGIN;
if (info.raw_track_access)
max = (unsigned long long)info.hw_cylinders *
(unsigned long long)info.geo.heads * RAWTRACKSIZE;
else
max = (unsigned long long)info.hw_cylinders *
(unsigned long long)info.geo.heads *
(unsigned long long)info.geo.sectors *
(unsigned long long)info.blksize;
if (info.begin > max) {
zt_error_print("dasdview: usage error\n"
"'begin' value is not within disk range!");
exit(-1);
}
if (info.size_specified)
dasdview_parse_input(&info.size, &info, size_param_str);
else if (info.raw_track_access)
info.size = RAWTRACKSIZE;
else
info.size = DEFAULT_SIZE;
if ((info.begin_specified || info.size_specified) &&
((info.begin + info.size) > max)) {
zt_error_print("dasdview: usage error\n"
"'begin' + 'size' is not within "
"disk range!");
exit(-1);
}
if ((info.begin_specified || info.size_specified) &&
(!info.format1 && !info.format2))
info.format1 = 1;
if ((info.format1 || info.format2) &&
(!info.size_specified && !info.begin_specified)) {
zt_error_print("dasdview: usage error\n"
"Options -1 or -2 make only sense with "
"options -b or -s!");
exit(-1);
}
/* do the output */
if (info.begin_specified || info.size_specified)
dasdview_view(&info);
if (info.general_info || info.extended_info)
dasdview_print_general_info(&info);
if (info.extended_info)
dasdview_print_extended_info(&info);
if (info.volser)
dasdview_print_volser(&info);
if (info.vlabel_info)
dasdview_print_vlabel(&info);
if (info.vtoc)
dasdview_print_vtoc(&info);
if (!info.action_specified)
printf("No action specified.\n");
if (info.characteristic_specified)
dasdview_print_characteristic(&info);
return 0;
}