aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-02-11 01:43:25 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-02-11 01:43:25 +0000
commit9ddcd0ac08f1c6a46d681bc349f3f523e8da4fcf (patch)
treed15aa1b54d7d769ab510d895a66a529d6532d658 /utils
parentd491f4c710d6d1d123d421eb0ba7aeddee9cf7d7 (diff)
downloadsg3_utils-9ddcd0ac08f1c6a46d681bc349f3f523e8da4fcf.tar.gz
sg_pt: add sg_get_opcode_translation() to replace global pointer to array; utils/hxascdmp: add -o=<offset> option; testing/sgh_dd fixes
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@811 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'utils')
-rw-r--r--utils/hxascdmp.113
-rw-r--r--utils/hxascdmp.c170
2 files changed, 176 insertions, 7 deletions
diff --git a/utils/hxascdmp.1 b/utils/hxascdmp.1
index 16300aa3..22814922 100644
--- a/utils/hxascdmp.1
+++ b/utils/hxascdmp.1
@@ -1,10 +1,10 @@
-.TH HXASCDMP "1" "February 2014" "sg3_utils\-1.38" SG3_UTILS
+.TH HXASCDMP "1" "February 2019" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
hxascdmp \- hexadecimal ASCII dump
.SH SYNOPSIS
.B hxascdmp
-[\fI\-b=BPL\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-N\fR] [\fI\-V\fR]
-[\fIFILE+\fR]
+[\fI\-b=BPL\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-N\fR] [\fI\-o=OFF\fR]
+[\fI\-V\fR] [\fIFILE+\fR]
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -46,6 +46,11 @@ end of each line).
\fB\-N\fR
no address; so each line starts with the next hexadecimal byte.
.TP
+\fB\-o\fR=\fIOFF\fR
+where \fIOFF\fR specifies the byte offset from the beginning of the pipe or
+the beginning of each file that the output starts. If the address is being
+printed out then it starts at \fIOFF\fR. The default is an \fIOFF\fR of 0 .
+.TP
\fB\-V\fR, \fB\-\-version\fR
print the version string and then exit.
.SH NOTES
@@ -98,7 +103,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2014 Douglas Gilbert
+Copyright \(co 2004\-2019 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/utils/hxascdmp.c b/utils/hxascdmp.c
index 9f6566d3..4184c037 100644
--- a/utils/hxascdmp.c
+++ b/utils/hxascdmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2014 Douglas Gilbert.
+ * Copyright (c) 2004-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.
@@ -14,12 +14,16 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
#define DEF_BYTES_PER_LINE 16
static int bytes_per_line = DEF_BYTES_PER_LINE;
-static const char * version_str = "1.15 20181207";
+static const char * version_str = "1.17 20190210";
#define CHARS_PER_HEX_BYTE 3
#define BINARY_START_COL 6
@@ -73,6 +77,126 @@ num_chs_in_str(const char * s, int slen, int ch)
return res;
}
+/* If the number in 'buf' can be decoded or the multiplier is unknown
+ * then -1LL is returned. Accepts a hex prefix (0x or 0X) or a decimal
+ * multiplier suffix (as per GNU's dd (since 2002: SI and IEC 60027-2)).
+ * Main (SI) multipliers supported: K, M, G, T, P. Ignore leading spaces
+ * and tabs; accept comma, hyphen, space, tab and hash as terminator. */
+int64_t
+sg_get_llnum(const char * buf)
+{
+ int res, len, n;
+ int64_t num, ll;
+ uint64_t unum;
+ char * cp;
+ const char * b;
+ char c = 'c';
+ char c2 = '\0'; /* keep static checker happy */
+ char c3 = '\0'; /* keep static checker happy */
+ char lb[32];
+
+ if ((NULL == buf) || ('\0' == buf[0]))
+ return -1LL;
+ len = strlen(buf);
+ n = strspn(buf, " \t");
+ if (n > 0) {
+ if (n == len)
+ return -1LL;
+ buf += n;
+ len -= n;
+ }
+ /* following hack to keep C++ happy */
+ cp = strpbrk((char *)buf, " \t,#-");
+ if (cp) {
+ len = cp - buf;
+ n = (int)sizeof(lb) - 1;
+ len = (len < n) ? len : n;
+ memcpy(lb, buf, len);
+ lb[len] = '\0';
+ b = lb;
+ } else
+ b = buf;
+ if (('0' == b[0]) && (('x' == b[1]) || ('X' == b[1]))) {
+ res = sscanf(b + 2, "%" SCNx64 , &unum);
+ num = unum;
+ } else if ('H' == toupper((int)b[len - 1])) {
+ res = sscanf(b, "%" SCNx64 , &unum);
+ num = unum;
+ } else
+ res = sscanf(b, "%" SCNd64 "%c%c%c", &num, &c, &c2, &c3);
+ if (res < 1)
+ return -1LL;
+ else if (1 == res)
+ return num;
+ else {
+ if (res > 2)
+ c2 = toupper((int)c2);
+ if (res > 3)
+ c3 = toupper((int)c3);
+ switch (toupper((int)c)) {
+ case 'C':
+ return num;
+ case 'W':
+ return num * 2;
+ case 'B':
+ return num * 512;
+ case 'K':
+ if (2 == res)
+ return num * 1024;
+ if (('B' == c2) || ('D' == c2))
+ return num * 1000;
+ if (('I' == c2) && (4 == res) && ('B' == c3))
+ return num * 1024;
+ return -1LL;
+ case 'M':
+ if (2 == res)
+ return num * 1048576;
+ if (('B' == c2) || ('D' == c2))
+ return num * 1000000;
+ if (('I' == c2) && (4 == res) && ('B' == c3))
+ return num * 1048576;
+ return -1LL;
+ case 'G':
+ if (2 == res)
+ return num * 1073741824;
+ if (('B' == c2) || ('D' == c2))
+ return num * 1000000000;
+ if (('I' == c2) && (4 == res) && ('B' == c3))
+ return num * 1073741824;
+ return -1LL;
+ case 'T':
+ if (2 == res)
+ return num * 1099511627776LL;
+ if (('B' == c2) || ('D' == c2))
+ return num * 1000000000000LL;
+ if (('I' == c2) && (4 == res) && ('B' == c3))
+ return num * 1099511627776LL;
+ return -1LL;
+ case 'P':
+ if (2 == res)
+ return num * 1099511627776LL * 1024;
+ if (('B' == c2) || ('D' == c2))
+ return num * 1000000000000LL * 1000;
+ if (('I' == c2) && (4 == res) && ('B' == c3))
+ return num * 1099511627776LL * 1024;
+ return -1LL;
+ case 'X':
+ cp = (char *)strchr(b, 'x');
+ if (NULL == cp)
+ cp = (char *)strchr(b, 'X');
+ if (cp) {
+ ll = sg_get_llnum(cp + 1);
+ if (-1LL != ll)
+ return num * ll;
+ }
+ return -1LL;
+ default:
+ fprintf(stderr, "unrecognized multiplier\n");
+ return -1LL;
+ }
+ }
+}
+
static void
dStrHex(const char* str, int len, long start, int noAddr)
{
@@ -202,6 +326,8 @@ usage()
fprintf(stderr, " -H print hex only (i.e. no ASCII "
"to right)\n");
fprintf(stderr, " -N no address, start in first column\n");
+ fprintf(stderr, " -o=<off> start decoding at byte <off>. Suffix "
+ "multipliers allowed\n");
fprintf(stderr, " -V print version string then exits\n");
fprintf(stderr, " -? print this usage message\n");
fprintf(stderr, " <file>+ reads file(s) and outputs each "
@@ -216,6 +342,7 @@ main(int argc, const char ** argv)
char buff[8192];
int num = 8192;
long start = 0;
+ int64_t offset = 0;
int res, k, u, len, n;
int inFile = STDIN_FILENO;
int doHelp = 0;
@@ -237,6 +364,15 @@ main(int argc, const char ** argv)
return 1;
}
bytes_per_line = u;
+ } else if (0 == strncmp("-o=", cp, 3)) {
+ int64_t off = sg_get_llnum(cp + 3);
+
+ if (off == -1) {
+ fprintf(stderr, "Bad value after '-o=' option\n");
+ usage();
+ return 1;
+ }
+ offset = off;
} else if ((len > 1) && ('-' == cp[0]) && ('-' != cp[1])) {
res = 0;
n = num_chs_in_str(cp + 1, len - 1, 'h');
@@ -292,7 +428,21 @@ main(int argc, const char ** argv)
ret = 1;
} else {
sg_set_binary_mode(inFile);
- start = 0;
+ if (offset > 0) {
+ int err;
+ int64_t off_res;
+
+ off_res = lseek(inFile, offset, SEEK_SET);
+ if (off_res < 0) {
+ err = errno;
+ fprintf(stderr, "failed moving filepos: wanted=%"
+ PRId64 " [0x%" PRIx64 "]\nlseek error: %s\n",
+ offset, offset, strerror(err));
+ goto fini1;
+ }
+ start = offset;
+ } else
+ start = 0;
if (! doHex)
printf("ASCII hex dump of file: %s\n", argv[k]);
while ((res = read(inFile, buff, num)) > 0) {
@@ -303,10 +453,24 @@ main(int argc, const char ** argv)
start += (long)res;
}
}
+fini1:
close(inFile);
}
} else {
sg_set_binary_mode(inFile);
+ if (offset > 0) {
+ start = offset;
+ do { /* eat up offset bytes */
+ if ((res = read(inFile, buff,
+ (num > offset ? offset : num))) > 0)
+ offset -= res;
+ else {
+ fprintf(stderr, "offset read() error: %s\n",
+ strerror(errno));
+ break;
+ }
+ } while (offset > 0);
+ }
while ((res = read(inFile, buff, num)) > 0) {
if (doHex)
dStrHexOnly(buff, res, start, noAddr);