aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2016-03-06 16:37:42 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2016-03-06 16:37:42 +0000
commit70cacd5629374ab1a56c4d372aac986f1de09207 (patch)
treebe9ce8109bcd7d9517405730a8fbb29f82478487
parentf6ae61b384844df7d322c0b3bad461d080b6790f (diff)
downloadsg3_utils-70cacd5629374ab1a56c4d372aac986f1de09207.tar.gz
sg_logs: fix volume statistics lpage, decode mount history log parameter; sg_ses: expand join debug code
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@684 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog6
-rw-r--r--doc/sg3_utils.84
-rw-r--r--doc/sg_ses.828
-rw-r--r--lib/sg_cmds_basic2.c24
-rw-r--r--lib/sg_cmds_extra.c145
-rw-r--r--lib/sg_cmds_mmc.c24
-rw-r--r--src/sg_logs.c71
-rw-r--r--src/sg_ses.c186
8 files changed, 326 insertions, 162 deletions
diff --git a/ChangeLog b/ChangeLog
index 6964cdf6..b0393322 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,15 +2,19 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.43 [20160302] [svn: r682]
+Changelog for sg3_utils-1.43 [20160304] [svn: r684]
- sg_senddiag: add --timeout=SEC option
- sg_sanitize: add --timeout=SEC option
- sg_format: add --timeout=SEC option
+ - sg_logs: fix volume statistics lpage when subpage
+ is zero (ssc5r02a); decode mount history log parameter
- sg_reassign+sg_write_same: fix ULONG_MAX problem
- sg_turs+sg_requests: make both accept '--num=NUM'
and '--number=NUM' for mutual compatibility
+ - sg_ses: expand join debug code
- rescan-scsi-bus.sh: harden code
- shellcheck cleanup on scripts
+ - automake: add AM_PROG_AR to configure.ac
Changelog for sg3_utils-1.42 [20160217] [svn: r663]
- sg_timestamp: new, to report or set timestamp
diff --git a/doc/sg3_utils.8 b/doc/sg3_utils.8
index bb80cd4a..701422f4 100644
--- a/doc/sg3_utils.8
+++ b/doc/sg3_utils.8
@@ -449,8 +449,8 @@ action.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output). Can be used multiple
-times to further increase verbosity. The additional output is usually sent
-to stderr.
+times to further increase verbosity. The additional output caused by this
+option is almost always sent to stderr.
.TP
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit. Each utility has its own version
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index 8d2d47b8..2aea1e7c 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -1,4 +1,4 @@
-.TH SG_SES "8" "December 2015" "sg3_utils\-1.42" SG3_UTILS
+.TH SG_SES "8" "March 2016" "sg3_utils\-1.43" SG3_UTILS
.SH NAME
sg_ses \- access a SCSI Enclosure Services (SES) device
.SH SYNOPSIS
@@ -130,11 +130,11 @@ DESCRIPTOR NAME, DEVICE SLOT NUMBER AND SAS ADDRESS section below.
\fB\-E\fR, \fB\-\-eiioe\fR=\fIA_F\fR
\fIA_F\fR is either the string 'auto' or 'force'. There was some fuzziness
in the interpretation of the 'element index' field in the Additional Element
-Status page between SES\-2 and SES\-3. The EIIOE bit was introduced to
+Status (AES) page between SES\-2 and SES\-3. The EIIOE bit was introduced to
resolve the problem but not all enclosures have caught up.
-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
+Using '\-\-eiioe=force' will decode the AES page as if the EIIOE bit is set.
+Using '\-\-eiioe=auto' will decode the AES 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
@@ -251,6 +251,9 @@ starts with a digit it is assumed to be in decimal unless prefixed by
0x for hex. Valid range is 0 to 255 (0x0 to 0xff) inclusive. Default is
page 'sdp' which is page_code 0 (i.e. "Supported Diagnostic Pages") if
no other options are given.
+.br
+To list the available page abbreviations give "xxx" for \fIPG\fR; the same
+information can also be found with the \fI\-\-enumerate\fR option.
.TP
\fB\-r\fR, \fB\-\-raw\fR
outputs the chosen status page in ASCII hex in a format suitable for a
@@ -292,7 +295,10 @@ command. In the absence of other options that imply modifying a page (e.g.
\fI\-\-control\fR or \fI\-\-set=STR\fR) then \fI\-\-status\fR is assumed.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
-increase the level of verbosity, (i.e. debug output).
+increase the level of verbosity. For example when this option is given four
+times (in which case the short form is more convenient: '\-vvvv') then if
+the internal join array has been generated then it is output to stderr in
+form suitable for debugging.
.TP
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit.
@@ -474,7 +480,9 @@ Element Status descriptors correctly. At least one SES device vendor has
misinterpreted the SES\-2 standard with its "element index" field. The
code in this utility interprets the "element index" field as per the SES\-2
standard and if that yields an inappropriate Element type, adjusts its
-indexing to follow that vendor's misinterpretation.
+indexing to follow that vendor's misinterpretation. The SES\-3 drafts have
+introduced the EIIOE (element index includes overall elements) to resolve
+this ambiguity. See the \fI\-\-eiioe=A_F\fR option.
.PP
In draft SES\-3 revision 5 the "Door Lock" element name was changed to
the "Door" (and an OPEN field was added to the status element). As a
@@ -484,8 +492,8 @@ to 'do'.
There is a related command set called SAF\-TE (SCSI attached fault\-tolerant
enclosure) for enclosure (including RAID) status and control. SCSI devices
that support SAF\-TE report "Processor" peripheral device type (0x3) in their
-INQUIRY response. See the sg_safte utility in this package or safte\-monitor
-on the Internet.
+INQUIRY response. See the sg_safte utility in this package or the
+safte\-monitor utility on the Internet.
.SH EXAMPLES
Examples can also be found at http://sg.danny.cz/sg/sg_ses.html
.PP
@@ -585,7 +593,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2015 Douglas Gilbert
+Copyright \(co 2004\-2016 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/lib/sg_cmds_basic2.c b/lib/sg_cmds_basic2.c
index adb29163..14a2de76 100644
--- a/lib/sg_cmds_basic2.c
+++ b/lib/sg_cmds_basic2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2015 Douglas Gilbert.
+ * Copyright (c) 1999-2016 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.
@@ -308,9 +308,14 @@ sg_ll_mode_sense6(int sg_fd, int dbd, int pc, int pg_code, int sub_pg_code,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" mode sense (6): response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" mode sense (6): response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -381,9 +386,14 @@ sg_ll_mode_sense10(int sg_fd, int llbaa, int dbd, int pc, int pg_code,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" mode sense (10): response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" mode sense (10): response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index ce3948eb..40fd136d 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -161,9 +161,14 @@ sg_ll_get_lba_status(int sg_fd, uint64_t start_llba, void * resp,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" get LBA status: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" get LBA status: response\n");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -229,9 +234,14 @@ sg_ll_report_tgt_prt_grp2(int sg_fd, void * resp, int mx_resp_len,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" report target port group: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" report target port group: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -343,9 +353,14 @@ sg_ll_report_referrals(int sg_fd, uint64_t start_llba, int one_seg,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" report referrals: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" report referrals: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -470,9 +485,14 @@ sg_ll_receive_diag(int sg_fd, int pcv, int pg_code, void * resp,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" receive diagnostic results: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" receive diagnostic results: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -531,9 +551,14 @@ sg_ll_read_defect10(int sg_fd, int req_plist, int req_glist, int dl_format,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read defect (10): response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read defect (10): response\n");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -588,9 +613,14 @@ sg_ll_read_media_serial_num(int sg_fd, void * resp, int mx_resp_len,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read media serial number: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read media serial number: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -648,9 +678,14 @@ sg_ll_report_id_info(int sg_fd, int itype, void * resp, int max_resp_len,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" report identifying information: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" report identifying information: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -903,9 +938,14 @@ sg_ll_persistent_reserve_in(int sg_fd, int rq_servact, void * resp,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" persistent reserve in: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" persistent reserve in: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -1065,9 +1105,14 @@ sg_ll_read_long10(int sg_fd, int pblock, int correct, unsigned int lba,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read long(10): response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read long(10): response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -1150,9 +1195,14 @@ sg_ll_read_long16(int sg_fd, int pblock, int correct, uint64_t llba,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read long(16): response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read long(16): response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -1686,9 +1736,14 @@ sg_ll_read_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read buffer: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read buffer: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -1718,10 +1773,15 @@ sg_ll_write_buffer(int sg_fd, int mode, int buffer_id, int buffer_offset,
pr2ws("%02x ", wbufCmdBlk[k]);
pr2ws("\n");
if ((verbose > 1) && paramp && param_len) {
- pr2ws(" Write buffer parameter list%s:\n",
- ((param_len > 256) ? " (first 256 bytes)" : ""));
- dStrHexErr((const char *)paramp,
- ((param_len > 256) ? 256 : param_len), -1);
+ pr2ws(" Write buffer parameter list");
+ if (2 == verbose) {
+ pr2ws("%s:\n", (param_len > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)paramp,
+ (param_len > 256 ? 256 : param_len), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)paramp, param_len, 0);
+ }
}
}
@@ -1866,9 +1926,14 @@ sg_ll_read_block_limits(int sg_fd, void * resp, int mx_resp_len,
}
} else {
if ((verbose > 2) && (ret > 0)) {
- pr2ws(" read block limits: response%s\n",
- (ret > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ pr2ws(" read block limits: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
diff --git a/lib/sg_cmds_mmc.c b/lib/sg_cmds_mmc.c
index 8bb85691..3dab6e7b 100644
--- a/lib/sg_cmds_mmc.c
+++ b/lib/sg_cmds_mmc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2015 Douglas Gilbert.
+ * Copyright (c) 2008-2016 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.
@@ -194,9 +194,14 @@ sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
if (len < 0)
len = 0;
len = (ret < len) ? ret : len;
- pr2ws(" get configuration: response%s\n",
- (len > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (len > 256 ? 256 : len), -1);
+ pr2ws(" get configuration: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
@@ -282,9 +287,14 @@ sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba,
if (len < 0)
len = 0;
len = (ret < len) ? ret : len;
- pr2ws(" get performance:: response%s\n",
- (len > 256 ? ", first 256 bytes" : ""));
- dStrHexErr((const char *)resp, (len > 256 ? 256 : len), -1);
+ pr2ws(" get performance:: response");
+ if (3 == verbose) {
+ pr2ws("%s:\n", (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHexErr((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ } else {
+ pr2ws(":\n");
+ dStrHexErr((const char *)resp, ret, 0);
+ }
}
ret = 0;
}
diff --git a/src/sg_logs.c b/src/sg_logs.c
index a2534d8c..74bea70d 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.39 20160203"; /* spc5r08 + sbc4r10 */
+static const char * version_str = "1.40 20160303"; /* spc5r08 + sbc4r10 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -134,7 +134,7 @@ struct opts_t {
int verbose;
int do_version;
int filter;
- int filter_given;
+ bool filter_given;
int page_control;
int maxlen;
int pg_code;
@@ -219,12 +219,12 @@ static bool show_mchanger_diag_data_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_non_volatile_cache_page(const uint8_t * resp, int len,
const struct opts_t * op);
-static bool show_volume_stats_page(const uint8_t * resp, int len,
- const struct opts_t * op);
+static bool show_volume_stats_pages(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_protocol_specific_page(const uint8_t * resp, int len,
const struct opts_t * op);
-static bool show_stats_perform_page(const uint8_t * resp, int len,
- const struct opts_t * op);
+static bool show_stats_perform_pages(const uint8_t * resp, int len,
+ const struct opts_t * op);
static bool show_cache_stats_page(const uint8_t * resp, int len,
const struct opts_t * op);
static bool show_power_condition_transitions_page(const uint8_t * resp,
@@ -324,14 +324,14 @@ static struct log_elem log_arr[] = {
show_mchanger_diag_data_page}, /* 0x16, 0x0 SMC */
{0x17, 0, 0, 0, 0, "Non volatile cache", "nvc",
show_non_volatile_cache_page}, /* 0x17, 0x0 SBC */
- {0x17, 0, 0, PDT_TAPE, 0, "Volume statistics", "vs",
- show_volume_stats_page}, /* 0x17, 0x0 SSC */
+ {0x17, 0, 0xf, PDT_TAPE, 0, "Volume statistics", "vs",
+ show_volume_stats_pages}, /* 0x17, 0x0...0xf SSC */
{PROTO_SPECIFIC_LPAGE, 0, 0, -1, 0, "Protocol specific port", "psp",
show_protocol_specific_page}, /* 0x18, 0x0 */
{STATS_LPAGE, 0, 0, -1, 0, "General Statistics and Performance", "gsp",
- show_stats_perform_page}, /* 0x19, 0x0 */
+ show_stats_perform_pages}, /* 0x19, 0x0 */
{STATS_LPAGE, 0x1, 0x1f, -1, 0, "Group Statistics and Performance", "grsp",
- show_stats_perform_page}, /* 0x19, 0x1...0x1f */
+ show_stats_perform_pages}, /* 0x19, 0x1...0x1f */
{STATS_LPAGE, 0x20, 0, -1, 0, "Cache memory statistics", "cms",
show_cache_stats_page}, /* 0x19, 0x20 */
{PCT_LPAGE, 0, 0, -1, 0, "Power condition transitions", "pct",
@@ -758,7 +758,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
}
op->filter = n;
}
- ++op->filter_given;
+ op->filter_given = true;
break;
case 'h':
case '?':
@@ -970,7 +970,7 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
op->filter = n;
- ++op->filter_given;
+ op->filter_given = true;
} else if (0 == strncmp("i=", cp, 2))
op->in_fn = cp + 2;
else if (0 == strncmp("m=", cp, 2)) {
@@ -3188,11 +3188,11 @@ skip:
return true;
}
-/* Returns 1 if processed page, 0 otherwise */
+/* Returns true if processed page, false otherwise */
/* STATS_LPAGE [0x19], subpages: 0x0 to 0x1f introduced: SPC-4 */
static bool
-show_stats_perform_page(const uint8_t * resp, int len,
- const struct opts_t * op)
+show_stats_perform_pages(const uint8_t * resp, int len,
+ const struct opts_t * op)
{
int k, num, param_len, param_code, spf, subpg_code, extra;
int pcb, nam;
@@ -3482,7 +3482,7 @@ show_stats_perform_page(const uint8_t * resp, int len,
return true;
}
-/* Returns 1 if processed page, 0 otherwise */
+/* Returns true if processed page, false otherwise */
/* STATS_LPAGE [0x19], CACHE_STATS_SUBPG [0x20] introduced: SPC-4 */
static bool
show_cache_stats_page(const uint8_t * resp, int len, const struct opts_t * op)
@@ -5298,7 +5298,7 @@ skip:
return true;
}
-/* Helper for show_volume_stats_page() */
+/* Helper for show_volume_stats_pages() */
static void
volume_stats_partition(const uint8_t * xp, int len, bool in_hex)
{
@@ -5345,9 +5345,32 @@ volume_stats_partition(const uint8_t * xp, int len, bool in_hex)
}
}
-/* Volume Statistics log page (ssc-4) [0x17, 0x1-0xf] */
+/* Helper for show_volume_stats_pages() */
+static void
+volume_stats_history(const uint8_t * xp, int len)
+{
+ int dl, mhi;
+
+ while (len > 3) {
+ dl = xp[0] + 1;
+ if (dl < 4)
+ return;
+ mhi = sg_get_unaligned_be16(xp + 2);
+ if (dl < 12)
+ printf(" index: %d\n", mhi);
+ else if (12 == dl)
+ printf(" index: %d, vendor: %.8s\n", mhi, xp + 4);
+ else
+ printf(" index: %d, vendor: %.8s, unit serial number: %.*s\n",
+ mhi, xp + 4, dl - 12, xp + 12);
+ xp += dl;
+ len -= dl;
+ }
+}
+
+/* Volume Statistics log page and subpages (ssc-4) [0x17, 0x0-0xf] */
static bool
-show_volume_stats_page(const uint8_t * resp, int len,
+show_volume_stats_pages(const uint8_t * resp, int len,
const struct opts_t * op)
{
int num, pl, pc, pcb, spf, subpg_code;
@@ -5358,10 +5381,7 @@ show_volume_stats_page(const uint8_t * resp, int len,
spf = !!(resp[0] & 0x40);
subpg_code = spf ? resp[1] : 0;
if (op->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)
+ if (subpg_code < 0x10)
printf("Volume statistics page (ssc-4), subpage=%d\n",
subpg_code);
else {
@@ -5550,9 +5570,8 @@ show_volume_stats_page(const uint8_t * resp, int len,
volume_stats_partition(ucp + 4, pl - 4, false);
break;
case 0x300:
- printf(" Mount history, payload in hex:\n");
- // xxxxxxxx TODO
- dStrHex((const char *)(ucp + 4), pl - 4, 0);
+ printf(" Mount history:\n");
+ volume_stats_history(ucp + 4, pl - 4);
break;
default:
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 64996641..fbdc5774 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
@@ -30,7 +31,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.07 20160201"; /* ses3r08->11 */
+static const char * version_str = "2.08 20160306"; /* ses3r08->11 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -101,7 +102,7 @@ struct element_type_t {
struct opts_t {
int byte1;
- int byte1_given;
+ bool byte1_given;
int do_control;
int do_data;
int dev_slot_num;
@@ -111,7 +112,7 @@ struct opts_t {
int do_filter;
int do_help;
int do_hex;
- int ind_given;
+ bool ind_given;
int ind_th; /* type header index */
int ind_indiv; /* individual element index; -1 for overall */
int ind_et_inst; /* ETs can have multiple type header instances */
@@ -121,9 +122,9 @@ struct opts_t {
int mask_ign; /* element read-mask-modify-write actions */
int maxlen;
int seid;
- int seid_given;
+ bool seid_given;
int page_code;
- int page_code_given;
+ bool page_code_given;
int do_raw;
int o_readonly;
int do_status;
@@ -185,7 +186,7 @@ struct join_row_t {
unsigned char * elem_descp;
unsigned char * enc_statp; /* NULL indicates past last */
unsigned char * thresh_inp;
- unsigned char * add_elem_statp;
+ unsigned char * ae_statp;
int dev_slot_num; /* if not available, set to -1 */
unsigned char sas_addr[8]; /* if not available, set to 0 */
};
@@ -826,7 +827,7 @@ parse_index(struct opts_t *op)
const struct element_type_t * etp;
char b[64];
- op->ind_given = 1;
+ op->ind_given = true;
if ((cp = strchr(op->index_str, ','))) {
if (0 == strcmp("-1", cp + 1))
n = -1;
@@ -940,7 +941,7 @@ parse_index(struct opts_t *op)
}
-/* process command line options and argument. Returns 0 if ok. */
+/* command line process, options and arguments. Returns 0 if ok. */
static int
cl_process(struct opts_t *op, int argc, char *argv[])
{
@@ -953,8 +954,8 @@ cl_process(struct opts_t *op, int argc, char *argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:Mp:rRsS:v"
- "Vwx:", long_options, &option_index);
+ c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:Mp:rRs"
+ "S:vVwx:", long_options, &option_index);
if (c == -1)
break;
@@ -984,7 +985,7 @@ cl_process(struct opts_t *op, int argc, char *argv[])
pr2serr("bad argument to '--byte1' (0 to 255 inclusive)\n");
return SG_LIB_SYNTAX_ERROR;
}
- ++op->byte1_given;
+ op->byte1_given = true;
break;
case 'c':
++op->do_control;
@@ -1049,7 +1050,7 @@ cl_process(struct opts_t *op, int argc, char *argv[])
pr2serr("bad argument to '--nick_id' (0 to 255 inclusive)\n");
return SG_LIB_SYNTAX_ERROR;
}
- ++op->seid_given;
+ op->seid_given = true;
break;
case 'm':
op->maxlen = sg_get_num(optarg);
@@ -1086,7 +1087,7 @@ cl_process(struct opts_t *op, int argc, char *argv[])
return SG_LIB_SYNTAX_ERROR;
}
}
- ++op->page_code_given;
+ op->page_code_given = true;
break;
case 'r':
++op->do_raw;
@@ -1174,7 +1175,7 @@ cl_process(struct opts_t *op, int argc, char *argv[])
return SG_LIB_SYNTAX_ERROR;
}
if ((0 == op->do_join) && (0 == op->do_control) &&
- (0 == op->num_cgs) && (0 == op->page_code_given)) {
+ (0 == op->num_cgs) && (! op->page_code_given)) {
++op->do_join; /* implicit --join */
if (op->verbose)
pr2serr("assume --join option is set\n");
@@ -1182,8 +1183,8 @@ cl_process(struct opts_t *op, int argc, char *argv[])
}
if (op->ind_given) {
if ((0 == op->do_join) && (0 == op->do_control) &&
- (0 == op->num_cgs) && (0 == op->page_code_given)) {
- ++op->page_code_given;
+ (0 == op->num_cgs) && (! op->page_code_given)) {
+ op->page_code_given = true;
op->page_code = 2; /* implicit status page */
if (op->verbose)
pr2serr("assume --page=2 (es) option is set\n");
@@ -2252,18 +2253,23 @@ reserved_or_num(char * buff, int buff_len, int num, int reserve_num)
}
static void
-ses_threshold_helper(const char * pad, const unsigned char *tp, int etype,
+ses_threshold_helper(const char * header, const char * pad,
+ const unsigned char *tp, int etype,
const struct opts_t * op)
{
char b[128];
char b2[128];
if (op->inner_hex) {
+ if (header)
+ printf("%s", header);
printf("%s%02x %02x %02x %02x\n", pad, tp[0], tp[1], tp[2], tp[3]);
return;
}
switch (etype) {
case 0x4: /*temperature */
+ if (header)
+ printf("%s", header);
printf("%shigh critical=%s, high warning=%s\n", pad,
reserved_or_num(b, 128, tp[0] - TEMPERAT_OFF, -TEMPERAT_OFF),
reserved_or_num(b2, 128, tp[1] - TEMPERAT_OFF, -TEMPERAT_OFF));
@@ -2272,6 +2278,8 @@ ses_threshold_helper(const char * pad, const unsigned char *tp, int etype,
reserved_or_num(b2, 128, tp[3] - TEMPERAT_OFF, -TEMPERAT_OFF));
break;
case 0xb: /* UPS */
+ if (header)
+ printf("%s", header);
if (0 == tp[2])
strcpy(b, "<vendor>");
else
@@ -2284,19 +2292,23 @@ ses_threshold_helper(const char * pad, const unsigned char *tp, int etype,
printf("low critical=%s (in minutes)\n", b);
break;
case 0x12: /* voltage */
+ if (header)
+ printf("%s", header);
#ifdef SG_LIB_MINGW
- printf("%shigh critical=%g %%, high warning=%g %%\n", pad,
- 0.5 * tp[0], 0.5 * tp[1]);
- printf("%slow warning=%g %%, low critical=%g %% (from nominal "
+ printf("%shigh critical=%g %%, high warning=%g %% (above nominal "
+ "voltage)\n", pad, 0.5 * tp[0], 0.5 * tp[1]);
+ printf("%slow warning=%g %%, low critical=%g %% (below nominal "
"voltage)\n", pad, 0.5 * tp[2], 0.5 * tp[3]);
#else
- printf("%shigh critical=%.1f %%, high warning=%.1f %%\n", pad,
- 0.5 * tp[0], 0.5 * tp[1]);
- printf("%slow warning=%.1f %%, low critical=%.1f %% (from nominal "
+ printf("%shigh critical=%.1f %%, high warning=%.1f %% (above nominal "
+ "voltage)\n", pad, 0.5 * tp[0], 0.5 * tp[1]);
+ printf("%slow warning=%.1f %%, low critical=%.1f %% (below nominal "
"voltage)\n", pad, 0.5 * tp[2], 0.5 * tp[3]);
#endif
break;
case 0x13: /* current */
+ if (header)
+ printf("%s", header);
#ifdef SG_LIB_MINGW
printf("%shigh critical=%g %%, high warning=%g %%", pad,
0.5 * tp[0], 0.5 * tp[1]);
@@ -2307,8 +2319,11 @@ ses_threshold_helper(const char * pad, const unsigned char *tp, int etype,
printf(" (above nominal current)\n");
break;
default:
- if (op->verbose)
+ if (op->verbose) {
+ if (header)
+ printf("%s", header);
printf("%s<< no thresholds for this element type >>\n", pad);
+ }
break;
}
}
@@ -2348,8 +2363,8 @@ ses_threshold_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
printf(" Element type: %s, subenclosure id: %d [ti=%d]\n",
find_element_tname(tdhp->etype, b, sizeof(b)),
tdhp->se_id, k);
- printf(" Overall descriptor:\n");
- ses_threshold_helper(" ", ucp, tdhp->etype, op);
+ ses_threshold_helper(" Overall descriptor:\n", " ",
+ ucp, tdhp->etype, op);
++got1;
}
for (ucp += 4, j = 0, elem_ind = 0; j < tdhp->num_elements;
@@ -2359,8 +2374,9 @@ ses_threshold_sdg(const struct type_desc_hdr_t * tdhp, int num_telems,
(elem_ind != op->ind_indiv))
continue;
}
- printf(" Element %d descriptor:\n", elem_ind);
- ses_threshold_helper(" ", ucp, tdhp->etype, op);
+ snprintf(b, sizeof(b), " Element %d descriptor:\n",
+ elem_ind);
+ ses_threshold_helper(b, " ", ucp, tdhp->etype, op);
++got1;
}
}
@@ -3351,13 +3367,18 @@ devslotnum_and_sasaddr(struct join_row_t * jrp, unsigned char * ae_ucp)
/* Fetch Configuration, Enclosure Status, Element Descriptor, Additional
* Element Status and optionally Threshold In pages, place in static arrays.
* Collate (join) overall and individual elements into the static join_arr[].
- * Returns 0 for success, any other return value is an error. */
+ * When 'display' is true then the join_arr[] is output to stdout in a form
+ * suitable for end users. For debug purposes the join_arr[] is output to
+ * stderr when op->verbose > 3. Returns 0 for success, any other return value
+ * is an error. */
static int
-join_work(int sg_fd, struct opts_t * op, int display)
+join_work(int sg_fd, struct opts_t * op, bool display)
{
int k, j, res, num_t_hdrs, elem_ind, ei, desc_len, dn_len;
int et4aes, broken_ei, ei2, got1, jr_max_ind, mlen;
uint32_t ref_gen_code, gen_code;
+ int eip_count = 0;
+ int eiioe_count = 0;
struct join_row_t * jrp;
struct join_row_t * jr2p;
unsigned char * es_ucp;
@@ -3470,7 +3491,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
}
if ((op->do_join > 1) ||
- ((0 == display) && (DPC_THRESHOLD == op->page_code))) {
+ ((! display) && (DPC_THRESHOLD == op->page_code))) {
mlen = sizeof(threshold_rsp);
if (mlen > op->maxlen)
mlen = op->maxlen;
@@ -3517,7 +3538,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
jrp->elem_descp = ed_ucp;
if (ed_ucp)
ed_ucp += sg_get_unaligned_be16(ed_ucp + 2) + 4;
- jrp->add_elem_statp = NULL;
+ jrp->ae_statp = NULL;
jrp->thresh_inp = t_ucp;
jrp->dev_slot_num = -1;
/* assume sas_addr[8] zeroed since it's static file scope */
@@ -3547,7 +3568,7 @@ join_work(int sg_fd, struct opts_t * op, int display)
/* assume sas_addr[8] zeroed since it's static file scope */
if (t_ucp)
t_ucp += 4;
- jrp->add_elem_statp = NULL;
+ jrp->ae_statp = NULL;
++jr_max_ind;
}
if (jrp >= join_arr_lastp) {
@@ -3577,11 +3598,14 @@ join_work(int sg_fd, struct opts_t * op, int display)
break;
}
eip = !!(ae_ucp[0] & 0x10); /* element index present */
- if (eip)
+ if (eip) {
+ ++eip_count;
+ if (ae_ucp[2] & 1)
+ ++eiioe_count;
eiioe = op->eiioe_force ? 1 : (ae_ucp[2] & 1);
- else
+ } else
eiioe = 0;
- if (eip && eiioe) {
+ if (eip && eiioe) { /* EIIOE=1 */
ei = ae_ucp[3];
jr2p = join_arr + ei;
if ((ei >= jr_max_ind) || (NULL == jr2p->enc_statp)) {
@@ -3592,13 +3616,19 @@ join_work(int sg_fd, struct opts_t * op, int display)
break;
}
devslotnum_and_sasaddr(jr2p, ae_ucp);
- if (jr2p->add_elem_statp) {
- if (op->warn || op->verbose)
- pr2serr("warning: aes slot busy [oi=%d, "
- "ei=%d, aes_i=%d]\n", k, ei, aes_i);
+ if (jr2p->ae_statp) {
+ if (op->warn || op->verbose) {
+ pr2serr("warning: aes slot already in use, "
+ "keep existing AES+%ld\n\t",
+ jr2p->ae_statp - add_elem_rsp);
+ pr2serr("dropping AES+%ld [length=%d, oi=%d, "
+ "ei=%d, aes_i=%d]\n",
+ ae_ucp - add_elem_rsp,
+ ae_ucp[1] + 2, k, ei, aes_i);
+ }
} else
- jr2p->add_elem_statp = ae_ucp;
- } else if (eip) { /* and EIIOE=0 */
+ jr2p->ae_statp = ae_ucp;
+ } else if (eip) { /* and EIIOE=0 */
ei = ae_ucp[3];
try_again:
for (jr2p = join_arr; jr2p->enc_statp; ++jr2p) {
@@ -3623,15 +3653,21 @@ try_again:
goto try_again;
}
devslotnum_and_sasaddr(jr2p, ae_ucp);
- if (jr2p->add_elem_statp) {
- if (op->warn || op->verbose)
- pr2serr("warning: aes slot busy [oi=%d, "
- "ei=%d, aes_i=%d]\n", k, ei, aes_i);
+ if (jr2p->ae_statp) {
+ if (op->warn || op->verbose) {
+ pr2serr("warning2: aes slot already in use, "
+ "keep existing AES+%ld\n\t",
+ jr2p->ae_statp - add_elem_rsp);
+ pr2serr("dropping AES+%ld [length=%d, oi=%d, "
+ "ei=%d, aes_i=%d]\n",
+ ae_ucp - add_elem_rsp,
+ ae_ucp[1] + 2, k, ei, aes_i);
+ }
} else
- jr2p->add_elem_statp = ae_ucp;
+ jr2p->ae_statp = ae_ucp;
} else { /* EIP=0 */
while (jrp->enc_statp && ((-1 == jrp->el_ind_indiv) ||
- jrp->add_elem_statp))
+ jrp->ae_statp))
++jrp;
if (NULL == jrp->enc_statp) {
get_out = 1;
@@ -3639,7 +3675,7 @@ try_again:
"ae\n", __func__);
break;
}
- jrp->add_elem_statp = ae_ucp;
+ jrp->ae_statp = ae_ucp;
++jrp;
}
ae_ucp += ae_ucp[1] + 2;
@@ -3664,21 +3700,33 @@ try_again:
if (op->verbose > 3) {
jrp = join_arr;
for (k = 0; ((k < MX_JOIN_ROWS) && jrp->enc_statp); ++k, ++jrp) {
- pr2serr("el_ind_th=%d el_ind_indiv=%d etype=%d se_id=%d ei=%d "
- "ei2=%d dsn=%d sa=0x", jrp->el_ind_th, jrp->el_ind_indiv,
+ pr2serr("ei_th=%d ei_indiv=%d etype=%d se_id=%d ei=%d "
+ "ei2=%d dsn=%d", jrp->el_ind_th, jrp->el_ind_indiv,
jrp->etype, jrp->se_id, jrp->ei_asc, jrp->ei_asc2,
jrp->dev_slot_num);
- if (saddr_non_zero(jrp->sas_addr)) {
- for (j = 0; j < 8; ++j)
- pr2serr("%02x", jrp->sas_addr[j]);
- } else
- pr2serr("0");
- pr2serr(" %s %s %s %s\n", (jrp->enc_statp ? "ES" : ""),
- (jrp->elem_descp ? "ED" : ""),
- (jrp->add_elem_statp ? "AES" : ""),
- (jrp->thresh_inp ? "TI" : ""));
+ if (op->do_join > 2) {
+ pr2serr(" sa=0x");
+ if (saddr_non_zero(jrp->sas_addr)) {
+ for (j = 0; j < 8; ++j)
+ pr2serr("%02x", jrp->sas_addr[j]);
+ } else
+ pr2serr("0");
+ }
+ if (jrp->enc_statp)
+ pr2serr(" ES+%ld", jrp->enc_statp - enc_stat_rsp);
+ if (jrp->elem_descp)
+ pr2serr(" ED+%ld", jrp->elem_descp - elem_desc_rsp);
+ if (jrp->ae_statp)
+ pr2serr(" AES+%ld", jrp->ae_statp - add_elem_rsp);
+ if (jrp->thresh_inp)
+ pr2serr(" TI+%ld", jrp->thresh_inp - threshold_rsp);
+ pr2serr("\n");
}
- pr2serr(">> elements in join_arr: %d, broken_ei=%d\n", k, broken_ei);
+ pr2serr(">> ES len=%d, ED len=%d, AES len=%d, TI len=%d\n",
+ enc_stat_rsp_len, elem_desc_rsp_len, add_elem_rsp_len,
+ threshold_rsp_len);
+ pr2serr(">> join_arr elements=%d, eip_count=%d, eiioe_count=%d "
+ "broken_ei=%d\n", k, eip_count, eiioe_count, broken_ei);
}
if (! display) /* probably wanted join_arr[] built only */
@@ -3737,16 +3785,16 @@ try_again:
jrp->el_ind_indiv, cp);
printf(" Enclosure Status:\n");
enc_status_helper(" ", jrp->enc_statp, jrp->etype, op);
- if (jrp->add_elem_statp) {
+ if (jrp->ae_statp) {
printf(" Additional Element Status:\n");
- ae_ucp = jrp->add_elem_statp;
+ ae_ucp = jrp->ae_statp;
desc_len = ae_ucp[1] + 2;
additional_elem_helper(" ", ae_ucp, desc_len, jrp->etype, op);
}
if (jrp->thresh_inp) {
- printf(" Threshold In:\n");
t_ucp = jrp->thresh_inp;
- ses_threshold_helper(" ", t_ucp, jrp->etype, op);
+ ses_threshold_helper(" Threshold In:\n", " ", t_ucp,
+ jrp->etype, op);
}
}
if (0 == got1) {
@@ -4011,7 +4059,7 @@ cgs_additional_el(const struct join_row_t * jrp,
uint64_t ui;
const struct acronym2tuple * ap;
- if (NULL == jrp->add_elem_statp) {
+ if (NULL == jrp->ae_statp) {
pr2serr("No additional element status element available\n");
return -1;
}
@@ -4034,7 +4082,7 @@ cgs_additional_el(const struct join_row_t * jrp,
return -2;
}
if (op->get_str) {
- ui = get_big_endian(jrp->add_elem_statp + s_byte, s_bit, n_bits);
+ ui = get_big_endian(jrp->ae_statp + s_byte, s_bit, n_bits);
if (op->do_hex)
printf("0x%" PRIx64 "\n", ui);
else
@@ -4077,7 +4125,7 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
pr2serr("acroynm %s not found (try '-ee' option)\n", tavp->acron);
return -1;
}
- ret = join_work(sg_fd, op, 0);
+ ret = join_work(sg_fd, op, false);
if (ret)
return ret;
dn_len = op->desc_name ? (int)strlen(op->desc_name) : 0;
@@ -4380,7 +4428,7 @@ main(int argc, char * argv[])
else if (have_cgs)
ret = ses_cgs(sg_fd, &tav, op);
else if (op->do_join)
- ret = join_work(sg_fd, op, 1);
+ ret = join_work(sg_fd, op, true);
else if (op->do_status)
ret = ses_process_status_page(sg_fd, op);
else { /* control page requested */