aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_cmds_basic.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2017-10-09 23:49:50 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2017-10-09 23:49:50 +0000
commitb2e59f46a39f19ffc18be02fad71df68974a8d0b (patch)
tree83b037b8108830c5f04d93fa50d19bbda5fb6ea1 /lib/sg_cmds_basic.c
parentdc469cf010ce1c840d6a1790cc4179ea0f5912dd (diff)
downloadsg3_utils-b2e59f46a39f19ffc18be02fad71df68974a8d0b.tar.gz
convert lots of two valued 'int's to bool; add sg_ll_inquiry_v2() sg_ll_write_buffer_v2() sg_get_sfs_name() and sg_decode_transportid_str()
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@719 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib/sg_cmds_basic.c')
-rw-r--r--lib/sg_cmds_basic.c102
1 files changed, 95 insertions, 7 deletions
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 4cec465e..44c3fa45 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -35,7 +35,7 @@
#endif
-static const char * const version_str = "1.75 20170917";
+static const char * const version_str = "1.76 20171007";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -86,7 +86,7 @@ pr2ws(const char * fmt, ...)
/* Returns file descriptor >= 0 if successful. If error in Unix returns
negated errno. */
int
-sg_cmds_open_device(const char * device_name, int read_only, int verbose)
+sg_cmds_open_device(const char * device_name, bool read_only, int verbose)
{
/* The following 2 lines are temporary. It is to avoid a NULL pointer
* crash when an old utility is used with a newer library built after
@@ -327,9 +327,10 @@ create_pt_obj(const char * cname)
static const char * const inquiry_s = "inquiry";
/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
- * successful, various SG_LIB_CAT_* positive values or -1 -> other errors */
+ * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * The CMDDT field is obsolete in the INQUIRY cdb. */
int
-sg_ll_inquiry(int sg_fd, int cmddt, int evpd, int pg_op, void * resp,
+sg_ll_inquiry(int sg_fd, bool cmddt, bool evpd, int pg_op, void * resp,
int mx_resp_len, bool noisy, int verbose)
{
int res, ret, k, sense_cat, resid;
@@ -469,6 +470,93 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
return ret;
}
+/* Invokes a SCSI INQUIRY command and yields the response. Returns 0 when
+ * successful, various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * The CMDDT field is obsolete in the INQUIRY cdb (since spc3r16 in 2003) so
+ * an argument to set it has been removed (use the REPORT SUPPORTED OPERATION
+ * CODES command instead). Adds the ability to set the command abort timeout
+ * and the ability to report the residual count. If timeout_secs is zero
+ * or less the the default command abort timeout (60 seconds) is used.
+ * If residp is non-NULL then the residual value is written where residp
+ * points. A residual value of 0 implies mx_resp_len bytes have be written
+ * where resp points. If the residual value equals mx_resp_len then no
+ * bytes have been written. */
+int
+sg_ll_inquiry_v2(int sg_fd, bool evpd, int pg_op, void * resp,
+ int mx_resp_len, int timeout_secs, int * residp,
+ bool noisy, int verbose)
+{
+ int res, ret, k, sense_cat, resid;
+ unsigned char inq_cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ unsigned char * up;
+ struct sg_pt_base * ptvp;
+
+ if (evpd)
+ inq_cdb[1] |= 1;
+ inq_cdb[2] = (unsigned char)pg_op;
+ /* 16 bit allocation length (was 8) is a recent SPC-3 addition */
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, inq_cdb + 3);
+ if (verbose) {
+ pr2ws(" inquiry cdb: ");
+ for (k = 0; k < INQUIRY_CMDLEN; ++k)
+ pr2ws("%02x ", inq_cdb[k]);
+ pr2ws("\n");
+ }
+ if (resp && (mx_resp_len > 0)) {
+ up = (unsigned char *)resp;
+ up[0] = 0x7f; /* defensive prefill */
+ if (mx_resp_len > 4)
+ up[4] = 0;
+ }
+ if (timeout_secs <= 0)
+ timeout_secs = DEF_PT_TIMEOUT;
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2ws("%s: out of memory\n", __func__);
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, inq_cdb, sizeof(inq_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
+ res = do_scsi_pt(ptvp, sg_fd, timeout_secs, verbose);
+ ret = sg_cmds_process_resp(ptvp, "inquiry", res, mx_resp_len, sense_b,
+ noisy, verbose, &sense_cat);
+ resid = get_scsi_pt_resid(ptvp);
+ if (residp)
+ *residp = resid;
+ destruct_scsi_pt_obj(ptvp);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else if (ret < 4) {
+ if (verbose)
+ pr2ws("%s: got too few bytes (%d)\n", __func__, ret);
+ ret = SG_LIB_CAT_MALFORMED;
+ } else
+ ret = 0;
+
+ if (resid > 0) {
+ if (resid > mx_resp_len) {
+ pr2ws("INQUIRY resid (%d) should never exceed requested "
+ "len=%d\n", resid, mx_resp_len);
+ return ret ? ret : SG_LIB_CAT_MALFORMED;
+ }
+ /* zero unfilled section of response buffer */
+ memset((unsigned char *)resp + (mx_resp_len - resid), 0, resid);
+ }
+ return ret;
+}
+
/* Invokes a SCSI TEST UNIT READY command.
* 'pack_id' is just for diagnostics, safe to set to 0.
* Looks for progress indicator if 'progress' non-NULL;
@@ -498,8 +586,8 @@ sg_ll_test_unit_ready_progress(int sg_fd, int pack_id, int * progress,
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_packet_id(ptvp, pack_id);
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
- ret = sg_cmds_process_resp(ptvp, tur_s, res, 0, sense_b, noisy, verbose,
- &sense_cat);
+ ret = sg_cmds_process_resp(ptvp, tur_s, res, SG_NO_DATA_IN, sense_b,
+ noisy, verbose, &sense_cat);
if (-1 == ret)
;
else if (-2 == ret) {
@@ -539,7 +627,7 @@ sg_ll_test_unit_ready(int sg_fd, int pack_id, bool noisy, int verbose)
/* Invokes a SCSI REQUEST SENSE command. Returns 0 when successful, various
* SG_LIB_CAT_* positive values or -1 -> other errors */
int
-sg_ll_request_sense(int sg_fd, int desc, void * resp, int mx_resp_len,
+sg_ll_request_sense(int sg_fd, bool desc, void * resp, int mx_resp_len,
bool noisy, int verbose)
{
static const char * const rq_s = "request sense";