aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2016-04-02 00:33:00 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2016-04-02 00:33:00 +0000
commit61a0b017ebca98eca9c5d85264af45b3eb1853e5 (patch)
treea4eccd675fce2340b4a4ff78a4ce386df36a920f
parent2133555f87aa82ee833494d2e55ca530132dfb4e (diff)
downloadsg3_utils-61a0b017ebca98eca9c5d85264af45b3eb1853e5.tar.gz
sg_raw: add '--enumerate' option
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@688 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog3
-rw-r--r--doc/sg_raw.836
-rw-r--r--doc/sg_readcap.820
-rw-r--r--lib/sg_cmds_basic.c7
-rw-r--r--lib/sg_cmds_basic2.c8
-rw-r--r--lib/sg_lib.c112
-rw-r--r--lib/sg_lib_data.c4
-rw-r--r--src/sg_inq.c35
-rw-r--r--src/sg_logs.c4
-rw-r--r--src/sg_raw.c110
-rw-r--r--src/sg_vpd.c12
11 files changed, 202 insertions, 149 deletions
diff --git a/ChangeLog b/ChangeLog
index 95dfb360..158a6aa2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.43 [20160325] [svn: r687]
+Changelog for sg3_utils-1.43 [20160401] [svn: r688]
- sg_senddiag: add --timeout=SEC option
- sg_sanitize: add --timeout=SEC option
- sg_format: add --timeout=SEC option
@@ -19,6 +19,7 @@ Changelog for sg3_utils-1.43 [20160325] [svn: r687]
and '--number=NUM' for mutual compatibility
- sg_zone: fix debug cdb naming
- sg_opcode: add '--enumerate' and '--pdt=' options
+ - sg_raw: add '--enumerate' option
- sg_lib: add SSC maintenance in/out sa names
- add read buffer(16) mode names
- rescan-scsi-bus.sh: harden code
diff --git a/doc/sg_raw.8 b/doc/sg_raw.8
index 16d6437a..a80629fe 100644
--- a/doc/sg_raw.8
+++ b/doc/sg_raw.8
@@ -1,8 +1,13 @@
-.TH SG_RAW "8" "November 2015" "sg3_utils\-1.42" SG3_UTILS
+.TH SG_RAW "8" "March 2016" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_raw \- send arbitrary SCSI command to a device
.SH SYNOPSIS
-.B sg_raw [\fIOPTIONS\fR] \fIDEVICE\fR CDB0 CDB1 ...
+.B sg_raw
+[\fI\-\-binary\fR] [\fI\-\-enumerate\fR] [\fI\-\-help\fR]
+[\fI\-\-infile=IFILE\fR] [\fI\-\-nosense\fR] [\fI\-\-outfile=OFILE\fR]
+[\fI\-\-readonly\fR] [\fI\-\-request=RLEN\fR] [\fI\-\-send=SLEN\fR]
+[\fI\-\-skip=KLEN\fR] [\fI\-\-timeout=SEC\fR] [\fI\-\-verbose\fR]
+[\fI\-\-version\fR] \fIDEVICE\fR CDB0 CDB1 ...
.SH DESCRIPTION
This utility sends an arbitrary SCSI command (between 6 and 256 bytes) to
the \fIDEVICE\fR. There may be no associated data transfer; or data may be
@@ -20,6 +25,8 @@ The commands pass through a generic SCSI interface which is implemented
for several operating systems including Linux, FreeBSD and Windows.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
+The options are arranged in alphabetical order based on the long
+option name.
.TP
\fB\-b\fR, \fB\-\-binary\fR
Dump data in binary form, even when writing to stdout.
@@ -31,10 +38,6 @@ Display usage information and exit.
Read data from \fIIFILE\fR instead of stdin. This option is ignored if
\fB\-\-send\fR is not specified.
.TP
-\fB\-k\fR, \fB\-\-skip\fR=\fILEN\fR
-Skip the first \fILEN\fR bytes of the input file or stream. This option
-is ignored if \fB\-\-send\fR is not specified.
-.TP
\fB\-n\fR, \fB\-\-nosense\fR
Don't display SCSI Sense information.
.TP
@@ -42,7 +45,11 @@ Don't display SCSI Sense information.
Write data received from the \fIDEVICE\fR to \fIOFILE\fR. The data is
written in binary. By default, data is dumped in hex format to stdout.
If \fIOFILE\fR is '\-' then data is dumped in binary to stdout.
-This option is ignored if \fB\-\-request\fR is not specified.
+This option is ignored if \fI\-\-request\fR is not specified.
+.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+Open \fIDEVICE\fR read\-only. The default (without this option) is to open
+it read\-write.
.TP
\fB\-r\fR, \fB\-\-request\fR=\fIRLEN\fR
Expect to receive up to \fIRLEN\fR bytes of data from the \fIDEVICE\fR.
@@ -60,10 +67,6 @@ the "allocation length" field in the cdb is large enough. In practice, the
\fIDEVICE\fR will return no more bytes than indicated in the "allocation
length" field of the cdb.
.TP
-\fB\-R\fR, \fB\-\-readonly\fR
-Open \fIDEVICE\fR read\-only. The default (without this option) is to open
-it read\-write.
-.TP
\fB\-s\fR, \fB\-\-send\fR=\fISLEN\fR
Read \fISLEN\fR bytes of data, either from stdin or from a file, and send
them to the \fIDEVICE\fR. In the SCSI transport, \fISLEN\fR becomes the
@@ -75,6 +78,11 @@ length implied or stated in the cdb matches \fISLEN\fR. Note that some
common SCSI commands such as WRITE(10) have a "transfer length" field whose
units are logical blocks (which are often 512 bytes long).
.TP
+\fB\-k\fR, \fB\-\-skip\fR=\fIKLEN\fR
+Skip the first \fIKLEN\fR bytes of the input file or stream. This option
+is ignored if \fI\-\-send\fR is not specified. If \fI\-\-send\fR is given
+and this option is not given, then zero bytes are skipped.
+.TP
\fB\-t\fR, \fB\-\-timeout\fR=\fISEC\fR
Wait up to \fISEC\fR seconds for command completion (default: 20).
Note that if a command times out the operating system may start by
@@ -90,8 +98,8 @@ Display version and license information and exit.
The sg_inq utility can be used to send an INQUIRY command to a device
to determine its peripheral device type (e.g. '1' for a streaming
device (tape drive)) which determines which SCSI command sets a device
-should support (e.g. SPC and SSC). The sg_vpd utility probes the Vital
-Product Pages of a devices which may contain useful information.
+should support (e.g. SPC and SSC). The sg_vpd utility reads and decodes
+a device's Vital Product Pages which may contain useful information.
.PP
The ability to send more than a 16 byte CDB (in some cases 12 byte CDB)
may be restricted by the pass\-through interface, the low level driver
@@ -151,7 +159,7 @@ Written by Ingo van Lil
.SH "REPORTING BUGS"
Report bugs to <inguin at gmx dot de>.
.SH COPYRIGHT
-Copyright \(co 2001\-2015 Ingo van Lil
+Copyright \(co 2001\-2016 Ingo van Lil
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_readcap.8 b/doc/sg_readcap.8
index 9a8dc273..27e5b383 100644
--- a/doc/sg_readcap.8
+++ b/doc/sg_readcap.8
@@ -1,4 +1,4 @@
-.TH SG_READCAP "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_READCAP "8" "March 2016" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_readcap \- send SCSI READ CAPACITY command
.SH SYNOPSIS
@@ -104,11 +104,17 @@ increase level of verbosity. Can be used multiple times.
\fB\-V\fR, \fB\-\-version\fR
outputs version string then exits.
.SH NOTES
-In the 2.4 series of Linux kernels the \fIDEVICE\fR must be a SCSI
-generic (sg) device. In the 2.6 series block devices (e.g. SCSI disks
-and DVD drives) can also be specified. For example "sg_readcap /dev/sda"
-and "sg_readcap /dev/hdd" (if /dev/hdd is a ATAPI CD/DVD device) will
-work in the 2.6 series kernels.
+The response to READ CAPACITY(16) contains a LBPRZ bit in the SBC\-3
+standard (ANSI INCITS 514\-2014). There was also a LBPRZ bit with the same
+meaning in the Logical block provisioning VPD page (0xb2). Then somewhat
+confusingly T10 expanded the LBPRZ bit to a 3 bit field in SBC\-4 draft
+revision 7, but only in the LB provisioning VPD page. The reason for the
+expansion was to report a new "provisioning initialization pattern"
+state (when an unmapped logical block is read). The new state has been
+assigned LBPRZ=2 in the VPD page and it re\-uses LBPRZ=0 in the READ
+CAPACITY(16) response. LBPRZ=1 retains the same meaning for both variants,
+namely that a block of zeroes will be returned when an unmapped logical block
+is read.
.SH EXIT STATUS
The exit status of sg_readcap is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
@@ -166,7 +172,7 @@ outputs version string then exits.
.SH AUTHORS
Written by Douglas Gilbert
.SH COPYRIGHT
-Copyright \(co 1999\-2014 Douglas Gilbert
+Copyright \(co 1999\-2016 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 7a56d516..68dbd843 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -17,6 +17,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "sg_lib.h"
@@ -34,7 +35,7 @@
#endif
-static const char * version_str = "1.72 20160126";
+static const char * version_str = "1.73 20160331";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -118,7 +119,7 @@ sg_cmds_process_helper(const char * leadin, int mx_di_len, int resid,
{
int scat, got;
int n = 0;
- int check_data_in = 0;
+ bool check_data_in = false;
char b[512];
scat = sg_err_category_sense(sbp, slen);
@@ -136,7 +137,7 @@ sg_cmds_process_helper(const char * leadin, int mx_di_len, int resid,
break;
case SG_LIB_CAT_RECOVERED:
case SG_LIB_CAT_MEDIUM_HARD:
- ++check_data_in;
+ check_data_in = true;
/* drop through */
case SG_LIB_CAT_UNIT_ATTENTION:
case SG_LIB_CAT_SENSE:
diff --git a/lib/sg_cmds_basic2.c b/lib/sg_cmds_basic2.c
index 14a2de76..17c595a2 100644
--- a/lib/sg_cmds_basic2.c
+++ b/lib/sg_cmds_basic2.c
@@ -538,9 +538,7 @@ int
sg_mode_page_offset(const unsigned char * resp, int resp_len,
int mode_sense_6, char * err_buff, int err_buff_len)
{
- int bd_len;
- int calc_len;
- int offset;
+ int bd_len, calc_len, offset;
if ((NULL == resp) || (resp_len < 4) ||
((! mode_sense_6) && (resp_len < 8))) {
@@ -838,10 +836,10 @@ sg_ll_start_stop_unit(int sg_fd, int immed, int pc_mod__fl_num,
int power_cond, int noflush__fl, int loej, int start,
int noisy, int verbose)
{
- unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0};
- unsigned char sense_b[SENSE_BUFF_LEN];
int k, res, ret, sense_cat;
struct sg_pt_base * ptvp;
+ unsigned char ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
ssuBlk[1] = immed & 1;
ssuBlk[3] = pc_mod__fl_num & 0xf; /* bits 2 and 3 are reserved in MMC */
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 76ab165d..496e19de 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define __STDC_FORMAT_MACROS 1
@@ -158,7 +159,7 @@ void
sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff)
{
const char * ccp = NULL;
- int unknown = 0;
+ bool unknown = false;
if ((NULL == buff) || (buff_len < 1))
return;
@@ -180,7 +181,7 @@ sg_get_scsi_status_str(int scsi_status, int buff_len, char * buff)
case 0x30: ccp = "ACA Active"; break;
case 0x40: ccp = "Task Aborted"; break;
default:
- unknown = 1;
+ unknown = true;
break;
}
if (unknown)
@@ -238,7 +239,7 @@ char *
sg_get_asc_ascq_str(int asc, int ascq, int buff_len, char * buff)
{
int k, num, rlen;
- int found = 0;
+ bool found = false;
struct sg_lib_asc_ascq_t * eip;
struct sg_lib_asc_ascq_range_t * ei2p;
@@ -251,7 +252,7 @@ sg_get_asc_ascq_str(int asc, int ascq, int buff_len, char * buff)
if ((ei2p->asc == asc) &&
(ascq >= ei2p->ascq_min) &&
(ascq <= ei2p->ascq_max)) {
- found = 1;
+ found = true;
num = my_snprintf(buff, buff_len, "Additional sense: ");
rlen = buff_len - num;
num += my_snprintf(buff + num, ((rlen > 0) ? rlen : 0),
@@ -265,7 +266,7 @@ sg_get_asc_ascq_str(int asc, int ascq, int buff_len, char * buff)
eip = &sg_lib_asc_ascq[k];
if (eip->asc == asc &&
eip->ascq == ascq) {
- found = 1;
+ found = true;
my_snprintf(buff, buff_len, "Additional sense: %s", eip->text);
}
}
@@ -852,19 +853,26 @@ sg_get_designation_descriptor_str(const char * leadin,
n += dStrHexStr((const char *)ip, dlen, lip, 0, blen - n, b + n);
break;
case 8: /* SCSI name string */
- if (3 != c_set) {
- n += my_snprintf(b + n, blen - n, "%s << expected UTF-8 "
- "code_set >>\n", lip);
- n += dStrHexStr((const char *)ip, dlen, lip, 0, blen - n, b + n);
- break;
+ if (3 != c_set) { /* accept ASCII as subset of UTF-8 */
+ if (2 == c_set) {
+ if (do_long)
+ n += my_snprintf(b + n, blen - n, "%s << expected "
+ "UTF-8, use ASCII >>\n", lip);
+ } else {
+ n += my_snprintf(b + n, blen - n, "%s << expected UTF-8 "
+ "code_set >>\n", lip);
+ n += dStrHexStr((const char *)ip, dlen, lip, 0, blen - n,
+ b + n);
+ break;
+ }
}
n += my_snprintf(b + n, blen - n, "%s SCSI name string:\n", lip);
/* does %s print out UTF-8 ok??
* Seems to depend on the locale. Looks ok here with my
* locale setting: en_AU.UTF-8
*/
- n += my_snprintf(b + n, blen - n, "%s %s\n", lip,
- (const char *)ip);
+ n += my_snprintf(b + n, blen - n, "%s %.*s\n", lip,
+ dlen, (const char *)ip);
break;
case 9: /* Protocol specific port identifier */
/* added in spc4r36, PIV must be set, proto_id indicates */
@@ -933,7 +941,7 @@ sg_get_designation_descriptor_str(const char * leadin,
static int
decode_sks(const char * leadin, const unsigned char * descp, int add_d_len,
- int sense_key, int * processedp, int blen, char * b)
+ int sense_key, bool * processedp, int blen, char * b)
{
int progress, pr, rem, n;
const char * lip = "";
@@ -1002,14 +1010,14 @@ decode_sks(const char * leadin, const unsigned char * descp, int add_d_len,
default:
n += my_snprintf(b + n, blen - n, "Sense_key: 0x%x "
"unexpected\n", sense_key);
- *processedp = 0;
+ *processedp = false;
break;
}
return n;
too_short:
n += my_snprintf(b + n, blen - n, "%s\n", " >> descriptor too short");
- *processedp = 0;
+ *processedp = false;
return n;
}
@@ -1099,8 +1107,9 @@ sg_get_sense_descriptors_str(const char * leadin,
const unsigned char * sense_buffer, int sb_len,
int blen, char * b)
{
- int add_sb_len, add_d_len, desc_len, k, j, sense_key, processed;
+ int add_sb_len, add_d_len, desc_len, k, j, sense_key;
int n, progress, pr, rem;
+ bool processed;
const unsigned char * descp;
const char * lip = "";
const char * dtsp = " >> descriptor too short";
@@ -1129,7 +1138,7 @@ sg_get_sense_descriptors_str(const char * leadin,
add_d_len = add_sb_len - k - 2;
desc_len = add_d_len + 2;
n += my_snprintf(b + n, blen - n, "%s Descriptor type: ", lip);
- processed = 1;
+ processed = true;
switch (descp[0]) {
case 0:
n += my_snprintf(b + n, blen - n, "Information: ");
@@ -1140,7 +1149,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "\n");
} else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 1:
@@ -1152,7 +1161,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "\n");
} else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 2: /* Sense Key Specific */
@@ -1166,7 +1175,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "0x%x\n", descp[3]);
else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 4:
@@ -1182,7 +1191,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "\n");
} else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 5:
@@ -1193,22 +1202,22 @@ sg_get_sense_descriptors_str(const char * leadin,
(descp[3] & 0x20) ? "set" : "clear");
else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 6:
n += my_snprintf(b + n, blen - n, "OSD object identification\n");
- processed = 0;
+ processed = false;
break;
case 7:
n += my_snprintf(b + n, blen - n, "OSD response integrity check "
"value\n");
- processed = 0;
+ processed = false;
break;
case 8:
n += my_snprintf(b + n, blen - n, "OSD attribute "
"identification\n");
- processed = 0;
+ processed = false;
break;
case 9: /* this is defined in SAT (SAT-2) */
n += my_snprintf(b + n, blen - n, "ATA Status Return: ");
@@ -1233,7 +1242,7 @@ sg_get_sense_descriptors_str(const char * leadin,
descp[12], descp[13]);
} else {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
}
break;
case 0xa:
@@ -1242,7 +1251,7 @@ sg_get_sense_descriptors_str(const char * leadin,
"indication: ");
if (add_d_len < 6) {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
break;
}
progress = sg_get_unaligned_be16(descp + 6);
@@ -1257,7 +1266,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "User data segment referral: ");
if (add_d_len < 2) {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
break;
}
n += my_snprintf(b + n, blen - n, "\n");
@@ -1268,7 +1277,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "Forwarded sense data\n");
if (add_d_len < 2) {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
break;
}
n += my_snprintf(b + n, blen - n, "%s FSDT: %s\n", lip,
@@ -1317,7 +1326,7 @@ sg_get_sense_descriptors_str(const char * leadin,
n += my_snprintf(b + n, blen - n, "Direct-access block device\n");
if (add_d_len < 28) {
n += my_snprintf(b + n, blen - n, "%s\n", dtsp);
- processed = 0;
+ processed = false;
break;
}
if (0x20 & descp[2])
@@ -1364,7 +1373,7 @@ sg_get_sense_descriptors_str(const char * leadin,
else
n += my_snprintf(b + n, blen - n, "Unknown [0x%x]\n",
descp[0]);
- processed = 0;
+ processed = false;
break;
}
if (! processed) {
@@ -1393,7 +1402,7 @@ sg_get_sense_sat_pt_fixed_str(const char * leadin, const unsigned char * sp,
int slen, int blen, char * b)
{
int n = 0;
- int extend, count_upper_nz, lba_upper_nz;
+ bool extend, count_upper_nz, lba_upper_nz;
const char * lip = "";
if ((blen < 1) || (slen < 12))
@@ -1413,7 +1422,7 @@ sg_get_sense_sat_pt_fixed_str(const char * leadin, const unsigned char * sp,
sp[4], sp[5], sp[6], (count_upper_nz ? '+' : ' '));
n += my_snprintf(b + n, blen - n, "%s extend=%d, log_index=0x%x, "
"lba_high,mid,low(7:0)=0x%x,0x%x,0x%x%c\n", lip,
- extend, (0xf & sp[8]), sp[9], sp[10], sp[11],
+ (int)extend, (0xf & sp[8]), sp[9], sp[10], sp[11],
(lba_upper_nz ? '+' : ' '));
return n;
}
@@ -1423,10 +1432,11 @@ int
sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
int sb_len, int raw_sinfo, int buff_len, char * buff)
{
- int len, valid, progress, n, r, pr, rem, blen;
+ int len, progress, n, r, pr, rem, blen;
unsigned int info;
int descriptor_format = 0;
int sdat_ovfl = 0;
+ bool valid;
const char * ebp = NULL;
char error_buff[64];
char b[256];
@@ -1508,7 +1518,7 @@ sg_get_sense_str(const char * leadin, const unsigned char * sense_buffer,
sg_get_asc_ascq_str(ssh.asc, ssh.ascq,
sizeof(b), b));
r = 0;
- valid = sense_buffer[0] & 0x80;
+ valid = !!(sense_buffer[0] & 0x80);
if (strlen(lip) > 0)
r += my_snprintf(b + r, blen - r, "%s", lip);
if (len > 6) {
@@ -1902,22 +1912,28 @@ int
sg_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
int * off, int m_assoc, int m_desig_type, int m_code_set)
{
- const unsigned char * ucp;
- int k, c_set, assoc, desig_type;
+ bool fltr = ((m_assoc >= 0) || (m_desig_type >= 0) || (m_code_set >= 0));
+ int k = *off;
+ const unsigned char * ucp = initial_desig_desc;
- for (k = *off, ucp = initial_desig_desc ; (k + 3) < page_len; ) {
+ while ((k + 3) < page_len) {
k = (k < 0) ? 0 : (k + ucp[k + 3] + 4);
if ((k + 4) > page_len)
break;
- c_set = (ucp[k] & 0xf);
- if ((m_code_set >= 0) && (m_code_set != c_set))
- continue;
- assoc = ((ucp[k + 1] >> 4) & 0x3);
- if ((m_assoc >= 0) && (m_assoc != assoc))
- continue;
- desig_type = (ucp[k + 1] & 0xf);
- if ((m_desig_type >= 0) && (m_desig_type != desig_type))
- continue;
+ if (fltr) {
+ if (m_code_set >= 0) {
+ if ((ucp[k] & 0xf) != m_code_set)
+ continue;
+ }
+ if (m_assoc >= 0) {
+ if (((ucp[k + 1] >> 4) & 0x3) != m_assoc)
+ continue;
+ }
+ if (m_desig_type >= 0) {
+ if ((ucp[k + 1] & 0xf) != m_desig_type)
+ continue;
+ }
+ }
*off = k;
return 0;
}
@@ -2571,7 +2587,7 @@ sg_get_llnum(const char * buf)
if (n == len)
return -1LL;
buf += n;
- len -=n;
+ len -= n;
}
/* following hack to keep C++ happy */
cp = strpbrk((char *)buf, " \t,#");
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 91bffc30..89efe9ed 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -17,7 +17,7 @@
#endif
-const char * sg_lib_version_str = "2.18 20160312"; /* spc5r08, sbc4r10 */
+const char * sg_lib_version_str = "2.19 20160401"; /* spc5r08, sbc4r10 */
/* indexed by pdt; those that map to own index do not decay */
@@ -1430,7 +1430,7 @@ const char * sg_lib_sense_key_desc[] = {
"Completed" /* may occur for successful cmd (spc4r23) */
};
-const char * sg_lib_pdt_strs[] = {
+const char * sg_lib_pdt_strs[32] = { /* should have 2**5 elements */
/* 0 */ "disk",
"tape",
"printer", /* obsolete, spc5r01 */
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 6c58a5dd..54c455b8 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -123,13 +123,13 @@ static char usn_buff[MX_ALLOC_LEN + 1];
static const char * find_version_descriptor_str(int value);
static void decode_dev_ids(const char * leadin, unsigned char * buff,
- int len, int do_hex);
+ int len, int do_hex, int verbose);
static void decode_transport_id(const char * leadin, unsigned char * ucp,
int len);
#if defined(SG_LIB_LINUX) && defined(SG_SCSI_STRINGS)
static int try_ata_identify(int ata_fd, int do_hex, int do_raw,
- int do_verbose);
+ int verbose);
#endif
/* This structure is a duplicate of one of the same name in sg_vpd_vendor.c .
@@ -1272,14 +1272,15 @@ decode_ascii_inf(unsigned char * buff, int len, int do_hex)
}
static void
-decode_id_vpd(unsigned char * buff, int len, int do_hex)
+decode_id_vpd(unsigned char * buff, int len, int do_hex, int verbose)
{
if (len < 4) {
pr2serr("Device identification VPD page length too "
"short=%d\n", len);
return;
}
- decode_dev_ids("Device identification", buff + 4, len - 4, do_hex);
+ decode_dev_ids("Device identification", buff + 4, len - 4, do_hex,
+ verbose);
}
static const char * assoc_arr[] =
@@ -1393,7 +1394,7 @@ decode_mode_policy_vpd(unsigned char * buff, int len, int do_hex)
/* VPD_SCSI_PORTS */
static void
-decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
+decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex, int verbose)
{
int k, bump, rel_port, ip_tid_len, tpd_len;
unsigned char * ucp;
@@ -1439,7 +1440,7 @@ decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
(1 == do_hex) ? 1 : -1);
else
decode_dev_ids("SCSI Ports", ucp + bump + 4, tpd_len,
- do_hex);
+ do_hex, verbose);
}
bump += tpd_len + 4;
}
@@ -1447,7 +1448,8 @@ decode_scsi_ports_vpd(unsigned char * buff, int len, int do_hex)
/* These are target port, device server (i.e. target) and LU identifiers */
static void
-decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
+decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex,
+ int verbose)
{
int u, j, m, id_len, p_id, c_set, piv, assoc, desig_type, i_len;
int off, ci_off, c_id, d_id, naa, vsi, k;
@@ -1717,16 +1719,21 @@ decode_dev_ids(const char * leadin, unsigned char * buff, int len, int do_hex)
break;
case 8: /* SCSI name string */
if (3 != c_set) {
- pr2serr(" << expected UTF-8 code_set>>\n");
- dStrHexErr((const char *)ip, i_len, -1);
- break;
+ if (2 == c_set) {
+ if (verbose)
+ pr2serr(" << expected UTF-8, use ASCII>>\n");
+ } else {
+ pr2serr(" << expected UTF-8 code_set>>\n");
+ dStrHexErr((const char *)ip, i_len, -1);
+ break;
+ }
}
printf(" SCSI name string:\n");
/* does %s print out UTF-8 ok??
* Seems to depend on the locale. Looks ok here with my
* locale setting: en_AU.UTF-8
*/
- printf(" %s\n", (const char *)ip);
+ printf(" %.*s\n", i_len, (const char *)ip);
break;
case 9: /* Protocol specific port identifier */
/* added in spc4r36, PIV must be set, proto_id indicates */
@@ -3141,6 +3148,8 @@ vpd_fetch_page_from_dev(int sg_fd, unsigned char * rp, int page,
pr2serr("response length too long: %d > %d\n", len, MX_ALLOC_LEN);
return SG_LIB_CAT_MALFORMED;
} else {
+ /* First response indicated that not enough bytes of response were
+ * requested, so try again, this time requesting more. */
res = pt_inquiry(sg_fd, 1, page, rp, len, &resid, 1, vb);
if (res)
return res;
@@ -3525,7 +3534,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
else if (op->do_export)
export_dev_ids(rp + 4, len - 4, op->do_verbose);
else
- decode_id_vpd(rp, len, op->do_hex);
+ decode_id_vpd(rp, len, op->do_hex, op->do_verbose);
break;
case VPD_SOFTW_INF_ID:
if (! op->do_raw && (op->do_hex < 2))
@@ -3726,7 +3735,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len)
if (op->do_raw)
dStrRaw((const char *)rp, len);
else
- decode_scsi_ports_vpd(rp, len, op->do_hex);
+ decode_scsi_ports_vpd(rp, len, op->do_hex, op->do_verbose);
break;
default:
if ((pn > 0) && (pn < 0x80)) {
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 89a5c3d5..e5298a7a 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.41 20160323"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.42 20160329"; /* spc5r08 + sbc4r10 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -4846,7 +4846,7 @@ show_service_buffer_info_page(const uint8_t * resp, int len,
!!(0x8 & ucp[5]), !!(0x4 & ucp[5]), !!(0x2 & ucp[5]));
printf(" pd=%d, code_set: %s, Service buffer title:\n",
!!(0x1 & ucp[5]), sg_get_desig_code_set_str(0xf & ucp[6]));
- printf(" %*s\n", pl - 8, ucp + 8);
+ printf(" %.*s\n", pl - 8, ucp + 8);
} else if (pc < 0x8000) {
printf(" parameter_code=0x%x, Reserved, parameter in hex:\n",
pc);
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 8fd6dd7b..715d12a7 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -1,7 +1,7 @@
/*
* A utility program originally written for the Linux OS SCSI subsystem.
*
- * Copyright (C) 2000-2015 Ingo van Lil <inguin@gmx.de>
+ * Copyright (C) 2000-2016 Ingo van Lil <inguin@gmx.de>
*
* 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
@@ -15,6 +15,7 @@
#define _XOPEN_SOURCE 600 /* clear up posix_memalign() warning */
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
@@ -29,7 +30,7 @@
#include "sg_pt.h"
#include "sg_pr2serr.h"
-#define SG_RAW_VERSION "0.4.14 (2015-12-19)"
+#define SG_RAW_VERSION "0.4.15 (2016-03-31)"
#ifdef SG_LIB_WIN32
#ifndef HAVE_SYSCONF
@@ -53,6 +54,7 @@ win_pagesize(void)
static struct option long_options[] = {
{ "binary", no_argument, NULL, 'b' },
+ { "enumerate", no_argument, NULL, 'e' },
{ "help", no_argument, NULL, 'h' },
{ "infile", required_argument, NULL, 'i' },
{ "skip", required_argument, NULL, 'k' },
@@ -71,20 +73,21 @@ struct opts_t {
char *device_name;
unsigned char cdb[MAX_SCSI_CDBSZ];
int cdb_length;
- int do_datain;
+ bool do_datain;
int datain_len;
const char *datain_file;
- int datain_binary;
- int do_dataout;
+ bool datain_binary;
+ bool do_dataout;
int dataout_len;
const char *dataout_file;
off_t dataout_offset;
+ bool do_enumerate;
int timeout;
- int no_sense;
+ bool no_sense;
int readonly;
- int do_help;
- int do_verbose;
- int do_version;
+ bool do_help;
+ int verbose;
+ bool do_version;
};
@@ -106,24 +109,31 @@ usage()
pr2serr("Usage: sg_raw [OPTION]* DEVICE CDB0 CDB1 ...\n"
"\n"
"Options:\n"
- " -b, --binary Dump data in binary form, even when "
- "writing to stdout\n"
- " -h, --help Show this message and exit\n"
- " -i, --infile=IFILE Read data to send from IFILE (default: "
- "stdin)\n"
- " -k, --skip=LEN Skip the first LEN bytes when reading "
- "data to send\n"
- " -n, --nosense Don't display sense information\n"
- " -o, --outfile=OFILE Write binary data to OFILE (def: "
- "hexdump to stdout)\n"
- " -r, --request=RLEN Request up to RLEN bytes of data "
- "(data-in)\n"
- " -R, --readonly Open DEVICE read-only (default: "
+ " --binary|-b Dump data in binary form, even when "
+ "writing to\n"
+ " stdout\n"
+ " --enumerate|-e Decodes cdb name then exits; requires "
+ "DEVICE but\n"
+ " ignores it\n"
+ " --help|-h Show this message and exit\n"
+ " --infile=IFILE|-i IFILE Read data to send from IFILE "
+ "(default:\n"
+ " stdin)\n"
+ " --nosense|-n Don't display sense information\n"
+ " --outfile=OFILE|-o OFILE Write binary data to OFILE (def: "
+ "hexdump\n"
+ " to stdout)\n"
+ " --readonly|-R Open DEVICE read-only (default: "
"read-write)\n"
- " -s, --send=SLEN Send SLEN bytes of data (data-out)\n"
- " -t, --timeout=SEC Timeout in seconds (default: 20)\n"
- " -v, --verbose Increase verbosity\n"
- " -V, --version Show version information and exit\n"
+ " --request=RLEN|-r RLEN Request up to RLEN bytes of data "
+ "(data-in)\n"
+ " --send=SLEN|-s SLEN Send SLEN bytes of data (data-out)\n"
+ " --skip=KLEN|-k KLEN Skip the first KLEN bytes when "
+ "reading\n"
+ " data to send (default: 0)\n"
+ " --timeout=SEC|-t SEC Timeout in seconds (default: 20)\n"
+ " --verbose|-v Increase verbosity\n"
+ " --version|-V Show version information and exit\n"
"\n"
"Between 6 and 256 command bytes (two hex digits each) can be "
"specified\nand will be sent to DEVICE. Lengths RLEN and SLEN "
@@ -138,17 +148,20 @@ process_cl(struct opts_t * op, int argc, char *argv[])
while (1) {
int c, n;
- c = getopt_long(argc, argv, "bhi:k:no:r:Rs:t:vV", long_options, NULL);
+ c = getopt_long(argc, argv, "behi:k:no:r:Rs:t:vV", long_options, NULL);
if (c == -1)
break;
switch (c) {
case 'b':
- op->datain_binary = 1;
+ op->datain_binary = true;
+ break;
+ case 'e':
+ op->do_enumerate = true;
break;
case 'h':
case '?':
- op->do_help = 1;
+ op->do_help = true;
return 0;
case 'i':
if (op->dataout_file) {
@@ -166,7 +179,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
op->dataout_offset = n;
break;
case 'n':
- op->no_sense = 1;
+ op->no_sense = true;
break;
case 'o':
if (op->datain_file) {
@@ -176,7 +189,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
op->datain_file = optarg;
break;
case 'r':
- op->do_datain = 1;
+ op->do_datain = true;
n = sg_get_num(optarg);
if (n < 0 || n > MAX_SCSI_DXLEN) {
pr2serr("Invalid argument to '--request'\n");
@@ -188,7 +201,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
++op->readonly;
break;
case 's':
- op->do_dataout = 1;
+ op->do_dataout = true;
n = sg_get_num(optarg);
if (n < 0 || n > MAX_SCSI_DXLEN) {
pr2serr("Invalid argument to '--send'\n");
@@ -205,10 +218,10 @@ process_cl(struct opts_t * op, int argc, char *argv[])
op->timeout = n;
break;
case 'v':
- ++op->do_verbose;
+ ++op->verbose;
break;
case 'V':
- op->do_version = 1;
+ op->do_version = true;
return 0;
default:
return SG_LIB_SYNTAX_ERROR;
@@ -243,7 +256,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
pr2serr("CDB too short (min. %d bytes)\n", MIN_SCSI_CDBSZ);
return SG_LIB_SYNTAX_ERROR;
}
- if (op->do_verbose > 1) {
+ if (op->do_enumerate || (op->verbose > 1)) {
int sa;
char b[80];
@@ -289,7 +302,7 @@ my_memalign(int length, unsigned char ** wrkBuffp, const struct opts_t * op)
if (wrkBuffp)
*wrkBuffp = (unsigned char *)wp;
res = (unsigned char *)wp;
- if (op->do_verbose > 3)
+ if (op->verbose > 3)
pr2serr("%s: posix, len=%d, wrkBuffp=%p, psz=%d, rp=%p\n",
__func__, length, *wrkBuffp, (int)psz, res);
return res;
@@ -307,7 +320,7 @@ my_memalign(int length, unsigned char ** wrkBuffp, const struct opts_t * op)
*wrkBuffp = wrkBuff;
res = (unsigned char *)(((uintptr_t)wrkBuff + psz - 1) &
(~(psz - 1)));
- if (op->do_verbose > 3)
+ if (op->verbose > 3)
pr2serr("%s: hack, len=%d, wrkBuffp=%p, psz=%d, rp=%p\n",
__func__, length, *wrkBuffp, (int)psz, res);
return res;
@@ -465,10 +478,11 @@ main(int argc, char *argv[])
} else if (op->do_version) {
version();
goto done;
- }
+ } else if (op->do_enumerate)
+ goto done;
sg_fd = scsi_pt_open_device(op->device_name, op->readonly,
- op->do_verbose);
+ op->verbose);
if (sg_fd < 0) {
pr2serr("%s: %s\n", op->device_name, safe_strerror(-sg_fd));
ret = SG_LIB_FILE_ERROR;
@@ -481,19 +495,19 @@ main(int argc, char *argv[])
ret = SG_LIB_CAT_OTHER;
goto done;
}
- if (op->do_verbose) {
+ if (op->verbose) {
pr2serr(" cdb to send: ");
for (k = 0; k < op->cdb_length; ++k)
pr2serr("%02x ", op->cdb[k]);
pr2serr("\n");
- if (op->do_verbose > 1) {
+ if (op->verbose > 1) {
sg_get_command_name(op->cdb, 0, sizeof(b) - 1, b);
b[sizeof(b) - 1] = '\0';
pr2serr(" Command name: %s\n", b);
}
}
set_scsi_pt_cdb(ptvp, op->cdb, op->cdb_length);
- if (op->do_verbose > 2)
+ if (op->verbose > 2)
pr2serr("sense_buffer=%p, length=%d\n", sense_buffer,
(int)sizeof(sense_buffer));
set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer));
@@ -504,7 +518,7 @@ main(int argc, char *argv[])
ret = SG_LIB_CAT_OTHER;
goto done;
}
- if (op->do_verbose > 2)
+ if (op->verbose > 2)
pr2serr("dxfer_buffer_out=%p, length=%d\n", dxfer_buffer_out,
op->dataout_len);
set_scsi_pt_data_out(ptvp, dxfer_buffer_out, op->dataout_len);
@@ -516,13 +530,13 @@ main(int argc, char *argv[])
ret = SG_LIB_CAT_OTHER;
goto done;
}
- if (op->do_verbose > 2)
+ if (op->verbose > 2)
pr2serr("dxfer_buffer_in=%p, length=%d\n", dxfer_buffer_in,
op->datain_len);
set_scsi_pt_data_in(ptvp, dxfer_buffer_in, op->datain_len);
}
- ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->do_verbose);
+ ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->verbose);
if (ret > 0) {
if (SCSI_PT_DO_BAD_PARAMS == ret) {
pr2serr("do_scsi_pt: bad pass through setup\n");
@@ -577,7 +591,7 @@ main(int argc, char *argv[])
"Information\n");
else {
pr2serr("Sense Information:\n");
- sg_print_sense(NULL, sense_buffer, slen, (op->do_verbose > 0));
+ sg_print_sense(NULL, sense_buffer, slen, (op->verbose > 0));
pr2serr("\n");
}
}
@@ -616,8 +630,8 @@ main(int argc, char *argv[])
}
done:
- if (op->do_verbose) {
- sg_get_category_sense_str(ret, sizeof(b), b, op->do_verbose - 1);
+ if (op->verbose) {
+ sg_get_category_sense_str(ret, sizeof(b), b, op->verbose - 1);
pr2serr("%s\n", b);
}
if (wrkBuf)
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 3a3cb68b..25df66a8 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -37,7 +37,7 @@
*/
-static const char * version_str = "1.15 20160312"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.16 20160327"; /* spc5r08 + sbc4r10 */
/* These structures are duplicates of those of the same name in
@@ -267,7 +267,7 @@ usage()
"also\n"
" given, FN is in binary (else FN is in "
"hex)\n"
- " --vendor=VP | -M VP vendor/product abbreviation [or "
+ " --vendor=VP|-M VP vendor/product abbreviation [or "
"number]\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
@@ -1122,7 +1122,7 @@ skip_1st_iter:
case 7: /* MD5 logical unit identifier */
break;
case 8: /* SCSI name string */
- if (3 != c_set) {
+ if (c_set < 2) { /* quietly accept ASCII for UTF-8 */
pr2serr(" << expected UTF-8 code_set>>\n");
dStrHexErr((const char *)ip, i_len, 0);
break;
@@ -1140,7 +1140,7 @@ skip_1st_iter:
* Seems to depend on the locale. Looks ok here with my
* locale setting: en_AU.UTF-8
*/
- printf(" %s\n", (const char *)ip);
+ printf(" %.*s\n", i_len, (const char *)ip);
break;
case 9: /* Protocol specific port identifier */
break;
@@ -1436,7 +1436,7 @@ decode_designation_descriptor(const unsigned char * ip, int i_len,
* Seems to depend on the locale. Looks ok here with my
* locale setting: en_AU.UTF-8
*/
- printf(" %s\n", (const char *)ip);
+ printf(" %.*s\n", i_len, (const char *)ip);
break;
case 9: /* Protocol specific port identifier */
/* added in spc4r36, PIV must be set, proto_id indicates */
@@ -2606,7 +2606,7 @@ decode_block_lb_prov_vpd(unsigned char * b, int len, const struct opts_t * op)
printf(" Write same (10) with unmap bit supported (LBWS10): %d\n",
!!(0x20 & b[5]));
printf(" Logical block provisioning read zeros (LBPRZ): %d\n",
- (0x7 & (b[5] >> 2)));
+ (0x7 & (b[5] >> 2))); /* expanded from 1 to 3 bits in sbc4r07 */
printf(" Anchored LBAs supported (ANC_SUP): %d\n", !!(0x2 & b[5]));
dp = !!(b[5] & 0x1);
printf(" Threshold exponent: %d\n", b[4]);