aboutsummaryrefslogtreecommitdiff
path: root/src/sg_format.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-10-07 04:38:02 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2014-10-07 04:38:02 +0000
commit64f8f0d1f6171b12cfe23f774ee831d320772f00 (patch)
tree9e31a5c7fca3c057aaa1763cc8d12c76cd9438dc /src/sg_format.c
parentfc92e18bc64fc037a85f2fe0d38cd7eb7ebc3cd2 (diff)
downloadsg3_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.c205
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;