aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_logs.892
-rw-r--r--doc/sg_persist.87
-rw-r--r--doc/sg_read_buffer.844
-rw-r--r--doc/sg_ses.85
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_inq.c11
-rw-r--r--src/sg_logs.c1950
-rw-r--r--src/sg_persist.c137
11 files changed, 1631 insertions, 627 deletions
diff --git a/ChangeLog b/ChangeLog
index 82cf1704..2dca0545 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,13 +2,17 @@ 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.39 [20140428] [svn: r571]
+Changelog for sg3_utils-1.39 [20140504] [svn: r572]
- sg_ses: add --eiioe=auto|force option
- fix AES dpage element indexing problems
- sg_write_buffer: add --bpw=CS option to call
write buffer multiple times for big blobs
- sg_format: add --ip_def option to fully provision
- sg_opcodes: add --mask option
+ - sg_logs: add --in=FN option for log select params
+ - add --filter=PARC (parameter code)
+ - sg_persist: add --readonly option
+ - or environment variable SG_PERSIST_O_RDONLY
- sginfo: strip trailing spaces from INQUIRY text
- sg_sat_set_features: add --readonly option
- sg_rbuf: add --echo option (to use echo buffer)
diff --git a/README b/README
index 2f4ca73b..750cbde0 100644
--- a/README
+++ b/README
@@ -403,4 +403,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-28th April 2014
+4th May 2014
diff --git a/debian/changelog b/debian/changelog
index cad487a5..c18078e0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.39-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Mon, 28 Apr 2014 01:00:00 -0400
+ -- Douglas Gilbert <dgilbert@interlog.com> Sun, 04 May 2014 22:00:00 -0400
sg3-utils (1.38-0.1) unstable; urgency=low
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index a73d2611..62504384 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -1,29 +1,29 @@
-.TH SG_LOGS "8" "February 2014" "sg3_utils\-1.38" SG3_UTILS
+.TH SG_LOGS "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_logs \- access log pages with SCSI LOG SENSE command
.SH SYNOPSIS
.B sg_logs
-[\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-control=PC\fR] [\fI\-\-help\fR]
-[\fI\-\-hex\fR] [\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
+[\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-control=PC\fR]
+[\fI\-\-filter=PARC\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-in=FN\fR]
+[\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
[\fI\-\-page=PG[,SPG]\fR] [\fI\-\-paramp=PP\fR] [\fI\-\-pcb\fR]
[\fI\-\-ppc\fR] [\fI\-\-raw\fR] [\fI\-\-reset\fR] [\fI\-\-select\fR]
[\fI\-\-sp\fR] [\fI\-\-temperature\fR] [\fI\-\-transport\fR]
[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_logs
-[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\fR] [\fI\-h\fR] [\fI\-H\fR]
-[\fI\-l\fR] [\fI\-L\fR] [\fI\-m=LEN\fR] [\fI\-n\fR] [\fI\-p=PG[,SPG]\fR]
-[\fI\-paramp=PP\fR] [\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-select\fR]
-[\fI\-sp\fR] [\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR]
-\fIDEVICE\fR
+[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\fR] [\fI\-f=PARC\fR]
+[\fI\-h\fR] [\fI\-H\fR] [\fI\-i=FN\fR] [\fI\-l\fR] [\fI\-L\fR]
+[\fI\-m=LEN\fR] [\fI\-n\fR] [\fI\-p=PG[,SPG]\fR] [\fI\-paramp=PP\fR]
+[\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-select\fR] [\fI\-sp\fR]
+[\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
This utility sends a SCSI LOG SENSE command to the \fIDEVICE\fR and then
outputs the response. The LOG SENSE command is used to fetch log pages. Known
log pages are decoded by default. When the \fI\-\-reset\fR and/or
-\fI\-\-select\fR option is given then a SCSI LOG SELECT command is issued to
-reset parameters (e.g. counters).
+\fI\-\-select\fR option is given then a SCSI LOG SELECT command is issued.
.PP
In SPC\-4 revision 5 a subpage code was introduced to both the LOG SENSE and
LOG SELECT command. At the same time a page code field was introduced to the
@@ -60,6 +60,15 @@ accepts 0, 1, 2 or 3 for the \fIPC\fR argument:
.br
The default value is 1 (i.e. current cumulative values).
.TP
+\fB\-f\fR, \fB\-\-filter\fR=\fIPARC\fR
+only output the log parameter whose parameter code (a number between 0 and
+65535) matches \fIPARC\fR. \fIPARC\fR is assumed to be decimal unless a
+hexadecimal indication is given (e.g. a leading '0x' or a trailing 'h').
+The \fB\-\-hex\fR option outputs log parameter in hexadecimal rather than
+decoding it. If the \fB\-\-hex\fR option is used twice then the leading
+address on each kine of hex is removed. If the \fB\-\-raw\fR option is
+given then the log parameter is output in binary.
+.TP
\fB\-h\fR, \fB\-\-help\fR
print out the usage message then exit.
.TP
@@ -68,6 +77,15 @@ The default action is to decode known mode page numbers (and subpage numbers)
into text. When this option is used once, the response is output in
hexadecimal.
.TP
+\fB\-i\fR, \fB\-\-in\fR=\fIFN\fR
+\fIFN\fR is treated as a file name (or '\-' for stdin) which contains ASCII
+hexadecimal or binary representing a log page that will be sent as parameter
+data of a LOG SELECT command. The hexadecimal should be arranged as 1 or 2
+digits representing a byte each of which is whitespace or comma separated.
+Anything from and including a hash mark to the end of line is ignored. If the
+\fI\-\-raw\fR option is also given then \fIFN\fR is treated as binary. See
+the LOG SELECT section.
+.TP
\fB\-l\fR, \fB\-\-list\fR
lists the names of all logs sense pages supported by this device. This is
done by reading the "supported log pages" log page. When used
@@ -96,9 +114,9 @@ switch to older style options.
\fB\-p\fR, \fB\-\-page\fR=\fIPG[,SPG]\fR
log page code to access. \fIPG\fR is expected to be a decimal number between
0 and 63 inclusive. A hexadecimal number can be specified by a leading "0x"
-or a trailing "h". Common log page codes are listed below. Optionally
-\fISPG\fR, a subpage code, can be given. \fISPG\fR is expected to be a
-decimal number between 0 and 255 inclusive.
+or a trailing "h" so the valid range is 0x to 0x3f. Common log page codes are
+listed below. Optionally \fISPG\fR, a subpage code, can be given. \fISPG\fR
+is expected to be a decimal or hex number between 0 and 255 inclusive.
.TP
\fB\-P\fR, \fB\-\-paramp\fR=\fIPP\fR
\fIPP\fR is the parameter pointer value to place in a field of that name in
@@ -112,7 +130,7 @@ being output in ASCII).
.TP
\fB\-Q\fR, \fB\-\-ppc\fR
sets the Parameter Pointer Control (PPC) bit in the LOG SENSE cdb. Default
-is 0 (i.e. cleared).
+is 0 (i.e. cleared). This bit was made obsolete in SPC\-4 revision 18.
.TP
\fB\-r\fR, \fB\-\-raw\fR
output the response in binary to stdout. Error messages and warnings are
@@ -120,8 +138,7 @@ output to stderr.
.TP
\fB\-R\fR, \fB\-\-reset\fR
use SCSI LOG SELECT command (PCR bit set) to reset the all log pages (or
-the given page). [SPC\-4 (rev 6) doesn't say that a given log (sub)page can
-be reset yet.] Exactly what is reset depends on the accompanying SP
+the given page). Exactly what is reset depends on the accompanying SP
bit (i.e. \fI\-\-sp\fR option which defaults to 0) and the
\fIPC\fR ("page control") value (which defaults to 1). Supplying this option
implies the \fI\-\-select\fR option as well. This option seems to clear error
@@ -132,12 +149,8 @@ which the counter is found will remain "stuck" until something is done.
.TP
\fB\-S\fR, \fB\-\-select\fR
use a LOG SELECT command. The default action (i.e. when neither this option
-nor \fI\-\-reset\fR is given) is to do a LOG SENSE command. When this option
-is given, the SP bit (i.e. \fI\-\-sp\fR option which defaults to 0), the
-\fIPC\fR ("page control") value (which defaults to 1) and the PCR bit (i.e.
-\fI\-\-reset\fR option which defaults to 0) are placed in the LOG SELECT
-cdb. At some stage the log page and subpage options may also be active [but
-SPC\-4 (rev 6) doesn't say that].
+nor \fI\-\-reset\fR is given) is to do a LOG SENSE command. See the LOG
+SELECT section.
.TP
\fB\-s\fR, \fB\-\-sp\fR
sets the Saving Parameters (SP) bit. Default is 0 (i.e. cleared). When set
@@ -154,14 +167,38 @@ that is not available tries the Informational Exceptions log page which
may also have the current temperature (especially on older disks).
.TP
\fB\-T\fR, \fB\-\-transport\fR
-outputs the transport ('Protocol specific port') log page. Equivalent
-to setting '\-\-page=18h'.
+outputs the transport ('Protocol specific port') log page. Equivalent to
+setting '\-\-page=18h'.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase level of verbosity.
.TP
\fB\-V\fR, \fB\-\-version\fR
print out version string then exit.
+.SH LOG SELECT
+The LOG SELECT command can be used to reset certain parameters to vendor
+specific defaults, save them to non-volatile storage (i.e. the media), or
+supply new page contents. This command has changed between SPC\-3 and SPC\-4
+with the addition of the Page and Subpage Code fields which can only be
+non zero when the Parameter list length is zero.
+.PP
+The \fI\-\-select\fR option is required to issue a LOG SELECT command. If
+the \fI\-\-in=FN\fR option is not given (or \fIFN\fR is effectively empty)
+then the Parameter list length field is set to zero. If the \fI\-\-in=FN\fR
+option is is given then its decoded data is placed in the data-out buffer
+and its length in bytes is placed in the Parameter list length field.
+.PP
+Other options that are active with the LOG SELECT command are
+\fI\-\-control=PC\fR, \fI\-\-reset\fR (which sets the PCR bit) and
+\fI\-\-sp\fR.
+.SH
+APPLICATION CLIENT
+This is the name of a log page that acts as a container for data provided
+by the user. An application client is a SCSI term for the program that issues
+commands to a SCSI initiator (often known as a Host Bus Adapter (HBA)).
+.PP
+The Application client log page has 64 log parameters with parameters codes
+0 to 63. Each can hold 252 bytes of user binary data.
.SH NOTES
This utility will usually do a double fetch of log pages with the SCSI LOG
SENSE command. The first fetch requests a 4 byte response (i.e. place 4 in
@@ -213,6 +250,8 @@ the leading "0x", or as their decimal equivalents.]:
.br
0xe Start\-stop cycle counter
.br
+0xf Application client
+.br
0x10 Self\-test results
.br
0x11 Solid state media
@@ -266,6 +305,11 @@ Equivalent to \fI\-\-control=PC\fR in the main description.
suppresses decoding of known log sense pages and prints out the
response in hex instead.
.TP
+\fB\-i\fR=\fIFN\fR
+\fIFN\fR is treated as a file name (or '\-' for stdin) which contains ASCII
+hexadecimal representing a log page that will be sent as parameter data of a
+LOG SELECT command. See the LOG SELECT section.
+.TP
\fB\-H\fR
same action as '\-h' in this section and equivalent to \fI\-\-hex\fR in
the main description.
diff --git a/doc/sg_persist.8 b/doc/sg_persist.8
index 40c84600..c8edfb65 100644
--- a/doc/sg_persist.8
+++ b/doc/sg_persist.8
@@ -160,6 +160,10 @@ Read Keys is a sub\-command of the PRIN command. Lists all the reservation
keys registered (i.e. registrations) with the given SCSI device. This is
the default sub\-command for the SCSI PRIN command.
.TP
+\fB\-y\fR, \fB\-\-readonly\fR
+Open \fIDEVICE\fR read\-only. May be useful with PRIN commands if there are
+unwanted side effects with the default read\-write open.
+.TP
\fB\-r\fR, \fB\-\-read\-reservation\fR
Read Reservation is a sub\-command of the PRIN command. List information
about the current holder of the reservation on the \fIDEVICE\fR. If there
@@ -312,6 +316,9 @@ the PROUT register and ignore existing key sub\-command. In SPC\-4 that
is disallowed yielding a CHECK CONDITION status with and ILLEGAL REQUEST
sense key and an additional sense code set to INVALID FIELD IN PARAMETER
LIST.
+.SH ENVIRONMENT VARIABLES
+Currently there is one recognised environment variable: SG_PERSIST_O_RDONLY
+which is present has the same effect as the \fI\-\-readonly\fR option.
.SH NOTES
In the 2.4 series of Linux kernels the \fIDEVICE\fR must be
a SCSI generic (sg) device. In the 2.6 series any SCSI device
diff --git a/doc/sg_read_buffer.8 b/doc/sg_read_buffer.8
index 271b11c1..482bc13e 100644
--- a/doc/sg_read_buffer.8
+++ b/doc/sg_read_buffer.8
@@ -1,4 +1,4 @@
-.TH SG_READ_BUFFER "8" "November 2012" "sg3_utils\-1.35" SG3_UTILS
+.TH SG_READ_BUFFER "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_read_buffer \- send SCSI READ BUFFER command
.SH SYNOPSIS
@@ -39,9 +39,9 @@ respond with less bytes.
\fB\-m\fR, \fB\-\-mode\fR=\fIMO\fR
this option sets the mode field in the cdb. \fIMO\fR is a value between
0 (default) and 31 inclusive. Alternatively an abbreviation can be given.
-To list the available mode abbreviations use an invalid
-one (e.g. '\-\-mode=xxx'). As an example, to fetch the read buffer
-descriptor give '\-\-mode=desc' .
+See the MODES section below. To list the available mode abbreviations use
+an invalid one (e.g. '\-\-mode=xxx'). As an example, to fetch the read
+buffer descriptor give '\-\-mode=desc' .
.TP
\fB\-o\fR, \fB\-\-offset\fR=\fIOFF\fR
this option sets the buffer offset field in the cdb. \fIOFF\fR is a value
@@ -55,6 +55,40 @@ increase the level of verbosity, (i.e. debug output).
.TP
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit.
+.SH MODES
+Following is a list of READ BUFFER command settings for the MODE field.
+First is an acronym accepted by the \fIMO\fR argument of this utility.
+Following the acronym in square brackets are the corresponding decimal and
+hex values that may also be given for \fIMO\fR. The following are listed
+in numerical order.
+.TP
+hd [0, 0x0]
+Combined header and data (obsolete in SPC\-4).
+.TP
+vendor [1, 0x1]
+Vendor specific.
+.TP
+data [2, 0x2]
+Data.
+.TP
+desc [3, 0x3]
+Descriptor: yields 4 bytes that contain an offset boundary field (1 byte)
+and buffer capacity (3 bytes).
+.TP
+echo [10, 0xa]
+Read data from echo buffer (was called "Echo buffer" in SPC\-3).
+.TP
+echo_desc [11, 0xb]
+Echo buffer descriptor: yields 4 bytes of which the last (lowest) 13 bits
+represent the echo buffer capacity. The maximum echo buffer size is 4096
+bytes.
+.TP
+en_ex [26, 0x1a]
+Enable expander communications protocol and Echo buffer. Made obsolete in
+SPC\-4.
+.TP
+err_hist [28, 0x1c]
+Error history. Introduced in SPC\-4.
.SH NOTES
All numbers given with options are assumed to be decimal.
Alternatively numerical values can be given in hexadecimal preceded by
@@ -67,7 +101,7 @@ Written by Luben Tuikov and Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2006\-2012 Luben Tuikov and Douglas Gilbert
+Copyright \(co 2006\-2014 Luben Tuikov and Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index 58beb923..bd283a88 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "April 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SG_SES "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -115,6 +115,9 @@ Using '\-\-eiioe=force' will decode this page as if the EIIOE bit is set.
Using '\-\-eiioe=auto' will decode this page as if the EIIOE bit is set if
the first element index in this page is 1 (in other words a heuristic to
guess whether the EIIOE bit should be set or not).
+.br
+If the enclosure sets the EIIOE bit 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
diff --git a/sg3_utils.spec b/sg3_utils.spec
index ead38c9e..b663c5b0 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Mon Apr 28 2014 - dgilbert at interlog dot com
+* Sun May 04 2014 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.39
diff --git a/src/sg_inq.c b/src/sg_inq.c
index de859cec..329428be 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -41,7 +41,7 @@
#include "sg_cmds_basic.h"
#include "sg_pt.h"
-static const char * version_str = "1.35 20140415"; /* SPC-4 rev 36s */
+static const char * version_str = "1.36 20140502"; /* SPC-4 rev 36t */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -775,15 +775,18 @@ f2hex_arr(const char * fname, int as_binary, int no_space,
return 1;
has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
if (as_binary) {
- if (has_stdin)
+ if (has_stdin) {
fd = STDIN_FILENO;
- else {
+ if (sg_set_binary_mode(STDIN_FILENO) < 0)
+ perror("sg_set_binary_mode");
+ } else {
fd = open(fname, O_RDONLY);
if (fd < 0) {
pr2serr("unable to open binary file %s: %s\n", fname,
safe_strerror(errno));
return 1;
- }
+ } else if (sg_set_binary_mode(fd) < 0)
+ perror("sg_set_binary_mode");
}
k = read(fd, mp_arr, max_arr_len);
if (k <= 0) {
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 21a7c095..ebd1ec13 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -13,11 +13,13 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
+#include <errno.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -25,7 +27,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
-static const char * version_str = "1.17 20140426"; /* spc4r36r + sbc4r01 */
+static const char * version_str = "1.18 20140504"; /* spc4r36t + sbc4r01 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -68,8 +70,10 @@ static struct option long_options[] = {
{"all", no_argument, 0, 'a'},
{"brief", no_argument, 0, 'b'},
{"control", required_argument, 0, 'c'},
+ {"filter", required_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"hex", no_argument, 0, 'H'},
+ {"in", required_argument, 0, 'i'},
{"list", no_argument, 0, 'l'},
{"maxlen", required_argument, 0, 'm'},
{"name", no_argument, 0, 'n'},
@@ -107,25 +111,51 @@ struct opts_t {
int do_transport;
int do_verbose;
int do_version;
+ int filter;
+ int filter_given;
int page_control;
int maxlen;
int pg_code;
int subpg_code;
int paramp;
- const char * device_name;
int opt_new;
+ const char * device_name;
+ const char * in_fn;
};
+
+#ifdef __GNUC__
+static int pr2serr(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+#else
+static int pr2serr(const char * fmt, ...);
+#endif
+
+
+static int
+pr2serr(const char * fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return n;
+}
+
static void
usage()
{
- printf("Usage: sg_logs [--all] [--brief] [--control=PC] [--help] [--hex] "
- "[--list]\n"
- " [--maxlen=LEN] [--name] [--page=PG[,SPG]] "
- "[--paramp=PP] [--pcb]\n"
- " [--ppc] [--raw] [--reset] [--select] [--sp] "
- "[--temperature]\n"
- " [--transport] [--verbose] [--version] DEVICE\n"
+ pr2serr("Usage: sg_logs [--all] [--brief] [--control=PC] [--filter=PARC] "
+ " [--help]\n"
+ " [--hex] [--in=FN] [--list] [--maxlen=LEN] "
+ "[--name]\n"
+ " [--page=PG[,SPG]] [--paramp=PP] [--pcb] [--ppc] "
+ "[--raw]\n"
+ " [--reset] [--select] [--sp] [--temperature] "
+ "[--transport]\n"
+ " [--verbose] [--version] DEVICE\n"
" where:\n"
" --all|-a fetch and decode all log pages\n"
" use twice to fetch and decode all log pages "
@@ -136,9 +166,15 @@ usage()
"cumulative\n"
" 2: default threshhold, 3: default "
"cumulative\n"
+ " --filter=PARC|-f PARC filter based on parameter code "
+ "PARC\n"
" --help|-h print usage message then exit\n"
" --hex|-H output response in hex (default: decode if "
"known)\n"
+ " --in=FN|-i FN FN is a filename containing a log page "
+ "in ASCII hex\n"
+ " or binary if --raw also given. For LOG "
+ "SELECT\n"
" --list|-l list supported log page names (equivalent to "
"'-p 0')\n"
" use twice to list supported log page and "
@@ -155,14 +191,13 @@ usage()
" --paramp=PP|-P PP parameter pointer (decimal) (def: 0)\n"
" --pcb|-q show parameter control bytes in decoded "
"output\n");
- printf(" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
+ pr2serr(" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
"(def: 0)\n"
- " the PPC bit made obsolete in SPC-4 rev 18\n"
" --raw|-r output response in binary to stdout\n"
" --reset|-R reset log parameters (takes PC and SP into "
"account)\n"
" (uses PCR bit in LOG SELECT)\n"
- " --select|-S perform LOG SELECT using SP and PC values\n"
+ " --select|-S perform LOG SELECT (def: LOG SENSE)\n"
" --sp|-s set the Saving Parameters (SP) bit (def: 0)\n"
" --temperature|-t decode temperature (log page 0xd or "
"0x2f)\n"
@@ -177,20 +212,26 @@ usage()
static void
usage_old()
{
- printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-h] [-H] [-l] [-L] "
- "[-m=LEN] [-n]\n"
- " [-p=PG[,SPG]] [-paramp=PP] [-pcb] [-ppc] "
- "[-r] [-select]\n"
- " [-sp] [-t] [-T] [-v] [-V] [-?] DEVICE\n"
+ printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-f=PARC] [-h] [-H] "
+ "[-i=FN]\n"
+ " [-l] [-L] [-m=LEN] [-n] [-p=PG[,SPG]] "
+ "[-paramp=PP]\n"
+ " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] "
+ "[-v] [-V]\n"
+ " [-?] DEVICE\n"
" where:\n"
" -a fetch and decode all log pages\n"
" -A fetch and decode all log pages and subpages\n"
" -b shorten the output of some log pages\n"
- " -c=PC page control(PC) (default: 1)\n"
+ " -c=PC page control(PC) (default: 1)\n"
" 0: current threshhold, 1: current cumulative\n"
" 2: default threshhold, 3: default cumulative\n"
+ " -f=PARC filter based on parameter code PARC\n"
" -h output in hex (default: decode if known)\n"
" -H output in hex (same as '-h')\n"
+ " -i=FN FN is a filename containing a log page "
+ "in ASCII hex.\n"
+ " For LOG SELECT\n"
" -l list supported log page names (equivalent to "
"'-p=0')\n"
" -L list supported log page and subpages names "
@@ -210,7 +251,7 @@ usage_old()
" -r reset log parameters (takes PC and SP into "
"account)\n"
" (uses PCR bit in LOG SELECT)\n"
- " -select perform LOG SELECT using SP and PC values\n"
+ " -select perform LOG SELECT (def: LOG SENSE)\n"
" -sp set the Saving Parameters (SP) bit (def: 0)\n"
" -t outputs temperature log page (0xd)\n"
" -T outputs transport (protocol specific port) log "
@@ -222,9 +263,9 @@ usage_old()
}
static void
-usage_for(const struct opts_t * optsp)
+usage_for(const struct opts_t * op)
{
- if (optsp->opt_new)
+ if (op->opt_new)
usage();
else
usage_old();
@@ -233,7 +274,7 @@ usage_for(const struct opts_t * optsp)
/* 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 * optsp, int argc, char * argv[])
+process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c, n, nn;
char * cp;
@@ -241,139 +282,150 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "aAbc:hHlLm:nNOp:P:qQrRsStTvV",
+ c = getopt_long(argc, argv, "aAbc:f:hHi:lLm:nNOp:P:qQrRsStTvV",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'a':
- ++optsp->do_all;
+ ++op->do_all;
break;
case 'A':
- optsp->do_all += 2;
+ op->do_all += 2;
break;
case 'b':
- ++optsp->do_brief;
+ ++op->do_brief;
break;
case 'c':
n = sg_get_num(optarg);
if ((n < 0) || (n > 3)) {
- fprintf(stderr, "bad argument to '--control='\n");
+ pr2serr("bad argument to '--control='\n");
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->page_control = n;
+ break;
+ case 'f':
+ n = sg_get_num(optarg);
+ if ((n < 0) || (n > 0xffff)) {
+ pr2serr("bad argument to '--filter='\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->page_control = n;
+ op->filter = n;
+ ++op->filter_given;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
+ break;
+ case 'i':
+ op->in_fn = optarg;
break;
case 'l':
- ++optsp->do_list;
+ ++op->do_list;
break;
case 'L':
- optsp->do_list += 2;
+ op->do_list += 2;
break;
case 'm':
n = sg_get_num(optarg);
if ((n < 0) || (1 == n) || (n > 0xffff)) {
- fprintf(stderr, "bad argument to '--maxlen=', from 2 to "
- "65535 (inclusive) expected\n");
+ pr2serr("bad argument to '--maxlen=', from 2 to 65535 "
+ "(inclusive) expected\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->maxlen = n;
+ op->maxlen = n;
break;
case 'n':
- ++optsp->do_name;
+ ++op->do_name;
break;
case 'N':
break; /* ignore */
case 'O':
- optsp->opt_new = 0;
+ op->opt_new = 0;
return 0;
case 'p':
cp = strchr(optarg, ',');
n = sg_get_num_nomult(optarg);
if ((n < 0) || (n > 63)) {
- fprintf(stderr, "Bad argument to '--page='\n");
+ pr2serr("Bad argument to '--page='\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
if (cp) {
nn = sg_get_num_nomult(cp + 1);
if ((nn < 0) || (nn > 255)) {
- fprintf(stderr, "Bad second value in argument to "
- "'--page='\n");
+ pr2serr("Bad second value in argument to '--page='\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
} else
nn = 0;
- optsp->pg_code = n;
- optsp->subpg_code = nn;
+ op->pg_code = n;
+ op->subpg_code = nn;
break;
case 'P':
n = sg_get_num(optarg);
if (n < 0) {
- fprintf(stderr, "bad argument to '--paramp='\n");
+ pr2serr("bad argument to '--paramp='\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->paramp = n;
+ op->paramp = n;
break;
case 'q':
- ++optsp->do_pcb;
+ ++op->do_pcb;
break;
case 'Q': /* N.B. PPC bit obsoleted in SPC-4 rev 18 */
- ++optsp->do_ppc;
+ ++op->do_ppc;
break;
case 'r':
- ++optsp->do_raw;
+ ++op->do_raw;
break;
case 'R':
- ++optsp->do_pcreset;
- ++optsp->do_select;
+ ++op->do_pcreset;
+ ++op->do_select;
break;
case 's':
- ++optsp->do_sp;
+ ++op->do_sp;
break;
case 'S':
- ++optsp->do_select;
+ ++op->do_select;
break;
case 't':
- ++optsp->do_temperature;
+ ++op->do_temperature;
break;
case 'T':
- ++optsp->do_transport;
+ ++op->do_transport;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
default:
- fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
- if (optsp->do_help)
+ pr2serr("unrecognised option code %c [0x%x]\n", c, c);
+ if (op->do_help)
break;
usage();
return SG_LIB_SYNTAX_ERROR;
}
}
if (optind < argc) {
- if (NULL == optsp->device_name) {
- optsp->device_name = argv[optind];
+ if (NULL == op->device_name) {
+ op->device_name = argv[optind];
++optind;
}
if (optind < argc) {
for (; optind < argc; ++optind)
- fprintf(stderr, "Unexpected extra argument: %s\n",
- argv[optind]);
+ pr2serr("Unexpected extra argument: %s\n", argv[optind]);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -384,7 +436,7 @@ process_cl_new(struct opts_t * optsp, 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 * optsp, int argc, char * argv[])
+process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, num, n;
unsigned int u, uu;
@@ -399,50 +451,50 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
switch (*cp) {
case 'a':
- ++optsp->do_all;
+ ++op->do_all;
break;
case 'A':
- optsp->do_all += 2;
+ op->do_all += 2;
break;
case 'b':
- ++optsp->do_brief;
+ ++op->do_brief;
break;
case 'h':
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'l':
- ++optsp->do_list;
+ ++op->do_list;
break;
case 'L':
- optsp->do_list += 2;
+ op->do_list += 2;
break;
case 'n':
- ++optsp->do_name;
+ ++op->do_name;
break;
case 'N':
- optsp->opt_new = 1;
+ op->opt_new = 1;
return 0;
case 'O':
break;
case 'r':
- optsp->do_pcreset = 1;
- optsp->do_select = 1;
+ op->do_pcreset = 1;
+ op->do_select = 1;
break;
case 't':
- ++optsp->do_temperature;
+ ++op->do_temperature;
break;
case 'T':
- ++optsp->do_transport;
+ ++op->do_transport;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case '-':
++cp;
@@ -460,72 +512,84 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
if (0 == strncmp("c=", cp, 2)) {
num = sscanf(cp + 2, "%x", &u);
if ((1 != num) || (u > 3)) {
- printf("Bad page control after '-c=' option [0..3]\n");
+ pr2serr("Bad page control after '-c=' option [0..3]\n");
+ usage_old();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ op->page_control = u;
+ } else if (0 == strncmp("f=", cp, 2)) {
+ n = sg_get_num(cp + 2);
+ if ((n < 0) || (n > 0xffff)) {
+ pr2serr("Bad argument after '-f=' option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->page_control = u;
- } else if (0 == strncmp("m=", cp, 2)) {
+ op->filter = n;
+ ++op->filter_given;
+ } else if (0 == strncmp("i=", cp, 2))
+ op->in_fn = cp + 2;
+ else if (0 == strncmp("m=", cp, 2)) {
num = sscanf(cp + 2, "%d", &n);
if ((1 != num) || (n < 0) || (n > MX_ALLOC_LEN)) {
- printf("Bad maximum response length after '-m=' option\n");
+ pr2serr("Bad maximum response length after '-m=' "
+ "option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->maxlen = n;
+ op->maxlen = n;
} else if (0 == strncmp("p=", cp, 2)) {
if (NULL == strchr(cp + 2, ',')) {
num = sscanf(cp + 2, "%x", &u);
if ((1 != num) || (u > 63)) {
- fprintf(stderr, "Bad page code value after '-p=' "
- "option\n");
+ pr2serr("Bad page code value after '-p=' option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->pg_code = u;
+ op->pg_code = u;
} else if (2 == sscanf(cp + 2, "%x,%x", &u, &uu)) {
if (uu > 255) {
- fprintf(stderr, "Bad sub page code value after '-p=' "
+ pr2serr("Bad sub page code value after '-p=' "
"option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->pg_code = u;
- optsp->subpg_code = uu;
+ op->pg_code = u;
+ op->subpg_code = uu;
} else {
- fprintf(stderr, "Bad page code, subpage code sequence "
- "after '-p=' option\n");
+ pr2serr("Bad page code, subpage code sequence after "
+ "'-p=' option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strncmp("paramp=", cp, 7)) {
num = sscanf(cp + 7, "%x", &u);
if ((1 != num) || (u > 0xffff)) {
- printf("Bad parameter pointer after '-paramp=' option\n");
+ pr2serr("Bad parameter pointer after '-paramp=' "
+ "option\n");
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->paramp = u;
+ op->paramp = u;
} else if (0 == strncmp("pcb", cp, 3))
- optsp->do_pcb = 1;
+ op->do_pcb = 1;
else if (0 == strncmp("ppc", cp, 3))
- optsp->do_ppc = 1;
+ op->do_ppc = 1;
else if (0 == strncmp("select", cp, 6))
- optsp->do_select = 1;
+ op->do_select = 1;
else if (0 == strncmp("sp", cp, 2))
- optsp->do_sp = 1;
+ op->do_sp = 1;
else if (0 == strncmp("old", cp, 3))
;
else if (jmp_out) {
- fprintf(stderr, "Unrecognized option: %s\n", cp);
+ pr2serr("Unrecognized option: %s\n", cp);
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == optsp->device_name)
- optsp->device_name = cp;
+ } else if (0 == op->device_name)
+ op->device_name = cp;
else {
- fprintf(stderr, "too many arguments, got: %s, not expecting: "
- "%s\n", optsp->device_name, cp);
+ pr2serr("too many arguments, got: %s, not expecting: %s\n",
+ op->device_name, cp);
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
@@ -540,22 +604,22 @@ process_cl_old(struct opts_t * optsp, 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 * optsp, int argc, char * argv[])
+process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
- optsp->opt_new = 0;
- res = process_cl_old(optsp, argc, argv);
- if ((0 == res) && optsp->opt_new)
- res = process_cl_new(optsp, argc, argv);
+ op->opt_new = 0;
+ res = process_cl_old(op, argc, argv);
+ if ((0 == res) && op->opt_new)
+ res = process_cl_new(op, argc, argv);
} else {
- optsp->opt_new = 1;
- res = process_cl_new(optsp, argc, argv);
- if ((0 == res) && (0 == optsp->opt_new))
- res = process_cl_old(optsp, argc, argv);
+ op->opt_new = 1;
+ res = process_cl_new(op, argc, argv);
+ if ((0 == res) && (0 == op->opt_new))
+ res = process_cl_old(op, argc, argv);
}
return res;
}
@@ -591,6 +655,185 @@ decode_count(const unsigned char * xp, int len)
return ull;
}
+/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
+ * stdin). If reading ASCII hex then there should be either one entry per
+ * line or a comma, space or tab separated list of bytes. If no_space is
+ * set then a string of ACSII hex digits is expected, 2 per byte. Everything
+ * from and including a '#' on a line is ignored. Returns 0 if ok, or 1 if
+ * error. */
+static int
+f2hex_arr(const char * fname, int as_binary, int no_space,
+ unsigned char * mp_arr, int * mp_arr_len, int max_arr_len)
+{
+ int fn_len, in_len, k, j, m, split_line, fd, has_stdin;
+ unsigned int h;
+ const char * lcp;
+ FILE * fp;
+ char line[512];
+ char carry_over[4];
+ int off = 0;
+
+ if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
+ return 1;
+ fn_len = strlen(fname);
+ if (0 == fn_len)
+ return 1;
+ has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
+ if (as_binary) {
+ if (has_stdin) {
+ fd = STDIN_FILENO;
+ if (sg_set_binary_mode(STDIN_FILENO) < 0)
+ perror("sg_set_binary_mode");
+ } else {
+ fd = open(fname, O_RDONLY);
+ if (fd < 0) {
+ pr2serr("unable to open binary file %s: %s\n", fname,
+ safe_strerror(errno));
+ return 1;
+ } else if (sg_set_binary_mode(fd) < 0)
+ perror("sg_set_binary_mode");
+ }
+ k = read(fd, mp_arr, max_arr_len);
+ if (k <= 0) {
+ if (0 == k)
+ pr2serr("read 0 bytes from binary file %s\n", fname);
+ else
+ pr2serr("read from binary file %s: %s\n", fname,
+ safe_strerror(errno));
+ if (! has_stdin)
+ close(fd);
+ return 1;
+ }
+ *mp_arr_len = k;
+ if (! has_stdin)
+ close(fd);
+ return 0;
+ } else { /* So read the file as ASCII hex */
+ if (has_stdin)
+ fp = stdin;
+ else {
+ fp = fopen(fname, "r");
+ if (NULL == fp) {
+ pr2serr("Unable to open %s for reading\n", fname);
+ return 1;
+ }
+ }
+ }
+
+ carry_over[0] = 0;
+ for (j = 0; j < 512; ++j) {
+ if (NULL == fgets(line, sizeof(line), fp))
+ break;
+ in_len = strlen(line);
+ if (in_len > 0) {
+ if ('\n' == line[in_len - 1]) {
+ --in_len;
+ line[in_len] = '\0';
+ split_line = 0;
+ } else
+ split_line = 1;
+ }
+ if (in_len < 1) {
+ carry_over[0] = 0;
+ continue;
+ }
+ if (carry_over[0]) {
+ if (isxdigit(line[0])) {
+ carry_over[1] = line[0];
+ carry_over[2] = '\0';
+ if (1 == sscanf(carry_over, "%x", &h))
+ mp_arr[off - 1] = h; /* back up and overwrite */
+ else {
+ pr2serr("f2hex_arr: carry_over error ['%s'] around line "
+ "%d\n", carry_over, j + 1);
+ goto bad;
+ }
+ lcp = line + 1;
+ --in_len;
+ } else
+ lcp = line;
+ carry_over[0] = 0;
+ } else
+ lcp = line;
+
+ m = strspn(lcp, " \t");
+ if (m == in_len)
+ continue;
+ lcp += m;
+ in_len -= m;
+ if ('#' == *lcp)
+ continue;
+ k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
+ if ((k < in_len) && ('#' != lcp[k])) {
+ pr2serr("f2hex_arr: syntax error at line %d, pos %d\n",
+ j + 1, m + k + 1);
+ goto bad;
+ }
+ if (no_space) {
+ for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
+ ++k, lcp += 2) {
+ if (1 != sscanf(lcp, "%2x", &h)) {
+ pr2serr("f2hex_arr: bad hex number in line %d, "
+ "pos %d\n", j + 1, (int)(lcp - line + 1));
+ goto bad;
+ }
+ if ((off + k) >= max_arr_len) {
+ pr2serr("f2hex_arr: array length exceeded\n");
+ goto bad;
+ }
+ mp_arr[off + k] = h;
+ }
+ if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
+ carry_over[0] = *lcp;
+ off += k;
+ } else {
+ for (k = 0; k < 1024; ++k) {
+ if (1 == sscanf(lcp, "%x", &h)) {
+ if (h > 0xff) {
+ pr2serr("f2hex_arr: hex number larger than "
+ "0xff in line %d, pos %d\n", j + 1,
+ (int)(lcp - line + 1));
+ goto bad;
+ }
+ if (split_line && (1 == strlen(lcp))) {
+ /* single trailing hex digit might be a split pair */
+ carry_over[0] = *lcp;
+ }
+ if ((off + k) >= max_arr_len) {
+ pr2serr("f2hex_arr: array length exceeded\n");
+ goto bad;
+ }
+ mp_arr[off + k] = h;
+ lcp = strpbrk(lcp, " ,\t");
+ if (NULL == lcp)
+ break;
+ lcp += strspn(lcp, " ,\t");
+ if ('\0' == *lcp)
+ break;
+ } else {
+ if ('#' == *lcp) {
+ --k;
+ break;
+ }
+ pr2serr("f2hex_arr: error in line %d, at pos %d\n", j + 1,
+ (int)(lcp - line + 1));
+ goto bad;
+ }
+ }
+ off += (k + 1);
+ }
+ }
+ *mp_arr_len = off;
+ if (stdin != fp)
+ fclose(fp);
+ return 0;
+bad:
+ if (stdin != fp)
+ fclose(fp);
+ return 1;
+}
+
+
/* Call LOG SENSE twice: the first time ask for 4 byte response to determine
actual length of response; then a second time requesting the
min(actual_len, mx_resp_len) bytes. If the calculated length for the
@@ -601,18 +844,18 @@ decode_count(const unsigned char * xp, int len)
SG_LIB_CAT_ABORTED_COMMAND and -1 for other errors. */
static int
do_logs(int sg_fd, unsigned char * resp, int mx_resp_len,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int actual_len, res, vb;
memset(resp, 0, mx_resp_len);
- vb = optsp->do_verbose;
- if (optsp->maxlen > 1)
+ vb = op->do_verbose;
+ if (op->maxlen > 1)
actual_len = mx_resp_len;
else {
- if ((res = sg_ll_log_sense(sg_fd, optsp->do_ppc, optsp->do_sp,
- optsp->page_control, optsp->pg_code,
- optsp->subpg_code, optsp->paramp,
+ if ((res = sg_ll_log_sense(sg_fd, op->do_ppc, op->do_sp,
+ op->page_control, op->pg_code,
+ op->subpg_code, op->paramp,
resp, LOG_SENSE_PROBE_ALLOC_LEN,
1 /* noisy */, vb))) {
switch (res) {
@@ -627,21 +870,20 @@ do_logs(int sg_fd, unsigned char * resp, int mx_resp_len,
}
}
actual_len = (resp[2] << 8) + resp[3] + 4;
- if ((0 == optsp->do_raw) && (vb > 1)) {
- fprintf(stderr, " Log sense (find length) response:\n");
+ if ((0 == op->do_raw) && (vb > 1)) {
+ pr2serr(" Log sense (find length) response:\n");
dStrHexErr((const char *)resp, LOG_SENSE_PROBE_ALLOC_LEN, 1);
- fprintf(stderr, " hence calculated response length=%d\n",
- actual_len);
+ pr2serr(" hence calculated response length=%d\n", actual_len);
}
- if (optsp->pg_code != (0x3f & resp[0])) {
+ if (op->pg_code != (0x3f & resp[0])) {
if (vb)
- fprintf(stderr, "Page code does not appear in first byte "
- "of response so it's suspect\n");
+ pr2serr("Page code does not appear in first byte of "
+ "response so it's suspect\n");
if (actual_len > 0x40) {
actual_len = 0x40;
if (vb)
- fprintf(stderr, "Trim response length to 64 bytes due "
- "to suspect response format\n");
+ pr2serr("Trim response length to 64 bytes due to "
+ "suspect response format\n");
}
}
/* Some HBAs don't like odd transfer lengths */
@@ -650,9 +892,9 @@ do_logs(int sg_fd, unsigned char * resp, int mx_resp_len,
if (actual_len > mx_resp_len)
actual_len = mx_resp_len;
}
- if ((res = sg_ll_log_sense(sg_fd, optsp->do_ppc, optsp->do_sp,
- optsp->page_control, optsp->pg_code,
- optsp->subpg_code, optsp->paramp,
+ if ((res = sg_ll_log_sense(sg_fd, op->do_ppc, op->do_sp,
+ op->page_control, op->pg_code,
+ op->subpg_code, op->paramp,
resp, actual_len, 1 /* noisy */, vb))) {
switch (res) {
case SG_LIB_CAT_NOT_READY:
@@ -665,8 +907,8 @@ do_logs(int sg_fd, unsigned char * resp, int mx_resp_len,
return -1;
}
}
- if ((0 == optsp->do_raw) && (vb > 1)) {
- fprintf(stderr, " Log sense response:\n");
+ if ((0 == op->do_raw) && (vb > 1)) {
+ pr2serr(" Log sense response:\n");
dStrHexErr((const char *)resp, actual_len, 1);
}
return 0;
@@ -938,24 +1180,36 @@ get_pcb_str(int pcb, char * outp, int maxoutlen)
/* BUFF_OVER_UNDER_LPAGE [0x1] */
static void
-show_buffer_under_over_run_page(unsigned char * resp, int len, int show_pcb)
+show_buffer_under_over_run_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
- int num, pl, pcb;
- unsigned int paramc;
+ int num, pl, pcb, pc;
uint64_t count;
unsigned char * ucp;
const char * cp;
char pcb_str[PCB_STR_LEN];
- printf("Buffer over-run/under-run page (spc-2) [0x1]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Buffer over-run/under-run page (spc-2) [0x1]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
cp = NULL;
pl = ucp[3] + 4;
count = (pl > 4) ? decode_count(ucp + 4, pl - 4) : 0;
- paramc = (ucp[0] << 8) + ucp[1];
- switch (paramc) {
+ pc = (ucp[0] << 8) + ucp[1];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
case 0x0:
cp = "under-run";
break;
@@ -1030,18 +1284,21 @@ show_buffer_under_over_run_page(unsigned char * resp, int len, int show_pcb)
break;
default:
printf(" undefined parameter code [0x%x], count = %" PRIu64 "",
- paramc, count);
+ pc, count);
break;
}
if (cp)
printf(" %s = %" PRIu64 "", cp, count);
- if (show_pcb) {
+ if (op->do_pcb) {
pcb = ucp[2];
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -1050,29 +1307,34 @@ show_buffer_under_over_run_page(unsigned char * resp, int len, int show_pcb)
/* WRITE_ERR_LPAGE; READ_ERR_LPAGE; READ_REV_ERR_LPAGE; VERIFY_ERR_LPAGE */
/* [0x2, 0x3, 0x4, 0x5] */
static void
-show_error_counter_page(unsigned char * resp, int len, int show_pcb)
+show_error_counter_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb, pg_code;
unsigned char * ucp;
char pcb_str[PCB_STR_LEN];
pg_code = resp[0] & 0x3f;
- switch(pg_code) {
- case WRITE_ERR_LPAGE:
- printf("Write error counter page (spc-3) [0x%x]\n", pg_code);
- break;
- case READ_ERR_LPAGE:
- printf("Read error counter page (spc-3) [0x%x]\n", pg_code);
- break;
- case READ_REV_ERR_LPAGE:
- printf("Read Reverse error counter page (spc-3) [0x%x]\n", pg_code);
- break;
- case VERIFY_ERR_LPAGE:
- printf("Verify error counter page (spc-3) [0x%x]\n", pg_code);
- break;
- default:
- printf("expecting error counter page, got page = 0x%x\n", resp[0]);
- return;
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ switch(pg_code) {
+ case WRITE_ERR_LPAGE:
+ printf("Write error counter page (spc-3) [0x%x]\n", pg_code);
+ break;
+ case READ_ERR_LPAGE:
+ printf("Read error counter page (spc-3) [0x%x]\n", pg_code);
+ break;
+ case READ_REV_ERR_LPAGE:
+ printf("Read Reverse error counter page (spc-3) [0x%x]\n",
+ pg_code);
+ break;
+ case VERIFY_ERR_LPAGE:
+ printf("Verify error counter page (spc-3) [0x%x]\n", pg_code);
+ break;
+ default:
+ pr2serr("expecting error counter page, got page = 0x%x\n",
+ resp[0]);
+ return;
+ }
}
num = len - 4;
ucp = &resp[0] + 4;
@@ -1080,6 +1342,17 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb)
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0: printf(" Errors corrected without substantial delay"); break;
case 1: printf(" Errors corrected with possible delays"); break;
@@ -1093,11 +1366,14 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb)
default: printf(" Reserved or vendor specific [0x%x]", pc); break;
}
printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -1105,22 +1381,36 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb)
/* NON_MEDIUM_LPAGE [0x6] */
static void
-show_non_medium_error_page(unsigned char * resp, int len, int show_pcb)
+show_non_medium_error_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
char pcb_str[PCB_STR_LEN];
- printf("Non-medium error page (spc-2) [0x6]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Non-medium error page (spc-2) [0x6]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0:
- printf(" Non-medium error count"); break;
+ printf(" Non-medium error count");
+ break;
default:
if (pc <= 0x7fff)
printf(" Reserved [0x%x]", pc);
@@ -1129,11 +1419,14 @@ show_non_medium_error_page(unsigned char * resp, int len, int show_pcb)
break;
}
printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -1142,19 +1435,31 @@ show_non_medium_error_page(unsigned char * resp, int len, int show_pcb)
/* PCT_LPAGE [0x1a] */
static void
show_power_condition_transitions_page(unsigned char * resp, int len,
- int show_pcb)
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
char pcb_str[PCB_STR_LEN];
- printf("Power condition transitions page (spc-4) [0x1a]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Power condition transitions page (spc-4) [0x1a]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0:
printf(" Accumulated transitions to active"); break;
@@ -1172,11 +1477,14 @@ show_power_condition_transitions_page(unsigned char * resp, int len,
printf(" Reserved [0x%x]", pc);
}
printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -1184,7 +1492,8 @@ show_power_condition_transitions_page(unsigned char * resp, int len,
/* Tape usage: Vendor specific (IBM): 0x30 */
static void
-show_tape_usage_log_page(unsigned char * resp, int len, int show_pcb)
+show_tape_usage_log_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, num, extra, pc, pcb;
unsigned int n;
@@ -1195,14 +1504,27 @@ show_tape_usage_log_page(unsigned char * resp, int len, int show_pcb)
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed tape usage page\n");
+ pr2serr("badly formed tape usage page\n");
return;
}
- printf("Tape usage page (IBM specific) [0x30]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Tape usage page (IBM specific) [0x30]\n");
for (k = num; k > 0; k -= extra, ucp += extra) {
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
extra = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
ull = n = 0;
switch (ucp[3]) {
case 2:
@@ -1268,17 +1590,20 @@ show_tape_usage_log_page(unsigned char * resp, int len, int show_pcb)
dStrHex((const char *)ucp, extra, 1);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
/* Tape capacity: vendor specific (IBM): 0x31 */
static void
-show_tape_capacity_log_page(unsigned char * resp, int len, int show_pcb)
+show_tape_capacity_log_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, num, extra, pc, pcb;
unsigned int n;
@@ -1288,14 +1613,27 @@ show_tape_capacity_log_page(unsigned char * resp, int len, int show_pcb)
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed tape capacity page\n");
+ pr2serr("badly formed tape capacity page\n");
return;
}
- printf("Tape capacity page (IBM specific) [0x31]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Tape capacity page (IBM specific) [0x31]\n");
for (k = num; k > 0; k -= extra, ucp += extra) {
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
extra = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
if (extra != 8)
continue;
n = (ucp[4] << 24) | (ucp[5] << 16) | (ucp[6] << 8) | ucp[7];
@@ -1318,18 +1656,21 @@ show_tape_capacity_log_page(unsigned char * resp, int len, int show_pcb)
dStrHex((const char *)ucp, extra, 1);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
/* Data compression: originally vendor specific 0x32 (IBM), then
* ssc-4 standardizes it at 0x1b */
static void
-show_data_compression_log_page(unsigned char * resp, int len, int show_pcb)
+show_data_compression_log_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, j, pl, num, extra, pc, pcb, pg_code;
uint64_t n;
@@ -1340,19 +1681,33 @@ show_data_compression_log_page(unsigned char * resp, int len, int show_pcb)
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed data compression page\n");
+ pr2serr("badly formed data compression page\n");
return;
}
- if (0x1b == pg_code)
- printf("Data compression page (ssc-4) [0x1b]\n");
- else
- printf("Data compression page (IBM specific) [0x%x]\n",
- pg_code);
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (0x1b == pg_code)
+ printf("Data compression page (ssc-4) [0x1b]\n");
+ else
+ printf("Data compression page (IBM specific) [0x%x]\n",
+ pg_code);
+ }
for (k = num; k > 0; k -= extra, ucp += extra) {
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
pl = ucp[3];
extra = pl + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
if ((0 == pl) || (pl > 8)) {
printf("badly formed data compression log parameter\n");
printf(" parameter code = 0x%x, contents in hex:\n", pc);
@@ -1405,17 +1760,20 @@ show_data_compression_log_page(unsigned char * resp, int len, int show_pcb)
break;
}
skip_para:
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
/* LAST_N_ERR_LPAGE [0x7] */
static void
-show_last_n_error_page(unsigned char * resp, int len, int show_pcb)
+show_last_n_error_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, num, pl, pc, pcb;
unsigned char * ucp;
@@ -1427,7 +1785,8 @@ show_last_n_error_page(unsigned char * resp, int len, int show_pcb)
printf("No error events logged\n");
return;
}
- printf("Last n error events page (spc-2) [0x7]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Last n error events page (spc-2) [0x7]\n");
for (k = num; k > 0; k -= pl, ucp += pl) {
if (k < 3) {
printf("short Last n error events page\n");
@@ -1436,6 +1795,17 @@ show_last_n_error_page(unsigned char * resp, int len, int show_pcb)
pl = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
printf(" Error event %d:\n", pc);
if (pl > 4) {
if ((pcb & 0x1) && (pcb & 0x2)) {
@@ -1448,16 +1818,19 @@ show_last_n_error_page(unsigned char * resp, int len, int show_pcb)
dStrHex((const char *)ucp + 4, pl - 4, 1);
}
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
}
}
/* LAST_N_DEFERRED_LPAGE [0xb] */
static void
-show_last_n_deferred_error_page(unsigned char * resp, int len, int show_pcb)
+show_last_n_deferred_error_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, num, pl, pc, pcb;
unsigned char * ucp;
@@ -1469,7 +1842,8 @@ show_last_n_deferred_error_page(unsigned char * resp, int len, int show_pcb)
printf("No deferred errors logged\n");
return;
}
- printf("Last n deferred errors page (spc-2) [0xb]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Last n deferred errors page (spc-2) [0xb]\n");
for (k = num; k > 0; k -= pl, ucp += pl) {
if (k < 3) {
printf("short Last n deferred errors page\n");
@@ -1478,12 +1852,25 @@ show_last_n_deferred_error_page(unsigned char * resp, int len, int show_pcb)
pl = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
printf(" Deferred error %d:\n", pc);
dStrHex((const char *)ucp + 4, pl - 4, 1);
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
}
}
@@ -1507,9 +1894,9 @@ static const char * self_test_result[] = {
/* SELF_TEST_LPAGE [0x10] */
static void
-show_self_test_page(unsigned char * resp, int len, int show_pcb)
+show_self_test_page(unsigned char * resp, int len, const struct opts_t * op)
{
- int k, num, n, res, pcb;
+ int k, num, n, res, pc, pl, pcb;
unsigned int v;
unsigned char * ucp;
uint64_t ull;
@@ -1518,23 +1905,36 @@ show_self_test_page(unsigned char * resp, int len, int show_pcb)
num = len - 4;
if (num < 0x190) {
- printf("short self-test results page [length 0x%x rather than "
- "0x190 bytes]\n", num);
+ pr2serr("short self-test results page [length 0x%x rather than "
+ "0x190 bytes]\n", num);
return;
}
- printf("Self-test results page (spc-3) [0x10]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Self-test results page (spc-3) [0x10]\n");
for (k = 0, ucp = resp + 4; k < 20; ++k, ucp += 20 ) {
pcb = ucp[2];
+ pl = ucp[3] + 4;
+ pc = (ucp[0] << 8) + ucp[1];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
n = (ucp[6] << 8) | ucp[7];
if ((0 == n) && (0 == ucp[4]))
break;
printf(" Parameter code = %d, accumulated power-on hours = %d\n",
- (ucp[0] << 8) | ucp[1], n);
+ pc, n);
printf(" self-test code: %s [%d]\n",
self_test_code[(ucp[4] >> 5) & 0x7], (ucp[4] >> 5) & 0x7);
res = ucp[4] & 0xf;
- printf(" self-test result: %s [%d]\n",
- self_test_result[res], res);
+ printf(" self-test result: %s [%d]\n", self_test_result[res], res);
if (ucp[5])
printf(" self-test number = %d\n", (int)ucp[5]);
ull = ucp[8]; ull <<= 8; ull |= ucp[9]; ull <<= 8; ull |= ucp[10];
@@ -1552,18 +1952,20 @@ show_self_test_page(unsigned char * resp, int len, int show_pcb)
printf(" [%s]\n", sg_get_asc_ascq_str(ucp[17], ucp[18],
sizeof(b), b));
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
/* TEMPERATURE_LPAGE [0xd] */
static void
-show_temperature_page(unsigned char * resp, int len, int show_pcb, int hdr,
- int show_unknown)
+show_temperature_page(unsigned char * resp, int len,
+ const struct opts_t * op, int show_extra)
{
int k, num, extra, pc, pcb;
unsigned char * ucp;
@@ -1572,51 +1974,72 @@ show_temperature_page(unsigned char * resp, int len, int show_pcb, int hdr,
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed Temperature page\n");
+ pr2serr("badly formed Temperature page\n");
return;
}
- if (hdr)
- printf("Temperature page (spc-3) [0xd]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (show_extra)
+ printf("Temperature page (spc-3) [0xd]\n");
+ }
for (k = num; k > 0; k -= extra, ucp += extra) {
if (k < 3) {
- printf("short Temperature page\n");
+ pr2serr("short Temperature page\n");
return;
}
extra = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
- if (0 == pc) {
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0:
if ((extra > 5) && (k > 5)) {
if (ucp[5] < 0xff)
printf(" Current temperature = %d C", ucp[5]);
else
printf(" Current temperature = <not available>");
}
- } else if (1 == pc) {
+ break;
+ case 1:
if ((extra > 5) && (k > 5)) {
if (ucp[5] < 0xff)
printf(" Reference temperature = %d C", ucp[5]);
else
printf(" Reference temperature = <not available>");
}
-
- } else if (show_unknown) {
- printf(" unknown parameter code = 0x%x, contents in "
- "hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
- } else
- continue;
- if (show_pcb) {
+ break;
+ default:
+ if (show_extra) {
+ printf(" unknown parameter code = 0x%x, contents in "
+ "hex:\n", pc);
+ dStrHex((const char *)ucp, extra, 1);
+ } else
+ continue;
+ break;
+ }
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
/* START_STOP_LPAGE [0xe] */
static void
-show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose)
+show_start_stop_page(unsigned char * resp, int len, const struct opts_t * op)
{
int k, num, extra, pc, pcb;
unsigned int n;
@@ -1626,26 +2049,39 @@ show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose)
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed Start-stop cycle counter page\n");
+ pr2serr("badly formed Start-stop cycle counter page\n");
return;
}
- printf("Start-stop cycle counter page (spc-3) [0xe]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Start-stop cycle counter page (spc-3) [0xe]\n");
for (k = num; k > 0; k -= extra, ucp += extra) {
if (k < 3) {
- printf("short Start-stop cycle counter page\n");
+ pr2serr("short Start-stop cycle counter page\n");
return;
}
extra = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 1:
if (10 == extra)
printf(" Date of manufacture, year: %.4s, week: %.2s",
&ucp[4], &ucp[8]);
- else if (verbose) {
- fprintf(stderr, " Date of manufacture parameter length "
- "strange: %d\n", extra - 4);
+ else if (op->do_verbose) {
+ pr2serr(" Date of manufacture parameter length strange: "
+ "%d\n", extra - 4);
dStrHexErr((const char *)ucp, extra, 1);
}
break;
@@ -1653,9 +2089,9 @@ show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose)
if (10 == extra)
printf(" Accounting date, year: %.4s, week: %.2s",
&ucp[4], &ucp[8]);
- else if (verbose) {
- fprintf(stderr, " Accounting date parameter length "
- "strange: %d\n", extra - 4);
+ else if (op->do_verbose) {
+ pr2serr(" Accounting date parameter length strange: %d\n",
+ extra - 4);
dStrHexErr((const char *)ucp, extra, 1);
}
break;
@@ -1705,17 +2141,75 @@ show_start_stop_page(unsigned char * resp, int len, int show_pcb, int verbose)
dStrHex((const char *)ucp, extra, 1);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
+ get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
+ printf("\n <%s>\n", pcb_str);
+ } else
+ printf("\n");
+ if (op->filter_given)
+ break;
+ }
+}
+
+/* APP_CLIENT_LPAGE [0xf] */
+static void
+show_app_client_page(unsigned char * resp, int len, const struct opts_t * op)
+{
+ int k, num, extra, pc, pcb;
+ unsigned char * ucp;
+ char pcb_str[PCB_STR_LEN];
+
+ num = len - 4;
+ ucp = &resp[0] + 4;
+ if (num < 4) {
+ pr2serr("badly formed Application Client page\n");
+ return;
+ }
+ if (op->do_verbose || ((op->do_raw == 0) && (op->do_hex == 0)))
+ printf("Application client page (spc-3) [0xf]\n");
+ if (0 == op->filter_given) {
+ if ((len > 128) && (0 == op->do_hex)) {
+ dStrHex((const char *)resp, 64, 1);
+ printf(" ..... [truncated after 64 of %d bytes (use '-H' to "
+ "see the rest)]\n", len);
+ }
+ else
+ dStrHex((const char *)resp, len, 1);
+ return;
+ }
+ /* only here if filter_given set */
+ for (k = num; k > 0; k -= extra, ucp += extra) {
+ if (k < 3) {
+ pr2serr("short Application client page\n");
+ return;
+ }
+ extra = ucp[3] + 4;
+ pc = (ucp[0] << 8) + ucp[1];
+ pcb = ucp[2];
+ if (op->filter != pc)
+ continue;
+ if (op->do_raw)
+ dStrRaw((const char *)ucp, extra);
+ else if (0 == op->do_hex)
+ dStrHex((const char *)ucp, extra, 0);
+ else if (1 == op->do_hex)
+ dStrHex((const char *)ucp, extra, 1);
+ else
+ dStrHex((const char *)ucp, extra, -1);
+
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ break;
}
}
/* IE_LPAGE [0x2f] */
static void
-show_ie_page(unsigned char * resp, int len, int show_pcb, int full)
+show_ie_page(unsigned char * resp, int len, const struct opts_t * op,
+ int full)
{
int k, num, extra, pc, pcb;
unsigned char * ucp;
@@ -1725,11 +2219,13 @@ show_ie_page(unsigned char * resp, int len, int show_pcb, int full)
num = len - 4;
ucp = &resp[0] + 4;
if (num < 4) {
- printf("badly formed Informational Exceptions page\n");
+ pr2serr("badly formed Informational Exceptions page\n");
return;
}
- if (full)
- printf("Informational Exceptions page (spc-3) [0x2f]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (full)
+ printf("Informational Exceptions page (spc-3) [0x2f]\n");
+ }
for (k = num; k > 0; k -= extra, ucp += extra) {
if (k < 3) {
printf("short Informational Exceptions page\n");
@@ -1738,7 +2234,20 @@ show_ie_page(unsigned char * resp, int len, int show_pcb, int full)
extra = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
- if (0 == pc) {
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0:
if (extra > 5) {
if (full) {
printf(" IE asc = 0x%x, ascq = 0x%x", ucp[4], ucp[5]);
@@ -1761,15 +2270,21 @@ show_ie_page(unsigned char * resp, int len, int show_pcb, int full)
}
}
}
- } else if (full) {
- printf(" parameter code = 0x%x, contents in hex:\n", pc);
- dStrHex((const char *)ucp, extra, 1);
+ break;
+ default:
+ if (full) {
+ printf(" parameter code = 0x%x, contents in hex:\n", pc);
+ dStrHex((const char *)ucp, extra, 1);
+ }
+ break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
}
}
@@ -1910,7 +2425,7 @@ show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val)
/* PROTO_SPECIFIC_LPAGE [0x18] for a SAS port */
static void
show_sas_port_param(unsigned char * ucp, int param_len,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int j, m, n, nphys, pcb, t, sz, spld_len;
unsigned char * vcp;
@@ -1922,20 +2437,20 @@ show_sas_port_param(unsigned char * ucp, int param_len,
sz = sizeof(s);
pcb = ucp[2];
t = (ucp[0] << 8) | ucp[1];
- if (optsp->do_name)
+ if (op->do_name)
printf("rel_target_port=%d\n", t);
else
printf("relative target port id = %d\n", t);
- if (optsp->do_name)
+ if (op->do_name)
printf(" gen_code=%d\n", ucp[6]);
else
printf(" generation code = %d\n", ucp[6]);
nphys = ucp[7];
- if (optsp->do_name)
+ if (op->do_name)
printf(" num_phys=%d\n", nphys);
else {
printf(" number of phys = %d", nphys);
- if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ if ((op->do_pcb) && (0 == op->do_name)) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
@@ -1944,7 +2459,7 @@ show_sas_port_param(unsigned char * ucp, int param_len,
for (j = 0, vcp = ucp + 8; j < (param_len - 8);
vcp += spld_len, j += spld_len) {
- if (optsp->do_name)
+ if (op->do_name)
printf(" phy_id=%d\n", vcp[1]);
else
printf(" phy identifier = %d\n", vcp[1]);
@@ -1953,7 +2468,7 @@ show_sas_port_param(unsigned char * ucp, int param_len,
spld_len = 48; /* in SAS-1 and SAS-1.1 vcp[3]==0 */
else
spld_len += 4;
- if (optsp->do_name) {
+ if (op->do_name) {
t = ((0x70 & vcp[4]) >> 4);
printf(" att_dev_type=%d\n", t);
printf(" att_iport_mask=0x%x\n", vcp[6]);
@@ -2092,12 +2607,12 @@ show_sas_port_param(unsigned char * ucp, int param_len,
unsigned int pvdt;
num_ped = vcp[51];
- if (optsp->do_verbose > 1)
+ if (op->do_verbose > 1)
printf(" <<Phy event descriptors: %d, spld_len: %d, "
"calc_ped: %d>>\n", num_ped, spld_len,
(spld_len - 52) / 12);
if (num_ped > 0) {
- if (optsp->do_name) {
+ if (op->do_name) {
printf(" phy_event_desc_num=%d\n", num_ped);
return; /* don't decode at this stage */
} else
@@ -2112,7 +2627,7 @@ show_sas_port_param(unsigned char * ucp, int param_len,
xcp[11];
show_sas_phy_event_info(pes, ui, pvdt);
}
- } else if (optsp->do_verbose)
+ } else if (op->do_verbose)
printf(" <<No phy event descriptors>>\n");
}
}
@@ -2120,24 +2635,45 @@ show_sas_port_param(unsigned char * ucp, int param_len,
/* PROTO_SPECIFIC_LPAGE [0x18] */
static int
show_protocol_specific_page(unsigned char * resp, int len,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
- int k, num, param_len;
+ int k, num, pl, pc, pid;
unsigned char * ucp;
num = len - 4;
- if (optsp->do_name)
- printf("log_page=0x%x\n", PROTO_SPECIFIC_LPAGE);
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (op->do_name)
+ printf("log_page=0x%x\n", PROTO_SPECIFIC_LPAGE);
+ }
for (k = 0, ucp = resp + 4; k < num; ) {
- param_len = ucp[3] + 4;
- if (6 != (0xf & ucp[4]))
+ pc = (ucp[0] << 8) + ucp[1];
+ pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ pid = 0xf & ucp[4];
+ if (6 != pid) {
+ pr2serr("Protocol identifier: %d, only support SAS (SPL) which "
+ "is 6\n", pid);
return 0; /* only decode SAS log page */
- if ((0 == k) && (0 == optsp->do_name))
+ }
+ if ((0 == k) && (0 == op->do_name))
printf("Protocol Specific port page for SAS SSP (sas-2) "
"[0x18]\n");
- show_sas_port_param(ucp, param_len, optsp);
- k += param_len;
- ucp += param_len;
+ show_sas_port_param(ucp, pl, op);
+ if (op->filter_given)
+ break;
+skip:
+ k += pl;
+ ucp += pl;
}
return 1;
}
@@ -2146,7 +2682,7 @@ show_protocol_specific_page(unsigned char * resp, int len,
/* STATS_LPAGE [0x19], subpages: 0x0 to 0x1f */
static int
show_stats_perform_page(unsigned char * resp, int len,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int k, num, n, param_len, param_code, spf, subpg_code, extra;
int pcb, nam;
@@ -2155,21 +2691,24 @@ show_stats_perform_page(unsigned char * resp, int len,
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- nam = optsp->do_name;
+ nam = op->do_name;
num = len - 4;
ucp = resp + 4;
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
- if (nam) {
- printf("log_page=0x%x\n", STATS_LPAGE);
- if (subpg_code > 0)
- printf("log_subpage=0x%x\n", subpg_code);
- } else {
- if (0 == subpg_code)
- printf("General Statistics and Performance (spc-4) [0x19]\n");
- else
- printf("Group Statistics and Performance (%d) (spc-4) "
- "[0x19,0x%x]\n", subpg_code, subpg_code);
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (nam) {
+ printf("log_page=0x%x\n", STATS_LPAGE);
+ if (subpg_code > 0)
+ printf("log_subpage=0x%x\n", subpg_code);
+ } else {
+ if (0 == subpg_code)
+ printf("General Statistics and Performance (spc-4) "
+ "[0x19]\n");
+ else
+ printf("Group Statistics and Performance (%d) (spc-4) "
+ "[0x19,0x%x]\n", subpg_code, subpg_code);
+ }
}
if (subpg_code > 31)
return 0;
@@ -2183,6 +2722,18 @@ show_stats_perform_page(unsigned char * resp, int len,
extra = param_len + 4;
param_code = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (param_code != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (param_code) {
case 1: /* Statistics and performance log parameter */
ccp = nam ? "parameter_code=1" : "Statistics and performance "
@@ -2337,16 +2888,18 @@ show_stats_perform_page(unsigned char * resp, int len,
printf("parameter_code=%d\n", param_code);
printf(" unknown=1\n");
} else
- fprintf(stderr, "show_performance... unknown parameter "
- "code %d\n", param_code);
- if (optsp->do_verbose)
+ pr2serr("show_performance... unknown parameter code "
+ "%d\n", param_code);
+ if (op->do_verbose)
dStrHexErr((const char *)ucp, extra, 1);
break;
}
- if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ if ((op->do_pcb) && (0 == op->do_name)) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
}
} else { /* Group statistics and performance (n) log page */
if (num < 0x34)
@@ -2358,6 +2911,18 @@ show_stats_perform_page(unsigned char * resp, int len,
extra = param_len + 4;
param_code = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (param_code != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (param_code) {
case 1: /* Group n Statistics and performance log parameter */
if (nam)
@@ -2460,16 +3025,18 @@ show_stats_perform_page(unsigned char * resp, int len,
printf("parameter_code=%d\n", param_code);
printf(" unknown=1\n");
} else
- fprintf(stderr, "show_performance... unknown parameter "
- "code %d\n", param_code);
- if (optsp->do_verbose)
+ pr2serr("show_performance... unknown parameter code "
+ "%d\n", param_code);
+ if (op->do_verbose)
dStrHexErr((const char *)ucp, extra, 1);
break;
}
- if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ if ((op->do_pcb) && (0 == op->do_name)) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
}
}
return 1;
@@ -2479,7 +3046,7 @@ show_stats_perform_page(unsigned char * resp, int len,
/* STATS_LPAGE [0x19], CACHE_STATS_SUBPG [0x20] */
static int
show_cache_stats_page(unsigned char * resp, int len,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int k, num, n, pc, spf, subpg_code, extra;
int pcb, nam;
@@ -2488,25 +3055,27 @@ show_cache_stats_page(unsigned char * resp, int len,
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- nam = optsp->do_name;
+ nam = op->do_name;
num = len - 4;
ucp = resp + 4;
if (num < 4) {
- printf("badly formed Cache memory statistics page\n");
+ pr2serr("badly formed Cache memory statistics page\n");
return 0;
}
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
- if (nam) {
- printf("log_page=0x%x\n", STATS_LPAGE);
- if (subpg_code > 0)
- printf("log_subpage=0x%x\n", subpg_code);
- } else
- printf("Cache memory statistics page (spc-4) [0x19,0x20]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (nam) {
+ printf("log_page=0x%x\n", STATS_LPAGE);
+ if (subpg_code > 0)
+ printf("log_subpage=0x%x\n", subpg_code);
+ } else
+ printf("Cache memory statistics page (spc-4) [0x19,0x20]\n");
+ }
for (k = num; k > 0; k -= extra, ucp += extra) {
if (k < 3) {
- printf("short Cache memory statistics page\n");
+ pr2serr("short Cache memory statistics page\n");
return 0;
}
if (8 != ucp[3]) {
@@ -2517,6 +3086,18 @@ show_cache_stats_page(unsigned char * resp, int len,
extra = ucp[3] + 4;
pc = (ucp[0] << 8) + ucp[1];
pcb = ucp[2];
+ if (op->filter_given) {
+ if (pc != op->filter)
+ continue;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, extra);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, extra,
+ ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 1: /* Read cache memory hits log parameter */
ccp = nam ? "parameter_code=1" :
@@ -2595,23 +3176,26 @@ show_cache_stats_page(unsigned char * resp, int len,
printf("parameter_code=%d\n", pc);
printf(" unknown=1\n");
} else
- fprintf(stderr, "show_performance... unknown parameter "
- "code %d\n", pc);
- if (optsp->do_verbose)
+ pr2serr("show_performance... unknown parameter code %d\n",
+ pc);
+ if (op->do_verbose)
dStrHexErr((const char *)ucp, extra, 1);
break;
}
- if ((optsp->do_pcb) && (0 == optsp->do_name)) {
+ if ((op->do_pcb) && (0 == op->do_name)) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
}
return 1;
}
/* FORMAT_STATUS_LPAGE [0x8] */
static void
-show_format_status_page(unsigned char * resp, int len, int show_pcb)
+show_format_status_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int k, j, num, pl, pc, pcb, all_ff, counter;
unsigned char * ucp;
@@ -2619,13 +3203,25 @@ show_format_status_page(unsigned char * resp, int len, int show_pcb)
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- printf("Format status page (sbc-2) [0x8]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Format status page (sbc-2) [0x8]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
counter = 1;
switch (pc) {
case 0: printf(" Format data out:\n");
@@ -2663,17 +3259,20 @@ show_format_status_page(unsigned char * resp, int len, int show_pcb)
printf(" <not available>");
else
printf(" = %" PRIu64 "", ull);
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
} else {
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
}
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -2681,19 +3280,32 @@ show_format_status_page(unsigned char * resp, int len, int show_pcb)
/* Non-volatile cache page [0x17] */
static void
-show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb)
+show_non_volatile_cache_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int j, num, pl, pc, pcb;
unsigned char * ucp;
char pcb_str[PCB_STR_LEN];
- printf("Non-volatile cache page (sbc-2) [0x17]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Non-volatile cache page (sbc-2) [0x17]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0:
printf(" Remaining non-volatile time: ");
@@ -2742,10 +3354,13 @@ show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb)
dStrHex((const char *)ucp, pl, 0);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -2753,20 +3368,33 @@ show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb)
/* LB_PROV_LPAGE [0xc] */
static void
-show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb)
+show_lb_provisioning_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int j, num, pl, pc, pcb;
unsigned char * ucp;
const char * cp;
char str[PCB_STR_LEN];
- printf("Logical block provisioning page (sbc-3) [0xc]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Logical block provisioning page (sbc-3) [0xc]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0x1:
cp = " Available LBA mapping threshold";
@@ -2791,11 +3419,11 @@ show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb)
printf(" %s resource count:", cp);
if ((pl < 8) || (num < 8)) {
if (num < 8)
- fprintf(stderr, "\n truncated by response length, "
- "expected at least 8 bytes\n");
+ pr2serr("\n truncated by response length, expected at "
+ "least 8 bytes\n");
else
- fprintf(stderr, "\n parameter length >= 8 expected, "
- "got %d\n", pl);
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
break;
}
j = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
@@ -2816,10 +3444,13 @@ show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb)
printf(" Reserved [parameter_code=0x%x]:\n", pc);
dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -2827,39 +3458,58 @@ show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb)
/* SOLID_STATE_MEDIA_LPAGE [0x11] */
static void
-show_solid_state_media_page(unsigned char * resp, int len, int show_pcb)
+show_solid_state_media_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
char str[PCB_STR_LEN];
- printf("Solid state media page (sbc-3) [0x11]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Solid state media page (sbc-3) [0x11]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
- if (0x1 == pc) {
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
+ switch (pc) {
+ case 0x1:
printf(" Percentage used endurance indicator:");
if ((pl < 8) || (num < 8)) {
if (num < 8)
- fprintf(stderr, "\n truncated by response length, "
- "expected at least 8 bytes\n");
+ pr2serr("\n truncated by response length, expected "
+ "at least 8 bytes\n");
else
- fprintf(stderr, "\n parameter length >= 8 expected, "
- "got %d\n", pl);
+ pr2serr("\n parameter length >= 8 expected, got %d\n",
+ pl);
break;
}
printf(" %d%%\n", ucp[7]);
- } else {
+ break;
+ default:
printf(" Reserved [parameter_code=0x%x]:\n", pc);
dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
+ break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -2887,29 +3537,42 @@ static const char * dt_dev_activity[] = {
/* DT device status [0x11] (ssc, adc) */
static void
-show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
+show_dt_device_status_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb, j;
unsigned char * ucp;
char str[PCB_STR_LEN];
- printf("DT device status page (ssc-3, adc-3) [0x11]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("DT device status page (ssc-3, adc-3) [0x11]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0x0:
printf(" Very high frequency data:\n");
if ((pl < 8) || (num < 8)) {
if (num < 8)
- fprintf(stderr, " truncated by response length, "
- "expected at least 8 bytes\n");
+ pr2serr(" truncated by response length, expected at "
+ "least 8 bytes\n");
else
- fprintf(stderr, " parameter length >= 8 expected, "
- "got %d\n", pl);
+ pr2serr(" parameter length >= 8 expected, got %d\n",
+ pl);
break;
}
printf(" PAMR=%d HUI=%d MACC=%d CMPR=%d ", !!(0x80 & ucp[4]),
@@ -2938,11 +3601,11 @@ show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
printf(" Very high frequency polling delay: ");
if ((pl < 6) || (num < 6)) {
if (num < 6)
- fprintf(stderr, "\n truncated by response length, "
- "expected at least 6 bytes\n");
+ pr2serr("\n truncated by response length, expected at "
+ "least 6 bytes\n");
else
- fprintf(stderr, "\n parameter length >= 6 expected, "
- "got %d\n", pl);
+ pr2serr("\n parameter length >= 6 expected, got %d\n",
+ pl);
break;
}
printf(" %d milliseconds\n", (ucp[4] << 8) + ucp[5]);
@@ -2952,11 +3615,11 @@ show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
"only now):\n");
if ((pl < 12) || (num < 12)) {
if (num < 12)
- fprintf(stderr, " truncated by response length, "
- "expected at least 12 bytes\n");
+ pr2serr(" truncated by response length, expected at "
+ "least 12 bytes\n");
else
- fprintf(stderr, " parameter length >= 12 expected, "
- "got %d\n", pl);
+ pr2serr(" parameter length >= 12 expected, got %d\n",
+ pl);
break;
}
dStrHex((const char *)ucp + 4, 8, 1);
@@ -2965,11 +3628,11 @@ show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
printf(" Key management error data (hex only now):\n");
if ((pl < 16) || (num < 16)) {
if (num < 16)
- fprintf(stderr, " truncated by response length, "
- "expected at least 16 bytes\n");
+ pr2serr(" truncated by response length, expected at "
+ "least 16 bytes\n");
else
- fprintf(stderr, " parameter length >= 16 expected, "
- "got %d\n", pl);
+ pr2serr(" parameter length >= 16 expected, got %d\n",
+ pl);
break;
}
dStrHex((const char *)ucp + 4, 12, 1);
@@ -2980,10 +3643,13 @@ show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
break;
}
// xxxxxxxxxxxxxxx
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -2991,20 +3657,33 @@ show_dt_device_status_page(unsigned char * resp, int len, int show_pcb)
/* SAT_ATA_RESULTS_LPAGE (SAT-2) [0x16] */
static void
-show_ata_pt_results_page(unsigned char * resp, int len, int show_pcb)
+show_ata_pt_results_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
unsigned char * dp;
char str[PCB_STR_LEN];
- printf("ATA pass-through results page (sat-2) [0x16]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("ATA pass-through results page (sat-2) [0x16]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
if ((pc < 0xf) && (pl > 17)) {
int extend, sector_count;
@@ -3024,10 +3703,13 @@ show_ata_pt_results_page(unsigned char * resp, int len, int show_pcb)
printf(" Reserved [parameter_code=0x%x]:\n", pc);
dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3062,30 +3744,42 @@ static const char * reassign_status[] = {
/* Background scan results [0x15,0] for disk */
static void
-show_background_scan_results_page(unsigned char * resp, int len, int show_pcb,
- int verbose)
+show_background_scan_results_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int j, m, num, pl, pc, pcb;
unsigned char * ucp;
char str[PCB_STR_LEN];
- printf("Background scan results page (sbc-3) [0x15]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Background scan results page (sbc-3) [0x15]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0:
printf(" Status parameters:\n");
if ((pl < 16) || (num < 16)) {
if (num < 16)
- fprintf(stderr, " truncated by response length, "
- "expected at least 16 bytes\n");
+ pr2serr(" truncated by response length, expected at "
+ "least 16 bytes\n");
else
- fprintf(stderr, " parameter length >= 16 expected, "
- "got %d\n", pl);
+ pr2serr(" parameter length >= 16 expected, got %d\n",
+ pl);
break;
}
printf(" Accumulated power on minutes: ");
@@ -3129,11 +3823,11 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb,
printf(" Medium scan parameter # %d [0x%x]\n", pc, pc);
if ((pl < 24) || (num < 24)) {
if (num < 24)
- fprintf(stderr, " truncated by response length, "
- "expected at least 24 bytes\n");
+ pr2serr(" truncated by response length, expected at "
+ "least 24 bytes\n");
else
- fprintf(stderr, " parameter length >= 24 expected, "
- "got %d\n", pl);
+ pr2serr(" parameter length >= 24 expected, got %d\n",
+ pl);
break;
}
printf(" Power on minutes when error detected: ");
@@ -3151,7 +3845,7 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb,
if (ucp[9] || ucp[10])
printf(" %s\n", sg_get_asc_ascq_str(ucp[9], ucp[10],
sizeof(str), str));
- if (verbose) {
+ if (op->do_verbose) {
printf(" vendor bytes [11 -> 15]: ");
for (m = 0; m < 5; ++m)
printf("0x%02x ", ucp[11 + m]);
@@ -3163,10 +3857,13 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb,
printf("\n");
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3174,49 +3871,61 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb,
/* Sequential access device page [0xc] for tape */
static void
-show_sequential_access_page(unsigned char * resp, int len, int show_pcb,
- int verbose)
+show_sequential_access_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
uint64_t ull, gbytes;
char pcb_str[PCB_STR_LEN];
- printf("Sequential access device page (ssc-3)\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Sequential access device page (ssc-3)\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
ull = decode_count(ucp + 4, pl - 4);
gbytes = ull / 1000000000;
switch (pc) {
case 0:
printf(" Data bytes received with WRITE commands: %" PRIu64
" GB", gbytes);
- if (verbose)
+ if (op->do_verbose)
printf(" [%" PRIu64 " bytes]", ull);
printf("\n");
break;
case 1:
printf(" Data bytes written to media by WRITE commands: %" PRIu64
" GB", gbytes);
- if (verbose)
+ if (op->do_verbose)
printf(" [%" PRIu64 " bytes]", ull);
printf("\n");
break;
case 2:
printf(" Data bytes read from media by READ commands: %" PRIu64
" GB", gbytes);
- if (verbose)
+ if (op->do_verbose)
printf(" [%" PRIu64 " bytes]", ull);
printf("\n");
break;
case 3:
printf(" Data bytes transferred by READ commands: %" PRIu64
" GB", gbytes);
- if (verbose)
+ if (op->do_verbose)
printf(" [%" PRIu64 " bytes]", ull);
printf("\n");
break;
@@ -3245,7 +3954,7 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb,
printf(" Cleaning action required\n");
else
printf(" Cleaning action not required (or completed)\n");
- if (verbose)
+ if (op->do_verbose)
printf(" cleaning value: %" PRIu64 "\n", ull);
break;
default:
@@ -3257,10 +3966,13 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb,
pc, ull);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3268,20 +3980,33 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb,
/* 0x14 for tape and ADC */
static void
-show_device_stats_page(unsigned char * resp, int len, int show_pcb)
+show_device_stats_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- printf("Device statistics page (ssc-3 and adc)\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Device statistics page (ssc-3 and adc)\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
if (pc < 0x1000) {
ull = decode_count(ucp + 4, pl - 4);
switch (pc) {
@@ -3350,10 +4075,13 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb)
break;
}
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3361,20 +4089,32 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb)
/* 0x14 for media changer */
static void
-show_media_stats_page(unsigned char * resp, int len, int show_pcb)
+show_media_stats_page(unsigned char * resp, int len, const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- printf("Media statistics page (smc-3)\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Media statistics page (smc-3)\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
ull = decode_count(ucp + 4, pl - 4);
switch (pc) {
case 0:
@@ -3472,10 +4212,13 @@ show_media_stats_page(unsigned char * resp, int len, int show_pcb)
pc, ull);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3483,20 +4226,33 @@ show_media_stats_page(unsigned char * resp, int len, int show_pcb)
/* 0x15 for media changer */
static void
-show_element_stats_page(unsigned char * resp, int len, int show_pcb)
+show_element_stats_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned int v;
unsigned char * ucp;
char str[PCB_STR_LEN];
- printf("Element statistics page (smc-3) [0x15]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Element statistics page (smc-3) [0x15]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
printf(" Element address: %d\n", pc);
v = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7];
printf(" Number of places: %u\n", v);
@@ -3510,10 +4266,13 @@ show_element_stats_page(unsigned char * resp, int len, int show_pcb)
printf(" Number of determined volume identifiers: %u\n", v);
v = (ucp[24] << 24) + (ucp[25] << 16) + (ucp[26] << 8) + ucp[27];
printf(" Number of unreadable volume identifiers: %u\n", v);
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3521,7 +4280,8 @@ show_element_stats_page(unsigned char * resp, int len, int show_pcb)
/* 0x16 for tape */
static void
-show_tape_diag_data_page(unsigned char * resp, int len, int show_pcb)
+show_tape_diag_data_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned int v;
@@ -3529,13 +4289,25 @@ show_tape_diag_data_page(unsigned char * resp, int len, int show_pcb)
char str[PCB_STR_LEN];
char b[80];
- printf("Tape diagnostics data page (ssc-3) [0x16]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Tape diagnostics data page (ssc-3) [0x16]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
printf(" Parameter code: %d\n", pc);
printf(" Density code: 0x%x\n", ucp[6]);
printf(" Medium type: 0x%x\n", ucp[7]);
@@ -3568,10 +4340,13 @@ show_tape_diag_data_page(unsigned char * resp, int len, int show_pcb)
printf(" Vendor specific:\n");
dStrHex((const char *)(ucp + 72), pl - 72, 0);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3579,7 +4354,8 @@ show_tape_diag_data_page(unsigned char * resp, int len, int show_pcb)
/* 0x16 for media changer */
static void
-show_mchanger_diag_data_page(unsigned char * resp, int len, int show_pcb)
+show_mchanger_diag_data_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned int v;
@@ -3587,13 +4363,25 @@ show_mchanger_diag_data_page(unsigned char * resp, int len, int show_pcb)
char str[PCB_STR_LEN];
char b[80];
- printf("Media changer diagnostics data page (smc-3) [0x16]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Media changer diagnostics data page (smc-3) [0x16]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
printf(" Parameter code: %d\n", pc);
printf(" Repeat: %d\n", !!(ucp[5] & 0x80));
v = ucp[5] & 0xf;
@@ -3646,10 +4434,13 @@ show_mchanger_diag_data_page(unsigned char * resp, int len, int show_pcb)
printf(" Timestamp:\n");
dStrHex((const char *)(ucp + 94), 6, 1);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3707,7 +4498,8 @@ volume_stats_partition(const unsigned char * xp, int len, int hex)
/* Volume Statistics log page (ssc-4) [0x17, 0x1-0xf] */
static void
-show_volume_stats_page(unsigned char * resp, int len, int show_pcb)
+show_volume_stats_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb, spf, subpg_code;
unsigned char * ucp;
@@ -3715,15 +4507,18 @@ show_volume_stats_page(unsigned char * resp, int len, int show_pcb)
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
- if (0 == subpg_code)
- printf("Volume statistics page (ssc-4) but subpage=0, abnormal: "
- "treat like subpage=1\n");
- else if (subpg_code < 0x10)
- printf("Volume statistics page (ssc-4), subpage=%d\n", subpg_code);
- else {
- printf("Volume statistics page (ssc-4), subpage=%d; Reserved, "
- "skip\n", subpg_code);
- return;
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex))) {
+ if (0 == subpg_code)
+ printf("Volume statistics page (ssc-4) but subpage=0, abnormal: "
+ "treat like subpage=1\n");
+ else if (subpg_code < 0x10)
+ printf("Volume statistics page (ssc-4), subpage=%d\n",
+ subpg_code);
+ else {
+ printf("Volume statistics page (ssc-4), subpage=%d; Reserved, "
+ "skip\n", subpg_code);
+ return;
+ }
}
num = len - 4;
ucp = &resp[0] + 4;
@@ -3731,6 +4526,17 @@ show_volume_stats_page(unsigned char * resp, int len, int show_pcb)
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0:
@@ -3894,7 +4700,7 @@ show_volume_stats_page(unsigned char * resp, int len, int show_pcb)
break;
case 0x300:
printf(" Mount history, payload in hex:\n");
- // xxxxxxxxxxxxxxxxx
+ // xxxxxxxx TODO
dStrHex((const char *)(ucp + 4), pl - 4, 0);
break;
@@ -3908,10 +4714,13 @@ show_volume_stats_page(unsigned char * resp, int len, int show_pcb)
dStrHex((const char *)(ucp + 4), pl - 4, 0);
break;
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf(" <%s>\n", pcb_str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -3983,25 +4792,37 @@ static const char * tape_alert_strs[] = {
/* TAPE_ALERT_LPAGE [0x2e] */
static void
-show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb,
- const struct opts_t * optsp)
+show_tape_alert_ssc_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb, flag;
unsigned char * ucp;
char str[PCB_STR_LEN];
/* N.B. the Tape alert log page for smc-3 is different */
- printf("Tape alert page (ssc-3) [0x2e]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Tape alert page (ssc-3) [0x2e]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
flag = ucp[4] & 1;
- if (optsp->do_verbose && (0 == optsp->do_brief) && flag)
+ if (op->do_verbose && (0 == op->do_brief) && flag)
printf(" >>>> ");
- if ((0 == optsp->do_brief) || optsp->do_verbose || flag) {
+ if ((0 == op->do_brief) || op->do_verbose || flag) {
if (pc < (int)(sizeof(tape_alert_strs) /
sizeof(tape_alert_strs[0])))
printf(" %s: %d\n", tape_alert_strs[pc], flag);
@@ -4009,10 +4830,13 @@ show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb,
printf(" Reserved parameter code 0x%x, flag: %d\n", pc,
flag);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, str, sizeof(str));
printf(" <%s>\n", str);
}
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -4020,19 +4844,32 @@ show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb,
/* 0x37 */
static void
-show_seagate_cache_page(unsigned char * resp, int len, int show_pcb)
+show_seagate_cache_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb;
unsigned char * ucp;
char pcb_str[PCB_STR_LEN];
- printf("Seagate cache page [0x37]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Seagate cache page [0x37]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
switch (pc) {
case 0: printf(" Blocks sent to initiator"); break;
case 1: printf(" Blocks received from initiator"); break;
@@ -4049,11 +4886,14 @@ show_seagate_cache_page(unsigned char * resp, int len, int show_pcb)
default: printf(" Unknown Seagate parameter code = 0x%x", pc); break;
}
printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4));
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -4061,20 +4901,33 @@ show_seagate_cache_page(unsigned char * resp, int len, int show_pcb)
/* 0x3e */
static void
-show_seagate_factory_page(unsigned char * resp, int len, int show_pcb)
+show_seagate_factory_page(unsigned char * resp, int len,
+ const struct opts_t * op)
{
int num, pl, pc, pcb, valid;
unsigned char * ucp;
uint64_t ull;
char pcb_str[PCB_STR_LEN];
- printf("Seagate/Hitachi factory page [0x3e]\n");
+ if (op->do_verbose || ((0 == op->do_raw) && (0 == op->do_hex)))
+ printf("Seagate/Hitachi factory page [0x3e]\n");
num = len - 4;
ucp = &resp[0] + 4;
while (num > 3) {
pc = (ucp[0] << 8) | ucp[1];
pcb = ucp[2];
pl = ucp[3] + 4;
+ if (op->filter_given) {
+ if (pc != op->filter)
+ goto skip;
+ if (op->do_raw) {
+ dStrRaw((const char *)ucp, pl);
+ break;
+ } else if (op->do_hex) {
+ dStrHex((const char *)ucp, pl, ((1 == op->do_hex) ? 1 : -1));
+ break;
+ }
+ }
valid = 1;
switch (pc) {
case 0: printf(" number of hours powered up"); break;
@@ -4092,11 +4945,14 @@ show_seagate_factory_page(unsigned char * resp, int len, int show_pcb)
else
printf(" = %" PRIu64 "", ull);
}
- if (show_pcb) {
+ if (op->do_pcb) {
get_pcb_str(pcb, pcb_str, sizeof(pcb_str));
printf("\n <%s>\n", pcb_str);
} else
printf("\n");
+ if (op->filter_given)
+ break;
+skip:
num -= pl;
ucp += pl;
}
@@ -4105,12 +4961,12 @@ show_seagate_factory_page(unsigned char * resp, int len, int show_pcb)
static void
show_ascii_page(unsigned char * resp, int len,
struct sg_simple_inquiry_resp * inq_dat,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int k, num, done, pg_code, subpg_code, spf;
if (len < 0) {
- printf("response has bad length\n");
+ pr2serr("%s: response has bad length\n", __func__);
return;
}
num = len - 4;
@@ -4142,26 +4998,26 @@ show_ascii_page(unsigned char * resp, int len,
}
break;
case BUFF_OVER_UNDER_LPAGE: /* 0x1 */
- show_buffer_under_over_run_page(resp, len, optsp->do_pcb);
+ show_buffer_under_over_run_page(resp, len, op);
break;
case WRITE_ERR_LPAGE: /* 0x2 */
case READ_ERR_LPAGE: /* 0x3 */
case READ_REV_ERR_LPAGE: /* 0x4 */
case VERIFY_ERR_LPAGE: /* 0x5 */
- show_error_counter_page(resp, len, optsp->do_pcb);
+ show_error_counter_page(resp, len, op);
break;
case NON_MEDIUM_LPAGE: /* 0x6 */
- show_non_medium_error_page(resp, len, optsp->do_pcb);
+ show_non_medium_error_page(resp, len, op);
break;
case LAST_N_ERR_LPAGE: /* 0x7 */
- show_last_n_error_page(resp, len, optsp->do_pcb);
+ show_last_n_error_page(resp, len, op);
break;
case FORMAT_STATUS_LPAGE: /* 0x8 */
{
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
- show_format_status_page(resp, len, optsp->do_pcb);
+ show_format_status_page(resp, len, op);
break;
default:
done = 0;
@@ -4170,18 +5026,17 @@ show_ascii_page(unsigned char * resp, int len,
}
break;
case LAST_N_DEFERRED_LPAGE: /* 0xb */
- show_last_n_deferred_error_page(resp, len, optsp->do_pcb);
+ show_last_n_deferred_error_page(resp, len, op);
break;
case 0xc:
{
switch (inq_dat->peripheral_type) {
case PDT_DISK: /* LB_PROV_LPAGE */
- show_lb_provisioning_page(resp, len, optsp->do_pcb);
+ show_lb_provisioning_page(resp, len, op);
break;
case PDT_TAPE: case PDT_PRINTER:
/* tape and (printer) type devices */
- show_sequential_access_page(resp, len, optsp->do_pcb,
- optsp->do_verbose);
+ show_sequential_access_page(resp, len, op);
break;
default:
done = 0;
@@ -4190,21 +5045,24 @@ show_ascii_page(unsigned char * resp, int len,
}
break;
case TEMPERATURE_LPAGE: /* 0xd */
- show_temperature_page(resp, len, optsp->do_pcb, 1, 1);
+ show_temperature_page(resp, len, op, 1);
break;
case START_STOP_LPAGE: /* 0xe */
- show_start_stop_page(resp, len, optsp->do_pcb, optsp->do_verbose);
+ show_start_stop_page(resp, len, op);
+ break;
+ case APP_CLIENT_LPAGE: /* 0xf */
+ show_app_client_page(resp, len, op);
break;
case SELF_TEST_LPAGE: /* 0x10 */
- show_self_test_page(resp, len, optsp->do_pcb);
+ show_self_test_page(resp, len, op);
break;
case SOLID_STATE_MEDIA_LPAGE: /* 0x11 */
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
- show_solid_state_media_page(resp, len, optsp->do_pcb);
+ show_solid_state_media_page(resp, len, op);
break;
case PDT_TAPE: case PDT_ADC:
- show_dt_device_status_page(resp, len, optsp->do_pcb);
+ show_dt_device_status_page(resp, len, op);
break;
default:
done = 0;
@@ -4216,10 +5074,10 @@ show_ascii_page(unsigned char * resp, int len,
switch (inq_dat->peripheral_type) {
case PDT_TAPE: case PDT_ADC:
/* tape and adc type devices */
- show_device_stats_page(resp, len, optsp->do_pcb);
+ show_device_stats_page(resp, len, op);
break;
case PDT_MCHANGER: /* smc-3 */
- show_media_stats_page(resp, len, optsp->do_pcb);
+ show_media_stats_page(resp, len, op);
break;
default:
done = 0;
@@ -4233,13 +5091,12 @@ show_ascii_page(unsigned char * resp, int len,
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
if (0 == subpg_code)
- show_background_scan_results_page(resp, len,
- optsp->do_pcb, optsp->do_verbose);
+ show_background_scan_results_page(resp, len, op);
else
done = 0; /* todo: pending defects [0x15,1] */
break;
case PDT_MCHANGER: /* smc-3 */
- show_element_stats_page(resp, len, optsp->do_pcb);
+ show_element_stats_page(resp, len, op);
break;
default:
done = 0;
@@ -4252,13 +5109,13 @@ show_ascii_page(unsigned char * resp, int len,
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
- show_ata_pt_results_page(resp, len, optsp->do_pcb);
+ show_ata_pt_results_page(resp, len, op);
break;
case PDT_TAPE: /* ssc-4 */
- show_tape_diag_data_page(resp, len, optsp->do_pcb);
+ show_tape_diag_data_page(resp, len, op);
break;
case PDT_MCHANGER: /* smc-3 */
- show_mchanger_diag_data_page(resp, len, optsp->do_pcb);
+ show_mchanger_diag_data_page(resp, len, op);
break;
default:
done = 0;
@@ -4271,10 +5128,10 @@ show_ascii_page(unsigned char * resp, int len,
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
- show_non_volatile_cache_page(resp, len, optsp->do_pcb);
+ show_non_volatile_cache_page(resp, len, op);
break;
case PDT_TAPE: /* ssc-4, subpages 1 to 0xf */
- show_volume_stats_page(resp, len, optsp->do_pcb);
+ show_volume_stats_page(resp, len, op);
break;
default:
done = 0;
@@ -4283,27 +5140,27 @@ show_ascii_page(unsigned char * resp, int len,
}
break;
case PROTO_SPECIFIC_LPAGE: /* 0x18 */
- done = show_protocol_specific_page(resp, len, optsp);
+ done = show_protocol_specific_page(resp, len, op);
break;
case STATS_LPAGE: /* 0x19, defined for subpages 0 to 32 inclusive */
if (subpg_code <= HIGH_GRP_STATS_SUBPG)
- done = show_stats_perform_page(resp, len, optsp);
+ done = show_stats_perform_page(resp, len, op);
else if (subpg_code == CACHE_STATS_SUBPG)
- done = show_cache_stats_page(resp, len, optsp);
+ done = show_cache_stats_page(resp, len, op);
else
done = 0;
break;
case PCT_LPAGE: /* 0x1a */
- show_power_condition_transitions_page(resp, len, optsp->do_pcb);
+ show_power_condition_transitions_page(resp, len, op);
break;
case 0x1b:
- show_data_compression_log_page(resp, len, optsp->do_pcb);
+ show_data_compression_log_page(resp, len, op);
break;
case TAPE_ALERT_LPAGE: /* 0x2e */
{
switch (inq_dat->peripheral_type) {
case PDT_TAPE: /* ssc only */
- show_tape_alert_ssc_page(resp, len, optsp->do_pcb, optsp);
+ show_tape_alert_ssc_page(resp, len, op);
break;
default:
done = 0;
@@ -4312,23 +5169,23 @@ show_ascii_page(unsigned char * resp, int len,
}
break;
case 0x30: /* vendor specific: IBM */
- show_tape_usage_log_page(resp, len, optsp->do_pcb);
+ show_tape_usage_log_page(resp, len, op);
break;
case 0x31: /* vendor specific: IBM */
- show_tape_capacity_log_page(resp, len, optsp->do_pcb);
+ show_tape_capacity_log_page(resp, len, op);
break;
case 0x32: /* vendor specific, now tweaked and standardized at 0x1b */
- show_data_compression_log_page(resp, len, optsp->do_pcb);
+ show_data_compression_log_page(resp, len, op);
break;
case IE_LPAGE:
- show_ie_page(resp, len, optsp->do_pcb, 1);
+ show_ie_page(resp, len, op, 1);
break;
case 0x37:
{
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
- show_seagate_cache_page(resp, len, optsp->do_pcb);
+ show_seagate_cache_page(resp, len, op);
break;
default:
done = 0;
@@ -4341,7 +5198,7 @@ show_ascii_page(unsigned char * resp, int len,
switch (inq_dat->peripheral_type) {
case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC:
/* disk (direct access) type devices */
- show_seagate_factory_page(resp, len, optsp->do_pcb);
+ show_seagate_factory_page(resp, len, op);
break;
default:
done = 0;
@@ -4372,38 +5229,38 @@ show_ascii_page(unsigned char * resp, int len,
static int
fetchTemperature(int sg_fd, unsigned char * resp, int max_len,
- struct opts_t * optsp)
+ struct opts_t * op)
{
int len;
int res = 0;
- optsp->pg_code = TEMPERATURE_LPAGE;
- optsp->subpg_code = NOT_SPG_SUBPG;
- res = do_logs(sg_fd, resp, max_len, optsp);
+ op->pg_code = TEMPERATURE_LPAGE;
+ op->subpg_code = NOT_SPG_SUBPG;
+ res = do_logs(sg_fd, resp, max_len, op);
if (0 == res) {
len = (resp[2] << 8) + resp[3] + 4;
- if (optsp->do_raw)
+ if (op->do_raw)
dStrRaw((const char *)resp, len);
- else if (optsp->do_hex)
- dStrHex((const char *)resp, len, (1 == optsp->do_hex));
+ else if (op->do_hex)
+ dStrHex((const char *)resp, len, (1 == op->do_hex));
else
- show_temperature_page(resp, len, optsp->do_pcb, 0, 0);
+ show_temperature_page(resp, len, op, 0);
}else if (SG_LIB_CAT_NOT_READY == res)
- fprintf(stderr, "Device not ready\n");
+ pr2serr("Device not ready\n");
else {
- optsp->pg_code = IE_LPAGE;
- res = do_logs(sg_fd, resp, max_len, optsp);
+ op->pg_code = IE_LPAGE;
+ res = do_logs(sg_fd, resp, max_len, op);
if (0 == res) {
len = (resp[2] << 8) + resp[3] + 4;
- if (optsp->do_raw)
+ if (op->do_raw)
dStrRaw((const char *)resp, len);
- else if (optsp->do_hex)
- dStrHex((const char *)resp, len, (1 == optsp->do_hex));
+ else if (op->do_hex)
+ dStrHex((const char *)resp, len, (1 == op->do_hex));
else
- show_ie_page(resp, len, 0, 0);
+ show_ie_page(resp, len, op, 0);
} else
- fprintf(stderr, "Unable to find temperature in either "
- "Temperature or IE log page\n");
+ pr2serr("Unable to find temperature in either Temperature or "
+ "IE log page\n");
}
sg_cmds_close_device(sg_fd);
return (res >= 0) ? res : SG_LIB_CAT_OTHER;
@@ -4414,126 +5271,164 @@ int
main(int argc, char * argv[])
{
int sg_fd, k, pg_len, res, resp_len;
+ int in_len = -1;
int ret = 0;
struct sg_simple_inquiry_resp inq_out;
struct opts_t opts;
+ struct opts_t * op;
- memset(&opts, 0, sizeof(opts));
+ op = &opts;
+ memset(op, 0, sizeof(opts));
memset(rsp_buff, 0, sizeof(rsp_buff));
/* N.B. some disks only give data for current cumulative */
- opts.page_control = 1;
- res = process_cl(&opts, argc, argv);
+ op->page_control = 1;
+ res = process_cl(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
- if (opts.do_help) {
- usage_for(&opts);
+ if (op->do_help) {
+ usage_for(op);
return 0;
}
- if (opts.do_version) {
- fprintf(stderr, "Version string: %s\n", version_str);
+ if (op->do_version) {
+ pr2serr("Version string: %s\n", version_str);
return 0;
}
- if (NULL == opts.device_name) {
- fprintf(stderr, "No DEVICE argument given\n");
- usage_for(&opts);
+ if (NULL == op->device_name) {
+ pr2serr("No DEVICE argument given\n");
+ usage_for(op);
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.do_raw) {
+ if (op->do_select) {
+ if (op->do_temperature) {
+ pr2serr("--select cannot be used with --temperature\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (op->do_transport) {
+ pr2serr("--select cannot be used with --transport\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ } else if (op->do_raw) {
if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
perror("sg_set_binary_mode");
return SG_LIB_FILE_ERROR;
}
}
+ if (op->do_all) {
+ if (op->do_select) {
+ pr2serr("--all conflicts with --select\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (op->filter) {
+ pr2serr("--all conflicts with --filter\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (op->in_fn) {
+ if (! op->do_select) {
+ pr2serr("--in=FN can only be used with --select\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ if (f2hex_arr(op->in_fn, op->do_raw, 0, rsp_buff, &in_len,
+ sizeof(rsp_buff)))
+ return SG_LIB_FILE_ERROR;
+ }
- if ((sg_fd = sg_cmds_open_device(opts.device_name, 0 /* rw */,
- opts.do_verbose)) < 0) {
- if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* r0 */,
- opts.do_verbose)) < 0) {
- fprintf(stderr, "error opening file: %s: %s \n",
- opts.device_name, safe_strerror(-sg_fd));
+ if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /* rw */,
+ op->do_verbose)) < 0) {
+ if ((sg_fd = sg_cmds_open_device(op->device_name, 1 /* r0 */,
+ op->do_verbose)) < 0) {
+ pr2serr("error opening file: %s: %s \n", op->device_name,
+ safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
}
- if (opts.do_list || opts.do_all) {
- opts.pg_code = SUPP_PAGES_LPAGE;
- if ((opts.do_list > 1) || (opts.do_all > 1))
- opts.subpg_code = SUPP_SPGS_SUBPG;
+ if (op->do_list || op->do_all) {
+ op->pg_code = SUPP_PAGES_LPAGE;
+ if ((op->do_list > 1) || (op->do_all > 1))
+ op->subpg_code = SUPP_SPGS_SUBPG;
}
- if (opts.do_transport) {
- if ((opts.pg_code > 0) || (opts.subpg_code > 0) ||
- opts.do_temperature) {
- fprintf(stderr, "'-T' should not be mixed with options "
- "implying other pages\n");
+ if (op->do_transport) {
+ if ((op->pg_code > 0) || (op->subpg_code > 0) ||
+ op->do_temperature) {
+ pr2serr("'-T' should not be mixed with options implying other "
+ "pages\n");
return SG_LIB_FILE_ERROR;
}
- opts.pg_code = PROTO_SPECIFIC_LPAGE;
+ op->pg_code = PROTO_SPECIFIC_LPAGE;
}
pg_len = 0;
- if (0 == opts.do_raw) {
- if (sg_simple_inquiry(sg_fd, &inq_out, 1, opts.do_verbose)) {
- fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n",
- opts.device_name);
+ if ((0 == op->do_raw) && (0 == op->do_select)) {
+ if (sg_simple_inquiry(sg_fd, &inq_out, 1, op->do_verbose)) {
+ pr2serr("%s doesn't respond to a SCSI INQUIRY\n",
+ op->device_name);
sg_cmds_close_device(sg_fd);
return SG_LIB_CAT_OTHER;
- } else if ((0 == opts.do_hex) && (0 == opts.do_name))
+ } else if ((0 == op->do_hex) && (0 == op->do_name))
printf(" %.8s %.16s %.4s\n", inq_out.vendor,
inq_out.product, inq_out.revision);
} else
memset(&inq_out, 0, sizeof(inq_out));
- if (1 == opts.do_temperature)
- return fetchTemperature(sg_fd, rsp_buff, SHORT_RESP_LEN, &opts);
+ if (1 == op->do_temperature)
+ return fetchTemperature(sg_fd, rsp_buff, SHORT_RESP_LEN, op);
- if (opts.do_select) {
- k = sg_ll_log_select(sg_fd, !!(opts.do_pcreset), opts.do_sp,
- opts.page_control, opts.pg_code, opts.subpg_code,
- NULL, 0, 1, opts.do_verbose);
+ if (op->do_select) {
+ k = sg_ll_log_select(sg_fd, !!(op->do_pcreset), op->do_sp,
+ op->page_control, op->pg_code, op->subpg_code,
+ rsp_buff, ((in_len > 0) ? in_len : 0),
+ 1, op->do_verbose);
if (k) {
if (SG_LIB_CAT_NOT_READY == k)
- fprintf(stderr, "log_select: device not ready\n");
+ pr2serr("log_select: device not ready\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "log_select: field in cdb illegal\n");
+ pr2serr("log_select: field in cdb illegal\n");
else if (SG_LIB_CAT_INVALID_OP == k)
- fprintf(stderr, "log_select: not supported\n");
+ pr2serr("log_select: not supported\n");
else if (SG_LIB_CAT_UNIT_ATTENTION == k)
- fprintf(stderr, "log_select: unit attention\n");
+ pr2serr("log_select: unit attention\n");
else if (SG_LIB_CAT_ABORTED_COMMAND == k)
- fprintf(stderr, "log_select: aborted command\n");
+ pr2serr("log_select: aborted command\n");
else
- fprintf(stderr, "log_select: failed (%d), try '-v' for more "
+ pr2serr("log_select: failed (%d), try '-v' for more "
"information\n", k);
}
return (k >= 0) ? k : SG_LIB_CAT_OTHER;
}
- resp_len = (opts.maxlen > 0) ? opts.maxlen : MX_ALLOC_LEN;
- res = do_logs(sg_fd, rsp_buff, resp_len, &opts);
+ resp_len = (op->maxlen > 0) ? op->maxlen : MX_ALLOC_LEN;
+ res = do_logs(sg_fd, rsp_buff, resp_len, op);
if (0 == res) {
pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
if ((pg_len + 4) > resp_len) {
- printf("Only fetched %d bytes of response (available: %d "
- "bytes)\n truncate output\n",
+ pr2serr("Only fetched %d bytes of response (available: %d "
+ "bytes)\n truncate output\n",
resp_len, pg_len + 4);
pg_len = resp_len - 4;
}
} else if (SG_LIB_CAT_INVALID_OP == res)
- fprintf(stderr, "log_sense: not supported\n");
+ pr2serr("log_sense: not supported\n");
else if (SG_LIB_CAT_NOT_READY == res)
- fprintf(stderr, "log_sense: device not ready\n");
+ pr2serr("log_sense: device not ready\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "log_sense: field in cdb illegal\n");
+ pr2serr("log_sense: field in cdb illegal\n");
else if (SG_LIB_CAT_UNIT_ATTENTION == res)
- fprintf(stderr, "log_sense: unit attention\n");
+ pr2serr("log_sense: unit attention\n");
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
- fprintf(stderr, "log_sense: aborted command\n");
- if (0 == opts.do_all) {
- if (opts.do_raw)
+ pr2serr("log_sense: aborted command\n");
+ if (0 == op->do_all) {
+ if (op->filter_given) {
+ if (op->do_hex > 2)
+ dStrHex((const char *)rsp_buff, pg_len + 4,
+ (op->do_hex < 4));
+ else
+ show_ascii_page(rsp_buff, pg_len + 4, &inq_out, op);
+ } else if (op->do_raw)
dStrRaw((const char *)rsp_buff, pg_len + 4);
- else if (opts.do_hex > 1)
- dStrHex((const char *)rsp_buff, pg_len + 4, (2 == opts.do_hex));
+ else if (op->do_hex > 1)
+ dStrHex((const char *)rsp_buff, pg_len + 4, (2 == op->do_hex));
else if (pg_len > 1) {
- if (opts.do_hex) {
+ if (op->do_hex) {
if (rsp_buff[0] & 0x40)
printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, "
"page_len=0x%x\n", rsp_buff[0] & 0x3f, rsp_buff[1],
@@ -4544,46 +5439,46 @@ main(int argc, char * argv[])
dStrHex((const char *)rsp_buff, pg_len + 4, 1);
}
else
- show_ascii_page(rsp_buff, pg_len + 4, &inq_out, &opts);
+ show_ascii_page(rsp_buff, pg_len + 4, &inq_out, op);
}
}
ret = res;
- if (opts.do_all && (pg_len > 1)) {
+ if (op->do_all && (pg_len > 1)) {
int my_len = pg_len;
int spf;
unsigned char parr[1024];
spf = !!(rsp_buff[0] & 0x40);
if (my_len > (int)sizeof(parr)) {
- fprintf(stderr, "Unexpectedly large page_len=%d, trim to %d\n",
- my_len, (int)sizeof(parr));
+ pr2serr("Unexpectedly large page_len=%d, trim to %d\n", my_len,
+ (int)sizeof(parr));
my_len = sizeof(parr);
}
memcpy(parr, rsp_buff + 4, my_len);
for (k = 0; k < my_len; ++k) {
- if (0 == opts.do_raw)
+ if (0 == op->do_raw)
printf("\n");
- opts.pg_code = parr[k] & 0x3f;
+ op->pg_code = parr[k] & 0x3f;
if (spf)
- opts.subpg_code = parr[++k];
+ op->subpg_code = parr[++k];
else
- opts.subpg_code = NOT_SPG_SUBPG;
+ op->subpg_code = NOT_SPG_SUBPG;
- res = do_logs(sg_fd, rsp_buff, resp_len, &opts);
+ res = do_logs(sg_fd, rsp_buff, resp_len, op);
if (0 == res) {
pg_len = (rsp_buff[2] << 8) + rsp_buff[3];
if ((pg_len + 4) > resp_len) {
- fprintf(stderr, "Only fetched %d bytes of response, "
- "truncate output\n", resp_len);
+ pr2serr("Only fetched %d bytes of response, truncate "
+ "output\n", resp_len);
pg_len = resp_len - 4;
}
- if (opts.do_raw)
+ if (op->do_raw)
dStrRaw((const char *)rsp_buff, pg_len + 4);
- else if (opts.do_hex > 1)
+ else if (op->do_hex > 1)
dStrHex((const char *)rsp_buff, pg_len + 4,
- (2 == opts.do_hex));
- else if (opts.do_hex) {
+ (2 == op->do_hex));
+ else if (op->do_hex) {
if (rsp_buff[0] & 0x40)
printf("Log page code=0x%x,0x%x, DS=%d, SPF=1, page_"
"len=0x%x\n", rsp_buff[0] & 0x3f, rsp_buff[1],
@@ -4595,22 +5490,21 @@ main(int argc, char * argv[])
dStrHex((const char *)rsp_buff, pg_len + 4, 1);
}
else
- show_ascii_page(rsp_buff, pg_len + 4, &inq_out, &opts);
+ show_ascii_page(rsp_buff, pg_len + 4, &inq_out, op);
} else if (SG_LIB_CAT_INVALID_OP == res)
- fprintf(stderr, "log_sense: page=0x%x,0x%x not supported\n",
- opts.pg_code, opts.subpg_code);
+ pr2serr("log_sense: page=0x%x,0x%x not supported\n",
+ op->pg_code, op->subpg_code);
else if (SG_LIB_CAT_NOT_READY == res)
- fprintf(stderr, "log_sense: device not ready\n");
+ pr2serr("log_sense: device not ready\n");
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
- fprintf(stderr, "log_sense: field in cdb illegal "
- "[page=0x%x,0x%x]\n", opts.pg_code, opts.subpg_code);
+ pr2serr("log_sense: field in cdb illegal "
+ "[page=0x%x,0x%x]\n", op->pg_code, op->subpg_code);
else if (SG_LIB_CAT_UNIT_ATTENTION == res)
- fprintf(stderr, "log_sense: unit attention\n");
+ pr2serr("log_sense: unit attention\n");
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
- fprintf(stderr, "log_sense: aborted command\n");
+ pr2serr("log_sense: aborted command\n");
else
- fprintf(stderr, "log_sense: failed, try '-v' for more "
- "information\n");
+ pr2serr("log_sense: failed, try '-v' for more information\n");
}
}
sg_cmds_close_device(sg_fd);
diff --git a/src/sg_persist.c b/src/sg_persist.c
index c2138384..ca6eb874 100644
--- a/src/sg_persist.c
+++ b/src/sg_persist.c
@@ -27,7 +27,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
-static const char * version_str = "0.45 20140421";
+static const char * version_str = "0.47 20140504";
#define PRIN_RKEY_SA 0x0
@@ -47,6 +47,8 @@ static const char * version_str = "0.45 20140421";
#define MX_TIDS 32
#define MX_TID_LEN 256
+#define SG_PERSIST_O_RDONLY "SG_PERSIST_O_RDONLY"
+
struct opts_t {
unsigned int prout_type;
uint64_t param_rk;
@@ -60,6 +62,7 @@ struct opts_t {
int param_unreg;
int inquiry;
int hex;
+ int readonly;
unsigned char transportid_arr[MX_TIDS * MX_TID_LEN];
int num_transportids;
unsigned int alloc_len;
@@ -86,6 +89,7 @@ static struct option long_options[] = {
{"prout-type", 1, 0, 'T'},
{"read-full-status", 0, 0, 's'},
{"read-keys", 0, 0, 'k'},
+ {"readonly", 0, 0, 'y'},
{"read-reservation", 0, 0, 'r'},
{"read-status", 0, 0, 's'},
{"register", 0, 0, 'G'},
@@ -195,7 +199,9 @@ usage()
" --prout-type=TYPE|-T TYPE PR Out command type\n"
" --read-full-status|-s PR In: Read Full Status\n"
" --read-keys|-k PR In: Read Keys\n");
- pr2serr(" --read-reservation|-r PR In: Read Reservation\n"
+ pr2serr(" --readonly|-y open DEVICE read-only (def: "
+ "read-write)\n"
+ " --read-reservation|-r PR In: Read Reservation\n"
" --read-status|-s PR In: Read Full Status\n"
" --register|-G PR Out: Register\n"
" --register-ignore|-I PR Out: Register and Ignore\n"
@@ -1029,99 +1035,105 @@ main(int argc, char * argv[])
struct sg_simple_inquiry_resp inq_resp;
const char * cp;
struct opts_t opts;
+ struct opts_t * op;
+
+ op = &opts;
+ memset(op, 0, sizeof(opts));
+ op->prin = 1;
+ op->prin_sa = -1;
+ op->prout_sa = -1;
+ op->inquiry = 1;
+ op->alloc_len = MX_ALLOC_LEN;
+ cp = getenv(SG_PERSIST_O_RDONLY);
+ if (cp)
+ op->readonly = 1;
- memset(&opts, 0, sizeof(opts));
- opts.prin = 1;
- opts.prin_sa = -1;
- opts.prout_sa = -1;
- opts.inquiry = 1;
- opts.alloc_len = MX_ALLOC_LEN;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "AcCd:GHhiIkK:l:LMnoPQ:rRsS:T:UvVX:YzZ",
+ c = getopt_long(argc, argv, "AcCd:GHhiIkK:l:LMnoPQ:rRsS:T:UvVX:yYzZ",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'A':
- opts.prout_sa = PROUT_PREE_AB_SA;
+ op->prout_sa = PROUT_PREE_AB_SA;
++num_prout_sa;
break;
case 'c':
- opts.prin_sa = PRIN_RCAP_SA;
+ op->prin_sa = PRIN_RCAP_SA;
++num_prin_sa;
break;
case 'C':
- opts.prout_sa = PROUT_CLEAR_SA;
+ op->prout_sa = PROUT_CLEAR_SA;
++num_prout_sa;
break;
case 'd':
device_name = optarg;
break;
case 'G':
- opts.prout_sa = PROUT_REG_SA;
+ op->prout_sa = PROUT_REG_SA;
++num_prout_sa;
break;
case 'h':
usage();
return 0;
case 'H':
- ++opts.hex;
+ ++op->hex;
break;
case 'i':
want_prin = 1;
break;
case 'I':
- opts.prout_sa = PROUT_REG_IGN_SA;
+ op->prout_sa = PROUT_REG_IGN_SA;
++num_prout_sa;
break;
case 'k':
- opts.prin_sa = PRIN_RKEY_SA;
+ op->prin_sa = PRIN_RKEY_SA;
++num_prin_sa;
break;
case 'K':
- if (1 != sscanf(optarg, "%" SCNx64 "", &opts.param_rk)) {
+ if (1 != sscanf(optarg, "%" SCNx64 "", &op->param_rk)) {
pr2serr("bad argument to '--param-rk'\n");
return SG_LIB_SYNTAX_ERROR;
}
++num_prout_param;
break;
case 'l':
- if (1 != sscanf(optarg, "%x", &opts.alloc_len)) {
+ if (1 != sscanf(optarg, "%x", &op->alloc_len)) {
pr2serr("bad argument to '--alloc-length'\n");
return SG_LIB_SYNTAX_ERROR;
- } else if (MX_ALLOC_LEN < opts.alloc_len) {
+ } else if (MX_ALLOC_LEN < op->alloc_len) {
pr2serr("'--alloc-length' argument exceeds maximum value "
"(%d)\n", MX_ALLOC_LEN);
return SG_LIB_SYNTAX_ERROR;
}
break;
case 'L':
- opts.prout_sa = PROUT_REL_SA;
+ op->prout_sa = PROUT_REL_SA;
++num_prout_sa;
break;
case 'M':
- opts.prout_sa = PROUT_REG_MOVE_SA;
+ op->prout_sa = PROUT_REG_MOVE_SA;
++num_prout_sa;
break;
case 'n':
- opts.inquiry = 0;
+ op->inquiry = 0;
break;
case 'o':
want_prout = 1;
break;
case 'P':
- opts.prout_sa = PROUT_PREE_SA;
+ op->prout_sa = PROUT_PREE_SA;
++num_prout_sa;
break;
case 'Q':
- if (1 != sscanf(optarg, "%x", &opts.param_rtp)) {
+ if (1 != sscanf(optarg, "%x", &op->param_rtp)) {
pr2serr("bad argument to '--relative-target-port'\n");
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.param_rtp > 0xffff) {
+ if (op->param_rtp > 0xffff) {
pr2serr("argument to '--relative-target-port' 0 to ffff "
"inclusive\n");
return SG_LIB_SYNTAX_ERROR;
@@ -1129,57 +1141,60 @@ main(int argc, char * argv[])
++num_prout_param;
break;
case 'r':
- opts.prin_sa = PRIN_RRES_SA;
+ op->prin_sa = PRIN_RRES_SA;
++num_prin_sa;
break;
case 'R':
- opts.prout_sa = PROUT_RES_SA;
+ op->prout_sa = PROUT_RES_SA;
++num_prout_sa;
break;
case 's':
- opts.prin_sa = PRIN_RFSTAT_SA;
+ op->prin_sa = PRIN_RFSTAT_SA;
++num_prin_sa;
break;
case 'S':
- if (1 != sscanf(optarg, "%" SCNx64 "", &opts.param_sark)) {
+ if (1 != sscanf(optarg, "%" SCNx64 "", &op->param_sark)) {
pr2serr("bad argument to '--param-sark'\n");
return SG_LIB_SYNTAX_ERROR;
}
++num_prout_param;
break;
case 'T':
- if (1 != sscanf(optarg, "%x", &opts.prout_type)) {
+ if (1 != sscanf(optarg, "%x", &op->prout_type)) {
pr2serr("bad argument to '--prout-type'\n");
return SG_LIB_SYNTAX_ERROR;
}
++num_prout_param;
break;
case 'U':
- opts.param_unreg = 1;
+ op->param_unreg = 1;
break;
case 'v':
- ++opts.verbose;
+ ++op->verbose;
break;
case 'V':
pr2serr("version: %s\n", version_str);
return 0;
case 'X':
- if (0 != build_transportid(optarg, &opts)) {
+ if (0 != build_transportid(optarg, op)) {
pr2serr("bad argument to '--transport-id'\n");
return SG_LIB_SYNTAX_ERROR;
}
++num_prout_param;
break;
+ case 'y':
+ ++op->readonly;
+ break;
case 'Y':
- opts.param_alltgpt = 1;
+ op->param_alltgpt = 1;
++num_prout_param;
break;
case 'z':
- opts.prout_sa = PROUT_REPL_LOST_SA;
+ op->prout_sa = PROUT_REPL_LOST_SA;
++num_prout_sa;
break;
case 'Z':
- opts.param_aptpl = 1;
+ op->param_aptpl = 1;
++num_prout_param;
break;
case '?':
@@ -1214,7 +1229,7 @@ main(int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
} else if (want_prout) { /* syntax check on PROUT arguments */
- opts.prin = 0;
+ op->prin = 0;
if ((1 != num_prout_sa) || (0 != num_prin_sa)) {
pr2serr(">> For Persistent Reserve Out one and only one "
"appropriate\n>> service action must be chosen (e.g. "
@@ -1231,7 +1246,7 @@ main(int argc, char * argv[])
if (0 == num_prin_sa) {
pr2serr(">> No service action given; assume Persistent Reserve "
"In command\n>> with Read Keys service action\n");
- opts.prin_sa = 0;
+ op->prin_sa = 0;
++num_prin_sa;
} else if (num_prin_sa > 1) {
pr2serr("Too many service actions given; choose one only\n");
@@ -1239,43 +1254,43 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
- if ((opts.param_unreg || opts.param_rtp) &&
- (PROUT_REG_MOVE_SA != opts.prout_sa)) {
+ if ((op->param_unreg || op->param_rtp) &&
+ (PROUT_REG_MOVE_SA != op->prout_sa)) {
pr2serr("--unreg or --relative-target-port only useful with "
"--register-move\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- if ((PROUT_REG_MOVE_SA == opts.prout_sa) &&
- (1 != opts.num_transportids)) {
+ if ((PROUT_REG_MOVE_SA == op->prout_sa) &&
+ (1 != op->num_transportids)) {
pr2serr("with --register-move one (and only one) --transport-id "
"should be given\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
- if (((PROUT_RES_SA == opts.prout_sa) ||
- (PROUT_REL_SA == opts.prout_sa) ||
- (PROUT_PREE_SA == opts.prout_sa) ||
- (PROUT_PREE_AB_SA == opts.prout_sa)) &&
- (0 == opts.prout_type)) {
+ if (((PROUT_RES_SA == op->prout_sa) ||
+ (PROUT_REL_SA == op->prout_sa) ||
+ (PROUT_PREE_SA == op->prout_sa) ||
+ (PROUT_PREE_AB_SA == op->prout_sa)) &&
+ (0 == op->prout_type)) {
pr2serr("warning>>> --prout-type probably needs to be given\n");
}
- if ((opts.verbose > 2) && opts.num_transportids) {
+ if ((op->verbose > 2) && op->num_transportids) {
pr2serr("number of tranport-ids decoded from command line (or "
- "stdin): %d\n", opts.num_transportids);
+ "stdin): %d\n", op->num_transportids);
pr2serr(" Decode given transport-ids:\n");
- decode_transport_id(" ", opts.transportid_arr,
- 0, opts.num_transportids);
+ decode_transport_id(" ", op->transportid_arr,
+ 0, op->num_transportids);
}
- if (opts.inquiry) {
+ if (op->inquiry) {
if ((sg_fd = sg_cmds_open_device(device_name, 1 /* ro */,
- opts.verbose)) < 0) {
+ op->verbose)) < 0) {
pr2serr("sg_persist: error opening file (ro): %s: %s\n",
device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, opts.verbose)) {
+ if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, op->verbose)) {
printf(" %.8s %.16s %.4s\n", inq_resp.vendor, inq_resp.product,
inq_resp.revision);
peri_type = inq_resp.peripheral_type;
@@ -1292,19 +1307,19 @@ main(int argc, char * argv[])
sg_cmds_close_device(sg_fd);
}
- if ((sg_fd = sg_cmds_open_device(device_name, 0 /* rw */,
- opts.verbose)) < 0) {
+ if ((sg_fd = sg_cmds_open_device(device_name, op->readonly,
+ op->verbose)) < 0) {
pr2serr("sg_persist: error opening file (rw): %s: %s\n", device_name,
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (opts.prin)
- ret = prin_work(sg_fd, &opts);
- else if (PROUT_REG_MOVE_SA == opts.prout_sa)
- ret = prout_reg_move_work(sg_fd, &opts);
+ if (op->prin)
+ ret = prin_work(sg_fd, op);
+ else if (PROUT_REG_MOVE_SA == op->prout_sa)
+ ret = prout_reg_move_work(sg_fd, op);
else /* PROUT commands other than 'register and move' */
- ret = prout_work(sg_fd, &opts);
+ ret = prout_work(sg_fd, op);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {