aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-03-05 03:44:16 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-03-05 03:44:16 +0000
commitbb1ca28ae1a69909b23522bcd412244b0c8e583c (patch)
tree5df479456e4f6b4d0a0dcc203abed41f69e03ff0
parent090d6026610616895444792b75d90861b3c968f9 (diff)
downloadsg3_utils-bb1ca28ae1a69909b23522bcd412244b0c8e583c.tar.gz
sg_ses: --data=@FN with --status now decodes dpage(s) in FN; add --quiet option to suppress messages
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@758 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog7
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_ses.8349
-rw-r--r--include/sg_cmds_basic.h24
-rw-r--r--lib/sg_cmds_basic.c12
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_decode_sense.c6
-rw-r--r--src/sg_logs.c18
-rw-r--r--src/sg_modes.c18
-rw-r--r--src/sg_opcodes.c18
-rw-r--r--src/sg_raw.c6
-rw-r--r--src/sg_rbuf.c18
-rw-r--r--src/sg_readcap.c18
-rw-r--r--src/sg_seek.c6
-rw-r--r--src/sg_senddiag.c18
-rw-r--r--src/sg_ses.c958
-rw-r--r--src/sg_start.c20
-rw-r--r--src/sg_turs.c18
18 files changed, 954 insertions, 564 deletions
diff --git a/ChangeLog b/ChangeLog
index dee7229c..ca6675fd 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 [20180227] [svn: r757]
+Changelog for sg3_utils-1.43 [20180304] [svn: r758]
- sg_write_x: where x can be normal, atomic, or(write),
same, scattered, or stream writes with 16 or 32 byte
cdbs (sbc4r04 for atomic, sbc4r11 for scattered)
@@ -15,12 +15,14 @@ Changelog for sg3_utils-1.43 [20180227] [svn: r757]
- add --quick option to skip reconsideration time
- sg_decode sense: add --cdb option
- sg_ses: handle 2 bit EIIOE field in aes dpage
+ - add --quiet option to suppress messages
- expand join handling of SAS connectors and others
- expand join debug code
- allow multiple --clear=, --get= and --set= options
- allow individual index ranges (e.g. --index=3,5)
- allow --index=IIA with -ee to enumerate only fields
belonging to element type IIA
+ - --data=@FN with --status now decodes dpage(s) in FN
- add 'offset_temp' and 'rqst_override' to temperature
sensor element type
- interpret '--join --page=aes' to only display join
@@ -88,7 +90,8 @@ Changelog for sg3_utils-1.43 [20180227] [svn: r757]
- check resid and trim response if necessary
- report when --no-inquiry is ignored
- sg_raw: add --enumerate option
- - add --cmdfile=CF option
+ - add --cmdfile=CF option, permit 64 byte NVMe
+ admin commands to be sent
- add --raw option (for CF in binary)
- page align input and output buffers
- sg_get_lba_status: add --report-type= option (sbc4r12)
diff --git a/debian/changelog b/debian/changelog
index a0d2a92b..f0ea355f 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> Fri, 16 Feb 2018 17:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Sun, 04 Mar 2018 22:00:00 -0500
sg3-utils (1.42-0.1) unstable; urgency=low
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index f941c908..deaf6bac 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "January 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_SES "8" "March 2018" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -6,13 +6,13 @@ sg_ses \- access a SCSI Enclosure Services (SES) device
[\fI\-\-descriptor=DES\fR] [\fI\-\-dev\-slot\-num=SN\fR] [\fI\-\-eiioe=A_F\fR]
[\fI\-\-filter\fR] [\fI\-\-get=STR\fR] [\fI\-\-hex\fR]
[\fI\-\-index=IIA\fR | \fI\-\-index=TIA,II\fR] [\fI\-\-inner\-hex\fR]
-[\fI\-\-join\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-page=PG\fR] [\fI\-\-raw\fR]
-[\fI\-\-readonly\fR] [\fI\-\-sas\-addr=SA\fR] [\fI\-\-status\fR]
-[\fI\-\-verbose\fR] [\fI\-\-warn\fR] \fIDEVICE\fR
+[\fI\-\-join\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-page=PG\fR] [\fI\-\-quiet\fR]
+[\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-sas\-addr=SA\fR]
+[\fI\-\-status\fR] [\fI\-\-verbose\fR] [\fI\-\-warn\fR] \fIDEVICE\fR
.PP
.B sg_ses
[\fI\-\-byte1=B1\fR] [\fI\-\-clear=STR\fR] [\fI\-\-control\fR]
-[\fI\-\-data=H,H...\fR] [\fI\-\-descriptor=DES\fR]
+[\fI\-\-data=H,H...\fR] [\fI\-\-data=@FN\fR] [\fI\-\-descriptor=DES\fR]
[\fI\-\-dev\-slot\-num=SN\fR] [\fI\-\-index=IIA\fR | \fI\-\-index=TIA,II\fR]
[\fI\-\-mask\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-nickname=SEN\fR]
[\fI\-\-nickid=SEID\fR] [\fI\-\-page=PG\fR] [\fI\-\-readonly\fR]
@@ -20,6 +20,10 @@ sg_ses \- access a SCSI Enclosure Services (SES) device
\fIDEVICE\fR
.PP
.B sg_ses
+\fI\-\-data=@FN\fR \fI\-\-status\fR [\fI\-\-raw\fR \fI\-\-raw\fR]
+[<all options from first form>]
+.PP
+.B sg_ses
[\fI\-\-enumerate\fR] [\fI\-\-index=IIA\fR] [\fI\-\-list\fR] [\fI\-\-help\fR]
[\fI\-\-version\fR]
.SH DESCRIPTION
@@ -34,25 +38,31 @@ device (e.g. a disk) in which case the EncServ bit is set in its INQUIRY
response.
.PP
If the \fIDEVICE\fR argument is given with no options then the names of all
-diagnostic pages supported are listed. Most, but not necessarily all, of the
-named diagnostic pages are defined in the SES standards and drafts. The most
-recent reference for this utility is the draft SCSI Enclosure Services 4
-document T10/BSR INCITS 555 Revision 1 at http://www.t10.org . Existing
+diagnostic pages (dpages) supported are listed. Most, but not necessarily
+all, of the named dpages are defined in the SES standards and drafts. The
+most recent reference for this utility is the draft SCSI Enclosure Services
+4 document T10/BSR INCITS 555 Revision 1 at http://www.t10.org . Existing
standards for SES, SES\-2 and SES\-3 are ANSI INCITS 305\-1998 and ANSI
INCITS 448\-2008 and ANSI INCITS 518\-2017 respectively.
.PP
-The first form shown in the synopsis is for fetching and decoding pages
-or fields from the SES \fIDEVICE\fR. Alternatively a fetched page may be
+The first form shown in the synopsis is for fetching and decoding dpages
+or fields from the SES \fIDEVICE\fR. Alternatively a fetched dpage may be
output in hex or binary with the \fI\-\-hex\fR or \fI\-\-raw\fR options.
.PP
-The second form in the synopsis is for modifying pages or fields held in
+The second form in the synopsis is for modifying dpages or fields held in
the SES \fIDEVICE\fR. Changing the state of an enclosure (e.g. requesting
the "ident" (locate) LED to flash on a disk carrier in an array) is typically
done using a read\-modify\-write cycle. See the section on CHANGING STATE
below.
.PP
-The third form in the synopsis shows the options for providing command line
-help (i.e. usage information), listing out page and field information tables
+The third form in the synopsis shows the options for decoding the contents
+of a file that holds a hexadecimal or binary representation of a SES
+dpage response. Typically an earlier invocation of the first form of this
+utility with the '\-HHHH' option would have generated that file. Since no
+SCSI commands are sent, the \fIDEVICE\fR argument if given will be ignored.
+.PP
+The last form in the synopsis shows the options for providing command line
+help (i.e. usage information), listing out dpage and field information tables
held by the utility (\fI\-\-enumerate\fR), or printing the version string
of this utility.
.PP
@@ -60,19 +70,20 @@ There is a web page discussing this utility at
http://sg.danny.cz/sg/sg_ses.html . Support for downloading microcode to
a SES device has been placed in a separate utility called sg_ses_microcode.
.PP
-In the following sections "page" refers to a diagnostic page, either
-fetched with a SCSI RECEIVE DIAGNOSTIC RESULTS command or sent to the
-\fIDEVICE\fR with a SCSI SEND DIAGNOSTIC command.
+In the following sections "dpage" refers to a diagnostic page, either fetched
+with a SCSI RECEIVE DIAGNOSTIC RESULTS command, sent to the \fIDEVICE\fR with
+a SCSI SEND DIAGNOSTIC command, or fetched from data supplied by the
+\fI\-\-data=\fR option.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
The options are arranged in alphabetical order based on the long
option name.
.TP
\fB\-b\fR, \fB\-\-byte1\fR=\fIB1\fR
-some modifiable pages may need byte 1 (i.e. the second byte) set. In the
-Enclosure Control page, byte 1 contains the INFO, NON\-CRIT, CRIT and
+some modifiable dpages may need byte 1 (i.e. the second byte) set. In the
+Enclosure Control dpage, byte 1 contains the INFO, NON\-CRIT, CRIT and
UNRECOV bits. In the Subenclosure String Out, Subenclosure Nickname Control
-and Download Microcode Control pages, byte 1 is the Subenclosure identifier.
+and Download Microcode Control dpages, byte 1 is the Subenclosure identifier.
Active when the \fI\-\-control\fR and \fI\-\-data=H,H...\fR options are used
and the default value is 0. If the \fI\-\-clear=STR\fR or \fI\-\-set=STR\fR
option is used then the value read from byte 1 is written back to byte 1.
@@ -81,8 +92,8 @@ trailing 'h' or 'H').
.TP
\fB\-C\fR, \fB\-\-clear\fR=\fISTR\fR
Used to clear an element field in the Enclosure Control or Threshold Out
-page. Must be used together with an indexing option to specify which element
-is to be changed. The Enclosure Control page is assumed if the
+dpage. Must be used together with an indexing option to specify which element
+is to be changed. The Enclosure Control dpage is assumed if the
\fI\-\-page=PG\fR option is not given. See the STR FORMAT and the CLEAR, GET,
SET sections below.
.TP
@@ -91,31 +102,31 @@ will send control information to the \fIDEVICE\fR via a SCSI SEND
DIAGNOSTIC command. Cannot give both this option and \fI\-\-status\fR.
The Enclosure Control, String Out, Threshold Out, Array Control (obsolete
in SES\-2), Subenclosure String Out, Subenclosure Nickname Control and
-Download Microcode pages can be set currently. This option is assumed if
+Download Microcode dpages can be set currently. This option is assumed if
either the \fI\-\-clear=STR\fR or \fI\-\-set=STR\fR option is given.
.TP
\fB\-d\fR, \fB\-\-data\fR=\fIH,H...\fR
permits a string of comma separated (ASCII) hex bytes to be specified (limit
1024). A (single) space separated string of hex bytes is also allowed but
the list needs to be in quotes. This option allows the parameters to a
-control page to be specified. The string given should not include the first 4
-bytes (i.e. page code and length).
+control dpage to be specified. The string given should not include the first 4
+bytes (i.e. page code and length). See the DATA SUPPLIED section below.
.TP
\fB\-d\fR, \fB\-\-data\fR=\-
-reads one or more data strings from stdin, limit 2048 bytes. stdin may
-provide ASCII hex as a comma separated list (i.e. as with the
+reads one or more data strings from stdin, limit almost 2**16 bytes. stdin
+may provide ASCII hex as a comma separated list (i.e. as with the
\fI\-\-data=H,H...\fR option). Additionally spaces, tabs and line feeds are
permitted as separators from stdin . Stops reading stdin when an EOF is
-detected.
+detected. See the DATA SUPPLIED section below.
.TP
\fB\-d\fR, \fB\-\-data\fR=@\fIFN\fR
-reads one or more data strings from the file called \fIFN\fR, limit 2048
-bytes. The contents of the file is decoded in the same fashion as stdin
-described in the previous option.
+reads one or more data strings from the file called \fIFN\fR, limit almost
+2**16 bytes. The contents of the file is decoded in the same fashion as
+stdin described in the previous option. See the DATA SUPPLIED section below.
.TP
\fB\-D\fR, \fB\-\-descriptor\fR=\fIDES\fR
where \fIDES\fR is a descriptor name (string) as found in the Element
-Descriptor page. This is a medium level indexing alternative to the low
+Descriptor dpage. This is a medium level indexing alternative to the low
level \fI\-\-index=\fR options. If the descriptor name contains a space then
\fIDES\fR needs to be surrounded by quotes (single or double) or the space
escaped (e.g. preceded by a backslash). See the DESCRIPTOR NAME, DEVICE SLOT
@@ -123,7 +134,7 @@ NUMBER AND SAS ADDRESS section below.
.TP
\fB\-x\fR, \fB\-\-dev\-slot\-num\fR=\fISN\fR, \fB\-\-dsn\fR=\fISN\fR
where \fISN\fR is a device slot number found in the Additional Element Status
-page. Only entries for FCP and SAS devices (with EIP=1) have device slot
+dpage. Only entries for FCP and SAS devices (with EIP=1) have device slot
numbers. \fISN\fR must be a number in the range 0 to 255 (inclusive). 255 is
used to indicate there is no corresponding device slot. This is a medium level
indexing alternative to the low level \fI\-\-index=\fR options. See the
@@ -132,11 +143,11 @@ DESCRIPTOR NAME, DEVICE SLOT NUMBER AND SAS ADDRESS section below.
\fB\-E\fR, \fB\-\-eiioe\fR=\fIA_F\fR
\fIA_F\fR is either the string 'auto' or 'force'. There was some fuzziness
in the interpretation of the 'element index' field in the Additional Element
-Status (AES) page between SES\-2 and SES\-3. The EIIOE bit was introduced to
+Status (AES) dpage between SES\-2 and SES\-3. The EIIOE bit was introduced to
resolve the problem but not all enclosures have caught up. In the SES\-3
revision 12 draft the EIIOE bit was expanded to a 2 bit EIIOE field.
-Using '\-\-eiioe=force' will decode the AES page as if the EIIOE field is set
-to 1. Using '\-\-eiioe=auto' will decode the AES page as if the EIIOE field
+Using '\-\-eiioe=force' will decode the AES dpage as if the EIIOE field is set
+to 1. Using '\-\-eiioe=auto' will decode the AES dpage as if the EIIOE field
is set to 1 if the first AES descriptor has its EIP bit set and its element
index field is 1 (in other words a heuristic to guess whether the EIIOE field
should be set to 1 or 0).
@@ -145,33 +156,33 @@ If the enclosure sets the actual EIIOE field to 1 or more then this option has
no effect. It is recommended that HP JBOD users set \-\-eiioe=auto .
.TP
\fB\-e\fR, \fB\-\-enumerate\fR
-enumerate all known page names and SES elements when this option is given
+enumerate all known dpage names and SES elements when this option is given
once.
.br
If \fI\-\-enumerate\fR is given twice, then the recognised acronyms for the
\fI\-\-clear=STR\fR, \fI\-\-get=STR\fR and \fI\-\-set=STR\fR options are
-listed. The utility exits after listing this information (so most other
-options and \fIDEVICE\fR are ignored). Since there are many acronyms for
-the Enclosure Control/Status page then the output can be further restricted
+listed. The utility exits after listing this information, so most other
+options and \fIDEVICE\fR are ignored. Since there are many acronyms for
+the Enclosure Control/Status dpage then the output can be further restricted
by giving the \fI\-\-index=IIA\fR option (e.g. "sg_ses \-ee \-I ts" to only
-show the acronyms associated with the Enclosure Control/Status page's
+show the acronyms associated with the Enclosure Control/Status dpage's
Temperature Sensor Element Type).
.TP
\fB\-f\fR, \fB\-\-filter\fR
-cuts down on the amount of output from the Enclosure Status page and the
-Additional Element Status page. When this option is given, any line which
+cuts down on the amount of output from the Enclosure Status dpage and the
+Additional Element Status dpage. When this option is given, any line which
has all its binary flags cleared (i.e. 0) is filtered out (i.e. ignored).
If a line has some other value on it (e.g. a temperature) then it is output.
When this option is used twice only elements associated with the "status=ok"
-field (in the Enclosure status page) are output. The \fI\-\-filter\fR option
+field (in the Enclosure status dpage) are output. The \fI\-\-filter\fR option
is useful for reducing the amount of output generated by the \fI\-\-join\fR
option.
.TP
\fB\-G\fR, \fB\-\-get\fR=\fISTR\fR
Used to read a field in a status element. Must be used together with a an
indexing option to specify which element is to be read. By default the
-Enclosure Status page is read, the only other pages that can be read are the
-Threshold In and Additional Element Status pages. If a value is found it is
+Enclosure Status dpage is read, the only other dpages that can be read are the
+Threshold In and Additional Element Status dpages. If a value is found it is
output in decimal to stdout (by default) or in hexadecimal preceded by "0x"
if the \fI\-\-hex\fR option is also given. See the STR FORMAT and the CLEAR,
GET, SET sections below.
@@ -188,14 +199,23 @@ If the \fI\-\-get=STR\fR option is given then output the value found (if
any) in hexadecimal, with a leading "0x". Otherwise output the response
in hexadecimal; with trailing ASCII if given once, without it if given
twice, and simple hex if given three or more times. Ignored when all
-elements from several pages are being accessed (e.g. when the \fI\-\-join\fR
+elements from several dpages are being accessed (e.g. when the \fI\-\-join\fR
option is used). Also see the \fI\-\-raw\fR option which may be used
with this option.
+.br
+To dump one of more dpage responses to stdout in ASCII parsable hexadecimal
+use \fI-HHH\fR or \fI-HHHH\fR. The triple H form only outputs hexadecimals
+which is fine for a single dpage response. When all dpages are dumped (e.g.
+with \fI\-\-page=all\fR) then the quad H form adds the name of each dpage
+following a hash mark ('#'). The \fI\-\-data=\fR option parser ignores
+everything from and including a hash mark to the end of the line. Hence the
+output of the quad H form is still parsable plus it is easier to users to
+view and possibly edit.
.TP
\fB\-I\fR, \fB\-\-index\fR=\fIIIA\fR
where \fIIIA\fR is either an individual index (II) or an Element type
abbreviation (A). See the INDEXES section below. If the \fI\-\-page=PG\fR
-option is not given then the Enclosure Status (or Control) page is assumed.
+option is not given then the Enclosure Status (or Control) dpage is assumed.
May be used with the \fI\-\-join\fR option or one of the \fI\-\-clear=STR\fR,
\fI\-\-get=STR\fR or \fI\-\-set=STR\fR options. To enumerate the available
Element type abbreviations use the \fI\-\-enumerate\fR option.
@@ -204,30 +224,30 @@ Element type abbreviations use the \fI\-\-enumerate\fR option.
where \fITIA,II\fR is an type header index (TI) or Element type
abbreviation (A) followed by an individual index (II). See the INDEXES section
below. If the \fI\-\-page=PG\fR option is not given then the Enclosure
-Status (or Control) page is assumed. May be used with the \fI\-\-join\fR
+Status (or Control) dpage is assumed. May be used with the \fI\-\-join\fR
option or one of the \fI\-\-clear=STR\fR, \fI\-\-get=STR\fR or
\fI\-\-set=STR\fR options. To enumerate the available Element type
abbreviations use the \fI\-\-enumerate\fR option.
.TP
\fB\-i\fR, \fB\-\-inner\-hex\fR
-the outer levels of a status page are decoded and printed out but the
+the outer levels of a status dpage are decoded and printed out but the
innermost level (e.g. the Element Status Descriptor) is output in hex. Also
-active with the Additional Element Status and Threshold In pages. Can be
+active with the Additional Element Status and Threshold In dpages. Can be
used with an indexing option and/or \fI\-\-join\fR options.
.TP
\fB\-j\fR, \fB\-\-join\fR
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.
-.PP
+Element Status dpages. If this option is given twice then elements from the
+Threshold In dpage are also grouped. The order is dictated by the Configuration
+dpage.
+.br
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
+rows that don't have a "aes" dpage component. See the INDEXES and DESCRIPTOR
NAME, DEVICE SLOT NUMBER AND SAS ADDRESS sections below.
.TP
\fB\-l\fR, \fB\-\-list\fR
@@ -265,20 +285,37 @@ Subenclosure identifier. The default value is 0 which is the
main enclosure.
.TP
\fB\-p\fR, \fB\-\-page\fR=\fIPG\fR
-where \fIPG\fR is a page abbreviation or code (a number). If \fIPG\fR
+where \fIPG\fR is a dpage abbreviation or code (a number). If \fIPG\fR
starts with a digit it is assumed to be in decimal unless prefixed by
0x for hex. Valid range is 0 to 255 (0x0 to 0xff) inclusive. Default is
-page 'sdp' which is page_code 0 (i.e. "Supported Diagnostic Pages") if
+dpage 'sdp' which is page_code 0 (i.e. "Supported Diagnostic Pages") if
no other options are given.
.br
-To list the available page abbreviations give "xxx" for \fIPG\fR; the same
+Page code 0xff or abbreviation "all" is not a real dpage (as the highest
+real dpage is 0x3f) but instead causes all dpages whose page code is 0x2f
+or less to be output. This can be used with either the \fI\-HHHH\fR or
+\fI\-rr\fR to send either hexadecimal ASCII or binary respectively to
+stdout.
+.br
+To list the available dpage abbreviations give "xxx" for \fIPG\fR; the same
information can also be found with the \fI\-\-enumerate\fR option.
.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+this suppresses the number of warnings and messages output. The exit status
+of the utility is unaffected by this option.
+.TP
\fB\-r\fR, \fB\-\-raw\fR
-outputs the chosen status page in ASCII hex in a format suitable for a
-later invocation using the \fI\-\-data=\fR option. A page less its first
+outputs the chosen status dpage in ASCII hex in a format suitable for a
+later invocation using the \fI\-\-data=\fR option. A dpage less its first
4 bytes (page code and length) is output. When used twice (e.g. \fI\-rr\fR)
-the full page contents is output in binary to stdout.
+the full dpage contents is output in binary to stdout.
+.br
+when \fI\-rr\fR is used together with the \fI\-\-data=\-\fR or
+\fI\-\-data=FN\fR then stdin or file FN is decoded as a binary stream that
+continues to be read until an end of file (EOF). Once that data is read then
+the internal raw option is cleared to 0 so the output is not effected. So
+the \fI\-rr\fR option either changes how the input or output is treated,
+but not both.
.TP
\fB\-R\fR, \fB\-\-readonly\fR
open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
@@ -286,7 +323,7 @@ The default is to open it read\-write.
.TP
\fB\-A\fR, \fB\-\-sas\-addr\fR=\fISA\fR
this is an indexing method for SAS end devices (e.g. SAS disks). The utility
-will try to find the element or slot in the Additional Element Status page
+will try to find the element or slot in the Additional Element Status dpage
whose SAS address matches \fISA\fR. For a SAS disk or tape that SAS address
is its target port identifier for the port connected to that element or slot.
Most SAS disks and tapes have two such target ports, usually numbered
@@ -303,15 +340,19 @@ leading '0x' or '0X' or a trailing 'h' or 'H'. This option is a medium level
See the DESCRIPTOR NAME, DEVICE SLOT NUMBER AND SAS ADDRESS section below.
.TP
\fB\-S\fR, \fB\-\-set\fR=\fISTR\fR
-Used to set an element field in the Enclosure Control or Threshold Out page.
+Used to set an element field in the Enclosure Control or Threshold Out dpage.
Must be used together with an indexing option to specify which element is to
-be changed. The Enclosure Control page is assumed if the \fI\-\-page=PG\fR
+be changed. The Enclosure Control dpage is assumed if the \fI\-\-page=PG\fR
option is not given. See the STR FORMAT and CLEAR, GET, SET sections below.
.TP
\fB\-s\fR, \fB\-\-status\fR
-will fetch page from the \fIDEVICE\fR via a SCSI RECEIVE DIAGNOSTIC RESULTS
-command. In the absence of other options that imply modifying a page (e.g.
-\fI\-\-control\fR or \fI\-\-set=STR\fR) then \fI\-\-status\fR is assumed.
+will fetch dpage from the \fIDEVICE\fR via a SCSI RECEIVE DIAGNOSTIC RESULTS
+command (or from \fI\-\-data=@FN\fR). In the absence of other options that
+imply modifying a dpage (e.g. \fI\-\-control\fR or \fI\-\-set=STR\fR) then
+\fI\-\-status\fR is assumed, except when the \fI\-\-data=\fR option is given.
+When the \fI\-\-data=\fR option is given there is no default action: either
+the \fI\-\-control\fR or this option must be given to distinguish between
+the two different ways that data will be treated.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity. For example when this option is given four
@@ -324,42 +365,42 @@ print the version string and then exit.
.TP
\fB\-w\fR, \fB\-\-warn\fR
warn about certain irregularities with warnings sent to stderr. The join
-is a complex operation that relies on information from several pages to be
+is a complex operation that relies on information from several dpages to be
synchronized. The quality of SES devices vary and to be fair, the
descriptions from T10 drafts and standards have been tweaked several
times (see the EIIOE field) in order to clear up confusion.
.SH INDEXES
An enclosure can have information about its disk and tape drives plus other
-supporting components like power supplies spread across several pages.
-Addressing a specific element (overall or individual) within a page is
+supporting components like power supplies spread across several dpages.
+Addressing a specific element (overall or individual) within a dpage is
complicated. This section describes low level indexing (i.e. choosing a
single element (or a group of related elements) from a large number of
elements). If available, the medium level indexing described in the
following section (DESCRIPTOR NAME, DEVICE SLOT NUMBER AND SAS ADDRESS)
might be simpler to use.
.PP
-The Configuration page is key to low level indexing: it contains a list
+The Configuration dpage is key to low level indexing: it contains a list
of "type headers", each of which contains an Element type (e.g. Array
Device Slot), a Subenclosure identifier (0 for the primary enclosure) and
a "Number of possible elements". Corresponding to each type header, the
-Enclosure Status page has one "overall" element plus "Number of possible
+Enclosure Status dpage has one "overall" element plus "Number of possible
elements" individual elements all of which have the given Element type. For
some Element types the "Number of possible elements" will be 0 so the
-Enclosure Status page has only one "overall" element corresponding to that
-type header. The Element Descriptor page and the Threshold (In and Out)
-pages follow the same pattern as the Enclosure Status page.
+Enclosure Status dpage has only one "overall" element corresponding to that
+type header. The Element Descriptor dpage and the Threshold (In and Out)
+dpages follow the same pattern as the Enclosure Status dpage.
.PP
The numeric index corresponding to the overall element is "\-1". If the
-Configuration page indicates a particular element type has "n" elements
+Configuration dpage indicates a particular element type has "n" elements
and n is greater than 0 then its indexes range from 0 to n\-1 .
.PP
-The Additional Element Status page is a bit more complicated. It has
+The Additional Element Status dpage is a bit more complicated. It has
entries for "Number of possible elements" of certain Element types. It
does not have entries corresponding to the "overall" elements. To make
-the correspondence a little clearer each descriptor in this page optionally
+the correspondence a little clearer each descriptor in this dpage optionally
contains an "Element Index Present" (EIP) indicator. If EIP is set then each
element's "Element Index" field refers to the position of the corresponding
-element in the Enclosure Status page.
+element in the Enclosure Status dpage.
.PP
Addressing a single overall element or a single individual element is done
with two indexes: TI and II. Both are origin 0. TI=0 corresponds to the
@@ -391,7 +432,7 @@ For example these are equivalent: \fI\-\-index=arr\fR and
\fI\-\-index=_23\fR since the Array Device Slot Element type value is 23.
Also \fI\-\-index=ps1\fR and \fI\-\-index=_2_1\fR are equivalent.
.PP
-Another example: if the first type header in the Configuration page has
+Another example: if the first type header in the Configuration dpage has
has Array Device Slot Element type then \fI\-\-index=0,\-1\fR is
equivalent to \fI\-\-index=arr\fR. Also \fI\-\-index=arr,3\fR is equivalent
to \fI\-\-index=3\fR.
@@ -406,13 +447,13 @@ The three options: \fI\-\-descriptor=DES\fR, \fI\-\-dev\-slot\-num=SN\fR
and \fI\-\-sas\-addr=SA\fR allow medium level indexing, as an alternative
to the low level \fI\-\-index=\fR options. Only one of the three options
can be used in an invocation. Each of the three options implicitly set the
-\fI\-\-join\fR option since they need either the Element Descriptor page or
-the Additional Element Status page as well as the pages needed by the
+\fI\-\-join\fR option since they need either the Element Descriptor dpage
+or the Additional Element Status dpage as well as the dpages needed by the
\fI\-\-index=\fR option.
.PP
These medium level indexing options need support from the SES device and
that support is optional. For example the \fI\-\-descriptor=DES\fR needs
-the Element Descriptor page provided by the SES device however that is
+the Element Descriptor dpage provided by the SES device however that is
optional. Also the provided descriptor names need to be useful, and having
descriptor names which are all "0" is not very useful. Also some
elements (e.g. overall elements) may not have descriptor names.
@@ -452,30 +493,72 @@ The supported list of <acronym>s can be viewed by using the
.SH CLEAR, GET, SET
The \fI\-\-clear=STR\fR, \fI\-\-get=STR\fR and \fI\-\-set=STR\fR options can
be used up to 8 times in the same invocation. Any <acronym>s used in the
-\fISTR\fR operands must refer to the same diagnostic page.
+\fISTR\fR operands must refer to the same dpage.
.PP
When multiple of these options are used, they are applied in the order in
which they appear on the command line. So if options contradict each other,
the last one appearing on the command line will be enforced. When there
are multiple \fI\-\-clear=STR\fR and \fI\-\-set=STR\fR options, then the
-diagnostic page they refer to is only written after the last one.
+dpage they refer to is only written after the last one.
+.SH DATA SUPPLIED
+This section describes the two scenarios that can occur when the
+\fI\-\-data=\fR option is given. These scenarios are the same irrespective
+of whether the argument to the \fI\-\-data=\fR option is a string of
+hex bytes on the command line, stdin (indicated by \fI\-\-data=\-\fR) or
+names a file (e.g. \fI\-\-data=@thresh_in_dpage.hex\fR).
+.PP
+The first scenario is flagged by the \fI\-\-control\fR option. It uses the
+supplied data to build a 'control' dpage that will be sent to the
+\fIDEVICE\fR. The supplied dpage data should not include its first 4 bytes.
+Those 4 bytes are added by this utility using the \fI\-\-page=PG\fR option
+with \fIPG\fR placed at byte offset 0). The \fI\-\-byte1=B1\fR option sets
+byte offset 1, else 0 is placed in that position. The number of bytes
+decoded from the data provided (i.e. its length) goes into byte offsets 2
+and 3.
+.PP
+The second scenario is flagged by the \fI\-\-status\fR option. It decodes
+the supplied data assuming that it represents the response to one or more
+SCSI SEND DIAGNOSTIC commands. Those responses have typically been captured
+from some earlier invocation(s) of this utility. Those earlier invocations
+could use the '\-HHH' or '\-HHHH' option and file redirection to capture
+that response (or responses) in hexadecimal. The supplied dpage response
+data is decoded according to the other command line options. For example
+the \fI\-\-join\fR option could be given and that would require the data
+from multiple dpages typically: Configuration, Enclosure status, Element
+descriptor and Additional element status dpages.
+.PP
+By default the user supplied data is assumed to be ASCII hexadecimal in
+lines that don't exceed 512 characters. Anything on a line from and
+including a hash mark ('#') to the end of line is ignored. An end of
+line can be a LF or CR,LF and blank lines are ignored. Each separated
+pair (or single) hexadecimal digits represent a byte (and neither a
+leading '0x' nor a trailing 'h' should be given). Separators are either
+space, tab, comma or end of line.
+.PP
+Alternatively binary can be used and this is flagged by the '\-rr' option.
+The \fI\-\-data=H,H...\fR form cannot use binary values for the 'H's, only
+ASCII hexadecimal. The other two forms (\fI\-\-data=\-\fR and
+\fI\-\-data=@FN\fR) may contain binary data. Note that when the '\-rr'
+option is used with \fI\-\-data=@FN\fR that it only changes the
+interpretation of the input data, it does not change the decoding and output
+representation.
.SH CHANGING STATE
This utility has various techniques for changing the state of a SES device.
As noted above this is typically a read\-modify\-write type operation.
-Most modifiable pages have a "status" (or "in") page that can be read, and
-a corresponding "control" (or "out") page that can be written back to change
+Most modifiable dpages have a "status" (or "in") page that can be read, and
+a corresponding "control" (or "out") dpage that can be written back to change
the state of the enclosure.
.PP
The lower level technique provided by this utility involves outputting
-a "status" page in hex with \fI\-\-raw\fR. Then a text editor can be used
+a "status" dpage in hex with \fI\-\-raw\fR. Then a text editor can be used
to edit the hex (note: to change an Enclosure Control descriptor the SELECT
-bit needs to be set). Next the control page data can fed back with the
+bit needs to be set). Next the control dpage data can fed back with the
\fI\-\-data=H,H...\fR option together with the \fI\-\-control\fR option;
the \fI\-\-byte1=B1\fR option may need to be given as well.
.PP
-Changes to the Enclosure Control page (and the Threshold Out page) can be
-done at a higher level. This involves choosing a page (the default in this
-case is the Enclosure Control page). Next choose an individual or overall
+Changes to the Enclosure Control dpage (and the Threshold Out dpage) can be
+done at a higher level. This involves choosing a dpage (the default in this
+case is the Enclosure Control dpage). Next choose an individual or overall
element index (or name it with its Element Descriptor string). Then give
the element's name (e.g. "ident" for RQST IDENT) or its position within that
element (e.g. in an Array Device Slot Control element RQST IDENT is byte 2,
@@ -483,10 +566,10 @@ bit 1 and 1 bit long ("2:1:1")). Finally a value can be given, if not the
value for \fI\-\-set=STR\fR defaults to 1 and for \fI\-\-clear=STR\fR
defaults to 0.
.SH SETTING SUBENCLOSURE NICKNAME
-The format of the Subenclosure Nickname control page is different from its
-corresponding status page. The status page reports all Subenclosure
+The format of the Subenclosure Nickname control dpage is different from its
+corresponding status dpage. The status dpage reports all Subenclosure
Nicknames (and Subenclosure identifier 0 is the main enclosure) while the
-control page allows only one of them to be changed. Therefore using the
+control dpage allows only one of them to be changed. Therefore using the
\fB\-\-data\fR option technique to change a Subenclosure nickname is
difficult (but still possible).
.PP
@@ -500,36 +583,36 @@ the \fI\-\-page=PG\fR option is not given then \fI\-\-page=snic\fR is
assumed.
.PP
When \fI\-\-nickname=SEN\fR is given then the Subenclosure Nickname Status
-page is read to obtain the Generation Code field. That Generation Code
+dpage is read to obtain the Generation Code field. That Generation Code
together with no more than 32 bytes from the Nickname (\fISEN\fR) and the
Subenclosure Identifier (\fISEID\fR) are written to the Subenclosure Nickname
-Control page.
+Control dpage.
.PP
There is an example of changing a nickname in the EXAMPLES section below.
.SH NVME ENCLOSURES
Support has been added to sg_ses (actually, its underlying library) for
NVMe (also known as NVM Express) Enclosures. It can be considered
-experimental in sg3_utils package version 1.43 and sg_ses version 2.31 .
+experimental in sg3_utils package version 1.43 and sg_ses version 2.34 .
.PP
This support is based on a decision by NVME-MI (Management Interface)
-developers to support the SES\-3 standard. This was done using the newly
-added SES Send and SES Receive commands that tunnel diagnostic page
-contents as used by SES.
+developers to support the SES\-3 standard. This was facilitated by adding
+NVME-MI SES Send and SES Receive commands that tunnel dpage contents as
+used by SES.
.SH NOTES
-This utility can be used to fetch arbitrary (i.e. non SES) diagnostic
-pages (using the SCSI READ DIAGNOSTIC command). To this end the
-\fI\-\-page=PG\fR and \fI\-\-hex\fR options would be appropriate. Arbitrary
-diagnostic pages can be sent to a device with the sg_senddiag utility.
+This utility can be used to fetch arbitrary (i.e. non SES) dpages (using
+the SCSI READ DIAGNOSTIC command). To this end the \fI\-\-page=PG\fR and
+\fI\-\-hex\fR options would be appropriate. No-SES dpages can be sent to
+a device with the sg_senddiag utility.
.PP
The most troublesome part of the join operation is associating Additional
Element Status descriptors correctly. At least one SES device vendor has
-misinterpreted the SES\-2 standard with its "element index" field. The
-code in this utility interprets the "element index" field as per the SES\-2
-standard and if that yields an inappropriate Element type, adjusts its
-indexing to follow that vendor's misinterpretation. The SES\-3 drafts have
-introduced the EIIOE (element index includes overall elements) bit which
-later became a 2 bit field to resolve this ambiguity. See the
-\fI\-\-eiioe=A_F\fR option.
+misinterpreted the SES\-2 standard, specifically with its "element index"
+field interpretation. The code in this utility interprets the "element
+index" field as per the SES\-2 standard and if that yields an inappropriate
+Element type, adjusts its indexing to follow that vendor's
+misinterpretation. The SES\-3 drafts have introduced the EIIOE (Element
+Index Includes Overall Elements) bit which later became a 2 bit field to
+resolve this ambiguity. See the \fI\-\-eiioe=A_F\fR option.
.PP
In draft SES\-3 revision 5 the "Door Lock" element name was changed to
the "Door" (and an OPEN field was added to the status element). As a
@@ -547,25 +630,25 @@ Examples can also be found at http://sg.danny.cz/sg/sg_ses.html
The following examples use Linux device names. For suitable device names
in other supported Operating Systems see the sg3_utils(8) man page.
.PP
-To view the supported pages:
+To view the supported dpages:
.PP
sg_ses /dev/bsg/6:0:2:0
.PP
-To view the Configuration Diagnostic page:
+To view the Configuration Diagnostic dpage:
.PP
sg_ses \-\-page=cf /dev/bsg/6:0:2:0
.PP
-To view the Enclosure Status page:
+To view the Enclosure Status dpage:
.PP
sg_ses \-\-page=es /dev/bsg/6:0:2:0
.PP
To get the (attached) SAS address of that device (which is held in the
-Additional Element Sense page (page 10)) printed on hex:
+Additional Element Sense dpage (dpage 10)) printed on hex:
.PP
sg_ses \-p aes \-D ArrayDevice07 \-G at_sas_addr \-H /dev/sg3
.PP
To collate the information in the Enclosure Status, Element Descriptor
-and Additional Element Status pages the \fI\-\-join\fR option can be used:
+and Additional Element Status dpages the \fI\-\-join\fR option can be used:
.PP
sg_ses \-\-join /dev/sg3
.PP
@@ -574,16 +657,16 @@ much information add the \fI\-\-filter\fR option:
.PP
sg_ses \-\-join \-\-filter /dev/sg3
.PP
-Fields in the various elements of the Enclosure Control and Threshold pages
+Fields in the various elements of the Enclosure Control and Threshold dpages
can be changed with the \fI\-\-clear=STR\fR and \fI\-\-set=STR\fR
-options. [All modifiable pages can be changed with the \fI\-\-raw\fR and
+options. [All modifiable dpages can be changed with the \fI\-\-raw\fR and
\fI\-\-data=H,H...\fR options.] The following example looks at making
the "ident" LED (also called "locate") flash on "ArrayDevice07" which is a
disk (or more precisely the carrier drawer the disk is in):
.PP
sg_ses \-\-index=7 \-\-set=2:1:1 /dev/sg3
.PP
-If the Element Descriptor diagnostic page shows that "ArrayDevice07" is
+If the Element Descriptor diagnostic dpage shows that "ArrayDevice07" is
the descriptor name associated with element index 7 then this invocation
is equivalent to the previous one:
.PP
@@ -604,15 +687,15 @@ The above assumes the descriptor name 'ArrayDevice07' corresponds to device
slot number 7.
.PP
Now for an example of a more general but lower level technique for changing
-a modifiable diagnostic page. The String (In and Out) diagnostics page is
-relatively simple (compared with the Enclosure Status/Control page). However
+a modifiable diagnostic dpage. The String (In and Out) diagnostics dpage is
+relatively simple (compared with the Enclosure Status/Control dpage). However
the use of this lower level technique is awkward involving three steps: read,
-modify then write. First check the current String (In) page contents:
+modify then write. First check the current String (In) dpage contents:
.PP
sg_ses \-\-page=str /dev/bsg/6:0:2:0
.PP
Now the "read" step. The following command will send the contents of the
-String page (from byte 4 onwards) to stdout. The output will be in ASCII
+String dpage (from byte 4 onwards) to stdout. The output will be in ASCII
hex with pairs of hex digits representing a byte, 16 pairs per line,
space separated. The redirection puts stdout in a file called "t":
.PP
@@ -624,7 +707,7 @@ device with:
.PP
sg_ses \-\-page=str \-\-control \-\-data=\- /dev/bsg/6:0:2:0 < t
.PP
-If the above is successful, the String page should have been changed. To
+If the above is successful, the String dpage should have been changed. To
check try:
.PP
sg_ses \-\-page=str /dev/bsg/6:0:2:0
@@ -632,6 +715,20 @@ check try:
To change the nickname on the main enclosure:
.PP
sg_ses \-\-nickname='1st enclosure' \-\-control /dev/bsg/6:0:2:0
+.PP
+To capture the whole state of an enclosure (from a SES perspective) for
+later analysis, this can be done:
+.PP
+ sg_ses \-\-page=all \-HHHH /dev/sg5 > enc_sg5_all.hex
+.PP
+Note that if there are errors or warnings they will be sent to stderr so
+they will appear on the command line (since only stdout is redirected).
+A text editor could be used to inspect enc_sg5_all.hex . If all looks in
+order at some later time, potentially on a different machine where
+enc_sg5_all.hex has been copied, a "join" could be done. Note that join
+reflects the state of the enclosure when the capture was done.
+.PP
+ sg_ses \-\-data=@enc_sg5_all.hex \-\-status \-\-join
.SH EXIT STATUS
The exit status of sg_ses is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
diff --git a/include/sg_cmds_basic.h b/include/sg_cmds_basic.h
index 12b8771c..672b3ead 100644
--- a/include/sg_cmds_basic.h
+++ b/include/sg_cmds_basic.h
@@ -32,21 +32,21 @@ extern "C" {
/* Invokes a SCSI INQUIRY command and yields the response
* Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb,
- * SG_LIB_CAT_ABORTED_COMMAND, -1 -> other errors */
+ * SG_LIB_CAT_ABORTED_COMMAND, a negated errno or -1 -> other errors */
int sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
int mx_resp_len, bool noisy, int verbose);
/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
- * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
- * The CMDDT field is obsolete in the INQUIRY cdb (since spc3r16 in 2003) so
- * an argument to set it has been removed (use the REPORT SUPPORTED OPERATION
- * CODES command instead). 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 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. */
+ * successful, various SG_LIB_CAT_* positive values, negated error or -1
+ * for other errors. The CMDDT field is obsolete in the INQUIRY cdb (since
+ * spc3r16 in 2003) so * an argument to set it has been removed (use the
+ * REPORT SUPPORTED OPERATION CODES command instead). 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 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_inquiry_v2(int sg_fd, bool evpd, int pg_op, void * resp,
int mx_resp_len, int timeout_secs, int * residp,
@@ -216,7 +216,7 @@ struct sg_simple_inquiry_resp {
/* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response.
* Returns 0 when successful, SG_LIB_CAT_INVALID_OP -> not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND,
- * -1 -> other errors */
+ * a negated errno or -1 -> other errors */
int sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
bool noisy, int verbose);
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 36a3d4dd..a31d1834 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -36,7 +36,7 @@
#endif
-static const char * const version_str = "1.84 20180219";
+static const char * const version_str = "1.85 20180302";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -333,6 +333,8 @@ create_pt_obj(const char * cname)
static const char * const inquiry_s = "inquiry";
+/* Returns 0 on success, while positive values are SG_LIB_CAT_* errors
+ * (e.g. SG_LIB_CAT_MALFORMED). If OS error, returns negated errno or -1. */
static int
sg_ll_inquiry_com(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
int mx_resp_len, int timeout_secs, int * residp,
@@ -414,8 +416,8 @@ sg_ll_inquiry_com(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
}
/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
- * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
- * The CMDDT field is obsolete in the INQUIRY cdb. */
+ * successful, various SG_LIB_CAT_* positive values, negated errno or
+ * -1 -> other errors. The CMDDT field is obsolete in the INQUIRY cdb. */
int
sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
int mx_resp_len, bool noisy, int verbose)
@@ -425,8 +427,8 @@ sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
}
/* Yields most of first 36 bytes of a standard INQUIRY (evpd==0) response.
- * Returns 0 when successful, various SG_LIB_CAT_* positive values or
- * -1 -> other errors */
+ * Returns 0 when successful, various SG_LIB_CAT_* positive values, negated
+ * errno or -1 -> other errors */
int
sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
bool noisy, int verbose)
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 48634d49..cd6294dd 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Fri Feb 16 2018 - dgilbert at interlog dot com
+* Sun Mar 04 2018 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.43
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index c5ded466..2a4532f6 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -28,7 +28,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "1.14 20180219";
+static const char * version_str = "1.15 20180302";
#define MAX_SENSE_LEN 1024 /* max descriptor format actually: 256+8 */
@@ -110,7 +110,7 @@ usage()
}
static int
-process_cl(struct opts_t *op, int argc, char *argv[])
+parse_cmd_line(struct opts_t *op, int argc, char *argv[])
{
int c;
unsigned int ui;
@@ -418,7 +418,7 @@ main(int argc, char *argv[])
op = &opts;
memset(op, 0, sizeof(opts));
memset(b, 0, sizeof(b));
- ret = process_cl(op, argc, argv);
+ ret = parse_cmd_line(op, argc, argv);
if (ret != 0) {
usage();
return ret;
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 034630d1..699cb41f 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -34,7 +34,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.61 20180218"; /* spc5r19 + sbc4r11 */
+static const char * version_str = "1.62 20180302"; /* spc5r19 + sbc4r11 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -885,7 +885,7 @@ usage_for(int hval, const struct opts_t * op)
/* Processes command line options according to new option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n;
@@ -1063,7 +1063,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
/* Processes command line options according to old option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen, num, n;
@@ -1294,7 +1294,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
* of these options is detected (when processing the other format), processing
* stops and is restarted using the other format. Clear? */
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -1302,14 +1302,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (0 == op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -6698,7 +6698,7 @@ main(int argc, char * argv[])
op->dev_pdt = -1;
op->vend_prod_num = VP_NONE;
op->deduced_vpn = VP_NONE;
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 322b016e..675e5539 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.56 20180219";
+static const char * version_str = "1.57 20180302";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -199,7 +199,7 @@ usage_for(const struct opts_t * op)
/* Processes command line options according to new option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n, nn;
char * cp;
@@ -335,7 +335,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
/* Processes command line options according to old option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen, num, n;
@@ -484,7 +484,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
* of these options is detected (when processing the other format), processing
* stops and is restarted using the other format. Clear? */
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -492,14 +492,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (! op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -997,7 +997,7 @@ main(int argc, char * argv[])
op = &opts;
memset(op, 0, sizeof(opts));
op->pg_code = -1;
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 183397c1..fc1e583e 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -30,7 +30,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.55 20180219"; /* spc5r14 */
+static const char * version_str = "0.56 20180302"; /* spc5r14 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -309,7 +309,7 @@ do_rstmf(int sg_fd, bool repd, void * resp, int mx_resp_len,
}
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n;
char * cp;
@@ -449,7 +449,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen, n, num;
@@ -564,7 +564,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -572,14 +572,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (! op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -921,7 +921,7 @@ main(int argc, char * argv[])
memset(op, 0, sizeof(opts));
op->opcode = -1;
op->servact = -1;
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 73f61e02..9dee2852 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -37,7 +37,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.23 (2018-02-16)"
+#define SG_RAW_VERSION "0.4.24 (2018-03-02)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -343,7 +343,7 @@ bad:
}
static int
-process_cl(struct opts_t * op, int argc, char *argv[])
+parse_cmd_line(struct opts_t * op, int argc, char *argv[])
{
while (1) {
int c, n;
@@ -667,7 +667,7 @@ main(int argc, char *argv[])
op = &opts;
memset(op, 0, sizeof(opts));
op->timeout = DEFAULT_TIMEOUT;
- ret = process_cl(op, argc, argv);
+ ret = parse_cmd_line(op, argc, argv);
if (ret != 0) {
usage();
goto done;
diff --git a/src/sg_rbuf.c b/src/sg_rbuf.c
index c06b1652..2bc14d4b 100644
--- a/src/sg_rbuf.c
+++ b/src/sg_rbuf.c
@@ -57,7 +57,7 @@
#endif
-static const char * version_str = "5.02 20180219";
+static const char * version_str = "5.03 20180302";
static struct option long_options[] = {
{"buffer", required_argument, 0, 'b'},
@@ -150,7 +150,7 @@ usage_for(const struct opts_t * optsp)
}
static int
-process_cl_new(struct opts_t * optsp, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * optsp, int argc, char * argv[])
{
int c, n;
int64_t nn;
@@ -236,7 +236,7 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * optsp, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * optsp, int argc, char * argv[])
{
bool jmp_out;
int k, plen, num;
@@ -328,7 +328,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * optsp, int argc, char * argv[])
+parse_cmd_line(struct opts_t * optsp, int argc, char * argv[])
{
int res;
char * cp;
@@ -336,14 +336,14 @@ process_cl(struct opts_t * optsp, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
optsp->opt_new = false;
- res = process_cl_old(optsp, argc, argv);
+ res = old_parse_cmd_line(optsp, argc, argv);
if ((0 == res) && optsp->opt_new)
- res = process_cl_new(optsp, argc, argv);
+ res = new_parse_cmd_line(optsp, argc, argv);
} else {
optsp->opt_new = true;
- res = process_cl_new(optsp, argc, argv);
+ res = new_parse_cmd_line(optsp, argc, argv);
if ((0 == res) && (! optsp->opt_new))
- res = process_cl_old(optsp, argc, argv);
+ res = old_parse_cmd_line(optsp, argc, argv);
}
return res;
}
@@ -378,7 +378,7 @@ main(int argc, char * argv[])
#endif
op = &opts;
memset(op, 0, sizeof(opts));
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index bf556fde..9b5a6850 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -34,7 +34,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "3.99 20180219";
+static const char * version_str = "4.00 20180302";
#define ME "sg_readcap: "
@@ -151,7 +151,7 @@ usage_for(const struct opts_t * op)
}
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c;
int a_one = 0;
@@ -246,7 +246,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen, num;
@@ -348,7 +348,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -356,14 +356,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (! op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -413,7 +413,7 @@ main(int argc, char * argv[])
op = &opts;
memset(op, 0, sizeof(opts));
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_seek.c b/src/sg_seek.c
index 5dcfe0ba..cf5bc5cb 100644
--- a/src/sg_seek.c
+++ b/src/sg_seek.c
@@ -47,7 +47,7 @@
* to that LBA ...
*/
-static const char * version_str = "1.02 20180222";
+static const char * version_str = "1.03 20180304";
#define BACKGROUND_CONTROL_SA 0x15
@@ -136,7 +136,7 @@ main(int argc, char * argv[])
bool prefetch = false;
bool readonly = false;
bool start_tm_valid = false;
- int sg_fd, res, c, err;
+ int sg_fd, res, c;
int first_err = 0;
int last_err = 0;
int ret = 0;
@@ -326,6 +326,8 @@ main(int argc, char * argv[])
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
if ((count > 0) && start_tm_valid &&
(start_tm.tv_sec || start_tm.tv_nsec)) {
+ int err;
+
res = clock_gettime(CLOCK_MONOTONIC, &end_tm);
if (res < 0) {
err = errno;
diff --git a/src/sg_senddiag.c b/src/sg_senddiag.c
index e8614b3a..936ea247 100644
--- a/src/sg_senddiag.c
+++ b/src/sg_senddiag.c
@@ -31,7 +31,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "0.58 20180217";
+static const char * version_str = "0.59 20180302";
#define ME "sg_senddiag: "
@@ -163,7 +163,7 @@ usage_old()
}
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n;
@@ -275,7 +275,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen, num, n;
@@ -389,7 +389,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -397,14 +397,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (! op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -685,7 +685,7 @@ main(int argc, char * argv[])
memset(op, 0, sizeof(opts));
op->maxlen = DEF_ALLOC_LEN;
op->page_code = -1;
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 87046170..390566f8 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -14,6 +14,8 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
@@ -36,14 +38,18 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.32 20180217"; /* ses4r02 */
+static const char * version_str = "2.34 20180304"; /* ses4r02 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
-#define MX_DATA_IN 2048
+#define DATA_IN_OFF 4
+#define MIN_DATA_IN_SZ 8192 /* use max(MIN_DATA_IN_SZ, op->maxlen) for
+ * the size of data_arr */
+#define MX_DATA_IN_LINES (16 * 1024)
#define MX_JOIN_ROWS 260 /* element index fields in dpages are only 8
* bit, and index 0xff (255) is sometimes used
* for 'not applicable' */
+#define MX_DATA_IN_DESCS 32
#define NUM_ACTIVE_ET_AESP_ARR 32
#define TEMPERAT_OFF 20 /* 8 bits represents -19 C to +235 C */
@@ -66,9 +72,10 @@ static const char * version_str = "2.32 20180217"; /* ses4r02 */
#define ADD_ELEM_STATUS_DPC 0xa
#define SUBENC_HELP_TEXT_DPC 0xb
#define SUBENC_STRING_DPC 0xc
-#define SUPPORTED_SES_DPC 0xd
+#define SUPPORTED_SES_DPC 0xd /* should be 0x1 <= dpc <= 0x2f */
#define DOWNLOAD_MICROCODE_DPC 0xe
#define SUBENC_NICKNAME_DPC 0xf
+#define ALL_DPC 0xff
/* Element Type codes */
#define UNSPECIFIED_ETC 0x0
@@ -124,24 +131,25 @@ struct cgs_cl_t {
};
struct opts_t {
- bool byte1_given;
- bool do_control;
- bool do_data;
- bool eiioe_auto;
+ bool byte1_given; /* true if -b B1 or --byte1=B1 given */
+ bool do_control; /* want to write to DEVICE */
+ bool do_data; /* flag if --data= option has been used */
+ bool do_list;
+ bool do_status; /* want to read from DEVICE (or user data) */
+ bool do_version;
+ bool eiioe_auto; /* Element Index Includes Overall (status) Element */
bool eiioe_force;
bool ind_given; /* '--index=...' or '-I ...' */
bool inner_hex;
- bool do_list;
+ bool many_dpages; /* user supplied data has more than one dpage */
bool mask_ign; /* element read-mask-modify-write actions */
- bool seid_given;
- bool page_code_given; /* or suitable abbreviation */
bool o_readonly;
- bool do_status;
- bool do_version;
+ bool page_code_given; /* or suitable abbreviation */
+ bool quiet; /* exit status unaltered by --quiet */
+ bool seid_given;
bool warn;
- int byte1;
+ int byte1; /* (origin 0 so second byte) in Control dpage */
int dev_slot_num;
- int enumerate;
int do_filter;
int do_help;
int do_hex;
@@ -149,6 +157,7 @@ struct opts_t {
descriptor and Additional element status dpages.
Use twice to add Threshold in dpage to join. */
int do_raw;
+ int enumerate;
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] */
@@ -158,16 +167,17 @@ struct opts_t {
int page_code; /* recognised abbreviations converted to dpage num */
int verbose;
int num_cgs; /* number of --clear-, --get= and --set= options */
- int arr_len;
- uint8_t sas_addr[8];
+ int mx_arr_len; /* allocated size of data_arr */
+ int arr_len; /* valid bytes in data_arr */
uint8_t * data_arr;
uint8_t * free_data_arr;
const char * desc_name;
const char * dev_name;
+ const struct element_type_t * ind_etp;
const char * index_str;
const char * nickname_str;
- const struct element_type_t * ind_etp;
struct cgs_cl_t cgs_cl_arr[CGS_CL_ARR_MAX_SZ];
+ uint8_t sas_addr[8];
};
struct diag_page_code {
@@ -270,8 +280,15 @@ struct enclosure_info {
uint8_t product_rev_level[4]; /* may differ from INQUIRY response */
};
+/* When --status is given with --data= the file contents may contain more
+ * than one dpage to be decoded. */
+struct data_in_desc_t {
+ bool in_use;
+ int page_code;
+ int offset; /* byte offset from op->data_arr + DATA_IN_OFF */
+ int dp_len; /* byte length of this diagnostic page */
+};
-static struct type_desc_hdr_t type_desc_hdr_arr[MX_ELEM_HDR];
/* Join array has four "element index"ing stategies:
* [1] based on all descriptors in the Enclosure Status (ES) dpage
@@ -319,6 +336,14 @@ static struct join_row_t join_arr[MX_JOIN_ROWS];
static struct join_row_t * join_arr_lastp = join_arr + MX_JOIN_ROWS - 1;
static bool join_done = false;
+static struct type_desc_hdr_t type_desc_hdr_arr[MX_ELEM_HDR];
+static int type_desc_hdr_count = 0;
+static uint8_t * config_dp_resp = NULL;
+static uint8_t * free_config_dp_resp = NULL;
+static int config_dp_resp_len;
+
+static struct data_in_desc_t data_in_desc_arr[MX_DATA_IN_DESCS];
+
/* Large buffers on heap, aligned to page size and zeroed */
static uint8_t * enc_stat_rsp;
static uint8_t * elem_desc_rsp;
@@ -358,6 +383,7 @@ static struct diag_page_code dpc_arr[] = {
{0x40, "Translate Address (SBC)"},
{0x41, "Device Status (SBC)"},
{0x42, "Rebuild Assist (SBC)"}, /* sbc3r31 */
+ {ALL_DPC, "All SES diagnostic pages output (sg_ses)"},
{-1, NULL},
};
@@ -414,6 +440,7 @@ static struct diag_page_code out_dpc_arr[] = {
static struct diag_page_abbrev dp_abbrev[] = {
{"ac", ARRAY_CONTROL_DPC},
{"aes", ADD_ELEM_STATUS_DPC},
+ {"all", ALL_DPC},
{"as", ARRAY_STATUS_DPC},
{"cf", CONFIGURATION_DPC},
{"dm", DOWNLOAD_MICROCODE_DPC},
@@ -430,7 +457,7 @@ static struct diag_page_abbrev dp_abbrev[] = {
{"sstr", SUBENC_STRING_DPC},
{"str", STRING_DPC},
{"th", THRESHOLD_DPC},
- {NULL, -1},
+ {NULL, -999},
};
/* Names of element types used by the Enclosure Control/Status diagnostic
@@ -727,6 +754,7 @@ static struct option long_options[] = {
{"mask", required_argument, 0, 'M'},
{"maxlen", required_argument, 0, 'm'},
{"page", required_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
{"sas-addr", required_argument, 0, 'A'},
@@ -771,24 +799,25 @@ static uint8_t ses3_element_cmask_arr[NUM_ETC][4] = {
};
-static int read_hex(const char * inp, uint8_t * arr, int * arr_len,
- int verb);
+static int read_hex(const char * inp, uint8_t * arr, int mx_arr_len,
+ int * arr_len, bool in_hex, int verb);
static int strcase_eq(const char * s1p, const char * s2p);
static void enumerate_diag_pages(void);
static bool saddr_non_zero(const uint8_t * bp);
+static const char * find_in_diag_page_desc(int page_num);
static void
usage(int help_num)
{
- if (help_num < 2) {
+ if (2 != help_num) {
pr2serr(
"Usage: sg_ses [--descriptor=DES] [--dev-slot-num=SN] "
"[--eiioe=A_F]\n"
" [--filter] [--get=STR] [--hex] "
"[--index=IIA | =TIA,II]\n"
" [--inner-hex] [--join] [--maxlen=LEN] "
- "[--page=PG]\n"
+ "[--page=PG] [--quiet]\n"
" [--raw] [--readonly] [--sas-addr=SA] [--status] "
"[--verbose]\n"
" [--warn] DEVICE\n\n"
@@ -801,20 +830,24 @@ usage(int help_num)
" [--page=PG] [--sas-addr=SA] [--set=STR] "
"[--verbose]\n"
" DEVICE\n\n"
+ " sg_ses --data=@FN --status [-rr] [<most options from "
+ "first form>]\n\n"
" sg_ses [--enumerate] [--help] [--index=IIA] [--list] "
"[--version]\n\n"
);
- if (help_num < 1) {
+ if ((help_num < 1) || (help_num > 2)) {
pr2serr("Or the corresponding short option usage: \n"
" sg_ses [-D DES] [-x SN] [-E A_F] [-f] [-G STR] [-H] "
"[-I IIA|TIA,II] [-i]\n"
- " [-j] [-m LEN] [-p PG] [-r] [-R] [-A SA] [-s] "
- "[-v] [-w] DEVICE\n\n"
+ " [-j] [-m LEN] [-p PG] [-q] [-r] [-R] [-A SA] "
+ "[-s] [-v] [-w] DEVICE\n\n"
" sg_ses [-b B1] [-C STR] [-c] [-d H,H...] [-D DES] "
"[-x SN] [-I IIA|TIA,II]\n"
" [-M] [-m LEN] [-N SEID] [-n SEN] [-p PG] "
"[-A SA] [-S STR]\n"
" [-v] DEVICE\n\n"
+ " sg_ses -d @FN -s [-rr] [<most options from first "
+ "form>]\n\n"
" sg_ses [-e] [-h] [-I IIA] [-l] [-V]\n"
);
pr2serr("\nFor help use with '-h' one or more times\n");
@@ -874,8 +907,10 @@ usage(int help_num)
" where the remaining sg_ses options are:\n"
" --byte1=B1|-b B1 byte 1 (2nd byte) of control page set "
"to B1\n"
- " --data=H,H...|-d H,H... string of ASCII hex bytes for "
- "control pages\n"
+ " --data=H,H...|-d H,H... string of ASCII hex bytes to "
+ "send as a\n"
+ " control page or decode as a "
+ "status page\n"
" --data=- | -d - fetch string of ASCII hex bytes from "
"stdin\n"
" --data=@FN | -d @FN fetch string of ASCII hex bytes from "
@@ -903,6 +938,7 @@ usage(int help_num)
" used to specify which nickname to "
"change\n"
" --nickname=SEN|-n SEN SEN is new subenclosure nickname\n"
+ " --quiet|-q suppress some output messages\n"
" --raw|-r print status page in ASCII hex suitable "
"for '-d';\n"
" when used twice outputs page in binary "
@@ -950,7 +986,7 @@ parse_index(struct opts_t *op)
else {
n = sg_get_num_nomult(cp + 1);
if ((n < 0) || (n > 255)) {
- pr2serr("bad argument to '--index', after comma expect "
+ pr2serr("bad argument to '--index=', after comma expect "
"number from -1 to 255\n");
return SG_LIB_SYNTAX_ERROR;
}
@@ -1080,7 +1116,7 @@ parse_index(struct opts_t *op)
static int
parse_cmd_line(struct opts_t *op, int argc, char *argv[])
{
- int c, j, n, ret;
+ int c, j, n, d_len, ret;
const char * data_arg = NULL;
uint64_t saddr;
const char * cp;
@@ -1089,7 +1125,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
int option_index = 0;
bool ff;
- c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:Mp:rRs"
+ c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:Mp:qrRs"
"S:vVwx:", long_options, &option_index);
if (c == -1)
break;
@@ -1100,7 +1136,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
if ((strlen(optarg) > 2) && ('X' == toupper(optarg[1])))
cp = optarg + 2;
if (1 != sscanf(cp, "%" SCNx64 "", &saddr)) {
- pr2serr("bad argument to '--sas-addr'\n");
+ pr2serr("bad argument to '--sas-addr=SA'\n");
return SG_LIB_SYNTAX_ERROR;
}
for (j = 7, ff = true; j >= 0; --j) {
@@ -1110,14 +1146,15 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
saddr >>= 8;
}
if (ff) {
- pr2serr("error decoding '--sas-addr=' argument\n");
+ pr2serr("error decoding '--sas-addr=SA' argument\n");
return SG_LIB_SYNTAX_ERROR;
}
break;
case 'b':
op->byte1 = sg_get_num_nomult(optarg);
if ((op->byte1 < 0) || (op->byte1 > 255)) {
- pr2serr("bad argument to '--byte1' (0 to 255 inclusive)\n");
+ pr2serr("bad argument to '--byte1=B1' (0 to 255 "
+ "inclusive)\n");
return SG_LIB_SYNTAX_ERROR;
}
op->byte1_given = true;
@@ -1209,7 +1246,8 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
case 'N':
op->seid = sg_get_num_nomult(optarg);
if ((op->seid < 0) || (op->seid > 255)) {
- pr2serr("bad argument to '--nick_id' (0 to 255 inclusive)\n");
+ pr2serr("bad argument to '--nickid=SEID' (0 to 255 "
+ "inclusive)\n");
return SG_LIB_SYNTAX_ERROR;
}
op->seid_given = true;
@@ -1217,14 +1255,14 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
case 'm':
n = sg_get_num(optarg);
if ((n < 0) || (n > 65535)) {
- pr2serr("bad argument to '--maxlen' (0 to 65535 inclusive "
- "expected)\n");
+ pr2serr("bad argument to '--maxlen=LEN' (0 to 65535 "
+ "inclusive expected)\n");
return SG_LIB_SYNTAX_ERROR;
}
if (0 == n)
op->maxlen = MX_ALLOC_LEN;
else if (n < 4)
- pr2serr("Warning: --maxlen= less than 4 ignored\n");
+ pr2serr("Warning: --maxlen=LEN less than 4 ignored\n");
else
op->maxlen = n;
break;
@@ -1235,7 +1273,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
if (isdigit(optarg[0])) {
op->page_code = sg_get_num_nomult(optarg);
if ((op->page_code < 0) || (op->page_code > 255)) {
- pr2serr("bad argument to '--page' (0 to 255 "
+ pr2serr("bad argument to '--page=PG' (0 to 255 "
"inclusive)\n");
return SG_LIB_SYNTAX_ERROR;
}
@@ -1249,7 +1287,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
}
}
if (NULL == ap->abbrev) {
- pr2serr("'--page=' argument abbreviation \"%s\" not "
+ pr2serr("'--page=PG' argument abbreviation \"%s\" not "
"found\nHere are the choices:\n", optarg);
enumerate_diag_pages();
return SG_LIB_SYNTAX_ERROR;
@@ -1257,6 +1295,9 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
}
op->page_code_given = true;
break;
+ case 'q':
+ op->quiet = true;
+ break;
case 'r':
++op->do_raw;
break;
@@ -1317,11 +1358,68 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
goto err_help;
}
}
+ op->mx_arr_len = (op->maxlen > MIN_DATA_IN_SZ) ? op->maxlen :
+ MIN_DATA_IN_SZ;
+ op->data_arr = sg_memalign(op->mx_arr_len, 0 /* page aligned */,
+ &op->free_data_arr, false);
+ if (NULL == op->data_arr) {
+ pr2serr("unable to allocate %u bytes on heap\n", op->mx_arr_len);
+ return sg_convert_errno(ENOMEM);
+ }
if (data_arg) {
- if (read_hex(data_arg, op->data_arr + 4, &op->arr_len, op->verbose)) {
- pr2serr("bad argument to '--data'\n");
+ if (read_hex(data_arg, op->data_arr + DATA_IN_OFF,
+ op->mx_arr_len - DATA_IN_OFF, &op->arr_len,
+ (op->do_raw < 2), op->verbose)) {
+ pr2serr("bad argument, expect '--data=H,H...', '--data=-' or "
+ "'--data=@FN'\n");
return SG_LIB_SYNTAX_ERROR;
}
+ op->do_raw = 0;
+ if (op->arr_len > 3) {
+ int off;
+ int pc = 0;
+ const uint8_t * bp = op->data_arr + DATA_IN_OFF;
+ struct data_in_desc_t * didp = data_in_desc_arr;
+
+ d_len = sg_get_unaligned_be16(bp + 2) + 4;
+ for (n = 0, off = 0; n < MX_DATA_IN_DESCS; ++n, ++didp) {
+ didp->in_use = true;
+ pc = bp[0];
+ didp->page_code = pc;
+ didp->offset = off;
+ didp->dp_len = d_len;
+ off += d_len;
+ if ((off + 3) < op->arr_len) {
+ bp += d_len;
+ d_len = sg_get_unaligned_be16(bp + 2) + 4;
+ } else {
+ ++n;
+ break;
+ }
+ }
+ if (n > 1)
+ op->many_dpages = true;
+ else if (1 == n) {
+ op->page_code_given = true;
+ op->page_code = pc;
+ } else {
+ pr2serr("No dpage found --data= argument\n");
+ goto err_help;
+ }
+ if (op->verbose > 3) {
+ int k;
+ char b[128];
+
+ for (didp = data_in_desc_arr, k = 0; k < n; ++k, ++didp) {
+ if ((cp = find_in_diag_page_desc(didp->page_code)))
+ snprintf(b, sizeof(b), "%s dpage", cp);
+ else
+ snprintf(b, sizeof(b), "dpage 0x%x", didp->page_code);
+ pr2serr("%s found, offset %d, dp_len=%d\n", b,
+ didp->offset, didp->dp_len);
+ }
+ }
+ }
}
if (op->do_join && op->do_control) {
pr2serr("cannot have '--join' and '--control'\n");
@@ -1345,7 +1443,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
saddr_non_zero(op->sas_addr)) > 1) {
pr2serr("can only have one of --descriptor, "
"--dev-slot-num and --sas-addr\n");
- return SG_LIB_SYNTAX_ERROR;
+ goto err_help;
}
if ((0 == op->do_join) && (! op->do_control) &&
(0 == op->num_cgs) && (! op->page_code_given)) {
@@ -1365,6 +1463,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
}
if (op->do_list || op->enumerate)
return 0;
+
if (op->do_control && op->do_status) {
pr2serr("cannot have both '--control' and '--status'\n");
goto err_help;
@@ -1375,26 +1474,36 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
pr2serr("need to give '--data' in control mode\n");
goto err_help;
}
- } else if (! op->do_status)
+ } else if (! op->do_status) {
+ if (op->do_data) {
+ pr2serr("when user data given, require '--control' or "
+ "'--status' option\n");
+ goto err_help;
+ }
op->do_status = true; /* default to receiving status pages */
+ } else if (op->do_status && op->do_data && op->dev_name) {
+ pr2serr(">>> Warning: device name (%s) will be ignored\n",
+ op->dev_name);
+ op->dev_name = NULL; /* quash device name */
+ }
if (op->nickname_str) {
if (! op->do_control) {
pr2serr("since '--nickname=' implies control mode, require "
"'--control' as well\n");
- return SG_LIB_SYNTAX_ERROR;
+ goto err_help;
}
if (op->page_code_given) {
if (SUBENC_NICKNAME_DPC != op->page_code) {
pr2serr("since '--nickname=' assume or expect "
"'--page=snic'\n");
- return SG_LIB_SYNTAX_ERROR;
+ goto err_help;
}
} else
op->page_code = SUBENC_NICKNAME_DPC;
} else if (op->seid_given) {
pr2serr("'--nickid=' must be used together with '--nickname='\n");
- return SG_LIB_SYNTAX_ERROR;
+ goto err_help;
}
if ((op->verbose > 4) && saddr_non_zero(op->sas_addr)) {
@@ -1404,15 +1513,17 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
pr2serr("\n");
}
- if (NULL == op->dev_name) {
+ if ((! (op->do_data && op->do_status)) && (NULL == op->dev_name)) {
pr2serr("missing DEVICE name!\n");
goto err_help;
}
return 0;
err_help:
- pr2serr("\n");
- usage(0);
+ if (op->verbose) {
+ pr2serr("\n");
+ usage(0);
+ }
return SG_LIB_SYNTAX_ERROR;
}
@@ -1531,9 +1642,10 @@ match_last_ind_indiv(int index, const struct opts_t * op)
/* Return of 0 -> success, SG_LIB_CAT_* positive values or -1 -> other
* failures */
static int
-do_senddiag(int sg_fd, bool pf_bit, void * outgoing_pg, int outgoing_len,
- bool noisy, int verbose)
+do_senddiag(int sg_fd, void * outgoing_pg, int outgoing_len, bool noisy,
+ int verbose)
{
+ const bool pf_bit = true;
const char * cp;
int page_num;
@@ -1717,31 +1829,76 @@ find_join_row_cnst(const struct th_es_t * tesp, int index,
}
}
-/* Return of 0 -> success, SG_LIB_CAT_* positive values or -1 -> other
- * failures */
+/* Return of 0 -> success, SG_LIB_CAT_* positive values or -2 if response
+ * had bad format, -1 -> other failures */
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_buff_size, struct opts_t * op, int * rsp_lenp)
{
- int rsp_len, res, resid;
+ int k, d_len, rsp_len, res;
+ int resid = 0;
+ int vb = op->verbose;
const char * cp;
char b[80];
+ char bb[120];
+ static const char * rdr = "Receive diagnostic results";
memset(rsp_buff, 0, rsp_buff_size);
if (rsp_lenp)
*rsp_lenp = 0;
- cp = find_in_diag_page_desc(page_code);
- if (op->verbose > 1) {
- if (cp)
- pr2serr(" Receive diagnostic results command for %s page\n",
- cp);
- else
- pr2serr(" Receive diagnostic results command for page 0x%x\n",
- page_code);
+ if ((cp = find_in_diag_page_desc(page_code)))
+ snprintf(bb, sizeof(bb), "%s dpage", cp);
+ else
+ snprintf(bb, sizeof(bb), "dpage 0x%x", page_code);
+ cp = bb;
+
+ if (op->data_arr && op->do_data) { /* user provided data */
+ /* N.B. First 4 bytes in data_arr are not used, user data was read in
+ * starting at byte offset 4 */
+ bool found = false;
+ int off = 0;
+ const uint8_t * bp = op->data_arr + DATA_IN_OFF;
+ const struct data_in_desc_t * didp = data_in_desc_arr;
+
+ for (k = 0, d_len = 0; k < MX_DATA_IN_DESCS; ++k, ++didp) {
+ if (! didp->in_use)
+ break;
+ if (page_code == didp->page_code) {
+ off = didp->offset;
+ d_len = didp->dp_len;
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ memcpy(rsp_buff, bp + off, d_len);
+ else {
+ if (vb)
+ pr2serr("%s: %s not found in user data\n", __func__, cp);
+ return SG_LIB_CAT_OTHER;
+ }
+
+ cp = find_in_diag_page_desc(page_code);
+ if (vb > 2) {
+ pr2serr(" %s: response data from user", rdr);
+ if (3 == vb) {
+ pr2serr("%s:\n", (d_len > 256 ? ", first 256 bytes" : ""));
+ hex2stderr(rsp_buff, (d_len > 256 ? 256 : d_len), -1);
+ } else {
+ pr2serr(":\n");
+ hex2stderr(rsp_buff, d_len, 0);
+ }
+ }
+ res = 0;
+ resid = rsp_buff_size - d_len;
+ goto decode; /* step over the device access */
}
+ if (vb > 1)
+ pr2serr(" %s command for %s\n", rdr, cp);
res = sg_ll_receive_diag_v2(sg_fd, true /* pcv */, page_code, rsp_buff,
rsp_buff_size, 0 /* default timeout */,
- &resid, true, op->verbose);
+ &resid, ! op->quiet, vb);
+decode:
if (0 == res) {
rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4;
if (rsp_len > rsp_buff_size) {
@@ -1776,12 +1933,8 @@ do_rec_diag(int sg_fd, int page_code, uint8_t * rsp_buff,
return -2;
}
return 0;
- } else if (op->verbose) {
- if (cp)
- pr2serr("Attempt to fetch %s diagnostic page failed\n", cp);
- else
- pr2serr("Attempt to fetch status diagnostic page [0x%x] failed\n",
- page_code);
+ } else if (vb) {
+ pr2serr("Attempt to fetch %s failed\n", cp);
sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
pr2serr(" %s\n", b);
}
@@ -1906,35 +2059,44 @@ build_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, int max_elems,
int resp_len, k, el, num_subs, sum_type_dheaders, res, n;
int ret = 0;
uint32_t gen_code;
- uint8_t * resp = NULL;
- uint8_t * free_resp = NULL;
const uint8_t * bp;
const uint8_t * last_bp;
- resp = sg_memalign(op->maxlen, 0, &free_resp, op->verbose > 3);
- if (NULL == resp) {
- pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
- op->maxlen);
- ret = -1;
- goto the_end;
- }
- res = do_rec_diag(fd, CONFIGURATION_DPC, resp, op->maxlen, op, &resp_len);
- if (res) {
- pr2serr("%s: couldn't read config page, res=%d\n", __func__, res);
- ret = -1;
- goto the_end;
- }
- if (resp_len < 4) {
- ret = -1;
- goto the_end;
- }
- num_subs = resp[1] + 1;
+ if (NULL == config_dp_resp) {
+ config_dp_resp = sg_memalign(op->maxlen, 0, &free_config_dp_resp,
+ false);
+ if (NULL == config_dp_resp) {
+ pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
+ op->maxlen);
+ ret = -1;
+ goto the_end;
+ }
+ res = do_rec_diag(fd, CONFIGURATION_DPC, config_dp_resp, op->maxlen,
+ op, &resp_len);
+ if (res) {
+ pr2serr("%s: couldn't read config page, res=%d\n", __func__, res);
+ ret = -1;
+ free(free_config_dp_resp);
+ free_config_dp_resp = NULL;
+ goto the_end;
+ }
+ if (resp_len < 4) {
+ ret = -1;
+ free(free_config_dp_resp);
+ free_config_dp_resp = NULL;
+ goto the_end;
+ }
+ config_dp_resp_len = resp_len;
+ } else
+ resp_len = config_dp_resp_len;
+
+ num_subs = config_dp_resp[1] + 1;
sum_type_dheaders = 0;
- last_bp = resp + resp_len - 1;
- gen_code = sg_get_unaligned_be32(resp + 4);
+ last_bp = config_dp_resp + resp_len - 1;
+ gen_code = sg_get_unaligned_be32(config_dp_resp + 4);
if (generationp)
*generationp = gen_code;
- bp = resp + 8;
+ bp = config_dp_resp + 8;
for (k = 0; k < num_subs; ++k, bp += el) {
if ((bp + 3) > last_bp)
goto p_truncated;
@@ -1998,8 +2160,8 @@ p_truncated:
ret = -1;
the_end:
- if (free_resp)
- free(free_resp);
+ if (0 == ret)
+ ++type_desc_hdr_count;
return ret;
}
@@ -3692,13 +3854,16 @@ truncated:
return;
}
-/* Reads hex data from command line, stdin or a file. Returns 0 on success,
- * 1 otherwise. */
+/* Reads hex data from command line, stdin or a file when in_hex is true.
+ * Reads binary from stdin or file when in_hex is false. Returns 0 on
+ * success, 1 otherwise. If inp is a file, then the first skipped (since
+ * (it should be '@'). */
static int
-read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
+read_hex(const char * inp, uint8_t * arr, int mx_arr_len, int * arr_len,
+ bool in_hex, int vb)
{
+ bool has_stdin, split_line;
int in_len, k, j, m, off;
- bool split_line;
unsigned int h;
const char * lcp;
char * cp;
@@ -3711,10 +3876,60 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
return 1;
lcp = inp;
in_len = strlen(inp);
- if (0 == in_len)
+ if (0 == in_len) {
*arr_len = 0;
- if (('-' == inp[0]) || ('@' == inp[0])) { /* read from stdin or file */
- if ('-' == inp[0])
+ return 0;
+ }
+ has_stdin = ((1 == in_len) && ('-' == inp[0]));
+
+ if (! in_hex) { /* binary, assume its not on the command line, */
+ int fd; /* that leaves stdin or a file (pipe) */
+ struct stat a_stat;
+
+ if (has_stdin)
+ fd = STDIN_FILENO;
+ else {
+ fd = open(inp + 1, O_RDONLY);
+ if (fd < 0) {
+ pr2serr("unable to open binary file %s: %s\n", inp,
+ safe_strerror(errno));
+ return 1;
+ }
+ }
+ k = read(fd, arr, mx_arr_len);
+ if (k <= 0) {
+ if (0 == k)
+ pr2serr("read 0 bytes from binary file %s\n", inp);
+ else
+ pr2serr("read from binary file %s: %s\n", inp,
+ safe_strerror(errno));
+ if (! has_stdin)
+ close(fd);
+ return 1;
+ }
+ if ((0 == fstat(fd, &a_stat)) && S_ISFIFO(a_stat.st_mode)) {
+ /* pipe; keep reading till error or 0 read */
+ while (k < mx_arr_len) {
+ m = read(fd, arr + k, mx_arr_len - k);
+ if (0 == m)
+ break;
+ if (m < 0) {
+ pr2serr("read from binary pipe %s: %s\n", inp,
+ safe_strerror(errno));
+ if (! has_stdin)
+ close(fd);
+ return 1;
+ }
+ k += m;
+ }
+ }
+ *arr_len = k;
+ if (! has_stdin)
+ close(fd);
+ return 0;
+ }
+ if (has_stdin || ('@' == inp[0])) { /* read from stdin or file */
+ if (has_stdin)
fp = stdin;
else {
fp = fopen(inp + 1, "r");
@@ -3724,8 +3939,7 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
}
}
carry_over[0] = 0;
- for (j = 0, off = 0; j < MX_DATA_IN; ++j) {
- /* limit lines read to MX_DATA_IN */
+ for (j = 0, off = 0; j < MX_DATA_IN_LINES; ++j) {
if (NULL == fgets(line, sizeof(line), fp))
break;
in_len = strlen(line);
@@ -3770,14 +3984,19 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
if (in_len != k) {
pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
j + 1, m + k + 1);
+ if (vb > 2)
+ pr2serr("first 40 characters of line: %.40s\n", line);
goto err_with_fp;
}
- for (k = 0; k < (MX_DATA_IN - off); ++k) {
+ for (k = 0; k < (mx_arr_len - off); ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
pr2serr("%s: hex number larger than 0xff in line %d, "
"pos %d\n", __func__, j + 1,
(int)(lcp - line + 1));
+ if (vb > 2)
+ pr2serr("first 40 characters of line: %.40s\n",
+ line);
goto err_with_fp;
}
if (split_line && (1 == strlen(lcp))) {
@@ -3794,11 +4013,13 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
} else {
pr2serr("%s: error in line %d, at pos %d\n", __func__,
j + 1, (int)(lcp - line + 1));
+ if (vb > 2)
+ pr2serr("first 40 characters of line: %.40s\n", line);
goto err_with_fp;
}
}
off += k + 1;
- if (off >= MX_DATA_IN)
+ if (off >= mx_arr_len)
break;
}
*arr_len = off;
@@ -3808,7 +4029,7 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
pr2serr("%s: error at pos %d\n", __func__, k + 1);
goto err_with_fp;
}
- for (k = 0; k < MX_DATA_IN; ++k) {
+ for (k = 0; k < mx_arr_len; ++k) {
if (1 == sscanf(lcp, "%x", &h)) {
if (h > 0xff) {
pr2serr("%s: hex number larger than 0xff at pos %d\n",
@@ -3833,8 +4054,10 @@ read_hex(const char * inp, uint8_t * arr, int * arr_len, int verb)
}
*arr_len = k + 1;
}
- if (verb > 3)
- hex2stdout(arr, *arr_len, 0);
+ if (vb > 3) {
+ pr2serr("%s: user provided data:\n", __func__);
+ hex2stderr(arr, *arr_len, 0);
+ }
if (fp && (fp != stdin))
fclose(fp);
return 0;
@@ -3845,34 +4068,26 @@ err_with_fp:
return 1;
}
-/* Display "status" page (op->page_code). data-in from SES device.
- * Return 0 for success. */
static int
-process_status_page(int sg_fd, struct opts_t * op)
+process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
+ struct opts_t * op)
{
- int j, resp_len, num_ths;
+ int j, num_ths;
int ret = 0;
uint32_t ref_gen_code;
- uint8_t * resp = NULL;
- uint8_t * free_resp = NULL;
const char * cp;
struct enclosure_info primary_info;
struct th_es_t tes;
struct th_es_t * tesp;
+ char bb[120];
- resp = sg_memalign(op->maxlen, 0, &free_resp, op->verbose > 3);
- if (NULL == resp) {
- pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
- op->maxlen);
- ret = -1;
- goto fini;
- }
tesp = &tes;
memset(tesp, 0, sizeof(tes));
- cp = find_in_diag_page_desc(op->page_code);
- ret = do_rec_diag(sg_fd, op->page_code, resp, op->maxlen, op, &resp_len);
- if (ret)
- goto fini;
+ if ((cp = find_in_diag_page_desc(page_code)))
+ snprintf(bb, sizeof(bb), "%s dpage", cp);
+ else
+ snprintf(bb, sizeof(bb), "dpage 0x%x", page_code);
+ cp = bb;
if (op->do_raw) {
if (1 == op->do_raw)
hex2stdout(resp + 4, resp_len - 4, -1);
@@ -3881,164 +4096,229 @@ process_status_page(int sg_fd, struct opts_t * op)
perror("sg_set_binary_mode");
dStrRaw(resp, resp_len);
}
+ goto fini;
} else if (op->do_hex) {
- if (op->do_hex > 2)
+ if (op->do_hex > 2) {
+ if (4 == op->do_hex)
+ printf("\n# %s:\n", cp);
hex2stdout(resp, resp_len, -1);
- else {
- if (cp)
- printf("Response in hex from diagnostic page: %s\n", cp);
- else
- printf("Response in hex from unknown diagnostic page "
- "[0x%x]\n", op->page_code);
+ } else {
+ printf("# Response in hex for %s:\n", cp);
hex2stdout(resp, resp_len, (2 == op->do_hex));
}
- } else {
- memset(&primary_info, 0, sizeof(primary_info));
- switch (op->page_code) {
- case SUPPORTED_DPC:
- supported_pages_sdg("Supported diagnostic pages", resp, resp_len);
- break;
- case CONFIGURATION_DPC:
- configuration_sdg(resp, resp_len);
- break;
- case ENC_STATUS_DPC:
- 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) {
- ret = num_ths;
- goto fini;
- }
- if (primary_info.have_info) {
- printf(" Primary enclosure logical identifier (hex): ");
- for (j = 0; j < 8; ++j)
- printf("%02x", primary_info.enc_log_id[j]);
- printf("\n");
- }
- tesp->th_base = type_desc_hdr_arr;
- tesp->num_ths = num_ths;
- enc_status_dp(tesp, ref_gen_code, resp, resp_len, op);
- break;
- case ARRAY_STATUS_DPC:
- 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) {
- ret = num_ths;
- goto fini;
- }
- if (primary_info.have_info) {
- printf(" Primary enclosure logical identifier (hex): ");
- for (j = 0; j < 8; ++j)
- printf("%02x", primary_info.enc_log_id[j]);
- printf("\n");
- }
- tesp->th_base = type_desc_hdr_arr;
- tesp->num_ths = num_ths;
- array_status_dp(tesp, ref_gen_code, resp, resp_len, op);
- break;
- case HELP_TEXT_DPC:
- printf("Help text diagnostic page (for primary "
- "subenclosure):\n");
- if (resp_len > 4)
- printf(" %.*s\n", resp_len - 4, resp + 4);
- else
- printf(" <empty>\n");
- break;
- case STRING_DPC:
- printf("String In diagnostic page (for primary "
- "subenclosure):\n");
- if (resp_len > 4)
- hex2stdout(resp + 4, resp_len - 4, 0);
- else
- printf(" <empty>\n");
- break;
- case THRESHOLD_DPC:
- 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) {
- ret = num_ths;
- goto fini;
- }
- if (primary_info.have_info) {
- printf(" Primary enclosure logical identifier (hex): ");
- for (j = 0; j < 8; ++j)
- printf("%02x", primary_info.enc_log_id[j]);
- printf("\n");
- }
- tesp->th_base = type_desc_hdr_arr;
- tesp->num_ths = num_ths;
- threshold_sdg(tesp, ref_gen_code, resp, resp_len, op);
- break;
- case ELEM_DESC_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ goto fini;
+ }
+
+ memset(&primary_info, 0, sizeof(primary_info));
+ switch (page_code) {
+ case SUPPORTED_DPC:
+ supported_pages_sdg("Supported diagnostic pages", resp, resp_len);
+ break;
+ case CONFIGURATION_DPC:
+ configuration_sdg(resp, resp_len);
+ break;
+ case ENC_STATUS_DPC:
+ 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) {
+ ret = num_ths;
+ goto fini;
+ }
+ if ((1 == type_desc_hdr_count) && primary_info.have_info) {
+ printf(" Primary enclosure logical identifier (hex): ");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", primary_info.enc_log_id[j]);
+ printf("\n");
+ }
+ tesp->th_base = type_desc_hdr_arr;
+ tesp->num_ths = num_ths;
+ enc_status_dp(tesp, ref_gen_code, resp, resp_len, op);
+ break;
+ case ARRAY_STATUS_DPC:
+ 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) {
+ ret = num_ths;
+ goto fini;
+ }
+ if ((1 == type_desc_hdr_count) && primary_info.have_info) {
+ printf(" Primary enclosure logical identifier (hex): ");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", primary_info.enc_log_id[j]);
+ printf("\n");
+ }
+ tesp->th_base = type_desc_hdr_arr;
+ tesp->num_ths = num_ths;
+ array_status_dp(tesp, ref_gen_code, resp, resp_len, op);
+ break;
+ case HELP_TEXT_DPC:
+ printf("Help text diagnostic page (for primary "
+ "subenclosure):\n");
+ if (resp_len > 4)
+ printf(" %.*s\n", resp_len - 4, resp + 4);
+ else
+ printf(" <empty>\n");
+ break;
+ case STRING_DPC:
+ printf("String In diagnostic page (for primary "
+ "subenclosure):\n");
+ if (resp_len > 4)
+ hex2stdout(resp + 4, resp_len - 4, 0);
+ else
+ printf(" <empty>\n");
+ break;
+ case THRESHOLD_DPC:
+ 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) {
+ ret = num_ths;
+ goto fini;
+ }
+ if ((1 == type_desc_hdr_count) && primary_info.have_info) {
+ printf(" Primary enclosure logical identifier (hex): ");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", primary_info.enc_log_id[j]);
+ printf("\n");
+ }
+ tesp->th_base = type_desc_hdr_arr;
+ tesp->num_ths = num_ths;
+ threshold_sdg(tesp, ref_gen_code, resp, resp_len, op);
+ break;
+ case ELEM_DESC_DPC:
+ 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) {
- ret = num_ths;
- goto fini;
- }
- if (primary_info.have_info) {
- printf(" Primary enclosure logical identifier (hex): ");
- for (j = 0; j < 8; ++j)
- printf("%02x", primary_info.enc_log_id[j]);
- printf("\n");
+ ret = num_ths;
+ goto fini;
+ }
+ if ((1 == type_desc_hdr_count) && primary_info.have_info) {
+ printf(" Primary enclosure logical identifier (hex): ");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", primary_info.enc_log_id[j]);
+ printf("\n");
+ }
+ tesp->th_base = type_desc_hdr_arr;
+ tesp->num_ths = num_ths;
+ element_desc_sdg(tesp, ref_gen_code, resp, resp_len, op);
+ break;
+ case SHORT_ENC_STATUS_DPC:
+ printf("Short enclosure status diagnostic page, "
+ "status=0x%x\n", resp[1]);
+ break;
+ case ENC_BUSY_DPC:
+ printf("Enclosure Busy diagnostic page, "
+ "busy=%d [vendor specific=0x%x]\n",
+ resp[1] & 1, (resp[1] >> 1) & 0xff);
+ break;
+ case ADD_ELEM_STATUS_DPC:
+ 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) {
+ ret = num_ths;
+ goto fini;
+ }
+ if (primary_info.have_info) {
+ printf(" Primary enclosure logical identifier (hex): ");
+ for (j = 0; j < 8; ++j)
+ printf("%02x", primary_info.enc_log_id[j]);
+ printf("\n");
+ }
+ tesp->th_base = type_desc_hdr_arr;
+ tesp->num_ths = num_ths;
+ additional_elem_sdg(tesp, ref_gen_code, resp, resp_len, op);
+ break;
+ case SUBENC_HELP_TEXT_DPC:
+ subenc_help_sdg(resp, resp_len);
+ break;
+ case SUBENC_STRING_DPC:
+ subenc_string_sdg(resp, resp_len);
+ break;
+ case SUPPORTED_SES_DPC:
+ supported_pages_sdg("Supported SES diagnostic pages", resp,
+ resp_len);
+ break;
+ case DOWNLOAD_MICROCODE_DPC:
+ download_code_sdg(resp, resp_len);
+ break;
+ case SUBENC_NICKNAME_DPC:
+ subenc_nickname_sdg(resp, resp_len);
+ break;
+ default:
+ printf("Cannot decode response from diagnostic "
+ "page: %s\n", (cp ? cp : "<unknown>"));
+ hex2stdout(resp, resp_len, 0);
+ }
+
+fini:
+ return ret;
+}
+
+/* Display "status" page or pages (if op->page_code==0xff) . data-in from
+ * SES device or user provided (with --data= option). Return 0 for success */
+static int
+process_status_page_s(int sg_fd, struct opts_t * op)
+{
+ int page_code, ret, resp_len;
+ uint8_t * resp = NULL;
+ uint8_t * free_resp = NULL;
+
+ resp = sg_memalign(op->maxlen, 0, &free_resp, false);
+ if (NULL == resp) {
+ pr2serr("%s: unable to allocate %d bytes on heap\n", __func__,
+ op->maxlen);
+ ret = -1;
+ goto fini;
+ }
+ page_code = op->page_code;
+ if (ALL_DPC == page_code) {
+ int k, n;
+ uint8_t pc, prev;
+ uint8_t supp_dpg_arr[256];
+ const int s_arr_sz = sizeof(supp_dpg_arr);
+
+ memset(supp_dpg_arr, 0, s_arr_sz);
+ ret = do_rec_diag(sg_fd, SUPPORTED_DPC, resp, op->maxlen, op,
+ &resp_len);
+ if (ret) /* SUPPORTED_DPC failed so try SUPPORTED_SES_DPC */
+ ret = do_rec_diag(sg_fd, SUPPORTED_SES_DPC, resp, op->maxlen, op,
+ &resp_len);
+ if (ret)
+ goto fini;
+ for (n = 0, pc = 0; (n < s_arr_sz) && (n < (resp_len - 4)); ++n) {
+ prev = pc;
+ pc = resp[4 + n];
+ if (prev > pc) {
+ if (pc) { /* could be zero pad at end which is ok */
+ pr2serr("%s: Supported (SES) dpage seems corrupt, "
+ "should ascend\n", __func__);
+ ret = SG_LIB_CAT_OTHER;
+ goto fini;
+ }
+ break;
}
- tesp->th_base = type_desc_hdr_arr;
- tesp->num_ths = num_ths;
- element_desc_sdg(tesp, ref_gen_code, resp, resp_len, op);
- break;
- case SHORT_ENC_STATUS_DPC:
- printf("Short enclosure status diagnostic page, "
- "status=0x%x\n", resp[1]);
- break;
- case ENC_BUSY_DPC:
- printf("Enclosure Busy diagnostic page, "
- "busy=%d [vendor specific=0x%x]\n",
- resp[1] & 1, (resp[1] >> 1) & 0xff);
- break;
- case ADD_ELEM_STATUS_DPC:
- 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) {
- ret = num_ths;
+ if (pc > 0x2f)
+ break;
+ supp_dpg_arr[n] = pc;
+ }
+ for (k = 0; k < n; ++k) {
+ page_code = supp_dpg_arr[k];
+ ret = do_rec_diag(sg_fd, page_code, resp, op->maxlen, op,
+ &resp_len);
+ if (ret)
goto fini;
- }
- if (primary_info.have_info) {
- printf(" Primary enclosure logical identifier (hex): ");
- for (j = 0; j < 8; ++j)
- printf("%02x", primary_info.enc_log_id[j]);
- printf("\n");
- }
- tesp->th_base = type_desc_hdr_arr;
- tesp->num_ths = num_ths;
- additional_elem_sdg(tesp, ref_gen_code, resp, resp_len, op);
- break;
- case SUBENC_HELP_TEXT_DPC:
- subenc_help_sdg(resp, resp_len);
- break;
- case SUBENC_STRING_DPC:
- subenc_string_sdg(resp, resp_len);
- break;
- case SUPPORTED_SES_DPC:
- supported_pages_sdg("Supported SES diagnostic pages", resp,
- resp_len);
- break;
- case DOWNLOAD_MICROCODE_DPC:
- download_code_sdg(resp, resp_len);
- break;
- case SUBENC_NICKNAME_DPC:
- subenc_nickname_sdg(resp, resp_len);
- break;
- default:
- printf("Cannot decode response from diagnostic "
- "page: %s\n", (cp ? cp : "<unknown>"));
- hex2stdout(resp, resp_len, 0);
+ ret = process_status_dpage(sg_fd, page_code, resp, resp_len, op);
}
+ } else { /* asking for a specific page code */
+ ret = do_rec_diag(sg_fd, page_code, resp, op->maxlen, op, &resp_len);
+ if (ret)
+ goto fini;
+ ret = process_status_dpage(sg_fd, page_code, resp, resp_len, op);
}
- ret = 0;
fini:
if (free_resp)
@@ -4843,7 +5123,7 @@ cgs_enc_ctl_stat(int sg_fd, struct join_row_t * jrp,
enc_stat_rsp[1] = op->byte1;
len = sg_get_unaligned_be16(enc_stat_rsp + 2) + 4;
if (last) {
- ret = do_senddiag(sg_fd, true, enc_stat_rsp, len, true,
+ ret = do_senddiag(sg_fd, enc_stat_rsp, len, ! op->quiet,
op->verbose);
if (ret) {
pr2serr("couldn't send Enclosure Control page\n");
@@ -4901,7 +5181,7 @@ cgs_threshold(int sg_fd, const struct join_row_t * jrp,
threshold_rsp[1] = op->byte1;
len = sg_get_unaligned_be16(threshold_rsp + 2) + 4;
if (last) {
- ret = do_senddiag(sg_fd, true, threshold_rsp, len, true,
+ ret = do_senddiag(sg_fd, threshold_rsp, len, ! op->quiet,
op->verbose);
if (ret) {
pr2serr("couldn't send Threshold Out page\n");
@@ -4972,6 +5252,11 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
const uint8_t * ed_bp;
char b[64];
+ if ((sg_fd < 0) && (GET_OPT != tavp->cgs_sel)) {
+ pr2serr("%s: --clear= and --set= only supported when DEVICE is "
+ "given\n", __func__);
+ return SG_LIB_SYNTAX_ERROR;
+ }
found = false;
if (NULL == tavp->acron) {
if (! op->page_code_given)
@@ -5093,6 +5378,10 @@ ses_set_nickname(int sg_fd, struct opts_t * op)
uint8_t b[64];
const int control_plen = 0x24;
+ if (sg_fd < 0) {
+ pr2serr("%s: ignored when no device name\n", __func__);
+ return 0;
+ }
memset(b, 0, sizeof(b));
/* Only after the generation code, offset 4 for 4 bytes */
res = do_rec_diag(sg_fd, SUBENC_NICKNAME_DPC, b, 8, op, &resp_len);
@@ -5120,7 +5409,8 @@ ses_set_nickname(int sg_fd, struct opts_t * op)
if (len > 32)
len = 32;
memcpy(b + 8, op->nickname_str, len);
- return do_senddiag(sg_fd, true, b, control_plen + 4, true, op->verbose);
+ return do_senddiag(sg_fd, b, control_plen + 4, ! op->quiet,
+ op->verbose);
}
static void
@@ -5225,12 +5515,10 @@ int
main(int argc, char * argv[])
{
bool have_cgs = false;
- bool vb3;
- int k, res, vb;
+ int k, d_len, res, vb;
int sg_fd = -1;
int pd_type = 0;
int ret = 0;
- uint32_t pg_sz;
const char * cp;
struct opts_t opts;
struct opts_t * op;
@@ -5250,18 +5538,13 @@ main(int argc, char * argv[])
op->dev_slot_num = -1;
op->ind_indiv_last = -1;
op->maxlen = MX_ALLOC_LEN;
- pg_sz = sg_get_page_size();
- op->data_arr = sg_memalign(MX_DATA_IN + 16, pg_sz, &op->free_data_arr,
- false);
- if (NULL == op->data_arr) {
- pr2serr("unable to allocate %u bytes on heap\n", MX_DATA_IN + 16);
- return sg_convert_errno(ENOMEM);
- }
res = parse_cmd_line(op, argc, argv);
if (res) {
ret = SG_LIB_SYNTAX_ERROR;
+ vb = op->verbose;
goto early_out;
}
+ vb = op->verbose;
if (op->do_version) {
pr2serr("version: %s\n", version_str);
goto early_out;
@@ -5274,27 +5557,25 @@ main(int argc, char * argv[])
enumerate_work(op);
goto early_out;
}
- vb = op->verbose;
- vb3 = (vb > 3);
- enc_stat_rsp = sg_memalign(op->maxlen, pg_sz, &free_enc_stat_rsp, vb3);
+ enc_stat_rsp = sg_memalign(op->maxlen, 0, &free_enc_stat_rsp, false);
if (NULL == enc_stat_rsp) {
pr2serr("Unable to get heap for enc_stat_rsp\n");
goto err_out;
}
enc_stat_rsp_sz = op->maxlen;
- elem_desc_rsp = sg_memalign(op->maxlen, pg_sz, &free_elem_desc_rsp, vb3);
+ elem_desc_rsp = sg_memalign(op->maxlen, 0, &free_elem_desc_rsp, false);
if (NULL == elem_desc_rsp) {
pr2serr("Unable to get heap for elem_desc_rsp\n");
goto err_out;
}
elem_desc_rsp_sz = op->maxlen;
- add_elem_rsp = sg_memalign(op->maxlen, pg_sz, &free_add_elem_rsp, vb3);
+ add_elem_rsp = sg_memalign(op->maxlen, 0, &free_add_elem_rsp, false);
if (NULL == add_elem_rsp) {
pr2serr("Unable to get heap for add_elem_rsp\n");
goto err_out;
}
add_elem_rsp_sz = op->maxlen;
- threshold_rsp = sg_memalign(op->maxlen, pg_sz, &free_threshold_rsp, vb3);
+ threshold_rsp = sg_memalign(op->maxlen, 0, &free_threshold_rsp, false);
if (NULL == threshold_rsp) {
pr2serr("Unable to get heap for threshold_rsp\n");
goto err_out;
@@ -5373,31 +5654,36 @@ main(int argc, char * argv[])
}
#endif
- sg_fd = sg_cmds_open_device(op->dev_name, op->o_readonly, vb);
- if (sg_fd < 0) {
- pr2serr("open error: %s: %s\n", op->dev_name,
- safe_strerror(-sg_fd));
- ret = SG_LIB_FILE_ERROR;
- goto err_out;
- }
- if (! (op->do_raw || have_cgs || (op->do_hex > 2))) {
- if (sg_simple_inquiry(sg_fd, &inq_resp, 1, vb)) {
- pr2serr("%s doesn't respond to a SCSI INQUIRY\n", op->dev_name);
- ret = SG_LIB_CAT_OTHER;
+ if (op->dev_name) {
+ sg_fd = sg_cmds_open_device(op->dev_name, op->o_readonly, vb);
+ if (sg_fd < 0) {
+ pr2serr("open error: %s: %s\n", op->dev_name,
+ safe_strerror(-sg_fd));
+ ret = SG_LIB_FILE_ERROR;
goto err_out;
- } else {
- printf(" %.8s %.16s %.4s\n", inq_resp.vendor,
- inq_resp.product, inq_resp.revision);
- pd_type = inq_resp.peripheral_type;
- cp = sg_get_pdt_str(pd_type, sizeof(buff), buff);
- if (0xd == pd_type) {
- if (vb)
- printf(" enclosure services device\n");
- } else if (0x40 & inq_resp.byte_6)
- printf(" %s device has EncServ bit set\n", cp);
- else
- printf(" %s device (not an enclosure)\n", cp);
}
+ if (! (op->do_raw || have_cgs || (op->do_hex > 2))) {
+ if ((ret = sg_simple_inquiry(sg_fd, &inq_resp, ! op->quiet, vb))) {
+ pr2serr("%s doesn't respond to a SCSI INQUIRY\n",
+ op->dev_name);
+ goto err_out;
+ } else {
+ printf(" %.8s %.16s %.4s\n", inq_resp.vendor,
+ inq_resp.product, inq_resp.revision);
+ pd_type = inq_resp.peripheral_type;
+ cp = sg_get_pdt_str(pd_type, sizeof(buff), buff);
+ if (0xd == pd_type) {
+ if (vb)
+ printf(" enclosure services device\n");
+ } else if (0x40 & inq_resp.byte_6)
+ printf(" %s device has EncServ bit set\n", cp);
+ else
+ printf(" %s device (not an enclosure)\n", cp);
+ }
+ }
+ } else if (op->do_control) {
+ pr2serr("Cannot do SCSI Send diagnostic command without a DEVICE\n");
+ return SG_LIB_SYNTAX_ERROR;
}
if (op->nickname_str)
@@ -5412,17 +5698,17 @@ main(int argc, char * argv[])
} else if (op->do_join)
ret = join_work(sg_fd, op, true);
else if (op->do_status)
- ret = process_status_page(sg_fd, op);
+ ret = process_status_page_s(sg_fd, op);
else { /* control page requested */
op->data_arr[0] = op->page_code;
op->data_arr[1] = op->byte1;
+ d_len = op->arr_len + DATA_IN_OFF;
sg_put_unaligned_be16((uint16_t)op->arr_len, op->data_arr + 2);
switch (op->page_code) {
case ENC_CONTROL_DPC: /* Enclosure Control diagnostic page [0x2] */
printf("Sending Enclosure Control [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Enclosure Control page\n");
goto err_out;
@@ -5431,8 +5717,7 @@ main(int argc, char * argv[])
case STRING_DPC: /* String Out diagnostic page [0x4] */
printf("Sending String Out [0x%x] page, with page length=%d "
"bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send String Out page\n");
goto err_out;
@@ -5441,8 +5726,7 @@ main(int argc, char * argv[])
case THRESHOLD_DPC: /* Threshold Out diagnostic page [0x5] */
printf("Sending Threshold Out [0x%x] page, with page length=%d "
"bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Threshold Out page\n");
goto err_out;
@@ -5451,8 +5735,7 @@ main(int argc, char * argv[])
case ARRAY_CONTROL_DPC: /* Array control diagnostic page [0x6] */
printf("Sending Array Control [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Array Control page\n");
goto err_out;
@@ -5461,8 +5744,7 @@ main(int argc, char * argv[])
case SUBENC_STRING_DPC: /* Subenclosure String Out page [0xc] */
printf("Sending Subenclosure String Out [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Subenclosure String Out page\n");
goto err_out;
@@ -5470,11 +5752,10 @@ main(int argc, char * argv[])
break;
case DOWNLOAD_MICROCODE_DPC: /* Download Microcode Control [0xe] */
printf("Sending Download Microcode Control [0x%x] page, with "
- "page length=%d bytes\n", op->page_code, op->arr_len);
+ "page length=%d bytes\n", op->page_code, d_len);
printf(" Perhaps it would be better to use the sg_ses_microcode "
"utility\n");
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Download Microcode Control page\n");
goto err_out;
@@ -5482,9 +5763,8 @@ main(int argc, char * argv[])
break;
case SUBENC_NICKNAME_DPC: /* Subenclosure Nickname Control [0xf] */
printf("Sending Subenclosure Nickname Control [0x%x] page, with "
- "page length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, true, op->data_arr, op->arr_len + 4,
- true, vb);
+ "page length=%d bytes\n", op->page_code, d_len);
+ ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Subenclosure Nickname Control page\n");
goto err_out;
@@ -5505,9 +5785,6 @@ err_out:
sg_get_category_sense_str(ret, sizeof(b), b, vb);
pr2serr(" %s\n", b);
}
- if (ret && (0 == vb))
- pr2serr("Problem detected, try again with --verbose option for more "
- "information\n");
if (sg_fd >= 0)
res = sg_cmds_close_device(sg_fd);
else
@@ -5526,7 +5803,16 @@ err_out:
ret = SG_LIB_FILE_ERROR;
}
early_out:
+ if ((0 == vb) && (! op->quiet)) {
+ if (! sg_if_can2stderr("sg_ses failed: ", ret))
+ pr2serr("Some error occurred, try again with '-v' or '-vv' for "
+ "more information\n");
+ else if ((SG_LIB_SYNTAX_ERROR == ret) && (0 == vb))
+ pr2serr("Add '-h' to command line for usage infomation\n");
+ }
if (op->free_data_arr)
free(op->free_data_arr);
+ if (free_config_dp_resp)
+ free(free_config_dp_resp);
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/src/sg_start.c b/src/sg_start.c
index 685af0de..8fee166e 100644
--- a/src/sg_start.c
+++ b/src/sg_start.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2017 D. Gilbert
+ * Copyright (C) 1999-2018 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -34,7 +34,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "0.63 20171010"; /* sbc3r14; mmc6r01a */
+static const char * version_str = "0.64 20180302"; /* sbc3r14; mmc6r01a */
static struct option long_options[] = {
{"eject", no_argument, 0, 'e'},
@@ -169,7 +169,7 @@ usage_old()
}
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+news_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n, err;
@@ -286,7 +286,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool ambigu = false;
bool jmp_out;
@@ -458,7 +458,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -466,14 +466,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opt_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opt_new)
- res = process_cl_new(op, argc, argv);
+ res = news_parse_cmd_line(op, argc, argv);
} else {
op->opt_new = true;
- res = process_cl_new(op, argc, argv);
+ res = news_parse_cmd_line(op, argc, argv);
if ((0 == res) && (! op->opt_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -490,7 +490,7 @@ main(int argc, char * argv[])
op = &opts;
memset(op, 0, sizeof(opts));
op->do_fl = -1; /* only when >= 0 set FL bit */
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {
diff --git a/src/sg_turs.c b/src/sg_turs.c
index 7b8b0567..24a37f92 100644
--- a/src/sg_turs.c
+++ b/src/sg_turs.c
@@ -36,7 +36,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "3.38 20180123";
+static const char * version_str = "3.39 20180302";
#if defined(MSC_VER) || defined(__MINGW32__)
#define HAVE_MS_SLEEP
@@ -124,7 +124,7 @@ usage_for(const struct opts_t * op)
}
static int
-process_cl_new(struct opts_t * op, int argc, char * argv[])
+new_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int c, n;
@@ -191,7 +191,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl_old(struct opts_t * op, int argc, char * argv[])
+old_parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
bool jmp_out;
int k, plen;
@@ -261,7 +261,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
}
static int
-process_cl(struct opts_t * op, int argc, char * argv[])
+parse_cmd_line(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
@@ -269,14 +269,14 @@ process_cl(struct opts_t * op, int argc, char * argv[])
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
op->opts_new = false;
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
if ((0 == res) && op->opts_new)
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
} else {
op->opts_new = true;
- res = process_cl_new(op, argc, argv);
+ res = new_parse_cmd_line(op, argc, argv);
if ((0 == res) && (0 == op->opts_new))
- res = process_cl_old(op, argc, argv);
+ res = old_parse_cmd_line(op, argc, argv);
}
return res;
}
@@ -299,7 +299,7 @@ main(int argc, char * argv[])
op = &opts;
memset(op, 0, sizeof(opts));
op->do_number = 1;
- res = process_cl(op, argc, argv);
+ res = parse_cmd_line(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
if (op->do_help) {