aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_requests.857
-rw-r--r--doc/sg_turs.835
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_requests.c89
-rw-r--r--src/sg_start.c2
-rw-r--r--utils/Makefile14
-rw-r--r--utils/README5
-rw-r--r--utils/hxascdmp.187
-rw-r--r--utils/hxascdmp.c152
11 files changed, 356 insertions, 94 deletions
diff --git a/ChangeLog b/ChangeLog
index 39943a81..645ea135 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.26 [20080318]
+Changelog for sg3_utils-1.26 [20080326]
- sg_ses: sync with ses2r19b
- sg_get_config: sync with mmc6r01
- allow Microcode upgrade and DVD read feature descriptors
@@ -26,7 +26,10 @@ Changelog for sg3_utils-1.26 [20080318]
- sg_start: add '--noflush' and '--mod=PC_MOD' options (08-139r1)
- change 'long long' to int64_t and 'unsigned long long' to
uint64_t to stress that 64 bit integer wanted, not larger
+ - sg_request: add a '--progress' option (similar to sg_turs)
+ - sg_turs: add more to man page about '--progress' indication
- sg_lib: update asc/ascq code to spc4r13
+ - utils/hxascdmp: add hxascdmp(1) man page
- split sg_lib into sg_lib_data.[hc] and sg_lib.[hc]
- split sg_cmds_extra into sg_cmds_extra and sg_cmds_mmc
- add osd2r03 service actions (all different from osd-r10)
diff --git a/debian/changelog b/debian/changelog
index 32b280c5..797e46ca 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.26-0.1) unstable; urgency=low
* New upstream version
- -- Doug Gilbert <dgilbert@interlog.com> Tue, 18 Mar 2008 13:00:00 -0400
+ -- Doug Gilbert <dgilbert@interlog.com> Wed, 26 Mar 2008 09:00:00 -0400
sg3-utils (1.25-0.1) unstable; urgency=low
diff --git a/doc/sg_requests.8 b/doc/sg_requests.8
index afed2060..83d93591 100644
--- a/doc/sg_requests.8
+++ b/doc/sg_requests.8
@@ -1,17 +1,21 @@
-.TH SG_REQUESTS "8" "January 2007" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_REQUESTS "8" "March 2008" "sg3_utils\-1.26" SG3_UTILS
.SH NAME
sg_requests \- send one or more SCSI REQUEST SENSE commands
.SH SYNOPSIS
.B sg_requests
[\fI\-\-desc\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-num=NUM\fR]
-[\fI\-\-raw\fR] [\fI\-\-status\fR] [\fI\-\-time\fR] [\fI\-\-verbose\fR]
-[\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-progress\fR] [\fI\-\-raw\fR] [\fI\-\-status\fR] [\fI\-\-time\fR]
+[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
-Send REQUEST SENSE command to \fIDEVICE\fR and output the response which is
-expected to be in sense data format. Both fixed and descriptor format are
-supported.
+Send SCSI REQUEST SENSE command to \fIDEVICE\fR and output the parameter
+data response which is expected to be in sense data format. Both fixed
+and descriptor sense data formats are supported.
+.PP
+Multiple REQUEST SENSE commands can be sent with the \fI\-\-num=NUM\fR
+option. This can be used for timing purposes or monitoring the progress
+indication.
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
@@ -32,14 +36,22 @@ output response in ASCII hexadecimal.
perform \fINUM\fR SCSI REQUEST SENSE commands, stopping when either \fINUM\fR
is reached or an error occurs. The default value for \fINUM\fR is 1 .
.TP
+\fB\-p\fR, \fB\-\-progress\fR
+show progress indication (a percentage) if available. If \fI\-\-number=NUM\fR
+is given, \fINUM\fR is greater than 1 and an initial progress indication
+was detected then this utility waits 30 seconds before subsequent checks.
+Exits when \fINUM\fR is reached or there are no more progress indications.
+Ignores \fI\-\-hex\fR, \fI\-\-raw\fR and \fI\-\-time\fR options. See
+NOTES section below.
+.TP
\fB\-r\fR, \fB\-\-raw\fR
output response in binary (to stdout).
.TP
\fB\-s\fR, \fB\-\-status\fR
-if the last REQUEST SENSE finished without error (from SCSI status or
-autosense) then the contents of the parameter data are analysed as
+if the REQUEST SENSE command finished without error (as indicated by its
+SCSI status) then the contents of the parameter data are analysed as
sense data and the exit status is set accordingly. The default
-action (when this option is not given) is to ignore the contents
+action (i.e. when this option is not given) is to ignore the contents
of the parameter data for the purposes of setting the exit status.
Some types of error set a sense key of "NO SENSE" with non\-zero
information in the additional sense code (e.g. the FAILURE PREDICTION
@@ -65,17 +77,28 @@ and warning processing in SCSI. The autosense capability rendered this
command almost superfluous.
.PP
However recent SCSI drafts (e.g. SPC\-3 rev 23 and SBC\-2 rev 16) increase
-the utility of the REQUEST SENSE command. Idle and standby power
-conditions can now be detected with this command; a progress indication
-is given during FORMAT (when that command was started with with IMMED=1
-in its parameter header); and the Filemark, ILI and EOM bits may be
-set (e.g. by a tape drive). Interestingly the sense key is set
-to "no sense" while the asc/ascq code convey the information (e.g.
-0x5e/0x4 "Standby condition activated by command").
+the utility of the REQUEST SENSE command. Idle and standby (low) power
+conditions can be detected with this command.
.PP
The REQUEST SENSE command is not marked as mandatory in SPC\-3 (i.e. for
all SCSI devices) but is marked as mandatory in SBC\-2 (i.e. for disks),
SSC\-3 (i.e. for tapes) and MMC\-4 (i.e. for CD/DVD drives).
+.PP
+The progress indication is optionally part of the sense data. When a prior
+command that takes a long time to complete (and typically precludes other
+media access commands) is still underway, the progress indication can be used
+to determine how long before the device returns to its normal state.
+.PP
+The SCSI FORMAT command for disks used with the IMMED bit set is an example
+of an operation that takes a significant amount of time and precludes other
+media access during that time. The IMMED bit set instructs the FORMAT command
+to return control to the application client once the format has commenced (see
+SBC-3). Several long duration SCSI commands associated with tape drives also
+use the progress indication (see SSC-3).
+.PP
+Early standards suggested that the SCSI TEST UNIT READY command be used for
+polling the progress indication. More recent standards seem to suggest
+the SCSI REQUEST SENSE command should be used instead.
.SH EXIT STATUS
The exit status of sg_requests is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
@@ -84,7 +107,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2004\-2007 Douglas Gilbert
+Copyright \(co 2004\-2008 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/doc/sg_turs.8 b/doc/sg_turs.8
index 2018c63a..3f12b563 100644
--- a/doc/sg_turs.8
+++ b/doc/sg_turs.8
@@ -1,4 +1,4 @@
-.TH SG_TURS "8" "December 2006" "sg3_utils\-1.23" SG3_UTILS
+.TH SG_TURS "8" "March 2008" "sg3_utils\-1.26" SG3_UTILS
.SH NAME
sg_turs \- send one or more SCSI TEST UNIT READY commands
.SH SYNOPSIS
@@ -15,9 +15,7 @@ sg_turs \- send one or more SCSI TEST UNIT READY commands
This utility sends one or more SCSI TEST UNIT READY commands to the
\fIDEVICE\fR. This may be useful for timing the per command overhead.
Note that TEST UNIT READY has no associated data, just a 6 byte command
-and a returned SCSI status value. If the SCSI status value is CHECK
-CONDITION then most modern initiators fetch sense data from
-the device (i.e. autosense).
+and a returned SCSI status value.
.PP
This utility supports two command line syntaxes, the preferred one is
shown first in the synopsis and explained in this section. A later section
@@ -40,10 +38,11 @@ number may be given, prefixed by either '0x' or has a trailing 'h'.
switch to older style options.
.TP
\fB\-p\fR, \fB\-\-progress\fR
-show progress indication (a percentage) if available. If \fI\-\-number=NUM\fR
-is given and \fINUM\fR is greater than 1 then waits 30 seconds before
-subsequent checks. Exits when \fINUM\fR is reached or there is no more
-progress indication. Ignores \fI\-\-time\fR option.
+show progress indication (a percentage) if available. If \fI\-\-number=NUM\fR
+is given, \fINUM\fR is greater than 1 and an initial progress indication
+was detected then this utility waits 30 seconds before subsequent checks.
+Exits when \fINUM\fR is reached or there are no more progress indications.
+Ignores \fI\-\-time\fR option. See NOTES section below.
.TP
\fB\-t\fR, \fB\-\-time\fR
after completing the requested number of TEST UNIT READY commands, outputs
@@ -54,6 +53,22 @@ increase level or verbosity.
.TP
\fB\-V\fR, \fB\-\-version\fR
print version string then exit.
+.SH NOTES
+The progress indication is optionally part of the sense data. When a prior
+command that takes a long time to complete (and typically precludes other
+media access commands) is still underway, the progress indication can be used
+to determine how long before the device returns to its normal state.
+.PP
+The SCSI FORMAT command for disks used with the IMMED bit set is an example
+of an operation that takes a significant amount of time and precludes other
+media access during that time. The IMMED bit set instructs the FORMAT command
+to return control to the application client once the format has commenced (see
+SBC-3). Several long duration SCSI commands associated with tape drives also
+use the progress indication (see SSC-3).
+.PP
+Early standards suggested that the SCSI TEST UNIT READY command be used for
+polling the progress indication. More recent standards seem to suggest
+the SCSI REQUEST SENSE command should be used instead.
.SH EXIT STATUS
The exit status of sg_turs is 0 when it is successful. Otherwise see
the sg3_utils(8) man page.
@@ -87,9 +102,9 @@ print out version string then exit.
.SH AUTHORS
Written by D. Gilbert
.SH COPYRIGHT
-Copyright \(co 2000\-2006 Douglas Gilbert
+Copyright \(co 2000\-2008 Douglas Gilbert
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.SH "SEE ALSO"
-.B sg_inq(sg3_utils)
+.B sg_inq, sg_request (sg3_utils)
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 003cedfc..28ad9760 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Tue Mar 18 2008 - dgilbert at interlog dot com
+* Wed Mar 26 2008 - dgilbert at interlog dot com
- sg_get_config sync with mmc6r01, add sg_sat_phy_event
* sg3_utils-1.26
diff --git a/src/sg_requests.c b/src/sg_requests.c
index 0be47f00..ba42f2b6 100644
--- a/src/sg_requests.c
+++ b/src/sg_requests.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2007 Douglas Gilbert.
+ * Copyright (c) 2004-2008 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,10 +47,21 @@
* This program issues the SCSI command REQUEST SENSE to the given SCSI device.
*/
-static char * version_str = "1.18 20070919";
+static char * version_str = "1.19 20080325";
#define REQUEST_SENSE_BUFF_LEN 252
+/* Not all environments support the Unix sleep() */
+#if defined(MSC_VER) || defined(__MINGW32__)
+#define HAVE_MS_SLEEP
+#endif
+#ifdef HAVE_MS_SLEEP
+#include <windows.h>
+#define sleep_for(seconds) Sleep( (seconds) * 1000)
+#else
+#define sleep_for(seconds) sleep(seconds)
+#endif
+
#define ME "sg_requests: "
@@ -59,6 +70,7 @@ static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"hex", 0, 0, 'H'},
{"num", 1, 0, 'n'},
+ {"progress", 0, 0, 'p'},
{"raw", 0, 0, 'r'},
{"status", 0, 0, 's'},
{"time", 0, 0, 't'},
@@ -70,7 +82,8 @@ static struct option long_options[] = {
static void usage()
{
fprintf(stderr, "Usage: "
- "sg_requests [--desc] [--help] [--hex] [--num=NUM] [--raw]\n"
+ "sg_requests [--desc] [--help] [--hex] [--num=NUM] [--progress] "
+ "[--raw]\n"
" [--status] [--time] [--verbose] [--version] "
"DEVICE\n"
" where:\n"
@@ -80,6 +93,8 @@ static void usage()
" --hex|-H output in hexadecimal\n"
" --num=NUM|-n NUM number of REQUEST SENSE commands "
"to send (def: 1)\n"
+ " --progress|-p output a progress indication (percentage) "
+ "if available\n"
" --raw|-r output in binary (to stdout)\n"
" --status|-s set exit status from parameter data "
"(def: only set\n"
@@ -103,11 +118,12 @@ static void dStrRaw(const char* str, int len)
int main(int argc, char * argv[])
{
- int sg_fd, res, c, resp_len, k;
+ int sg_fd, res, c, resp_len, k, progress;
unsigned char requestSenseBuff[REQUEST_SENSE_BUFF_LEN];
int desc = 0;
int num_rs = 1;
int do_hex = 0;
+ int do_progress = 0;
int do_raw = 0;
int do_status = 0;
int do_time = 0;
@@ -121,7 +137,7 @@ int main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhHn:rstvV", long_options,
+ c = getopt_long(argc, argv, "dhHn:prstvV", long_options,
&option_index);
if (c == -1)
break;
@@ -144,6 +160,9 @@ int main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
break;
+ case 'p':
+ ++do_progress;
+ break;
case 'r':
++do_raw;
break;
@@ -190,6 +209,62 @@ int main(int argc, char * argv[])
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
+ if (do_progress) {
+ for (k = 0; k < num_rs; ++k) {
+ if (k > 0)
+ sleep_for(30);
+ memset(requestSenseBuff, 0x0, sizeof(requestSenseBuff));
+ res = sg_ll_request_sense(sg_fd, desc, requestSenseBuff,
+ sizeof(requestSenseBuff), 1, verbose);
+ if (res) {
+ ret = res;
+ if (SG_LIB_CAT_INVALID_OP == res)
+ fprintf(stderr, "Request Sense command not supported\n");
+ else if (SG_LIB_CAT_ILLEGAL_REQ == res)
+ fprintf(stderr, "bad field in Request Sense cdb\n");
+ else if (SG_LIB_CAT_ABORTED_COMMAND == res)
+ fprintf(stderr, "Request Sense, aborted command\n");
+ else {
+ fprintf(stderr, "Request Sense command unexpectedly "
+ "failed\n");
+ if (0 == verbose)
+ fprintf(stderr, " try the '-v' option for "
+ "more information\n");
+ }
+ break;
+ }
+ resp_len = requestSenseBuff[7] + 8;
+ if (verbose > 1) {
+ fprintf(stderr, "Parameter data in hex\n");
+ dStrHex((const char *)requestSenseBuff, resp_len, 1);
+ }
+ progress = -1;
+#if 1
+{
+ static int p1 = 0x22;
+
+ requestSenseBuff[15] = 0x80;
+ if (k > 0)
+ p1 += 0x08;
+ requestSenseBuff[16] = p1;
+ requestSenseBuff[17] = 0x0;
+}
+#endif
+ sg_get_sense_progress_fld(requestSenseBuff, resp_len,
+ &progress);
+ if (progress < 0) {
+ ret = res;
+ if (verbose > 1)
+ fprintf(stderr, "No progress indication found, "
+ "iteration %d\n", k + 1);
+ /* N.B. exits first time there isn't a progress indication */
+ break;
+ } else
+ printf("Progress indication: %d%% done\n",
+ (progress * 100) / 65536);
+ }
+ goto finish;
+ }
#ifndef SG3_UTILS_MINGW
if (do_time) {
@@ -215,7 +290,7 @@ int main(int argc, char * argv[])
else if (1 == num_rs) {
fprintf(stderr, "Decode parameter data as sense data:\n");
sg_print_sense(NULL, requestSenseBuff, resp_len, 0);
- if (verbose) {
+ if (verbose > 1) {
fprintf(stderr, "\nParameter data in hex\n");
dStrHex((const char *)requestSenseBuff, resp_len, 1);
}
@@ -270,6 +345,8 @@ int main(int argc, char * argv[])
printf("\n");
}
#endif
+
+finish:
res = sg_cmds_close_device(sg_fd);
if (res < 0) {
fprintf(stderr, "close error: %s\n", safe_strerror(-res));
diff --git a/src/sg_start.c b/src/sg_start.c
index 305452cd..9d52a50c 100644
--- a/src/sg_start.c
+++ b/src/sg_start.c
@@ -30,7 +30,7 @@
*/
-static char * version_str = "0.56 20080316"; /* sbc3r13+08-139r1; mmc6r01a */
+static char * version_str = "0.57 20080325"; /* sbc3r14; mmc6r01a */
static struct option long_options[] = {
{"eject", 0, 0, 'e'},
diff --git a/utils/Makefile b/utils/Makefile
index 2b519bc5..3bf73659 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -1,18 +1,19 @@
SHELL = /bin/sh
-PREFIX=/usr/local
+PREFIX=/usr
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
-MANDIR=$(DESTDIR)/$(PREFIX)/man
+MANDIR=$(DESTDIR)/$(PREFIX)/share/man
CC = gcc
LD = gcc
-EXECS = hxascdmp sg_chk_asc
+EXECS = hxascdmp
+# EXECS = hxascdmp sg_chk_asc
-MAN_PGS =
-MAN_PREF = man8
+MAN_PGS = hxascdmp.1
+MAN_PREF = man1
-CFLAGS = -g -O2 -W
+CFLAGS = -g -O2 -W -Wall
# CFLAGS = -g -O2 -W -pedantic -std=c99
LDFLAGS =
@@ -29,6 +30,7 @@ clean:
hxascdmp: hxascdmp.o
$(LD) -o $@ $(LDFLAGS) $^
+# building sg_chk_asc depends on a prior successful make in ../lib
sg_chk_asc: sg_chk_asc.o ../lib/sg_lib.o ../lib/sg_lib_data.o
$(LD) -o $@ $(LDFLAGS) $^
diff --git a/utils/README b/utils/README
index 19c70a56..3faef309 100644
--- a/utils/README
+++ b/utils/README
@@ -3,7 +3,8 @@ This directory contains these utilities:
which is sent to stdout. The incoming binary stream can either be
from a file or, in the absence of a file name, from stdin. Similar to
the Unix "od" command. By default, it decodes 16 bytes per line with
- an ASCII interpretation to the right of each line.
+ an ASCII interpretation to the right of each line. See its
+ hxascdmp(1) man page.
- sg_chk_asc: utility decodes the SCSI additional sense code table
found at http://www.t10.org/lists/asc-num.txt and checks it
against the table found in sg_lib.c in the lib/ subdirectory.
@@ -21,4 +22,4 @@ the lib/ subdirectory. One way to meet that requirement is to execute
Doug Gilbert
-11th January 2008
+26th March 2008
diff --git a/utils/hxascdmp.1 b/utils/hxascdmp.1
new file mode 100644
index 00000000..6412b4cf
--- /dev/null
+++ b/utils/hxascdmp.1
@@ -0,0 +1,87 @@
+.TH HXASCDMP "1" "March 2008" "sg3_utils\-1.26" SG3_UTILS
+.SH NAME
+hxascdmp \- hexadecimal ASCII dump
+.SH SYNOPSIS
+.B hxascdmp
+[\fI\-b=BPL\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-V\fR]
+[\fIFILE+\fR]
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+This utility reads one or more \fIFILE\fR names and dumps them in hexadecimal
+and ASCII to stdout. If no \fIFILE\fR is given then stdin is read instead;
+reading continues (or stalls) until an EOF is received.
+.PP
+The default format is to start each line with the hexadecimal address (offset
+from the start of file) followed by 16 hexadecimal bytes separated by a
+single space (apart from the 8th and 9th bytes which are separated by two
+spaces). If the \fI\-H\fR is not given, there is then a string of 16 ASCII
+characters corresponding to the hexadecimal bytes earlier in the line; only
+bytes in the range 0x20 to 0x7e are printed in ASCII, other bytes values are
+printed as '.' . Each \fIFILE\fR name that appears on the command line is
+printed on a separate line prior to that file's hexadecimal ASCII dump.
+.PP
+This utility is pretty close to the 'hexdump -C' variant of BSD's
+.B hexdump(1)
+command.
+.SH OPTIONS
+.TP
+\fB\-b\fR=\fIBPL\fR
+where \fIBPL\fR specifies the number of bytes per line. The default value is
+16. 16 bytes per line is just enough to allow the address, 16 bytes in
+hexadecimal followed by 16 bytes as ASCII to fit on a standard 80 column
+wide terminal.
+.TP
+\fB\-h\fR
+output the usage message then exit.
+.TP
+\fB\-H\fR
+output hexadecimal only (i.e. don't place an ASCII representation at the
+end of each line).
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.SH EXIT STATUS
+The exit status of hxascdmp is 0 when it is successful. If any of the
+given \fIFILE\fR names cannot be opened then the exit status is 1.
+.SH EXAMPLES
+First we manufacture a short file with a mix of data in it: mostly ASCII with
+some control characters and 0xaa (which the echo command only accepts in
+octal (0252):
+.PP
+ $ echo -e "three blind mice,\t\r\0252" > 3bm.txt
+.PP
+Now we use this utility to see exactly what is in the file. To avoid
+problems with line wrapping, the bytes per line option is set to 8:
+.PP
+ $ hxascdmp -b=8 3bm.txt
+.br
+ASCII hex dump of file: 3bm.txt
+.br
+ 00 74 68 72 65 65 20 62 6c three bl
+.br
+ 08 69 6e 64 20 6d 69 63 65 ind mice
+.br
+ 10 2c 09 0d aa 0a ,....
+.PP
+Using the same file, use this utility to output only hexadecimal formatted
+16 bytes per line.
+.PP
+ $ hxascdmp -H 3bm.txt
+.br
+hex dump of file: 3bm.txt
+.br
+ 00 74 68 72 65 65 20 62 6c 69 6e 64 20 6d 69 63 65
+.br
+ 10 2c 09 0d aa 0a
+.SH AUTHORS
+Written by Douglas Gilbert.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2004\-2008 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.
+.SH "SEE ALSO"
+.B hexdump(1)
diff --git a/utils/hxascdmp.c b/utils/hxascdmp.c
index dedeae80..fb636950 100644
--- a/utils/hxascdmp.c
+++ b/utils/hxascdmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Douglas Gilbert.
+ * Copyright (c) 2004-2008 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,15 @@
static int bytes_per_line = DEF_BYTES_PER_LINE;
+static const char * version_str = "1.10 20080321";
+
#define CHARS_PER_HEX_BYTE 3
#define BINARY_START_COL 6
#define MAX_LINE_LENGTH 257
-static void dStrHex(const char* str, int len, long start)
+static void
+dStrHex(const char* str, int len, long start)
{
const char* p = str;
unsigned char c;
@@ -62,8 +65,7 @@ static void dStrHex(const char* str, int len, long start)
return;
line_length = BINARY_START_COL +
(bytes_per_line * (1 + CHARS_PER_HEX_BYTE)) + 7;
- if (line_length >= MAX_LINE_LENGTH)
- {
+ if (line_length >= MAX_LINE_LENGTH) {
fprintf(stderr, "bytes_per_line causes maximum line length of %d "
"to be exceeded\n", MAX_LINE_LENGTH);
return;
@@ -75,8 +77,7 @@ static void dStrHex(const char* str, int len, long start)
if (bpos >= ((bpstart + (midline_space * CHARS_PER_HEX_BYTE))))
bpos++;
- for(i = 0; i < len; i++)
- {
+ for(i = 0; i < len; i++) {
c = *p++;
bpos += CHARS_PER_HEX_BYTE;
if (bpos == (bpstart + (midline_space * CHARS_PER_HEX_BYTE)))
@@ -86,8 +87,7 @@ static void dStrHex(const char* str, int len, long start)
if ((c < ' ') || (c >= 0x7f))
c='.';
buff[cpos++] = c;
- if (cpos >= (cpstart + bytes_per_line))
- {
+ if (cpos >= (cpstart + bytes_per_line)) {
printf("%s\n", buff);
bpos = bpstart;
cpos = cpstart;
@@ -101,22 +101,76 @@ static void dStrHex(const char* str, int len, long start)
printf("%s\n", buff);
}
+static void
+dStrHexOnly(const char* str, int len, long start)
+{
+ const char* p = str;
+ unsigned char c;
+ char buff[MAX_LINE_LENGTH];
+ long a = start;
+ const int bpstart = BINARY_START_COL;
+ int bpos = bpstart;
+ int midline_space = (bytes_per_line / 2) + 1;
+ int i, k, line_length;
+
+ if (len <= 0)
+ return;
+ line_length = BINARY_START_COL +
+ (bytes_per_line * CHARS_PER_HEX_BYTE) + 4;
+ if (line_length >= MAX_LINE_LENGTH) {
+ fprintf(stderr, "bytes_per_line causes maximum line length of %d "
+ "to be exceeded\n", MAX_LINE_LENGTH);
+ return;
+ }
+ memset(buff, ' ', line_length);
+ buff[line_length] = '\0';
+ k = sprintf(buff + 1, "%.2lx", a);
+ buff[k + 1] = ' ';
+ if (bpos >= ((bpstart + (midline_space * CHARS_PER_HEX_BYTE))))
+ bpos++;
+
+ for(i = 0; i < len; i++) {
+ c = *p++;
+ bpos += CHARS_PER_HEX_BYTE;
+ if (bpos == (bpstart + (midline_space * CHARS_PER_HEX_BYTE)))
+ bpos++;
+ sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
+ buff[bpos + 2] = ' ';
+ if (bpos >= (bpstart + (bytes_per_line * CHARS_PER_HEX_BYTE)))
+ {
+ printf("%s\n", buff);
+ bpos = bpstart;
+ a += bytes_per_line;
+ memset(buff,' ', line_length);
+ k = sprintf(buff + 1, "%.2lx", a);
+ buff[k + 1] = ' ';
+ }
+ }
+ if (bpos > bpstart)
+ printf("%s\n", buff);
+}
-static void usage()
+static void
+usage()
{
- fprintf(stderr, "Usage: hxascdmp [-b=<n>] [-h] [-?] [file+] \n");
- fprintf(stderr, " Sends hex ASCII dump of stdin/file to stdout\n");
+ fprintf(stderr, "Usage: hxascdmp [-b=<n>] [-h] [-H] [-V] [-?] "
+ "[<file>+]\n");
fprintf(stderr, " where:\n");
- fprintf(stderr, " -b=<n> bytes per line to display "
+ fprintf(stderr, " -b=<n> bytes per line to display "
"(def: 16)\n");
- fprintf(stderr, " -h print this usage message\n");
- fprintf(stderr, " -? print this usage message\n");
- fprintf(stderr, " file reads file(s) and outputs it "
+ fprintf(stderr, " -h print this usage message\n");
+ fprintf(stderr, " -H print hex only (i.e. no ASCII "
+ "to right)\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 "
"as hex ASCII\n");
- fprintf(stderr, " if no files reads stdin\n");
+ fprintf(stderr, " if no <file> then reads stdin\n\n");
+ fprintf(stderr, "Sends hex ASCII dump of stdin/file to stdout\n");
}
-int main(int argc, const char ** argv)
+int
+main(int argc, const char ** argv)
{
char buff[8192];
int num = 8192;
@@ -124,15 +178,14 @@ int main(int argc, const char ** argv)
int res, k, u;
int inFile = 0; /* stdin */
int doHelp = 0;
+ int doHex = 0;
int hasFilename = 0;
+ int ret = 0;
- for (k = 1; k < argc; k++)
- {
- if (0 == strncmp("-b=", argv[k], 3))
- {
+ for (k = 1; k < argc; k++) {
+ if (0 == strncmp("-b=", argv[k], 3)) {
res = sscanf(argv[k] + 3, "%d", &u);
- if ((1 != res) || (u < 1))
- {
+ if ((1 != res) || (u < 1)) {
printf("Bad value after '-b' switch\n");
usage();
return 1;
@@ -141,22 +194,23 @@ int main(int argc, const char ** argv)
}
else if (0 == strcmp("-h", argv[k]))
doHelp = 1;
- else if (0 == strcmp("-?", argv[k]))
+ else if (0 == strcmp("-H", argv[k]))
+ doHex = 1;
+ else if (0 == strcmp("-V", argv[k])) {
+ fprintf(stderr, "%s\n", version_str);
+ return 0;
+ } else if (0 == strcmp("-?", argv[k]))
doHelp = 1;
- else if (*argv[k] == '-')
- {
+ else if (*argv[k] == '-') {
fprintf(stderr, "unknown switch: %s\n", argv[k]);
usage();
return 1;
- }
- else
- {
+ } else {
hasFilename = 1;
break;
}
}
- if (doHelp)
- {
+ if (doHelp) {
usage();
return 0;
}
@@ -165,36 +219,36 @@ int main(int argc, const char ** argv)
if (0 != (num % bytes_per_line))
num = (num / bytes_per_line) * bytes_per_line;
- if (hasFilename)
- {
+ if (hasFilename) {
for ( ; k < argc; k++)
{
inFile = open(argv[k], O_RDONLY);
- if (inFile < 0)
- {
+ if (inFile < 0) {
fprintf(stderr, "Couldn't open file: %s\n", argv[k]);
- }
- else
- {
+ ret = 1;
+ } else {
start = 0;
- printf("ASCII hex dump of file: %s\n", argv[k]);
- while ((res = read(inFile, buff, num)) > 0)
- {
- dStrHex(buff, res, start);
+ printf("%shex dump of file: %s\n",
+ (doHex ? "" : "ASCII "), argv[k]);
+ while ((res = read(inFile, buff, num)) > 0) {
+ if (doHex)
+ dStrHexOnly(buff, res, start);
+ else
+ dStrHex(buff, res, start);
start += (long)res;
}
}
close(inFile);
printf("\n");
}
- }
- else
- {
- while ((res = read(inFile, buff, num)) > 0)
- {
- dStrHex(buff, res, start);
+ } else {
+ while ((res = read(inFile, buff, num)) > 0) {
+ if (doHex)
+ dStrHexOnly(buff, res, start);
+ else
+ dStrHex(buff, res, start);
start += (long)res;
}
}
- return 0;
+ return ret;
}