aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-05-02 22:02:05 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-05-02 22:02:05 +0000
commita59b767b38f08c0dafc011a58e8791aa06d4feb0 (patch)
tree8be0500cec5edb562779bc41f0ef7ad46b8c86fc /src
parentf65566c3934a9e22335dee20401cc1cc50865d56 (diff)
downloadsg3_utils-a59b767b38f08c0dafc011a58e8791aa06d4feb0.tar.gz
sg_lib: add sg_ll_inquiry_pt(), sg_ll_test_unit_ready_progress_pt(), sg_ll_request_sense_pt(), sg_ll_send_diag_pt(), sg_ll_receive_diag_pt(); sg_timestamp: add --elapsed, --hex and --no-timestamp options; sg_ses: check for NVMe enclosure bits
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@769 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.in5
-rw-r--r--src/sg_compare_and_write.c26
-rw-r--r--src/sg_copy_results.c13
-rw-r--r--src/sg_dd.c4
-rw-r--r--src/sg_get_lba_status.c34
-rw-r--r--src/sg_inq.c3
-rw-r--r--src/sg_logs.c46
-rw-r--r--src/sg_luns.c12
-rw-r--r--src/sg_modes.c2
-rw-r--r--src/sg_opcodes.c45
-rw-r--r--src/sg_raw.c6
-rw-r--r--src/sg_read.c4
-rw-r--r--src/sg_read_attr.c14
-rw-r--r--src/sg_read_long.c5
-rw-r--r--src/sg_referrals.c17
-rw-r--r--src/sg_rep_zones.c15
-rw-r--r--src/sg_sanitize.c2
-rw-r--r--src/sg_ses.c244
-rw-r--r--src/sg_stream_ctl.c18
-rw-r--r--src/sg_test_rwbuf.c24
-rw-r--r--src/sg_timestamp.c165
-rw-r--r--src/sg_vpd.c3
-rw-r--r--src/sg_write_long.c18
-rw-r--r--src/sg_write_same.c15
-rw-r--r--src/sg_write_verify.c17
-rw-r--r--src/sg_write_x.c22
-rw-r--r--src/sginfo.c2
-rw-r--r--src/sgm_dd.c28
-rw-r--r--src/sgp_dd.c104
30 files changed, 592 insertions, 324 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2407435f..18985656 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,7 +35,7 @@ endif
# For C++/clang testing
-## CC = gcc
+## CC = gcc-8
## CC = g++
## CC = clang
## CC = clang++
@@ -49,6 +49,7 @@ AM_CFLAGS = -Wall -W
# AM_CFLAGS = -Wall -W -pedantic -std=c11
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
+# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
sg_bg_ctl_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index 999c0f4b..dc56ca9c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.15 from Makefile.am.
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -579,6 +579,7 @@ AM_CFLAGS = -Wall -W
# AM_CFLAGS = -Wall -W -pedantic -std=c11
# AM_CFLAGS = -Wall -W -pedantic -std=c11 --analyze
# AM_CFLAGS = -Wall -W -pedantic -std=c++14
+# AM_CFLAGS = -Wall -W -pedantic -std=c++1z
sg_bg_ctl_LDADD = ../lib/libsgutils2.la
sg_compare_and_write_LDADD = ../lib/libsgutils2.la
sg_copy_results_LDADD = ../lib/libsgutils2.la
diff --git a/src/sg_compare_and_write.c b/src/sg_compare_and_write.c
index 1ede6e88..e4dbc5ae 100644
--- a/src/sg_compare_and_write.c
+++ b/src/sg_compare_and_write.c
@@ -54,7 +54,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.22 20180219";
+static const char * version_str = "1.22 20180428";
#define DEF_BLOCK_SIZE 512
#define DEF_NUM_BLOCKS (1)
@@ -457,11 +457,12 @@ int
main(int argc, char * argv[])
{
bool ifn_stdin;
- int res, half_xlen;
+ int res, half_xlen, vb;
int infd = -1;
int wfd = -1;
int devfd = -1;
uint8_t * wrkBuff = NULL;
+ uint8_t * free_wrkBuff = NULL;
struct opts_t * op;
struct opts_t opts;
@@ -473,7 +474,8 @@ main(int argc, char * argv[])
goto out;
}
- if (op->verbose) {
+ vb = op->verbose;
+ if (vb) {
pr2serr("Running COMPARE AND WRITE command with the "
"following options:\n in=%s ", op->ifn);
if (op->wfn_given)
@@ -501,16 +503,17 @@ main(int argc, char * argv[])
}
}
- devfd = open_dev(op->device_name, op->verbose);
+ devfd = open_dev(op->device_name, vb);
if (devfd < 0) {
res = -devfd;
goto out;
}
- wrkBuff = (uint8_t *)malloc(op->xfer_len);
- if (0 == wrkBuff) {
+ wrkBuff = (uint8_t *)sg_memalign(op->xfer_len, 0, &free_wrkBuff,
+ vb > 3);
+ if (NULL == wrkBuff) {
pr2serr("Not enough user memory\n");
- res = SG_LIB_CAT_OTHER;
+ res = sg_convert_errno(ENOMEM);
goto out;
}
@@ -547,7 +550,7 @@ main(int argc, char * argv[])
}
res = sg_ll_compare_and_write(devfd, wrkBuff, op->numblocks, op->lba,
op->xfer_len, op->flags, ! op->quiet,
- op->verbose);
+ vb);
out:
if (0 != res) {
@@ -559,15 +562,14 @@ out:
case SG_LIB_FILE_ERROR:
break; /* already reported */
default:
- sg_get_category_sense_str(res, sizeof(b), b,
- op->verbose);
+ sg_get_category_sense_str(res, sizeof(b), b, vb);
pr2serr(ME "SCSI COMPARE AND WRITE: %s\n", b);
break;
}
}
- if (wrkBuff)
- free(wrkBuff);
+ if (free_wrkBuff)
+ free(free_wrkBuff);
if ((infd >= 0) && (! ifn_stdin))
close(infd);
if (wfd >= 0)
diff --git a/src/sg_copy_results.c b/src/sg_copy_results.c
index 97cd5388..514a33b9 100644
--- a/src/sg_copy_results.c
+++ b/src/sg_copy_results.c
@@ -38,7 +38,7 @@
and the optional list identifier passed as the list_id argument.
*/
-static const char * version_str = "1.19 20180326";
+static const char * version_str = "1.20 20180428";
#define MAX_XFER_LEN 10000
@@ -314,6 +314,7 @@ main(int argc, char * argv[])
uint32_t list_id = 0;
const char * cp;
uint8_t * cpResultBuff = NULL;
+ uint8_t * free_cprb = NULL;
const char * device_name = NULL;
char file_name[256];
@@ -401,11 +402,12 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
- if (NULL == (cpResultBuff = (uint8_t *)malloc(xfer_len))) {
+ cpResultBuff = (uint8_t *)sg_memalign(xfer_len, 0, &free_cprb,
+ verbose > 3);
+ if (NULL == cpResultBuff) {
pr2serr(ME "out of memory\n");
- return SG_LIB_FILE_ERROR;
+ return sg_convert_errno(ENOMEM);
}
- memset(cpResultBuff, 0x00, xfer_len);
sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
@@ -453,7 +455,8 @@ main(int argc, char * argv[])
}
finish:
- free(cpResultBuff);
+ if (free_cprb)
+ free(free_cprb);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr(ME "close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_dd.c b/src/sg_dd.c
index 6abc50f4..af168fc6 100644
--- a/src/sg_dd.c
+++ b/src/sg_dd.c
@@ -62,7 +62,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "5.97 20180219";
+static const char * version_str = "5.98 20180502";
#define ME "sg_dd: "
@@ -71,7 +71,7 @@ static const char * version_str = "5.97 20180219";
#define STR_SZ 1024
#define INOUTF_SZ 512
-#define EBUFF_SZ 512
+#define EBUFF_SZ 768
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
diff --git a/src/sg_get_lba_status.c b/src/sg_get_lba_status.c
index 29e95115..7db694e4 100644
--- a/src/sg_get_lba_status.c
+++ b/src/sg_get_lba_status.c
@@ -32,7 +32,7 @@
* device.
*/
-static const char * version_str = "1.14 20180311";
+static const char * version_str = "1.15 20180425";
#ifndef UINT32_MAX
#define UINT32_MAX ((uint32_t)-1)
@@ -42,7 +42,6 @@ static const char * version_str = "1.14 20180311";
#define DEF_GLBAS_BUFF_LEN 24
static uint8_t glbasBuff[DEF_GLBAS_BUFF_LEN];
-static uint8_t * glbasBuffp = glbasBuff;
static struct option long_options[] = {
@@ -149,26 +148,28 @@ decode_lba_status_desc(const uint8_t * bp, uint64_t * slbap,
int
main(int argc, char * argv[])
{
+ bool do_16 = false;
+ bool do_32 = false;
+ bool do_raw = false;
+ bool o_readonly = false;
int sg_fd, k, j, res, c, rlen, num_descs, completion_cond;
int do_brief = 0;
int do_hex = 0;
- int64_t ll;
- uint64_t lba = 0;
+ int ret = 0;
+ int maxlen = DEF_GLBAS_BUFF_LEN;
+ int rt = 0;
+ int verbose = 0;
+ uint8_t add_status = 0; /* keep gcc quiet */
uint64_t d_lba = 0;
uint32_t d_blocks = 0;
uint32_t element_id = 0;
uint32_t scan_len = 0;
- int maxlen = DEF_GLBAS_BUFF_LEN;
- int rt = 0;
- int verbose = 0;
- bool do_16 = false;
- bool do_32 = false;
- bool do_raw = false;
- bool o_readonly = false;
+ int64_t ll;
+ uint64_t lba = 0;
const char * device_name = NULL;
const uint8_t * bp;
- int ret = 0;
- uint8_t add_status = 0; /* keep gcc quiet */
+ uint8_t * glbasBuffp = glbasBuff;
+ uint8_t * free_glbasBuffp = NULL;
while (1) {
int option_index = 0;
@@ -271,7 +272,8 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
if (maxlen > DEF_GLBAS_BUFF_LEN) {
- glbasBuffp = (uint8_t *)calloc(maxlen, 1);
+ glbasBuffp = (uint8_t *)sg_memalign(maxlen, 0, &free_glbasBuffp,
+ verbose > 3);
if (NULL == glbasBuffp) {
pr2serr("unable to allocate %d bytes on heap\n", maxlen);
return SG_LIB_SYNTAX_ERROR;
@@ -477,7 +479,7 @@ the_end:
ret = SG_LIB_FILE_ERROR;
}
free_buff:
- if (glbasBuffp && (glbasBuffp != glbasBuff))
- free(glbasBuffp);
+ if (free_glbasBuffp)
+ free(free_glbasBuffp);
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/src/sg_inq.c b/src/sg_inq.c
index 57f234db..85dab11a 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
@@ -48,7 +49,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "1.92 20180405"; /* SPC-5 rev 19 */
+static const char * version_str = "1.93 20180425"; /* SPC-5 rev 19 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
diff --git a/src/sg_logs.c b/src/sg_logs.c
index c8086115..283a1831 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -34,7 +34,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.63 20180325"; /* spc5r19 + sbc4r11 */
+static const char * version_str = "1.65 20180501"; /* spc5r19 + sbc4r11 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -3042,17 +3042,22 @@ show_app_client_page(const uint8_t * resp, int len, const struct opts_t * op)
static bool
show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
{
- int k, num, extra, pc;
+ int k, num, param_len, pc;
const uint8_t * bp;
const char * cp;
char str[PCB_STR_LEN];
char b[256];
char bb[32];
- bool full, decoded, has_header;
+ bool full, decoded;
+ bool has_header = false;
bool is_smstr = op->lep ? (MVP_SMSTR & op->lep->flags) :
(VP_SMSTR == op->vend_prod_num);
full = ! op->do_temperature;
+ if ('\0' != t10_vendor_str[0]) {
+ if (0 != strcmp(vp_arr[VP_SMSTR].t10_vendorp, t10_vendor_str))
+ is_smstr = false; /* Inquiry vendor string says not SmrtStor */
+ }
num = len - 4;
bp = &resp[0] + 4;
if (num < 4) {
@@ -3063,54 +3068,63 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
if (full)
printf("Informational Exceptions page [0x2f]\n");
}
- for (k = num, has_header = false; k > 0; k -= extra, bp += extra) {
+ for (k = num; k > 0; k -= param_len, bp += param_len) {
if (k < 3) {
printf("short Informational Exceptions page\n");
return false;
}
- extra = bp[3] + 4;
+ param_len = bp[3] + 4;
pc = sg_get_unaligned_be16(bp + 0);
if (op->filter_given) {
if (pc != op->filter)
continue;
if (op->do_raw) {
- dStrRaw(bp, extra);
+ dStrRaw(bp, param_len);
break;
} else if (op->do_hex) {
- hex2stdout(bp, extra, ((1 == op->do_hex) ? 1 : -1));
+ hex2stdout(bp, param_len, ((1 == op->do_hex) ? 1 : -1));
break;
}
}
decoded = true;
cp = NULL;
+
switch (pc) {
case 0x0:
- if (extra > 5) {
+ if (param_len > 5) {
if (full) {
printf(" IE asc = 0x%x, ascq = 0x%x", bp[4], bp[5]);
if (bp[4] || bp[5])
if(sg_get_asc_ascq_str(bp[4], bp[5], sizeof(b), b))
printf("\n [%s]", b);
}
- if (extra > 6) {
+ if (param_len > 6) {
if (bp[6] < 0xff)
printf("\n Current temperature = %d C", bp[6]);
else
printf("\n Current temperature = <not available>");
- if (extra > 7) {
+ if (param_len > 7) {
if (bp[7] < 0xff)
printf("\n Threshold temperature = %d C "
"[common extension]", bp[7]);
else
printf("\n Threshold temperature = <not "
"available>");
- }
+ if ((param_len > 8) && (bp[8] >= bp[6])) {
+ if (bp[8] < 0xff)
+ printf("\n Maximum temperature = %d C "
+ "[(since new), extension]", bp[8]);
+ else
+ printf("\n Maximum temperature = <not "
+ "available>");
+ }
+ }
}
decoded = true;
}
break;
default:
- if (! is_smstr) {
+ if ((! is_smstr) || (param_len < 24)) {
decoded = false;
break;
}
@@ -3170,8 +3184,8 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
break;
}
break;
- }
- if (cp && (extra >= 24)) {
+ } /* end of switch statement */
+ if (cp && (param_len >= 24)) {
if (! has_header) {
has_header = true;
printf(" Has|Ever %% to worst %% Current "
@@ -3188,14 +3202,14 @@ show_ie_page(const uint8_t * resp, int len, const struct opts_t * op)
/* decoded = true; */
} else if ((! decoded) && full) {
printf(" parameter code = 0x%x, contents in hex:\n", pc);
- hex2stdout(bp, extra, 1);
+ hex2stdout(bp, param_len, 1);
}
printf("\n");
if (op->do_pcb)
printf(" <%s>\n", get_pcb_str(bp[2], str, sizeof(str)));
if (op->filter_given)
break;
- }
+ } /* end of for loop */
return true;
}
diff --git a/src/sg_luns.c b/src/sg_luns.c
index 20502ef5..cacb37c6 100644
--- a/src/sg_luns.c
+++ b/src/sg_luns.c
@@ -31,7 +31,7 @@
* and decodes the response.
*/
-static const char * version_str = "1.38 20180329";
+static const char * version_str = "1.39 20180425";
#define MAX_RLUNS_BUFF_LEN (1024 * 1024)
#define DEF_RLUNS_BUFF_LEN (1024 * 8)
@@ -380,6 +380,7 @@ main(int argc, char * argv[])
const char * device_name = NULL;
const char * cp;
uint8_t * reportLunsBuff = NULL;
+ uint8_t * free_reportLunsBuff = NULL;
uint8_t lun_arr[8];
struct sg_simple_inquiry_resp sir;
@@ -593,9 +594,10 @@ main(int argc, char * argv[])
if (0 == maxlen)
maxlen = DEF_RLUNS_BUFF_LEN;
- reportLunsBuff = (uint8_t *)calloc(1, maxlen);
+ reportLunsBuff = (uint8_t *)sg_memalign(maxlen, 0, &free_reportLunsBuff,
+ verbose > 3);
if (NULL == reportLunsBuff) {
- pr2serr("unable to malloc %d bytes\n", maxlen);
+ pr2serr("unable to sg_memalign %d bytes\n", maxlen);
return SG_LIB_CAT_OTHER;
}
trunc = false;
@@ -669,8 +671,8 @@ main(int argc, char * argv[])
}
the_end:
- if (reportLunsBuff)
- free(reportLunsBuff);
+ if (free_reportLunsBuff)
+ free(free_reportLunsBuff);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 0a839526..e680a153 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -550,7 +550,7 @@ static struct page_code_desc pc_desc_disk[] = {
{0xa, 0x5, "IO advice hints grouping"}, /* added sbc4r06 */
{0xa, 0x6, "Background operation control"}, /* added sbc4r07 */
{0xa, 0xf1, "Parallel ATA control (SAT)"},
- {0xa, 0xf2, "Reserved (SATA control) (SAT)"},
+/* {0xa, 0xf2, "Reserved (SATA control) (SAT)"}, // proposed + dropped ?? */
{0xb, 0x0, "Medium types supported (obsolete)"},
{0xc, 0x0, "Notch and partition (obsolete)"},
{0xd, 0x0, "Power condition (obsolete, moved to 0x1a)"},
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 8164dfb5..4e7f73d5 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -17,6 +17,7 @@
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#include <getopt.h>
#ifdef HAVE_CONFIG_H
@@ -30,7 +31,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.58 20180403"; /* spc5r14 */
+static const char * version_str = "0.59 20180428"; /* spc5r14 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -45,7 +46,7 @@ static const char * version_str = "0.58 20180403"; /* spc5r14 */
#define NAME_BUFF_SZ 128
-#define SEAGATE_READ_UDS_DATA_CMD 0xf7 /* may start reporting vendor cmds */
+#define SEAGATE_READ_UDS_DATA_CMD 0xf7 /* may start reporting vendor cmds */
static int peri_dtype = -1; /* ugly but not easy to pass to alpha compare */
@@ -907,12 +908,13 @@ list_one(uint8_t * rsoc_buff, int cd_len, int rep_opts,
int
main(int argc, char * argv[])
{
- int sg_fd, cd_len, res, len, act_len, rq_len;
+ int sg_fd, cd_len, res, len, act_len, rq_len, vb;
int rep_opts = 0;
const char * cp;
struct opts_t * op;
const char * op_name;
- uint8_t rsoc_buff[MX_ALLOC_LEN];
+ uint8_t * rsoc_buff = NULL;
+ uint8_t * free_rsoc_buff = NULL;
char buff[48];
char b[80];
struct sg_simple_inquiry_resp inq_resp;
@@ -936,6 +938,7 @@ main(int argc, char * argv[])
pr2serr("Version string: %s\n", version_str);
return 0;
}
+ vb = op->verbose;
if ((NULL == op->device_name) && (! op->do_enumerate)) {
pr2serr("No DEVICE argument given\n");
@@ -976,7 +979,7 @@ main(int argc, char * argv[])
if (peri_dtype < 0)
peri_dtype = 0;
printf("SCSI command:");
- if (op->verbose)
+ if (vb)
printf(" [opcode=0x%x, sa=0x%x, pdt=0x%x]\n", op->opcode,
op->servact, peri_dtype);
else
@@ -990,18 +993,25 @@ main(int argc, char * argv[])
op_name = op->do_taskman ? "Report supported task management functions" :
"Report supported operation codes";
+ rsoc_buff = (uint8_t *)sg_memalign(MX_ALLOC_LEN, 0, &free_rsoc_buff,
+ vb > 3);
+ if (NULL == rsoc_buff) {
+ pr2serr("Unable to allocate memory\n");
+ return sg_convert_errno(ENOMEM);
+ }
+
if (op->opcode < 0) {
- if ((sg_fd = scsi_pt_open_device(op->device_name, 1 /* RO */,
- op->verbose)) < 0) {
+ /* Try to open read-only */
+ if ((sg_fd = scsi_pt_open_device(op->device_name, 1, vb)) < 0) {
pr2serr("sg_opcodes: error opening file (ro): %s: %s\n",
op->device_name, safe_strerror(-sg_fd));
- return SG_LIB_FILE_ERROR;
+ goto open_rw;
}
if (op->no_inquiry && (peri_dtype < 0))
pr2serr("--no-inquiry ignored because --pdt= not given\n");
if (op->no_inquiry && (peri_dtype >= 0))
;
- else if (0 == sg_simple_inquiry(sg_fd, &inq_resp, true, op->verbose)) {
+ else if (0 == sg_simple_inquiry(sg_fd, &inq_resp, true, vb)) {
peri_dtype = inq_resp.peripheral_type;
if (! (op->do_raw || op->no_inquiry)) {
printf(" %.8s %.16s %.4s\n", inq_resp.vendor,
@@ -1024,26 +1034,25 @@ main(int argc, char * argv[])
}
}
- if ((sg_fd = scsi_pt_open_device(op->device_name, 0 /* RW */,
- op->verbose)) < 0) {
+open_rw:
+ if ((sg_fd = scsi_pt_open_device(op->device_name, 0 /* RW */, vb)) < 0) {
pr2serr("sg_opcodes: error opening file (rw): %s: %s\n",
op->device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
if (op->opcode >= 0)
rep_opts = ((op->servact >= 0) ? 2 : 1);
- memset(rsoc_buff, 0, sizeof(rsoc_buff));
if (op->do_taskman) {
rq_len = (op->do_repd ? 16 : 4);
- res = do_rstmf(sg_fd, op->do_repd, rsoc_buff,
- rq_len, &act_len, true, op->verbose);
+ res = do_rstmf(sg_fd, op->do_repd, rsoc_buff, rq_len, &act_len, true,
+ vb);
} else {
- rq_len = sizeof(rsoc_buff);
+ rq_len = MX_ALLOC_LEN;
res = do_rsoc(sg_fd, op->do_rctd, rep_opts, op->opcode, op->servact,
- rsoc_buff, rq_len, &act_len, true, op->verbose);
+ rsoc_buff, rq_len, &act_len, true, vb);
}
if (res) {
- sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
+ sg_get_category_sense_str(res, sizeof(b), b, vb);
pr2serr("%s: %s\n", op_name, b);
goto err_out;
}
@@ -1133,6 +1142,8 @@ main(int argc, char * argv[])
res = 0;
err_out:
+ if (free_rsoc_buff)
+ free(free_rsoc_buff);
scsi_pt_close_device(sg_fd);
return res;
}
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 9dee2852..d480e6d0 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -37,7 +37,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.24 (2018-03-02)"
+#define SG_RAW_VERSION "0.4.25 (2018-04-25)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -576,7 +576,7 @@ fetch_dataout(struct opts_t * op, uint8_t ** free_buf, int * errp)
pr2serr("sg_memalign: failed to get %d bytes of memory\n",
op->dataout_len);
if (errp)
- *errp = SG_LIB_OS_BASE_ERR + ENOMEM;
+ *errp = sg_convert_errno(ENOMEM);
goto bail;
}
@@ -728,7 +728,7 @@ main(int argc, char *argv[])
if (dinp == NULL) {
pr2serr("sg_memalign: failed to get %d bytes of memory\n",
din_len);
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto done;
}
if (op->verbose > 2)
diff --git a/src/sg_read.c b/src/sg_read.c
index 9d9038cd..9326b180 100644
--- a/src/sg_read.c
+++ b/src/sg_read.c
@@ -53,7 +53,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.30 20180219";
+static const char * version_str = "1.31 20180502";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -368,7 +368,7 @@ static int sg_bread(int sg_fd, uint8_t * buff, int blocks,
#define STR_SZ 1024
#define INF_SZ 512
-#define EBUFF_SZ 512
+#define EBUFF_SZ 768
int main(int argc, char * argv[])
diff --git a/src/sg_read_attr.c b/src/sg_read_attr.c
index c8673e61..ff10af92 100644
--- a/src/sg_read_attr.c
+++ b/src/sg_read_attr.c
@@ -12,6 +12,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
@@ -36,7 +37,7 @@
* and decodes the response. Based on spc5r08.pdf
*/
-static const char * version_str = "1.08 20180219";
+static const char * version_str = "1.09 20180425";
#define MAX_RATTR_BUFF_LEN (1024 * 1024)
#define DEF_RATTR_BUFF_LEN (1024 * 8)
@@ -912,6 +913,7 @@ main(int argc, char * argv[])
const char * device_name = NULL;
const char * fname = NULL;
uint8_t * rabp = NULL;
+ uint8_t * free_rabp = NULL;
struct opts_t opts;
struct opts_t * op;
char b[80];
@@ -1052,10 +1054,10 @@ main(int argc, char * argv[])
if (0 == op->maxlen)
op->maxlen = DEF_RATTR_BUFF_LEN;
- rabp = (uint8_t *)calloc(1, op->maxlen);
+ rabp = (uint8_t *)sg_memalign(op->maxlen, 0, &free_rabp, op->verbose > 3);
if (NULL == rabp) {
- pr2serr("unable to calloc %d bytes\n", op->maxlen);
- return SG_LIB_CAT_OTHER;
+ pr2serr("unable to sg_memalign %d bytes\n", op->maxlen);
+ return sg_convert_errno(ENOMEM);
}
if (NULL == device_name) {
@@ -1142,7 +1144,7 @@ close_then_end:
ret = SG_LIB_FILE_ERROR;
}
clean_up:
- if (rabp)
- free(rabp);
+ if (free_rabp)
+ free(free_rabp);
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/src/sg_read_long.c b/src/sg_read_long.c
index e214e5f6..1c278801 100644
--- a/src/sg_read_long.c
+++ b/src/sg_read_long.c
@@ -33,13 +33,13 @@
#include "sg_cmds_extra.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.24 20180219";
+static const char * version_str = "1.26 20180502";
#define MAX_XFER_LEN 10000
#define ME "sg_read_long: "
-#define EBUFF_SZ 256
+#define EBUFF_SZ 512
static struct option long_options[] = {
@@ -53,6 +53,7 @@ static struct option long_options[] = {
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"xfer_len", required_argument, 0, 'x'},
+ {"xfer-len", required_argument, 0, 'x'},
{0, 0, 0, 0},
};
diff --git a/src/sg_referrals.c b/src/sg_referrals.c
index 96e1368e..83ab89e7 100644
--- a/src/sg_referrals.c
+++ b/src/sg_referrals.c
@@ -12,6 +12,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>
@@ -34,7 +35,7 @@
* SCSI device.
*/
-static const char * version_str = "1.10 20180219"; /* sbc4r10 */
+static const char * version_str = "1.11 20180425"; /* sbc4r10 */
#define MAX_REFER_BUFF_LEN (1024 * 1024)
#define DEF_REFER_BUFF_LEN 256
@@ -48,7 +49,6 @@ static const char * version_str = "1.10 20180219"; /* sbc4r10 */
#define TPGS_STATE_TRANSITIONING 0xf
static uint8_t referralBuff[DEF_REFER_BUFF_LEN];
-static uint8_t * referralBuffp = referralBuff;
static const char *decode_tpgs_state(const int st)
{
@@ -86,6 +86,7 @@ static struct option long_options[] = {
{"lba", required_argument, 0, 'l'},
{"maxlen", required_argument, 0, 'm'},
{"one-segment", no_argument, 0, 's'},
+ {"one_segment", no_argument, 0, 's'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
{"verbose", no_argument, 0, 'v'},
@@ -182,6 +183,8 @@ main(int argc, char * argv[])
uint64_t lba = 0;
const char * device_name = NULL;
const uint8_t * bp;
+ uint8_t * referralBuffp = referralBuff;
+ uint8_t * free_referralBuffp = NULL;
while (1) {
int option_index = 0;
@@ -255,10 +258,12 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
if (maxlen > DEF_REFER_BUFF_LEN) {
- referralBuffp = (uint8_t *)calloc(maxlen, 1);
+ referralBuffp = (uint8_t *)sg_memalign(maxlen, 0,
+ &free_referralBuffp,
+ verbose > 3);
if (NULL == referralBuffp) {
pr2serr("unable to allocate %d bytes on heap\n", maxlen);
- return SG_LIB_SYNTAX_ERROR;
+ return sg_convert_errno(ENOMEM);
}
}
if (do_raw) {
@@ -343,7 +348,7 @@ the_end:
ret = SG_LIB_FILE_ERROR;
}
free_buff:
- if (referralBuffp && (referralBuffp != referralBuff))
- free(referralBuffp);
+ if (free_referralBuffp)
+ free(free_referralBuffp);
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
diff --git a/src/sg_rep_zones.c b/src/sg_rep_zones.c
index 2e8ef942..ce4078ad 100644
--- a/src/sg_rep_zones.c
+++ b/src/sg_rep_zones.c
@@ -12,6 +12,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#define __STDC_FORMAT_MACROS 1
@@ -35,7 +36,7 @@
* and decodes the response. Based on zbc-r02.pdf
*/
-static const char * version_str = "1.15 20180219";
+static const char * version_str = "1.16 20180425";
#define MAX_RZONES_BUFF_LEN (1024 * 1024)
#define DEF_RZONES_BUFF_LEN (1024 * 8)
@@ -287,6 +288,7 @@ main(int argc, char * argv[])
int64_t ll;
const char * device_name = NULL;
uint8_t * reportZonesBuff = NULL;
+ uint8_t * free_rzbp = NULL;
uint8_t * bp;
char b[80];
@@ -390,10 +392,11 @@ main(int argc, char * argv[])
if (0 == maxlen)
maxlen = DEF_RZONES_BUFF_LEN;
- reportZonesBuff = (uint8_t *)calloc(1, maxlen);
+ reportZonesBuff = (uint8_t *)sg_memalign(maxlen, 0, &free_rzbp,
+ verbose > 3);
if (NULL == reportZonesBuff) {
- pr2serr("unable to malloc %d bytes\n", maxlen);
- return SG_LIB_CAT_OTHER;
+ pr2serr("unable to sg_memalign %d bytes\n", maxlen);
+ return sg_convert_errno(ENOMEM);
}
res = sg_ll_report_zones(sg_fd, st_lba, do_partial, reporting_opt,
@@ -467,8 +470,8 @@ main(int argc, char * argv[])
}
the_end:
- if (reportZonesBuff)
- free(reportZonesBuff);
+ if (free_rzbp)
+ free(free_rzbp);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_sanitize.c b/src/sg_sanitize.c
index e67a634c..38e5030b 100644
--- a/src/sg_sanitize.c
+++ b/src/sg_sanitize.c
@@ -661,7 +661,7 @@ main(int argc, char * argv[])
if (! got_stdin)
close(infd);
}
- wBuff[0] = op->count & 0x1f;;
+ wBuff[0] = op->count & 0x1f;
if (op->test)
wBuff[0] |= ((op->test & 0x3) << 5);
if (op->invert)
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 41eea275..15d76295 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -28,9 +28,7 @@
#include "sg_cmds_basic.h"
#include "sg_cmds_extra.h"
#include "sg_unaligned.h"
-#ifdef SG_LIB_WIN32
-#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
-#endif
+#include "sg_pt.h"
#include "sg_pr2serr.h"
/*
@@ -38,10 +36,11 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "2.35 20180305"; /* ses4r02 */
+static const char * version_str = "2.37 20180502"; /* ses4r02 */
#define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
+#define REQUEST_SENSE_RESP_SZ 252
#define DATA_IN_OFF 4
#define MIN_DATA_IN_SZ 8192 /* use max(MIN_DATA_IN_SZ, op->maxlen) for
* the size of data_arr */
@@ -499,6 +498,7 @@ static struct element_type_t element_type_by_code =
/* Many control element names below have "RQST" in front in drafts.
These are for the Enclosure Control/Status diagnostic page */
static struct acronym2tuple ecs_a2t_arr[] = {
+ /* acron element_type start_byte start_bit num_bits */
{"ac_fail", UI_POWER_SUPPLY_ETC, 2, 4, 1, NULL},
{"ac_hi", UI_POWER_SUPPLY_ETC, 2, 6, 1, NULL},
{"ac_lo", UI_POWER_SUPPLY_ETC, 2, 7, 1, NULL},
@@ -557,7 +557,8 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"fault", ARRAY_DEV_ETC, 3, 5, 1, NULL},
{"hotspare", ARRAY_DEV_ETC, 1, 5, 1, NULL},
{"hotswap", COOLING_ETC, 3, 7, 1, NULL},
- {"hotswap", ENC_SCELECTR_ETC, 3, 7, 1, NULL},
+ {"hotswap", ENC_SCELECTR_ETC, 3, 7, 1, NULL}, /* status only */
+ {"hw_reset", ENC_SCELECTR_ETC, 1, 2, 1, "hardware reset"}, /* 18-047r0 */
{"ident", DEVICE_ETC, 2, 1, 1, "flash LED"},
{"ident", ARRAY_DEV_ETC, 2, 1, 1, "flash LED"},
{"ident", POWER_SUPPLY_ETC, 1, 7, 1, "flash LED"},
@@ -652,7 +653,7 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"remove", DEVICE_ETC, 2, 2, 1, NULL},
{"remove", ARRAY_DEV_ETC, 2, 2, 1, NULL},
{"remind", AUD_ALARM_ETC, 3, 4, 1, NULL},
- {"report", ENC_SCELECTR_ETC, 2, 0, 1, NULL},
+ {"report", ENC_SCELECTR_ETC, 2, 0, 1, NULL}, /* status only */
{"report", SCC_CELECTR_ETC, 2, 0, 1, NULL},
{"report", SCSI_IPORT_ETC, 2, 0, 1, NULL},
{"report", SCSI_TPORT_ETC, 2, 0, 1, NULL},
@@ -661,7 +662,7 @@ static struct acronym2tuple ecs_a2t_arr[] = {
{"rqst_override", TEMPERATURE_ETC, 3, 7, 1, "Request(ed) override"},
{"rrabort", ARRAY_DEV_ETC, 1, 0, 1, "rebuild/remap abort"},
{"rsvddevice", ARRAY_DEV_ETC, 1, 6, 1, "reserved device"},
- {"select_element", ENC_SCELECTR_ETC, 2, 0, 1, NULL},
+ {"select_element", ENC_SCELECTR_ETC, 2, 0, 1, NULL}, /* control */
{"short_stat", SIMPLE_SUBENC_ETC, 3, 7, 8, "short enclosure status"},
{"size", NV_CACHE_ETC, 2, 7, 16, NULL},
{"speed_act", COOLING_ETC, 1, 2, 11, "actual speed (rpm / 10)"},
@@ -669,6 +670,7 @@ static struct acronym2tuple ecs_a2t_arr[] = {
"0: leave; 1: lowest... 7: highest"},
{"size_mult", NV_CACHE_ETC, 1, 1, 2, NULL},
{"swap", -1, 0, 4, 1, NULL}, /* Reset swap */
+ {"sw_reset", ENC_SCELECTR_ETC, 1, 3, 1, "software reset"},/* 18-047r0 */
{"temp", TEMPERATURE_ETC, 2, 7, 8, "(Requested) temperature"},
{"unlock", DOOR_ETC, 3, 0, 1, NULL},
{"undertemp_fail", TEMPERATURE_ETC, 3, 1, 1, "Undertemperature failure"},
@@ -738,6 +740,7 @@ static struct option long_options[] = {
{"data", required_argument, 0, 'd'},
{"descriptor", required_argument, 0, 'D'},
{"dev-slot-num", required_argument, 0, 'x'},
+ {"dev_slot_num", required_argument, 0, 'x'},
{"dsn", required_argument, 0, 'x'},
{"eiioe", required_argument, 0, 'E'},
{"enumerate", no_argument, 0, 'e'},
@@ -747,6 +750,7 @@ static struct option long_options[] = {
{"hex", no_argument, 0, 'H'},
{"index", required_argument, 0, 'I'},
{"inner-hex", no_argument, 0, 'i'},
+ {"inner_hex", no_argument, 0, 'i'},
{"join", no_argument, 0, 'j'},
{"list", no_argument, 0, 'l'},
{"nickid", required_argument, 0, 'N'},
@@ -758,6 +762,7 @@ static struct option long_options[] = {
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
{"sas-addr", required_argument, 0, 'A'},
+ {"sas_addr", required_argument, 0, 'A'},
{"set", required_argument, 0, 'S'},
{"status", no_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
@@ -1508,7 +1513,7 @@ parse_cmd_line(struct opts_t *op, int argc, char *argv[])
}
if ((! (op->do_data && op->do_status)) && (NULL == op->dev_name)) {
- pr2serr("missing DEVICE name!\n");
+ pr2serr("missing DEVICE name!\n\n");
goto err_help;
}
return 0;
@@ -1636,12 +1641,12 @@ match_last_ind_indiv(int index, const struct opts_t * op)
/* Return of 0 -> success, SG_LIB_CAT_* positive values or -1 -> other
* failures */
static int
-do_senddiag(int sg_fd, void * outgoing_pg, int outgoing_len, bool noisy,
- int verbose)
+do_senddiag(struct sg_pt_base * ptvp, void * outgoing_pg, int outgoing_len,
+ bool noisy, int verbose)
{
const bool pf_bit = true;
+ int page_num, ret;
const char * cp;
- int page_num;
if (outgoing_pg && (verbose > 2)) {
page_num = ((const char *)outgoing_pg)[0];
@@ -1652,10 +1657,12 @@ do_senddiag(int sg_fd, void * outgoing_pg, int outgoing_len, bool noisy,
pr2serr(" Send diagnostic command page number: 0x%x\n",
page_num);
}
- return sg_ll_send_diag(sg_fd, 0 /* sf_code */, pf_bit, false /* sf_bit */,
- false /* devofl_bit */, false /* unitofl_bit */,
- 0 /* long_duration */, outgoing_pg, outgoing_len,
- noisy, verbose);
+ ret = sg_ll_send_diag_pt(ptvp, 0 /* sf_code */, pf_bit,
+ false /* sf_bit */, false /* devofl_bit */,
+ false /* unitofl_bit */, 0 /* long_duration */,
+ outgoing_pg, outgoing_len, noisy, verbose);
+ clear_scsi_pt_obj(ptvp);
+ return ret;
}
/* Fetch diagnostic page name (status and/or control). Returns NULL if not
@@ -1826,7 +1833,7 @@ find_join_row_cnst(const struct th_es_t * tesp, int index,
/* Return of 0 -> success, SG_LIB_CAT_* positive values or -2 if response
* had bad format, -1 -> other failures */
static int
-do_rec_diag(int sg_fd, int page_code, uint8_t * rsp_buff,
+do_rec_diag(struct sg_pt_base * ptvp, int page_code, uint8_t * rsp_buff,
int rsp_buff_size, struct opts_t * op, int * rsp_lenp)
{
int k, d_len, rsp_len, res;
@@ -1889,9 +1896,10 @@ do_rec_diag(int sg_fd, int page_code, uint8_t * rsp_buff,
}
if (vb > 1)
pr2serr(" %s command for %s\n", rdr, cp);
- res = sg_ll_receive_diag_v2(sg_fd, true /* pcv */, page_code, rsp_buff,
+ res = sg_ll_receive_diag_pt(ptvp, true /* pcv */, page_code, rsp_buff,
rsp_buff_size, 0 /* default timeout */,
&resid, ! op->quiet, vb);
+ clear_scsi_pt_obj(ptvp);
decode:
if (0 == res) {
rsp_len = sg_get_unaligned_be16(rsp_buff + 2) + 4;
@@ -2045,7 +2053,8 @@ truncated:
* Returns total number of type descriptor headers written to 'tdhp' or -1
* if there is a problem */
static int
-build_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, int max_elems,
+build_type_desc_hdr_arr(struct sg_pt_base * ptvp,
+ struct type_desc_hdr_t * tdhp, int max_elems,
uint32_t * generationp,
struct enclosure_info * primary_ip,
struct opts_t * op)
@@ -2065,7 +2074,7 @@ build_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, int max_elems,
ret = -1;
goto the_end;
}
- res = do_rec_diag(fd, CONFIGURATION_DPC, config_dp_resp, op->maxlen,
+ res = do_rec_diag(ptvp, CONFIGURATION_DPC, config_dp_resp, op->maxlen,
op, &resp_len);
if (res) {
pr2serr("%s: couldn't read config page, res=%d\n", __func__, res);
@@ -4063,8 +4072,8 @@ err_with_fp:
}
static int
-process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
- struct opts_t * op)
+process_status_dpage(struct sg_pt_base * ptvp, int page_code, uint8_t * resp,
+ int resp_len, struct opts_t * op)
{
int j, num_ths;
int ret = 0;
@@ -4112,7 +4121,7 @@ process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
configuration_sdg(resp, resp_len);
break;
case ENC_STATUS_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr,
MX_ELEM_HDR, &ref_gen_code,
&primary_info, op);
if (num_ths < 0) {
@@ -4130,7 +4139,7 @@ process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
enc_status_dp(tesp, ref_gen_code, resp, resp_len, op);
break;
case ARRAY_STATUS_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr,
MX_ELEM_HDR, &ref_gen_code,
&primary_info, op);
if (num_ths < 0) {
@@ -4164,7 +4173,7 @@ process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
printf(" <empty>\n");
break;
case THRESHOLD_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr,
MX_ELEM_HDR, &ref_gen_code,
&primary_info, op);
if (num_ths < 0) {
@@ -4182,7 +4191,7 @@ process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
threshold_sdg(tesp, ref_gen_code, resp, resp_len, op);
break;
case ELEM_DESC_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr,
MX_ELEM_HDR, &ref_gen_code,
&primary_info, op);
if (num_ths < 0) {
@@ -4209,7 +4218,7 @@ process_status_dpage(int sg_fd, int page_code, uint8_t * resp, int resp_len,
resp[1] & 1, (resp[1] >> 1) & 0xff);
break;
case ADD_ELEM_STATUS_DPC:
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr,
MX_ELEM_HDR, &ref_gen_code,
&primary_info, op);
if (num_ths < 0) {
@@ -4255,7 +4264,7 @@ fini:
/* Display "status" page or pages (if op->page_code==0xff) . data-in from
* SES device or user provided (with --data= option). Return 0 for success */
static int
-process_status_page_s(int sg_fd, struct opts_t * op)
+process_status_page_s(struct sg_pt_base * ptvp, struct opts_t * op)
{
int page_code, ret, resp_len;
uint8_t * resp = NULL;
@@ -4276,10 +4285,10 @@ process_status_page_s(int sg_fd, struct opts_t * op)
const int s_arr_sz = sizeof(supp_dpg_arr);
memset(supp_dpg_arr, 0, s_arr_sz);
- ret = do_rec_diag(sg_fd, SUPPORTED_DPC, resp, op->maxlen, op,
+ ret = do_rec_diag(ptvp, SUPPORTED_DPC, resp, op->maxlen, op,
&resp_len);
if (ret) /* SUPPORTED_DPC failed so try SUPPORTED_SES_DPC */
- ret = do_rec_diag(sg_fd, SUPPORTED_SES_DPC, resp, op->maxlen, op,
+ ret = do_rec_diag(ptvp, SUPPORTED_SES_DPC, resp, op->maxlen, op,
&resp_len);
if (ret)
goto fini;
@@ -4301,17 +4310,17 @@ process_status_page_s(int sg_fd, struct opts_t * op)
}
for (k = 0; k < n; ++k) {
page_code = supp_dpg_arr[k];
- ret = do_rec_diag(sg_fd, page_code, resp, op->maxlen, op,
+ ret = do_rec_diag(ptvp, page_code, resp, op->maxlen, op,
&resp_len);
if (ret)
goto fini;
- ret = process_status_dpage(sg_fd, page_code, resp, resp_len, op);
+ ret = process_status_dpage(ptvp, page_code, resp, resp_len, op);
}
} else { /* asking for a specific page code */
- ret = do_rec_diag(sg_fd, page_code, resp, op->maxlen, op, &resp_len);
+ ret = do_rec_diag(ptvp, page_code, resp, op->maxlen, op, &resp_len);
if (ret)
goto fini;
- ret = process_status_dpage(sg_fd, page_code, resp, resp_len, op);
+ ret = process_status_dpage(ptvp, page_code, resp, resp_len, op);
}
fini:
@@ -4785,7 +4794,7 @@ join_juggle_aes(struct th_es_t * tesp, uint8_t * es_bp, const uint8_t * ed_bp,
* 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, bool display)
+join_work(struct sg_pt_base * ptvp, struct opts_t * op, bool display)
{
bool broken_ei;
int j, res, num_ths, mlen;
@@ -4802,7 +4811,7 @@ join_work(int sg_fd, struct opts_t * op, bool display)
struct th_es_t tes;
memset(&primary_info, 0, sizeof(primary_info));
- num_ths = build_type_desc_hdr_arr(sg_fd, type_desc_hdr_arr, MX_ELEM_HDR,
+ num_ths = build_type_desc_hdr_arr(ptvp, type_desc_hdr_arr, MX_ELEM_HDR,
&ref_gen_code, &primary_info, op);
if (num_ths < 0)
return num_ths;
@@ -4819,7 +4828,7 @@ join_work(int sg_fd, struct opts_t * op, bool display)
mlen = enc_stat_rsp_sz;
if (mlen > op->maxlen)
mlen = op->maxlen;
- res = do_rec_diag(sg_fd, ENC_STATUS_DPC, enc_stat_rsp, mlen, op,
+ res = do_rec_diag(ptvp, ENC_STATUS_DPC, enc_stat_rsp, mlen, op,
&enc_stat_rsp_len);
if (res)
return res;
@@ -4838,7 +4847,7 @@ join_work(int sg_fd, struct opts_t * op, bool display)
mlen = elem_desc_rsp_sz;
if (mlen > op->maxlen)
mlen = op->maxlen;
- res = do_rec_diag(sg_fd, ELEM_DESC_DPC, elem_desc_rsp, mlen, op,
+ res = do_rec_diag(ptvp, ELEM_DESC_DPC, elem_desc_rsp, mlen, op,
&elem_desc_rsp_len);
if (0 == res) {
if (elem_desc_rsp_len < 8) {
@@ -4866,7 +4875,7 @@ join_work(int sg_fd, struct opts_t * op, bool display)
mlen = add_elem_rsp_sz;
if (mlen > op->maxlen)
mlen = op->maxlen;
- res = do_rec_diag(sg_fd, ADD_ELEM_STATUS_DPC, add_elem_rsp, mlen, op,
+ res = do_rec_diag(ptvp, ADD_ELEM_STATUS_DPC, add_elem_rsp, mlen, op,
&add_elem_rsp_len);
if (0 == res) {
if (add_elem_rsp_len < 8) {
@@ -4904,7 +4913,7 @@ join_work(int sg_fd, struct opts_t * op, bool display)
mlen = threshold_rsp_sz;
if (mlen > op->maxlen)
mlen = op->maxlen;
- res = do_rec_diag(sg_fd, THRESHOLD_DPC, threshold_rsp, mlen, op,
+ res = do_rec_diag(ptvp, THRESHOLD_DPC, threshold_rsp, mlen, op,
&threshold_rsp_len);
if (0 == res) {
if (threshold_rsp_len < 8) {
@@ -5013,7 +5022,7 @@ is_acronym_in_additional(const struct tuple_acronym_val * tavp)
* Do clear/get/set (cgs) on Enclosure Control/Status page. Return 0 for ok
* -2 for acronym not found, else -1 . */
static int
-cgs_enc_ctl_stat(int sg_fd, struct join_row_t * jrp,
+cgs_enc_ctl_stat(struct sg_pt_base * ptvp, struct join_row_t * jrp,
const struct tuple_acronym_val * tavp,
const struct opts_t * op, bool last)
{
@@ -5074,7 +5083,7 @@ cgs_enc_ctl_stat(int sg_fd, struct join_row_t * jrp,
enc_stat_rsp[1] = op->byte1;
len = sg_get_unaligned_be16(enc_stat_rsp + 2) + 4;
if (last) {
- ret = do_senddiag(sg_fd, enc_stat_rsp, len, ! op->quiet,
+ ret = do_senddiag(ptvp, enc_stat_rsp, len, ! op->quiet,
op->verbose);
if (ret) {
pr2serr("couldn't send Enclosure Control page\n");
@@ -5089,7 +5098,7 @@ cgs_enc_ctl_stat(int sg_fd, struct join_row_t * jrp,
* Do clear/get/set (cgs) on Threshold In/Out page. Return 0 for ok,
* -2 for acronym not found, else -1 . */
static int
-cgs_threshold(int sg_fd, const struct join_row_t * jrp,
+cgs_threshold(struct sg_pt_base * ptvp, const struct join_row_t * jrp,
const struct tuple_acronym_val * tavp,
const struct opts_t * op, bool last)
{
@@ -5132,7 +5141,7 @@ cgs_threshold(int sg_fd, const struct join_row_t * jrp,
threshold_rsp[1] = op->byte1;
len = sg_get_unaligned_be16(threshold_rsp + 2) + 4;
if (last) {
- ret = do_senddiag(sg_fd, threshold_rsp, len, ! op->quiet,
+ ret = do_senddiag(ptvp, threshold_rsp, len, ! op->quiet,
op->verbose);
if (ret) {
pr2serr("couldn't send Threshold Out page\n");
@@ -5194,7 +5203,7 @@ cgs_additional_el(const struct join_row_t * jrp,
/* Do --clear, --get or --set .
* Returns 0 for success, any other return value is an error. */
static int
-ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
+ses_cgs(struct sg_pt_base * ptvp, const struct tuple_acronym_val * tavp,
struct opts_t * op, bool last)
{
int ret, k, j, desc_len, dn_len;
@@ -5203,7 +5212,7 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
const uint8_t * ed_bp;
char b[64];
- if ((sg_fd < 0) && (GET_OPT != tavp->cgs_sel)) {
+ if ((NULL == ptvp) && (GET_OPT != tavp->cgs_sel)) {
pr2serr("%s: --clear= and --set= only supported when DEVICE is "
"given\n", __func__);
return SG_LIB_SYNTAX_ERROR;
@@ -5240,7 +5249,7 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
return -1;
}
if (false == join_done) {
- ret = join_work(sg_fd, op, false);
+ ret = join_work(ptvp, op, false);
if (ret)
return ret;
}
@@ -5278,9 +5287,9 @@ ses_cgs(int sg_fd, const struct tuple_acronym_val * tavp,
continue;
}
if (ENC_CONTROL_DPC == op->page_code)
- ret = cgs_enc_ctl_stat(sg_fd, jrp, tavp, op, last);
+ ret = cgs_enc_ctl_stat(ptvp, jrp, tavp, op, last);
else if (THRESHOLD_DPC == op->page_code)
- ret = cgs_threshold(sg_fd, jrp, tavp, op, last);
+ ret = cgs_threshold(ptvp, jrp, tavp, op, last);
else if (ADD_ELEM_STATUS_DPC == op->page_code)
ret = cgs_additional_el(jrp, tavp, op);
else {
@@ -5322,20 +5331,20 @@ inconsistent:
* the generation code. Returns 0 for success, any other return value is
* an error. */
static int
-ses_set_nickname(int sg_fd, struct opts_t * op)
+ses_set_nickname(struct sg_pt_base * ptvp, struct opts_t * op)
{
int res, len;
int resp_len = 0;
uint8_t b[64];
const int control_plen = 0x24;
- if (sg_fd < 0) {
+ if (NULL == ptvp) {
pr2serr("%s: ignored when no device name\n", __func__);
return 0;
}
memset(b, 0, sizeof(b));
/* Only after the generation code, offset 4 for 4 bytes */
- res = do_rec_diag(sg_fd, SUBENC_NICKNAME_DPC, b, 8, op, &resp_len);
+ res = do_rec_diag(ptvp, SUBENC_NICKNAME_DPC, b, 8, op, &resp_len);
if (res) {
pr2serr("%s: Subenclosure nickname status page, res=%d\n", __func__,
res);
@@ -5360,7 +5369,7 @@ ses_set_nickname(int sg_fd, struct opts_t * op)
if (len > 32)
len = 32;
memcpy(b + 8, op->nickname_str, len);
- return do_senddiag(sg_fd, b, control_plen + 4, ! op->quiet,
+ return do_senddiag(ptvp, b, control_plen + 4, ! op->quiet,
op->verbose);
}
@@ -5466,7 +5475,7 @@ int
main(int argc, char * argv[])
{
bool have_cgs = false;
- int k, d_len, res, vb;
+ int k, d_len, res, resid, vb;
int sg_fd = -1;
int pd_type = 0;
int ret = 0;
@@ -5479,10 +5488,10 @@ main(int argc, char * argv[])
uint8_t * free_elem_desc_rsp = NULL;
uint8_t * free_add_elem_rsp = NULL;
uint8_t * free_threshold_rsp = NULL;
+ struct sg_pt_base * ptvp = NULL;
struct tuple_acronym_val tav_arr[CGS_CL_ARR_MAX_SZ];
- struct sg_simple_inquiry_resp inq_resp;
char buff[128];
- char b[80];
+ char b[128];
op = &opts;
memset(op, 0, sizeof(*op));
@@ -5610,46 +5619,131 @@ main(int argc, char * argv[])
if (sg_fd < 0) {
pr2serr("open error: %s: %s\n", op->dev_name,
safe_strerror(-sg_fd));
- ret = SG_LIB_FILE_ERROR;
+ ret = sg_convert_errno(-sg_fd);
+ goto err_out;
+ }
+ ptvp = construct_scsi_pt_obj_with_fd(sg_fd, vb);
+ if (NULL == ptvp) {
+ pr2serr("construct pt_base failed, probably out of memory\n");
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
if (! (op->do_raw || have_cgs || (op->do_hex > 2))) {
- if ((ret = sg_simple_inquiry(sg_fd, &inq_resp, ! op->quiet, vb))) {
+ if ((ret = sg_ll_inquiry_pt(ptvp, false, 0, enc_stat_rsp, 36,
+ 0, &resid, ! op->quiet, vb))) {
pr2serr("%s doesn't respond to a SCSI INQUIRY\n",
op->dev_name);
goto err_out;
} else {
- printf(" %.8s %.16s %.4s\n", inq_resp.vendor,
- inq_resp.product, inq_resp.revision);
- pd_type = inq_resp.peripheral_type;
+ if (resid > 0)
+ pr2serr("Short INQUIRY response, not looking good\n");
+ printf(" %.8s %.16s %.4s\n", enc_stat_rsp + 8,
+ enc_stat_rsp + 16, enc_stat_rsp + 32);
+ pd_type = 0x1f & enc_stat_rsp[0];
cp = sg_get_pdt_str(pd_type, sizeof(buff), buff);
if (0xd == pd_type) {
if (vb)
printf(" enclosure services device\n");
- } else if (0x40 & inq_resp.byte_6)
+ } else if (0x40 & enc_stat_rsp[6])
printf(" %s device has EncServ bit set\n", cp);
- else
- printf(" %s device (not an enclosure)\n", cp);
+ else {
+ if (0 != memcmp("NVMe", enc_stat_rsp + 8, 4))
+ printf(" %s device (not an enclosure)\n", cp);
+ }
}
+ clear_scsi_pt_obj(ptvp);
+ /* finished using enc_stat_rsp so clear back to zero */
+ memset(enc_stat_rsp, 0, enc_stat_rsp_sz);
}
} else if (op->do_control) {
pr2serr("Cannot do SCSI Send diagnostic command without a DEVICE\n");
return SG_LIB_SYNTAX_ERROR;
}
+#if (HAVE_NVME && (! IGNORE_NVME))
+ if (ptvp && pt_device_is_nvme(ptvp) && (enc_stat_rsp_sz > 4095)) {
+ /* Fetch VPD 0xde (vendor specific: sg3_utils) for Identify ctl */
+ ret = sg_ll_inquiry_pt(ptvp, true, 0xde, enc_stat_rsp, 4096, 0,
+ &resid, ! op->quiet, vb);
+ if (ret) {
+ if (vb)
+ pr2serr("Fetch VPD page 0xde (NVMe Identify ctl) failed, "
+ "continue\n");
+ } else if (resid > 0) {
+ if (vb)
+ pr2serr("VPD page 0xde (NVMe Identify ctl) less than 4096 "
+ "bytes, continue\n");
+ } else {
+ uint8_t nvmsr;
+ uint16_t oacs;
+
+ nvmsr = enc_stat_rsp[253];
+ oacs = sg_get_unaligned_le16(enc_stat_rsp + 256);
+ if (vb > 3)
+ pr2serr("NVMe Identify ctl response: nvmsr=%u, oacs=0x%x\n",
+ nvmsr, oacs);
+ if (! ((0x2 & nvmsr) && (0x40 & oacs))) {
+ pr2serr(">>> Warning: A NVMe enclosure needs both the "
+ "enclosure bit and support for\n");
+ pr2serr(">>> MI Send+Receive commands bit set; current "
+ "state: %s, %s\n", (0x2 & nvmsr) ? "set" : "clear",
+ (0x40 & oacs) ? "set" : "clear");
+ }
+ }
+ clear_scsi_pt_obj(ptvp);
+ memset(enc_stat_rsp, 0, 4096);
+ }
+#endif
+
+ if (ptvp) {
+ ret = sg_ll_request_sense_pt(ptvp, false, enc_stat_rsp,
+ REQUEST_SENSE_RESP_SZ, ! op->quiet, vb);
+ if (0 == ret) {
+ int sense_len = REQUEST_SENSE_RESP_SZ - get_scsi_pt_resid(ptvp);
+ struct sg_scsi_sense_hdr ssh;
+
+ if ((sense_len > 7) && sg_scsi_normalize_sense(enc_stat_rsp,
+ sense_len, &ssh)) {
+ const char * aa_str = sg_get_asc_ascq_str(ssh.asc, ssh.ascq,
+ sizeof(b), b);
+
+ /* Ignore the possibility that multiple UAs queued up */
+ if (SPC_SK_UNIT_ATTENTION == ssh.sense_key)
+ pr2serr("Unit attention detected: %s\n ... continue\n",
+ aa_str);
+ else {
+ if (vb) {
+ pr2serr("Request Sense near startup detected "
+ "something:\n");
+ pr2serr(" Sense key: %s, additional: %s\n ... "
+ "continue\n",
+ sg_get_sense_key_str(ssh.sense_key,
+ sizeof(buff), buff), aa_str);
+ }
+ }
+ }
+ } else {
+ if (vb)
+ pr2serr("Request sense failed (res=%d), most likely "
+ " problems ahead\n", ret);
+ }
+ clear_scsi_pt_obj(ptvp);
+ memset(enc_stat_rsp, 0, REQUEST_SENSE_RESP_SZ);
+ }
+
if (op->nickname_str)
- ret = ses_set_nickname(sg_fd, op);
+ ret = ses_set_nickname(ptvp, op);
else if (have_cgs) {
for (k = 0, tavp = tav_arr, cgs_clp = op->cgs_cl_arr;
k < op->num_cgs; ++k, ++tavp, ++cgs_clp) {
- ret = ses_cgs(sg_fd, tavp, op, cgs_clp->last_cs);
+ ret = ses_cgs(ptvp, tavp, op, cgs_clp->last_cs);
if (ret)
break;
}
} else if (op->do_join)
- ret = join_work(sg_fd, op, true);
+ ret = join_work(ptvp, op, true);
else if (op->do_status)
- ret = process_status_page_s(sg_fd, op);
+ ret = process_status_page_s(ptvp, op);
else { /* control page requested */
op->data_arr[0] = op->page_code;
op->data_arr[1] = op->byte1;
@@ -5659,7 +5753,7 @@ main(int argc, char * argv[])
case ENC_CONTROL_DPC: /* Enclosure Control diagnostic page [0x2] */
printf("Sending Enclosure Control [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Enclosure Control page\n");
goto err_out;
@@ -5668,7 +5762,7 @@ main(int argc, char * argv[])
case STRING_DPC: /* String Out diagnostic page [0x4] */
printf("Sending String Out [0x%x] page, with page length=%d "
"bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send String Out page\n");
goto err_out;
@@ -5677,7 +5771,7 @@ main(int argc, char * argv[])
case THRESHOLD_DPC: /* Threshold Out diagnostic page [0x5] */
printf("Sending Threshold Out [0x%x] page, with page length=%d "
"bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Threshold Out page\n");
goto err_out;
@@ -5686,7 +5780,7 @@ main(int argc, char * argv[])
case ARRAY_CONTROL_DPC: /* Array control diagnostic page [0x6] */
printf("Sending Array Control [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Array Control page\n");
goto err_out;
@@ -5695,7 +5789,7 @@ main(int argc, char * argv[])
case SUBENC_STRING_DPC: /* Subenclosure String Out page [0xc] */
printf("Sending Subenclosure String Out [0x%x] page, with page "
"length=%d bytes\n", op->page_code, op->arr_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Subenclosure String Out page\n");
goto err_out;
@@ -5706,7 +5800,7 @@ main(int argc, char * argv[])
"page length=%d bytes\n", op->page_code, d_len);
printf(" Perhaps it would be better to use the sg_ses_microcode "
"utility\n");
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Download Microcode Control page\n");
goto err_out;
@@ -5715,7 +5809,7 @@ main(int argc, char * argv[])
case SUBENC_NICKNAME_DPC: /* Subenclosure Nickname Control [0xf] */
printf("Sending Subenclosure Nickname Control [0x%x] page, with "
"page length=%d bytes\n", op->page_code, d_len);
- ret = do_senddiag(sg_fd, op->data_arr, d_len, ! op->quiet, vb);
+ ret = do_senddiag(ptvp, op->data_arr, d_len, ! op->quiet, vb);
if (ret) {
pr2serr("couldn't send Subenclosure Nickname Control page\n");
goto err_out;
@@ -5754,6 +5848,8 @@ err_out:
ret = SG_LIB_FILE_ERROR;
}
early_out:
+ if (ptvp)
+ destruct_scsi_pt_obj(ptvp);
if ((0 == vb) && (! op->quiet)) {
if (! sg_if_can2stderr("sg_ses failed: ", ret))
pr2serr("Some error occurred, try again with '-v' or '-vv' for "
diff --git a/src/sg_stream_ctl.c b/src/sg_stream_ctl.c
index e278e4a2..f2372ed7 100644
--- a/src/sg_stream_ctl.c
+++ b/src/sg_stream_ctl.c
@@ -33,7 +33,7 @@
* to the given SCSI device. Based on sbc4r15.pdf .
*/
-static const char * version_str = "1.02 20180219";
+static const char * version_str = "1.03 20180427";
#define STREAM_CONTROL_SA 0x14
#define GET_STREAM_STATUS_SA 0x16
@@ -166,7 +166,10 @@ sg_ll_get_stream_status(int sg_fd, uint16_t s_str_id, uint8_t * resp,
}
/* Invokes a SCSI STREAM CONTROL command (SBC-4). Return of 0 -> success,
- * various SG_LIB_CAT_* positive values or -1 -> other errors */
+ * various SG_LIB_CAT_* positive values or -1 -> other errors.
+ * N.B. The is a device modifying command that is SERVICE ACTION IN(16)
+ * command since it has data-in buffer that for open returns the
+ * ASSIGNED_STR_ID field . */
static int
sg_ll_stream_control(int sg_fd, uint32_t str_ctl, uint16_t str_id,
uint8_t * resp, uint32_t alloc_len, int * residp,
@@ -202,12 +205,9 @@ sg_ll_stream_control(int sg_fd, uint32_t str_ctl, uint16_t str_id,
res = do_scsi_pt(ptvp, -1, DEF_PT_TIMEOUT, verbose);
ret = sg_cmds_process_resp(ptvp, cmd_name, res, alloc_len, sense_b,
noisy, verbose, &sense_cat);
- if (-1 == ret) {
- int os_err = get_scsi_pt_os_err(ptvp);
-
- if ((os_err > 0) && (os_err < 47))
- ret = SG_LIB_OS_BASE_ERR + os_err;
- } else if (-2 == ret) {
+ if (-1 == ret)
+ ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
+ else if (-2 == ret) {
switch (sense_cat) {
case SG_LIB_CAT_RECOVERED:
case SG_LIB_CAT_NO_SENSE:
@@ -378,7 +378,7 @@ main(int argc, char * argv[])
arr = sg_memalign(pg_sz, pg_sz, &free_arr, verbose > 3);
if (NULL == arr) {
pr2serr("Unable to allocate space for response\n");
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return sg_convert_errno(ENOMEM);
}
resid = 0;
diff --git a/src/sg_test_rwbuf.c b/src/sg_test_rwbuf.c
index 7bd5d962..c680ae4b 100644
--- a/src/sg_test_rwbuf.c
+++ b/src/sg_test_rwbuf.c
@@ -29,6 +29,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <errno.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
@@ -44,7 +45,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.15 20180219";
+static const char * version_str = "1.16 20180428";
#define BPI (signed)(sizeof(int))
@@ -64,6 +65,7 @@ static int base = 0x12345678;
static int buf_capacity = 0;
static int buf_granul = 255;
static uint8_t *cmpbuf = NULL;
+static uint8_t *free_cmpbuf = NULL;
/* Options */
@@ -229,7 +231,9 @@ int read_buffer (int sg_fd, unsigned ssize)
int res, k;
uint8_t rb_cdb[] = {READ_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int bufSize = ssize + addread;
- uint8_t * rbBuff = (uint8_t *)malloc(bufSize);
+ uint8_t * free_rbBuff = NULL;
+ uint8_t * rbBuff = (uint8_t *)sg_memalign(bufSize, 0, &free_rbBuff,
+ false);
uint8_t sense_buffer[32];
struct sg_io_hdr io_hdr;
@@ -280,7 +284,8 @@ int read_buffer (int sg_fd, unsigned ssize)
}
res = do_checksum((int*)rbBuff, ssize, false);
- free(rbBuff);
+ if (free_rbBuff)
+ free(free_rbBuff);
return res;
}
@@ -288,7 +293,9 @@ int write_buffer (int sg_fd, unsigned ssize)
{
uint8_t wb_cdb[] = {WRITE_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int bufSize = ssize + addwrite;
- uint8_t * wbBuff = (uint8_t *)malloc(bufSize);
+ uint8_t * free_wbBuff = NULL;
+ uint8_t * wbBuff = (uint8_t *)sg_memalign(bufSize, 0, &free_wbBuff,
+ false);
uint8_t sense_buffer[32];
struct sg_io_hdr io_hdr;
int k, res;
@@ -340,7 +347,8 @@ int write_buffer (int sg_fd, unsigned ssize)
free(wbBuff);
return res;
}
- free(wbBuff);
+ if (free_wbBuff)
+ free(free_wbBuff);
return res;
}
@@ -511,7 +519,7 @@ int main (int argc, char * argv[])
goto err_out;
}
- cmpbuf = (uint8_t *)malloc(size);
+ cmpbuf = (uint8_t *)sg_memalign(size, 0, &free_cmpbuf, false);
for (k = 0; k < times; ++k) {
ret = write_buffer (sg_fd, size);
if (ret) {
@@ -526,8 +534,8 @@ int main (int argc, char * argv[])
}
err_out:
- if (cmpbuf)
- free(cmpbuf);
+ if (free_cmpbuf)
+ free(free_cmpbuf);
res = close(sg_fd);
if (res < 0) {
perror(ME "close error");
diff --git a/src/sg_timestamp.c b/src/sg_timestamp.c
index 17105976..976bca56 100644
--- a/src/sg_timestamp.c
+++ b/src/sg_timestamp.c
@@ -35,7 +35,7 @@
* to the given SCSI device. Based on spc5r07.pdf .
*/
-static const char * version_str = "1.07 20180219";
+static const char * version_str = "1.08 20180502";
#define REP_TIMESTAMP_CMDLEN 12
#define SET_TIMESTAMP_CMDLEN 12
@@ -53,8 +53,12 @@ uint8_t d_buff[256];
static struct option long_options[] = {
+ {"elapsed", no_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
{"milliseconds", required_argument, 0, 'm'},
+ {"no_timestamp", no_argument, 0, 'N'},
+ {"no-timestamp", no_argument, 0, 'N'},
{"origin", no_argument, 0, 'o'},
{"raw", no_argument, 0, 'r'},
{"readonly", no_argument, 0, 'R'},
@@ -79,20 +83,38 @@ static const char * ts_origin_arr[] = {
static void
-usage()
+usage(int num)
{
+ if (num > 1)
+ goto page2;
+
pr2serr("Usage: "
- "sg_timestamp [--help] [--milliseconds=MS] [--origin] [--raw]\n"
- " [--readonly] [--seconds=SEC] [--srep] "
- "[--verbose]\n"
- " [--version] DEVICE\n");
+ "sg_timestamp [--elapsed] [--help] [--hex] [--milliseconds=MS]\n"
+ " [--no-timestamp] [--origin] [--raw] "
+ "[--readonly]\n"
+ " [--seconds=SEC] [--srep] [--verbose] "
+ "[--version]\n"
+ " DEVICE\n"
+ );
pr2serr(" where:\n"
- " --help|-h print out usage message\n"
+ " --elapsed|-e show time as '<n> days hh.mm.ss.xxx' "
+ "where\n"
+ " '.xxx' is the remainder milliseconds. "
+ "Don't show\n"
+ " '<n> days' if <n> is 0 (unless '-e' "
+ "given twice)\n"
+ " --help|-h print out usage message, use twice for "
+ "examples\n"
+ " --hex|-H output response in ASCII hexadecimal\n"
" --milliseconds=MS|-m MS set timestamp to MS "
"milliseconds since\n"
" 1970-01-01 00:00:00 UTC\n"
+ " --no-timestamp|-N suppress output of timestamp\n"
" --origin|-o show Report timestamp origin "
"(def: don't)\n"
+ " used twice outputs value of field\n"
+ " 0: power up or hard reset; 2: SET "
+ "TIMESTAMP\n"
" --raw|-r output Report timestamp response to "
"stdout in\n"
" binary\n"
@@ -106,17 +128,62 @@ usage()
" milliseconds)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
- "Performs a SCSI REPORT TIMESTAMP or SET TIMESTAMP command. "
+ );
+ pr2serr("Performs a SCSI REPORT TIMESTAMP or SET TIMESTAMP command. "
"The timestamp\nis SET if either the --milliseconds=MS or "
"--seconds=SEC option is given,\notherwise the existing "
- "timestamp is reported. The DEVICE stores the\ntimestamp as "
- "the number of milliseconds since power up (or reset) or\n"
- "since 1970-01-01 00:00:00 UTC which also happens to be the "
- "time 'epoch'\nof Unix machines. The 'date +%%s' command in "
+ "timestamp is reported in milliseconds. The\nDEVICE stores "
+ "the timestamp as the number of milliseconds since power up\n"
+ "(or reset) or since 1970-01-01 00:00:00 UTC which also "
+ "happens to\nbe the time 'epoch'of Unix machines.\n\n"
+ "Use '-hh' (the '-h' option twice) for examples.\n"
+#if 0
+ "The 'date +%%s' command in "
"Unix returns the number of\nseconds since the epoch. To "
"convert a reported timestamp (in seconds since\nthe epoch) "
"to a more readable form use "
- "'date --date='@<secs_since_epoch>' .\n");
+ "'date --date=@<secs_since_epoch>' .\n"
+#endif
+ );
+ return;
+page2:
+ pr2serr("sg_timestamp examples:\n"
+ "It is possible that the target device containing a SCSI "
+ "Logical Unit (LU)\nhas a battery (or supercapacitor) to "
+ "keep its RTC (real time clock)\nticking during a power "
+ "outage. More likely it doesn't and its RTC is\ncleared to "
+ "zero after a power cycle or hard reset.\n\n"
+ "Either way REPORT TIMESTAMP returns a 48 bit counter value "
+ "whose unit is\na millisecond. A heuristic to determine if a "
+ "date or elapsed time is\nbeing returned is to choose a date "
+ "like 1 January 2000 which is 30 years\nafter the Unix epoch "
+ "(946,684,800,000 milliseconds) and values less than\nthat are "
+ "elapsed times and greater are timestamps. Observing the "
+ "TIMESTAMP\nORIGIN field of REPORT TIMESTAMP is a better "
+ "method:\n\n"
+ );
+ pr2serr(" $ sg_timestamp -o -N /dev/sg1\n"
+ "Device clock initialized to zero at power on or by hard "
+ "reset\n"
+ " $ sg_timestamp -oo -N /dev/sg1\n"
+ "0\n\n"
+ " $ sg_timestamp /dev/sg1\n"
+ "3984499\n"
+ " $ sg_timestamp --elapsed /dev/sg1\n"
+ "01:06:28.802\n\n"
+ "The last output indicates an elapsed time of 1 hour, 6 minutes "
+ "and 28.802\nseconds. Next set the clock to the current time:\n\n"
+ " $ sg_timestamp --seconds=`date +%%s` /dev/sg1\n\n"
+ " $ sg_timestamp -o -N /dev/sg1\n"
+ "Device clock initialized by SET TIMESTAMP command\n\n"
+ "Now show that as an elapsed time:\n\n"
+ " $ sg_timestamp -e /dev/sg1\n"
+ "17652 days 20:53:22.545\n\n"
+ "That is over 48 years worth of days. Lets try again as a "
+ "data-time\nstamp in UTC:\n\n"
+ " $ date -u -R --date=@`sg_timestamp -S /dev/sg1`\n"
+ "Tue, 01 May 2018 20:56:38 +0000\n"
+ );
}
/* Invokes a SCSI REPORT TIMESTAMP command. Return of 0 -> success,
@@ -244,12 +311,16 @@ dStrRaw(const uint8_t * str, int len)
int
main(int argc, char * argv[])
{
- bool do_origin = false;
bool do_srep = false;
bool do_raw = false;
+ bool no_timestamp = false;
bool readonly = false;
bool secs_given = false;
int sg_fd, res, c;
+ int elapsed = 0;
+ int do_origin = 0;
+ int do_help = 0;
+ int do_hex = 0;
int do_set = 0;
int ret = 0;
int verbose = 0;
@@ -262,16 +333,22 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hm:orRs:SvV", long_options,
+ c = getopt_long(argc, argv, "ehHm:NorRs:SvV", long_options,
&option_index);
if (c == -1)
break;
switch (c) {
+ case 'e':
+ ++elapsed;
+ break;
case 'h':
case '?':
- usage();
- return 0;
+ ++do_help;
+ break;
+ case 'H':
+ ++do_hex;
+ break;
case 'm':
ll = sg_get_llnum(optarg);
if (-1 == ll) {
@@ -281,8 +358,11 @@ main(int argc, char * argv[])
msecs = (uint64_t)ll;
++do_set;
break;
+ case 'N':
+ no_timestamp = true;
+ break;
case 'o':
- do_origin = true;
+ ++do_origin;
break;
case 'r':
do_raw = true;
@@ -311,7 +391,7 @@ main(int argc, char * argv[])
return 0;
default:
pr2serr("unrecognised option code 0x%x ??\n", c);
- usage();
+ usage(1);
return SG_LIB_SYNTAX_ERROR;
}
}
@@ -323,21 +403,25 @@ main(int argc, char * argv[])
if (optind < argc) {
for (; optind < argc; ++optind)
pr2serr("Unexpected extra argument: %s\n", argv[optind]);
- usage();
+ usage(1);
return SG_LIB_SYNTAX_ERROR;
}
}
+ if (do_help) {
+ usage(do_help);
+ return 0;
+ }
if (do_set > 1) {
pr2serr("either --milliseconds=MS or --seconds=SEC may be given, "
"not both\n");
- usage();
+ usage(1);
return SG_LIB_SYNTAX_ERROR;
}
if (NULL == device_name) {
- pr2serr("missing device name!\n");
- usage();
+ pr2serr("missing device name!\n\n");
+ usage(1);
return SG_LIB_SYNTAX_ERROR;
}
@@ -359,17 +443,42 @@ main(int argc, char * argv[])
if (0 == res) {
if (do_raw)
dStrRaw(d_buff, 12);
+ else if (do_hex)
+ hex2stderr(d_buff, 12, 1);
else {
int len = sg_get_unaligned_be16(d_buff + 0);
+
if (len < 8)
pr2serr("timestamp parameter data length too short, "
"expect >= 10, got %d\n", len + 2);
else {
- if (do_origin)
- printf("Device clock %s\n",
- ts_origin_arr[0x7 & d_buff[2]]);
- msecs = sg_get_unaligned_be48(d_buff + 4);
- printf("%" PRIu64 "\n", do_srep ? (msecs / 1000) : msecs);
+ if (do_origin) {
+ if (1 == do_origin)
+ printf("Device clock %s\n",
+ ts_origin_arr[0x7 & d_buff[2]]);
+ else if (2 == do_origin)
+ printf("%d\n", 0x7 & d_buff[2]);
+ else
+ printf("TIMESTAMP_ORIGIN=%d\n", 0x7 & d_buff[2]);
+ }
+ if (! no_timestamp) {
+ msecs = sg_get_unaligned_be48(d_buff + 4);
+ if (elapsed) {
+ int days = (int)(msecs / 1000 / 60 / 60 / 24);
+ int hours = (int)(msecs / 1000 / 60 / 60 % 24);
+ int mins = (int)(msecs / 1000 / 60 % 60);
+ int secs_in_min =(int)( msecs / 1000 % 60);
+ int rem_msecs = (int)(msecs % 1000);
+
+ if ((elapsed > 1) || (days > 0))
+ printf("%d day%s ", days,
+ ((1 == days) ? "" : "s"));
+ printf("%02d:%02d:%02d.%03d\n", hours, mins,
+ secs_in_min, rem_msecs);
+ } else
+ printf("%" PRIu64 "\n", do_srep ?
+ (msecs / 1000) : msecs);
+ }
}
}
}
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 1aad48df..2e2d7081 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -856,6 +856,9 @@ decode_mode_policy_vpd(uint8_t * buff, int len, int do_hex)
printf(", subpage code: 0x%x\n", bp[1]);
else
printf("\n");
+ if ((0 == k) && (0x3f == (0x3f & bp[0])) && (0xff == bp[1]))
+ printf(" therefore the policy applies to all modes pages "
+ "and subpages\n");
printf(" MLUS=%d, Policy: %s\n", !!(bp[2] & 0x80),
mode_page_policy_arr[bp[2] & 0x3]);
}
diff --git a/src/sg_write_long.c b/src/sg_write_long.c
index 8b01c1a7..b6f9e694 100644
--- a/src/sg_write_long.c
+++ b/src/sg_write_long.c
@@ -35,20 +35,21 @@
#include "sg_cmds_extra.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.16 20180219";
+static const char * version_str = "1.17 20180502";
-#define MAX_XFER_LEN 10000
+#define MAX_XFER_LEN (15 * 1024)
/* #define SG_DEBUG */
#define ME "sg_write_long: "
-#define EBUFF_SZ 256
+#define EBUFF_SZ 512
static struct option long_options[] = {
{"16", no_argument, 0, 'S'},
{"cor_dis", no_argument, 0, 'c'},
+ {"cor-dis", no_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{"in", required_argument, 0, 'i'},
{"lba", required_argument, 0, 'l'},
@@ -56,7 +57,9 @@ static struct option long_options[] = {
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"wr_uncor", no_argument, 0, 'w'},
+ {"wr-uncor", no_argument, 0, 'w'},
{"xfer_len", required_argument, 0, 'x'},
+ {"xfer-len", required_argument, 0, 'x'},
{0, 0, 0, 0},
};
@@ -111,6 +114,7 @@ main(int argc, char * argv[])
const char * device_name = NULL;
uint8_t * writeLongBuff = NULL;
void * rawp = NULL;
+ uint8_t * free_rawp = NULL;
const char * ten_or;
char file_name[256];
char b[80];
@@ -209,9 +213,9 @@ main(int argc, char * argv[])
pr2serr(">>> warning: when '--wr_uncor' given '-in=' is "
"ignored\n");
} else {
- if (NULL == (rawp = malloc(MAX_XFER_LEN))) {
+ if (NULL == (rawp = sg_memalign(MAX_XFER_LEN, 0, &free_rawp, false))) {
pr2serr(ME "out of memory\n");
- ret = SG_LIB_FILE_ERROR;
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
writeLongBuff = (uint8_t *)rawp;
@@ -279,8 +283,8 @@ main(int argc, char * argv[])
}
err_out:
- if (rawp)
- free(rawp);
+ if (free_rawp)
+ free(free_rawp);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_write_same.c b/src/sg_write_same.c
index d2176395..2d6d241a 100644
--- a/src/sg_write_same.c
+++ b/src/sg_write_same.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.21 20180219";
+static const char * version_str = "1.22 20180425";
#define ME "sg_write_same: "
@@ -317,6 +317,7 @@ main(int argc, char * argv[])
const char * device_name = NULL;
struct opts_t * op;
uint8_t * wBuff = NULL;
+ uint8_t * free_wBuff = NULL;
char ebuff[EBUFF_SZ];
char b[80];
uint8_t resp_buff[RCAP16_RESP_LEN];
@@ -550,11 +551,11 @@ main(int argc, char * argv[])
ret = SG_LIB_SYNTAX_ERROR;
goto err_out;
}
- wBuff = (uint8_t*)calloc(op->xfer_len, 1);
+ wBuff = (uint8_t *)sg_memalign(op->xfer_len, 0, &free_wBuff, vb > 3);
if (NULL == wBuff) {
- pr2serr("unable to allocate %d bytes of memory with calloc()\n",
- op->xfer_len);
- ret = SG_LIB_SYNTAX_ERROR;
+ pr2serr("unable to allocate %d bytes of memory with "
+ "sg_memalign()\n", op->xfer_len);
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
if (op->ifilename[0]) {
@@ -610,8 +611,8 @@ main(int argc, char * argv[])
}
err_out:
- if (wBuff)
- free(wBuff);
+ if (free_wBuff)
+ free(free_wBuff);
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
pr2serr("close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_write_verify.c b/src/sg_write_verify.c
index 00adb6e0..aae62257 100644
--- a/src/sg_write_verify.c
+++ b/src/sg_write_verify.c
@@ -288,7 +288,8 @@ main(int argc, char * argv[])
uint64_t llba = 0;
int64_t ll;
uint8_t * wvb = NULL;
- void * wrkBuff = NULL;
+ uint8_t * wrkBuff = NULL;
+ uint8_t * free_wrkBuff = NULL;
const char * device_name = NULL;
const char * ifnp;
char cmd_name[32];
@@ -497,9 +498,10 @@ main(int argc, char * argv[])
} else if (verbose)
pr2serr("Using file size of %d bytes\n", ilen);
}
- if (NULL == (wrkBuff = malloc(ilen))) {
+ if (NULL == (wrkBuff = (uint8_t *)sg_memalign(ilen, 0,
+ &free_wrkBuff, verbose > 3))) {
pr2serr(ME "out of memory\n");
- ret = SG_LIB_CAT_OTHER;
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
wvb = (uint8_t *)wrkBuff;
@@ -523,9 +525,10 @@ main(int argc, char * argv[])
num_lb, 512, 512 * num_lb);
ilen = 512 * num_lb;
}
- if (NULL == (wrkBuff = malloc(ilen))) {
+ if (NULL == (wrkBuff = (uint8_t *)sg_memalign(ilen, 0,
+ &free_wrkBuff, verbose > 3))) {
pr2serr(ME "out of memory\n");
- ret = SG_LIB_CAT_OTHER;
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
wvb = (uint8_t *)wrkBuff;
@@ -576,8 +579,8 @@ err_out:
if (repeat)
pr2serr("%d [0x%x] logical blocks written, in total\n", tnum_lb_wr,
tnum_lb_wr);
- if (wrkBuff)
- free(wrkBuff);
+ if (free_wrkBuff)
+ free(free_wrkBuff);
if ((ifd >= 0) && (STDIN_FILENO != ifd))
close(ifd);
res = sg_cmds_close_device(sg_fd);
diff --git a/src/sg_write_x.c b/src/sg_write_x.c
index 71f4d556..3311ad0d 100644
--- a/src/sg_write_x.c
+++ b/src/sg_write_x.c
@@ -36,16 +36,16 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.15 20180329";
+static const char * version_str = "1.16 20180425";
/* Protection Information refers to 8 bytes of extra information usually
* associated with each logical block and is often abbreviated to PI while
* its fields: reference-tag (4 bytes), application-tag (2 bytes) and
* tag-mask (2 bytes) are often abbreviated to RT, AT and TM respectively.
* And the LBA Range Descriptor associated with the WRITE SCATTERED command
- * is abbreviated to RD. A degenerate RD is one where both the LBA and length
- * components are zero; they are not illegal according to T10 but are a
- * little tricky to handle when scanning and little extra information
+ * is abbreviated to RD. A degenerate RD is one where length components,
+ ( and perhaps the LBA, are zero; it is not illegal according to T10 but are
+ * a little tricky to handle when scanning and little extra information
* is provided. */
#define ORWRITE16_OP 0x8b
@@ -1841,7 +1841,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == up) {
pr2serr("unable to allocate aligned memory for "
"scatterlist+data\n");
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return sg_convert_errno(ENOMEM);
}
ret = bin_read(infd, up, ((if_len < d) ? if_len : d), "IF c1");
if (ret)
@@ -1908,7 +1908,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == u2p) {
pr2serr("unable to allocate memory for final "
"scatterlist+data\n");
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto finii;
}
memcpy(u2p, up, d);
@@ -1943,7 +1943,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == up) {
pr2serr("unable to allocate aligned memory for "
"scatterlist+data\n");
- return SG_LIB_OS_BASE_ERR + ENOMEM;
+ return sg_convert_errno(ENOMEM);
}
num_lbard = 0;
sum_num = 0;
@@ -2032,7 +2032,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == up) {
pr2serr("unable to allocate aligned memory for "
"scatterlist+data\n");
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto finii;
}
ret = bin_read(sfr_fd, up, sf_len, "SF");
@@ -2054,7 +2054,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == u2p) {
pr2serr("unable to allocate memory for final "
"scatterlist+data\n");
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto finii;
}
memcpy(u2p, up, dd);
@@ -2096,7 +2096,7 @@ process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
if (NULL == up) {
pr2serr("unable to allocate aligned memory for "
"scatterlist+data\n");
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto finii;
}
for (n = lbard_sz, k = 0; k < (int)addr_arr_len; ++k,
@@ -2562,7 +2562,7 @@ main(int argc, char * argv[])
up = sg_memalign(do_len, 0, &free_up, false);
if (NULL == up) {
pr2serr("unable to allocate %u bytes of memory\n", do_len);
- ret = SG_LIB_OS_BASE_ERR + ENOMEM;
+ ret = sg_convert_errno(ENOMEM);
goto err_out;
}
ret = bin_read(infd, up, ((if_len < do_len) ? if_len : do_len),
diff --git a/src/sginfo.c b/src/sginfo.c
index b466e8f1..6569140a 100644
--- a/src/sginfo.c
+++ b/src/sginfo.c
@@ -374,7 +374,7 @@ struct scsi_cmnd_io
#define SENSE_BUFF_LEN 64
#define CMD_TIMEOUT 60000 /* 60,000 milliseconds (60 seconds) */
-#define EBUFF_SZ 256
+#define EBUFF_SZ 512
#define GENERAL_ERROR 1
diff --git a/src/sgm_dd.c b/src/sgm_dd.c
index 0e2f6483..90729f0a 100644
--- a/src/sgm_dd.c
+++ b/src/sgm_dd.c
@@ -66,7 +66,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.51 20171209";
+static const char * version_str = "1.53 20180502";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -680,7 +680,7 @@ process_flags(const char * arg, struct flags_t * fp)
#define STR_SZ 1024
#define INOUTF_SZ 512
-#define EBUFF_SZ 512
+#define EBUFF_SZ 768
int
@@ -1187,24 +1187,18 @@ main(int argc, char * argv[])
if (wrkMmap) {
wrkPos = wrkMmap;
} else {
- if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
- wrkBuff = (uint8_t *)malloc(blk_sz * bpt + psz);
- if (NULL == wrkBuff) {
- pr2serr("Not enough user memory for raw\n");
- return SG_LIB_FILE_ERROR;
- }
+ wrkPos = (uint8_t *)sg_memalign(blk_sz * bpt, 0, &wrkBuff,
+ verbose > 3);
+ if (NULL == wrkPos) {
+ pr2serr("Not enough user memory\n");
+ return sg_convert_errno(ENOMEM);
+ }
+#if 0 /* keep copy of hack below, just in case ... */
/* perhaps use posix_memalign() instead */
+ wrkBuff = (uint8_t *)malloc(blk_sz * bpt + psz);
wrkPos = (uint8_t *)(((sg_uintptr_t)wrkBuff + psz - 1) &
(~(psz - 1)));
- }
- else {
- wrkBuff = (uint8_t *)malloc(blk_sz * bpt);
- if (NULL == wrkBuff) {
- pr2serr("Not enough user memory\n");
- return SG_LIB_FILE_ERROR;
- }
- wrkPos = wrkBuff;
- }
+#endif
}
blocks_per = bpt;
diff --git a/src/sgp_dd.c b/src/sgp_dd.c
index df5e12f2..de9697ea 100644
--- a/src/sgp_dd.c
+++ b/src/sgp_dd.c
@@ -60,7 +60,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "5.62 20180219";
+static const char * version_str = "5.63 20180502";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -68,7 +68,6 @@ static const char * version_str = "5.62 20180219";
#define DEF_SCSI_CDBSZ 10
#define MAX_SCSI_CDBSZ 16
-#define ME "sgp_dd: "
/* #define SG_DEBUG */
@@ -97,7 +96,7 @@ static const char * version_str = "5.62 20180219";
#define DEV_NULL_MINOR_NUM 3
-#define EBUFF_SZ 512
+#define EBUFF_SZ 768
struct flags_t {
bool append;
@@ -190,6 +189,8 @@ static int64_t dd_count = -1;
static int num_threads = DEF_NUM_THREADS;
static int exit_status = 0;
+static const char * my_name = "sgp_dd: ";
+
static void
calc_duration_throughput(int contin)
@@ -482,7 +483,7 @@ sig_listen_thread(void * v_clp)
if (shutting_down)
break;
if (SIGINT == sig_number) {
- pr2serr(ME "interrupted by SIGINT\n");
+ pr2serr("%sinterrupted by SIGINT\n", my_name);
guarded_stop_both(clp);
pthread_cond_broadcast(&clp->out_sync_cv);
}
@@ -740,18 +741,18 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
sg_put_unaligned_be24(0x1fffff & start_block, cdbp + 1);
cdbp[4] = (256 == blocks) ? 0 : (uint8_t)blocks;
if (blocks > 256) {
- pr2serr(ME "for 6 byte commands, maximum number of blocks is "
- "256\n");
+ pr2serr("%sfor 6 byte commands, maximum number of blocks is "
+ "256\n", my_name);
return 1;
}
if ((start_block + blocks - 1) & (~0x1fffff)) {
- pr2serr(ME "for 6 byte commands, can't address blocks beyond "
- "%d\n", 0x1fffff);
+ pr2serr("%sfor 6 byte commands, can't address blocks beyond "
+ "%d\n", my_name, 0x1fffff);
return 1;
}
if (dpo || fua) {
- pr2serr(ME "for 6 byte commands, neither dpo nor fua bits "
- "supported\n");
+ pr2serr("%sfor 6 byte commands, neither dpo nor fua bits "
+ "supported\n", my_name);
return 1;
}
break;
@@ -762,8 +763,8 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
sg_put_unaligned_be32((uint32_t)start_block, cdbp + 2);
sg_put_unaligned_be16((uint16_t)blocks, cdbp + 7);
if (blocks & (~0xffff)) {
- pr2serr(ME "for 10 byte commands, maximum number of blocks is "
- "%d\n", 0xffff);
+ pr2serr("%sfor 10 byte commands, maximum number of blocks is "
+ "%d\n", my_name, 0xffff);
return 1;
}
break;
@@ -782,8 +783,8 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
sg_put_unaligned_be32((uint32_t)blocks, cdbp + 10);
break;
default:
- pr2serr(ME "expected cdb size of 6, 10, 12, or 16 but got %d\n",
- cdb_sz);
+ pr2serr("%sexpected cdb size of 6, 10, 12, or 16 but got %d\n",
+ my_name, cdb_sz);
return 1;
}
return 0;
@@ -801,7 +802,8 @@ sg_in_operation(Rq_coll * clp, Rq_elem * rep)
if (1 == res)
err_exit(ENOMEM, "sg starting in command");
else if (res < 0) {
- pr2serr(ME "inputting to sg failed, blk=%" PRId64 "\n", rep->blk);
+ pr2serr("%sinputting to sg failed, blk=%" PRId64 "\n", my_name,
+ rep->blk);
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
guarded_stop_both(clp);
@@ -876,8 +878,8 @@ sg_out_operation(Rq_coll * clp, Rq_elem * rep)
if (1 == res)
err_exit(ENOMEM, "sg starting out command");
else if (res < 0) {
- pr2serr(ME "outputting from sg failed, blk=%" PRId64 "\n",
- rep->blk);
+ pr2serr("%soutputting from sg failed, blk=%" PRId64 "\n",
+ my_name, rep->blk);
status = pthread_mutex_unlock(&clp->out_mutex);
if (0 != status) err_exit(status, "unlock out_mutex");
guarded_stop_both(clp);
@@ -950,8 +952,8 @@ sg_start_io(Rq_elem * rep)
if (sg_build_scsi_cdb(rep->cmd, cdbsz, rep->num_blks, rep->blk,
rep->wr, fua, dpo)) {
- pr2serr(ME "bad cdb build, start_blk=%" PRId64 ", blocks=%d\n",
- rep->blk, rep->num_blks);
+ pr2serr("%sbad cdb build, start_blk=%" PRId64 ", blocks=%d\n",
+ my_name, rep->blk, rep->num_blks);
return -1;
}
memset(hp, 0, sizeof(struct sg_io_hdr));
@@ -1068,17 +1070,17 @@ sg_prepare(int fd, int bs, int bpt)
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
if ((res < 0) || (t < 30000)) {
- pr2serr(ME "sg driver prior to 3.x.y\n");
+ pr2serr("%ssg driver prior to 3.x.y\n", my_name);
return 1;
}
t = bs * bpt;
res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
if (res < 0)
- perror(ME "SG_SET_RESERVED_SIZE error");
+ perror("sgp_dd: SG_SET_RESERVED_SIZE error");
t = 1;
res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
if (res < 0)
- perror(ME "SG_SET_FORCE_PACK_ID error");
+ perror("sgp_dd: SG_SET_FORCE_PACK_ID error");
return 0;
}
@@ -1185,14 +1187,14 @@ main(int argc, char * argv[])
if (0 == strcmp(key,"bpt")) {
rcoll.bpt = sg_get_num(buf);
if (-1 == rcoll.bpt) {
- pr2serr(ME "bad argument to 'bpt='\n");
+ pr2serr("%sbad argument to 'bpt='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
bpt_given = 1;
} else if (0 == strcmp(key,"bs")) {
rcoll.bs = sg_get_num(buf);
if (-1 == rcoll.bs) {
- pr2serr(ME "bad argument to 'bs='\n");
+ pr2serr("%sbad argument to 'bs='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"cdbsz")) {
@@ -1206,7 +1208,7 @@ main(int argc, char * argv[])
if (0 != strcmp("-1", buf)) {
dd_count = sg_get_llnum(buf);
if (-1LL == dd_count) {
- pr2serr(ME "bad argument to 'count='\n");
+ pr2serr("%sbad argument to 'count='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} /* treat 'count=-1' as calculate count (same as not given) */
@@ -1225,7 +1227,7 @@ main(int argc, char * argv[])
} else if (0 == strcmp(key,"ibs")) {
ibs = sg_get_num(buf);
if (-1 == ibs) {
- pr2serr(ME "bad argument to 'ibs='\n");
+ pr2serr("%sbad argument to 'ibs='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (strcmp(key,"if") == 0) {
@@ -1236,13 +1238,13 @@ main(int argc, char * argv[])
strncpy(inf, buf, INOUTF_SZ);
} else if (0 == strcmp(key, "iflag")) {
if (process_flags(buf, &rcoll.in_flags)) {
- pr2serr(ME "bad argument to 'iflag='\n");
+ pr2serr("%sbad argument to 'iflag='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"obs")) {
obs = sg_get_num(buf);
if (-1 == obs) {
- pr2serr(ME "bad argument to 'obs='\n");
+ pr2serr("%sbad argument to 'obs='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (strcmp(key,"of") == 0) {
@@ -1253,19 +1255,19 @@ main(int argc, char * argv[])
strncpy(outf, buf, INOUTF_SZ);
} else if (0 == strcmp(key, "oflag")) {
if (process_flags(buf, &rcoll.out_flags)) {
- pr2serr(ME "bad argument to 'oflag='\n");
+ pr2serr("%sbad argument to 'oflag='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"seek")) {
seek = sg_get_llnum(buf);
if (-1LL == seek) {
- pr2serr(ME "bad argument to 'seek='\n");
+ pr2serr("%sbad argument to 'seek='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"skip")) {
skip = sg_get_llnum(buf);
if (-1LL == skip) {
- pr2serr(ME "bad argument to 'skip='\n");
+ pr2serr("%sbad argument to 'skip='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"sync"))
@@ -1281,7 +1283,7 @@ main(int argc, char * argv[])
return 0;
} else if ((0 == strncmp(key, "--vers", 6)) ||
(0 == strcmp(key, "-V"))) {
- pr2serr(ME ": %s\n", version_str);
+ pr2serr("%s%s\n", my_name, version_str);
return 0;
}
else {
@@ -1322,8 +1324,8 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
if (rcoll.debug)
- pr2serr(ME "if=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%"
- PRId64 "\n", inf, skip, outf, seek, dd_count);
+ pr2serr("%sif=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%"
+ PRId64 "\n", my_name, inf, skip, outf, seek, dd_count);
install_handler(SIGINT, interrupt_handler);
install_handler(SIGQUIT, interrupt_handler);
@@ -1336,10 +1338,10 @@ main(int argc, char * argv[])
rcoll.in_type = dd_filetype(inf);
if (FT_ERROR == rcoll.in_type) {
- pr2serr(ME "unable to access %s\n", inf);
+ pr2serr("%sunable to access %s\n", my_name, inf);
return SG_LIB_FILE_ERROR;
} else if (FT_ST == rcoll.in_type) {
- pr2serr(ME "unable to use scsi tape device %s\n", inf);
+ pr2serr("%sunable to use scsi tape device %s\n", my_name, inf);
return SG_LIB_FILE_ERROR;
} else if (FT_SG == rcoll.in_type) {
flags = O_RDWR;
@@ -1351,8 +1353,8 @@ main(int argc, char * argv[])
flags |= O_SYNC;
if ((rcoll.infd = open(inf, flags)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg reading", inf);
+ snprintf(ebuff, EBUFF_SZ, "%scould not open %s for sg "
+ "reading", my_name, inf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
@@ -1369,8 +1371,8 @@ main(int argc, char * argv[])
flags |= O_SYNC;
if ((rcoll.infd = open(inf, flags)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for reading", inf);
+ snprintf(ebuff, EBUFF_SZ, "%scould not open %s for reading",
+ my_name, inf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
@@ -1379,8 +1381,8 @@ main(int argc, char * argv[])
offset *= rcoll.bs; /* could exceed 32 here! */
if (lseek64(rcoll.infd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "couldn't skip to required position on %s", inf);
+ snprintf(ebuff, EBUFF_SZ, "%scouldn't skip to required "
+ "position on %s", my_name, inf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
@@ -1391,7 +1393,7 @@ main(int argc, char * argv[])
rcoll.out_type = dd_filetype(outf);
if (FT_ST == rcoll.out_type) {
- pr2serr(ME "unable to use scsi tape device %s\n", outf);
+ pr2serr("%sunable to use scsi tape device %s\n", my_name, outf);
return SG_LIB_FILE_ERROR;
}
else if (FT_SG == rcoll.out_type) {
@@ -1404,8 +1406,8 @@ main(int argc, char * argv[])
flags |= O_SYNC;
if ((rcoll.outfd = open(outf, flags)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for sg writing", outf);
+ snprintf(ebuff, EBUFF_SZ, "%scould not open %s for sg "
+ "writing", my_name, outf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
@@ -1428,16 +1430,16 @@ main(int argc, char * argv[])
flags |= O_APPEND;
if ((rcoll.outfd = open(outf, flags, 0666)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for writing", outf);
+ snprintf(ebuff, EBUFF_SZ, "%scould not open %s for "
+ "writing", my_name, outf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
}
else { /* raw output file */
if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "could not open %s for raw writing", outf);
+ snprintf(ebuff, EBUFF_SZ, "%scould not open %s for raw "
+ "writing", my_name, outf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
@@ -1447,8 +1449,8 @@ main(int argc, char * argv[])
offset *= rcoll.bs; /* could exceed 32 bits here! */
if (lseek64(rcoll.outfd, offset, SEEK_SET) < 0) {
- snprintf(ebuff, EBUFF_SZ,
- ME "couldn't seek to required position on %s", outf);
+ snprintf(ebuff, EBUFF_SZ, "%scouldn't seek to required "
+ "position on %s", my_name, outf);
perror(ebuff);
return SG_LIB_FILE_ERROR;
}