/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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 :" " \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; }