diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2014-10-07 04:38:02 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2014-10-07 04:38:02 +0000 |
commit | 64f8f0d1f6171b12cfe23f774ee831d320772f00 (patch) | |
tree | 9e31a5c7fca3c057aaa1763cc8d12c76cd9438dc /src/sg_format.c | |
parent | fc92e18bc64fc037a85f2fe0d38cd7eb7ebc3cd2 (diff) | |
download | sg3_utils-64f8f0d1f6171b12cfe23f774ee831d320772f00.tar.gz |
sg_ll_inquiry(), sg_ll_mode_sense*(), sg_ll_log_sense(): use resid to clear unfilled data-in buffer; sg_format, sg_sanitize: output unit serial number and LU name prior to
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@613 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src/sg_format.c')
-rw-r--r-- | src/sg_format.c | 205 |
1 files changed, 182 insertions, 23 deletions
diff --git a/src/sg_format.c b/src/sg_format.c index 90ac932b..bbb28bfa 100644 --- a/src/sg_format.c +++ b/src/sg_format.c @@ -32,7 +32,7 @@ #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" -static const char * version_str = "1.29 20140921"; +static const char * version_str = "1.30 20141006"; #define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */ @@ -303,6 +303,180 @@ scsi_format(int fd, int fmtpinfo, int cmplst, int pf_usage, int immed, return 0; } +#define VPD_DEVICE_ID 0x83 +#define VPD_ASSOC_LU 0 +#define VPD_ASSOC_TPORT 1 +#define TPROTO_ISCSI 5 + +static char * +get_lu_name(const unsigned char * ucp, int u_len, char * b, int b_len) +{ + int len, off, sns_dlen, dlen, k; + unsigned char u_sns[512]; + char * cp; + + len = u_len - 4; + ucp += 4; + off = -1; + if (0 == sg_vpd_dev_id_iter(ucp, len, &off, VPD_ASSOC_LU, + 8 /* SCSI name string (sns) */, + 3 /* UTF-8 */)) { + sns_dlen = ucp[off + 3]; + memcpy(u_sns, ucp + off + 4, sns_dlen); + /* now want to check if this is iSCSI */ + off = -1; + if (0 == sg_vpd_dev_id_iter(ucp, len, &off, VPD_ASSOC_TPORT, + 8 /* SCSI name string (sns) */, + 3 /* UTF-8 */)) { + if ((0x80 & ucp[1]) && + (TPROTO_ISCSI == (ucp[0] >> 4))) { + snprintf(b, b_len, "%.*s", sns_dlen, u_sns); + return b; + } + } + } else + sns_dlen = 0; + if (0 == sg_vpd_dev_id_iter(ucp, len, &off, VPD_ASSOC_LU, + 3 /* NAA */, 1 /* binary */)) { + dlen = ucp[off + 3]; + if (! ((8 == dlen) || (16 ==dlen))) + return b; + cp = b; + for (k = 0; ((k < dlen) && (b_len > 1)); ++k) { + snprintf(cp, b_len, "%02x", ucp[off + 4 + k]); + cp += 2; + b_len -= 2; + } + } else if (0 == sg_vpd_dev_id_iter(ucp, len, &off, VPD_ASSOC_LU, + 2 /* EUI */, 1 /* binary */)) { + dlen = ucp[off + 3]; + if (! ((8 == dlen) || (12 == dlen) || (16 ==dlen))) + return b; + cp = b; + for (k = 0; ((k < dlen) && (b_len > 1)); ++k) { + snprintf(cp, b_len, "%02x", ucp[off + 4 + k]); + cp += 2; + b_len -= 2; + } + } else if (sns_dlen > 0) + snprintf(b, b_len, "%.*s", sns_dlen, u_sns); + return b; +} + +#define SAFE_STD_INQ_RESP_LEN 36 +#define VPD_SUPPORTED_VPDS 0x0 +#define VPD_UNIT_SERIAL_NUM 0x80 +#define VPD_DEVICE_ID 0x83 + +static int +print_dev_id(int fd, unsigned char * sinq_resp, int max_rlen, int verbose) +{ + int res, k, n, verb, pdt, has_sn, has_di; + unsigned char b[256]; + char a[256]; + char pdt_name[64]; + + verb = (verbose > 1) ? verbose - 1 : 0; + memset(sinq_resp, 0, max_rlen); + res = sg_ll_inquiry(fd, 0, 0 /* evpd */, 0 /* pg_op */, b, + SAFE_STD_INQ_RESP_LEN, 1, verb); + if (res) + return res; + n = b[4] + 5; + if (n > SAFE_STD_INQ_RESP_LEN) + n = SAFE_STD_INQ_RESP_LEN; + memcpy(sinq_resp, b, (n < max_rlen) ? n : max_rlen); + if (n == SAFE_STD_INQ_RESP_LEN) { + pdt = b[0] & 0x1f; + printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n", + (const char *)(b + 8), (const char *)(b + 16), + (const char *)(b + 32), + sg_get_pdt_str(pdt, sizeof(pdt_name), pdt_name), pdt); + if (verbose) + printf(" PROTECT=%d\n", !!(b[5] & 1)); + if (b[5] & 1) + printf(" << supports protection information>>" + "\n"); + } else { + fprintf(stderr, "Short INQUIRY response: %d bytes, expect at " + "least " "36\n", n); + return SG_LIB_CAT_OTHER; + } + res = sg_ll_inquiry(fd, 0, 1 /* evpd */, VPD_SUPPORTED_VPDS, b, + SAFE_STD_INQ_RESP_LEN, 1, verb); + if (res) { + if (verbose) + fprintf(stderr, "VPD_SUPPORTED_VPDS gave res=%d\n", + res); + return 0; + } + if (VPD_SUPPORTED_VPDS != b[1]) { + if (verbose) + fprintf(stderr, "VPD_SUPPORTED_VPDS corrupted\n"); + return 0; + } + n = (b[2] << 8) + b[3]; + if (n > (SAFE_STD_INQ_RESP_LEN - 4)) + n = (SAFE_STD_INQ_RESP_LEN - 4); + for (k = 0, has_sn = 0, has_di = 0; k < n; ++k) { + if (VPD_UNIT_SERIAL_NUM == b[4 + k]) { + if (has_di) { + if (verbose) + fprintf(stderr, "VPD_SUPPORTED_VPDS " + "dis-ordered\n"); + return 0; + } + ++has_sn; + } else if (VPD_DEVICE_ID == b[4 + k]) { + ++has_di; + break; + } + } + if (has_sn) { + res = sg_ll_inquiry(fd, 0, 1 /* evpd */, VPD_UNIT_SERIAL_NUM, + b, sizeof(b), 1, verb); + if (res) { + if (verbose) + fprintf(stderr, "VPD_UNIT_SERIAL_NUM gave " + "res=%d\n", res); + return 0; + } + if (VPD_UNIT_SERIAL_NUM != b[1]) { + if (verbose) + fprintf(stderr, "VPD_UNIT_SERIAL_NUM " + "corrupted\n"); + return 0; + } + n = (b[2] << 8) + b[3]; + if (n > (int)(sizeof(b) - 4)) + n = (sizeof(b) - 4); + printf(" Unit serial number: %.*s\n", n, + (const char *)(b + 4)); + } + if (has_di) { + res = sg_ll_inquiry(fd, 0, 1 /* evpd */, VPD_DEVICE_ID, b, + sizeof(b), 1, verb); + if (res) { + if (verbose) + fprintf(stderr, "VPD_DEVICE_ID gave res=%d\n", + res); + return 0; + } + if (VPD_DEVICE_ID != b[1]) { + if (verbose) + fprintf(stderr, "VPD_DEVICE_ID corrupted\n"); + return 0; + } + n = (b[2] << 8) + b[3]; + if (n > (int)(sizeof(b) - 4)) + n = (sizeof(b) - 4); + n = strlen(get_lu_name(b, n + 4, a, sizeof(a))); + if (n > 0) + printf(" LU name: %.*s\n", n, a); + } + return 0; +} + #define RCAP_REPLY_LEN 32 /* Returns block size or -2 if do_16==0 and the number of blocks is too @@ -385,7 +559,7 @@ main(int argc, char **argv) { int mode_page = RW_ERROR_RECOVERY_PAGE; int fd, res, calc_len, bd_len, dev_specific_param; - int offset, j, bd_blk_len, prob, len; + int offset, j, bd_blk_len, prob, len, pdt; uint64_t ull; int64_t blk_count = 0; /* -c value */ int blk_size = 0; /* -s value */ @@ -408,9 +582,8 @@ main(int argc, char **argv) int do_si = 0; int early = 0; const char * device_name = NULL; - char pdt_name[64]; char b[80]; - struct sg_simple_inquiry_resp inq_out; + unsigned char inq_resp[SAFE_STD_INQ_RESP_LEN]; int ret = 0; while (1) { @@ -600,25 +773,11 @@ main(int argc, char **argv) if (format > 2) goto format_only; - if (sg_simple_inquiry(fd, &inq_out, 1, verbose)) { - fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n", - device_name); - ret = SG_LIB_CAT_OTHER; - goto out; - } - printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n", - inq_out.vendor, inq_out.product, inq_out.revision, - sg_get_pdt_str(inq_out.peripheral_type, sizeof(pdt_name), - pdt_name), - inq_out.peripheral_type); - if (verbose) - printf(" PROTECT=%d\n", !!(inq_out.byte_5 & 1)); - if (inq_out.byte_5 & 1) - printf(" << supports protection information>>\n"); - - if ((0 != inq_out.peripheral_type) && - (7 != inq_out.peripheral_type) && - (0xe != inq_out.peripheral_type)) { + ret = print_dev_id(fd, inq_resp, sizeof(inq_resp), verbose); + if (ret) + goto out; + pdt = 0x1f & inq_resp[0]; + if ((0 != pdt) && (7 != pdt) && (0xe != pdt)) { fprintf(stderr, "This format is only defined for disks " "(using SBC-2 or RBC) and MO media\n"); ret = SG_LIB_CAT_MALFORMED; |