aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2016-02-02 04:21:27 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2016-02-02 04:21:27 +0000
commitc68b788ce091800ab12ad6a37681d0c1ee275ca0 (patch)
tree87fcb51f0e9ba2b6bdf98e732ae097238b116ba2 /src
parent572d431816271830cc321c2c7b596236e5708ea0 (diff)
downloadsg3_utils-c68b788ce091800ab12ad6a37681d0c1ee275ca0.tar.gz
sg_unaligned.h: gets for variable length unsigned integers; sg_inq: version descriptor list to 20160125
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@658 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_get_config.c97
-rw-r--r--src/sg_inq.c28
-rw-r--r--src/sg_inq_data.c21
-rw-r--r--src/sg_logs.c558
-rw-r--r--src/sg_persist.c33
-rw-r--r--src/sg_read_buffer.c9
-rw-r--r--src/sg_referrals.c10
-rw-r--r--src/sg_ses.c66
-rw-r--r--src/sg_unmap.c45
-rw-r--r--src/sg_vpd.c29
-rw-r--r--src/sg_xcopy.c4
11 files changed, 517 insertions, 383 deletions
diff --git a/src/sg_get_config.c b/src/sg_get_config.c
index d98341b6..2e20a6b4 100644
--- a/src/sg_get_config.c
+++ b/src/sg_get_config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2015 Douglas Gilbert.
+ * Copyright (c) 2004-2016 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -19,6 +19,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
#include "sg_cmds_mmc.h"
+#include "sg_unaligned.h"
#include "sg_pr2serr.h"
/* A utility program originally written for the Linux OS SCSI subsystem.
@@ -28,7 +29,7 @@
*/
-static const char * version_str = "0.40 20151219"; /* mmc6r02 */
+static const char * version_str = "0.41 20160131"; /* mmc6r02 */
#define MX_ALLOC_LEN 8192
#define NAME_BUFF_SZ 64
@@ -255,7 +256,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" available profiles [more recent typically higher "
"in list]:\n");
for (k = 4; k < len; k += 4) {
- profile = (ucp[k] << 8) + ucp[k + 1];
+ profile = sg_get_unaligned_be16(ucp + k);
printf(" profile: %s , currentP=%d\n",
get_profile_str(profile, buff), !!(ucp[k + 2] & 1));
}
@@ -268,7 +269,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" additional length [%d] too short\n", len - 4);
break;
}
- num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
+ num = sg_get_unaligned_be32(ucp + 4);
switch (num) {
case 0: cp = "unspecified"; break;
case 1: cp = "SCSI family"; break;
@@ -347,9 +348,9 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" additional length [%d] too short\n", len - 4);
break;
}
- num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
+ num = sg_get_unaligned_be32(ucp + 4);
printf(" Logical block size=0x%x, blocking=0x%x, PP=%d\n",
- num, ((ucp[8] << 8) + ucp[9]), !!(ucp[10] & 0x1));
+ num, sg_get_unaligned_be16(ucp + 8), !!(ucp[10] & 0x1));
break;
case 0x1d: /* Multi-read */
case 0x22: /* Sector erasable */
@@ -393,10 +394,10 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" additional length [%d] too short\n", len - 4);
break;
}
- num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
- n = (ucp[8] << 24) + (ucp[9] << 16) + (ucp[10] << 8) + ucp[11];
+ num = sg_get_unaligned_be32(ucp + 4);
+ n = sg_get_unaligned_be32(ucp + 8);
printf(" Last lba=0x%x, Logical block size=0x%x, blocking=0x%x,"
- " PP=%d\n", num, n, ((ucp[12] << 8) + ucp[13]),
+ " PP=%d\n", num, n, sg_get_unaligned_be16(ucp + 12),
!!(ucp[14] & 0x1));
break;
case 0x21: /* Incremental streaming writable */
@@ -408,7 +409,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
break;
}
printf(" Data block types supported=0x%x, TRIO=%d, ARSV=%d, "
- "BUF=%d\n", ((ucp[4] << 8) + ucp[5]), !!(ucp[6] & 0x4),
+ "BUF=%d\n", sg_get_unaligned_be16(ucp + 4), !!(ucp[6] & 0x4),
!!(ucp[6] & 0x2), !!(ucp[6] & 0x1));
num = ucp[7];
printf(" Number of link sizes=%d\n", num);
@@ -442,9 +443,9 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" additional length [%d] too short\n", len - 4);
break;
}
- num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
+ num = sg_get_unaligned_be16(ucp + 4);
printf(" Logical block size=0x%x, blocking=0x%x, PP=%d\n",
- num, ((ucp[8] << 8) + ucp[9]), !!(ucp[10] & 0x1));
+ num, sg_get_unaligned_be16(ucp + 8), !!(ucp[10] & 0x1));
break;
/* case 0x26: Restricted overwrite -> see 0x1d entry */
/* case 0x27: CDRW CAV write -> see 0x1d entry */
@@ -466,7 +467,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
}
printf(" DRT-DM=%d, number of DBI cache zones=0x%x, number of "
"entries=0x%x\n", !!(ucp[4] & 0x1), ucp[5],
- ((ucp[6] << 8) + ucp[7]));
+ sg_get_unaligned_be16(ucp + 6));
break;
case 0x2a: /* DVD+RW */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -513,7 +514,8 @@ decode_feature(int feature, unsigned char * ucp, int len)
!!(ucp[4] & 0x40), !!(ucp[4] & 0x10), !!(ucp[4] & 0x8),
!!(ucp[4] & 0x4));
printf(" CD-RW=%d, R-W sub-code=%d, Data type supported=%d\n",
- !!(ucp[4] & 0x2), !!(ucp[4] & 0x1), (ucp[6] << 8) + ucp[7]);
+ !!(ucp[4] & 0x2), !!(ucp[4] & 0x1),
+ sg_get_unaligned_be16(ucp + 6));
break;
case 0x2e: /* CD mastering (session at once) */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -529,7 +531,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" Test write=%d, CD-RW=%d, R-W=%d\n",
!!(ucp[4] & 0x4), !!(ucp[4] & 0x2), !!(ucp[4] & 0x1));
printf(" Maximum cue sheet length=0x%x\n",
- (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]);
+ sg_get_unaligned_be24(ucp + 5));
break;
case 0x2f: /* DVD-R/-RW write */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -610,22 +612,22 @@ decode_feature(int feature, unsigned char * ucp, int len)
}
printf(" Bitmaps for BD-RE read support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[8] << 8) + ucp[9],
- (ucp[10] << 8) + ucp[11],
- (ucp[12] << 8) + ucp[13],
- (ucp[14] << 8) + ucp[15]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 8),
+ sg_get_unaligned_be16(ucp + 10),
+ sg_get_unaligned_be16(ucp + 12),
+ sg_get_unaligned_be16(ucp + 14));
printf(" Bitmaps for BD-R read support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[16] << 8) + ucp[17],
- (ucp[18] << 8) + ucp[19],
- (ucp[20] << 8) + ucp[21],
- (ucp[22] << 8) + ucp[23]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 16),
+ sg_get_unaligned_be16(ucp + 18),
+ sg_get_unaligned_be16(ucp + 20),
+ sg_get_unaligned_be16(ucp + 22));
printf(" Bitmaps for BD-ROM read support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[24] << 8) + ucp[25],
- (ucp[26] << 8) + ucp[27],
- (ucp[28] << 8) + ucp[29],
- (ucp[30] << 8) + ucp[31]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 24),
+ sg_get_unaligned_be16(ucp + 26),
+ sg_get_unaligned_be16(ucp + 28),
+ sg_get_unaligned_be16(ucp + 30));
break;
case 0x41: /* BD Write */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -638,22 +640,22 @@ decode_feature(int feature, unsigned char * ucp, int len)
printf(" SVNR=%d\n", !!(ucp[4] & 0x1));
printf(" Bitmaps for BD-RE write support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[8] << 8) + ucp[9],
- (ucp[10] << 8) + ucp[11],
- (ucp[12] << 8) + ucp[13],
- (ucp[14] << 8) + ucp[15]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 8),
+ sg_get_unaligned_be16(ucp + 10),
+ sg_get_unaligned_be16(ucp + 12),
+ sg_get_unaligned_be16(ucp + 14));
printf(" Bitmaps for BD-R write support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[16] << 8) + ucp[17],
- (ucp[18] << 8) + ucp[19],
- (ucp[20] << 8) + ucp[21],
- (ucp[22] << 8) + ucp[23]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 16),
+ sg_get_unaligned_be16(ucp + 18),
+ sg_get_unaligned_be16(ucp + 20),
+ sg_get_unaligned_be16(ucp + 22));
printf(" Bitmaps for BD-ROM write support:\n");
printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, "
- "Class 3=0x%x\n", (ucp[24] << 8) + ucp[25],
- (ucp[26] << 8) + ucp[27],
- (ucp[28] << 8) + ucp[29],
- (ucp[30] << 8) + ucp[31]);
+ "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 24),
+ sg_get_unaligned_be16(ucp + 26),
+ sg_get_unaligned_be16(ucp + 28),
+ sg_get_unaligned_be16(ucp + 30));
break;
/* case 0x42: TSR (timely safe recording) -> see 0x1d entry */
case 0x50: /* HD DVD Read */
@@ -730,7 +732,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
}
printf(" Scan=%d, SCM=%d, SV=%d, number of volume levels=%d\n",
!!(ucp[4] & 0x4), !!(ucp[4] & 0x2), !!(ucp[4] & 0x1),
- (ucp[6] << 8) + ucp[7]);
+ sg_get_unaligned_be16(ucp + 6));
break;
case 0x104: /* Firmware upgrade */
printf(" version=%d, persist=%d, current=%d [0x%x]\n",
@@ -749,7 +751,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
feature);
if (len > 7) {
printf(" Group 3=%d, unit length=%d\n",
- !!(ucp[4] & 0x1), (ucp[6] << 8) + ucp[7]);
+ !!(ucp[4] & 0x1), sg_get_unaligned_be16(ucp + 6));
}
break;
case 0x106: /* DVD CSS */
@@ -792,8 +794,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
feature);
printf(" Disc control blocks:\n");
for (k = 4; k < len; k += 4) {
- printf(" 0x%x\n", ((unsigned int)ucp[k] << 24) +
- (ucp[k + 1] << 16) + (ucp[k + 2] << 8) + ucp[k + 3]);
+ printf(" 0x%x\n", sg_get_unaligned_be32(ucp + k));
}
break;
case 0x10b: /* DVD CPRM */
@@ -868,8 +869,7 @@ decode_feature(int feature, unsigned char * ucp, int len)
num = ucp[5];
printf(" Profile numbers:\n");
for (k = 6; (num > 0) && (k < len); --num, k += 2) {
- printf(" %d\n",
- ((unsigned int)ucp[k] << 8) + ucp[k + 1]);
+ printf(" %u\n", sg_get_unaligned_be16(ucp + k));
}
break;
default:
@@ -898,7 +898,7 @@ decode_config(unsigned char * resp, int max_resp_len, int len, int brief,
pr2serr("response length too short: %d\n", len);
return;
}
- curr_profile = (resp[6] << 8) + resp[7];
+ curr_profile = sg_get_unaligned_be16(resp + 6);
if (0 == curr_profile)
pr2serr("No current profile\n");
else
@@ -908,7 +908,7 @@ decode_config(unsigned char * resp, int max_resp_len, int len, int brief,
len -= 8;
for (k = 0; k < len; k += extra_len, ucp += extra_len) {
extra_len = 4 + ucp[3];
- feature = (ucp[0] << 8) + ucp[1];
+ feature = sg_get_unaligned_be16(ucp + 0);
printf(" %s feature\n", get_feature_str(feature, buff));
if (brief)
continue;
@@ -1085,8 +1085,7 @@ main(int argc, char * argv[])
sizeof(resp_buffer), 1, verbose);
ret = res;
if (0 == res) {
- len = (resp_buffer[0] << 24) + (resp_buffer[1] << 16) +
- (resp_buffer[2] << 8) + resp_buffer[3] + 4;
+ len = sg_get_unaligned_be32(resp_buffer + 0) + 4;
if (do_hex) {
if (len > (int)sizeof(resp_buffer))
len = sizeof(resp_buffer);
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 11b7badc..7148acec 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -19,6 +19,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
@@ -42,7 +43,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.55 20160126"; /* SPC-5 rev 08 */
+static const char * version_str = "1.56 20160201"; /* SPC-5 rev 08 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -741,7 +742,8 @@ static int
f2hex_arr(const char * fname, int as_binary, int no_space,
unsigned char * mp_arr, int * mp_arr_len, int max_arr_len)
{
- int fn_len, in_len, k, j, m, split_line, fd, has_stdin;
+ int fn_len, in_len, k, j, m, split_line, fd;
+ bool has_stdin;
unsigned int h;
const char * lcp;
FILE * fp;
@@ -820,8 +822,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
if (1 == sscanf(carry_over, "%x", &h))
mp_arr[off - 1] = h; /* back up and overwrite */
else {
- pr2serr("f2hex_arr: carry_over error ['%s'] around line "
- "%d\n", carry_over, j + 1);
+ pr2serr("%s: carry_over error ['%s'] around line %d\n",
+ __func__, carry_over, j + 1);
goto bad;
}
lcp = line + 1;
@@ -841,7 +843,7 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
continue;
k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("f2hex_arr: syntax error at line %d, pos %d\n",
+ pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
j + 1, m + k + 1);
goto bad;
}
@@ -849,12 +851,12 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
++k, lcp += 2) {
if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("f2hex_arr: bad hex number in line %d, "
- "pos %d\n", j + 1, (int)(lcp - line + 1));
+ pr2serr("%s: bad hex number in line %d, pos %d\n",
+ __func__, j + 1, (int)(lcp - line + 1));
goto bad;
}
if ((off + k) >= max_arr_len) {
- pr2serr("f2hex_arr: array length exceeded\n");
+ pr2serr("%s: array length exceeded\n", __func__);
goto bad;
}
mp_arr[off + k] = h;
@@ -866,8 +868,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
for (k = 0; k < 1024; ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
- pr2serr("f2hex_arr: hex number larger than "
- "0xff in line %d, pos %d\n", j + 1,
+ pr2serr("%s: hex number larger than 0xff in line %d, "
+ "pos %d\n", __func__, j + 1,
(int)(lcp - line + 1));
goto bad;
}
@@ -876,7 +878,7 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
carry_over[0] = *lcp;
}
if ((off + k) >= max_arr_len) {
- pr2serr("f2hex_arr: array length exceeded\n");
+ pr2serr("%s: array length exceeded\n", __func__);
goto bad;
}
mp_arr[off + k] = h;
@@ -891,8 +893,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
--k;
break;
}
- pr2serr("f2hex_arr: error in line %d, at pos %d\n", j + 1,
- (int)(lcp - line + 1));
+ pr2serr("%s: error in line %d, at pos %d\n", __func__,
+ j + 1, (int)(lcp - line + 1));
goto bad;
}
}
diff --git a/src/sg_inq_data.c b/src/sg_inq_data.c
index a76384b9..a0a0f7fe 100644
--- a/src/sg_inq_data.c
+++ b/src/sg_inq_data.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2015 D. Gilbert
+* Copyright (C) 2000-2016 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)
@@ -26,10 +26,10 @@ const char * sg_ansi_version_arr[] =
"no conformance claimed",
"SCSI-1", /* obsolete, ANSI X3.131-1986 */
"SCSI-2", /* obsolete, ANSI X3.131-1994 */
- "SPC", /* withdrawn */
- "SPC-2",
- "SPC-3",
- "SPC-4",
+ "SPC", /* withdrawn, ANSI INCITS 301-1997 */
+ "SPC-2", /* ANSI INCITS 351-2001, ISO/IEC 14776-452 */
+ "SPC-3", /* ANSI INCITS 408-2005, ISO/IEC 14776-453 */
+ "SPC-4", /* ANSI INCITS 513-2015 */
"SPC-5",
"ecma=1, [8h]",
"ecma=1, [9h]",
@@ -48,8 +48,8 @@ struct sg_version_descriptor {
const char * name;
};
-/* table from SPC-5 revision 06 [sorted numerically (from Annex E.9)] */
-/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20151101 */
+/* table from SPC-5 revision 08 [sorted numerically (from Annex E.9)] */
+/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20160125 */
#ifdef SG_SCSI_STRINGS
@@ -233,7 +233,9 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x600, "SBC-4 (no version claimed)"},
{0x620, "ZBC (no version claimed)"},
{0x622, "ZBC BSR INCITS 536 revision 02"},
+ {0x624, "ZBC BSR INCITS 536 revision 05"},
{0x640, "ADC-4 (no version claimed)"},
+ {0x660, "ZBC-2 (no version claimed)"},
{0x820, "SSA-TL2 (no version claimed)"},
{0x83b, "SSA-TL2 T10/1147-D revision 05b"},
{0x83c, "SSA-TL2 ANSI INCITS 308-1998"},
@@ -277,7 +279,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x99a, "SBP-3 T10/1467-D revision 4"},
{0x99b, "SBP-3 T10/1467-D revision 5"},
{0x99c, "SBP-3 ANSI INCITS 375-2004"},
- /* {0x9a0, "SRP-2 (no version claimed)"}, */
+ {0x9a0, "SRP-2 (no version claimed)"},
{0x9c0, "ADP (no version claimed)"},
{0x9e0, "ADT (no version claimed)"},
{0x9f9, "ADT T10/1557-D revision 11"},
@@ -518,8 +520,9 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x2204, "PQI T10/BSR INCITS 490 revision 6"},
{0x2206, "PQI T10/BSR INCITS 490 revision 7"},
{0x2208, "PQI ANSI INCITS 490-2014"},
- {0x2220, "SOP-2 (no version claimed)"},
+ {0x2220, "SOP-2 (no draft published)"},
{0x2240, "PQI-2 (no version claimed)"},
+ {0x2242, "PQI-2 T10/BSR INCITS 507 revision 01"},
{0xffc0, "IEEE 1667 (no version claimed)"},
{0xffc1, "IEEE 1667-2006"},
{0xffc2, "IEEE 1667-2009"},
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 204b0f81..be7cc0de 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.37 20160124"; /* spc5r07 + sbc4r10 */
+static const char * version_str = "1.38 20160130"; /* spc5r08 + sbc4r10 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -72,6 +72,7 @@ static const char * version_str = "1.37 20160124"; /* spc5r07 + sbc4r10 */
#define LPS_MISALIGNMENT_SUBPG 0x3
#define VENDOR_M 0x1000
+#define LTO5_M 0x2000
#define PCB_STR_LEN 128
@@ -84,6 +85,7 @@ static struct option long_options[] = {
{"brief", no_argument, 0, 'b'},
{"control", required_argument, 0, 'c'},
{"enumerate", no_argument, 0, 'e'},
+ {"enum_vendor", no_argument, 0, 'E'},
{"filter", required_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
@@ -114,6 +116,7 @@ struct opts_t {
int do_all;
int do_brief;
int do_enumerate;
+ int do_enum_vendor;
int do_help;
int do_hex;
int do_list;
@@ -341,44 +344,44 @@ static struct log_elem log_arr[] = {
{IE_LPAGE, 0, 0, -1, 0, "Informational exceptions", "ie",
show_ie_page}, /* 0x2f, 0 */
/* vendor specific */
- {0x30, 0, 0, PDT_TAPE, VENDOR_M, "Performance counters (Hitachi)", "pc_hi",
- NULL}, /* 0x30, 0 SBC */
- {0x30, 0, 0, PDT_TAPE, VENDOR_M, "Tape usage (lto-5, 6)", "ta_",
+ {0x30, 0, 0, PDT_DISK, VENDOR_M, "Performance counters (Hitachi)",
+ "pc_hi", NULL}, /* 0x30, 0 SBC */
+ {0x30, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Tape usage (lto-5, 6)", "ta_",
show_tape_usage_page}, /* 0x30, 0 SSC */
- {0x31, 0, 0, PDT_TAPE, VENDOR_M, "Tape capacity (lto-5, 6)", "tc_",
- show_tape_capacity_page}, /* 0x31, 0 SSC */
- {0x32, 0, 0, PDT_TAPE, VENDOR_M, "Data compression (ibm)", "dc_",
+ {0x31, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Tape capacity (lto-5, 6)",
+ "tc_", show_tape_capacity_page}, /* 0x31, 0 SSC */
+ {0x32, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Data compression (ibm)", "dc_",
show_data_compression_page}, /* 0x32, 0 SSC; redirect to 0x1b */
- {0x33, 0, 0, PDT_TAPE, VENDOR_M, "Write errors (lto-5)", "we_",
+ {0x33, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Write errors (lto-5)", "we_",
NULL}, /* 0x33, 0 SSC */
- {0x34, 0, 0, PDT_TAPE, VENDOR_M, "Read forward errors (lto-5)", "rfe_",
- NULL}, /* 0x34, 0 SSC */
- {0x35, 0, 0, PDT_TAPE, VENDOR_M, "DT Device Error (lto-6)", "dtde_",
- NULL}, /* 0x35, 0 SSC */
+ {0x34, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Read forward errors (lto-5)",
+ "rfe_", NULL}, /* 0x34, 0 SSC */
+ {0x35, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "DT Device Error (lto-5, 6)",
+ "dtde_", NULL}, /* 0x35, 0 SSC */
{0x37, 0, 0, PDT_DISK, VENDOR_M, "Cache (seagate)", "c_se",
show_seagate_cache_page}, /* 0x37, 0 SBC */
{0x37, 0, 0, PDT_DISK, VENDOR_M, "Miscellaneous (hitachi)", "mi_hi",
NULL}, /* 0x37, 0 SBC */
- {0x37, 0, 0, PDT_TAPE, VENDOR_M, "Performance characteristics (lto-5)",
- "pc_", NULL}, /* 0x37, 0 SSC */
- {0x38, 0, 0, PDT_TAPE, VENDOR_M, "Blocks/bytes transferred (lto-5)",
- "bbt_", NULL}, /* 0x38, 0 SSC */
- {0x39, 0, 0, PDT_TAPE, VENDOR_M, "Host port 0 interface errors (lto-5)",
- "hp0_", NULL}, /* 0x39, 0 SSC */
- {0x3a, 0, 0, PDT_TAPE, VENDOR_M, "Drive control verification (lto-5)",
- "dcv_", NULL}, /* 0x3a, 0 SSC */
- {0x3b, 0, 0, PDT_TAPE, VENDOR_M, "Host port 1 interface errors (lto-5)",
- "hp1_", NULL}, /* 0x3b, 0 SSC */
- {0x3c, 0, 0, PDT_TAPE, VENDOR_M, "Drive usage information (lto-5)",
- "dui_", NULL}, /* 0x3c, 0 SSC */
- {0x3d, 0, 0, PDT_TAPE, VENDOR_M, "Subsystem statistics (lto-5)", "ss_",
- NULL}, /* 0x3d, 0 SSC */
+ {0x37, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Performance characteristics "
+ "(lto-5)", "pc_", NULL}, /* 0x37, 0 SSC */
+ {0x38, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Blocks/bytes transferred "
+ "(lto-5)", "bbt_", NULL}, /* 0x38, 0 SSC */
+ {0x39, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Host port 0 interface errors "
+ "(lto-5)", "hp0_", NULL}, /* 0x39, 0 SSC */
+ {0x3a, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Drive control verification "
+ "(lto-5)", "dcv_", NULL}, /* 0x3a, 0 SSC */
+ {0x3b, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Host port 1 interface errors "
+ "(lto-5)", "hp1_", NULL}, /* 0x3b, 0 SSC */
+ {0x3c, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Drive usage information "
+ "(lto-5)", "dui_", NULL}, /* 0x3c, 0 SSC */
+ {0x3d, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Subsystem statistics (lto-5)",
+ "ss_", NULL}, /* 0x3d, 0 SSC */
{0x3e, 0, 0, PDT_DISK, VENDOR_M, "Factory (seagate)", "f_se",
show_seagate_factory_page}, /* 0x3e, 0 SBC */
{0x3e, 0, 0, PDT_DISK, VENDOR_M, "Factory (hitachi)", "f_hi",
NULL}, /* 0x3e, 0 SBC */
- {0x3e, 0, 0, PDT_TAPE, VENDOR_M, "Device Status (lto-6)", "ds_",
- NULL}, /* 0x3e, 0 SSC */
+ {0x3e, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Device Status (lto-5, 6)",
+ "ds_", NULL}, /* 0x3e, 0 SSC */
{-1, -1, -1, -1, -1, NULL, "zzzzz", NULL}, /* end sentinel */
};
@@ -395,14 +398,15 @@ usage(int hval)
if (1 == hval) {
pr2serr(
"Usage: sg_logs [--all] [--brief] [--control=PC] [--enumerate] "
- "[--filter=FI]\n"
- " [--help] [--hex] [--in=FN] [--list] [--no_inq] "
- "[--maxlen=LEN]\n"
- " [--name] [--page=PG] [--paramp=PP] [--pcb] "
- "[--ppc] [--raw]\n"
- " [--readonly] [--reset] [--select] [--sp] "
- "[--temperature]\n"
- " [--transport] [--verbose] [--version] DEVICE\n"
+ "[--enum_vendor]\n"
+ " [--filter=FI] [--help] [--hex] [--in=FN] [--list] "
+ "[--no_inq]\n"
+ " [--maxlen=LEN] [--name] [--page=PG] [--paramp=PP] "
+ "[--pcb]\n"
+ " [--ppc] [--raw] [--readonly] [--reset] [--select] "
+ "[--sp]\n"
+ " [--temperature] [--transport] [--verbose] "
+ "[--version] DEVICE\n"
" where the main options are:\n"
" --all|-a fetch and decode all log pages, but not "
"subpages; use\n"
@@ -415,6 +419,8 @@ usage(int hval)
"by acronym;\n"
" '-eee': all numerically; '-eeee': "
"non-v numerically\n"
+ " --enum_vendor|-E enumerate known specific vendor pages "
+ "only\n"
" --filter=FI|-f FI FI is parameter code to display (def: "
"all); with\n"
" '-e' then FI>=0 enumerate that pdt + "
@@ -489,13 +495,13 @@ usage(int hval)
static void
usage_old()
{
- printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-e] [-f=FI] [-h] [-H] "
- "[-i=FN]\n"
- " [-l] [-L] [-m=LEN] [-n] [-p=PG] "
+ printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-e] [-E] [-f=FI] [-h] "
+ "[-H]\n"
+ " [-i=FN] [-l] [-L] [-m=LEN] [-n] [-p=PG] "
"[-paramp=PP]\n"
- " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] "
+ " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] "
"[-v] [-V]\n"
- " [-x] [-X] [-?] DEVICE\n"
+ " [-x] [-X] [-?] DEVICE\n"
" where:\n"
" -a fetch and decode all log pages\n"
" -A fetch and decode all log pages and subpages\n"
@@ -504,6 +510,7 @@ usage_old()
" 0: current threshhold, 1: current cumulative\n"
" 2: default threshhold, 3: default cumulative\n"
" -e enumerate known log pages\n"
+ " -E enumerate known vendor specific log pages only\n"
" -f=FI filter match parameter code or pdt\n"
" -h output in hex (default: decode if known)\n"
" -H output in hex (same as '-h')\n"
@@ -572,6 +579,8 @@ enumerate_helper(const struct log_elem * lep, int pos,
printf("===================================================\n");
}
}
+ if ((op->do_enum_vendor > 0) && !(VENDOR_M & lep->flags))
+ return;
if ((0 == (op->do_enumerate % 2)) && (VENDOR_M & lep->flags))
return; /* if do_enumerate is even then skip vendor pages */
else if ((! op->filter_given) || (-1 == op->filter))
@@ -662,6 +671,8 @@ pg_subpg_pdt_search(int pg_code, int subpg_code, int pdt)
return lep;
else if (d_pdt == lep->pdt)
return lep;
+ else if (pdt == sg_lib_pdt_decay(lep->pdt))
+ return lep;
} else if ((lep->subpg_high > 0) &&
(subpg_code > lep->subpg_code) &&
(subpg_code <= lep->subpg_high))
@@ -690,7 +701,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "aAbc:ef:hHi:lLm:nNOp:P:qQrRsStTvVxX",
+ c = getopt_long(argc, argv, "aAbc:eEf:hHi:lLm:nNOp:P:qQrRsStTvVxX",
long_options, &option_index);
if (c == -1)
break;
@@ -717,6 +728,9 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
case 'e':
++op->do_enumerate;
break;
+ case 'E':
+ ++op->do_enum_vendor;
+ break;
case 'f':
if ('-' == optarg[0]) {
n = sg_get_num(optarg + 1);
@@ -871,6 +885,9 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
case 'e':
++op->do_enumerate;
break;
+ case 'E':
+ ++op->do_enum_vendor;
+ break;
case 'h':
case 'H':
++op->do_hex;
@@ -1089,17 +1106,35 @@ dStrRaw(const char* str, int len)
printf("%c", str[k]);
}
-/* Decode counter up to 8 chars long (big endian) into an uint64_t.
- * In the unlikely event that the counter is larger than 8 chars long
- * then take the last 8 chars. */
-static uint64_t
-decode_count(const uint8_t * xp, int len)
+/* Assumes an integral numbers of bytes pointed to by 'xp' of length
+ * 'num_bytes' given. [So the number of bits modulo 8 must be zero.]
+ * Returns true if all bytes are 0xff (which is the same as all bits
+ * being set), else returns false. */
+static bool
+all_bits_set(const uint8_t * xp, int num_bytes)
{
- if (len > (int)sizeof(uint64_t)) {
- xp += (len - sizeof(uint64_t));
- len = sizeof(uint64_t);
+ for ( ; num_bytes > 0; ++xp, --num_bytes) {
+ if (0xff != *xp)
+ return false;
}
- return sg_get_unaligned_be64(xp + 0);
+ return true;
+}
+
+static char *
+num_or_unknown(const uint8_t * xp, int num_bytes, bool in_hex, char * b,
+ int blen)
+{
+ if (all_bits_set(xp, num_bytes))
+ snprintf(b, blen, "unknown");
+ else {
+ uint64_t num = sg_get_unaligned_be(num_bytes, xp);
+
+ if (in_hex)
+ snprintf(b, blen, "0x%" PRIx64, num);
+ else
+ snprintf(b, blen, "%" PRIu64, num);
+ }
+ return b;
}
/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
@@ -1475,7 +1510,7 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len,
while (num > 3) {
cp = NULL;
pl = ucp[3] + 4;
- count = (pl > 4) ? decode_count(ucp + 4, pl - 4) : 0;
+ count = (pl > 4) ? sg_get_unaligned_be(pl - 4, ucp + 4) : 0;
pc = sg_get_unaligned_be16(ucp + 0);
if (op->filter_given) {
if (pc != op->filter)
@@ -1645,7 +1680,7 @@ show_error_counter_page(const uint8_t * resp, int len,
case 0x8015: printf(" Positioning errors [Hitachi]"); break;
default: printf(" Reserved or vendor specific [0x%x]", pc); break;
}
- printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4));
if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
@@ -1699,7 +1734,7 @@ show_non_medium_error_page(const uint8_t * resp, int len,
printf(" Vendor specific [0x%x]", pc);
break;
}
- printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4));
if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
@@ -1758,7 +1793,7 @@ show_power_condition_transitions_page(const uint8_t * resp, int len,
default:
printf(" Reserved [0x%x]", pc);
}
- printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4));
if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
@@ -2409,9 +2444,11 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op)
printf(" self-test result: %s [%d]\n", self_test_result[res], res);
if (ucp[5])
printf(" self-test number = %d\n", (int)ucp[5]);
- ull = sg_get_unaligned_be64(ucp + 8);
- if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf))
- printf(" address of first error = 0x%" PRIx64 "\n", ull);
+ if (! all_bits_set(ucp + 8, 8)) {
+ ull = sg_get_unaligned_be64(ucp + 8);
+ if ((res > 0) && ( res < 0xf))
+ printf(" address of first error = 0x%" PRIx64 "\n", ull);
+ }
v = ucp[16] & 0xf;
if (v) {
printf(" sense key = 0x%x [%s] , asc = 0x%x, ascq = 0x%x",
@@ -2512,7 +2549,6 @@ static bool
show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
{
int k, num, extra, pc, pcb;
- unsigned int n;
const uint8_t * ucp;
char pcb_str[PCB_STR_LEN];
@@ -2567,42 +2603,40 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
case 3:
if (extra > 7) {
- n = sg_get_unaligned_be32(ucp + 4);
- if (0xffffffff == n)
+ if (all_bits_set(ucp + 4, 4))
printf(" Specified cycle count over device lifetime "
"= -1");
else
printf(" Specified cycle count over device lifetime "
- "= %u", n);
+ "= %u", sg_get_unaligned_be32(ucp + 4));
}
break;
case 4:
if (extra > 7) {
- n = sg_get_unaligned_be32(ucp + 4);
- if (0xffffffff == n)
+ if (all_bits_set(ucp + 4, 4))
printf(" Accumulated start-stop cycles = -1");
else
- printf(" Accumulated start-stop cycles = %u", n);
+ printf(" Accumulated start-stop cycles = %u",
+ sg_get_unaligned_be32(ucp + 4));
}
break;
case 5:
if (extra > 7) {
- n = sg_get_unaligned_be32(ucp + 4);
- if (0xffffffff == n)
+ if (all_bits_set(ucp + 4, 4))
printf(" Specified load-unload count over device "
"lifetime = -1");
else
printf(" Specified load-unload count over device "
- "lifetime = %u", n);
+ "lifetime = %u", sg_get_unaligned_be32(ucp + 4));
}
break;
case 6:
if (extra > 7) {
- n = sg_get_unaligned_be32(ucp + 4);
- if (0xffffffff == n)
+ if (all_bits_set(ucp + 4, 4))
printf(" Accumulated load-unload cycles = -1");
else
- printf(" Accumulated load-unload cycles = %u", n);
+ printf(" Accumulated load-unload cycles = %u",
+ sg_get_unaligned_be32(ucp + 4));
}
break;
default:
@@ -2904,6 +2938,37 @@ show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val)
}
}
+static const char * sas_link_rate_arr[16] = {
+ "phy enabled; unknown rate",
+ "phy disabled",
+ "phy enabled; speed negotiation failed",
+ "phy enabled; SATA spinup hold state",
+ "phy enabled; port selector",
+ "phy enabled; reset in progress",
+ "phy enabled; unsupported phy attached",
+ "reserved [0x7]",
+ "1.5 Gbps", /* 0x8 */
+ "3 Gbps",
+ "6 Gbps",
+ "12 Gbps",
+ "22.5 Gbps",
+ "reserved [0xd]",
+ "reserved [0xe]",
+ "reserved [0xf]",
+};
+
+static char *
+sas_negot_link_rate(int lrate, char * b, int blen)
+{
+ int mask = 0xf;
+
+ if (~mask & lrate)
+ snprintf(b, blen, "bad link_rate value=0x%x\n", lrate);
+ else
+ snprintf(b, blen, "%s", sas_link_rate_arr[lrate]);
+ return b;
+}
+
/* helper for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */
static void
show_sas_port_param(const uint8_t * ucp, int param_len,
@@ -3018,49 +3083,8 @@ show_sas_port_param(const uint8_t * ucp, int param_len,
default: snprintf(s, sz, "reserved [0x%x]", t); break;
}
printf(" reason: %s\n", s);
- t = (0xf & vcp[5]);
- switch (t) {
- case 0:
- snprintf(s, sz, "phy enabled; unknown reason");
- break;
- case 1:
- snprintf(s, sz, "phy disabled");
- break;
- case 2:
- snprintf(s, sz, "phy enabled; speed negotiation failed");
- break;
- case 3:
- snprintf(s, sz, "phy enabled; SATA spinup hold state");
- break;
- case 4:
- snprintf(s, sz, "phy enabled; port selector");
- break;
- case 5:
- snprintf(s, sz, "phy enabled; reset in progress");
- break;
- case 6:
- snprintf(s, sz, "phy enabled; unsupported phy attached");
- break;
- case 8:
- snprintf(s, sz, "1.5 Gbps");
- break;
- case 9:
- snprintf(s, sz, "3 Gbps");
- break;
- case 0xa:
- snprintf(s, sz, "6 Gbps");
- break;
- case 0xb:
- snprintf(s, sz, "12 Gbps");
- break;
- case 0xc:
- snprintf(s, sz, "22.5 Gbps");
- break;
- default:
- snprintf(s, sz, "reserved [%d]", t);
- break;
- }
- printf(" negotiated logical link rate: %s\n", s);
+ printf(" negotiated logical link rate: %s\n",
+ sas_negot_link_rate((0xf & vcp[5]), s, sz));
printf(" attached initiator port: ssp=%d stp=%d smp=%d\n",
!! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2));
printf(" attached target port: ssp=%d stp=%d smp=%d\n",
@@ -4041,6 +4065,7 @@ show_dt_device_status_page(const uint8_t * resp, int len,
int num, pl, pc, pcb, j;
const uint8_t * ucp;
char str[PCB_STR_LEN];
+ char b[64];
if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
printf("DT device status page (ssc-3, adc-3) [0x11]\n");
@@ -4136,11 +4161,32 @@ show_dt_device_status_page(const uint8_t * resp, int len,
dStrHex((const char *)ucp + 4, 12, 1);
break;
default:
- printf(" Reserved [parameter_code=0x%x]:\n", pc);
- dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ if ((pc >= 0x101) && (pc <= 0x1ff)) {
+ printf(" Primary port %d status:\n", pc - 0x100);
+ if (12 == ucp[3]) { /* if length of desc is 12, assume SAS */
+ printf(" SAS: negotiated physical link rate: %s\n",
+ sas_negot_link_rate((0xf & (ucp[4] >> 4)), b,
+ sizeof(b)));
+ printf(" signal=%d, pic=%d, ", !!(0x2 & ucp[4]),
+ !!(0x1 & ucp[4]));
+ printf("hashed SAS addr: 0x%u\n",
+ sg_get_unaligned_be24(ucp + 5));
+ printf(" SAS addr: 0x%" PRIx64 "\n",
+ sg_get_unaligned_be64(ucp + 8));
+ } else {
+ printf(" non-SAS transport, in hex:\n");
+ dStrHex((const char *)ucp + 4,
+ ((pl < num) ? pl : num) - 4, 0);
+ }
+ } else if (pc >= 0x8000) {
+ printf(" Vendor specific [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ } else {
+ printf(" Reserved [parameter_code=0x%x]:\n", pc);
+ dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ }
break;
}
-// xxxxxxxxxxxxxxx
if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
@@ -4575,6 +4621,7 @@ show_sequential_access_page(const uint8_t * resp, int len,
int num, pl, pc, pcb;
const uint8_t * ucp;
uint64_t ull, gbytes;
+ bool all_set;
char pcb_str[PCB_STR_LEN];
if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
@@ -4596,7 +4643,8 @@ show_sequential_access_page(const uint8_t * resp, int len,
break;
}
}
- ull = decode_count(ucp + 4, pl - 4);
+ ull = sg_get_unaligned_be(pl - 4, ucp + 4);
+ all_set = all_bits_set(ucp + 4, pl - 4);
gbytes = ull / 1000000000;
switch (pc) {
case 0:
@@ -4628,24 +4676,29 @@ show_sequential_access_page(const uint8_t * resp, int len,
printf("\n");
break;
case 4:
- printf(" Native capacity from BOP to EOD: %" PRIu64 " MB\n",
- ull);
+ if (! all_set)
+ printf(" Native capacity from BOP to EOD: %" PRIu64 " MB\n",
+ ull);
break;
case 5:
- printf(" Native capacity from BOP to EW of current partition: "
- "%" PRIu64 " MB\n", ull);
+ if (! all_set)
+ printf(" Native capacity from BOP to EW of current "
+ "partition: %" PRIu64 " MB\n", ull);
break;
case 6:
- printf(" Minimum native capacity from EW to EOP of current "
- "partition: %" PRIu64 " MB\n", ull);
+ if (! all_set)
+ printf(" Minimum native capacity from EW to EOP of current "
+ "partition: %" PRIu64 " MB\n", ull);
break;
case 7:
- printf(" Native capacity from BOP to current position: %"
- PRIu64 " MB\n", ull);
+ if (! all_set)
+ printf(" Native capacity from BOP to current position: %"
+ PRIu64 " MB\n", ull);
break;
case 8:
- printf(" Maximum native capacity in device object buffer: %"
- PRIu64 " MB\n", ull);
+ if (! all_set)
+ printf(" Maximum native capacity in device object buffer: %"
+ PRIu64 " MB\n", ull);
break;
case 0x100:
if (ull > 0)
@@ -4707,7 +4760,7 @@ show_device_stats_page(const uint8_t * resp, int len,
}
}
if (pc < 0x1000) {
- ull = decode_count(ucp + 4, pl - 4);
+ ull = sg_get_unaligned_be(pl - 4, ucp + 4);
switch (pc) {
case 0:
printf(" Lifetime media loads: %" PRIu64 "\n", ull);
@@ -4755,21 +4808,88 @@ show_device_stats_page(const uint8_t * resp, int len,
"initiated forced reset\n and/or emergency "
"eject occurred: %" PRIu64 "\n", ull);
break;
+ case 0xc:
+ printf(" Lifetime power cycles: %" PRIu64 "\n", ull);
+ break;
+ case 0xd:
+ printf(" Volume loads since last parameter reset: %" PRIu64
+ "\n", ull);
+ break;
+ case 0xe:
+ printf(" Hard write errors: %" PRIu64 "\n", ull);
+ break;
+ case 0xf:
+ printf(" Hard read errors: %" PRIu64 "\n", ull);
+ break;
+ case 0x10:
+ printf(" Duty cycle sample time: %" PRIu64 " ms\n", ull);
+ break;
+ case 0x11:
+ printf(" Read duty cycle: %" PRIu64 "\n", ull);
+ break;
+ case 0x12:
+ printf(" Write duty cycle: %" PRIu64 "\n", ull);
+ break;
+ case 0x13:
+ printf(" Activity duty cycle: %" PRIu64 "\n", ull);
+ break;
+ case 0x14:
+ printf(" Volume not present duty cycle: %" PRIu64 "\n", ull);
+ break;
+ case 0x15:
+ printf(" Ready duty cycle: %" PRIu64 "\n", ull);
+ break;
+ case 0x16:
+ printf(" MBs transferred from app client in duty cycle "
+ "sample time: %" PRIu64 "\n", ull);
+ break;
+ case 0x17:
+ printf(" MBs transferred to app client in duty cycle "
+ "sample time: %" PRIu64 "\n", ull);
+ break;
+ case 0x40:
+ printf(" Drive manufacturer's serial number: %" PRIu64 "\n",
+ ull);
+ break;
+ case 0x41:
+ printf(" Drive serial number: %" PRIu64 "\n", ull);
+ break;
+ case 0x80:
+ printf(" Medium removal prevented: %" PRIu64 "\n", ull);
+ break;
+ case 0x81:
+ printf(" Maximum recommended mechanism temperature "
+ "exceeded: %" PRIu64 "\n", ull);
+ break;
+ case 0x1000:
+ printf(" Medium motion hours for each medium type: %" PRIu64
+ "\n", ull);
+ break;
default:
- printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n",
- pc, ull);
+ printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n", pc,
+ ull);
break;
}
} else {
+ int k;
+ const uint8_t * p = ucp + 4;
+
switch (pc) {
case 0x1000:
printf(" Media motion (head) hours for each medium type:\n");
- printf(" <<to be decoded, dump in hex for now>>:\n");
- dStrHex((const char *)ucp, pl, 0);
- // xxxxxxxxxxx
+ for (k = 0; ((pl - 4) - k) >= 8; k += 8, p += 8) {
+ printf(" Density code: 0x%x, Medium type: 0x%x\n",
+ p[2], p[3]);
+ printf(" Medium motion hours: %u\n",
+ sg_get_unaligned_be32(p + 4));
+ }
break;
default:
- printf(" Reserved parameter [0x%x], dump in hex:\n", pc);
+ if (pc >= 0x8000)
+ printf(" Vendor specific parameter [0x%x], dump in "
+ "hex:\n", pc);
+ else
+ printf(" Reserved parameter [0x%x], dump in hex:\n", pc);
dStrHex((const char *)ucp, pl, 0);
break;
}
@@ -4815,7 +4935,7 @@ show_media_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
}
}
- ull = decode_count(ucp + 4, pl - 4);
+ ull = sg_get_unaligned_be(pl - 4, ucp + 4);
switch (pc) {
case 0:
printf(" Number of moves: %" PRIu64 "\n", ull);
@@ -5170,51 +5290,46 @@ skip:
/* Helper for show_volume_stats_page() */
static void
-volume_stats_partition(const uint8_t * xp, int len, int hex)
+volume_stats_partition(const uint8_t * xp, int len, bool in_hex)
{
- int dl, pn;
+ int dl, pn, k;
+ bool all_ffs, ffs_last_fe;
+ uint8_t uc;
+ uint64_t ull;
while (len > 3) {
dl = xp[0] + 1;
if (dl < 3)
return;
pn = sg_get_unaligned_be16(xp + 2);
- if (hex)
- printf(" partition number: %d, partition record data "
- "counter: 0x%" PRIx64 "\n", pn,
- decode_count(xp + 4, dl - 4));
- else {
- int k;
- int all_ffs = 0;
- int ffs_last_fe = 0;
- uint8_t uc;
-
- for (k = 0; k < (dl - 4); ++k) {
- uc = xp[4 + k];
- if (uc < 0xfe)
- break;
- if ((k < (dl - 5)) && (0xfe == uc))
- break;
- if (k == (dl - 5)) {
- if (0xff == uc)
- all_ffs = 1;
- else if (0xfe == uc)
- ffs_last_fe = 1;
- }
+ for (k = 0, all_ffs = false, ffs_last_fe = false; k < (dl - 4); ++k) {
+ uc = xp[4 + k];
+ if (uc < 0xfe)
+ break;
+ if ((k < (dl - 5)) && (0xfe == uc))
+ break;
+ if (k == (dl - 5)) {
+ if (0xff == uc)
+ all_ffs = true;
+ else if (0xfe == uc)
+ ffs_last_fe = true;
}
-
- if (0 == (all_ffs + ffs_last_fe))
- printf(" partition number: %d, partition record data "
- "counter: %" PRIu64 "\n", pn,
- decode_count(xp + 4, dl - 4));
- else if (all_ffs)
+ }
+ if ((! all_ffs) && (! ffs_last_fe)) {
+ ull = sg_get_unaligned_be(dl - 4, xp + 4);
+ if (in_hex)
printf(" partition number: %d, partition record data "
- "counter is all 0xFFs\n", pn);
+ "counter: 0x%" PRIx64 "\n", pn, ull);
else
printf(" partition number: %d, partition record data "
- "counter is all 0xFFs apart\n from a trailing "
- "0xFE\n", pn);
- }
+ "counter: %" PRIu64 "\n", pn, ull);
+ } else if (all_ffs)
+ printf(" partition number: %d, partition record data "
+ "counter is all 0xFFs\n", pn);
+ else
+ printf(" partition number: %d, partition record data "
+ "counter is all 0xFFs apart\n from a trailing "
+ "0xFE\n", pn);
xp += dl;
len -= dl;
}
@@ -5228,6 +5343,7 @@ show_volume_stats_page(const uint8_t * resp, int len,
int num, pl, pc, pcb, spf, subpg_code;
const uint8_t * ucp;
char pcb_str[PCB_STR_LEN];
+ char b[64];
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
@@ -5265,99 +5381,99 @@ show_volume_stats_page(const uint8_t * resp, int len,
switch (pc) {
case 0:
printf(" Page valid: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 1:
printf(" Thread count: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 2:
printf(" Total data sets written: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 3:
printf(" Total write retries: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 4:
printf(" Total unrecovered write errors: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 5:
printf(" Total suspended writes: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 6:
printf(" Total fatal suspended writes: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 7:
printf(" Total data sets read: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 8:
printf(" Total read retries: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 9:
printf(" Total unrecovered read errors: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xa:
printf(" Total suspended reads: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xb:
printf(" Total fatal suspended reads: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xc:
printf(" Last mount unrecovered write errors: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xd:
printf(" Last mount unrecovered read errors: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xe:
printf(" Last mount megabytes written: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0xf:
printf(" Last mount megabytes read: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x10:
printf(" Lifetime megabytes written: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x11:
printf(" Lifetime megabytes read: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x12:
printf(" Last load write compression ratio: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x13:
printf(" Last load read compression ratio: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x14:
printf(" Medium mount time: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x15:
printf(" Medium ready time: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x16:
- printf(" Total native capacity: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ printf(" Total native capacity [MB]: %s\n",
+ num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b)));
break;
case 0x17:
- printf(" Total used native capacity: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ printf(" Total used native capacity [MB]: %s\n",
+ num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b)));
break;
case 0x40:
printf(" Volume serial number: %.*s\n", pl - 4, ucp + 4);
@@ -5378,49 +5494,50 @@ show_volume_stats_page(const uint8_t * resp, int len,
printf(" Volume personality: %.*s\n", pl - 4, ucp + 4);
break;
case 0x80:
- printf(" Write protect: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ printf(" Write protect: %s\n",
+ num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b)));
break;
case 0x81:
- printf(" WORM: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ printf(" WORM: %s\n",
+ num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b)));
break;
case 0x82:
- printf(" Maximum recommended tape path temperature exceeded: %"
- PRIu64 "\n", decode_count(ucp + 4, pl - 4));
+ printf(" Maximum recommended tape path temperature exceeded: "
+ "%s\n", num_or_unknown(ucp + 4, pl - 4, false, b,
+ sizeof(b)));
break;
case 0x100:
printf(" Volume write mounts: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x101:
printf(" Beginning of medium passes: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x102:
printf(" Middle of medium passes: %" PRIu64 "\n",
- decode_count(ucp + 4, pl - 4));
+ sg_get_unaligned_be(pl - 4, ucp + 4));
break;
case 0x200:
printf(" Logical position of first encrypted logical object:\n");
- volume_stats_partition(ucp + 4, pl - 4, 1);
+ volume_stats_partition(ucp + 4, pl - 4, true);
break;
case 0x201:
printf(" Logical position of first unencrypted logical object "
"after first\n encrypted logical object:\n");
- volume_stats_partition(ucp + 4, pl - 4, 1);
+ volume_stats_partition(ucp + 4, pl - 4, true);
break;
case 0x202:
- printf(" Native capacity partition(s):\n");
- volume_stats_partition(ucp + 4, pl - 4, 0);
+ printf(" Native capacity partition(s) [MB]:\n");
+ volume_stats_partition(ucp + 4, pl - 4, false);
break;
case 0x203:
- printf(" Used native capacity partition(s):\n");
- volume_stats_partition(ucp + 4, pl - 4, 0);
+ printf(" Used native capacity partition(s) [MB]:\n");
+ volume_stats_partition(ucp + 4, pl - 4, false);
break;
case 0x204:
- printf(" Remaining native capacity partition(s):\n");
- volume_stats_partition(ucp + 4, pl - 4, 0);
+ printf(" Remaining native capacity partition(s) [MB]:\n");
+ volume_stats_partition(ucp + 4, pl - 4, false);
break;
case 0x300:
printf(" Mount history, payload in hex:\n");
@@ -5611,7 +5728,7 @@ show_seagate_cache_page(const uint8_t * resp, int len,
"> segment size"); break;
default: printf(" Unknown Seagate parameter code = 0x%x", pc); break;
}
- printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
+ printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4));
if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
@@ -5666,7 +5783,7 @@ show_seagate_factory_page(const uint8_t * resp, int len,
break;
}
if (valid) {
- ull = decode_count(ucp + 4, pl - 4);
+ ull = sg_get_unaligned_be(pl - 4, ucp + 4);
if (0 == pc)
printf(" = %.2f", ((double)ull) / 60.0 );
else
@@ -5711,11 +5828,10 @@ show_ascii_page(const uint8_t * resp, int len, const struct opts_t * op)
if (! done) {
if (spf)
- printf("No ascii information for page = 0x%x, subpage = 0x%x, "
- "here is hex:\n", pg_code, subpg_code);
+ printf("Unable to decode page = 0x%x, subpage = 0x%x, here is "
+ "hex:\n", pg_code, subpg_code);
else
- printf("No ascii information for page = 0x%x, here is hex:\n",
- pg_code);
+ printf("Unable to decode page = 0x%x, here is hex:\n", pg_code);
if (len > 128) {
dStrHex((const char *)resp, 64, 1);
printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
@@ -5853,10 +5969,12 @@ main(int argc, char * argv[])
pr2serr("Version string: %s\n", version_str);
return 0;
}
- if (op->do_enumerate > 0) {
+ if ((op->do_enumerate > 0) || (op->do_enum_vendor > 0)) {
if (op->device_name && op->verbose)
pr2serr("Warning: device: %s is being ignored\n",
op->device_name);
+ if ((op->do_enum_vendor > 0) && (0 == op->do_enumerate))
+ op->do_enumerate = 1;
enumerate_pages(op);
return 0;
}
diff --git a/src/sg_persist.c b/src/sg_persist.c
index 957525d4..9d19e79d 100644
--- a/src/sg_persist.c
+++ b/src/sg_persist.c
@@ -1,5 +1,5 @@
/* A utility program originally written for the Linux OS SCSI subsystem.
- * Copyright (C) 2004-2015 D. Gilbert
+ * Copyright (C) 2004-2016 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)
@@ -28,7 +28,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "0.51 20151219";
+static const char * version_str = "0.52 20160201";
#define PRIN_RKEY_SA 0x0
@@ -779,8 +779,8 @@ decode_sym_transportid(const char * lcp, unsigned char * tidp)
return 0;
}
-/* Read one or more TransportIDs from the given file or from stdin.
- * Returns 0 if successful, 1 otherwise. */
+/* Read one or more TransportIDs from the given file or stdin. Reads from
+ * stdin when 'fnp' is NULL. Returns 0 if successful, 1 otherwise. */
static int
decode_file_tids(const char * fnp, struct opts_t * op)
{
@@ -797,7 +797,7 @@ decode_file_tids(const char * fnp, struct opts_t * op)
if (fnp) {
fp = fopen(fnp, "r");
if (NULL == fp) {
- pr2serr("decode_file_tids: unable to open %s\n", fnp);
+ pr2serr("%s: unable to open %s\n", __func__, fnp);
return 1;
}
}
@@ -825,8 +825,8 @@ decode_file_tids(const char * fnp, struct opts_t * op)
if (1 == sscanf(carry_over, "%x", &h))
tid_arr[off - 1] = h; /* back up and overwrite */
else {
- pr2serr("decode_file_tids: carry_over error ['%s'] "
- "around line %d\n", carry_over, j + 1);
+ pr2serr("%s: carry_over error ['%s'] around line %d\n",
+ __func__, carry_over, j + 1);
goto bad;
}
lcp = line + 1;
@@ -847,16 +847,15 @@ decode_file_tids(const char * fnp, struct opts_t * op)
goto my_cont_a;
k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
if ((k < in_len) && ('#' != lcp[k])) {
- pr2serr("decode_file_tids: syntax error at line %d, pos %d\n",
- j + 1, m + k + 1);
+ pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1,
+ m + k + 1);
goto bad;
}
for (k = 0; k < 1024; ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
- pr2serr("decode_file_tids: hex number larger than 0xff "
- "in line %d, pos %d\n", j + 1,
- (int)(lcp - line + 1));
+ pr2serr("%s: hex number larger than 0xff in line %d, pos "
+ "%d\n", __func__, j + 1, (int)(lcp - line + 1));
goto bad;
}
if (split_line && (1 == strlen(lcp))) {
@@ -864,7 +863,7 @@ decode_file_tids(const char * fnp, struct opts_t * op)
carry_over[0] = *lcp;
}
if ((off + k) >= (int)sizeof(op->transportid_arr)) {
- pr2serr("decode_file_tids: array length exceeded\n");
+ pr2serr("%s: array length exceeded\n", __func__);
goto bad;
}
tid_arr[off + k] = h;
@@ -879,20 +878,22 @@ decode_file_tids(const char * fnp, struct opts_t * op)
--k;
break;
}
- pr2serr("decode_file_tids: error in line %d, at pos %d\n",
- j + 1, (int)(lcp - line + 1));
+ pr2serr("%s: error in line %d, at pos %d\n", __func__, j + 1,
+ (int)(lcp - line + 1));
goto bad;
}
}
my_cont_a:
off += MX_TID_LEN;
if (off >= (MX_TIDS * MX_TID_LEN)) {
- pr2serr("decode_file_tids: array length exceeded\n");
+ pr2serr("%s: array length exceeded\n", __func__);
goto bad;
}
++num;
}
op->num_transportids = num;
+ if (fnp)
+ fclose(fp);
return 0;
bad:
diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c
index 4b89a5f4..384bb18d 100644
--- a/src/sg_read_buffer.c
+++ b/src/sg_read_buffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2015 Luben Tuikov and Douglas Gilbert.
+ * Copyright (c) 2006-2016 Luben Tuikov and Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -30,7 +30,7 @@
* device.
*/
-static const char * version_str = "1.14 20151219";
+static const char * version_str = "1.15 20160131";
#ifndef SG_READ_BUFFER_10_CMD
@@ -484,14 +484,13 @@ main(int argc, char * argv[])
else {
switch (rb_mode) {
case MODE_DESCRIPTOR:
- k = (resp[1] << 16) | (resp[2] << 8) | resp[3];
+ k = sg_get_unaligned_be24(resp + 1);
printf("OFFSET BOUNDARY: %d, Buffer offset alignment: "
"%d-byte\n", resp[0], (1 << resp[0]));
printf("BUFFER CAPACITY: %d (0x%x)\n", k, k);
break;
case MODE_ECHO_BDESC:
- k = ((resp[2] & 0x1F) << 8) | resp[3];
-
+ k = sg_get_unaligned_be16(resp + 2) & 0x1fff;
printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0);
printf("Echo buffer capacity: %d (0x%x)\n", k, k);
break;
diff --git a/src/sg_referrals.c b/src/sg_referrals.c
index 051f3520..de65010d 100644
--- a/src/sg_referrals.c
+++ b/src/sg_referrals.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Hannes Reinecke.
+ * Copyright (c) 2010-2016 Hannes Reinecke.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -31,7 +31,7 @@
* SCSI device.
*/
-static const char * version_str = "1.05 20151219"; /* sbc4r01 */
+static const char * version_str = "1.06 20160131"; /* sbc4r10 */
#define MAX_REFER_BUFF_LEN (1024 * 1024)
#define DEF_REFER_BUFF_LEN 256
@@ -154,7 +154,8 @@ decode_referral_desc(const unsigned char * ucp, int bytes)
return -1;
printf(" target port descriptor %d:\n", j);
printf(" port group %x state (%s)\n",
- (ucp[n+2] << 8) | (ucp[n+3]), decode_tpgs_state(ucp[n] & 0xf));
+ sg_get_unaligned_be16(ucp + n + 2),
+ decode_tpgs_state(ucp[n] & 0xf));
n += 4;
bytes -= 4;
}
@@ -284,8 +285,7 @@ main(int argc, char * argv[])
* possible user segments.
* And maybe someone takes a pity and updates the spec ...
*/
- rlen = (referralBuffp[0] << 24) + (referralBuffp[1] << 16) +
- (referralBuffp[2] << 8) + referralBuffp[3] + 4;
+ rlen = sg_get_unaligned_be32(referralBuffp + 0) + 4;
else
rlen = maxlen;
k = (rlen > maxlen) ? maxlen : rlen;
diff --git a/src/sg_ses.c b/src/sg_ses.c
index c04a5797..64996641 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2015 Douglas Gilbert.
+ * Copyright (c) 2004-2016 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -30,7 +30,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.06 20151219"; /* ses3r08->11 */
+static const char * version_str = "2.07 20160201"; /* ses3r08->11 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -1615,14 +1615,14 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
resp = (unsigned char *)calloc(op->maxlen, 1);
if (NULL == resp) {
- pr2serr("populate: unable to allocate %d bytes on heap\n",
+ pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
op->maxlen);
ret = -1;
goto the_end;
}
res = do_rec_diag(fd, DPC_CONFIGURATION, resp, op->maxlen, op, &resp_len);
if (res) {
- pr2serr("populate: couldn't read config page, res=%d\n", res);
+ pr2serr("%s: couldn't read config page, res=%d\n", __func__, res);
ret = -1;
goto the_end;
}
@@ -1643,7 +1643,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
el = ucp[3] + 4;
sum_type_dheaders += ucp[2];
if (el < 40) {
- pr2serr("populate: short enc descriptor len=%d ??\n", el);
+ pr2serr("%s: short enc descriptor len=%d ??\n", __func__, el);
continue;
}
if ((0 == k) && primary_ip) {
@@ -1660,7 +1660,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
if ((ucp + 3) > last_ucp)
goto p_truncated;
if (k >= MX_ELEM_HDR) {
- pr2serr("populate: too many elements\n");
+ pr2serr("%s: too many elements\n", __func__);
ret = -1;
goto the_end;
}
@@ -1683,10 +1683,10 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
op->ind_th = k;
else {
if (op->ind_et_inst)
- pr2serr("populate: unable to find element type '%s%d'\n",
+ pr2serr("%s: unable to find element type '%s%d'\n", __func__,
op->ind_etp->abbrev, op->ind_et_inst);
else
- pr2serr("populate: unable to find element type '%s'\n",
+ pr2serr("%s: unable to find element type '%s'\n", __func__,
op->ind_etp->abbrev);
ret = -1;
goto the_end;
@@ -1696,7 +1696,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp,
goto the_end;
p_truncated:
- pr2serr("populate: config too short\n");
+ pr2serr("%s: config too short\n", __func__);
ret = -1;
the_end:
@@ -3010,16 +3010,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
return 1;
lcp = inp;
in_len = strlen(inp);
- if (0 == in_len) {
+ if (0 == in_len)
*arr_len = 0;
- }
if (('-' == inp[0]) || ('@' == inp[0])) { /* read from stdin or file */
if ('-' == inp[0])
fp = stdin;
else {
fp = fopen(inp + 1, "r");
if (NULL == fp) {
- pr2serr("read_hex: unable to open file: %s\n", inp + 1);
+ pr2serr("%s: unable to open file: %s\n", __func__, inp + 1);
return 1;
}
}
@@ -3048,8 +3047,8 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
if (1 == sscanf(carry_over, "%x", &h))
arr[off - 1] = h; /* back up and overwrite */
else {
- pr2serr("read_hex: carry_over error ['%s'] around "
- "line %d\n", carry_over, j + 1);
+ pr2serr("%s: carry_over error ['%s'] around line "
+ "%d\n", __func__, carry_over, j + 1);
goto err_with_fp;
}
lcp = line + 1;
@@ -3068,15 +3067,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
continue;
k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
if (in_len != k) {
- pr2serr("read_hex: syntax error at line %d, pos %d\n", j + 1,
- m + k + 1);
+ pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
+ j + 1, m + k + 1);
goto err_with_fp;
}
for (k = 0; k < (MX_DATA_IN - off); ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
- pr2serr("read_hex: hex number larger than 0xff in "
- "line %d, pos %d\n", j + 1,
+ pr2serr("%s: hex number larger than 0xff in line %d, "
+ "pos %d\n", __func__, j + 1,
(int)(lcp - line + 1));
goto err_with_fp;
}
@@ -3092,8 +3091,8 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
if ('\0' == *lcp)
break;
} else {
- pr2serr("read_hex: error in line %d, at pos %d\n", j + 1,
- (int)(lcp - line + 1));
+ pr2serr("%s: error in line %d, at pos %d\n", __func__,
+ j + 1, (int)(lcp - line + 1));
goto err_with_fp;
}
}
@@ -3105,15 +3104,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
} else { /* hex string on command line */
k = strspn(inp, "0123456789aAbBcCdDeEfF, ");
if (in_len != k) {
- pr2serr("read_hex: error at pos %d\n", k + 1);
- return 1;
+ pr2serr("%s: error at pos %d\n", __func__, k + 1);
+ goto err_with_fp;
}
for (k = 0; k < MX_DATA_IN; ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
- pr2serr("read_hex: hex number larger than 0xff at pos "
- "%d\n", (int)(lcp - inp + 1));
- return 1;
+ pr2serr("%s: hex number larger than 0xff at pos %d\n",
+ __func__, (int)(lcp - inp + 1));
+ goto err_with_fp;
}
arr[k] = h;
cp = (char *)strchr(lcp, ',');
@@ -3126,8 +3125,9 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb)
cp = c2p;
lcp = cp + 1;
} else {
- pr2serr("read_hex: error at pos %d\n", (int)(lcp - inp + 1));
- return 1;
+ pr2serr("%s: error at pos %d\n", __func__,
+ (int)(lcp - inp + 1));
+ goto err_with_fp;
}
}
*arr_len = k + 1;
@@ -3157,7 +3157,7 @@ ses_process_status_page(int sg_fd, struct opts_t * op)
resp = (unsigned char *)calloc(op->maxlen, 1);
if (NULL == resp) {
- pr2serr("process_status_page: unable to allocate %d bytes on heap\n",
+ pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
op->maxlen);
ret = -1;
goto fini;
@@ -4158,21 +4158,21 @@ ses_set_nickname(int sg_fd, struct opts_t * op)
/* Only after the generation code, offset 4 for 4 bytes */
res = do_rec_diag(sg_fd, DPC_SUBENC_NICKNAME, b, 8, op, &resp_len);
if (res) {
- pr2serr("set_nickname: Subenclosure nickname status page, res=%d\n",
+ pr2serr("%s: Subenclosure nickname status page, res=%d\n", __func__,
res);
return -1;
}
if (resp_len < 8) {
- pr2serr("set_nickname: Subenclosure nickname status page, response "
- "length too short: %d\n", resp_len);
+ pr2serr("%s: Subenclosure nickname status page, response length too "
+ "short: %d\n", __func__, resp_len);
return -1;
}
if (op->verbose) {
uint32_t gc;
gc = sg_get_unaligned_be32(b + 4);
- pr2serr("set_nickname: generation code from status page: %" PRIu32
- "\n", gc);
+ pr2serr("%s: generation code from status page: %" PRIu32 "\n",
+ __func__, gc);
}
b[0] = (unsigned char)DPC_SUBENC_NICKNAME; /* just in case */
b[1] = (unsigned char)op->seid;
diff --git a/src/sg_unmap.c b/src/sg_unmap.c
index cdaba327..024499d0 100644
--- a/src/sg_unmap.c
+++ b/src/sg_unmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2015 Douglas Gilbert.
+ * Copyright (c) 2009-2016 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
@@ -31,7 +32,7 @@
* logical blocks.
*/
-static const char * version_str = "1.09 20151219";
+static const char * version_str = "1.10 20160201";
#define DEF_TIMEOUT_SECS 60
@@ -252,7 +253,8 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
{
char line[1024];
int off = 0;
- int in_len, k, j, m, have_stdin, ind, bit0;
+ int in_len, k, j, m, ind, bit0;
+ bool have_stdin;
char * lcp;
FILE * fp;
int64_t ll;
@@ -263,7 +265,7 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
else {
fp = fopen(file_name, "r");
if (NULL == fp) {
- pr2serr("build_joint_arr: unable to open %s\n", file_name);
+ pr2serr("%s: unable to open %s\n", __func__, file_name);
return 1;
}
}
@@ -291,9 +293,9 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
continue;
k = strspn(lcp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP ,\t");
if ((k < in_len) && ('#' != lcp[k])) {
- pr2serr("build_joint_arr: syntax error at line %d, pos %d\n",
- j + 1, m + k + 1);
- return 1;
+ pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1,
+ m + k + 1);
+ goto bad_exit;
}
for (k = 0; k < 1024; ++k) {
ll = sg_get_llnum(lcp);
@@ -301,15 +303,15 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
ind = ((off + k) >> 1);
bit0 = 0x1 & (off + k);
if (ind >= max_arr_len) {
- pr2serr("build_joint_arr: array length exceeded\n");
- return 1;
+ pr2serr("%s: array length exceeded\n", __func__);
+ goto bad_exit;
}
if (bit0) {
if (ll > UINT32_MAX) {
- pr2serr("build_joint_arr: number exceeds 32 bits in "
- "line %d, at pos %d\n", j + 1,
+ pr2serr("%s: number exceeds 32 bits in line %d, at "
+ "pos %d\n", __func__, j + 1,
(int)(lcp - line + 1));
- return 1;
+ goto bad_exit;
}
num_arr[ind] = (uint32_t)ll;
} else
@@ -325,20 +327,27 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr,
--k;
break;
}
- pr2serr("build_joint_arr: error on line %d, at pos %d\n",
- j + 1, (int)(lcp - line + 1));
- return 1;
+ pr2serr("%s: error on line %d, at pos %d\n", __func__, j + 1,
+ (int)(lcp - line + 1));
+ goto bad_exit;
}
}
off += (k + 1);
}
if (0x1 & off) {
- pr2serr("build_joint_arr: expect LBA,NUM pairs but decoded odd "
- "number\n from %s\n", have_stdin ? "stdin" : file_name);
- return 1;
+ pr2serr("%s: expect LBA,NUM pairs but decoded odd number\n from "
+ "%s\n", __func__, have_stdin ? "stdin" : file_name);
+ goto bad_exit;
}
*arr_len = off >> 1;
+ if (fp && (stdin != fp))
+ fclose(fp);
return 0;
+
+bad_exit:
+ if (fp && (stdin != fp))
+ fclose(fp);
+ return 1;
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index d7591054..f6ba4bb7 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
@@ -36,7 +37,7 @@
*/
-static const char * version_str = "1.12 20160126"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.12 20160201"; /* spc5r08 + sbc4r10 */
/* These structures are duplicates of those of the same name in
@@ -286,7 +287,8 @@ static int
f2hex_arr(const char * fname, int as_binary, int no_space,
unsigned char * mp_arr, int * mp_arr_len, int max_arr_len)
{
- int fn_len, in_len, k, j, m, split_line, fd, has_stdin;
+ int fn_len, in_len, k, j, m, split_line, fd;
+ bool has_stdin;
unsigned int h;
const char * lcp;
FILE * fp;
@@ -499,7 +501,7 @@ pt_inquiry(int sg_fd, int evpd, int pg_op, void * resp, int mx_resp_len,
}
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
- pr2serr("inquiry: out of memory\n");
+ pr2serr("%s: out of memory\n", __func__);
return -1;
}
set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk));
@@ -526,7 +528,7 @@ pt_inquiry(int sg_fd, int evpd, int pg_op, void * resp, int mx_resp_len,
}
} else if (ret < 4) {
if (verbose)
- pr2serr("inquiry: got too few bytes (%d)\n", ret);
+ pr2serr("%s: got too few bytes (%d)\n", __func__, ret);
ret = SG_LIB_CAT_MALFORMED;
} else
ret = 0;
@@ -1892,14 +1894,14 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex)
{
int k, j, bump, cd_len;
unsigned char * ucp;
+ const char * dcp = "Device constituents VPD page";
if ((1 == do_hex) || (do_hex > 2)) {
dStrHex((const char *)buff, len, (1 == do_hex) ? 0 : -1);
return;
}
if (len < 4) {
- pr2serr("Deice constituents VPD page length too short=%d\n",
- len);
+ pr2serr("%s length too short=%d\n", dcp, len);
return;
}
len -= 4;
@@ -1909,8 +1911,8 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex)
printf(" Constituent descriptor %d:\n", j + 1);
if ((k + 36) > len) {
- pr2serr("Device constituents VPD page, short descriptor "
- "length=36, left=%d\n", (len - k));
+ pr2serr("%s, short descriptor length=36, left=%d\n", dcp,
+ (len - k));
return;
}
printf(" Constituent type: 0x%x\n",
@@ -1922,8 +1924,8 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex)
cd_len = sg_get_unaligned_be16(ucp + 34);
bump = 36 + cd_len;
if ((k + bump) > len) {
- pr2serr("Device constituents VPD page, short descriptor "
- "length=%d, left=%d\n", bump, (len - k));
+ pr2serr("%s, short descriptor length=%d, left=%d\n", dcp, bump,
+ (len - k));
return;
}
if (cd_len > 0) {
@@ -1952,13 +1954,14 @@ decode_power_consumption_vpd(unsigned char * buff, int len, int do_hex)
int k, bump;
unsigned char * ucp;
unsigned int value;
+ const char * pcp = "Power consumption VPD page";
if ((1 == do_hex) || (do_hex > 2)) {
dStrHex((const char *)buff, len, (1 == do_hex) ? 1 : -1);
return;
}
if (len < 4) {
- pr2serr("Power consumption VPD page length too short=%d\n", len);
+ pr2serr("%s length too short=%d\n", pcp,len);
return;
}
len -= 4;
@@ -1966,8 +1969,8 @@ decode_power_consumption_vpd(unsigned char * buff, int len, int do_hex)
for (k = 0; k < len; k += bump, ucp += bump) {
bump = 4;
if ((k + bump) > len) {
- pr2serr("Power consumption VPD page, short descriptor "
- "length=%d, left=%d\n", bump, (len - k));
+ pr2serr("%s, short descriptor length=%d, left=%d\n", pcp, bump,
+ (len - k));
return;
}
if (do_hex > 1)
diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c
index 57369bc8..a6a6ca17 100644
--- a/src/sg_xcopy.c
+++ b/src/sg_xcopy.c
@@ -63,7 +63,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "0.53 20160126";
+static const char * version_str = "0.53 20160201";
#define ME "sg_xcopy: "
@@ -992,7 +992,7 @@ decode_designation_descriptor(const unsigned char * ucp, int i_len)
char c[2048];
sg_get_designation_descriptor_str(NULL, ucp, i_len, 1, verbose,
- sizeof(c), c);
+ sizeof(c), c);
pr2serr("%s", c);
}