aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--doc/sg_read_buffer.86
-rw-r--r--include/sg_lib.h9
-rw-r--r--lib/sg_lib.c204
-rw-r--r--lib/sg_lib_data.c2
-rw-r--r--src/sg_decode_sense.c156
-rw-r--r--src/sg_inq.c190
-rw-r--r--src/sg_logs.c193
-rw-r--r--src/sg_raw.c201
-rw-r--r--src/sg_read_attr.c188
-rw-r--r--src/sg_read_buffer.c205
-rw-r--r--src/sg_vpd.c207
-rw-r--r--testing/sg_tst_ioctl.c32
-rw-r--r--testing/sgh_dd.cpp20
-rw-r--r--testing/sgs_dd.c12
15 files changed, 287 insertions, 1341 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b1bb6c9..2f869256 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.45 [20190515] [svn: r823]
+Changelog for sg3_utils-1.45 [20190517] [svn: r824]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (spc5r20)
@@ -26,6 +26,7 @@ Changelog for sg3_utils-1.45 [20190515] [svn: r823]
- tweak sg_pt interface to better handle bidi
- sg_cmds_process_resp(): two arguments removed
- add ${PACKAGE_VERSION} to '.so' name
+ - add sg_f2hex_arr()
- sg_pt_freebsd: fixes for FreeBSD 12.0 release
- scripts: update 54-before-scsi-sg3_id.rules,
scsi-enable-target-scan.sh and
diff --git a/doc/sg_read_buffer.8 b/doc/sg_read_buffer.8
index 422f0fa1..d1aed04b 100644
--- a/doc/sg_read_buffer.8
+++ b/doc/sg_read_buffer.8
@@ -16,6 +16,12 @@ it in binary to stdout. If a response is received for a "descriptor"
mode then, in the absence of \fI\-\-hex\fR and \fI\-\-raw\fR, it is
decoded. Response for non\-descriptor modes are output in hexadecimal
unless the \fI\-\-raw\fR option is given.
+.PP
+This utility may be called without a \fIDEVICE\fR but with a
+\fI\-\-inhex=FN\fR option instead. \fIFN\fR is expected to be a file
+name (or '\-' for stdin). The contents of the file (or stdin stream)
+is assumed to be hexadecimal (or binary) data that represents a SCSI
+READ BUFFER command response and is decoded as such.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
diff --git a/include/sg_lib.h b/include/sg_lib.h
index 80c536c1..ff162a61 100644
--- a/include/sg_lib.h
+++ b/include/sg_lib.h
@@ -569,6 +569,15 @@ void hex2stderr(const uint8_t * b_str, int len, int no_ascii);
int hex2str(const uint8_t * b_str, int len, const char * leadin, int format,
int cb_len, char * cbp);
+/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
+ * stdin). If reading ASCII hex then there should be either one entry per
+ * line or a comma, space or tab separated list of bytes. If no_space is
+ * set then a string of ACSII hex digits is expected, 2 per byte. Everything
+ * from and including a '#' on a line is ignored. Returns 0 if ok, or an
+ * error code. */
+int sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
+ uint8_t * mp_arr, int * mp_arr_len, int max_arr_len);
+
/* Returns true when executed on big endian machine; else returns false.
* Useful for displaying ATA identify words (which need swapping on a
* big endian machine). */
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index eb74aadc..bdfcd020 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -41,6 +41,9 @@
#include <inttypes.h>
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -3336,6 +3339,207 @@ sg_get_llnum_nomult(const char * buf)
return (1 == res) ? num : -1;
}
+/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
+ * stdin). If reading ASCII hex then there should be either one entry per
+ * line or a comma, space or tab separated list of bytes. If no_space is
+ * set then a string of ACSII hex digits is expected, 2 per byte. Everything
+ * from and including a '#' on a line is ignored. Returns 0 if ok, or an
+ * error code. */
+int
+sg_f2hex_arr(const char * fname, bool as_binary, bool no_space,
+ uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
+{
+ bool has_stdin, split_line;
+ int fn_len, in_len, k, j, m, fd, err;
+ int off = 0;
+ unsigned int h;
+ const char * lcp;
+ FILE * fp;
+ struct stat a_stat;
+ char line[512];
+ char carry_over[4];
+
+ if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
+ return SG_LIB_LOGIC_ERROR;
+ fn_len = strlen(fname);
+ if (0 == fn_len)
+ return SG_LIB_SYNTAX_ERROR;
+ has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
+ if (as_binary) {
+ if (has_stdin)
+ fd = STDIN_FILENO;
+ else {
+ fd = open(fname, O_RDONLY);
+ if (fd < 0) {
+ err = errno;
+ pr2serr("unable to open binary file %s: %s\n", fname,
+ safe_strerror(err));
+ return sg_convert_errno(err);
+ }
+ }
+ k = read(fd, mp_arr, max_arr_len);
+ if (k <= 0) {
+ int ret = SG_LIB_SYNTAX_ERROR;
+
+ if (0 == k)
+ pr2serr("read 0 bytes from binary file %s\n", fname);
+ else {
+ ret = sg_convert_errno(errno);
+ pr2serr("read from binary file %s: %s\n", fname,
+ safe_strerror(errno));
+ }
+ if (! has_stdin)
+ close(fd);
+ return ret;
+ }
+ if ((0 == fstat(fd, &a_stat)) && S_ISFIFO(a_stat.st_mode)) {
+ /* pipe; keep reading till error or 0 read */
+ while (k < max_arr_len) {
+ m = read(fd, mp_arr + k, max_arr_len - k);
+ if (0 == m)
+ break;
+ if (m < 0) {
+ err = errno;
+ pr2serr("read from binary pipe %s: %s\n", fname,
+ safe_strerror(err));
+ if (! has_stdin)
+ close(fd);
+ return sg_convert_errno(err);
+ }
+ k += m;
+ }
+ }
+ *mp_arr_len = k;
+ if (! has_stdin)
+ close(fd);
+ return 0;
+ } else { /* So read the file as ASCII hex */
+ if (has_stdin)
+ fp = stdin;
+ else {
+ fp = fopen(fname, "r");
+ if (NULL == fp) {
+ err = errno;
+ pr2serr("Unable to open %s for reading: %s\n", fname,
+ safe_strerror(err));
+ return sg_convert_errno(err);
+ }
+ }
+ }
+
+ carry_over[0] = 0;
+ for (j = 0; j < 512; ++j) {
+ if (NULL == fgets(line, sizeof(line), fp))
+ break;
+ in_len = strlen(line);
+ if (in_len > 0) {
+ if ('\n' == line[in_len - 1]) {
+ --in_len;
+ line[in_len] = '\0';
+ split_line = false;
+ } else
+ split_line = true;
+ }
+ if (in_len < 1) {
+ carry_over[0] = 0;
+ continue;
+ }
+ if (carry_over[0]) {
+ if (isxdigit(line[0])) {
+ carry_over[1] = line[0];
+ carry_over[2] = '\0';
+ if (1 == sscanf(carry_over, "%4x", &h))
+ mp_arr[off - 1] = h; /* back up and overwrite */
+ else {
+ pr2serr("%s: carry_over error ['%s'] around line %d\n",
+ __func__, carry_over, j + 1);
+ goto bad;
+ }
+ lcp = line + 1;
+ --in_len;
+ } else
+ lcp = line;
+ carry_over[0] = 0;
+ } else
+ lcp = line;
+
+ m = strspn(lcp, " \t");
+ if (m == in_len)
+ continue;
+ lcp += m;
+ in_len -= m;
+ if ('#' == *lcp)
+ continue;
+ k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
+ if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
+ pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
+ j + 1, m + k + 1);
+ goto bad;
+ }
+ if (no_space) {
+ for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
+ ++k, lcp += 2) {
+ if (1 != sscanf(lcp, "%2x", &h)) {
+ pr2serr("%s: bad hex number in line %d, pos %d\n",
+ __func__, j + 1, (int)(lcp - line + 1));
+ goto bad;
+ }
+ if ((off + k) >= max_arr_len) {
+ pr2serr("%s: array length exceeded\n", __func__);
+ goto bad;
+ }
+ mp_arr[off + k] = h;
+ }
+ if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
+ carry_over[0] = *lcp;
+ off += k;
+ } else {
+ for (k = 0; k < 1024; ++k) {
+ if (1 == sscanf(lcp, "%10x", &h)) {
+ if (h > 0xff) {
+ pr2serr("%s: hex number larger than 0xff in line "
+ "%d, pos %d\n", __func__, j + 1,
+ (int)(lcp - line + 1));
+ goto bad;
+ }
+ if (split_line && (1 == strlen(lcp))) {
+ /* single trailing hex digit might be a split pair */
+ carry_over[0] = *lcp;
+ }
+ if ((off + k) >= max_arr_len) {
+ pr2serr("%s: array length exceeded\n", __func__);
+ goto bad;
+ }
+ mp_arr[off + k] = h;
+ lcp = strpbrk(lcp, " ,\t");
+ if (NULL == lcp)
+ break;
+ lcp += strspn(lcp, " ,\t");
+ if ('\0' == *lcp)
+ break;
+ } else {
+ if (('#' == *lcp) || ('\r' == *lcp)) {
+ --k;
+ break;
+ }
+ pr2serr("%s: error in line %d, at pos %d\n", __func__,
+ j + 1, (int)(lcp - line + 1));
+ goto bad;
+ }
+ }
+ off += (k + 1);
+ }
+ }
+ *mp_arr_len = off;
+ if (stdin != fp)
+ fclose(fp);
+ return 0;
+bad:
+ if (stdin != fp)
+ fclose(fp);
+ return SG_LIB_SYNTAX_ERROR;
+}
+
/* Extract character sequence from ATA words as in the model string
* in a IDENTIFY DEVICE response. Returns number of characters
* written to 'ochars' before 0 character is found or 'num' words
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index fd4176b3..1e437ca6 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -19,7 +19,7 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "2.61 20190113";/* spc5r20, sbc4r15 */
+const char * sg_lib_version_str = "2.62 20190520";/* spc5r22, sbc4r17 */
/* indexed by pdt; those that map to own index do not decay */
diff --git a/src/sg_decode_sense.c b/src/sg_decode_sense.c
index 8dd682db..e4727593 100644
--- a/src/sg_decode_sense.c
+++ b/src/sg_decode_sense.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2018 Douglas Gilbert.
+ * Copyright (c) 2010-2019 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.
@@ -30,7 +30,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "1.19 20180714";
+static const char * version_str = "1.20 20190516";
#define MAX_SENSE_LEN 1024 /* max descriptor format actually: 255+8 */
@@ -244,154 +244,6 @@ the_end:
return 0;
}
-/* Read ASCII hex bytes from fname (a file named '-' taken as stdin).
- * There should be either one entry per line or a comma, space or tab
- * separated list of bytes. If no_space is set then a string of ACSII hex
- * digits is expected, 2 per byte. Everything from and including a '#'
- * on a line is ignored. Returns 0 if ok, sg3_utils code value. */
-static int
-f2hex_arr(const char * fname, bool no_space, uint8_t * mp_arr,
- int * mp_arr_len, int max_arr_len)
-{
- bool split_line;
- int fn_len, in_len, k, j, m, err;
- int off = 0;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- if ((1 == fn_len) && ('-' == fname[0])) /* read from stdin */
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- err = errno;
- pr2serr("Unable to open %s for reading: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1,
- m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line %d, "
- "pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return 0;
-bad:
- if (stdin != fp)
- fclose(fp);
- return SG_LIB_SYNTAX_ERROR;
-}
-
static void
write2wfn(FILE * fp, struct opts_t * op)
{
@@ -538,8 +390,8 @@ main(int argc, char *argv[])
}
op->sense_len = s;
} else if (op->file_given) {
- ret = f2hex_arr(op->fname, op->no_space, op->sense, &op->sense_len,
- MAX_SENSE_LEN);
+ ret = sg_f2hex_arr(op->fname, false, op->no_space, op->sense,
+ &op->sense_len, MAX_SENSE_LEN);
if (ret) {
pr2serr("unable to decode ASCII hex from file: %s\n", op->fname);
return ret;
diff --git a/src/sg_inq.c b/src/sg_inq.c
index d3534cb8..2319c9ed 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -51,7 +51,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * version_str = "2.00 20190313"; /* SPC-5 rev 21 */
+static const char * version_str = "2.01 20190520"; /* SPC-5 rev 22 */
/* INQUIRY notes:
* It is recommended that the initial allocation length given to a
@@ -820,190 +820,6 @@ parse_cmd_line(struct opts_t * op, int argc, char * argv[])
#endif /* SG_SCSI_STRINGS */
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * set then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns 0 if ok, or a
- * negated errno or SG_LIB_SYNTAX_ERROR or SG_LIB_FILE_ERROR . */
-static int
-f2hex_arr(const char * fname, int as_binary, int no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- bool has_stdin;
- bool split_line;
- int fn_len, in_len, k, j, m, fd, err;
- int off = 0;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin) {
- fd = STDIN_FILENO;
- if (sg_set_binary_mode(STDIN_FILENO) < 0)
- perror("sg_set_binary_mode");
- } else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- err = errno;
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(err));
- return -err;
- } else if (sg_set_binary_mode(fd) < 0)
- perror("sg_set_binary_mode");
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(errno));
- if (! has_stdin)
- close(fd);
- return SG_LIB_SYNTAX_ERROR;
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return 0;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- err = errno;
- pr2serr("Unable to open %s for reading\n", fname);
- return -err;
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line %d, "
- "pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- err = ferror(fp) ? SG_LIB_FILE_ERROR : 0;
- if (stdin != fp)
- fclose(fp);
- return err;
-bad:
- err = SG_LIB_SYNTAX_ERROR;
- if (stdin != fp)
- fclose(fp);
- return err;
-}
-
static const struct svpd_values_name_t *
sdp_find_vpd_by_acron(const char * ap)
{
@@ -4363,8 +4179,8 @@ main(int argc, char * argv[])
ret = SG_LIB_CONTRADICT;
goto err_out;
}
- err = f2hex_arr(op->inhex_fn, op->do_raw, 0, rsp_buff, &inhex_len,
- rsp_buff_sz);
+ err = sg_f2hex_arr(op->inhex_fn, !!op->do_raw, false, rsp_buff,
+ &inhex_len, rsp_buff_sz);
if (err) {
if (err < 0)
err = sg_convert_errno(-err);
diff --git a/src/sg_logs.c b/src/sg_logs.c
index a869f0c9..c60b50a1 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -36,7 +36,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "1.74 20190502"; /* spc5r21 + sbc4r17 */
+static const char * version_str = "1.75 20190516"; /* spc5r22 + sbc4r17 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -1356,189 +1356,6 @@ num_or_unknown(const uint8_t * xp, int num_bytes /* max is 8 */, bool in_hex,
return b;
}
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * set then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns 0 if ok, error
- * code. */
-static int
-f2hex_arr(const char * fname, bool as_binary, bool no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- bool split_line, has_stdin;
- int fn_len, in_len, k, j, m, fd, err;
- int off = 0;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin) {
- fd = STDIN_FILENO;
- if (sg_set_binary_mode(STDIN_FILENO) < 0)
- perror("sg_set_binary_mode");
- } else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- err = errno;
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- } else if (sg_set_binary_mode(fd) < 0)
- perror("sg_set_binary_mode");
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(errno));
- if (! has_stdin)
- close(fd);
- return SG_LIB_SYNTAX_ERROR;
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return 0;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- err = errno;
- pr2serr("Unable to open %s for reading: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%4x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%4x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line %d, "
- "pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return 0;
-bad:
- if (stdin != fp)
- fclose(fp);
- return SG_LIB_SYNTAX_ERROR;
-}
-
-
/* Call LOG SENSE twice: the first time ask for 4 byte response to determine
actual length of response; then a second time requesting the
min(actual_len, mx_resp_len) bytes. If the calculated length for the
@@ -6982,8 +6799,8 @@ main(int argc, char * argv[])
int pg_code, subpg_code, pdt, n;
uint16_t u;
- if ((ret = f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff,
- &in_len, rsp_buff_sz)))
+ if ((ret = sg_f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff,
+ &in_len, rsp_buff_sz)))
goto err_out;
if (vb > 2)
pr2serr("Read %d [0x%x] bytes of user supplied data\n",
@@ -7079,8 +6896,8 @@ main(int argc, char * argv[])
ret = SG_LIB_CONTRADICT;
goto err_out;
}
- if ((ret = f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff, &in_len,
- rsp_buff_sz)))
+ if ((ret = sg_f2hex_arr(op->in_fn, op->do_raw, false, rsp_buff,
+ &in_len, rsp_buff_sz)))
goto err_out;
if (vb > 2)
pr2serr("Read %d [0x%x] bytes of user supplied data\n", in_len,
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 00a58e0f..f9deaa9f 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -39,7 +39,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.29 (2019-01-24)"
+#define SG_RAW_VERSION "0.4.30 (2019-05-16)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -152,199 +152,6 @@ usage()
" sg_raw -r 1k /dev/sg0 12 00 00 00 60 00\n");
}
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * true then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns true if ok, or
- * false if error. */
-static bool
-f2hex_arr(const char * fname, bool as_binary, bool no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- int fn_len, in_len, k, j, m, fd;
- bool has_stdin, split_line;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
- int off = 0;
- struct stat a_stat;
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return false;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return false;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin)
- fd = STDIN_FILENO;
- else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(errno));
- return false;
- }
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(errno));
- if (! has_stdin)
- close(fd);
- return false;
- }
- if ((0 == fstat(fd, &a_stat)) && S_ISFIFO(a_stat.st_mode)) {
- /* pipe; keep reading till error or 0 read */
- while (k < max_arr_len) {
- m = read(fd, mp_arr + k, max_arr_len - k);
- if (0 == m)
- break;
- if (m < 0) {
- pr2serr("read from binary pipe %s: %s\n", fname,
- safe_strerror(errno));
- if (! has_stdin)
- close(fd);
- return false;
- }
- k += m;
- }
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return true;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- pr2serr("Unable to open %s for reading\n", fname);
- return false;
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%4x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%10x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line "
- "%d, pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return true;
-bad:
- if (stdin != fp)
- fclose(fp);
- return false;
-}
-
static int
parse_cmd_line(struct opts_t * op, int argc, char *argv[])
{
@@ -467,9 +274,9 @@ parse_cmd_line(struct opts_t * op, int argc, char *argv[])
if (op->cmdfile_given) {
bool ok;
- ok = f2hex_arr(op->cmd_file, (op->raw > 0) /* as_binary */,
- false /* no_space */, op->cdb, &op->cdb_length,
- MAX_SCSI_CDBSZ);
+ ok = sg_f2hex_arr(op->cmd_file, (op->raw > 0) /* as_binary */,
+ false /* no_space */, op->cdb, &op->cdb_length,
+ MAX_SCSI_CDBSZ);
if (! ok)
return SG_LIB_SYNTAX_ERROR;
if (op->verbose > 2) {
diff --git a/src/sg_read_attr.c b/src/sg_read_attr.c
index 33aa54ed..0b664596 100644
--- a/src/sg_read_attr.c
+++ b/src/sg_read_attr.c
@@ -373,190 +373,6 @@ enum_sa_acrons(void)
printf(" %d:\t\t%s\t%s\n", anvp->val, anvp->acron, anvp->name);
}
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * set then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns 0 if ok, or error
- * code. */
-static int
-f2hex_arr(const char * fname, bool as_binary, bool no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- bool split_line, has_stdin;
- int fn_len, in_len, k, j, m, fd, err;
- int off = 0;
- int ret = SG_LIB_SYNTAX_ERROR;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin) {
- fd = STDIN_FILENO;
- if (sg_set_binary_mode(STDIN_FILENO) < 0)
- perror("sg_set_binary_mode");
- } else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- err = errno;
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- } else if (sg_set_binary_mode(fd) < 0)
- perror("sg_set_binary_mode");
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else {
- err = errno;
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(err));
- ret = sg_convert_errno(err);
- }
- if (! has_stdin)
- close(fd);
- return ret;
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return 0;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- pr2serr("Unable to open %s for reading\n", fname);
- return 1;
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%4x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%4x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line %d, "
- "pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return 0;
-bad:
- if (stdin != fp)
- fclose(fp);
- return 1;
-}
-
/* Returns 1 if 'bp' all 0xff bytes, returns 2 is all 0xff bytes apart
* from last being 0xfe; otherwise returns 0. */
static int
@@ -1093,8 +909,8 @@ main(int argc, char * argv[])
if (NULL == device_name) {
if (fname) {
- if ((ret = f2hex_arr(fname, op->do_raw, 0 /* no space */, rabp,
- &in_len, op->maxlen)))
+ if ((ret = sg_f2hex_arr(fname, op->do_raw, false /* no space */,
+ rabp, &in_len, op->maxlen)))
goto clean_up;
if (op->do_raw)
op->do_raw = false; /* can interfere on decode */
diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c
index 82682f30..2dabefb2 100644
--- a/src/sg_read_buffer.c
+++ b/src/sg_read_buffer.c
@@ -39,7 +39,7 @@
* device.
*/
-static const char * version_str = "1.29 20190515"; /* spc5r22 */
+static const char * version_str = "1.29 20190516"; /* spc5r22 */
#ifndef SG_READ_BUFFER_10_CMD
@@ -391,207 +391,6 @@ decode_microcode_status(uint8_t * resp, int rb_len)
}
}
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * set then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns 0 if ok, or an
- * error code. */
-static int
-f2hex_arr(const char * fname, int as_binary, int no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- int fn_len, in_len, k, j, m, fd, err;
- bool has_stdin, split_line;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
- int off = 0;
- struct stat a_stat;
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin)
- fd = STDIN_FILENO;
- else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- err = errno;
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- int ret = SG_LIB_SYNTAX_ERROR;
-
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else {
- ret = sg_convert_errno(errno);
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(errno));
- }
- if (! has_stdin)
- close(fd);
- return ret;
- }
- if ((0 == fstat(fd, &a_stat)) && S_ISFIFO(a_stat.st_mode)) {
- /* pipe; keep reading till error or 0 read */
- while (k < max_arr_len) {
- m = read(fd, mp_arr + k, max_arr_len - k);
- if (0 == m)
- break;
- if (m < 0) {
- err = errno;
- pr2serr("read from binary pipe %s: %s\n", fname,
- safe_strerror(err));
- if (! has_stdin)
- close(fd);
- return sg_convert_errno(err);
- }
- k += m;
- }
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return 0;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- err = errno;
- pr2serr("Unable to open %s for reading: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%4x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%10x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line "
- "%d, pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return 0;
-bad:
- if (stdin != fp)
- fclose(fp);
- return 1;
-}
-
static void
dStrRaw(const uint8_t * str, int len)
{
@@ -782,7 +581,7 @@ main(int argc, char * argv[])
} else if (fname) {
rb_len = (rb_len > MAX_DEF_INHEX_LEN) ? rb_len : MAX_DEF_INHEX_LEN;
resp = (uint8_t *)sg_memalign(rb_len, 0, &free_resp, false);
- ret = f2hex_arr(fname, do_raw, 0, resp, &inhex_len, rb_len);
+ ret = sg_f2hex_arr(fname, do_raw, false, resp, &inhex_len, rb_len);
if (ret)
goto fini;
if (do_raw)
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index bf5c448f..6e4b21e8 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.53 20190429"; /* spc5r20 + sbc4r15 */
+static const char * version_str = "1.54 20190516"; /* spc5r22 + sbc4r17 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -300,207 +300,6 @@ usage()
"INQUIRY response.\n");
}
-/* Read ASCII hex bytes or binary from fname (a file named '-' taken as
- * stdin). If reading ASCII hex then there should be either one entry per
- * line or a comma, space or tab separated list of bytes. If no_space is
- * set then a string of ACSII hex digits is expected, 2 per byte. Everything
- * from and including a '#' on a line is ignored. Returns 0 if ok, or an
- * error code. */
-static int
-f2hex_arr(const char * fname, int as_binary, int no_space,
- uint8_t * mp_arr, int * mp_arr_len, int max_arr_len)
-{
- int fn_len, in_len, k, j, m, fd, err;
- bool has_stdin, split_line;
- unsigned int h;
- const char * lcp;
- FILE * fp;
- char line[512];
- char carry_over[4];
- int off = 0;
- struct stat a_stat;
-
- if ((NULL == fname) || (NULL == mp_arr) || (NULL == mp_arr_len))
- return SG_LIB_LOGIC_ERROR;
- fn_len = strlen(fname);
- if (0 == fn_len)
- return SG_LIB_SYNTAX_ERROR;
- has_stdin = ((1 == fn_len) && ('-' == fname[0])); /* read from stdin */
- if (as_binary) {
- if (has_stdin)
- fd = STDIN_FILENO;
- else {
- fd = open(fname, O_RDONLY);
- if (fd < 0) {
- err = errno;
- pr2serr("unable to open binary file %s: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
- k = read(fd, mp_arr, max_arr_len);
- if (k <= 0) {
- int ret = SG_LIB_SYNTAX_ERROR;
-
- if (0 == k)
- pr2serr("read 0 bytes from binary file %s\n", fname);
- else {
- ret = sg_convert_errno(errno);
- pr2serr("read from binary file %s: %s\n", fname,
- safe_strerror(errno));
- }
- if (! has_stdin)
- close(fd);
- return ret;
- }
- if ((0 == fstat(fd, &a_stat)) && S_ISFIFO(a_stat.st_mode)) {
- /* pipe; keep reading till error or 0 read */
- while (k < max_arr_len) {
- m = read(fd, mp_arr + k, max_arr_len - k);
- if (0 == m)
- break;
- if (m < 0) {
- err = errno;
- pr2serr("read from binary pipe %s: %s\n", fname,
- safe_strerror(err));
- if (! has_stdin)
- close(fd);
- return sg_convert_errno(err);
- }
- k += m;
- }
- }
- *mp_arr_len = k;
- if (! has_stdin)
- close(fd);
- return 0;
- } else { /* So read the file as ASCII hex */
- if (has_stdin)
- fp = stdin;
- else {
- fp = fopen(fname, "r");
- if (NULL == fp) {
- err = errno;
- pr2serr("Unable to open %s for reading: %s\n", fname,
- safe_strerror(err));
- return sg_convert_errno(err);
- }
- }
- }
-
- carry_over[0] = 0;
- for (j = 0; j < 512; ++j) {
- if (NULL == fgets(line, sizeof(line), fp))
- break;
- in_len = strlen(line);
- if (in_len > 0) {
- if ('\n' == line[in_len - 1]) {
- --in_len;
- line[in_len] = '\0';
- split_line = false;
- } else
- split_line = true;
- }
- if (in_len < 1) {
- carry_over[0] = 0;
- continue;
- }
- if (carry_over[0]) {
- if (isxdigit(line[0])) {
- carry_over[1] = line[0];
- carry_over[2] = '\0';
- if (1 == sscanf(carry_over, "%4x", &h))
- mp_arr[off - 1] = h; /* back up and overwrite */
- else {
- pr2serr("%s: carry_over error ['%s'] around line %d\n",
- __func__, carry_over, j + 1);
- goto bad;
- }
- lcp = line + 1;
- --in_len;
- } else
- lcp = line;
- carry_over[0] = 0;
- } else
- lcp = line;
-
- m = strspn(lcp, " \t");
- if (m == in_len)
- continue;
- lcp += m;
- in_len -= m;
- if ('#' == *lcp)
- continue;
- k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t");
- if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) {
- pr2serr("%s: syntax error at line %d, pos %d\n", __func__,
- j + 1, m + k + 1);
- goto bad;
- }
- if (no_space) {
- for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1));
- ++k, lcp += 2) {
- if (1 != sscanf(lcp, "%2x", &h)) {
- pr2serr("%s: bad hex number in line %d, pos %d\n",
- __func__, j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- }
- if (isxdigit(*lcp) && (! isxdigit(*(lcp + 1))))
- carry_over[0] = *lcp;
- off += k;
- } else {
- for (k = 0; k < 1024; ++k) {
- if (1 == sscanf(lcp, "%10x", &h)) {
- if (h > 0xff) {
- pr2serr("%s: hex number larger than 0xff in line "
- "%d, pos %d\n", __func__, j + 1,
- (int)(lcp - line + 1));
- goto bad;
- }
- if (split_line && (1 == strlen(lcp))) {
- /* single trailing hex digit might be a split pair */
- carry_over[0] = *lcp;
- }
- if ((off + k) >= max_arr_len) {
- pr2serr("%s: array length exceeded\n", __func__);
- goto bad;
- }
- mp_arr[off + k] = h;
- lcp = strpbrk(lcp, " ,\t");
- if (NULL == lcp)
- break;
- lcp += strspn(lcp, " ,\t");
- if ('\0' == *lcp)
- break;
- } else {
- if (('#' == *lcp) || ('\r' == *lcp)) {
- --k;
- break;
- }
- pr2serr("%s: error in line %d, at pos %d\n", __func__,
- j + 1, (int)(lcp - line + 1));
- goto bad;
- }
- }
- off += (k + 1);
- }
- }
- *mp_arr_len = off;
- if (stdin != fp)
- fclose(fp);
- return 0;
-bad:
- if (stdin != fp)
- fclose(fp);
- return 1;
-}
-
/* mxlen is command line --maxlen=LEN option (def: 0) or -1 for a VPD page
* with a short length (1 byte). Returns 0 for success. */
int /* global: use by sg_vpd_vendor.c */
@@ -4036,8 +3835,8 @@ main(int argc, char * argv[])
ret = SG_LIB_SYNTAX_ERROR;
goto err_out;
}
- if ((ret = f2hex_arr(op->inhex_fn, op->do_raw, 0, rsp_buff,
- &inhex_len, rsp_buff_sz))) {
+ if ((ret = sg_f2hex_arr(op->inhex_fn, !!op->do_raw, false, rsp_buff,
+ &inhex_len, rsp_buff_sz))) {
goto err_out;
}
if (op->verbose > 2)
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index a059643f..8629a684 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -75,7 +75,7 @@ static const char * version_str = "Version: 1.10 20190506";
#endif
#define DEF_Q_LEN 16 /* max in sg v3 and earlier */
-#define MAX_Q_LEN 256
+#define MAX_Q_LEN 512
#define DEF_RESERVE_BUFF_SZ (256 * 1024)
@@ -89,6 +89,7 @@ static bool mrq_immed = false; /* if set, also sets mrq_iosubmit */
static bool mrq_half_immed = false;
static bool mrq_iosubmit = false;
static bool show_size_value = false;
+static bool do_v3_only = false;
static int childs_pid = 0;
static int sg_drv_ver_num = 0;
@@ -104,8 +105,8 @@ static const char * relative_cp = NULL;
static void
usage(void)
{
- printf("Usage: sg_tst_ioctl [-f] [-h] [-l=Q_LEN] [-m=MRQS[,I|S]] [-M] "
- "[-o]\n"
+ printf("Usage: sg_tst_ioctl [-3] [-f] [-h] [-l=Q_LEN] [-m=MRQS[,I|S]] "
+ "[-M] [-o]\n"
" [-r=SZ] [-s=SEC] [-S] [-t] [-v] [-V] [-w]\n"
" <sg_device> [<sg_device2>]\n"
" where:\n"
@@ -257,8 +258,8 @@ set_more_async(int fd)
}
static int
-tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
- int sock, const char * cp)
+tst_extended_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
+ int sock, const char * cp)
{
uint32_t cflags;
struct sg_extended_info sei;
@@ -650,7 +651,9 @@ main(int argc, char * argv[])
pr2serr("Warning <<<< sizeof(struct sg_extended_info)=%zu not 96\n",
sizeof(struct sg_extended_info));
for (k = 1; k < argc; ++k) {
- if (0 == memcmp("-f", argv[k], 2))
+ if (0 == memcmp("-3", argv[k], 2))
+ do_v3_only = true;
+ else if (0 == memcmp("-f", argv[k], 2))
do_fork = true;
else if (0 == memcmp("-h", argv[k], 2)) {
file_name = 0;
@@ -811,7 +814,7 @@ main(int argc, char * argv[])
goto out;
}
printf("Linux sg driver version: %d\n", sg_drv_ver_num);
- if (more_async)
+ if (more_async && !do_v3_only)
set_more_async(sg_fd);
if (second_fname) {
@@ -824,11 +827,11 @@ main(int argc, char * argv[])
if (verbose)
fprintf(stderr, "opened second file: %s successfully, fd=%d\n",
second_fname, sg_fd2);
- if (more_async)
+ if (more_async && !do_v3_only)
set_more_async(sg_fd2);
}
- if (num_mrqs > 0) {
+ if ((num_mrqs > 0) && !do_v3_only) {
res = do_mrqs(sg_fd, sg_fd2, num_mrqs);
goto out;
}
@@ -862,15 +865,18 @@ main(int argc, char * argv[])
}
cp = do_fork ? relative_cp : "";
- if (tst_ioctl(file_name, sg_fd, second_fname, sg_fd2, sock, cp))
- goto out;
+ if (! do_v3_only) {
+ if (tst_extended_ioctl(file_name, sg_fd, second_fname, sg_fd2, sock,
+ cp))
+ goto out;
+ }
if (ioctl_only)
goto out;
if (do_fork && !is_parent)
return 0;
- printf("start iosubmit calls\n");
+ printf("start write() calls [submits]\n");
for (k = 0; k < q_len; ++k) {
/* Prepare INQUIRY command */
memset(&io_hdr[k], 0, sizeof(sg_io_hdr_t));
@@ -950,7 +956,7 @@ main(int argc, char * argv[])
else
printf("num_waiting: %d\n", num_waiting);
- printf("\nstart ioreceive() calls\n");
+ printf("\nstart read() calls [io receive]\n");
for (k = 0, done = false; k < q_len; ++k) {
if ((! done) && (k == q_len / 2)) {
done = true;
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index bde865dc..185044f1 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.30 20190505";
+static const char * version_str = "1.31 20190515";
#ifdef __GNUC__
#ifndef __clang__
@@ -305,6 +305,7 @@ static pthread_mutex_t strerr_mut = PTHREAD_MUTEX_INITIALIZER;
static bool have_sg_version = false;
static int sg_version = 0;
+static bool sg_version_lt_4 = false;
static bool shutting_down = false;
static bool do_sync = false;
static bool do_time = true;
@@ -1039,7 +1040,7 @@ read_write_thread(void * v_tip)
pr2serr_lk("thread=%d: using global sg OFILE2, fd=%d\n", rep->id,
rep->out2fd);
}
- if (rep->in_flags.noshare || rep->out_flags.noshare) {
+ if (rep->in_flags.noshare || rep->out_flags.noshare || sg_version_lt_4) {
if (vb > 4)
pr2serr_lk("thread=%d: Skipping share on both IFILE and OFILE\n",
rep->id);
@@ -2184,6 +2185,7 @@ static int
sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
bool unit_nano, bool no_dur, bool masync, uint8_t **mmpp)
{
+ static bool done = false;
int res, t, num;
uint8_t *mmp;
struct sg_extended_info sei;
@@ -2192,8 +2194,17 @@ sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
seip = &sei;
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
if ((res < 0) || (t < 40000)) {
- pr2serr_lk("%ssg driver prior to 4.0.00\n", my_name);
- return 0;
+ if (ioctl(fd, SG_GET_RESERVED_SIZE, &num) < 0) {
+ perror("SG_GET_RESERVED_SIZE ioctl failed");
+ return 0;
+ }
+ if (! done) {
+ done = true;
+ sg_version_lt_4 = true;
+ pr2serr_lk("%ssg driver prior to 4.0.00, reduced functionality\n",
+ my_name);
+ }
+ goto fini;
}
if (elem_sz >= 4096) {
memset(seip, 0, sizeof(*seip));
@@ -2263,6 +2274,7 @@ sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
errno, strerror(errno));
}
}
+fini:
return (res < 0) ? 0 : num;
}
diff --git a/testing/sgs_dd.c b/testing/sgs_dd.c
index 991f8011..e0ff7b4b 100644
--- a/testing/sgs_dd.c
+++ b/testing/sgs_dd.c
@@ -78,7 +78,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "4.07 20190503";
+static const char * version_str = "4.08 20190515";
static const char * my_name = "sgs_dd";
#define DEF_BLOCK_SIZE 512
@@ -471,7 +471,7 @@ do_v4:
}
static int
-sz_reserve(int fd, int bs, int bpt, bool rt_sig)
+sz_reserve(int fd, int bs, int bpt, bool rt_sig, bool vb)
{
int res, t, flags;
struct sg_extended_info sei;
@@ -484,7 +484,8 @@ sz_reserve(int fd, int bs, int bpt, bool rt_sig)
return 1;
}
else if (t < 40000) {
- fprintf(stderr, "sgs_dd: warning: sg driver prior to 4.0.00\n");
+ if (vb)
+ fprintf(stderr, "sgs_dd: warning: sg driver prior to 4.0.00\n");
sgs_old_sg_driver = true;
}
res = 0;
@@ -1075,7 +1076,8 @@ main(int argc, char * argv[])
return 1;
}
clp->in_is_sg = true;
- if (sz_reserve(clp->infd, clp->bs, clp->bpt, clp->use_rt_sig))
+ if (sz_reserve(clp->infd, clp->bs, clp->bpt, clp->use_rt_sig,
+ clp->debug))
return 1;
if (sgs_old_sg_driver && (clp->iflag.v4 || clp->oflag.v4)) {
pr2serr("Unable to implement v4 flag because sg driver too "
@@ -1095,7 +1097,7 @@ main(int argc, char * argv[])
else {
clp->out_is_sg = true;
if (sz_reserve(clp->outfd, clp->bs, clp->bpt,
- clp->use_rt_sig))
+ clp->use_rt_sig, clp->debug))
return 1;
if (sgs_old_sg_driver && (clp->iflag.v4 || clp->oflag.v4)) {
pr2serr("Unable to implement v4 flag because sg driver "