aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2017-10-22 17:32:39 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2017-10-22 17:32:39 +0000
commit9a9577a3b7f0b0c82ad0e77b9f16b3afa238322c (patch)
tree9d756acc6206a1dbc5c0777efc8ce6f6a3b9366b
parent23712b6e6d5ee067cf7a740ef10e4dbea90dd179 (diff)
downloadsg3_utils-9a9577a3b7f0b0c82ad0e77b9f16b3afa238322c.tar.gz
sg_lib: add sg_ll_log_sense_v2(), sg_ll_mode_sense10_v2() and sg_ll_receive_diag_v2(); documentation cleanup; sg_ses: filter join output on dpage element presence (AES dpage)
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@722 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog10
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg3_utils.819
-rw-r--r--doc/sg_compare_and_write.85
-rw-r--r--doc/sg_inq.86
-rw-r--r--doc/sg_logs.86
-rw-r--r--doc/sg_modes.86
-rw-r--r--doc/sg_opcodes.86
-rw-r--r--doc/sg_rbuf.88
-rw-r--r--doc/sg_readcap.86
-rw-r--r--doc/sg_reassign.812
-rw-r--r--doc/sg_reset.85
-rw-r--r--doc/sg_sat_identify.88
-rw-r--r--doc/sg_senddiag.86
-rw-r--r--doc/sg_ses.819
-rw-r--r--doc/sg_start.86
-rw-r--r--doc/sg_turs.86
-rw-r--r--doc/sg_xcopy.83
-rw-r--r--doc/sginfo.82
-rw-r--r--include/sg_cmds_basic.h16
-rw-r--r--include/sg_cmds_extra.h12
-rw-r--r--include/sg_lib.h2
-rw-r--r--lib/sg_cmds_basic.c2
-rw-r--r--lib/sg_cmds_basic2.c129
-rw-r--r--lib/sg_cmds_extra.c28
-rw-r--r--lib/sg_pt_linux.c7
-rwxr-xr-xscripts/scsi_mandat10
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_compare_and_write.c8
-rw-r--r--src/sg_dd.c8
-rw-r--r--src/sg_format.c44
-rw-r--r--src/sg_inq.c4
-rw-r--r--src/sg_logs.c243
-rw-r--r--src/sg_map26.c7
-rw-r--r--src/sg_modes.c111
-rw-r--r--src/sg_opcodes.c2
-rw-r--r--src/sg_rbuf.c2
-rw-r--r--src/sg_rdac.c42
-rw-r--r--src/sg_read.c4
-rw-r--r--src/sg_readcap.c2
-rw-r--r--src/sg_reset.c6
-rw-r--r--src/sg_sat_phy_event.c1
-rw-r--r--src/sg_senddiag.c40
-rw-r--r--src/sg_ses.c500
-rw-r--r--src/sg_start.c2
-rw-r--r--src/sg_stpg.c4
-rw-r--r--src/sg_test_rwbuf.c18
-rw-r--r--src/sg_turs.c2
-rw-r--r--src/sg_xcopy.c36
-rw-r--r--src/sginfo.c4
-rw-r--r--src/sgm_dd.c8
-rw-r--r--src/sgp_dd.c4
52 files changed, 902 insertions, 549 deletions
diff --git a/ChangeLog b/ChangeLog
index efa5f7cb..e91bc326 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 [20171012] [svn: r721]
+Changelog for sg3_utils-1.43 [20171022] [svn: r722]
- sg_bg_ctl: new Background control command (sbc4r08)
- sg_write_atomic: new 16 and 32 byte cdbs (sbc4r04)
- also can issue plain WRITE(16 or 32)
@@ -20,6 +20,8 @@ Changelog for sg3_utils-1.43 [20171012] [svn: r721]
belonging to element type IIA
- add 'offset_temp' and 'rqst_override' to temperature
sensor element type
+ - interpret '--join --page=aes' to only display join
+ rows that have a corresponding AES dpage element
- sync to ses4r01
- sg_luns: resync with drafts (sam6r02+spc5r10)
- remove undocumented test "W" format
@@ -64,11 +66,16 @@ Changelog for sg3_utils-1.43 [20171012] [svn: r721]
- decode response's RTP and two more provisioning
statuses and the additional status (sbc4r12)
- decode completion condition (sbc4r14)
+ - manpages and usage messages: corrections from
+ Gris Ge via github
- group_number: is 6 bit field allowing 0 to 63,
code in several utilities limited it to 31, fix
- convert many two valued 'int's to bool
- sg_lib: add SSC maintenance in/out sa names
- add sg_ll_inquiry_v2()
+ - add sg_ll_log_sense_v2()
+ - add sg_ll_mode_sense10_v2()
+ - add sg_ll_receive_diag_v2()
- add sg_ll_write_buffer_v2()
- add sg_get_llnum_nomult()
- add sg_ll_get_lba_status16()
@@ -92,6 +99,7 @@ Changelog for sg3_utils-1.43 [20171012] [svn: r721]
- 55-scsi-sg3_id.rules: fixes from Suse
- https://github.com/hreinecke/sg3_utils
branch sles15 synced 20170914
+ - gcc 7.2 cleanups (sysmacros.h etc)
- clang --analyze static checker clean ups
- shellcheck cleanup on scripts
- automake: add AM_PROG_AR to configure.ac
diff --git a/debian/changelog b/debian/changelog
index a60a3512..6b7189c3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.43-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Wed, 11 Oct 2017 23:00:00 -0400
+ -- Douglas Gilbert <dgilbert@interlog.com> Sun, 22 Oct 2017 12:00:00 -0400
sg3-utils (1.42-0.1) unstable; urgency=low
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index f03cb459..4052cbba 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -61,20 +61,23 @@ and '\-\-lba=2a6h' are equivalent). Note that with getopt_long(), short form
options can be elided, for example: '\-all' is equivalent to '\-a \-l \-l'.
The \fIDEVICE\fR argument may appear after, between or prior to any options.
.PP
-The older utilities, such as sg_inq, had individual command line processing
-code typically based on a single "\-" followed by one or more characters. If
-an argument is needed then it follows a "=" (e.g. '\-p=1f' in sg_modes with
-its older interface). Various options can be elided as long as it is not
-ambiguous (e.g. '\-vv' to increase the verbosity).
+The older utilities, including as sg_inq, sg_logs, sg_modes, sg_opcode,
+sg_rbuff, sg_readcap, sg_senddiag, sg_start and sg_turs had individual
+command line processing code typically based on a single "\-" followed by one
+or more characters. If an argument is needed then it follows a "=" (
+e.g. '\-p=1f' in sg_modes with its older interface). Various options can be
+elided as long as it is not ambiguous (e.g. '\-vv' to increase the verbosity).
.PP
Over time the command line interface of these older utilities became messy
and overloaded with options. So in sg3_utils version 1.23 the command line
interface of these older utilities was altered to have both a cleaner
getopt_long() interface and their older interface for backward compatibility.
By default these older utilities use their getopt_long() based interface.
-That can be overridden by defining the SG3_UTILS_OLD_OPTS environment
-variable or using '\-O' or '\-\-old' as the first command line option. The
-man pages of the older utilities documents the details.
+The getopt_long() is a GNU extension (i.e. not yet POSIX certified) but
+more recent command line utilities tend to use it. That can be overridden
+by defining the SG3_UTILS_OLD_OPTS environment variable or using '\-O'
+or '\-\-old' as the first command line option. The man pages of the older
+utilities documents the details.
.PP
Several sg3_utils utilities are based on the Unix dd command (e.g. sg_dd)
and permit copying data at the level of SCSI READ and WRITE commands. sg_dd
diff --git a/doc/sg_compare_and_write.8 b/doc/sg_compare_and_write.8
index 41b8a90c..e476153f 100644
--- a/doc/sg_compare_and_write.8
+++ b/doc/sg_compare_and_write.8
@@ -1,4 +1,4 @@
-.TH "COMPARE AND WRITE" "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
+.TH "COMPARE AND WRITE" "8" "October 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_compare_and_write \- send the SCSI COMPARE AND WRITE command
.SH SYNOPSIS
@@ -80,6 +80,9 @@ compare and write buffers (when the \fI\-\-inw=WF\fR option is not given) or
just the compare buffer (when the \fI\-\-inw=WF\fR option is given). If
\fIIF\fR is '\-' then stdin (e.g. a pipe) is read.
.TP
+\fB\-C\fR, \fB\-\-inc\fR=\fIIF\fR
+The same as the \fB\-\-in\fR option.
+.TP
\fB\-D\fR, \fB\-\-inw\fR=\fIWF\fR
read data (binary) from file named \fIWF\fR. This will the write buffer
that will become the second half of the data\-out buffer sent to the
diff --git a/doc/sg_inq.8 b/doc/sg_inq.8
index 5bb03a69..8a4c84bd 100644
--- a/doc/sg_inq.8
+++ b/doc/sg_inq.8
@@ -170,7 +170,7 @@ been added for compatibility with the sg_vpd, sg_modes and sg_logs
utilities.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-page\fR=\fIPG\fR
the \fIPG\fR argument can be either a number of an abbreviation for a VPD
@@ -360,8 +360,8 @@ to '\-\-page=mna' in the OPTIONS section.
decodes the Mode page policy VPD page [0x87]. Equivalent to '\-\-page=mpp'
in the OPTIONS section.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-o\fR=\fIOPCODE_PG\fR
used in conjunction with the \fI\-e\fR or \fI\-c\fR option. If neither given
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index fe2a6cee..72212829 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -188,7 +188,7 @@ not be able to differentiate between some log pages that are device
dependent. It will assume a PDT of 0 (i.e. a disk).
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-page\fR=\fIPG\fR
log page name/number to access. \fIPG\fR is either an acronym, a page number,
@@ -407,8 +407,8 @@ Equivalent to \fI\-\-vendor=VP\fR in the main description.
\fB\-n\fR
Equivalent to \fI\-\-name\fR in the main description.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB\-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-p\fR=\fIPG\fR
log page code to access. \fIPG\fR is either an acronym, a page number, or
diff --git a/doc/sg_modes.8 b/doc/sg_modes.8
index 88def72f..257b6e49 100644
--- a/doc/sg_modes.8
+++ b/doc/sg_modes.8
@@ -133,7 +133,7 @@ and no greater than 65535 for MODE SENSE (10) and not greater than 255
for MODE SENSE (6).
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-page\fR=\fIPG\fR
page code to fetch. The \fIPG\fR is assumed to be a decimal value unless
@@ -241,8 +241,8 @@ see \fB\-\-list\fR in the main description.
\fB\-L\fR
see \fB\-\-llbaa\fR in the main description.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-m\fR=\fILEN\fR
see \fB\-\-maxlen\fR=\fILEN\fR in the main description.
diff --git a/doc/sg_opcodes.8 b/doc/sg_opcodes.8
index 49db0723..f931418c 100644
--- a/doc/sg_opcodes.8
+++ b/doc/sg_opcodes.8
@@ -94,7 +94,7 @@ command response on stdout. If this option (or the \fI\-\-raw\fR option)
is given then that summary is not printed on stdout.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-o\fR, \fB\-\-opcode\fR=\fIOP\fR
the \fIDEVICE\fR will be queried for the given operation code (i.e. the
@@ -195,8 +195,8 @@ see the \fI\-\-mask\fR option above.
\fB\-n\fR
don't print a summary of the SCSI INQUIRY response on stdout.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-o\fR=\fIOP\fR
the \fIDEVICE\fR will be queried for the given operation code (i.e.
diff --git a/doc/sg_rbuf.8 b/doc/sg_rbuf.8
index f59d3b68..078d8b7d 100644
--- a/doc/sg_rbuf.8
+++ b/doc/sg_rbuf.8
@@ -4,7 +4,7 @@ sg_rbuf \- reads data using SCSI READ BUFFER command
.SH SYNOPSIS
.B sg_rbuf
[\fI\-\-buffer=EACH\fR] [\fI\-\-dio\fR] [\fI\-\-help\fR] [\fI\-\-mmap\fR]
-[\fI\-\-quick\fR] [\fI\-\-size=OVERALL\fR] [\fI\-\-test\fR]
+[\fI\-\-quick\fR] [\fI\-\-size=OVERALL\fR]
[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_rbuf
@@ -58,7 +58,7 @@ sg driver will attempt to configure the DMA from the SCSI adapter to transfer
directly into user memory. This will eliminate the copy via kernel buffers.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-q\fR, \fB\-\-quick\fR
only transfer the data into kernel buffers (typically by DMA from the SCSI
@@ -149,8 +149,8 @@ main description.
use memory mapped IO if available. Equivalent to the \fI\-\-mmap\fR option
in the main description.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-q\fR
only transfer the data into kernel buffers (typically by DMA from
diff --git a/doc/sg_readcap.8 b/doc/sg_readcap.8
index d94f7034..9ebb25d9 100644
--- a/doc/sg_readcap.8
+++ b/doc/sg_readcap.8
@@ -81,7 +81,7 @@ is used on a device whose size is too large then a last block address
of 0xffffffff is returned (if the device complies with SBC\-2 or later).
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-pmi\fR
partial medium indicator: for finding the next block address prior to
@@ -150,8 +150,8 @@ used in conjunction with \fI\-pmi\fR option. This variant of READ CAPACITY
will yield the last block address after \fILBA\fR prior to a delay.
Equivalent to \fI\-\-lba=LBA\fR in the main description.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-pmi\fR
partial medium indicator: for finding the next block address prior to
diff --git a/doc/sg_reassign.8 b/doc/sg_reassign.8
index 9ef07e61..ecacc7fe 100644
--- a/doc/sg_reassign.8
+++ b/doc/sg_reassign.8
@@ -1,10 +1,10 @@
-.TH SG_REASSIGN "8" "September 2017" "sg3_utils\-1.38" SG3_UTILS
+.TH SG_REASSIGN "8" "October 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_reassign \- send SCSI REASSIGN BLOCKS command
.SH SYNOPSIS
.B sg_reassign
[\fI\-\-address=A,A...\fR] [\fI\-\-dummy\fR] [\fI\-\-eight=0|1\fR]
-[\fI\-\-grown\fR] [\fI\-\-help\fR] [\fI\-\-longlist=0|1\fR]
+[\fI\-\-grown\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-longlist=0|1\fR]
[\fI\-\-primary\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
@@ -71,6 +71,10 @@ and the grown defect list. This list is sometimes referred to as the GLIST.
\fB\-h\fR, \fB\-\-help\fR
output the usage message then exit.
.TP
+\fB\-H\fR, \fB\-\-hex\fR
+print response in hex (for \fB\-g\fR, \fB\-\-grown\fR, \fB\-p\fR
+or \fB\-\-primary\fR).
+.TP
\fB\-l\fR, \fB\-\-longlist\fR=0 | 1
sets the REASSIGN BLOCKS cdb field of the same name to the given value.
Only 1000 addresses are permitted so there should be no need to specify
@@ -100,8 +104,8 @@ is reported on not (PER=1 implies do report). Irrespective of the ARRE, AWRE
or PER field settings, the error counter log pages reflect any
errors (recovered or otherwise). Whenever a block is reassigned, a new entry
is added in the "grown" defect list. Apart from doing selftests (see
-sg_senddiag or smartmontools) regularly, monitoring the grown defect list of a disk is
-a reasonable metric of its health. If the grown list starts growing
+sg_senddiag or smartmontools) regularly, monitoring the grown defect list of
+a disk is a reasonable metric of its health. If the grown list starts growing
quickly that is an ominous sign. The best grown defect lists are empty
ones. The number of elements in the grown defect list can be viewed with
the \fI\-\-grown\fR option. The contents of the grown defect list can be
diff --git a/doc/sg_reset.8 b/doc/sg_reset.8
index 39401001..0444a7f5 100644
--- a/doc/sg_reset.8
+++ b/doc/sg_reset.8
@@ -42,7 +42,7 @@ target on the \fIDEVICE\fR path.
attempt a SCSI device reset. This would typically involve sending a LOGICAL
UNIT RESET task management function to \fIDEVICE\fR.
.TP
-\fB\-h\fR, \fB\-\-help\fR
+\fB\-z\fR, \fB\-\-help\fR
print the usage message then exit.
.TP
\fB\-H\fR, \fB\-\-host\fR
@@ -57,6 +57,9 @@ reset (\fI\-\-bus\fR) fails then it will escalate to a host reset. With this
option only the requested reset is attempted. An alternate option name of
\fI\-\-no-escalate\fR is also accepted.
.TP
+\fB\-\-no\-escalate\fR
+The same as \fB\-N\fR, \fB\-\-no\-esc\fR.
+.TP
\fB\-t\fR, \fB\-\-target\fR
attempt a SCSI target reset. A SCSI target contains one or more LUs. This
would typically involve sending a I_T NEXUS RESET task management function
diff --git a/doc/sg_sat_identify.8 b/doc/sg_sat_identify.8
index 2459e2cb..db05d0f2 100644
--- a/doc/sg_sat_identify.8
+++ b/doc/sg_sat_identify.8
@@ -1,11 +1,11 @@
-.TH SG_SAT_IDENTIFY "8" "May 2016" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SAT_IDENTIFY "8" "October 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_sat_identify \- send ATA IDENTIFY DEVICE command via SCSI to ATA
Translation (SAT) layer
.SH SYNOPSIS
.B sg_sat_identify
[\fI\-\-ck_cond\fR] [\fI\-\-extend\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR]
-[\fI\-\-indent\fR] [\fI\-\-len=CLEN\fR] [\fI\-\-packet\fR] [\fI\-\-raw\fR]
+[\fI\-\-ident\fR] [\fI\-\-len=CLEN\fR] [\fI\-\-packet\fR] [\fI\-\-raw\fR]
[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
@@ -56,7 +56,7 @@ a header. When given thrice (i.e. '\-HHH') the output is in hex, grouped in
process. '\-HHHH' simply outputs hex data bytes, space separated, 16 per
line.
.TP
-\fB\-i\fR, \fB\-\-indent\fR
+\fB\-i\fR, \fB\-\-ident\fR
outputs the World Wide Name (WWN) of the device. This should be a NAA\-5
64 bit number. It is output in hex prefixed with "0x". If not available
then "0x0000000000000000" is output. The equivalent for a SCSI disk (i.e. its
@@ -110,7 +110,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2006\-2016 Douglas Gilbert
+Copyright \(co 2006\-2017 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_senddiag.8 b/doc/sg_senddiag.8
index d7145172..3877bfa3 100644
--- a/doc/sg_senddiag.8
+++ b/doc/sg_senddiag.8
@@ -76,7 +76,7 @@ there will be data sent or received by the command. The default value
is 4096 bytes. \fILEN\fR cannot exceed 65535 or 0xffff in hexadecimal.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-P\fR, \fB\-\-page\fR=\fIPG\fR
where \fIPG\fR is the RECEIVE DIAGNOSTIC RESULTS command page code field.
@@ -218,8 +218,8 @@ DIAGNOSTIC RESULTS command. When used in the absence of a \fIDEVICE\fR
argument then a list of diagnostic page names and their numbers, known
by this utility, are listed.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-pf\fR
set Page Format (PF) bit. By default it is clear (i.e. 0) unless
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index aeef8f66..e596ecd8 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "September 2017" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SES "8" "October 2017" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -219,11 +219,16 @@ used with an indexing option and/or \fI\-\-join\fR options.
group elements from the Element Descriptor, Enclosure Status and Additional
Element Status pages. If this option is given twice then elements from the
Threshold In page are also grouped. The order is dictated by the Configuration
-page. All elements are output unless one of the indexing options is given,
-in which case only the matching element and its associated fields are output.
-The \fI\-\-filter\fR option can be added to reduce the amount of output
-generated by this option. See the INDEXES and DESCRIPTOR NAME, DEVICE SLOT
-NUMBER AND SAS ADDRESS sections below.
+page.
+.PP
+There can be a bewildering amount of information in the "join" output. The
+default is to output everything. Several additional options are provided to
+cut down the amount displayed. If the indexing options is given, only the
+matching elements and their associated fields are output. The \fI\-\-filter\fR
+option (see its description) can be added to reduce the amount of output.
+Also "\-\-page=aes" (or "\-p 0xa") can be added to suppress the output of
+rows that don't have a "aes" page component. See the INDEXES and DESCRIPTOR
+NAME, DEVICE SLOT NUMBER AND SAS ADDRESS sections below.
.TP
\fB\-l\fR, \fB\-\-list\fR
This option is equivalent to \fI\-\-enumerate\fR. See that option.
@@ -310,7 +315,7 @@ command. In the absence of other options that imply modifying a page (e.g.
increase the level of verbosity. For example when this option is given four
times (in which case the short form is more convenient: '\-vvvv') then if
the internal join array has been generated then it is output to stderr in
-form suitable for debugging.
+a form suitable for debugging.
.TP
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit.
diff --git a/doc/sg_start.8 b/doc/sg_start.8
index 904e4d9d..d22a0171 100644
--- a/doc/sg_start.8
+++ b/doc/sg_start.8
@@ -92,7 +92,7 @@ a variant of this utility that limits access to the media. Using the
media. This 'noflush' field in the cdb was added after sbc3r13.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-pc\fR=\fIPC\fR
where \fIPC\fR is the 'power conditions' value. 0 to 15 (inclusive) are valid.
@@ -222,8 +222,8 @@ or "stop" operation is indicated does a stop and eject. [Note that the last
action differs from the new interface in which the option of this name
defaults to load and start.]
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-\-mod\fR=\fIPC_MOD\fR
where \fIPC_MOD\fR is the 'power condition modifier' value. 0 to 15 (inclusive)
diff --git a/doc/sg_turs.8 b/doc/sg_turs.8
index a51f0abb..d37f8fd4 100644
--- a/doc/sg_turs.8
+++ b/doc/sg_turs.8
@@ -40,7 +40,7 @@ same as \fI\-\-number=NUM\fR. Added for compatibility with sg_requests
which has taken over the role of polling the progress indication.
.TP
\fB\-O\fR, \fB\-\-old\fR
-switch to older style options.
+Switch to older style options. Please use as first option.
.TP
\fB\-p\fR, \fB\-\-progress\fR
show progress indication (a percentage) if available. If \fI\-\-number=NUM\fR
@@ -96,8 +96,8 @@ force the use of these older command line options.
performs TEST UNIT READY \fINUM\fR times. If not given defaults to 1.
Equivalent to \fI\-\-number=NUM\fR in the main description.
.TP
-\fB\-N\fR
-switch to the newer style options.
+\fB-N\fR, \fB\-\-new\fR
+Switch to the newer style options.
.TP
\fB\-p\fR
show progress indication (a percentage) if available.
diff --git a/doc/sg_xcopy.8 b/doc/sg_xcopy.8
index c67ff35c..978b0056 100644
--- a/doc/sg_xcopy.8
+++ b/doc/sg_xcopy.8
@@ -81,6 +81,9 @@ refers to the source (\fIdc=0\fR) or the target (\fIdc=1\fR) descriptor.
\fBconv\fR=\fBCONV\fR
all \fBCONV\fR arguments are ignored.
.TP
+\fBapp\fR=\fBAPPEND\fR
+all \fBAPPEND\fR arguments are ignored.
+.TP
\fBcount\fR=\fICOUNT\fR
copy \fICOUNT\fR blocks from \fIIFILE\fR to \fIOFILE\fR. Default is the
minimum (\fIIFILE\fR if \fIdc=0\fR or \fIOFILE\fR if \fIdc=1\fR)
diff --git a/doc/sginfo.8 b/doc/sginfo.8
index 77448a0a..bb913b98 100644
--- a/doc/sginfo.8
+++ b/doc/sginfo.8
@@ -206,7 +206,7 @@ The following are advanced options, not generally suited for most users:
Display output values in a list. Make them suitable for editing and
being given back to the '\-R' (replace command).
.TP
-\fB\\-R\fR
+\fB\-R\fR
Replace parameters \- best used with \-X (expert use only)
.SH CHANGING MODE PAGE PARAMETERS
Firstly you should know what you are doing before changing existing
diff --git a/include/sg_cmds_basic.h b/include/sg_cmds_basic.h
index 000ff7f3..c7c7ae66 100644
--- a/include/sg_cmds_basic.h
+++ b/include/sg_cmds_basic.h
@@ -70,6 +70,13 @@ int sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
int subpg_code, int paramp, unsigned char * resp,
int mx_resp_len, bool noisy, int verbose);
+/* Same as sg_ll_log_sense() apart from timeout_secs and residp. See
+ * sg_ll_inquiry_v2() for their description */
+int sg_ll_log_sense_v2(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
+ int subpg_code, int paramp, unsigned char * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose);
+
/* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> invalid opcode, SG_LIB_CAT_ILLEGAL_REQ ->
* bad field in cdb, * SG_LIB_CAT_NOT_READY -> device not ready,
@@ -104,6 +111,13 @@ int sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
int sub_pg_code, void * resp, int mx_resp_len,
bool noisy, int verbose);
+/* Same as sg_ll_mode_sense10() apart from timeout_secs and residp. See
+ * sg_ll_inquiry_v2() for their description */
+int sg_ll_mode_sense10_v2(int sg_fd, bool llbaa, bool dbd, int pc,
+ int pg_code, int sub_pg_code, void * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose);
+
/* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command (SPC-3)
* prevent==0 allows removal, prevent==1 prevents removal ...
* Return of 0 -> success,
@@ -235,7 +249,7 @@ int sg_mode_page_offset(const unsigned char * resp, int resp_len,
int sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code,
int sub_pg_code, bool dbd, bool flexible,
int mx_mpage_len, int * success_mask,
- void * pcontrol_arr[], int * reported_len,
+ void * pcontrol_arr[], int * reported_lenp,
int verbose);
/* Returns file descriptor >= 0 if successful. If error in Unix returns
diff --git a/include/sg_cmds_extra.h b/include/sg_cmds_extra.h
index ff46335b..9869ae9a 100644
--- a/include/sg_cmds_extra.h
+++ b/include/sg_cmds_extra.h
@@ -164,6 +164,18 @@ int sg_ll_reassign_blocks(int sg_fd, bool longlba, bool longlist,
int sg_ll_receive_diag(int sg_fd, bool pcv, int pg_code, void * resp,
int mx_resp_len, bool noisy, int verbose);
+/* Same as sg_ll_receive_diag() but with added timeout_secs and residp
+ * arguments. Adds the ability to set the command abort timeout
+ * and the ability to report the residual count. If timeout_secs is zero
+ * or less the the default command abort timeout (60 seconds) is used.
+ * If residp is non-NULL then the residual value is written where residp
+ * points. A residual value of 0 implies mx_resp_len bytes have be written
+ * where resp points. If the residual value equals mx_resp_len then no
+ * bytes have been written. */
+int sg_ll_receive_diag_v2(int sg_fd, bool pcv, int pg_code, void * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose);
+
/* Invokes a SCSI REPORT IDENTIFYING INFORMATION command. This command was
* called REPORT DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Report identifying information not supported,
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 5b7c9352..0c74eb5d 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -357,6 +357,8 @@ void sg_print_sense(const char * leadin, const unsigned char * sense_buffer,
#define SG_LIB_CAT_TASK_ABORTED 29 /* SCSI status, this command aborted by? */
#define SG_LIB_CAT_PROTECTION 40 /* subset of aborted command (for PI, DIF) */
/* [sk,asc,ascq: 0xb,0x10,*] */
+#define SG_LIB_WILD_RESID 49 /* Residual value for data-in transfer of a */
+ /* SCSI command is nonsensical */
#define SG_LIB_CAT_MALFORMED 97 /* Response to SCSI command malformed */
#define SG_LIB_CAT_SENSE 98 /* Something else is in the sense buffer */
#define SG_LIB_CAT_OTHER 99 /* Some other error/warning has occurred */
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 44c3fa45..4fa8863e 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -514,6 +514,8 @@ sg_ll_inquiry_v2(int sg_fd, bool evpd, int pg_op, void * resp,
ptvp = construct_scsi_pt_obj();
if (NULL == ptvp) {
pr2ws("%s: out of memory\n", __func__);
+ if (residp)
+ *residp = 0;
return -1;
}
set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
diff --git a/lib/sg_cmds_basic2.c b/lib/sg_cmds_basic2.c
index 08b1e2c2..640b76ba 100644
--- a/lib/sg_cmds_basic2.c
+++ b/lib/sg_cmds_basic2.c
@@ -340,12 +340,30 @@ sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
int sub_pg_code, void * resp, int mx_resp_len,
bool noisy, int verbose)
{
- static const char * const cdb_name_s = "mode sense(10)";
+ return sg_ll_mode_sense10_v2(sg_fd, llbaa, dbd, pc, pg_code, sub_pg_code,
+ resp, mx_resp_len, 0, NULL, noisy, verbose);
+}
+
+/* Invokes a SCSI MODE SENSE (10) command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * Adds the ability to set the command abort timeout
+ * and the ability to report the residual count. If timeout_secs is zero
+ * or less the the default command abort timeout (60 seconds) is used.
+ * If residp is non-NULL then the residual value is written where residp
+ * points. A residual value of 0 implies mx_resp_len bytes have be written
+ * where resp points. If the residual value equals mx_resp_len then no
+ * bytes have been written. */
+int
+sg_ll_mode_sense10_v2(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
+ int sub_pg_code, void * resp, int mx_resp_len,
+ int timeout_secs, int * residp, bool noisy, int verbose)
+{
int res, ret, k, sense_cat, resid;
+ static const char * const cdb_name_s = "mode sense(10)";
+ struct sg_pt_base * ptvp;
unsigned char modes_cdb[MODE_SENSE10_CMDLEN] =
{MODE_SENSE10_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- struct sg_pt_base * ptvp;
modes_cdb[1] = (unsigned char)((dbd ? 0x8 : 0) | (llbaa ? 0x10 : 0));
modes_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
@@ -353,7 +371,7 @@ sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
sg_put_unaligned_be16((int16_t)mx_resp_len, modes_cdb + 7);
if (mx_resp_len > 0xffff) {
pr2ws("mx_resp_len too big\n");
- return -1;
+ goto gen_err;
}
if (verbose) {
pr2ws(" %s cdb: ", cdb_name_s);
@@ -361,15 +379,20 @@ sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
pr2ws("%02x ", modes_cdb[k]);
pr2ws("\n");
}
+ if (timeout_secs <= 0)
+ timeout_secs = DEF_PT_TIMEOUT;
+
if (NULL == ((ptvp = create_pt_obj(cdb_name_s))))
- return -1;
+ goto gen_err;
set_scsi_pt_cdb(ptvp, modes_cdb, sizeof(modes_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b,
noisy, verbose, &sense_cat);
resid = get_scsi_pt_resid(ptvp);
+ if (residp)
+ *residp = resid;
destruct_scsi_pt_obj(ptvp);
if (-1 == ret)
;
@@ -407,6 +430,10 @@ sg_ll_mode_sense10(int sg_fd, bool llbaa, bool dbd, int pc, int pg_code,
memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid);
}
return ret;
+gen_err:
+ if (residp)
+ *residp = 0;
+ return -1;
}
/* Invokes a SCSI MODE SELECT (6) command. Return of 0 -> success,
@@ -587,17 +614,19 @@ int
sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code,
bool dbd, bool flexible, int mx_mpage_len,
int * success_mask, void * pcontrol_arr[],
- int * reported_len, int verbose)
+ int * reported_lenp, int verbose)
{
- int k, n, res, offset, calc_len, xfer_len, resp_mode6;
+ bool resp_mode6;
+ int k, n, res, offset, calc_len, xfer_len;
+ int resid = 0;
unsigned char buff[MODE_RESP_ARB_LEN];
char ebuff[EBUFF_SZ];
int first_err = 0;
if (success_mask)
*success_mask = 0;
- if (reported_len)
- *reported_len = 0;
+ if (reported_lenp)
+ *reported_lenp = 0;
if (mx_mpage_len < 4)
return 0;
memset(ebuff, 0, sizeof(ebuff));
@@ -607,24 +636,30 @@ sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code,
res = sg_ll_mode_sense6(sg_fd, dbd, 0 /* pc */, pg_code,
sub_pg_code, buff, MODE10_RESP_HDR_LEN, true,
verbose);
- else
- res = sg_ll_mode_sense10(sg_fd, false /* llbaa */, dbd,
- 0 /* pc */, pg_code, sub_pg_code, buff,
- MODE10_RESP_HDR_LEN, true, verbose);
+ else /* MODE SENSE(10) obviously */
+ res = sg_ll_mode_sense10_v2(sg_fd, false /* llbaa */, dbd,
+ 0 /* pc */, pg_code, sub_pg_code, buff,
+ MODE10_RESP_HDR_LEN, 0, &resid, true,
+ verbose);
if (0 != res)
return res;
n = buff[0];
- if (reported_len)
- *reported_len = mode6 ? (n + 1) : (sg_get_unaligned_be16(buff) + 2);
+ if (reported_lenp) {
+ int m;
+
+ m = (mode6 ? (n + 1) : (sg_get_unaligned_be16(buff) + 2)) - resid;
+ if (m < 0) /* Grrr, this should happen */
+ m = 0;
+ }
resp_mode6 = mode6;
if (flexible) {
if (mode6 && (n < 3)) {
- resp_mode6 = 0;
+ resp_mode6 = false;
if (verbose)
pr2ws(">>> msense(6) but resp[0]=%d so try msense(10) "
"response processing\n", n);
}
- if ((0 == mode6) && (n > 5)) {
+ if ((! mode6) && (n > 5)) {
if ((n > 11) && (0 == (n % 2)) && (0 == buff[4]) &&
(0 == buff[5]) && (0 == buff[6])) {
buff[1] = n;
@@ -633,7 +668,7 @@ sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code,
pr2ws(">>> msense(10) but resp[0]=%d and not msense(6) "
"response so fix length\n", n);
} else
- resp_mode6 = 1;
+ resp_mode6 = true;
}
}
if (verbose && (resp_mode6 != mode6))
@@ -657,17 +692,27 @@ sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code,
if (NULL == pcontrol_arr[k])
continue;
memset(pcontrol_arr[k], 0, mx_mpage_len);
+ resid = 0;
if (mode6)
res = sg_ll_mode_sense6(sg_fd, dbd, k /* pc */,
pg_code, sub_pg_code, buff,
calc_len, true, verbose);
else
- res = sg_ll_mode_sense10(sg_fd, false /* llbaa */, dbd,
- k /* pc */, pg_code, sub_pg_code,
- buff, calc_len, true, verbose);
- if (0 != res) {
- if (0 == first_err)
- first_err = res;
+ res = sg_ll_mode_sense10_v2(sg_fd, false /* llbaa */, dbd,
+ k /* pc */, pg_code, sub_pg_code,
+ buff, calc_len, 0, &resid, true,
+ verbose);
+ if (res || resid) {
+ if (0 == first_err) {
+ if (res)
+ first_err = res;
+ else {
+ first_err = -49; /* unexpected resid != 0 */
+ if (verbose)
+ pr2ws("%s: unexpected resid=%d, page=0x%x, "
+ "pcontrol=%d\n", __func__, resid, pg_code, k);
+ }
+ }
if (0 == k)
break; /* if problem on current page, it won't improve */
else
@@ -682,12 +727,32 @@ sg_get_mode_page_controls(int sg_fd, bool mode6, int pg_code, int sub_pg_code,
}
/* Invokes a SCSI LOG SENSE command. Return of 0 -> success,
- * various SG_LIB_CAT_* positive values or -1 -> other errors */
+ * various SG_LIB_CAT_* positive values or -1 -> other errors. */
int
sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
int subpg_code, int paramp, unsigned char * resp,
int mx_resp_len, bool noisy, int verbose)
{
+ return sg_ll_log_sense_v2(sg_fd, ppc, sp, pc, pg_code, subpg_code,
+ paramp, resp, mx_resp_len, 0, NULL, noisy,
+ verbose);
+}
+
+/* Invokes a SCSI LOG SENSE command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * Adds the ability to set the command abort timeout
+ * and the ability to report the residual count. If timeout_secs is zero
+ * or less the the default command abort timeout (60 seconds) is used.
+ * If residp is non-NULL then the residual value is written where residp
+ * points. A residual value of 0 implies mx_resp_len bytes have be written
+ * where resp points. If the residual value equals mx_resp_len then no
+ * bytes have been written. */
+int
+sg_ll_log_sense_v2(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
+ int subpg_code, int paramp, unsigned char * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose)
+{
static const char * const cdb_name_s = "log sense";
int res, ret, k, sense_cat, resid;
unsigned char logs_cdb[LOG_SENSE_CMDLEN] =
@@ -697,7 +762,7 @@ sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
if (mx_resp_len > 0xffff) {
pr2ws("mx_resp_len too big\n");
- return -1;
+ goto gen_err;
}
logs_cdb[1] = (unsigned char)((ppc ? 2 : 0) | (sp ? 1 : 0));
logs_cdb[2] = (unsigned char)(((pc << 6) & 0xc0) | (pg_code & 0x3f));
@@ -710,16 +775,20 @@ sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
pr2ws("%02x ", logs_cdb[k]);
pr2ws("\n");
}
+ if (timeout_secs <= 0)
+ timeout_secs = DEF_PT_TIMEOUT;
if (NULL == ((ptvp = create_pt_obj(cdb_name_s))))
- return -1;
+ goto gen_err;
set_scsi_pt_cdb(ptvp, logs_cdb, sizeof(logs_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len,
sense_b, noisy, verbose, &sense_cat);
resid = get_scsi_pt_resid(ptvp);
+ if (residp)
+ *residp = resid;
destruct_scsi_pt_obj(ptvp);
if (-1 == ret)
;
@@ -752,6 +821,10 @@ sg_ll_log_sense(int sg_fd, bool ppc, bool sp, int pc, int pg_code,
memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid);
}
return ret;
+gen_err:
+ if (residp)
+ *residp = 0;
+ return -1;
}
/* Invokes a SCSI LOG SELECT command. Return of 0 -> success,
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index fdeb1829..fb1b02be 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -525,12 +525,24 @@ int
sg_ll_receive_diag(int sg_fd, bool pcv, int pg_code, void * resp,
int mx_resp_len, bool noisy, int verbose)
{
- static const char * const cdb_name_s = "receive diagnostic results";
+ return sg_ll_receive_diag_v2(sg_fd, pcv, pg_code, resp, mx_resp_len, 0,
+ NULL, noisy, verbose);
+}
+
+/* Invokes a SCSI RECEIVE DIAGNOSTIC RESULTS command. Return of 0 -> success,
+ * various SG_LIB_CAT_* positive values or -1 -> other errors */
+int
+sg_ll_receive_diag_v2(int sg_fd, bool pcv, int pg_code, void * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose)
+{
+ int resid = 0;
int k, res, ret, sense_cat;
+ static const char * const cdb_name_s = "receive diagnostic results";
+ struct sg_pt_base * ptvp;
unsigned char rcvdiag_cdb[RECEIVE_DIAGNOSTICS_CMDLEN] =
{RECEIVE_DIAGNOSTICS_CMD, 0, 0, 0, 0, 0};
unsigned char sense_b[SENSE_BUFF_LEN];
- struct sg_pt_base * ptvp;
if (pcv)
rcvdiag_cdb[1] = 0x1;
@@ -543,15 +555,23 @@ sg_ll_receive_diag(int sg_fd, bool pcv, int pg_code, void * resp,
pr2ws("%02x ", rcvdiag_cdb[k]);
pr2ws("\n");
}
+ if (timeout_secs <= 0)
+ timeout_secs = DEF_PT_TIMEOUT;
- if (NULL == ((ptvp = create_pt_obj(cdb_name_s))))
+ if (NULL == ((ptvp = create_pt_obj(cdb_name_s)))) {
+ if (residp)
+ *residp = 0;
return -1;
+ }
set_scsi_pt_cdb(ptvp, rcvdiag_cdb, sizeof(rcvdiag_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
- res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
ret = sg_cmds_process_resp(ptvp, cdb_name_s, res, mx_resp_len, sense_b,
noisy, verbose, &sense_cat);
+ resid = get_scsi_pt_resid(ptvp);
+ if (residp)
+ *residp = resid;
if (-1 == ret)
;
else if (-2 == ret) {
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index 76773fa1..914570b2 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -5,7 +5,7 @@
* license that can be found in the BSD_LICENSE file.
*/
-/* sg_pt_linux version 1.27 20171005 */
+/* sg_pt_linux version 1.28 20171019 */
#include <stdio.h>
@@ -18,8 +18,11 @@
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h> /* to define 'major' */
+#ifndef major
+#include <sys/types.h>
+#endif
#ifdef HAVE_CONFIG_H
diff --git a/scripts/scsi_mandat b/scripts/scsi_mandat
index 7c11a408..1f72b406 100755
--- a/scripts/scsi_mandat
+++ b/scripts/scsi_mandat
@@ -42,10 +42,10 @@ aborted_command=0
usage()
{
echo "Usage: scsi_mandat [-h] [-L] [-q] [-v] <device>"
- echo " where: -h print usage message"
- echo " -L, --log append stderr to 'scsi_mandat.err'"
- echo " -q suppress some output"
- echo " -v increase verbosity of output"
+ echo " where: -h, --help print usage message"
+ echo " -L, --log append stderr to 'scsi_mandat.err'"
+ echo " -q, --quiet suppress some output"
+ echo " -v, --verbose increase verbosity of output"
echo ""
echo "Check <device> for mandatory SCSI command support"
}
@@ -71,7 +71,7 @@ if [ $# -lt 1 ]
then
usage
exit 1
-fi
+fi
for command in "sg_inq" "sg_luns" "sg_turs" "sg_requests" "sg_vpd" \
"sg_vpd -i" "sg_senddiag -t"
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 807645a8..639a4db3 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Wed Oct 11 2017 - dgilbert at interlog dot com
+* Sun Oct 22 2017 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.43
diff --git a/src/sg_compare_and_write.c b/src/sg_compare_and_write.c
index 2f790063..4549c362 100644
--- a/src/sg_compare_and_write.c
+++ b/src/sg_compare_and_write.c
@@ -54,7 +54,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.18 20171010";
+static const char * version_str = "1.19 20171020";
#define DEF_BLOCK_SIZE 512
#define DEF_NUM_BLOCKS (1)
@@ -116,11 +116,12 @@ usage()
{
pr2serr("Usage: sg_compare_and_write [--dpo] [--fua] [--fua_nv] "
"[--group=GN] [--help]\n"
- " --in=IF [--inw=WF] --lba=LBA "
+ " --in=IF|--inc=IF [--inw=WF] "
+ "--lba=LBA "
"[--num=NUM]\n"
" [--quiet] [--timeout=TO] "
"[--verbose] [--version]\n"
- " [--wrpotect=WP] [--xferlen=LEN] "
+ " [--wrprotect=WP] [--xferlen=LEN] "
"DEVICE\n"
" where:\n"
" --dpo|-d set the dpo bit in cdb (def: "
@@ -137,6 +138,7 @@ usage()
" optionally a write buffer (when "
"--inw=WF is\n"
" not given)\n"
+ " --inc=IF|-C IF The same as the --in option\n"
" --inw=WF|-D WF WF is a file containing a write "
"buffer\n"
" --lba=LBA|-l LBA LBA of the first block to compare "
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 97a6f77e..7bb5eedf 100644
--- a/src/sg_dd.c
+++ b/src/sg_dd.c
@@ -44,13 +44,15 @@
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/file.h>
-#include <linux/major.h>
+#include <sys/sysmacros.h>
+#ifndef major
+#include <sys/types.h>
+#endif
#include <linux/fs.h> /* <sys/mount.h> */
+#include <linux/major.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
diff --git a/src/sg_format.c b/src/sg_format.c
index 3bef6a17..54506d3a 100644
--- a/src/sg_format.c
+++ b/src/sg_format.c
@@ -37,7 +37,7 @@
#include "sg_pr2serr.h"
#include "sg_pt.h"
-static const char * version_str = "1.39 20171012";
+static const char * version_str = "1.39 20171021";
#define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */
@@ -756,15 +756,16 @@ print_read_cap(int fd, const struct opts_t * op)
int
main(int argc, char **argv)
{
+ bool prob = false;
int fd, res, calc_len, bd_len, dev_specific_param;
- int offset, j, n, bd_blk_len, len, pdt;
+ int offset, j, n, bd_blk_len, len, pdt, rsp_len;
+ int resid = 0;
int ret = 0;
- bool prob = false;
uint64_t ull;
- char b[80];
+ struct opts_t * op;
unsigned char inq_resp[SAFE_STD_INQ_RESP_LEN];
struct opts_t opts;
- struct opts_t * op;
+ char b[80];
op = &opts;
memset(op, 0, sizeof(opts));
@@ -1028,10 +1029,11 @@ again_with_long_lba:
op->mode_page, 0 /* subpage */, dbuff,
MAX_BUFF_SZ, true, op->verbose);
else
- res = sg_ll_mode_sense10(fd, op->long_lba, false /* DBD */,
- 0 /* current */, op->mode_page,
- 0 /* subpage */, dbuff,
- MAX_BUFF_SZ, true, op->verbose);
+ res = sg_ll_mode_sense10_v2(fd, op->long_lba, false /* DBD */,
+ 0 /* current */, op->mode_page,
+ 0 /* subpage */, dbuff,
+ MAX_BUFF_SZ, 0, &resid, true,
+ op->verbose);
ret = res;
if (res) {
if (SG_LIB_CAT_ILLEGAL_REQ == res) {
@@ -1055,6 +1057,7 @@ again_with_long_lba:
}
if (op->mode6) {
calc_len = dbuff[0] + 1;
+ rsp_len = calc_len;
dev_specific_param = dbuff[2];
bd_len = dbuff[3];
op->long_lba = false;
@@ -1063,7 +1066,23 @@ again_with_long_lba:
dbuff[0] = 0;
dbuff[1] = 0;
dbuff[2] = 0;
- } else {
+ } else { /* MODE SENSE(10) */
+ if (resid > 0)
+ rsp_len = MAX_BUFF_SZ - resid;
+ else
+ rsp_len = MAX_BUFF_SZ;
+ if (rsp_len < 0) {
+ pr2serr("%s: resid=%d implies negative response "
+ "length of %d\n", __func__, resid, rsp_len);
+ ret = SG_LIB_WILD_RESID;
+ goto out;
+ }
+ if (rsp_len < 8) {
+ pr2serr("%s: MS(10) response length too short (%d)\n",
+ __func__, rsp_len);
+ ret = -1;
+ goto out;
+ }
calc_len = sg_get_unaligned_be16(dbuff + 0);
dev_specific_param = dbuff[3];
bd_len = sg_get_unaligned_be16(dbuff + 6);
@@ -1075,6 +1094,11 @@ again_with_long_lba:
dbuff[2] = 0;
dbuff[3] = 0;
}
+ if (rsp_len < calc_len) {
+ pr2serr("%s: MS response length truncated (%d < %d)\n",
+ __func__, rsp_len, calc_len);
+ goto out;
+ }
if ((offset + bd_len) < calc_len)
dbuff[offset + bd_len] &= 0x7f; /* clear PS bit in mpage */
prob = false;
diff --git a/src/sg_inq.c b/src/sg_inq.c
index ea6374cd..f2a0719c 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -43,7 +43,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.69 20171012"; /* SPC-5 rev 17 */
+static const char * version_str = "1.70 20171021"; /* SPC-5 rev 17 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -317,6 +317,7 @@ usage()
"inquiry\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string then exit\n"
+ " --old|-O use old interface (use as first option)\n"
" --vpd|-e vital product data (set page with "
"'--page=PG')\n\n"
"Performs a SCSI INQUIRY command on DEVICE or decodes INQUIRY "
@@ -380,6 +381,7 @@ usage_old()
" -V output version string\n"
" -x decode extended INQUIRY data VPD page (0x86)\n"
" -36 perform standard INQUIRY with a 36 byte response\n"
+ " -N|--new use new interface\n"
" -? output this usage message\n\n"
"If no options given then does a standard SCSI INQUIRY\n");
}
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 096c7712..728e423c 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -32,7 +32,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.52 20171009"; /* spc5r17 + sbc4r11 */
+static const char * version_str = "1.54 20171022"; /* spc5r17 + sbc4r11 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -85,8 +85,9 @@ static const char * version_str = "1.52 20171009"; /* spc5r17 + sbc4r11 */
#define VP_ALL 99
#define MVP_OFFSET 8
-/* shared is T10 defined lpage with vendor specific parameter codes */
-#define MVP_SHARED (1 << (MVP_OFFSET - 1))
+/* MVO_STD or-ed with MVP_<vendor> is T10 defined lpage with vendor specific
+ * parameter codes */
+#define MVP_STD (1 << (MVP_OFFSET - 1))
#define MVP_SEAG (1 << (VP_SEAG + MVP_OFFSET))
#define MVP_HITA (1 << (VP_HITA + MVP_OFFSET))
#define MVP_WDC (1 << (VP_WDC + MVP_OFFSET))
@@ -102,6 +103,7 @@ static const char * version_str = "1.52 20171009"; /* spc5r17 + sbc4r11 */
#define PCB_STR_LEN 128
#define LOG_SENSE_PROBE_ALLOC_LEN 4
+#define LOG_SENSE_DEF_TIMEOUT 64 /* seconds */
static uint8_t rsp_buff[MX_ALLOC_LEN + 4];
@@ -120,6 +122,7 @@ static struct option long_options[] = {
{"name", no_argument, 0, 'n'},
{"new", no_argument, 0, 'N'},
{"no_inq", no_argument, 0, 'x'},
+ {"no-inq", no_argument, 0, 'x'},
{"old", no_argument, 0, 'O'},
{"page", required_argument, 0, 'p'},
{"paramp", required_argument, 0, 'P'},
@@ -144,7 +147,6 @@ struct opts_t {
bool do_pcb;
bool do_ppc;
bool do_raw;
- bool o_readonly;
bool do_pcreset;
bool do_select;
bool do_sp;
@@ -152,6 +154,7 @@ struct opts_t {
bool do_transport;
bool do_version;
bool filter_given;
+ bool o_readonly;
bool opt_new;
int do_all;
int do_brief;
@@ -298,107 +301,107 @@ static bool show_seagate_factory_page(const uint8_t * resp, int len,
/* elements in page_number/subpage_number order */
static struct log_elem log_arr[] = {
- {SUPP_PAGES_LPAGE, 0, 0, -1, 0, "Supported log pages", "sp",
+ {SUPP_PAGES_LPAGE, 0, 0, -1, MVP_STD, "Supported log pages", "sp",
show_supported_pgs_page}, /* 0, 0 */
- {SUPP_PAGES_LPAGE, SUPP_SPGS_SUBPG, 0, -1, 0, "Supported log pages and "
- "subpages", "ssp", show_supported_pgs_sub_page}, /* 0, 0xff */
- {BUFF_OVER_UNDER_LPAGE, 0, 0, -1, 0, "Buffer over-run/under-run", "bou",
- show_buffer_over_under_run_page}, /* 0x1, 0x0 */
- {WRITE_ERR_LPAGE, 0, 0, -1, 0, "Write error", "we",
+ {SUPP_PAGES_LPAGE, SUPP_SPGS_SUBPG, 0, -1, MVP_STD, "Supported log pages "
+ "and subpages", "ssp", show_supported_pgs_sub_page}, /* 0, 0xff */
+ {BUFF_OVER_UNDER_LPAGE, 0, 0, -1, MVP_STD, "Buffer over-run/under-run",
+ "bou", show_buffer_over_under_run_page}, /* 0x1, 0x0 */
+ {WRITE_ERR_LPAGE, 0, 0, -1, MVP_STD, "Write error", "we",
show_error_counter_page}, /* 0x2, 0x0 */
- {READ_ERR_LPAGE, 0, 0, -1, 0, "Read error", "re",
+ {READ_ERR_LPAGE, 0, 0, -1, MVP_STD, "Read error", "re",
show_error_counter_page}, /* 0x3, 0x0 */
- {READ_REV_ERR_LPAGE, 0, 0, -1, 0, "Read reverse error", "rre",
+ {READ_REV_ERR_LPAGE, 0, 0, -1, MVP_STD, "Read reverse error", "rre",
show_error_counter_page}, /* 0x4, 0x0 */
- {VERIFY_ERR_LPAGE, 0, 0, -1, 0, "Verify error", "ve",
+ {VERIFY_ERR_LPAGE, 0, 0, -1, MVP_STD, "Verify error", "ve",
show_error_counter_page}, /* 0x5, 0x0 */
- {NON_MEDIUM_LPAGE, 0, 0, -1, 0, "Non medium", "nm",
+ {NON_MEDIUM_LPAGE, 0, 0, -1, MVP_STD, "Non medium", "nm",
show_non_medium_error_page}, /* 0x6, 0x0 */
- {LAST_N_ERR_LPAGE, 0, 0, -1, 0, "Last n error", "lne",
+ {LAST_N_ERR_LPAGE, 0, 0, -1, MVP_STD, "Last n error", "lne",
show_last_n_error_page}, /* 0x7, 0x0 */
- {FORMAT_STATUS_LPAGE, 0, 0, 0, 0, "Format status", "fs",
+ {FORMAT_STATUS_LPAGE, 0, 0, 0, MVP_STD, "Format status", "fs",
show_format_status_page}, /* 0x8, 0x0 SBC */
- {LAST_N_DEFERRED_LPAGE, 0, 0, -1, 0, "Last n deferred error", "lnd",
+ {LAST_N_DEFERRED_LPAGE, 0, 0, -1, MVP_STD, "Last n deferred error", "lnd",
show_last_n_deferred_error_page}, /* 0xb, 0x0 */
- {LAST_N_DEFERRED_LPAGE, LAST_N_INQUIRY_DATA_CH_SUBPG, 0, -1, 0,
+ {LAST_N_DEFERRED_LPAGE, LAST_N_INQUIRY_DATA_CH_SUBPG, 0, -1, MVP_STD,
"Last n inquiry data changed", "lnic",
show_last_n_inq_data_ch_page}, /* 0xb, 0x1 */
- {LAST_N_DEFERRED_LPAGE, LAST_N_MODE_PG_DATA_CH_SUBPG, 0, -1, 0,
+ {LAST_N_DEFERRED_LPAGE, LAST_N_MODE_PG_DATA_CH_SUBPG, 0, -1, MVP_STD,
"Last n mode page data changed", "lnmc",
show_last_n_mode_pg_data_ch_page}, /* 0xb, 0x2 */
- {LB_PROV_LPAGE, 0, 0, 0, 0, "Logical block provisioning", "lbp",
+ {LB_PROV_LPAGE, 0, 0, 0, MVP_STD, "Logical block provisioning", "lbp",
show_lb_provisioning_page}, /* 0xc, 0x0 SBC */
- {0xc, 0, 0, PDT_TAPE, 0, "Sequential access device", "sad",
+ {0xc, 0, 0, PDT_TAPE, MVP_STD, "Sequential access device", "sad",
show_sequential_access_page}, /* 0xc, 0x0 SSC */
- {TEMPERATURE_LPAGE, 0, 0, -1, 0, "Temperature", "temp",
+ {TEMPERATURE_LPAGE, 0, 0, -1, MVP_STD, "Temperature", "temp",
show_temperature_page}, /* 0xd, 0x0 */
- {TEMPERATURE_LPAGE, ENV_REPORTING_SUBPG, 0, -1, 0, /* 0xd, 0x1 */
+ {TEMPERATURE_LPAGE, ENV_REPORTING_SUBPG, 0, -1, MVP_STD, /* 0xd, 0x1 */
"Environmental reporting", "enr", show_environmental_reporting_page},
- {TEMPERATURE_LPAGE, ENV_LIMITS_SUBPG, 0, -1, 0, /* 0xd, 0x2 */
+ {TEMPERATURE_LPAGE, ENV_LIMITS_SUBPG, 0, -1, MVP_STD, /* 0xd, 0x2 */
"Environmental limits", "enl", show_environmental_limits_page},
- {START_STOP_LPAGE, 0, 0, -1, 0, "Start-stop cycle counter", "sscc",
+ {START_STOP_LPAGE, 0, 0, -1, MVP_STD, "Start-stop cycle counter", "sscc",
show_start_stop_page}, /* 0xe, 0x0 */
- {START_STOP_LPAGE, UTILIZATION_SUBPG, 0, 0, 0, "Utilization", "util",
- show_utilization_page}, /* 0xe, 0x1 SBC */ /* sbc4r04 */
- {APP_CLIENT_LPAGE, 0, 0, -1, 0, "Application client", "ac",
+ {START_STOP_LPAGE, UTILIZATION_SUBPG, 0, 0, MVP_STD, "Utilization",
+ "util", show_utilization_page}, /* 0xe, 0x1 SBC */ /* sbc4r04 */
+ {APP_CLIENT_LPAGE, 0, 0, -1, MVP_STD, "Application client", "ac",
show_app_client_page}, /* 0xf, 0x0 */
- {SELF_TEST_LPAGE, 0, 0, -1, 0, "Self test results", "str",
+ {SELF_TEST_LPAGE, 0, 0, -1, MVP_STD, "Self test results", "str",
show_self_test_page}, /* 0x10, 0x0 */
- {SOLID_STATE_MEDIA_LPAGE, 0, 0, 0, 0, "Solid state media", "ssm",
+ {SOLID_STATE_MEDIA_LPAGE, 0, 0, 0, MVP_STD, "Solid state media", "ssm",
show_solid_state_media_page}, /* 0x11, 0x0 SBC */
- {0x11, 0, 0, PDT_TAPE, 0, "DT Device status", "dtds",
+ {0x11, 0, 0, PDT_TAPE, MVP_STD, "DT Device status", "dtds",
show_dt_device_status_page}, /* 0x11, 0x0 SSC,ADC */
- {0x12, 0, 0, PDT_TAPE, 0, "Tape alert response", "tar",
+ {0x12, 0, 0, PDT_TAPE, MVP_STD, "Tape alert response", "tar",
show_tapealert_response_page}, /* 0x12, 0x0 SSC,ADC */
- {0x13, 0, 0, PDT_TAPE, 0, "Requested recovery", "rr",
+ {0x13, 0, 0, PDT_TAPE, MVP_STD, "Requested recovery", "rr",
show_requested_recovery_page}, /* 0x13, 0x0 SSC,ADC */
- {0x14, 0, 0, PDT_TAPE, 0, "Device statistics", "ds",
+ {0x14, 0, 0, PDT_TAPE, MVP_STD, "Device statistics", "ds",
show_device_stats_page}, /* 0x14, 0x0 SSC,ADC */
- {0x14, 0, 0, PDT_MCHANGER, 0, "Media changer statistics", "mcs",
+ {0x14, 0, 0, PDT_MCHANGER, MVP_STD, "Media changer statistics", "mcs",
show_media_stats_page}, /* 0x14, 0x0 SMC */
- {0x14, ZONED_BLOCK_DEV_STATS_SUBPG, 0, 0, 0, /* 0x14,0x1 zbc2r01 */
+ {0x14, ZONED_BLOCK_DEV_STATS_SUBPG, 0, 0, MVP_STD, /* 0x14,0x1 zbc2r01 */
"Zoned block device statistics", "zbds", show_zoned_block_dev_stats},
- {BACKGROUND_SCAN_LPAGE, 0, 0, 0, 0, "Background scan results", "bsr",
- show_background_scan_results_page}, /* 0x15, 0x0 SBC */
- {BACKGROUND_SCAN_LPAGE, BACKGROUND_OP_SUBPG, 0, 0, 0,
+ {BACKGROUND_SCAN_LPAGE, 0, 0, 0, MVP_STD, "Background scan results",
+ "bsr", show_background_scan_results_page}, /* 0x15, 0x0 SBC */
+ {BACKGROUND_SCAN_LPAGE, BACKGROUND_OP_SUBPG, 0, 0, MVP_STD,
"Background operation", "bop", show_background_op_page},
/* 0x15, 0x2 SBC */
- {BACKGROUND_SCAN_LPAGE, LPS_MISALIGNMENT_SUBPG, 0, 0, 0,
+ {BACKGROUND_SCAN_LPAGE, LPS_MISALIGNMENT_SUBPG, 0, 0, MVP_STD,
"LPS misalignment", "lps", show_lps_misalignment_page},
/* 0x15, 0x3 SBC-4 */
- {0x15, 0, 0, PDT_MCHANGER, 0, "Element statistics", "els",
+ {0x15, 0, 0, PDT_MCHANGER, MVP_STD, "Element statistics", "els",
show_element_stats_page}, /* 0x15, 0x0 SMC */
- {0x15, 0, 0, PDT_ADC, 0, "Service buffers information", "sbi",
+ {0x15, 0, 0, PDT_ADC, MVP_STD, "Service buffers information", "sbi",
show_service_buffer_info_page}, /* 0x15, 0x0 ADC */
- {BACKGROUND_SCAN_LPAGE, PENDING_DEFECTS_SUBPG, 0, 0, 0,
+ {BACKGROUND_SCAN_LPAGE, PENDING_DEFECTS_SUBPG, 0, 0, MVP_STD,
"Pending defects", "pd", show_pending_defects_page}, /* 0x15, 0x1 SBC */
- {SAT_ATA_RESULTS_LPAGE, 0, 0, 0, 0, "ATA pass-through results", "aptr",
- show_ata_pt_results_page}, /* 0x16, 0x0 SAT */
- {0x16, 0, 0, PDT_TAPE, 0, "Tape diagnostic data", "tdd",
+ {SAT_ATA_RESULTS_LPAGE, 0, 0, 0, MVP_STD, "ATA pass-through results",
+ "aptr", show_ata_pt_results_page}, /* 0x16, 0x0 SAT */
+ {0x16, 0, 0, PDT_TAPE, MVP_STD, "Tape diagnostic data", "tdd",
show_tape_diag_data_page}, /* 0x16, 0x0 SSC */
- {0x16, 0, 0, PDT_MCHANGER, 0, "Media changer diagnostic data", "mcdd",
- show_mchanger_diag_data_page}, /* 0x16, 0x0 SMC */
- {0x17, 0, 0, 0, 0, "Non volatile cache", "nvc",
+ {0x16, 0, 0, PDT_MCHANGER, MVP_STD, "Media changer diagnostic data",
+ "mcdd", show_mchanger_diag_data_page}, /* 0x16, 0x0 SMC */
+ {0x17, 0, 0, 0, MVP_STD, "Non volatile cache", "nvc",
show_non_volatile_cache_page}, /* 0x17, 0x0 SBC */
- {0x17, 0, 0xf, PDT_TAPE, 0, "Volume statistics", "vs",
+ {0x17, 0, 0xf, PDT_TAPE, MVP_STD, "Volume statistics", "vs",
show_volume_stats_pages}, /* 0x17, 0x0...0xf SSC */
- {PROTO_SPECIFIC_LPAGE, 0, 0, -1, 0, "Protocol specific port", "psp",
- show_protocol_specific_page}, /* 0x18, 0x0 */
- {STATS_LPAGE, 0, 0, -1, 0, "General Statistics and Performance", "gsp",
- show_stats_perform_pages}, /* 0x19, 0x0 */
- {STATS_LPAGE, 0x1, 0x1f, -1, 0, "Group Statistics and Performance", "grsp",
- show_stats_perform_pages}, /* 0x19, 0x1...0x1f */
- {STATS_LPAGE, 0x20, 0, -1, 0, "Cache memory statistics", "cms",
+ {PROTO_SPECIFIC_LPAGE, 0, 0, -1, MVP_STD, "Protocol specific port",
+ "psp", show_protocol_specific_page}, /* 0x18, 0x0 */
+ {STATS_LPAGE, 0, 0, -1, MVP_STD, "General Statistics and Performance",
+ "gsp", show_stats_perform_pages}, /* 0x19, 0x0 */
+ {STATS_LPAGE, 0x1, 0x1f, -1, MVP_STD, "Group Statistics and Performance",
+ "grsp", show_stats_perform_pages}, /* 0x19, 0x1...0x1f */
+ {STATS_LPAGE, 0x20, 0, -1, MVP_STD, "Cache memory statistics", "cms",
show_cache_stats_page}, /* 0x19, 0x20 */
- {PCT_LPAGE, 0, 0, -1, 0, "Power condition transitions", "pct",
+ {PCT_LPAGE, 0, 0, -1, MVP_STD, "Power condition transitions", "pct",
show_power_condition_transitions_page}, /* 0x1a, 0 */
- {0x1b, 0, 0, PDT_TAPE, 0, "Data compression", "dc",
+ {0x1b, 0, 0, PDT_TAPE, MVP_STD, "Data compression", "dc",
show_data_compression_page}, /* 0x1b, 0 SSC */
- {0x2d, 0, 0, PDT_TAPE, 0, "Current service information", "csi",
+ {0x2d, 0, 0, PDT_TAPE, MVP_STD, "Current service information", "csi",
NULL}, /* 0x2d, 0 SSC */
- {TAPE_ALERT_LPAGE, 0, 0, PDT_TAPE, 0, "Tape alert", "ta",
+ {TAPE_ALERT_LPAGE, 0, 0, PDT_TAPE, MVP_STD, "Tape alert", "ta",
show_tape_alert_ssc_page}, /* 0x2e, 0 SSC */
- {IE_LPAGE, 0, 0, -1, (MVP_SHARED | MVP_SMSTR), "Informational exceptions",
+ {IE_LPAGE, 0, 0, -1, (MVP_STD | MVP_SMSTR), "Informational exceptions",
"ie", show_ie_page}, /* 0x2f, 0 */
/* vendor specific */
{0x30, 0, 0, PDT_DISK, MVP_HITA, "Performance counters (Hitachi)",
@@ -440,7 +443,7 @@ static struct log_elem log_arr[] = {
{0x3e, 0, 0, PDT_TAPE, OVP_LTO, "Device Status (lto-5, 6)",
"ds_", NULL}, /* 0x3e, 0 SSC */
- {-1, -1, -1, -1, -1, NULL, "zzzzz", NULL}, /* end sentinel */
+ {-1, -1, -1, -1, 0, NULL, "zzzzz", NULL}, /* end sentinel */
};
/* Supported vendor product codes */
@@ -608,29 +611,30 @@ usage_old()
" -M=VP vendor/product abbreviation [or number]\n"
" -n decode some pages into multiple name=value "
"lines\n"
+ " -N|--new use new interface\n"
" -p=PG PG is an acronym (def: 'sp')\n"
" -p=PGN page code in hex (def: 0)\n"
" -p=PGN,SPGN page and subpage codes in hex, (defs: 0,0)\n"
" -paramp=PP (in hex) (def: 0)\n"
- " -pcb show parameter control bytes in decoded "
+ " -pcb show parameter control bytes in decoded "
"output\n");
- printf(" -ppc set the Parameter Pointer Control (PPC) bit "
+ printf(" -ppc set the Parameter Pointer Control (PPC) bit "
"(def: 0)\n"
- " -r reset log parameters (takes PC and SP into "
+ " -r reset log parameters (takes PC and SP into "
"account)\n"
- " (uses PCR bit in LOG SELECT)\n"
+ " (uses PCR bit in LOG SELECT)\n"
" -select perform LOG SELECT (def: LOG SENSE)\n"
- " -sp set the Saving Parameters (SP) bit (def: 0)\n"
- " -t outputs temperature log page (0xd)\n"
- " -T outputs transport (protocol specific port) log "
+ " -sp set the Saving Parameters (SP) bit (def: 0)\n"
+ " -t outputs temperature log page (0xd)\n"
+ " -T outputs transport (protocol specific port) log "
"page (0x18)\n"
- " -v increase verbosity\n"
- " -V output version string\n"
- " -x no initial INQUIRY output (twice: no INQUIRY call)\n"
- " -X open DEVICE read-only (def: first read-write then "
+ " -v increase verbosity\n"
+ " -V output version string\n"
+ " -x no initial INQUIRY output (twice: no INQUIRY call)\n"
+ " -X open DEVICE read-only (def: first read-write then "
"if fails\n"
- " try open again with read-only)\n"
- " -? output this usage message\n\n"
+ " try open again with read-only)\n"
+ " -? output this usage message\n\n"
"Performs a SCSI LOG SENSE (or LOG SELECT) command\n");
}
@@ -657,16 +661,15 @@ asort_comp(const void * lp, const void * rp)
}
static void
-enumerate_helper(const struct log_elem * lep, int pos,
+enumerate_helper(const struct log_elem * lep, bool first,
const struct opts_t * op)
{
char b[80];
char bb[80];
const char * cp;
- bool mvp = !! lep->flags;
- bool shared_vp = !!(MVP_SHARED & lep->flags);
+ bool vendor_lpage = ! (MVP_STD & lep->flags);
- if (0 == pos) {
+ if (first) {
if (1 == op->verbose) {
printf("acronym pg[,spg] name\n");
printf("===============================================\n");
@@ -675,7 +678,7 @@ enumerate_helper(const struct log_elem * lep, int pos,
printf("===================================================\n");
}
}
- if ((0 == (op->do_enumerate % 2)) && mvp && ! shared_vp)
+ if ((0 == (op->do_enumerate % 2)) && vendor_lpage)
return; /* if do_enumerate is even then skip vendor pages */
else if ((! op->filter_given) || (-1 == op->filter))
; /* otherwise enumerate all lpages if no --filter= */
@@ -744,12 +747,12 @@ enumerate_pages(const struct opts_t * op)
qsort(lep_arr, k, sizeof(struct log_elem *), asort_comp);
printf("Known log pages in acronym order:\n");
for (lepp = lep_arr, j = 0; (*lepp)->pg_code >=0; ++lepp, ++j)
- enumerate_helper(*lepp, j, op);
+ enumerate_helper(*lepp, (0 == j), op);
free(lep_arr);
} else { /* -eee, -eeee numeric sort (as per table) */
printf("Known log pages in numerical order:\n");
for (lep = log_arr, j = 0; lep->pg_code >=0; ++lep, ++j)
- enumerate_helper(lep, j, op);
+ enumerate_helper(lep, (0 == j), op);
}
}
@@ -846,7 +849,10 @@ pg_subpg_pdt_search(int pg_code, int subpg_code, int pdt, int vpn)
for (lep = log_arr; lep->pg_code >=0; ++lep) {
if (pg_code == lep->pg_code) {
if (subpg_code == lep->subpg_code) {
- if (vp_mask && ! (vp_mask & lep->flags))
+ if ((MVP_STD & lep->flags) || (0 == vp_mask) ||
+ (vp_mask & lep->flags))
+ ;
+ else
continue;
if ((lep->pdt < 0) || (pdt == lep->pdt) || (pdt < 0))
return lep;
@@ -1539,7 +1545,7 @@ static int
do_logs(int sg_fd, uint8_t * resp, int mx_resp_len,
const struct opts_t * op)
{
- int actual_len, res, vb;
+ int calc_len, request_len, res, resid, vb;
#ifdef SG_LIB_WIN32
#ifdef SG_LIB_WIN32_DIRECT
@@ -1561,47 +1567,72 @@ do_logs(int sg_fd, uint8_t * resp, int mx_resp_len,
memset(resp, 0, mx_resp_len);
vb = op->verbose;
if (op->maxlen > 1)
- actual_len = mx_resp_len;
+ request_len = mx_resp_len;
else {
- if ((res = sg_ll_log_sense(sg_fd, op->do_ppc, op->do_sp,
- op->page_control, op->pg_code,
- op->subpg_code, op->paramp,
- resp, LOG_SENSE_PROBE_ALLOC_LEN,
- true /* noisy */, vb)))
+ request_len = LOG_SENSE_PROBE_ALLOC_LEN;
+ if ((res = sg_ll_log_sense_v2(sg_fd, op->do_ppc, op->do_sp,
+ op->page_control, op->pg_code,
+ op->subpg_code, op->paramp,
+ resp, request_len, LOG_SENSE_DEF_TIMEOUT,
+ &resid, true /* noisy */, vb)))
return res;
- actual_len = sg_get_unaligned_be16(resp + 2) + 4;
+ if (resid > 0) {
+ res = SG_LIB_WILD_RESID;
+ goto resid_err;
+ }
+ calc_len = sg_get_unaligned_be16(resp + 2) + 4;
if ((! op->do_raw) && (vb > 1)) {
pr2serr(" Log sense (find length) response:\n");
dStrHexErr((const char *)resp, LOG_SENSE_PROBE_ALLOC_LEN, 1);
- pr2serr(" hence calculated response length=%d\n", actual_len);
+ pr2serr(" hence calculated response length=%d\n", calc_len);
}
if (op->pg_code != (0x3f & resp[0])) {
if (vb)
pr2serr("Page code does not appear in first byte of "
"response so it's suspect\n");
- if (actual_len > 0x40) {
- actual_len = 0x40;
+ if (calc_len > 0x40) {
+ calc_len = 0x40;
if (vb)
pr2serr("Trim response length to 64 bytes due to "
"suspect response format\n");
}
}
/* Some HBAs don't like odd transfer lengths */
- if (actual_len % 2)
- actual_len += 1;
- if (actual_len > mx_resp_len)
- actual_len = mx_resp_len;
+ if (calc_len % 2)
+ calc_len += 1;
+ if (calc_len > mx_resp_len)
+ calc_len = mx_resp_len;
+ request_len = calc_len;
}
- if ((res = sg_ll_log_sense(sg_fd, op->do_ppc, op->do_sp,
- op->page_control, op->pg_code,
- op->subpg_code, op->paramp,
- resp, actual_len, true /* noisy */, vb)))
+ if ((res = sg_ll_log_sense_v2(sg_fd, op->do_ppc, op->do_sp,
+ op->page_control, op->pg_code,
+ op->subpg_code, op->paramp,
+ resp, request_len,
+ LOG_SENSE_DEF_TIMEOUT, &resid,
+ true /* noisy */, vb)))
return res;
+ if (resid > 0) {
+ request_len -= resid;
+ if (request_len < 4) {
+ request_len += resid;
+ res = SG_LIB_WILD_RESID;
+ goto resid_err;
+ }
+ }
if ((! op->do_raw) && (vb > 1)) {
pr2serr(" Log sense response:\n");
- dStrHexErr((const char *)resp, actual_len, 1);
+ dStrHexErr((const char *)resp, request_len, 1);
}
return 0;
+resid_err:
+ pr2serr("%s: request_len=%d, resid=%d, problems\n", __func__, request_len,
+ resid);
+ request_len -= resid;
+ if ((request_len > 0) && (! op->do_raw) && (vb > 1)) {
+ pr2serr(" Log sense (resid_err) response:\n");
+ dStrHexErr((const char *)resp, request_len, 1);
+ }
+ return res;
}
/* DS made obsolete in spc4r03; TMC and ETC made obsolete in spc5r03. */
@@ -3569,12 +3600,12 @@ static bool
show_stats_perform_pages(const uint8_t * resp, int len,
const struct opts_t * op)
{
- int k, num, param_len, param_code, subpg_code, extra;
bool nam, spf;
+ int k, num, param_len, param_code, subpg_code, extra;
unsigned int ui;
+ uint64_t ull;
const uint8_t * bp;
const char * ccp;
- uint64_t ull;
char str[PCB_STR_LEN];
nam = op->do_name;
diff --git a/src/sg_map26.c b/src/sg_map26.c
index 7739592d..8e583d29 100644
--- a/src/sg_map26.c
+++ b/src/sg_map26.c
@@ -33,8 +33,11 @@
#include <dirent.h>
#include <libgen.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h> /* new location for major + minor */
+#ifndef major
+#include <sys/types.h>
+#endif
#include <linux/major.h>
#ifdef HAVE_CONFIG_H
@@ -42,7 +45,7 @@
#endif
#include "sg_lib.h"
-static const char * version_str = "1.14 20171006";
+static const char * version_str = "1.15 20171019";
#define ME "sg_map26: "
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 0312de55..8bc59ce8 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -29,7 +29,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.51 20171011";
+static const char * version_str = "1.52 20171020";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -140,6 +140,7 @@ usage()
" --six|-6 use MODE SENSE(6), by default uses MODE "
"SENSE(10)\n"
" --verbose|-v increase verbosity\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V output version string then exit\n\n"
"Performs a SCSI MODE SENSE (10 or 6) command. To access and "
"possibly change\nmode page fields see the sdparm utility.\n");
@@ -180,6 +181,7 @@ usage_old()
" -v verbose\n"
" -V output version string\n"
" -6 Use MODE SENSE(6), by default uses MODE SENSE(10)\n"
+ " -N|--new use new interface\n"
" -? output this usage message\n\n"
"Performs a SCSI MODE SENSE (10 or 6) command\n");
}
@@ -710,7 +712,7 @@ get_mpage_trans_tbl_size(int t_proto, int * sizep)
static const char *
find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
- int inq_byte6, int t_proto)
+ bool encserv, bool mchngr, int t_proto)
{
int k;
int num;
@@ -738,7 +740,7 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
break;
}
}
- if ((0xd != scsi_ptype) && (inq_byte6 & 0x40)) {
+ if ((0xd != scsi_ptype) && encserv) {
/* check for attached enclosure services processor */
pcdp = get_mpage_tbl_size(0xd, &num);
if (pcdp) {
@@ -751,7 +753,7 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
}
}
}
- if ((0x8 != scsi_ptype) && (inq_byte6 & 0x8)) {
+ if ((0x8 != scsi_ptype) && mchngr) {
/* check for attached medium changer device */
pcdp = get_mpage_tbl_size(0x8, &num);
if (pcdp) {
@@ -776,7 +778,7 @@ find_page_code_desc(int page_num, int subpage_num, int scsi_ptype,
}
static void
-list_page_codes(int scsi_ptype, int inq_byte6, int t_proto)
+list_page_codes(int scsi_ptype, bool encserv, bool mchngr, int t_proto)
{
int num, num_ptype, pg, spg, c, d;
bool valid_transport;
@@ -835,7 +837,7 @@ list_page_codes(int scsi_ptype, int inq_byte6, int t_proto)
if ((NULL == dp) && (NULL == pe_dp))
break;
}
- if ((0xd != scsi_ptype) && (inq_byte6 & 0x40)) {
+ if ((0xd != scsi_ptype) && encserv) {
/* check for attached enclosure services processor */
printf("\n Attached enclosure services processor\n");
dp = get_mpage_tbl_size(0xd, &num);
@@ -849,7 +851,7 @@ list_page_codes(int scsi_ptype, int inq_byte6, int t_proto)
dp = (--num <= 0) ? NULL : (dp + 1);
}
}
- if ((0x8 != scsi_ptype) && (inq_byte6 & 0x8)) {
+ if ((0x8 != scsi_ptype) && mchngr) {
/* check for attached medium changer device */
printf("\n Attached medium changer device\n");
dp = get_mpage_tbl_size(0x8, &num);
@@ -879,16 +881,19 @@ list_page_codes(int scsi_ptype, int inq_byte6, int t_proto)
}
}
+/* Returns 0 for ok, else error value */
static int
-examine_pages(int sg_fd, int inq_pdt, int inq_byte6, const struct opts_t * op)
+examine_pages(int sg_fd, int inq_pdt, bool encserv, bool mchngr,
+ const struct opts_t * op)
{
bool header_printed;
- int k, res, mresp_len, len;
- unsigned char rbuf[256];
+ int k, res, mresp_len, len, resid;
const char * cp;
+ unsigned char rbuf[256];
mresp_len = (op->do_raw || op->do_hex) ? sizeof(rbuf) : 4;
for (header_printed = false, k = 0; k < PG_CODE_MAX; ++k) {
+ resid = 0;
if (op->do_six) {
res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len,
true, op->do_verbose);
@@ -901,8 +906,8 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, const struct opts_t * op)
return res;
}
} else {
- res = sg_ll_mode_sense10(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len,
- true, op->do_verbose);
+ res = sg_ll_mode_sense10_v2(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len,
+ 0, &resid, true, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res) {
pr2serr(">>>>>> try again with a '-6' switch for a 6 byte "
"MODE SENSE command\n");
@@ -915,6 +920,15 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, const struct opts_t * op)
if (0 == res) {
len = op->do_six ? (rbuf[0] + 1) :
(sg_get_unaligned_be16(rbuf + 0) + 2);
+ if (resid > 0) {
+ mresp_len -= resid;
+ if (mresp_len < 0) {
+ pr2serr("%s: MS(10) resid=%d implies negative "
+ "response length (%d)\n", __func__,
+ resid, mresp_len);
+ return SG_LIB_WILD_RESID;
+ }
+ }
if (len > mresp_len)
len = mresp_len;
if (op->do_raw) {
@@ -929,7 +943,7 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, const struct opts_t * op)
printf("Discovered mode pages:\n");
header_printed = true;
}
- cp = find_page_code_desc(k, 0, inq_pdt, inq_byte6, -1);
+ cp = find_page_code_desc(k, 0, inq_pdt, encserv, mchngr, -1);
if (cp)
printf(" %s\n", cp);
else
@@ -958,24 +972,25 @@ static const char * pg_control_str_arr[] = {
int
main(int argc, char * argv[])
{
- int sg_fd, k, num, len, res, md_len, bd_len, page_num;
- char ebuff[EBUFF_SZ];
+ bool resp_mode6, longlba, spf;
+ bool encserv = false;
+ bool mchngr = false;
+ unsigned char uc;
+ int sg_fd, k, num, len, res, md_len, bd_len, page_num, resid;
+ int density_code_off, t_proto, inq_pdt, num_ua_pages;
+ int ret = 0;
+ int rsp_buff_size = DEF_ALLOC_LEN;
const char * descp;
+ struct opts_t * op;
unsigned char * rsp_buff = NULL;
- unsigned char def_rsp_buff[DEF_ALLOC_LEN];
unsigned char * malloc_rsp_buff = NULL;
- int rsp_buff_size = DEF_ALLOC_LEN;
- int ret = 0;
- int density_code_off, t_proto, inq_pdt, inq_byte6;
- bool resp_mode6, longlba, spf;
- int num_ua_pages;
unsigned char * bp;
- unsigned char uc;
struct sg_simple_inquiry_resp inq_out;
- char pdt_name[64];
- char b[80];
struct opts_t opts;
- struct opts_t * op;
+ char b[80];
+ unsigned char def_rsp_buff[DEF_ALLOC_LEN];
+ char ebuff[EBUFF_SZ];
+ char pdt_name[64];
op = &opts;
memset(op, 0, sizeof(opts));
@@ -996,15 +1011,16 @@ main(int argc, char * argv[])
if (op->do_list) {
if ((op->pg_code < 0) || (op->pg_code > PG_CODE_MAX)) {
printf(" Assume peripheral device type: disk\n");
- list_page_codes(0, 0, -1);
+ list_page_codes(0, false, false, -1);
} else {
printf(" peripheral device type: %s\n",
sg_get_pdt_str(op->pg_code, sizeof(pdt_name),
pdt_name));
if (op->subpg_code_given)
- list_page_codes(op->pg_code, 0, op->subpg_code);
+ list_page_codes(op->pg_code, false, false,
+ op->subpg_code);
else
- list_page_codes(op->pg_code, 0, -1);
+ list_page_codes(op->pg_code, false, false, -1);
}
return 0;
}
@@ -1067,20 +1083,21 @@ main(int argc, char * argv[])
goto finish;
}
inq_pdt = inq_out.peripheral_type;
- inq_byte6 = inq_out.byte_6;
+ encserv = !! (0x40 & inq_out.byte_6);
+ mchngr = !! (0x8 & inq_out.byte_6);
if ((0 == op->do_raw) && (op->do_hex < 3))
printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n",
inq_out.vendor, inq_out.product, inq_out.revision,
sg_get_pdt_str(inq_pdt, sizeof(pdt_name), pdt_name), inq_pdt);
if (op->do_list) {
if (op->subpg_code_given)
- list_page_codes(inq_pdt, inq_byte6, op->subpg_code);
+ list_page_codes(inq_pdt, encserv, mchngr, op->subpg_code);
else
- list_page_codes(inq_pdt, inq_byte6, -1);
+ list_page_codes(inq_pdt, encserv, mchngr, -1);
goto finish;
}
if (op->do_examine) {
- ret = examine_pages(sg_fd, inq_pdt, inq_byte6, op);
+ ret = examine_pages(sg_fd, inq_pdt, encserv, mchngr, op);
goto finish;
}
if (PG_CODE_ALL == op->pg_code) {
@@ -1104,6 +1121,7 @@ main(int argc, char * argv[])
}
memset(rsp_buff, 0, rsp_buff_size);
+ resid = 0;
if (op->do_six) {
res = sg_ll_mode_sense6(sg_fd, op->do_dbd, op->page_control,
op->pg_code, op->subpg_code, rsp_buff,
@@ -1112,10 +1130,10 @@ main(int argc, char * argv[])
pr2serr(">>>>>> try again without the '-6' switch for a 10 byte "
"MODE SENSE command\n");
} else {
- res = sg_ll_mode_sense10(sg_fd, op->do_llbaa, op->do_dbd,
- op->page_control, op->pg_code,
- op->subpg_code, rsp_buff, rsp_buff_size,
- true, op->do_verbose);
+ res = sg_ll_mode_sense10_v2(sg_fd, op->do_llbaa, op->do_dbd,
+ op->page_control, op->pg_code,
+ op->subpg_code, rsp_buff, rsp_buff_size,
+ 0, &resid, true, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res)
pr2serr(">>>>>> try again with a '-6' switch for a 6 byte MODE "
"SENSE command\n");
@@ -1173,9 +1191,23 @@ main(int argc, char * argv[])
medium_type = rsp_buff[1];
specific = rsp_buff[2];
longlba = false;
- } else {
+ } else { /* MODE SENSE(10) with resid */
+ rsp_buff_size -= resid;
+ if (rsp_buff_size < 0) {
+ pr2serr("MS(10) resid=%d implies negative response length "
+ "(%d)\n", resid, rsp_buff_size);
+ ret = SG_LIB_WILD_RESID;
+ goto finish;
+ }
+ if (rsp_buff_size < 8) {
+ pr2serr("MS(10) resid=%d implies abridged header length "
+ "(%d)\n", resid, rsp_buff_size);
+ ret = SG_LIB_WILD_RESID;
+ goto finish;
+ }
headerlen = 8;
md_len = sg_get_unaligned_be16(rsp_buff + 0) + 2;
+ md_len = (md_len < rsp_buff_size) ? md_len : rsp_buff_size;
bd_len = sg_get_unaligned_be16(rsp_buff + 6);
medium_type = rsp_buff[2];
specific = rsp_buff[3];
@@ -1286,10 +1318,11 @@ main(int argc, char * argv[])
if ((0x18 == page_num) || (0x19 == page_num)) {
t_proto = (spf ? bp[5] : bp[2]) & 0xf;
descp = find_page_code_desc(page_num, (spf ? bp[1] : 0),
- inq_pdt, inq_byte6, t_proto);
+ inq_pdt, encserv, mchngr,
+ t_proto);
} else
descp = find_page_code_desc(page_num, (spf ? bp[1] : 0),
- inq_pdt, inq_byte6, -1);
+ inq_pdt, encserv, mchngr, -1);
if (NULL == descp) {
if (spf)
snprintf(ebuff, EBUFF_SZ, "0x%x, subpage_code: 0x%x",
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 0847fd82..2d2dc5f5 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -137,6 +137,7 @@ usage()
" (def: sort by opcode (then service "
"action))\n"
" --verbose|-v increase verbosity\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
"Performs a SCSI REPORT SUPPORTED OPERATION CODES or a REPORT "
"SUPPORTED\nTASK MANAGEMENT FUNCTIONS command.\n");
@@ -170,6 +171,7 @@ usage_old()
" -u output list of operation codes as is (unsorted)\n"
" -v verbose\n"
" -V output version string\n"
+ " -N|--new use new interface\n"
" -? output this usage message\n\n"
"Performs a SCSI REPORT SUPPORTED OPERATION CODES (or a REPORT "
"TASK MANAGEMENT\nFUNCTIONS) command\n");
diff --git a/src/sg_rbuf.c b/src/sg_rbuf.c
index 3b15d26c..899618d7 100644
--- a/src/sg_rbuf.c
+++ b/src/sg_rbuf.c
@@ -110,6 +110,7 @@ usage()
" default: 200 MiB\n"
" --time|-t time the data transfer\n"
" --verbose|-v increase verbosity (more debug)\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
"Use SCSI READ BUFFER command (data or echo buffer mode, buffer "
"id 0)\nrepeatedly. This utility only works with Linux sg "
@@ -132,6 +133,7 @@ usage_old()
printf(" maximum total size is 4000 MiB\n");
printf(" -t time the data transfer\n");
printf(" -v increase verbosity (more debug)\n");
+ printf(" -N|--new use new interface\n");
printf(" -V print version string then exit\n\n");
printf("Use SCSI READ BUFFER command (data or echo buffer mode, buffer "
"id 0)\nrepeatedly. This utility only works with Linux sg "
diff --git a/src/sg_rdac.c b/src/sg_rdac.c
index 3003f5a6..79a2831d 100644
--- a/src/sg_rdac.c
+++ b/src/sg_rdac.c
@@ -29,7 +29,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.13 20171008";
+static const char * version_str = "1.14 20171021";
unsigned char mode6_hdr[] = {
0x75, /* Length */
@@ -243,7 +243,7 @@ static int fail_this_path(int fd, int lun, bool use_6_byte)
return res;
}
-static void print_rdac_mode( unsigned char *ptr, int subpg)
+static void print_rdac_mode(unsigned char *ptr, bool exp_subpg)
{
int i, k, bd_len, lun_table_len;
unsigned char * lun_table = NULL;
@@ -251,7 +251,7 @@ static void print_rdac_mode( unsigned char *ptr, int subpg)
struct rdac_expanded_page *expanded;
struct rdac_page_common *rdac_ptr = NULL;
- if (subpg == 1) {
+ if (exp_subpg) {
bd_len = ptr[7];
expanded = (struct rdac_expanded_page *)(ptr + 8 + bd_len);
rdac_ptr = &expanded->attr;
@@ -265,7 +265,7 @@ static void print_rdac_mode( unsigned char *ptr, int subpg)
lun_table_len = 32;
}
- printf("RDAC %s page\n", (subpg == 1) ? "Expanded" : "Legacy");
+ printf("RDAC %s page\n", exp_subpg ? "Expanded" : "Legacy");
printf(" Controller serial: %s\n",
rdac_ptr->current_serial);
printf(" Alternate controller serial: %s\n",
@@ -388,7 +388,7 @@ int main(int argc, char * argv[])
bool fail_all = false;
bool fail_path = false;
bool use_6_byte = false;
- int res, fd, k, lun = -1;
+ int res, fd, k, resid, len, lun = -1;
int ret = 0;
char **argptr;
char * file_name = 0;
@@ -447,6 +447,7 @@ int main(int argc, char * argv[])
} else if (fail_path) {
res = fail_this_path(fd, lun, use_6_byte);
} else {
+ resid = 0;
if (use_6_byte)
res = sg_ll_mode_sense6(fd, /* DBD */ false,
/* PC */ 0,
@@ -455,17 +456,26 @@ int main(int argc, char * argv[])
rsp_buff, 252,
true, do_verbose);
else
- res = sg_ll_mode_sense10(fd, /* llbaa */ false,
- /* DBD */ false,
- /* page control */0,
- 0x2c, 0x1 /* subpage */,
- rsp_buff, 308,
- true, do_verbose);
-
- if (!res) {
- if (do_verbose)
- dump_mode_page(rsp_buff, rsp_buff[0]);
- print_rdac_mode(rsp_buff, !use_6_byte);
+ res = sg_ll_mode_sense10_v2(fd, /* llbaa */ false,
+ /* DBD */ false,
+ /* page control */0,
+ 0x2c, 0x1 /* subpage */,
+ rsp_buff, 308, 0, &resid,
+ true, do_verbose);
+
+ if (! res) {
+ len = use_6_byte ? (rsp_buff[0] + 1) :
+ (sg_get_unaligned_be16(rsp_buff + 0) + 2);
+ if (resid > 0) {
+ len = ((308 - resid) < len) ? (308 - resid) :
+ len;
+ if (len < 2)
+ pr2serr("MS(10) residual value (%d) "
+ "a worry\n", resid);
+ }
+ if (do_verbose && (len > 1))
+ dump_mode_page(rsp_buff, len);
+ print_rdac_mode(rsp_buff, ! use_6_byte);
} else {
if (SG_LIB_CAT_INVALID_OP == res)
pr2serr(">>>>>> try again without the '-6' "
diff --git a/src/sg_read.c b/src/sg_read.c
index 2cf8212d..1eb04110 100644
--- a/src/sg_read.c
+++ b/src/sg_read.c
@@ -36,9 +36,11 @@
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
+#ifndef major
+#include <sys/types.h>
+#endif
#include <sys/mman.h>
#include <sys/time.h>
#include <linux/major.h>
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index 26b00cb5..6d78d574 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -106,6 +106,7 @@ usage()
"read-write)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n"
+ " --old|-O use old interface (use as first option)\n"
" --zbc|-z show rc_basis ZBC field (implies --16)\n\n"
"Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
@@ -134,6 +135,7 @@ usage_old()
" -R open DEVICE read-only (def: RCAP(16) read-write)\n"
" -v increase verbosity\n"
" -V print version string and exit\n"
+ " -N|--new use new interface\n"
" -z show rc_basis ZBC field (implies -16)\n\n"
"Perform a SCSI READ CAPACITY (10 or 16) command\n");
}
diff --git a/src/sg_reset.c b/src/sg_reset.c
index e9f5a7f1..36f14470 100644
--- a/src/sg_reset.c
+++ b/src/sg_reset.c
@@ -30,7 +30,7 @@
#define ME "sg_reset: "
-static const char * version_str = "0.64 20171006";
+static const char * version_str = "0.65 20171021";
#ifndef SG_SCSI_RESET
#define SG_SCSI_RESET 0x2284
@@ -57,6 +57,7 @@ static struct option long_options[] = {
{"help", no_argument, 0, 'z'},
{"host", no_argument, 0, 'H'},
{"no-esc", no_argument, 0, 'N'},
+ {"no_esc", no_argument, 0, 'N'},
{"no-escalate", no_argument, 0, 'N'},
{"target", no_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
@@ -88,7 +89,7 @@ static void
usage(int compat_mode)
{
pr2serr("Usage: sg_reset [--bus] [--device] [--help] [--host] [--no-esc] "
- "[--target]\n"
+ "[--no-escalate] [--target]\n"
" [--verbose] [--version] DEVICE\n"
" where:\n"
" --bus|-b SCSI bus reset (SPI concept), might be all "
@@ -102,6 +103,7 @@ usage(int compat_mode)
" --host|-H host (bus adapter: HBA) reset\n");
}
pr2serr(" --no-esc|-N overrides default action and only does "
+ " --no-escalate The same as --no-esc|-N"
"reset requested\n"
" --target|-t target reset. The target holds the DEVICE "
"and perhaps\n"
diff --git a/src/sg_sat_phy_event.c b/src/sg_sat_phy_event.c
index ae59a006..fe7d1aeb 100644
--- a/src/sg_sat_phy_event.c
+++ b/src/sg_sat_phy_event.c
@@ -67,6 +67,7 @@ static struct option long_options[] = {
{"len", no_argument, 0, 'l'},
{"raw", no_argument, 0, 'r'},
{"reset", no_argument, 0, 'R'},
+ {"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
diff --git a/src/sg_senddiag.c b/src/sg_senddiag.c
index 9b57a1f6..9ae3cbd7 100644
--- a/src/sg_senddiag.c
+++ b/src/sg_senddiag.c
@@ -28,7 +28,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "0.52 20171011";
+static const char * version_str = "0.53 20171021";
#define ME "sg_senddiag: "
@@ -118,6 +118,7 @@ usage()
" unit: second (def: 7200 seconds)\n"
" --uoff|-u unit offline (def: 0, only with '--test')\n"
" --verbose|-v increase verbosity\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V output version string then exit\n\n"
"Performs a SCSI SEND DIAGNOSTIC (and/or a RECEIVE DIAGNOSTIC "
"RESULTS) command\n"
@@ -151,6 +152,7 @@ usage_old()
" -uoff unit offline (def: 0, only with '-t')\n"
" -v increase verbosity (print issued SCSI cmds)\n"
" -V output version string\n"
+ " -N|--new use new interface\n"
" -? output this usage message\n\n"
"Performs a SCSI SEND DIAGNOSTIC (and/or a RECEIVE DIAGNOSTIC "
"RESULTS) command\n"
@@ -426,24 +428,32 @@ do_senddiag(int sg_fd, int sf_code, bool pf_bit, bool sf_bit,
/* Get expected extended self-test time from mode page 0xa (for '-e') */
static int
-do_modes_0a(int sg_fd, void * resp, int mx_resp_len, bool noisy, bool mode6,
+do_modes_0a(int sg_fd, void * resp, int mx_resp_len, bool mode6, bool noisy,
int verbose)
{
int res;
+ int resid = 0;
if (mode6)
res = sg_ll_mode_sense6(sg_fd, true /* dbd */, false /* pc */,
0xa /* page */, false, resp, mx_resp_len,
noisy, verbose);
else
- res = sg_ll_mode_sense10(sg_fd, false /* llbaa */, true /* dbd */,
- false, 0xa, false, resp, mx_resp_len,
- noisy, verbose);
+ res = sg_ll_mode_sense10_v2(sg_fd, false /* llbaa */, true /* dbd */,
+ false, 0xa, false, resp, mx_resp_len,
+ 0, &resid, noisy, verbose);
if (res) {
char b[80];
sg_get_category_sense_str(res, sizeof(b), b, verbose);
pr2serr("Mode sense (%s): %s\n", (mode6 ? "6" : "10"), b);
+ } else {
+ mx_resp_len -= resid;
+ if (mx_resp_len < 4) {
+ pr2serr("%s: response length (%d) too small (resid=%d)\n",
+ __func__, mx_resp_len, resid);
+ res = SG_LIB_WILD_RESID;
+ }
}
return res;
}
@@ -657,7 +667,7 @@ list_page_codes()
int
main(int argc, char * argv[])
{
- int sg_fd, k, num, rsp_len, res, rsp_buff_size, pg;
+ int sg_fd, k, num, rsp_len, res, rsp_buff_size, pg, resid;
int read_in_len = 0;
int ret = 0;
struct opts_t opts;
@@ -787,7 +797,8 @@ main(int argc, char * argv[])
goto close_fini;
}
if (op->do_extdur) {
- res = do_modes_0a(sg_fd, rsp_buff, 32, true, false, op->do_verbose);
+ res = do_modes_0a(sg_fd, rsp_buff, 32, false /* mode6 */,
+ true /* noisy */, op->do_verbose);
if (0 == res) {
/* Assume mode sense(10) response without block descriptors */
num = sg_get_unaligned_be16(rsp_buff) - 6;
@@ -817,10 +828,19 @@ main(int argc, char * argv[])
else
res = 0;
if (0 == res) {
- if (0 == sg_ll_receive_diag(sg_fd, (pg >= 0x0),
- ((pg >= 0x0) ? pg : 0), rsp_buff,
- rsp_buff_size, 1, op->do_verbose)) {
+ resid = 0;
+ if (0 == sg_ll_receive_diag_v2(sg_fd, (pg >= 0x0),
+ ((pg >= 0x0) ? pg : 0), rsp_buff,
+ rsp_buff_size, 0, &resid,
+ true, op->do_verbose)) {
+ rsp_buff_size -= resid;
+ if (rsp_buff_size < 4) {
+ pr2serr("RD resid (%d) indicates response too small "
+ "(lem=%d)\n", resid, rsp_buff_size);
+ goto err_out;
+ }
rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4;
+ rsp_len= (rsp_len < rsp_buff_size) ? rsp_len : rsp_buff_size;
if (op->do_hex > 1)
dStrHex((const char *)rsp_buff, rsp_len,
(2 == op->do_hex) ? 0 : -1);
diff --git a/src/sg_ses.c b/src/sg_ses.c
index f9bdd849..c4123d02 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -32,7 +32,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.22 20171007"; /* ses4r01 */
+static const char * version_str = "2.23 20171020"; /* ses4r01 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -46,6 +46,7 @@ static const char * version_str = "2.22 20171007"; /* ses4r01 */
/* value of 0 (would imply -20 C) reserved */
/* Send Diagnostic and Receive Diagnostic Results page codes */
+/* Sometimes referred to as "dpage"s in code comments */
#define SUPPORTED_DPC 0x0
#define CONFIGURATION_DPC 0x1
#define ENC_CONTROL_DPC 0x2
@@ -124,12 +125,12 @@ struct opts_t {
bool do_data;
bool eiioe_auto;
bool eiioe_force;
- bool ind_given;
+ bool ind_given; /* '--index=...' or '-I ...' */
bool inner_hex;
bool do_list;
bool mask_ign; /* element read-mask-modify-write actions */
bool seid_given;
- bool page_code_given;
+ bool page_code_given; /* or suitable abbreviation */
bool o_readonly;
bool do_status;
bool do_version;
@@ -140,17 +141,17 @@ struct opts_t {
int do_filter;
int do_help;
int do_hex;
+ int do_join; /* relational join of Enclosure status, Element
+ descriptor and Additional element status dpages.
+ Use twice to add Threshold in dpage to join. */
+ int do_raw;
int ind_th; /* type header index, set by build_type_desc_hdr_arr() */
int ind_indiv; /* individual element index; -1 for overall */
int ind_indiv_last; /* if > ind_indiv then [ind_indiv..ind_indiv_last] */
int ind_et_inst; /* ETs can have multiple type header instances */
- int do_join; /* relational join of Enclosure status, Element
- descriptor and Additional element status pages.
- Use twice to add Threshold in page to join. */
int maxlen;
int seid;
- int page_code;
- int do_raw;
+ int page_code; /* recognised abbreviations converted to dpage num */
int verbose;
int num_cgs; /* number of --clear-, --get= and --set= options */
int arr_len;
@@ -1227,8 +1228,8 @@ cl_process(struct opts_t *op, int argc, char *argv[])
}
}
if (NULL == ap->abbrev) {
- pr2serr("'--page' abbreviation %s not found\nHere are "
- "the choices:\n", optarg);
+ pr2serr("'--page=' argument abbreviation \"%s\" not "
+ "found\nHere are the choices:\n", optarg);
enumerate_diag_pages();
return SG_LIB_SYNTAX_ERROR;
}
@@ -1703,7 +1704,7 @@ static int
do_rec_diag(int sg_fd, int page_code, uint8_t * rsp_buff,
int rsp_buff_size, const struct opts_t * op, int * rsp_lenp)
{
- int rsp_len, res;
+ int rsp_len, res, resid;
const char * cp;
char b[80];
@@ -1719,19 +1720,27 @@ do_rec_diag(int sg_fd, int page_code, uint8_t * rsp_buff,
pr2serr(" Receive diagnostic results command for page 0x%x\n",
page_code);
}
- res = sg_ll_receive_diag(sg_fd, true /* pcv */, page_code, rsp_buff,
- rsp_buff_size, true, op->verbose);
+ res = sg_ll_receive_diag_v2(sg_fd, true /* pcv */, page_code, rsp_buff,
+ rsp_buff_size, 0, &resid, true, op->verbose);
if (0 == res) {
rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4;
if (rsp_len > rsp_buff_size) {
if (rsp_buff_size > 8) /* tried to get more than header */
- pr2serr("<<< warning response buffer too small [%d but need "
- "%d]>>>\n", rsp_buff_size, rsp_len);
- rsp_len = rsp_buff_size;
+ pr2serr("<<< warning response buffer too small [was %d but "
+ "need %d]>>>\n", rsp_buff_size, rsp_len);
+ if (resid > 0)
+ rsp_buff_size -= resid;
+ } else if (resid > 0)
+ rsp_buff_size -= resid;
+ rsp_len = (rsp_len < rsp_buff_size) ? rsp_len : rsp_buff_size;
+ if (rsp_len < 0) {
+ pr2serr("<<< warning: resid=%d too large, implies negative "
+ "reply length: %d\n", resid, rsp_len);
+ rsp_len = 0;
}
if (rsp_lenp)
*rsp_lenp = rsp_len;
- if (page_code != rsp_buff[0]) {
+ if ((rsp_len > 1) && (page_code != rsp_buff[0])) {
if ((0x9 == rsp_buff[0]) && (1 & rsp_buff[1])) {
pr2serr("Enclosure busy, try again later\n");
if (op->do_hex)
@@ -4118,6 +4127,240 @@ try_again:
return broken_ei;
}
+
+/* User output of join array */
+static void
+join_array_display(struct th_es_t * tesp, struct opts_t * op)
+{
+ bool got1, need_aes;
+ int k, j, blen, desc_len, dn_len;
+ const uint8_t * ae_bp;
+ const char * cp;
+ const uint8_t * ed_bp;
+ struct join_row_t * jrp;
+ uint8_t * t_bp;
+ char b[64];
+
+ blen = sizeof(b);
+ need_aes = (op->page_code_given &&
+ (ADD_ELEM_STATUS_DPC == op->page_code));
+ dn_len = op->desc_name ? (int)strlen(op->desc_name) : 0;
+ for (k = 0, jrp = tesp->j_base, got1 = false;
+ ((k < MX_JOIN_ROWS) && jrp->enc_statp); ++k, ++jrp) {
+ if (op->ind_given) {
+ if (op->ind_th != jrp->th_i)
+ continue;
+ if (! match_ind_indiv(jrp->indiv_i, op))
+ continue;
+ }
+ if (need_aes && (NULL == jrp->ae_statp))
+ continue;
+ ed_bp = jrp->elem_descp;
+ if (op->desc_name) {
+ if (NULL == ed_bp)
+ continue;
+ desc_len = sg_get_unaligned_be16(ed_bp + 2);
+ /* some element descriptor strings have trailing NULLs and
+ * count them in their length; adjust */
+ while (desc_len && ('\0' == ed_bp[4 + desc_len - 1]))
+ --desc_len;
+ if (desc_len != dn_len)
+ continue;
+ if (0 != strncmp(op->desc_name, (const char *)(ed_bp + 4),
+ desc_len))
+ continue;
+ } else if (op->dev_slot_num >= 0) {
+ if (op->dev_slot_num != jrp->dev_slot_num)
+ continue;
+ } else if (saddr_non_zero(op->sas_addr)) {
+ for (j = 0; j < 8; ++j) {
+ if (op->sas_addr[j] != jrp->sas_addr[j])
+ break;
+ }
+ if (j < 8)
+ continue;
+ }
+ got1 = true;
+ if ((op->do_filter > 1) && (1 != (0xf & jrp->enc_statp[0])))
+ continue; /* when '-ff' and status!=OK, skip */
+ cp = etype_str(jrp->etype, b, blen);
+ if (ed_bp) {
+ desc_len = sg_get_unaligned_be16(ed_bp + 2) + 4;
+ if (desc_len > 4)
+ printf("%.*s [%d,%d] Element type: %s\n", desc_len - 4,
+ (const char *)(ed_bp + 4), jrp->th_i,
+ jrp->indiv_i, cp);
+ else
+ printf("[%d,%d] Element type: %s\n", jrp->th_i,
+ jrp->indiv_i, cp);
+ } else
+ printf("[%d,%d] Element type: %s\n", jrp->th_i,
+ jrp->indiv_i, cp);
+ printf(" Enclosure Status:\n");
+ enc_status_helper(" ", jrp->enc_statp, jrp->etype, false, op);
+ if (jrp->ae_statp) {
+ printf(" Additional Element Status:\n");
+ ae_bp = jrp->ae_statp;
+ desc_len = ae_bp[1] + 2;
+ additional_elem_helper(" ", ae_bp, desc_len, jrp->etype,
+ tesp, op);
+ }
+ if (jrp->thresh_inp) {
+ t_bp = jrp->thresh_inp;
+ threshold_helper(" Threshold In:\n", " ", t_bp, jrp->etype,
+ op);
+ }
+ }
+ if (! got1) {
+ if (op->ind_given) {
+ printf(" >>> no match on --index=%d,%d", op->ind_th,
+ op->ind_indiv);
+ if (op->ind_indiv_last > op->ind_indiv)
+ printf("-%d\n", op->ind_indiv_last);
+ else
+ printf("\n");
+ } else if (op->desc_name)
+ printf(" >>> no match on --descriptor=%s\n", op->desc_name);
+ else if (op->dev_slot_num >= 0)
+ printf(" >>> no match on --dev-slot-name=%d\n",
+ op->dev_slot_num);
+ else if (saddr_non_zero(op->sas_addr)) {
+ printf(" >>> no match on --sas-addr=0x");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", op->sas_addr[j]);
+ printf("\n");
+ }
+ }
+}
+
+/* This is for debugging, output to stderr */
+static void
+join_array_dump(struct th_es_t * tesp, int broken_ei, struct opts_t * op)
+{
+ int k, j, blen, hex;
+ int eiioe_count = 0;
+ int eip_count = 0;
+ struct join_row_t * jrp;
+ char b[64];
+
+ blen = sizeof(b);
+ hex = op->do_hex;
+ pr2serr("Dump of join array, each line is a row. Lines start with\n");
+ pr2serr("[<element_type>: <type_hdr_index>,<elem_ind_within>]\n");
+ pr2serr("'-1' indicates overall element or not applicable.\n");
+ jrp = tesp->j_base;
+ for (k = 0; ((k < MX_JOIN_ROWS) && jrp->enc_statp); ++k, ++jrp) {
+ pr2serr("[0x%x: %d,%d] ", jrp->etype, jrp->th_i, jrp->indiv_i);
+ if (jrp->se_id > 0)
+ pr2serr("se_id=%d ", jrp->se_id);
+ pr2serr("ei_ioe,_eoe,_aess=%s", offset_str(k, hex, b, blen));
+ pr2serr(",%s", offset_str(jrp->ei_eoe, hex, b, blen));
+ pr2serr(",%s", offset_str(jrp->ei_aess, hex, b, blen));
+ pr2serr(" dsn=%s", offset_str(jrp->dev_slot_num, hex, b, blen));
+ if (op->do_join > 2) {
+ pr2serr(" sa=0x");
+ if (saddr_non_zero(jrp->sas_addr)) {
+ for (j = 0; j < 8; ++j)
+ pr2serr("%02x", jrp->sas_addr[j]);
+ } else
+ pr2serr("0");
+ }
+ if (jrp->enc_statp)
+ pr2serr(" ES+%s", offset_str(jrp->enc_statp - enc_stat_rsp,
+ hex, b, blen));
+ if (jrp->elem_descp)
+ pr2serr(" ED+%s", offset_str(jrp->elem_descp - elem_desc_rsp,
+ hex, b, blen));
+ if (jrp->ae_statp) {
+ pr2serr(" AES+%s", offset_str(jrp->ae_statp - add_elem_rsp,
+ hex, b, blen));
+ if (jrp->ae_statp[0] & 0x10) {
+ ++eip_count;
+ if (jrp->ae_statp[2] & 0x3)
+ ++eiioe_count;
+ }
+ }
+ if (jrp->thresh_inp)
+ pr2serr(" TI+%s", offset_str(jrp->thresh_inp - threshold_rsp,
+ hex, b, blen));
+ pr2serr("\n");
+ }
+ pr2serr(">> ES len=%s, ", offset_str(enc_stat_rsp_len, hex, b, blen));
+ pr2serr("ED len=%s, ", offset_str(elem_desc_rsp_len, hex, b, blen));
+ pr2serr("AES len=%s, ", offset_str(add_elem_rsp_len, hex, b, blen));
+ pr2serr("TI len=%s\n", offset_str(threshold_rsp_len, hex, b, blen));
+ pr2serr(">> join_arr elements=%s, ", offset_str(k, hex, b, blen));
+ pr2serr("eip_count=%s, ", offset_str(eip_count, hex, b, blen));
+ pr2serr("eiioe_count=%s ", offset_str(eiioe_count, hex, b, blen));
+ pr2serr("broken_ei=%d\n", (int)broken_ei);
+}
+
+/* EIIOE juggling (standards + heuristics) for join with AES page */
+static void
+join_juggle_aes(struct th_es_t * tesp, uint8_t * es_bp, const uint8_t * ed_bp,
+ uint8_t * t_bp)
+{
+ bool et_used_by_aes;
+ int k, j, eoe, ei4aess;
+ struct join_row_t * jrp;
+ const struct type_desc_hdr_t * tdhp;
+
+ jrp = tesp->j_base;
+ tdhp = tesp->th_base;
+ for (k = 0, eoe = 0, ei4aess = 0; k < tesp->num_ths; ++k, ++tdhp) {
+ jrp->th_i = k;
+ jrp->indiv_i = -1;
+ jrp->etype = tdhp->etype;
+ jrp->ei_eoe = -1;
+ et_used_by_aes = is_et_used_by_aes(tdhp->etype);
+ jrp->ei_aess = -1;
+ jrp->se_id = tdhp->se_id;
+ /* check es_bp < es_last_bp still in range */
+ jrp->enc_statp = es_bp;
+ es_bp += 4;
+ jrp->elem_descp = ed_bp;
+ if (ed_bp)
+ ed_bp += sg_get_unaligned_be16(ed_bp + 2) + 4;
+ jrp->ae_statp = NULL;
+ jrp->thresh_inp = t_bp;
+ jrp->dev_slot_num = -1;
+ /* assume sas_addr[8] zeroed since it's static file scope */
+ if (t_bp)
+ t_bp += 4;
+ ++jrp;
+ for (j = 0; j < tdhp->num_elements; ++j, ++jrp) {
+ if (jrp >= join_arr_lastp)
+ break;
+ jrp->th_i = k;
+ jrp->indiv_i = j;
+ jrp->ei_eoe = eoe++;
+ if (et_used_by_aes)
+ jrp->ei_aess = ei4aess++;
+ else
+ jrp->ei_aess = -1;
+ jrp->etype = tdhp->etype;
+ jrp->se_id = tdhp->se_id;
+ jrp->enc_statp = es_bp;
+ es_bp += 4;
+ jrp->elem_descp = ed_bp;
+ if (ed_bp)
+ ed_bp += sg_get_unaligned_be16(ed_bp + 2) + 4;
+ jrp->thresh_inp = t_bp;
+ jrp->dev_slot_num = -1;
+ /* assume sas_addr[8] zeroed since it's static file scope */
+ if (t_bp)
+ t_bp += 4;
+ jrp->ae_statp = NULL;
+ ++tesp->num_j_eoe;
+ }
+ if (jrp >= join_arr_lastp) {
+ ++k;
+ break; /* leave last row all zeros */
+ }
+ }
+ tesp->num_j_rows = jrp - tesp->j_base;
+}
+
/* Fetch Configuration, Enclosure Status, Element Descriptor, Additional
* Element Status and optionally Threshold In pages, place in static arrays.
* Collate (join) overall and individual elements into the static join_arr[].
@@ -4128,33 +4371,21 @@ try_again:
static int
join_work(int sg_fd, struct opts_t * op, bool display)
{
- int k, j, res, num_ths, eoe, desc_len, dn_len, ei4aess;
- int mlen, hex, blen, eip_count, eiioe_count;
+ bool broken_ei;
+ int j, res, num_ths, mlen;
uint32_t ref_gen_code, gen_code;
- bool broken_ei, et_used_by_aes, got1;
- struct join_row_t * jrp;
- uint8_t * es_bp;
- const uint8_t * ed_bp;
const uint8_t * ae_bp;
- uint8_t * t_bp;
- /* const uint8_t * es_last_bp; */
- /* const uint8_t * ed_last_bp; */
const uint8_t * ae_last_bp;
- /* const uint8_t * t_last_bp; */
- const char * cp;
const char * enc_state_changed = " <<state of enclosure changed, "
"please try again>>\n";
- const struct type_desc_hdr_t * tdhp;
+ uint8_t * es_bp;
+ const uint8_t * ed_bp;
+ uint8_t * t_bp;
+ struct th_es_t * tesp;
struct enclosure_info primary_info;
struct th_es_t tes;
- struct th_es_t * tesp;
- char b[64];
- eip_count = 0;
- eiioe_count = 0;
memset(&primary_info, 0, sizeof(primary_info));
- hex = op->do_hex;
- blen = sizeof(b);
num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr, MX_ELEM_HDR,
&ref_gen_code, &primary_info, op);
if (num_ths < 0)
@@ -4283,208 +4514,23 @@ join_work(int sg_fd, struct opts_t * op, bool display)
t_bp = NULL;
}
+
tesp->j_base = join_arr;
- jrp = tesp->j_base;
- tdhp = tesp->th_base;
- for (k = 0, eoe = 0, ei4aess = 0; k < num_ths; ++k, ++tdhp) {
- jrp->th_i = k;
- jrp->indiv_i = -1;
- jrp->etype = tdhp->etype;
- jrp->ei_eoe = -1;
- et_used_by_aes = is_et_used_by_aes(tdhp->etype);
- jrp->ei_aess = -1;
- jrp->se_id = tdhp->se_id;
- /* check es_bp < es_last_bp still in range */
- jrp->enc_statp = es_bp;
- es_bp += 4;
- jrp->elem_descp = ed_bp;
- if (ed_bp)
- ed_bp += sg_get_unaligned_be16(ed_bp + 2) + 4;
- jrp->ae_statp = NULL;
- jrp->thresh_inp = t_bp;
- jrp->dev_slot_num = -1;
- /* assume sas_addr[8] zeroed since it's static file scope */
- if (t_bp)
- t_bp += 4;
- ++jrp;
- for (j = 0; j < tdhp->num_elements; ++j, ++jrp) {
- if (jrp >= join_arr_lastp)
- break;
- jrp->th_i = k;
- jrp->indiv_i = j;
- jrp->ei_eoe = eoe++;
- if (et_used_by_aes)
- jrp->ei_aess = ei4aess++;
- else
- jrp->ei_aess = -1;
- jrp->etype = tdhp->etype;
- jrp->se_id = tdhp->se_id;
- jrp->enc_statp = es_bp;
- es_bp += 4;
- jrp->elem_descp = ed_bp;
- if (ed_bp)
- ed_bp += sg_get_unaligned_be16(ed_bp + 2) + 4;
- jrp->thresh_inp = t_bp;
- jrp->dev_slot_num = -1;
- /* assume sas_addr[8] zeroed since it's static file scope */
- if (t_bp)
- t_bp += 4;
- jrp->ae_statp = NULL;
- ++tesp->num_j_eoe;
- }
- if (jrp >= join_arr_lastp) {
- ++k;
- break; /* leave last row all zeros */
- }
- }
- tesp->num_j_rows = jrp - tesp->j_base;
+ join_juggle_aes(tesp, es_bp, ed_bp, t_bp);
broken_ei = false;
if (ae_bp)
broken_ei = join_aes_helper(ae_bp, ae_last_bp, tesp, op);
- if (op->verbose > 3) {
- pr2serr("Dump of join array, each line is a row. Lines start with\n");
- pr2serr("[<element_type>: <type_hdr_index>,<elem_ind_within>]\n");
- pr2serr("'-1' indicates overall element or not applicable.\n");
- jrp = tesp->j_base;
- for (k = 0; ((k < MX_JOIN_ROWS) && jrp->enc_statp); ++k, ++jrp) {
- pr2serr("[0x%x: %d,%d] ", jrp->etype, jrp->th_i, jrp->indiv_i);
- if (jrp->se_id > 0)
- pr2serr("se_id=%d ", jrp->se_id);
- pr2serr("ei_ioe,_eoe,_aess=%s", offset_str(k, hex, b, blen));
- pr2serr(",%s", offset_str(jrp->ei_eoe, hex, b, blen));
- pr2serr(",%s", offset_str(jrp->ei_aess, hex, b, blen));
- pr2serr(" dsn=%s", offset_str(jrp->dev_slot_num, hex, b, blen));
- if (op->do_join > 2) {
- pr2serr(" sa=0x");
- if (saddr_non_zero(jrp->sas_addr)) {
- for (j = 0; j < 8; ++j)
- pr2serr("%02x", jrp->sas_addr[j]);
- } else
- pr2serr("0");
- }
- if (jrp->enc_statp)
- pr2serr(" ES+%s", offset_str(jrp->enc_statp - enc_stat_rsp,
- hex, b, blen));
- if (jrp->elem_descp)
- pr2serr(" ED+%s", offset_str(jrp->elem_descp - elem_desc_rsp,
- hex, b, blen));
- if (jrp->ae_statp) {
- pr2serr(" AES+%s", offset_str(jrp->ae_statp - add_elem_rsp,
- hex, b, blen));
- if (jrp->ae_statp[0] & 0x10) {
- ++eip_count;
- if (jrp->ae_statp[2] & 0x3)
- ++eiioe_count;
- }
- }
- if (jrp->thresh_inp)
- pr2serr(" TI+%s", offset_str(jrp->thresh_inp - threshold_rsp,
- hex, b, blen));
- pr2serr("\n");
- }
- pr2serr(">> ES len=%s, ", offset_str(enc_stat_rsp_len, hex, b, blen));
- pr2serr("ED len=%s, ", offset_str(elem_desc_rsp_len, hex, b, blen));
- pr2serr("AES len=%s, ", offset_str(add_elem_rsp_len, hex, b, blen));
- pr2serr("TI len=%s\n", offset_str(threshold_rsp_len, hex, b, blen));
- pr2serr(">> join_arr elements=%s, ", offset_str(k, hex, b, blen));
- pr2serr("eip_count=%s, ", offset_str(eip_count, hex, b, blen));
- pr2serr("eiioe_count=%s ", offset_str(eiioe_count, hex, b, blen));
- pr2serr("broken_ei=%d\n", (int)broken_ei);
- }
+ if (op->verbose > 3)
+ join_array_dump(tesp, broken_ei, op);
join_done = true;
- if (! display) /* probably wanted join_arr[] built only */
- return 0;
+ if (display) /* probably wanted join_arr[] built only */
+ join_array_display(tesp, op);
- /* Display contents of join_arr */
- dn_len = op->desc_name ? (int)strlen(op->desc_name) : 0;
- for (k = 0, jrp = tesp->j_base, got1 = false;
- ((k < MX_JOIN_ROWS) && jrp->enc_statp); ++k, ++jrp) {
- if (op->ind_given) {
- if (op->ind_th != jrp->th_i)
- continue;
- if (! match_ind_indiv(jrp->indiv_i, op))
- continue;
- }
- ed_bp = jrp->elem_descp;
- if (op->desc_name) {
- if (NULL == ed_bp)
- continue;
- desc_len = sg_get_unaligned_be16(ed_bp + 2);
- /* some element descriptor strings have trailing NULLs and
- * count them in their length; adjust */
- while (desc_len && ('\0' == ed_bp[4 + desc_len - 1]))
- --desc_len;
- if (desc_len != dn_len)
- continue;
- if (0 != strncmp(op->desc_name, (const char *)(ed_bp + 4),
- desc_len))
- continue;
- } else if (op->dev_slot_num >= 0) {
- if (op->dev_slot_num != jrp->dev_slot_num)
- continue;
- } else if (saddr_non_zero(op->sas_addr)) {
- for (j = 0; j < 8; ++j) {
- if (op->sas_addr[j] != jrp->sas_addr[j])
- break;
- }
- if (j < 8)
- continue;
- }
- got1 = true;
- if ((op->do_filter > 1) && (1 != (0xf & jrp->enc_statp[0])))
- continue; /* when '-ff' and status!=OK, skip */
- cp = etype_str(jrp->etype, b, blen);
- if (ed_bp) {
- desc_len = sg_get_unaligned_be16(ed_bp + 2) + 4;
- if (desc_len > 4)
- printf("%.*s [%d,%d] Element type: %s\n", desc_len - 4,
- (const char *)(ed_bp + 4), jrp->th_i,
- jrp->indiv_i, cp);
- else
- printf("[%d,%d] Element type: %s\n", jrp->th_i,
- jrp->indiv_i, cp);
- } else
- printf("[%d,%d] Element type: %s\n", jrp->th_i,
- jrp->indiv_i, cp);
- printf(" Enclosure Status:\n");
- enc_status_helper(" ", jrp->enc_statp, jrp->etype, false, op);
- if (jrp->ae_statp) {
- printf(" Additional Element Status:\n");
- ae_bp = jrp->ae_statp;
- desc_len = ae_bp[1] + 2;
- additional_elem_helper(" ", ae_bp, desc_len, jrp->etype,
- tesp, op);
- }
- if (jrp->thresh_inp) {
- t_bp = jrp->thresh_inp;
- threshold_helper(" Threshold In:\n", " ", t_bp, jrp->etype,
- op);
- }
- }
- if (! got1) {
- if (op->ind_given) {
- printf(" >>> no match on --index=%d,%d", op->ind_th,
- op->ind_indiv);
- if (op->ind_indiv_last > op->ind_indiv)
- printf("-%d\n", op->ind_indiv_last);
- else
- printf("\n");
- } else if (op->desc_name)
- printf(" >>> no match on --descriptor=%s\n", op->desc_name);
- else if (op->dev_slot_num >= 0)
- printf(" >>> no match on --dev-slot-name=%d\n",
- op->dev_slot_num);
- else if (saddr_non_zero(op->sas_addr)) {
- printf(" >>> no match on --sas-addr=0x");
- for (j = 0; j < 8; ++j)
- printf("%02x", op->sas_addr[j]);
- printf("\n");
- }
- }
return res;
+
}
static uint64_t
diff --git a/src/sg_start.c b/src/sg_start.c
index ab3e8352..685af0de 100644
--- a/src/sg_start.c
+++ b/src/sg_start.c
@@ -113,6 +113,7 @@ usage()
"given\n"
" --stop|-S stop unit (e.g. spin down disk)\n"
" --verbose|-v increase verbosity\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
" Example: 'sg_start --stop /dev/sdb' stops unit\n"
" 'sg_start --eject /dev/scd0' stops unit and "
@@ -158,6 +159,7 @@ usage_old()
"action\n"
" --stop stop unit (same as '0')\n"
" -v verbose (print out SCSI commands)\n"
+ " -N|--new use new interface\n"
" -V print version string then exit\n\n"
" Example: 'sg_start --stop /dev/sdb' stops unit\n"
" 'sg_start --eject /dev/scd0' stops unit and "
diff --git a/src/sg_stpg.c b/src/sg_stpg.c
index 0149e46d..a79cc8b2 100644
--- a/src/sg_stpg.c
+++ b/src/sg_stpg.c
@@ -32,7 +32,7 @@
* to the given SCSI device.
*/
-static const char * version_str = "1.14 20171007";
+static const char * version_str = "1.15 20171020";
#define TGT_GRP_BUFF_LEN 1024
#define MX_ALLOC_LEN (0xc000 + 0x80)
@@ -107,7 +107,7 @@ usage()
" --help|-h print out usage message\n"
" --hex|-H print out report response in hex, then "
"exit\n"
- " --offline|-l set asymm. access state to offline, takes "
+ " --offline|-l|-O set asymm. access state to offline, takes "
"relative\n"
" target port id, rather than target port "
"group id\n"
diff --git a/src/sg_test_rwbuf.c b/src/sg_test_rwbuf.c
index d6ea3201..4e86e7c3 100644
--- a/src/sg_test_rwbuf.c
+++ b/src/sg_test_rwbuf.c
@@ -43,7 +43,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.11 20171007";
+static const char * version_str = "1.12 20171020";
#define BPI (signed)(sizeof(int))
@@ -353,17 +353,17 @@ void usage ()
" or\n"
" sg_test_rwbuf DEVICE SZ [AW] [AR]\n");
printf (" where:\n"
- " --addrd=AR extra bytes to fetch during READ "
+ " --addrd=AR|-r extra bytes to fetch during READ "
"BUFFER\n"
- " --addwr=AW extra bytes to send to WRITE BUFFER\n"
- " --help output this usage message then exit\n"
- " --quick output read buffer size then exit\n"
- " --size=SZ size of buffer (in bytes) to write "
+ " --addwr=AW|-w extra bytes to send to WRITE BUFFER\n"
+ " --help|-l output this usage message then exit\n"
+ " --quick|-q output read buffer size then exit\n"
+ " --size=SZ|-s size of buffer (in bytes) to write "
"then read back\n"
- " --times=NUM number of times to run test "
+ " --times=NUM|-t number of times to run test "
"(default 1)\n"
- " --verbose increase verbosity of output\n"
- " --version output version then exit\n");
+ " --verbose|-v increase verbosity of output\n"
+ " --version|-V output version then exit\n");
printf ("\nWARNING: If you access the device at the same time, e.g. "
"because it's a\n");
printf (" mounted hard disk, the device's buffer may be used by the "
diff --git a/src/sg_turs.c b/src/sg_turs.c
index 1ee2fb4d..f4ac2efa 100644
--- a/src/sg_turs.c
+++ b/src/sg_turs.c
@@ -88,6 +88,7 @@ usage()
" --time|-t outputs total duration and commands per "
"second\n"
" --verbose|-v increase verbosity\n"
+ " --old|-O use old interface (use as first option)\n"
" --version|-V print version string then exit\n\n"
"Performs a SCSI TEST UNIT READY command (or many of them).\n");
}
@@ -105,6 +106,7 @@ usage_old()
" -t outputs total duration and commands per "
"second\n"
" -v increase verbosity\n"
+ " -N|--new use new interface\n"
" -V print version string then exit\n\n"
"Performs a SCSI TEST UNIT READY command (or many of them).\n");
}
diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c
index 11206ace..49b4341f 100644
--- a/src/sg_xcopy.c
+++ b/src/sg_xcopy.c
@@ -47,11 +47,13 @@
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/file.h>
+#include <sys/sysmacros.h>
+#ifndef major
+#include <sys/types.h>
+#endif
#include <linux/major.h>
#include <linux/fs.h> /* <sys/mount.h> */
@@ -65,7 +67,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "0.58 20171010";
+static const char * version_str = "0.59 20171021";
#define ME "sg_xcopy: "
@@ -509,20 +511,24 @@ usage(int n_help)
primary_help:
pr2serr("Usage: "
- "sg_xcopy [bpt=BPT] [bs=BS] [cat=0|1] [count=COUNT] [dc=0|1] "
- "[ibs=BS]\n"
- " [id_usage=hold|discard|disable] [if=IFILE] "
+ "sg_xcopy [app=0|1] [bpt=BPT] [bs=BS] [cat=0|1] [conv=CONV]\n"
+ " [count=COUNT] [dc=0|1] [ibs=BS]\n"
+ " [id_usage=hold|discard|disable] [if=IFILE] "
"[iflag=FLAGS]\n"
- " [list_id=ID] [obs=BS] [of=OFILE] [oflag=FLAGS] "
- "[prio=PRIO]\n"
- " [seek=SEEK] [skip=SKIP] [time=0|1] "
- "[verbose=VERB] [--help]\n"
- " [--on_dst|--on_src] [--verbose] [--version]\n\n"
+ " [list_id=ID] [obs=BS] [of=OFILE] "
+ "[oflag=FLAGS] [prio=PRIO]\n"
+ " [seek=SEEK] [skip=SKIP] [time=0|1] "
+ "[verbose=VERB]\n"
+ " [--help] [--on_dst|--on_src] [--verbose] "
+ "[--version]\n\n"
" where:\n"
+ " app if argument is 1 then open OFILE in append "
+ "mode\n"
" bpt is blocks_per_transfer (default: 128)\n"
" bs block size (default is 512)\n");
pr2serr(" cat xcopy segment descriptor CAT bit (default: "
"0)\n"
+ " conv ignored\n"
" count number of blocks to copy (def: device size)\n"
" dc xcopy segment descriptor DC bit (default: 0)\n"
" ibs input block size (if given must be same as "
@@ -548,11 +554,11 @@ primary_help:
"throughput\n"
" verbose 0->quiet(def), 1->some noise, 2->more noise, "
"etc\n"
- " --help print out this usage message then exit\n"
+ " --help|-h print out this usage message then exit\n"
" --on_dst send XCOPY command to OFILE\n"
" --on_src send XCOPY command to IFILE\n"
- " --verbose same action as verbose=1\n"
- " --version print version information then exit\n\n"
+ " --verbose|-v same action as verbose=1\n"
+ " --version|-V print version information then exit\n\n"
"Copy from IFILE to OFILE, similar to dd command; "
"but using the SCSI\nEXTENDED COPY (XCOPY(LID1)) command. For "
"list of flags, use '-hh'.\n");
@@ -560,7 +566,7 @@ primary_help:
secondary_help:
pr2serr("FLAGS:\n"
- " append (o) ignored\n"
+ " append (o) open OFILE in append mode\n"
" excl open corresponding device with O_EXCL\n"
" flock call flock(LOCK_EX|LOCK_NB)\n"
" null does nothing, placeholder\n"
diff --git a/src/sginfo.c b/src/sginfo.c
index 309126a3..8e6f946a 100644
--- a/src/sginfo.c
+++ b/src/sginfo.c
@@ -122,7 +122,7 @@
#define _GNU_SOURCE 1
#endif
-static const char * version_str = "2.38 [20171009]";
+static const char * version_str = "2.39 [20171019]";
#include <stdio.h>
#include <string.h>
@@ -3393,7 +3393,7 @@ show_devices(int raw)
int k, j, fd, err, bus;
My_scsi_idlun m_idlun;
char name[MDEV_NAME_SZ];
- char dev_name[MDEV_NAME_SZ];
+ char dev_name[MDEV_NAME_SZ + 6];
char ebuff[EBUFF_SZ];
int do_numeric = 1;
int max_holes = MAX_HOLES;
diff --git a/src/sgm_dd.c b/src/sgm_dd.c
index 4e40acce..edf48619 100644
--- a/src/sgm_dd.c
+++ b/src/sgm_dd.c
@@ -48,11 +48,13 @@
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/mman.h>
#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/sysmacros.h>
+#ifndef major
+#include <sys/types.h>
+#endif
#include <linux/major.h>
#include <linux/fs.h> /* <sys/mount.h> */
diff --git a/src/sgp_dd.c b/src/sgp_dd.c
index 1ebecca0..be9547bd 100644
--- a/src/sgp_dd.c
+++ b/src/sgp_dd.c
@@ -43,9 +43,11 @@
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
#include <sys/ioctl.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
+#ifndef major
+#include <sys/types.h>
+#endif
#include <sys/time.h>
#include <linux/major.h>
#include <linux/fs.h> /* <sys/mount.h> */