aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-02-03 02:38:23 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-02-03 02:38:23 +0000
commit6b32eacd43ada71e267506e510db11e8988cc7dc (patch)
tree394e5b9921dfd8bf199310581609e945f4b76e7d /src
parentd5890d56b6bcb6d1aa277f0bab78abb1ef66a88e (diff)
downloadsg3_utils-6b32eacd43ada71e267506e510db11e8988cc7dc.tar.gz
sg_rep_zones: add --brief option and --find ZT option; sg_modes: improve handling of zbc disks with pdt=0x14
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@935 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_logs.c150
-rw-r--r--src/sg_modes.c13
-rw-r--r--src/sg_rep_zones.c295
-rw-r--r--src/sg_senddiag.c25
4 files changed, 364 insertions, 119 deletions
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 26e1b477..2fce0b5a 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -36,7 +36,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.93 20220127"; /* spc6r06 + sbc5r01 */
+static const char * version_str = "1.94 20220201"; /* spc6r06 + sbc5r01 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -3112,7 +3112,7 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
const uint8_t * bp;
const char * cp;
char str[PCB_STR_LEN];
- char b[256];
+ char b[512];
char bb[32];
bool full, decoded;
bool has_header = false;
@@ -3305,8 +3305,8 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
} /* end of switch statement */
if ((! decoded) && full) {
- printf(" parameter code = 0x%x, contents in hex:\n", pc);
- hex2stdout(bp, param_len, 1);
+ hex2str(bp, param_len, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf(" parameter code = 0x%x, contents in hex:\n%s", pc, b);
} else
printf("\n");
if (op->do_pcb)
@@ -4132,6 +4132,7 @@ show_format_status_page(const uint8_t * resp, int len,
const uint8_t * xp;
uint64_t ull;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Format status page [0x8]\n");
@@ -4160,8 +4161,9 @@ show_format_status_page(const uint8_t * resp, int len,
if (sg_all_ffs(bp + 4, pl - 4))
printf(" Format data out: <not available>\n");
else {
- printf(" Format data out:\n");
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf(" Format data out:\n%s", b);
}
}
is_count = false;
@@ -4181,7 +4183,8 @@ show_format_status_page(const uint8_t * resp, int len,
default:
printf(" Unknown Format parameter code = 0x%x\n", pc);
is_count = false;
- hex2stdout(bp, pl, 0);
+ hex2str(bp, pl, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
}
if (is_count) {
@@ -4543,7 +4546,7 @@ show_dt_device_status_page(const uint8_t * resp, int len,
int num, pl, pc, j;
const uint8_t * bp;
char str[PCB_STR_LEN];
- char b[64];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("DT device status page (ssc-3, adc-3) [0x11]\n");
@@ -4621,7 +4624,8 @@ show_dt_device_status_page(const uint8_t * resp, int len,
pl);
break;
}
- hex2stdout(bp + 4, 8, 1);
+ hex2str(bp + 4, 8, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
case 0x3:
printf(" Key management error data (hex only now):\n");
@@ -4634,7 +4638,8 @@ show_dt_device_status_page(const uint8_t * resp, int len,
pl);
break;
}
- hex2stdout(bp + 4, 12, 1);
+ hex2str(bp + 4, 12, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
default:
if ((pc >= 0x101) && (pc <= 0x1ff)) {
@@ -4651,14 +4656,20 @@ show_dt_device_status_page(const uint8_t * resp, int len,
sg_get_unaligned_be64(bp + 8));
} else {
printf(" non-SAS transport, in hex:\n");
- hex2stdout(bp + 4, ((pl < num) ? pl : num) - 4, 0);
+ hex2str(bp + 4, ((pl < num) ? pl : num) - 4, " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
} else if (pc >= 0x8000) {
printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
} else {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
}
break;
}
@@ -4681,6 +4692,7 @@ show_tapealert_response_page(const uint8_t * resp, int len,
int num, pl, pc, k, mod, div;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("TapeAlert response page (ssc-3, adc-3) [0x12]\n");
@@ -4721,10 +4733,14 @@ show_tapealert_response_page(const uint8_t * resp, int len,
default:
if (pc <= 0x8000) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
} else {
printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
break;
}
@@ -4770,6 +4786,7 @@ show_requested_recovery_page(const uint8_t * resp, int len,
int num, pl, pc, j, k;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Requested recovery page (ssc-3) [0x13]\n");
@@ -4805,10 +4822,14 @@ show_requested_recovery_page(const uint8_t * resp, int len,
default:
if (pc <= 0x8000) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
} else {
printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
break;
}
@@ -4832,6 +4853,7 @@ show_ata_pt_results_page(const uint8_t * resp, int len,
const uint8_t * bp;
const uint8_t * dp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("ATA pass-through results page (sat-2) [0x16]\n");
@@ -4869,11 +4891,15 @@ show_ata_pt_results_page(const uint8_t * resp, int len,
printf(" device=0x%x status=0x%x\n", dp[12], dp[13]);
} else if (pl > 17) {
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
} else {
printf(" short parameter length: %d [parameter_code=0x%x]:\n",
pl, pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -4921,6 +4947,7 @@ show_background_scan_results_page(const uint8_t * resp, int len,
int j, m, num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Background scan results page [0x15]\n");
@@ -4987,7 +5014,9 @@ show_background_scan_results_page(const uint8_t * resp, int len,
else
printf(" Medium scan parameter # %d [0x%x], "
"reserved\n", pc, pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
} else
printf(" Medium scan parameter # %d [0x%x]\n", pc, pc);
@@ -5050,6 +5079,7 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len,
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Zoned block device statistics page [0x14,0x1]\n");
@@ -5196,7 +5226,9 @@ show_zoned_block_dev_stats(const uint8_t * resp, int len,
break;
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
}
if (trunc)
@@ -5299,6 +5331,7 @@ show_background_op_page(const uint8_t * resp, int len,
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Background operation page [0x15,0x2]\n");
@@ -5334,7 +5367,9 @@ show_background_op_page(const uint8_t * resp, int len,
break;
default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
- hex2stdout(bp, ((pl < num) ? pl : num), 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
}
if (op->do_pcb)
@@ -5357,6 +5392,7 @@ show_lps_misalignment_page(const uint8_t * resp, int len,
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("LPS misalignment page [0x15,0x3]\n");
@@ -5396,7 +5432,9 @@ show_lps_misalignment_page(const uint8_t * resp, int len,
pc, bp[4]);
} else {
printf("<unexpected pc=0x%x>\n", pc);
- hex2stdout(bp, pl, 0);
+ hex2str(bp, ((pl < num) ? pl : num), " ",
+ 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
break;
}
@@ -5419,6 +5457,7 @@ show_service_buffer_info_page(const uint8_t * resp, int len,
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Service buffer information page (adc-3) [0x15]\n");
@@ -5449,11 +5488,13 @@ show_service_buffer_info_page(const uint8_t * resp, int len,
} else if (pc < 0x8000) {
printf(" parameter_code=0x%x, Reserved, parameter in hex:\n",
pc);
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
} else {
printf(" parameter_code=0x%x, Vendor-specific, parameter in "
"hex:\n", pc);
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -5588,6 +5629,7 @@ show_device_stats_page(const uint8_t * resp, int len,
int num, pl, pc;
const uint8_t * bp;
char str[PCB_STR_LEN];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Device statistics page (ssc-3 and adc)\n");
@@ -5719,7 +5761,9 @@ show_device_stats_page(const uint8_t * resp, int len,
default:
vl_num = false;
printf(" Reserved parameter code [0x%x] data in hex:\n", pc);
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
break;
}
if (vl_num)
@@ -5742,7 +5786,9 @@ show_device_stats_page(const uint8_t * resp, int len,
"hex:\n", pc);
else
printf(" Reserved parameter [0x%x], dump in hex:\n", pc);
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
break;
}
}
@@ -5949,11 +5995,11 @@ static bool
show_tape_diag_data_page(const uint8_t * resp, int len,
const struct opts_t * op)
{
- int k, num, pl, pc;
+ int k, n, num, pl, pc;
unsigned int v;
const uint8_t * bp;
char str[PCB_STR_LEN];
- char b[80];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Tape diagnostics data page (ssc-3) [0x16]\n");
@@ -6000,24 +6046,25 @@ show_tape_diag_data_page(const uint8_t * resp, int len,
if (sg_all_zeros(bp + 32, 32))
printf(" Medium id number is 32 bytes of zero\n");
else {
- printf(" Medium id number (in hex):\n");
- hex2stdout(bp + 32, 32, 0);
+ hex2str(bp + 32, 32, " ", 0 /* with ASCII */, sizeof(b), b);
+ printf(" Medium id number (in hex):\n%s", b);
}
printf(" Timestamp origin: 0x%x\n", bp[64] & 0xf);
// Check Timestamp for all zeros
- for (k = 66; k < 72; ++k) {
- if(bp[k])
- break;
- }
- if (72 == k)
+ if (sg_all_zeros(bp + 66, 6))
printf(" Timestamp is all zeros:\n");
else {
- printf(" Timestamp:\n");
- hex2stdout(bp + 66, 6, 1);
+ hex2str(bp + 66, 6, NULL, 1 /* no ASCII */, sizeof(b), b);
+ printf(" Timestamp: %s", b);
}
if (pl > 72) {
+ n = pl - 72;
+ k = hex2str(bp + 72, n, " ", 0 /* with ASCII */,
+ sizeof(b), b);
printf(" Vendor specific:\n");
- hex2stdout(bp + 72, pl - 72, 0);
+ printf("%s", b);
+ if (k >= (int)sizeof(b) - 1)
+ printf(" <truncated>\n");
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -6039,7 +6086,7 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len,
unsigned int v;
const uint8_t * bp;
char str[PCB_STR_LEN];
- char b[80];
+ char b[512];
if (op->verbose || ((! op->do_raw) && (0 == op->do_hex)))
printf("Media changer diagnostics data page (smc-3) [0x16]\n");
@@ -6104,12 +6151,16 @@ show_mchanger_diag_data_page(const uint8_t * resp, int len,
printf(" Destination address: 0x%x\n", v);
if (pl > 91) {
printf(" Volume tag information:\n");
- hex2stdout((bp + 56), 36, 0);
+ hex2str(bp + 56, 36, " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
}
if (pl > 99) {
printf(" Timestamp origin: 0x%x\n", bp[92] & 0xf);
printf(" Timestamp:\n");
- hex2stdout((bp + 94), 6, 1);
+ hex2str(bp + 94, 6, " ", 1 /* no ASCII */,
+ sizeof(b), b);
+ printf("%s", b);
}
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
@@ -6202,7 +6253,7 @@ show_volume_stats_pages(const uint8_t * resp, int len,
bool spf;
const uint8_t * bp;
char str[PCB_STR_LEN];
- char b[64];
+ char b[512];
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
@@ -6414,7 +6465,8 @@ show_volume_stats_pages(const uint8_t * resp, int len,
else
printf(" Reserved parameter code (0x%x), payload in hex\n",
pc);
- hex2stdout(bp + 4, pl - 4, 0);
+ hex2str(bp + 4, pl - 4, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
break;
}
if (op->do_pcb)
@@ -6735,6 +6787,7 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op)
bool spf;
bool done = false;
const struct log_elem * lep;
+ char b[512];
if (len < 3) {
pr2serr("%s: response has bad length: %d\n", __func__, len);
@@ -6764,12 +6817,15 @@ decode_page_contents(const uint8_t * resp, int len, struct opts_t * op)
else
printf("Unable to decode page = 0x%x, here is hex:\n", pg_code);
if (len > 128) {
- hex2stdout(resp, 64, 1);
+ hex2str(resp, 64, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
"see the rest)]\n", len);
}
- else
- hex2stdout(resp, len, 1);
+ else {
+ hex2str(resp, len, " ", 1 /* no ASCII */, sizeof(b), b);
+ printf("%s", b);
+ }
}
}
diff --git a/src/sg_modes.c b/src/sg_modes.c
index c0fc87f0..2eead452 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2021 D. Gilbert
+ * Copyright (C) 2000-2022 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.74 20210803";
+static const char * version_str = "1.75 20220202";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -880,8 +880,7 @@ static const char *
find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
bool encserv, bool mchngr, int t_proto)
{
- int k;
- int num;
+ int k, num, decayed_pdt;
const struct page_code_desc * pcdp;
if (t_proto >= 0) {
@@ -896,6 +895,7 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
}
}
}
+try_again:
pcdp = get_mpage_tbl_size(scsi_ptype, &num);
if (pcdp) {
for (k = 0; k < num; ++k, ++pcdp) {
@@ -906,6 +906,11 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
break;
}
}
+ decayed_pdt = sg_lib_pdt_decay(scsi_ptype);
+ if (decayed_pdt != scsi_ptype) {
+ scsi_ptype = decayed_pdt;
+ goto try_again;
+ }
if ((0xd != scsi_ptype) && encserv) {
/* check for attached enclosure services processor */
pcdp = get_mpage_tbl_size(0xd, &num);
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 02c8953c..c77bd785 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -39,11 +39,11 @@
* Based on zbc2r10.pdf
*/
-static const char * version_str = "1.30 20220128";
+static const char * version_str = "1.31 20220201";
#define WILD_RZONES_BUFF_LEN (1 << 28)
-#define MAX_RZONES_BUFF_LEN (1024 * 1024)
-#define DEF_RZONES_BUFF_LEN (1024 * 8)
+#define MAX_RZONES_BUFF_LEN (2 * 1024 * 1024)
+#define DEF_RZONES_BUFF_LEN (1024 * 16)
#define SG_ZONING_IN_CMDLEN 16
@@ -51,6 +51,7 @@ static const char * version_str = "1.30 20220128";
#define REPORT_ZONE_DOMAINS_SA 0x7
#define REPORT_REALMS_SA 0x6
+#define REPORT_ZONES_DESC_LEN 64
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
#define DEF_PT_TIMEOUT 60 /* 60 seconds */
@@ -69,6 +70,7 @@ struct opts_t {
int do_help;
int do_hex;
int do_num;
+ int find_zt; /* negative values: find first not equal to */
int maxlen;
int reporting_opt;
int vb;
@@ -76,12 +78,17 @@ struct opts_t {
const char * in_fn;
};
+struct zt_num2abbrev_t {
+ int ztn;
+ const char * abbrev;
+};
static struct option long_options[] = {
{"brief", no_argument, 0, 'b'}, /* only header and last descriptor */
{"domain", no_argument, 0, 'd'},
{"domains", no_argument, 0, 'd'},
{"force", no_argument, 0, 'f'},
+ {"find", required_argument, 0, 'F'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
{"in", required_argument, 0, 'i'}, /* silent, same as --inhex= */
@@ -102,22 +109,58 @@ static struct option long_options[] = {
{0, 0, 0, 0},
};
+static struct zt_num2abbrev_t zt_num2abbrev[] = {
+ {0, "none"},
+ {1, "c"}, /* conventionial */
+ {2, "swr"}, /* sequential write required */
+ {3, "swp"}, /* sequential write preferred */
+ {4, "sobr"}, /* sequential or before required */
+ {5, "g"}, /* gap */
+ {-1, NULL}, /* sentinel */
+};
+
+static const char * zn_dnum_s = "zone descriptor number: ";
+
+
+static void
+prn_zone_type_abbrevs(void)
+{
+ const struct zt_num2abbrev_t * n2ap = zt_num2abbrev;
+ char b[32];
+
+ pr2serr("Zone type number\tAbbreviation\tName\n");
+ pr2serr("----------------\t------------\t----\n");
+ for ( ; n2ap->abbrev; ++n2ap) {
+ if (n2ap == zt_num2abbrev)
+ pr2serr("\t%d\t\t%s\t\t[reserved]\n",
+ n2ap->ztn, n2ap->abbrev);
+ else
+ pr2serr("\t%d\t\t%s\t\t%s\n", n2ap->ztn, n2ap->abbrev,
+ sg_get_zone_type_str(n2ap->ztn, sizeof(b), b));
+ }
+}
static void
usage(int h)
{
if (h > 1) goto h_twoormore;
pr2serr("Usage: "
- "sg_rep_zones [--domain] [--force] [--help] [--hex] "
- "[--inhex=FN]\n"
- " [--locator=LBA] [--maxlen=LEN] "
- "[--partial] [--only]\n"
- " [--raw] [--readonly] [--realm] "
- "[--report=OPT]\n"
- " [--start=LBA] [--verbose] [--version] "
- "DEVICE\n");
+ "sg_rep_zones [--domain] [--find=ZT] [--force] [--help] "
+ "[--hex]\n"
+ " [--inhex=FN] [--locator=LBA] "
+ "[--maxlen=LEN]\n"
+ " [--partial] [--only] [--raw] "
+ "[--readonly]\n"
+ " [--realm] [--report=OPT] [--start=LBA] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n");
pr2serr(" where:\n"
" --domain|-d sends a REPORT ZONE DOMAINS command\n"
+ " --find=ZT|-F ZT find first zone with ZT zone type, "
+ "starting at LBA\n"
+ " if first character of ZT is - or !, "
+ "find first\n"
+ " zone that is not ZT\n"
" --force|-f bypass some sanity checks when decoding "
"response\n"
" --help|-h print out usage message, use twice for "
@@ -186,6 +229,8 @@ h_twoormore:
"Required zones\n"
" 0x3 list all realms that contain active Sequential Write "
"Preferred zones\n");
+ pr2serr("\n");
+ prn_zone_type_abbrevs();
}
/* Invokes a SCSI REPORT ZONES, REPORT ZONE DOMAINS or REPORT REALMS command
@@ -317,18 +362,44 @@ static const char * same_desc_arr[16] = {
"Reserved [0xc]", "Reserved [0xd]", "Reserved [0xe]", "Reserved [0xf]",
};
+static uint64_t
+prt_a_zn_desc(const uint8_t *bp, const struct opts_t * op)
+{
+ uint8_t zt, zc;
+ uint64_t lba, len, wp;
+ char b[80];
+
+ zt = bp[0] & 0xf;
+ zc = (bp[1] >> 4) & 0xf;
+ printf(" Zone type: %s\n", sg_get_zone_type_str(zt, sizeof(b), b));
+ printf(" Zone condition: %s\n", zone_condition_str(zc, b,
+ sizeof(b), op->vb));
+ printf(" PUEP: %d\n", !!(bp[1] & 0x4)); /* added in zbc2r07 */
+ printf(" Non_seq: %d\n", !!(bp[1] & 0x2));
+ printf(" Reset: %d\n", bp[1] & 0x1);
+ len = sg_get_unaligned_be64(bp + 8);
+ printf(" Zone Length: 0x%" PRIx64 "\n", len);
+ lba = sg_get_unaligned_be64(bp + 16);
+ printf(" Zone start LBA: 0x%" PRIx64 "\n", lba);
+ wp = sg_get_unaligned_be64(bp + 24);
+ if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp)))
+ printf(" Write pointer LBA: -1\n");
+ else
+ printf(" Write pointer LBA: 0x%" PRIx64 "\n", wp);
+ return lba + len;
+}
+
static int
decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len,
const struct opts_t * op)
{
- uint8_t zt;
- int k, same, zc, num_zd;
- uint64_t wp, ul, ul2, mx_lba;
+ int k, same, num_zd;
+ uint64_t wp, ul, mx_lba;
const uint8_t * bp;
- char b[80];
if ((uint32_t)act_len < decod_len) {
- num_zd = (act_len >= 64) ? ((act_len - 64) / 64): 0;
+ num_zd = (act_len >= 64) ? ((act_len - 64) / REPORT_ZONES_DESC_LEN)
+ : 0;
if (act_len == op->maxlen) {
if (op->maxlen_given)
pr2serr("decode length [%u bytes] may be constrained by "
@@ -338,10 +409,15 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len,
} else if (op->in_fn)
pr2serr("perhaps %s has been truncated\n", op->in_fn);
} else
- num_zd = (decod_len - 64) / 64;
+ num_zd = (decod_len - 64) / REPORT_ZONES_DESC_LEN;
same = rzBuff[4] & 0xf;
mx_lba = sg_get_unaligned_be64(rzBuff + 8);
- if (! op->wp_only) {
+ if (op->wp_only) {
+ ;
+ } else if (op->do_hex) {
+ hex2stdout(rzBuff, 64, -1);
+ printf("\n");
+ } else {
printf(" Same=%d: %s\n", same, same_desc_arr[same]);
printf(" Maximum LBA: 0x%" PRIx64 "\n\n", mx_lba);
printf(" Reported zone starting LBA granularity: 0x%" PRIx64 "\n\n",
@@ -349,61 +425,54 @@ decode_rep_zones(const uint8_t * rzBuff, int act_len, uint32_t decod_len,
}
if (op->do_num > 0)
num_zd = (num_zd > op->do_num) ? op->do_num : num_zd;
- if (((uint32_t)act_len < decod_len) && ((num_zd * 64) + 64 > act_len)) {
+ if (((uint32_t)act_len < decod_len) &&
+ ((num_zd * REPORT_ZONES_DESC_LEN) + 64 > act_len)) {
pr2serr("Skip due to truncated response, try using --num= to a "
"value less than %d\n", num_zd);
return SG_LIB_CAT_MALFORMED;
}
if (op->do_brief && (num_zd > 0)) {
- bp = rzBuff + 64 + ((num_zd - 1) * 64);
+ bp = rzBuff + 64 + ((num_zd - 1) * REPORT_ZONES_DESC_LEN);
+ if (op->do_hex) {
+ if (op->wp_only)
+ hex2stdout(bp + 24, 8, -1);
+ else
+ hex2stdout(bp, 64, -1);
+ return 0;
+ }
printf("From last descriptor in this response:\n");
- ul = sg_get_unaligned_be64(bp + 16);
- printf(" Zone start LBA: 0x%" PRIx64 "\n", ul);
- ul2 = sg_get_unaligned_be64(bp + 8);
- printf(" Zone Length: 0x%" PRIx64 "\n", ul2);
- ul = ul + ul2;
+ printf(" %s%d\n", zn_dnum_s, num_zd - 1);
+ ul = prt_a_zn_desc(bp, op);
if (ul > mx_lba)
- printf(" This zone seems to be the last one\n");
+ printf(" >> This zone seems to be the last one\n");
else
- printf(" Probable next Zone start LBA: 0x%" PRIx64 "\n", ul);
+ printf(" >> Probable next Zone start LBA: 0x%" PRIx64 "\n", ul);
return 0;
}
- for (k = 0, bp = rzBuff + 64; k < num_zd; ++k, bp += 64) {
+ for (k = 0, bp = rzBuff + 64; k < num_zd;
+ ++k, bp += REPORT_ZONES_DESC_LEN) {
if (! op->wp_only)
- printf(" Zone descriptor: %d\n", k);
+ printf(" %s%d\n", zn_dnum_s, k);
if (op->do_hex) {
hex2stdout(bp, 64, -1);
continue;
}
if (op->wp_only) {
- wp = sg_get_unaligned_be64(bp + 24);
- if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp)))
- printf("-1\n");
- else
- printf("0x%" PRIx64 "\n", wp);
+ if (op->do_hex)
+ hex2stdout(bp + 24, 8, -1);
+ else {
+ wp = sg_get_unaligned_be64(bp + 24);
+ if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp)))
+ printf("-1\n");
+ else
+ printf("0x%" PRIx64 "\n", wp);
+ }
continue;
}
- zt = bp[0] & 0xf;
- zc = (bp[1] >> 4) & 0xf;
- printf(" Zone type: %s\n", sg_get_zone_type_str(zt, sizeof(b),
- b));
- printf(" Zone condition: %s\n", zone_condition_str(zc, b,
- sizeof(b), op->vb));
- printf(" PUEP: %d\n", !!(bp[1] & 0x4)); /* added in zbc2r07 */
- printf(" Non_seq: %d\n", !!(bp[1] & 0x2));
- printf(" Reset: %d\n", bp[1] & 0x1);
- printf(" Zone Length: 0x%" PRIx64 "\n",
- sg_get_unaligned_be64(bp + 8));
- printf(" Zone start LBA: 0x%" PRIx64 "\n",
- sg_get_unaligned_be64(bp + 16));
- wp = sg_get_unaligned_be64(bp + 24);
- if (sg_all_ffs((const uint8_t *)&wp, sizeof(wp)))
- printf(" Write pointer LBA: -1\n");
- else
- printf(" Write pointer LBA: 0x%" PRIx64 "\n", wp);
+ prt_a_zn_desc(bp, op);
}
- if ((op->do_num == 0) && (! op->wp_only)) {
- if ((64 + (64 * (uint32_t)num_zd)) < decod_len)
+ if ((op->do_num == 0) && (! op->wp_only) && (! op->do_hex)) {
+ if ((64 + (REPORT_ZONES_DESC_LEN * (uint32_t)num_zd)) < decod_len)
printf("\n>>> Beware: Zone list truncated, may need another "
"call\n");
}
@@ -532,11 +601,89 @@ decode_rep_zdomains(const uint8_t * rzBuff, int act_len,
return 0;
}
+static int
+find_report_zones(int sg_fd, uint8_t * rzBuff, const char * cmd_name,
+ struct opts_t * op)
+{
+ bool found = false;
+ uint8_t zt;
+ int k, res, resid, rlen, num_zd;
+ uint32_t zn_dnum = 0;
+ uint64_t slba = op->st_lba;
+ uint64_t mx_lba = 0;
+ const uint8_t * bp = rzBuff;
+ char b[96];
+
+ k = 0;
+ while (true) {
+ resid = 0;
+ res = sg_ll_report_zzz(sg_fd, REPORT_ZONES_SA, slba,
+ true /* set partial */, op->reporting_opt,
+ rzBuff, op->maxlen, &resid, true, op->vb);
+ if (res) {
+ if (SG_LIB_CAT_INVALID_OP == res)
+ pr2serr("%s: %s%u, %s command not supported\n", __func__,
+ zn_dnum_s, zn_dnum, cmd_name);
+ else {
+ sg_get_category_sense_str(res, sizeof(b), b, op->vb);
+ pr2serr("%s: %s%u, %s command: %s\n", __func__,
+ zn_dnum_s, zn_dnum, cmd_name, b);
+ }
+ break;
+ }
+ rlen = op->maxlen - resid;
+ if (rlen <= 64) {
+ break;
+ }
+ mx_lba = sg_get_unaligned_be64(rzBuff + 8);
+ num_zd = (rlen - 64) / REPORT_ZONES_DESC_LEN;
+ for (k = 0, bp = rzBuff + 64; k < num_zd;
+ ++k, bp += REPORT_ZONES_DESC_LEN, ++zn_dnum) {
+ zt = 0xf & bp[0];
+ if (op->find_zt > 0) {
+ if ((uint8_t)op->find_zt == zt )
+ break;
+ } else if (op->find_zt < 0) {
+ if ((uint8_t)(-op->find_zt) != zt )
+ break;
+ }
+ slba = sg_get_unaligned_be64(bp + 16) +
+ sg_get_unaligned_be64(bp + 8);
+ }
+ if (k < num_zd) {
+ found = true;
+ break;
+ } else if (slba > mx_lba)
+ break;
+ }
+ if (res == 0) {
+ if (found) {
+ if (op->do_hex) {
+ hex2stdout(rzBuff, 64, -1);
+ printf("\n");
+ hex2stdout(bp, 64, -1);
+ } else {
+ printf("Condition met at:\n");
+ printf(" %s: %d\n", zn_dnum_s, zn_dnum);
+ prt_a_zn_desc(bp, op);
+ }
+ } else {
+ if (op->do_hex) {
+ memset(b, 0xff, 64);
+ hex2stdout((const uint8_t *)b, 64, -1);
+ } else
+ printf("Condition NOT met; next %s%u\n", zn_dnum_s, zn_dnum);
+ }
+ }
+ return res;
+}
+
+
int
main(int argc, char * argv[])
{
bool no_final_msg = false;
- int res, c, act_len, rlen, in_len;
+ int res, c, act_len, rlen, in_len, off;
int sg_fd = -1;
int resid = 0;
int ret = 0;
@@ -555,8 +702,8 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "bdefhHi:l:m:n:o:prRs:vVw", long_options,
- &option_index);
+ c = getopt_long(argc, argv, "bdefF:hHi:l:m:n:o:prRs:vVw",
+ long_options, &option_index);
if (c == -1)
break;
@@ -575,6 +722,31 @@ main(int argc, char * argv[])
case 'f':
op->do_force = true;
break;
+ case 'F':
+ off = (('-' == *optarg) || ('!' == *optarg)) ? 1 : 0;
+ if (isdigit(*(optarg + off))) {
+ op->find_zt = sg_get_num_nomult(optarg + off);
+ if (op->find_zt < 0) {
+ pr2serr("bad numeric argument to '--find='\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (off)
+ op->find_zt = -op->find_zt; /* find first not equal */
+ } else { /* check for abbreviation */
+ struct zt_num2abbrev_t * zn2ap = zt_num2abbrev;
+
+ for ( ; zn2ap->abbrev; ++zn2ap) {
+ if (0 == strcmp(optarg + off, zn2ap->abbrev))
+ break;
+ }
+ if (NULL == zn2ap->abbrev) {
+ pr2serr("bad abbreviation argument to '--find='\n\n");
+ prn_zone_type_abbrevs();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->find_zt = off ? -zn2ap->ztn : zn2ap->ztn;
+ }
+ break;
case 'h':
case '?':
++op->do_help;
@@ -758,6 +930,10 @@ main(int argc, char * argv[])
goto the_end;
}
+ if (op->find_zt) { /* so '-F none' will drop through */
+ ret = find_report_zones(sg_fd, rzBuff, cmd_name, op);
+ goto the_end;
+ }
res = sg_ll_report_zzz(sg_fd, serv_act, op->st_lba, op->do_partial,
op->reporting_opt, rzBuff, op->maxlen, &resid,
true, op->vb);
@@ -782,7 +958,8 @@ start_response:
if ((REPORT_ZONES_SA == serv_act) && (! op->do_partial)) {
printf("%u zones starting from LBA 0x%" PRIx64 " available "
"but only %d zones returned\n",
- (decod_len - 64) / 64, op->st_lba, (rlen - 64) / 64);
+ (decod_len - 64) / REPORT_ZONES_DESC_LEN, op->st_lba,
+ (rlen - 64) / REPORT_ZONES_DESC_LEN);
decod_len = rlen;
act_len = rlen;
} else {
@@ -806,7 +983,7 @@ start_response:
hex2stdout(rzBuff, act_len, ((1 == op->do_hex) ? 1 : -1));
goto the_end;
}
- if (! op->wp_only)
+ if (! op->wp_only && (! op->do_hex))
printf("%s response:\n", cmd_name);
if (act_len < 64) {
pr2serr("Zone length [%d] too short (perhaps after truncation\n)",
diff --git a/src/sg_senddiag.c b/src/sg_senddiag.c
index 6539d79d..7e82dd47 100644
--- a/src/sg_senddiag.c
+++ b/src/sg_senddiag.c
@@ -1,6 +1,6 @@
/*
* A utility program originally written for the Linux OS SCSI subsystem
- * Copyright (C) 2003-2021 D. Gilbert
+ * Copyright (C) 2003-2022 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -34,7 +34,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "0.64 20210610";
+static const char * version_str = "0.65 20220128";
#define ME "sg_senddiag: "
@@ -836,16 +836,23 @@ main(int argc, char * argv[])
num = sg_msense_calc_length(rsp_buff, 32, false, &bd_len);
num -= (8 /* MS(10) header length */ + bd_len);
if (num >= 0xc) {
- int secs;
-
- secs = sg_get_unaligned_be16(rsp_buff + 8 + bd_len + 10);
+ int secs = sg_get_unaligned_be16(rsp_buff + 8 + bd_len + 10);
+
+ if (0xffff == secs) {
+ if (op->verbose > 1)
+ printf("Expected extended self-test duration's value "
+ "[65535] indicates the\nsimilarly named field "
+ "in the Extended Inquiry VPD page should be "
+ "used\n");
+ } else {
#ifdef SG_LIB_MINGW
- printf("Expected extended self-test duration=%d seconds "
- "(%g minutes)\n", secs, secs / 60.0);
+ printf("Expected extended self-test duration=%d seconds "
+ "(%g minutes)\n", secs, secs / 60.0);
#else
- printf("Expected extended self-test duration=%d seconds "
- "(%.2f minutes)\n", secs, secs / 60.0);
+ printf("Expected extended self-test duration=%d seconds "
+ "(%.2f minutes)\n", secs, secs / 60.0);
#endif
+ }
} else
printf("Extended self-test duration not available\n");
} else {