aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-09-05 05:23:31 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-09-05 05:23:31 +0000
commiteda37108f2a83c7944b1c0f63162647eddc9960d (patch)
treefd5990953d5dd017796554ff5d0c7efd407e64fa
parent7e7308a2dbdec4c900b0805ad94324d3a288a163 (diff)
downloadsg3_utils-eda37108f2a83c7944b1c0f63162647eddc9960d.tar.gz
sg_inq+sg_vpd: ongoing updates; rescan_scsi_bus.sh
https://github.com/doug-gilbert/sg3_utils/pull/21 change to rescan_scsi_bus.sh was applied in an earlier commit but not noted. git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@970 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog3
-rw-r--r--README.details11
-rw-r--r--doc/sg3_utils.82
-rw-r--r--doc/sg3_utils_json.852
-rw-r--r--include/sg_pr2serr.h99
-rw-r--r--src/sg_dd.c14
-rw-r--r--src/sg_inq.c118
-rw-r--r--src/sg_prevent.c8
-rw-r--r--src/sg_vpd.c74
-rw-r--r--src/sg_vpd_common.c20
10 files changed, 228 insertions, 173 deletions
diff --git a/ChangeLog b/ChangeLog
index ed818950..c22493a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for pre-release sg3_utils-1.48 [20220818] [svn: r969]
+Changelog for pre-release sg3_utils-1.48 [20220904] [svn: r970]
- some utilities: add experimental --json[=JO] option
- sg_z_act_query: new utility for sending either a
Zone activate or Zone query command
@@ -26,6 +26,7 @@ Changelog for pre-release sg3_utils-1.48 [20220818] [svn: r969]
- sgdevice26: do not traverse sg class if scsi_device
is not added
- add -no-lip-scan option
+ - https://github.com/doug-gilbert/sg3_utils/pull/21
- sg_rep_zones: add Report zone starting LBA granularity
field in REPORT ZONES response [zbc2r12]
- add --brief option, show part of header and last
diff --git a/README.details b/README.details
index 96cac8b5..560ea55e 100644
--- a/README.details
+++ b/README.details
@@ -542,10 +542,19 @@ replaced by "uint8_t" as the 8 bit (unsigned) byte type; "char" is still
used for ASCII text.
+Coding Style
+============
+Everyone has their own C/C++ coding style and the author is no different.
+In terms of the GNU indent command:
+ indent -i4 -il0 -nut -br -npcs -ncs -ce
+is pretty close. That is similar to the Linux kernel coding style but
+with 4 space indentations and no tabs.
+
+
Other SCSI and storage tools
============================
See https://sg.danny.cz/sg/tools.html
Douglas Gilbert dgilbert@interlog.com
-12th August 2022
+26th August 2022
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index 1eb2f4af..81c10143 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS "8" "August 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG3_UTILS "8" "September 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg3_utils \- a package of utilities for sending SCSI commands
.SH SYNOPSIS
diff --git a/doc/sg3_utils_json.8 b/doc/sg3_utils_json.8
index e8cdb62f..9c6eee2c 100644
--- a/doc/sg3_utils_json.8
+++ b/doc/sg3_utils_json.8
@@ -1,4 +1,4 @@
-.TH SG3_UTILS_JSON "8" "August 2022" "sg3_utils\-1.48" SG3_UTILS
+.TH SG3_UTILS_JSON "8" "September 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg3_utils_json \- JSON output for some sg3_utils utilities
.SH SYNOPSIS
@@ -229,19 +229,35 @@ SCSI INQUIRY command). SCSI "list"s become JSON named arrays (e.g. in
the Device Identification VPD page there is a "Designation descriptor
list" that becomes a JSON array named "designation_descriptor_list").
.PP
-At the completion of the utility that JSON tree is "measured" taking
-into account the form of output (i.e. pretty-printed, single line or
-packed single line). For the pretty-printed JSON output, the size of
-each indentation in spaces is also given (i.e. the tab width). The JSON
-is then output to a single C string, then sent to stdout. If a NULL
-character (ASCII zero and C string terminator) somehow finds its way
-into a field that should (according to the spec) be space padded, then
-the JSON output may appear truncated.
+At the completion of the utility that JSON tree is "measured" taking into
+account the form of output (i.e. pretty-printed, single line or packed single
+line). For the pretty-printed JSON output, the size of each indentation in
+spaces is also given (i.e. the tab width). The JSON is then output to a
+single C string, then sent to stdout. If a NULL character (ASCII zero and C
+string terminator) somehow finds its way into a field that should (according
+to the spec) be space padded, then the JSON output may appear truncated.
.PP
Note that this JSON processing means that if a utility is aborted for whatever
reason then no JSON output will appear. With the normal, human readable output
processing, some output may appear before the utility aborts in such bad
situations.
+.SH INTERACTION WITH OTHER OPTIONS
+As stated above, the default output is in human readable form using 7 bit
+ASCII. The \fI\-\-json[=JO]\fR option is designed to be an alternative to that
+human readable form. There are other alternative output formats such as the
+response output as a hexadecimal sequence of bytes or in "raw" binary output;
+both of those take precedence over the \fI\-\-json[=JO]\fR option. Other
+specialized output format (e.g. 'sg_inq \-\-export') will usually take
+precedence over JSON output.
+.PP
+When the \fI\-\-raw\fR option is used together with the \fI\-\-inhex=FN\fR
+option only the data input to the utility is interpreted as binary. So the
+output format defaults to human readable form and thus can be changed to
+JSON if the \fI\-\-json[=JO]\fR option is also used.
+.PP
+There is typically only one form of JSON output so options like
+\fI\-\-brief\fR and \fI\-\-quiet\fR are ignored in the JSON output. In some
+cases (i.e 'sg_inq \-\-descriptors') the JSON output is expanded.
.SH ERRORS
No attempts have been made to translate errors into JSON form, apart from the
final "exit_status" JSON object where a value of 0 means "no errors". Exit
@@ -265,24 +281,6 @@ The summary is that when JSON output is selected and an error occurs each
utility will process the error the same way as it would if JSON output had
not been selected. In all cases error messages, in human readable form,
are sent to stderr.
-.SH INTERACTION WITH OTHER OPTIONS
-As stated above, the default output is in human readable form using 7 bit
-ASCII. The \fI\-\-json[=JO]\fR option is designed to be an alternative
-to that human readable form. There are other alternative output formats
-such as the response output as a hexadecimal sequence of bytes or
-in "raw" binary output; both of those take precedence over the
-\fI\-\-json[=JO]\fR option. Other specialized output
-format (e.g. 'sg_inq \-\-export') will usually take precedence over JSON
-output.
-.PP
-When the \fI\-\-raw\fR option is used together with the \fI\-\-inhex=FN\fR
-option only the data input to the utility is interpreted as binary. So the
-output format defaults to human readable form and thus can be changed to
-JSON if the \fI\-\-json[=JO]\fR option is also used.
-.PP
-There is typically only one form of JSON output so options like
-\fI\-\-brief\fR and \fI\-\-quiet\fR are ignored in the JSON output. In some
-cases (i.e 'sg_inq \-\-descriptors') the JSON output is expanded.
.SH AUTHORS
Written by Douglas Gilbert. Some utilities have been contributed, see the
CREDITS file and individual source files (in the 'src' directory).
diff --git a/include/sg_pr2serr.h b/include/sg_pr2serr.h
index 54b8150c..556ff596 100644
--- a/include/sg_pr2serr.h
+++ b/include/sg_pr2serr.h
@@ -227,55 +227,6 @@ sgj_opaque_p sgj_js_nv_b(sgj_state * jsp, sgj_opaque_p jop,
sgj_opaque_p sgj_js_nv_o(sgj_state * jsp, sgj_opaque_p jop,
const char * name, sgj_opaque_p ua_jop);
-/* The '_haj_' refers to generating output both for human readable and/or
- * JSON with a single invocation. If jsp is non-NULL and jsp->pr_out_hr is
- * true then both JSON and human readable output is formed (and the latter is
- * placed in the jsp->out_hrp JSON array). The human readable form will have
- * leadin_sp spaces followed by 'name' then a separator, then 'value' with a
- * trailing LF. If 'name' is NULL then it and the separator are ignored. If
- * there is JSON output, then leadin_sp and sep are ignored. If 'jop' is NULL
- * then basep->basep is used. If 'name' is NULL then a JSON string object,
- * made from 'value' is added to the JSON array pointed to by 'jop'.
- * Otherwise a 'name'-d JSON object whose value is a JSON string object made
- * from 'value' is added at 'jop'. */
-void sgj_haj_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- const char * value);
-
-/* Similar to sgj_haj_vs()'s description with 'JSON string object'
- * replaced by 'JSON integer object'. */
-void sgj_haj_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- int64_t value, bool hex_as_well);
-void sgj_haj_vistr(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- int64_t value, bool hex_as_well, const char * val_s);
-
-/* The '_nex' refers to a "name_extra" (information) sub-object (a JSON
- * string) which explains a bit more about the 'name' entry. This is useful
- * when T10 specifies the name as an abbreviation (e.g. SYSV). Whether this
- * sub-object is shown in the JSON output is controlled by the 'n' control
- * character. */
-void sgj_haj_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- int64_t value, bool hex_as_well, const char * nex_s);
-void sgj_haj_vistr_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- int64_t value, bool hex_as_well,
- const char * val_s, const char * nex_s);
-
-/* Similar to above '_haj_' calls but a named sub-object is always formed
- * containing a JSON integer object named "i" whose value is 'value'. The
- * returned pointer is to that sub-object. */
-sgj_opaque_p sgj_haj_subo_r(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep,
- int64_t value, bool hex_as_well);
-
-/* Similar to sgj_haj_vs()'s description with 'JSON string object' replaced
- * by 'JSON boolean object'. */
-void sgj_haj_vb(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
- const char * name, enum sgj_separator_t sep, bool value);
-
/* This function only produces JSON output if jsp is non-NULL and
* jsp->pr_as_json is true. It adds a named object at 'jop' (or jop->basep
* if jop is NULL) along with a value. If jsp->pr_hex is true then that
@@ -298,6 +249,7 @@ void sgj_js_nv_istr(sgj_state * jsp, sgj_opaque_p jop,
const char * name, int64_t val_i,
const char * str_name, const char * val_s);
+/* Similar to sgj_js_nv_istr(). The hex output is conditional jsp->pr_hex . */
void sgj_js_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop,
const char * name, int64_t val_i,
const char * str_name, const char * val_s);
@@ -327,6 +279,55 @@ void sgj_js_nv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop,
void sgj_js_nv_hex_bytes(sgj_state * jsp, sgj_opaque_p jop, const char * name,
const uint8_t * byte_arr, int num_bytes);
+/* The '_haj_' refers to generating output both for human readable and/or
+ * JSON with a single invocation. If jsp is non-NULL and jsp->pr_out_hr is
+ * true then both JSON and human readable output is formed (and the latter is
+ * placed in the jsp->out_hrp JSON array). The human readable form will have
+ * leadin_sp spaces followed by 'name' then a separator, then 'value' with a
+ * trailing LF. If 'name' is NULL then it and the separator are ignored. If
+ * there is JSON output, then leadin_sp and sep are ignored. If 'jop' is NULL
+ * then basep->basep is used. If 'name' is NULL then a JSON string object,
+ * made from 'value' is added to the JSON array pointed to by 'jop'.
+ * Otherwise a 'name'-d JSON object whose value is a JSON string object made
+ * from 'value' is added at 'jop'. */
+void sgj_haj_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ const char * value);
+
+/* Similar to sgj_haj_vs()'s description with 'JSON string object'
+ * replaced by 'JSON integer object'. */
+void sgj_haj_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, bool hex_as_well);
+void sgj_haj_vistr(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, bool hex_as_well, const char * val_s);
+
+/* The '_nex' refers to a "name_extra" (information) sub-object (a JSON
+ * string) which explains a bit more about the 'name' entry. This is useful
+ * when T10 specifies the name as an abbreviation (e.g. SYSV). Whether this
+ * sub-object is shown in the JSON output is controlled by the 'n' control
+ * character. */
+void sgj_haj_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, bool hex_as_well, const char * nex_s);
+void sgj_haj_vistr_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, bool hex_as_well,
+ const char * val_s, const char * nex_s);
+
+/* Similar to above '_haj_' calls but a named sub-object is always formed
+ * containing a JSON integer object named "i" whose value is 'value'. The
+ * returned pointer is to that sub-object. */
+sgj_opaque_p sgj_haj_subo_r(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep,
+ int64_t value, bool hex_as_well);
+
+/* Similar to sgj_haj_vs()'s description with 'JSON string object' replaced
+ * by 'JSON boolean object'. */
+void sgj_haj_vb(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
+ const char * name, enum sgj_separator_t sep, bool value);
+
/* Breaks up the string pointed to by 'sp' into lines and adds them to the
* jsp->out_hrp array. Treat '\n' in sp as line breaks. Consumes characters
* from sp until either a '\0' is found or slen is exhausted. Add each line
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 8392f31d..e099c335 100644
--- a/src/sg_dd.c
+++ b/src/sg_dd.c
@@ -70,7 +70,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "6.34 20220729";
+static const char * version_str = "6.35 20220826";
#define ME "sg_dd: "
@@ -214,16 +214,16 @@ static void calc_duration_throughput(bool contin);
static void
-install_handler(int sig_num, void (*sig_handler) (int sig))
+install_handler(int sig_num, void (*sig_handler)(int sig))
{
struct sigaction sigact;
- sigaction (sig_num, NULL, &sigact);
- if (sigact.sa_handler != SIG_IGN)
- {
+
+ sigaction(sig_num, NULL, &sigact);
+ if (sigact.sa_handler != SIG_IGN) {
sigact.sa_handler = sig_handler;
- sigemptyset (&sigact.sa_mask);
+ sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
- sigaction (sig_num, &sigact, NULL);
+ sigaction(sig_num, &sigact, NULL);
}
}
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 47834743..edd571c7 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -53,7 +53,7 @@
#include "sg_vpd_common.h" /* for shared VPD page processing with sg_vpd */
-static const char * version_str = "2.28 20220818"; /* spc6r06, sbc5r03 */
+static const char * version_str = "2.30 20220904"; /* spc6r06, sbc5r03 */
#define MY_NAME "sg_inq"
@@ -1071,6 +1071,7 @@ svpd_inhex_decode_all(struct opts_t * op, sgj_opaque_p jop)
int bump, off;
int in_len = op->maxlen;
int prev_pn = -1;
+ sgj_state * jsp = &op->json_st;
uint8_t vpd0_buff[512];
uint8_t * rp = vpd0_buff;
@@ -1105,12 +1106,17 @@ svpd_inhex_decode_all(struct opts_t * op, sgj_opaque_p jop)
"max_pn=0x%x\n", __func__, pn, max_pn);
continue;
}
- if (op->do_long)
- printf("[0x%x] ", pn);
+ if (op->do_long) {
+ if (jsp->pr_as_json)
+ sgj_pr_hr(jsp, "[0x%x]:\n", pn);
+ else
+ sgj_pr_hr(jsp, "[0x%x] ", pn);
+ }
res = vpd_decode(-1, op, jop, off);
if (SG_LIB_CAT_OTHER == res) {
- ; // xxxxx
+ if (op->verbose)
+ pr2serr("Can't decode VPD page=0x%x\n", pn);
}
}
return res;
@@ -1204,6 +1210,7 @@ decode_ascii_inf(uint8_t * buff, int len, struct opts_t * op)
int al, k, bump;
uint8_t * bp;
uint8_t * p;
+ sgj_state * jsp = &op->json_st;
if (op->do_hex) {
hex2stdout(buff, len, no_ascii_4hex(op));
@@ -1221,15 +1228,15 @@ decode_ascii_inf(uint8_t * buff, int len, struct opts_t * op)
for (k = 0, bp = buff + 5; k < al; k += bump, bp += bump) {
p = (uint8_t *)memchr(bp, 0, al - k);
if (! p) {
- printf(" %.*s\n", al - k, (const char *)bp);
+ sgj_pr_hr(jsp, " %.*s\n", al - k, (const char *)bp);
break;
}
- printf(" %s\n", (const char *)bp);
+ sgj_pr_hr(jsp, " %s\n", (const char *)bp);
bump = (p - bp) + 1;
}
bp = buff + 5 + al;
if (bp < (buff + len)) {
- printf("Vendor specific information in hex:\n");
+ sgj_pr_hr(jsp, "Vendor specific information in hex:\n");
hex2stdout(bp, len - (al + 5), 0);
}
}
@@ -1688,6 +1695,8 @@ decode_dev_ids(const char * leadin, uint8_t * buff, int len,
pr2serr("%s VPD page error: around offset=%d\n", leadin, off);
}
+/* The --export and --json options are assumed to be mutually exclusive.
+ * Here the former takes precedence. */
static void
export_dev_ids(uint8_t * buff, int len, int verbose)
{
@@ -2128,9 +2137,15 @@ static const char * failover_mode_arr[] =
};
static void
-decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op)
+decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op,
+ sgj_opaque_p jop)
{
- int k, ip_mgmt, vpp80, lun_z;
+ uint8_t uc;
+ int k, n, ip_mgmt, vpp80, lun_z;
+ sgj_state * jsp = &op->json_st;
+ const char * cp;
+ char b[256];
+ static const int blen = sizeof(b);
if (len < 3) {
pr2serr("EMC upr VPD page [0xc0]: length too short=%d\n", len);
@@ -2145,50 +2160,64 @@ decode_upr_vpd_c0_emc(uint8_t * buff, int len, struct opts_t * op)
buff[9]);
return;
}
- printf(" LUN WWN: ");
- for (k = 0; k < 16; ++k)
- printf("%02x", buff[10 + k]);
- printf("\n");
- printf(" Array Serial Number: ");
- dStrRaw((const char *)&buff[50], buff[49]);
- printf("\n");
+ for (k = 0, n = 0; k < 16; ++k)
+ n += sg_scnpr(b + n, blen - n, "%02x", buff[10 + k]);
+ sgj_haj_vs(jsp, jop, 2, "LUN WWN", SGJ_SEP_COLON_1_SPACE, b);
+ snprintf(b, blen, "%.*s", buff[49], buff + 50);
+ sgj_haj_vs(jsp, jop, 2, "Array Serial Number", SGJ_SEP_COLON_1_SPACE, b);
- printf(" LUN State: ");
if (buff[4] > 0x02)
- printf("Unknown (%x)\n", buff[4]);
+ snprintf(b, blen, "Unknown (%x)", buff[4]);
else
- printf("%s\n", lun_state_arr[buff[4]]);
-
- printf(" This path connects to: ");
- if (buff[8] > 0x01)
- printf("Unknown SP (%x)", buff[8]);
+ snprintf(b, blen, "%s", lun_state_arr[buff[4]]);
+ sgj_haj_vistr(jsp, jop, 2, "LUN State", SGJ_SEP_COLON_1_SPACE,
+ buff[4], true, b);
+
+ uc = buff[8];
+ n = 0;
+ if (uc > 0x01)
+ n += sg_scnpr(b + n, blen - n, "Unknown SP (%x)", uc);
else
- printf("%s", sp_arr[buff[8]]);
- printf(", Port Number: %u\n", buff[7]);
+ n += sg_scnpr(b + n, blen - n, "%s", sp_arr[uc]);
+ sgj_js_nv_ihexstr(jsp, jop, "path_connects_to", uc, NULL, b);
+ n += sg_scnpr(b + n, blen - n, ", Port Number: %u", buff[7]);
+ sgj_pr_hr(jsp, " This path connects to: %s\n", b);
+ sgj_js_nv_ihex(jsp, jop, "port_number", buff[7]);
- printf(" Default Owner: ");
if (buff[5] > 0x01)
- printf("Unknown (%x)\n", buff[5]);
+ snprintf(b, blen, "Unknown (%x)\n", buff[5]);
else
- printf("%s\n", sp_arr[buff[5]]);
+ snprintf(b, blen, "%s\n", sp_arr[buff[5]]);
+ sgj_haj_vistr(jsp, jop, 2, "Default owner", SGJ_SEP_COLON_1_SPACE,
+ buff[5], true, b);
- printf(" NO_ATF: %s, Access Logix: %s\n",
- buff[6] & 0x80 ? "set" : "not set",
- buff[6] & 0x40 ? "supported" : "not supported");
+ cp = (buff[6] & 0x40) ? "supported" : "not supported";
+ sgj_pr_hr(jsp, " NO_ATF: %s, Access Logix: %s\n",
+ buff[6] & 0x80 ? "set" : "not set", cp);
+ sgj_js_nv_i(jsp, jop, "no_atf", !! (buff[6] & 0x80));
+ sgj_js_nv_istr(jsp, jop, "access_logix", !! (buff[6] & 0x40),
+ NULL, cp);
ip_mgmt = (buff[6] >> 4) & 0x3;
-
- printf(" SP IP Management Mode: %s\n", ip_mgmt_arr[ip_mgmt]);
- if (ip_mgmt == 2)
- printf(" SP IPv4 address: %u.%u.%u.%u\n",
- buff[44], buff[45], buff[46], buff[47]);
- else {
+ cp = ip_mgmt_arr[ip_mgmt];
+ sgj_pr_hr(jsp, " SP IP Management Mode: %s\n", cp);
+ sgj_js_nv_istr(jsp, jop, "sp_ip_management_mode", !! ip_mgmt,
+ NULL, cp);
+ if (ip_mgmt == 2) {
+ snprintf(b, blen, "%u.%u.%u.%u", buff[44], buff[45], buff[46],
+ buff[47]);
+ sgj_pr_hr(jsp, " SP IPv4 address: %s\n", b);
+ sgj_js_nv_s(jsp, jop, "sp_ipv4_address", b);
+ } else if (ip_mgmt == 3) {
printf(" SP IPv6 address: ");
+ n = 0;
for (k = 0; k < 16; ++k)
- printf("%02x", buff[32 + k]);
- printf("\n");
+ n += sg_scnpr(b + n, blen - n, "%02x", buff[32 + k]);
+ sgj_pr_hr(jsp, " SP IPv6 address: %s\n", b);
+ sgj_js_nv_hex_bytes(jsp, jop, "sp_ipv6_address", buff + 32, 16);
}
+// yyyyyyy more conversion work needed below this point
vpp80 = buff[30] & 0x08;
lun_z = buff[30] & 0x04;
@@ -3811,15 +3840,20 @@ vpd_decode(int sg_fd, struct opts_t * op, sgj_opaque_p jop, int off)
break;
/* Vendor specific VPD pages (>= 0xc0) */
case VPD_UPR_EMC: /* 0xc0 */
+ np = "Block device characteristics VPD page";
+ ep = "(EMC)";
if (!op->do_raw && (op->do_hex < 3))
- printf("VPD INQUIRY: Unit Path Report Page (EMC)\n");
+ sgj_pr_hr(jsp, "VPD INQUIRY: %s %s\n", np, ep);
res = vpd_fetch_page(sg_fd, rp, pn, -1, qt, vb, &len);
if (res)
break;
if (op->do_raw)
dStrRaw((const char *)rp, len);
- else
- decode_upr_vpd_c0_emc(rp, len, op);
+ else {
+ if (as_json)
+ jo2p = sg_vpd_js_hdr(jsp, jop, np, rp);
+ decode_upr_vpd_c0_emc(rp, len, op, jo2p);
+ }
break;
case VPD_RDAC_VERS: /* 0xc2 */
if (!op->do_raw && (op->do_hex < 3))
diff --git a/src/sg_prevent.c b/src/sg_prevent.c
index 487315ac..b2076c54 100644
--- a/src/sg_prevent.c
+++ b/src/sg_prevent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2018 Douglas Gilbert.
+ * Copyright (c) 2004-2022 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -29,7 +29,7 @@
* given SCSI device.
*/
-static const char * version_str = "1.12 20180627";
+static const char * version_str = "1.13 20220826";
#define ME "sg_prevent: "
@@ -94,8 +94,8 @@ main(int argc, char * argv[])
usage();
return 0;
case 'p':
- prevent = sg_get_num(optarg);
- if ((prevent < 0) || (prevent > 3)) {
+ prevent = sg_get_num(optarg);
+ if ((prevent < 0) || (prevent > 3)) {
pr2serr("bad argument to '--prevent'\n");
return SG_LIB_SYNTAX_ERROR;
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 9aae8a72..707d3e12 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -42,7 +42,7 @@
*/
-static const char * version_str = "1.81 20220818"; /* spc6r06 + sbc5r03 */
+static const char * version_str = "1.82 20220826"; /* spc6r06 + sbc5r03 */
#define MY_NAME "sg_vpd"
@@ -290,9 +290,9 @@ static int
count_standard_vpds(int vpd_pn)
{
const struct svpd_values_name_t * vnp;
- int matches;
+ int matches = 0;
- for (vnp = standard_vpd_pg, matches = 0; vnp->acron; ++vnp) {
+ for (vnp = standard_vpd_pg; vnp->acron; ++vnp) {
if ((vpd_pn == vnp->value) && vnp->name) {
if (0 == matches)
printf("Matching standard VPD pages:\n");
@@ -1374,10 +1374,10 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
else {
bool protect = false;
- op->protect_not_sure = false;
- if (op->std_inq_a_valid)
- protect = !! (0x1 & op->std_inq_a[5]);
- else if ((sg_fd >= 0) && (! op->do_force)) {
+ op->protect_not_sure = false;
+ if (op->std_inq_a_valid)
+ protect = !! (0x1 & op->std_inq_a[5]);
+ else if ((sg_fd >= 0) && (! op->do_force)) {
struct sg_simple_inquiry_resp sir;
res = sg_simple_inquiry(sg_fd, &sir, false, vb);
@@ -1385,11 +1385,11 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
if (op->verbose)
pr2serr("%s: sg_simple_inquiry() failed, "
"res=%d\n", __func__, res);
- op->protect_not_sure = true;
+ op->protect_not_sure = true;
} else
protect = !!(sir.byte_5 & 0x1); /* SPC-3 and later */
} else
- op->protect_not_sure = true;
+ op->protect_not_sure = true;
if (vb || long_notquiet)
sgj_pr_hr(jsp," [PQual=%d Peripheral device type: "
"%s]\n", pqual, pdt_str);
@@ -1650,7 +1650,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
if (0 == res) {
if (! allow_name && allow_if_found)
- printf("%s%s\n", pre, np);
+ sgj_pr_hr(jsp, "%s%s\n", pre, np);
if (op->do_raw)
dStrRaw(rp, len);
else {
@@ -1719,7 +1719,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb0\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb0\n", pre);
break;
case 0xb1: /* depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1770,7 +1770,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb1\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb1\n", pre);
break;
case 0xb2: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1815,7 +1815,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb2\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb2\n", pre);
break;
case 0xb3: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1857,7 +1857,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb3\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb3\n", pre);
break;
case 0xb4: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1902,7 +1902,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb4\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb4\n", pre);
break;
case 0xb5: /* VPD page depends on pdt */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1951,7 +1951,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb5\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb5\n", pre);
break;
case VPD_ZBC_DEV_CHARS: /* 0xb6 for both pdt=0 and pdt=0x14 */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -1989,7 +1989,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb6\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb6\n", pre);
break;
case 0xb7:
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -2027,7 +2027,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb7\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb7\n", pre);
break;
case 0xb8: /* VPD_FORMAT_PRESETS */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -2068,7 +2068,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb8\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb8\n", pre);
break;
case 0xb9: /* VPD_CON_POS_RANGE */
res = vpd_fetch_page(sg_fd, rp, pn, op->maxlen, qt, vb, &len);
@@ -2109,7 +2109,7 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, sgj_opaque_p jop,
return 0;
} else if ((! op->do_raw) && (! op->do_quiet) && (op->do_hex < 3) &&
exam_not_given)
- printf("%sVPD page=0xb8\n", pre);
+ sgj_pr_hr(jsp, "%sVPD page=0xb8\n", pre);
break;
default:
return SG_LIB_CAT_OTHER;
@@ -2123,6 +2123,7 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
int k, res, rlen, n, pn;
int max_pn = 255;
int any_err = 0;
+ sgj_state * jsp = &op->json_st;
uint8_t vpd0_buff[512];
uint8_t * rp = vpd0_buff;
@@ -2158,9 +2159,13 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
continue;
op->vpd_pn = pn;
if (k > 0)
- printf("\n");
- if (op->do_long)
- printf("[0x%x] ", pn);
+ sgj_pr_hr(jsp, "\n");
+ if (op->do_long) {
+ if (jsp->pr_as_json)
+ sgj_pr_hr(jsp, "[0x%x]:\n", pn);
+ else
+ printf("[0x%x] ", pn);
+ }
res = svpd_decode_t10(sg_fd, op, jop, 0, 0, NULL);
if (SG_LIB_CAT_OTHER == res) {
@@ -2215,8 +2220,12 @@ svpd_decode_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
"max_pn=0x%x\n", __func__, pn, max_pn);
continue;
}
- if (op->do_long)
- printf("[0x%x] ", pn);
+ if (op->do_long) {
+ if (jsp->pr_as_json)
+ sgj_pr_hr(jsp, "[0x%x]:\n", pn);
+ else
+ printf("[0x%x] ", pn);
+ }
res = svpd_decode_t10(-1, op, jop, 0, off, NULL);
if (SG_LIB_CAT_OTHER == res) {
@@ -2237,6 +2246,7 @@ svpd_examine_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
int k, res, start;
int max_pn;
int any_err = 0;
+ sgj_state * jsp = &op->json_st;
char b[80];
max_pn = (op->page_given ? op->vpd_pn : 0xff);
@@ -2261,7 +2271,7 @@ svpd_examine_all(int sg_fd, struct opts_t * op, sgj_opaque_p jop)
if (first)
first = false;
else if (got_one) {
- printf("\n");
+ sgj_pr_hr(jsp, "\n");
got_one = false;
}
if (op->do_long)
@@ -2455,6 +2465,7 @@ main(int argc, char * argv[])
return 0;
}
+ jsp = &op->json_st;
if (op->do_enum) {
if (op->device_name)
pr2serr("Device name %s ignored when --enumerate given\n",
@@ -2498,16 +2509,15 @@ main(int argc, char * argv[])
matches = svpd_count_vendor_vpds(op->vpd_pn,
op->vend_prod_num);
if (0 == matches)
- printf("No matches found for VPD page number 0x%x\n",
- op->vpd_pn);
+ sgj_pr_hr(jsp, "No matches found for VPD page number 0x%x\n",
+ op->vpd_pn);
} else { /* enumerate standard then vendor VPD pages */
- printf("Standard VPD pages:\n");
+ sgj_pr_hr(jsp, "Standard VPD pages:\n");
enumerate_vpds(1, 1);
}
return 0;
}
- jsp = &op->json_st;
as_json = jsp->pr_as_json;
if (as_json)
jop = sgj_start_r(MY_NAME, version_str, argc, argv, jsp);
@@ -2524,7 +2534,7 @@ main(int argc, char * argv[])
vnp = sdp_find_vpd_by_acron("sinq");
} else {
pr2serr("abbreviation doesn't match a VPD page\n");
- printf("Available standard VPD pages:\n");
+ sgj_pr_hr(jsp, "Available standard VPD pages:\n");
enumerate_vpds(1, 1);
ret = SG_LIB_SYNTAX_ERROR;
goto fini;
@@ -2545,7 +2555,7 @@ main(int argc, char * argv[])
op->vpd_pn = sg_get_num_nomult(op->page_str);
if ((op->vpd_pn < 0) || (op->vpd_pn > 255)) {
pr2serr("Bad page code value after '-p' option\n");
- printf("Available standard VPD pages:\n");
+ sgj_pr_hr(jsp, "Available standard VPD pages:\n");
enumerate_vpds(1, 1);
ret = SG_LIB_SYNTAX_ERROR;
goto fini;
diff --git a/src/sg_vpd_common.c b/src/sg_vpd_common.c
index 14b1bd2d..dcc7727b 100644
--- a/src/sg_vpd_common.c
+++ b/src/sg_vpd_common.c
@@ -1712,7 +1712,7 @@ decode_block_lb_prov_vpd(const uint8_t * buff, int len, struct opts_t * op,
if (jsp->pr_as_json && jsp->pr_out_hr)
sgj_js_str_out(jsp, b, strlen(b));
else
- printf("%s", b);
+ sgj_pr_hr(jsp, "%s", b);
}
return 0;
}
@@ -2237,6 +2237,8 @@ decode_rod_descriptor(const uint8_t * buff, int len, struct opts_t * op,
const uint8_t * bp = buff;
sgj_state * jsp = &op->json_st;
sgj_opaque_p jo2p;
+ char b[80];
+ static const int blen = sizeof(b);
static const char * ab_pdt = "abnormal use of 'pdt'";
for (k = 0; k < len; k += bump, bp += bump) {
@@ -2285,11 +2287,11 @@ decode_rod_descriptor(const uint8_t * buff, int len, struct opts_t * op,
sgj_haj_vi(jsp, jo2p, 4, "Maximum bytes in stream ROD",
SGJ_SEP_COLON_1_SPACE, ull, true);
ull = sg_get_unaligned_be64(bp + 16);
- printf(" Optimal Bytes in stream ROD transfer: ");
+ snprintf(b, blen, " Optimal Bytes in stream ROD transfer: ");
if (SG_LIB_UNBOUNDED_64BIT == ull)
- printf("-1 [no limit]\n");
+ sgj_pr_hr(jsp, "%s-1 [no limit]\n", b);
else
- printf("%" PRIu64 "\n", ull);
+ sgj_pr_hr(jsp, "%s%" PRIu64 "\n", b, ull);
break;
case 3:
/* Copy manager ROD device type specific descriptor */
@@ -2297,14 +2299,14 @@ decode_rod_descriptor(const uint8_t * buff, int len, struct opts_t * op,
pdt, false, NULL, "Copy manager ROD "
"device type specific descriptor",
ab_pdt);
- printf(" Maximum Bytes in processor ROD: %" PRIu64 "\n",
- sg_get_unaligned_be64(bp + 8));
+ sgj_pr_hr(jsp, " Maximum Bytes in processor ROD: %" PRIu64 "\n",
+ sg_get_unaligned_be64(bp + 8));
ull = sg_get_unaligned_be64(bp + 16);
- printf(" Optimal Bytes in processor ROD transfer: ");
+ snprintf(b, blen, " Optimal Bytes in processor ROD transfer: ");
if (SG_LIB_UNBOUNDED_64BIT == ull)
- printf("-1 [no limit]\n");
+ sgj_pr_hr(jsp, "%s-1 [no limit]\n", b);
else
- printf("%" PRIu64 "\n", ull);
+ sgj_pr_hr(jsp, "%s%" PRIu64 "\n", b, ull);
break;
default:
sgj_js_nv_ihexstr(jsp, jo2p, "peripheral_device_type",