aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--doc/sg_raw.828
-rw-r--r--include/sg_unaligned.h51
-rw-r--r--lib/sg_lib_data.c8
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/sg_logs.c2
-rw-r--r--src/sg_opcodes.c2
-rw-r--r--src/sg_raw.c145
-rw-r--r--src/sg_referrals.c2
-rw-r--r--src/sg_rtpg.c2
-rw-r--r--src/sg_vpd.c2
-rw-r--r--utils/tst_sg_lib.c94
14 files changed, 268 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index bbb07396..bfa6057d 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.42 [20151126] [svn: r648]
+Changelog for sg3_utils-1.42 [20151127] [svn: r649]
- sg_stpg: fix truncation of target port field
- sg_inq: cope with unicode strings, udev fixes
- update version descriptor list to 20151101
@@ -16,7 +16,9 @@ Changelog for sg3_utils-1.42 [20151126] [svn: r648]
Minimum and Threshold percentage fields
- sg_sanitize: add --znr option (sbc4r07)
- sg_rep_zones: add --partial option (zbc-r04)
- - sg_lib_data: sync asc/ascq codes with T10 20151101
+ - sg_raw: document length relationships
+ - sg_lib_data: sync asc/ascq codes with T10 20151126
+ - sg_unaligned.h: add 48 bit support
Changelog for sg3_utils-1.41 [20150511] [svn: r644]
- sg_zone: new utility for open, close and finish
diff --git a/README b/README
index b5b391b2..8695d06f 100644
--- a/README
+++ b/README
@@ -412,4 +412,4 @@ See http://sg.danny.cz/sg/tools.html
Douglas Gilbert
-24th November 2015
+27th November 2015
diff --git a/debian/changelog b/debian/changelog
index a659124b..06c1a8f7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.42-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Tue, 24 Nov 2015 17:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Fri, 27 Nov 2015 17:00:00 -0500
sg3-utils (1.41-0.1) unstable; urgency=low
diff --git a/doc/sg_raw.8 b/doc/sg_raw.8
index fa3ba844..16d6437a 100644
--- a/doc/sg_raw.8
+++ b/doc/sg_raw.8
@@ -1,4 +1,4 @@
-.TH SG_RAW "8" "October 2014" "sg3_utils\-1.40" SG3_UTILS
+.TH SG_RAW "8" "November 2015" "sg3_utils\-1.42" SG3_UTILS
.SH NAME
sg_raw \- send arbitrary SCSI command to a device
.SH SYNOPSIS
@@ -47,7 +47,18 @@ This option is ignored if \fB\-\-request\fR is not specified.
\fB\-r\fR, \fB\-\-request\fR=\fIRLEN\fR
Expect to receive up to \fIRLEN\fR bytes of data from the \fIDEVICE\fR.
\fIRLEN\fR may be suffixed with 'k' to use kilobytes (1024 bytes) instead
-of bytes.
+of bytes. \fIRLEN\fR is decimal unless it has a leading '0x' or a
+trailing 'h'.
+.br
+If \fIRLEN\fR is too small (i.e. either smaller than indicated by the
+cdb (typically the "allocation length" field) and/or smaller than the
+\fIDEVICE\fR tries to send back) then the HBA driver may complain. Making
+\fIRLEN\fR larger than required should cause no problems. Most
+SCSI "data\-in" commands return a data block that contains (in its early
+bytes) a length that the \fIDEVICE\fR would "like" to send back if
+the "allocation length" field in the cdb is large enough. In practice, the
+\fIDEVICE\fR will return no more bytes than indicated in the "allocation
+length" field of the cdb.
.TP
\fB\-R\fR, \fB\-\-readonly\fR
Open \fIDEVICE\fR read\-only. The default (without this option) is to open
@@ -55,7 +66,14 @@ it read\-write.
.TP
\fB\-s\fR, \fB\-\-send\fR=\fISLEN\fR
Read \fISLEN\fR bytes of data, either from stdin or from a file, and send
-them to the \fIDEVICE\fR.
+them to the \fIDEVICE\fR. In the SCSI transport, \fISLEN\fR becomes the
+length (in bytes) of the "data\-out" buffer. \fISLEN\fR is decimal unless
+it has a leading '0x' or a trailing 'h'.
+.br
+It is the responsibility of the user to make sure that the "data\-out"
+length implied or stated in the cdb matches \fISLEN\fR. Note that some
+common SCSI commands such as WRITE(10) have a "transfer length" field whose
+units are logical blocks (which are often 512 bytes long).
.TP
\fB\-t\fR, \fB\-\-timeout\fR=\fISEC\fR
Wait up to \fISEC\fR seconds for command completion (default: 20).
@@ -83,7 +101,7 @@ SG_IO ioctl cannot handle CDBs longer than 16 bytes, and the sg driver
can handle longer CDBs from lk 3.17 .
.PP
The CDB command name defined by T10 for the given CDB is shown if
-the '\-vvv' option is given. The command line syntax still needs to be
+the '\-vv' option is given. The command line syntax still needs to be
correct, so /dev/null may be used for the \fIDEVICE\fR since the CDB
command name decoding is done before the \fIDEVICE\fR is checked.
.SH EXAMPLES
@@ -133,7 +151,7 @@ Written by Ingo van Lil
.SH "REPORTING BUGS"
Report bugs to <inguin at gmx dot de>.
.SH COPYRIGHT
-Copyright \(co 2001\-2014 Ingo van Lil
+Copyright \(co 2001\-2015 Ingo van Lil
.br
This software is distributed under the GPL version 2. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/include/sg_unaligned.h b/include/sg_unaligned.h
index 3060ba46..a8410519 100644
--- a/include/sg_unaligned.h
+++ b/include/sg_unaligned.h
@@ -2,7 +2,7 @@
#define SG_UNALIGNED_H
/*
- * Copyright (c) 2014 Douglas Gilbert.
+ * Copyright (c) 2014-2015 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.
@@ -31,6 +31,13 @@ static inline uint32_t __get_unaligned_be32(const uint8_t *p)
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}
+/* Assume 48 bit value placed in uint64_t */
+static inline uint64_t __get_unaligned_be48(const uint8_t *p)
+{
+ return (uint64_t)__get_unaligned_be16(p) << 32 |
+ __get_unaligned_be32(p + 2);
+}
+
static inline uint64_t __get_unaligned_be64(const uint8_t *p)
{
return (uint64_t)__get_unaligned_be32(p) << 32 |
@@ -49,6 +56,13 @@ static inline void __put_unaligned_be32(uint32_t val, uint8_t *p)
__put_unaligned_be16(val, p + 2);
}
+/* Assume 48 bit value placed in uint64_t */
+static inline void __put_unaligned_be48(uint64_t val, uint8_t *p)
+{
+ __put_unaligned_be16(val >> 32, p);
+ __put_unaligned_be32(val, p + 2);
+}
+
static inline void __put_unaligned_be64(uint64_t val, uint8_t *p)
{
__put_unaligned_be32(val >> 32, p);
@@ -70,6 +84,12 @@ static inline uint32_t sg_get_unaligned_be32(const void *p)
return __get_unaligned_be32((const uint8_t *)p);
}
+/* Assume 48 bit value placed in uint64_t */
+static inline uint64_t sg_get_unaligned_be48(const void *p)
+{
+ return __get_unaligned_be48((const uint8_t *)p);
+}
+
static inline uint64_t sg_get_unaligned_be64(const void *p)
{
return __get_unaligned_be64((const uint8_t *)p);
@@ -92,6 +112,12 @@ static inline void sg_put_unaligned_be32(uint32_t val, void *p)
__put_unaligned_be32(val, (uint8_t *)p);
}
+/* Assume 48 bit value placed in uint64_t */
+static inline void sg_put_unaligned_be48(uint64_t val, void *p)
+{
+ __put_unaligned_be48(val, (uint8_t *)p);
+}
+
static inline void sg_put_unaligned_be64(uint64_t val, void *p)
{
__put_unaligned_be64(val, (uint8_t *)p);
@@ -177,9 +203,10 @@ static inline uint16_t sg_get_unaligned_le16(const void *p)
return __get_unaligned_le16((const uint8_t *)p);
}
-static inline uint32_t sg_get_unaligned_le24(const uint8_t *p)
+static inline uint32_t sg_get_unaligned_le24(const void *p)
{
- return p[2] << 16 | p[1] << 8 | p[0];
+ return (uint32_t)__get_unaligned_le16(p) |
+ ((const uint8_t *)p)[2] << 16;
}
static inline uint32_t sg_get_unaligned_le32(const void *p)
@@ -187,6 +214,13 @@ static inline uint32_t sg_get_unaligned_le32(const void *p)
return __get_unaligned_le32((const uint8_t *)p);
}
+/* Assume 48 bit value placed in uint64_t */
+static inline uint64_t sg_get_unaligned_le48(const void *p)
+{
+ return (uint64_t)__get_unaligned_le16((const uint8_t *)p + 4) << 32 |
+ __get_unaligned_le32(p);
+}
+
static inline uint64_t sg_get_unaligned_le64(const void *p)
{
return __get_unaligned_le64((const uint8_t *)p);
@@ -209,6 +243,17 @@ static inline void sg_put_unaligned_le32(uint32_t val, void *p)
__put_unaligned_le32(val, (uint8_t *)p);
}
+/* Assume 48 bit value placed in uint64_t */
+static inline void sg_put_unaligned_le48(uint64_t val, void *p)
+{
+ ((uint8_t *)p)[5] = (val >> 40) & 0xff;
+ ((uint8_t *)p)[4] = (val >> 32) & 0xff;
+ ((uint8_t *)p)[3] = (val >> 24) & 0xff;
+ ((uint8_t *)p)[2] = (val >> 16) & 0xff;
+ ((uint8_t *)p)[1] = (val >> 8) & 0xff;
+ ((uint8_t *)p)[0] = val & 0xff;
+}
+
static inline void sg_put_unaligned_le64(uint64_t val, void *p)
{
__put_unaligned_le64(val, (uint8_t *)p);
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index c41c847d..11b2c001 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -17,7 +17,7 @@
#endif
-const char * sg_lib_version_str = "2.15 20151126"; /* spc5r06, sbc4r09 */
+const char * sg_lib_version_str = "2.16 20151126"; /* spc5r07, sbc4r09 */
/* indexed by pdt; those that map to own index do not decay */
@@ -107,7 +107,7 @@ struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0x3b, 0, "Write buffer"},
{0x3c, 0, "Read buffer(10)"},
{0x3d, 0, "Update block"},
- {0x3e, 0, "Read long(10)"}, /* obsolete in SBC-4 r7 */
+ {0x3e, 0, "Read long(10)"}, /* obsolete in SBC-4 r7 */
{0x3f, 0, "Write long(10)"}, /* SBC-3 r31 recommends Write long(16) */
{0x40, 0, "Change definition"}, /* obsolete in SPC-4 r11 */
{0x41, 0, "Write same(10)"}, /* SBC-3 r31 recommends Write same(16) */
@@ -314,7 +314,7 @@ struct sg_lib_value_name_t sg_lib_serv_out12_arr[] = {
/* Service action in(16) [0x9e] service actions */
struct sg_lib_value_name_t sg_lib_serv_in16_arr[] = {
{0x10, 0, "Read capacity(16)"},
- {0x11, 0, "Read long(16)"}, /* obsolete in SBC-4 r7 */
+ {0x11, 0, "Read long(16)"}, /* obsolete in SBC-4 r7 */
{0x12, 0, "Get LBA status"},
{0x13, 0, "Report referrals"},
{0x14, 0, "Stream control"},
@@ -798,6 +798,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x20,0x0C,"Illegal command when not in append-only mode"},
{0x20,0x0D,"Not an administrative logical unit"},
{0x20,0x0E,"Not a subsidiary logical unit"},
+ {0x20,0x0F,"Not a conglomerate logical unit"},
{0x21,0x00,"Logical block address out of range"},
{0x21,0x01,"Invalid element address"},
{0x21,0x02,"Invalid address for write"},
@@ -806,6 +807,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x21,0x05,"Write boundary violation"},
{0x21,0x06,"Attempt to read invalid data"},
{0x21,0x07,"Read boundary violation"},
+ {0x21,0x08,"Misaligned write command"},
{0x22,0x00,"Illegal function (use 20 00, 24 00, or 26 00)"},
{0x23,0x00,"Invalid token operation, cause not reportable"},
{0x23,0x01,"Invalid token operation, unsupported token type"},
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 81dc8c66..93385919 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Tue Nov 24 2015 - dgilbert at interlog dot com
+* Fri Nov 27 2015 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.42
diff --git a/src/sg_logs.c b/src/sg_logs.c
index 29b4bef4..745b6954 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -31,7 +31,7 @@
#include "sg_unaligned.h"
#include "sg_pt.h" /* needed for scsi_pt_win32_direct() */
-static const char * version_str = "1.33 20151123"; /* spc5r03 + sbc4r05 */
+static const char * version_str = "1.34 20151127"; /* spc5r07 + sbc4r05 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
diff --git a/src/sg_opcodes.c b/src/sg_opcodes.c
index 34c00053..ed47b178 100644
--- a/src/sg_opcodes.c
+++ b/src/sg_opcodes.c
@@ -26,7 +26,7 @@
#include "sg_pt.h"
-static const char * version_str = "0.43 20150511"; /* spc4r37 */
+static const char * version_str = "0.44 20151127"; /* spc5r07 */
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 510684fa..3b950d57 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -15,6 +15,7 @@
#define _XOPEN_SOURCE 600 /* clear up posix_memalign() warning */
#include <stdlib.h>
+#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
@@ -28,7 +29,7 @@
#include "sg_lib.h"
#include "sg_pt.h"
-#define SG_RAW_VERSION "0.4.12 (2014-12-27)"
+#define SG_RAW_VERSION "0.4.13 (2015-11-27)"
#ifdef SG_LIB_WIN32
#ifndef HAVE_SYSCONF
@@ -86,11 +87,31 @@ struct opts_t {
int do_version;
};
+
+#ifdef __GNUC__
+static int pr2serr(const char * fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+#else
+static int pr2serr(const char * fmt, ...);
+#endif
+
+
+static int
+pr2serr(const char * fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return n;
+}
+
static void
version()
{
- fprintf(stderr,
- "sg_raw " SG_RAW_VERSION "\n"
+ pr2serr("sg_raw " SG_RAW_VERSION "\n"
"Copyright (C) 2007-2012 Ingo van Lil <inguin@gmx.de>\n"
"This is free software. You may redistribute copies of it "
"under the terms of\n"
@@ -102,8 +123,7 @@ version()
static void
usage()
{
- fprintf(stderr,
- "Usage: sg_raw [OPTION]* DEVICE CDB0 CDB1 ...\n"
+ pr2serr("Usage: sg_raw [OPTION]* DEVICE CDB0 CDB1 ...\n"
"\n"
"Options:\n"
" -b, --binary Dump data in binary form, even when "
@@ -126,8 +146,8 @@ usage()
" -V, --version Show version information and exit\n"
"\n"
"Between 6 and 256 command bytes (two hex digits each) can be "
- "specified\nand will be sent to DEVICE. Bidirectional commands "
- "accepted.\n\n"
+ "specified\nand will be sent to DEVICE. Lengths RLEN and SLEN "
+ "are decimal by\ndefault. Bidirectional commands accepted.\n\n"
"Simple example: Perform INQUIRY on /dev/sg0:\n"
" sg_raw -r 1k /dev/sg0 12 00 00 00 60 00\n");
}
@@ -152,7 +172,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
return 0;
case 'i':
if (op->dataout_file) {
- fprintf(stderr, "Too many '--infile=' options\n");
+ pr2serr("Too many '--infile=' options\n");
return SG_LIB_SYNTAX_ERROR;
}
op->dataout_file = optarg;
@@ -160,7 +180,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
case 'k':
n = sg_get_num(optarg);
if (n < 0) {
- fprintf(stderr, "Invalid argument to '--skip'\n");
+ pr2serr("Invalid argument to '--skip'\n");
return SG_LIB_SYNTAX_ERROR;
}
op->dataout_offset = n;
@@ -170,7 +190,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
break;
case 'o':
if (op->datain_file) {
- fprintf(stderr, "Too many '--outfile=' options\n");
+ pr2serr("Too many '--outfile=' options\n");
return SG_LIB_SYNTAX_ERROR;
}
op->datain_file = optarg;
@@ -179,7 +199,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
op->do_datain = 1;
n = sg_get_num(optarg);
if (n < 0 || n > MAX_SCSI_DXLEN) {
- fprintf(stderr, "Invalid argument to '--request'\n");
+ pr2serr("Invalid argument to '--request'\n");
return SG_LIB_SYNTAX_ERROR;
}
op->datain_len = n;
@@ -191,7 +211,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
op->do_dataout = 1;
n = sg_get_num(optarg);
if (n < 0 || n > MAX_SCSI_DXLEN) {
- fprintf(stderr, "Invalid argument to '--send'\n");
+ pr2serr("Invalid argument to '--send'\n");
return SG_LIB_SYNTAX_ERROR;
}
op->dataout_len = n;
@@ -199,7 +219,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
case 't':
n = sg_get_num(optarg);
if (n < 0) {
- fprintf(stderr, "Invalid argument to '--timeout'\n");
+ pr2serr("Invalid argument to '--timeout'\n");
return SG_LIB_SYNTAX_ERROR;
}
op->timeout = n;
@@ -216,7 +236,7 @@ process_cl(struct opts_t * op, int argc, char *argv[])
}
if (optind >= argc) {
- fprintf(stderr, "No device specified\n");
+ pr2serr("No device specified\n");
return SG_LIB_SYNTAX_ERROR;
}
op->device_name = argv[optind];
@@ -227,12 +247,12 @@ process_cl(struct opts_t * op, int argc, char *argv[])
char *endptr;
int cmd = strtol(opt, &endptr, 16);
if (*opt == '\0' || *endptr != '\0' || cmd < 0x00 || cmd > 0xff) {
- fprintf(stderr, "Invalid command byte '%s'\n", opt);
+ pr2serr("Invalid command byte '%s'\n", opt);
return SG_LIB_SYNTAX_ERROR;
}
if (op->cdb_length > MAX_SCSI_CDBSZ) {
- fprintf(stderr, "CDB too long (max. %d bytes)\n", MAX_SCSI_CDBSZ);
+ pr2serr("CDB too long (max. %d bytes)\n", MAX_SCSI_CDBSZ);
return SG_LIB_SYNTAX_ERROR;
}
op->cdb[op->cdb_length] = cmd;
@@ -240,10 +260,10 @@ process_cl(struct opts_t * op, int argc, char *argv[])
}
if (op->cdb_length < MIN_SCSI_CDBSZ) {
- fprintf(stderr, "CDB too short (min. %d bytes)\n", MIN_SCSI_CDBSZ);
+ pr2serr("CDB too short (min. %d bytes)\n", MIN_SCSI_CDBSZ);
return SG_LIB_SYNTAX_ERROR;
}
- if (op->do_verbose > 2) {
+ if (op->do_verbose > 1) {
int sa;
char b[80];
@@ -262,9 +282,10 @@ process_cl(struct opts_t * op, int argc, char *argv[])
/* Allocate aligned memory (heap) starting on page boundary */
static unsigned char *
-my_memalign(int length, unsigned char ** wrkBuffp)
+my_memalign(int length, unsigned char ** wrkBuffp, const struct opts_t * op)
{
size_t psz;
+ unsigned char * res;
#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
psz = sysconf(_SC_PAGESIZE); /* POSIX.1 (was getpagesize()) */
@@ -281,14 +302,17 @@ my_memalign(int length, unsigned char ** wrkBuffp)
err = posix_memalign(&wp, psz, length);
if (err || (NULL == wp)) {
- fprintf(stderr, "posix_memalign: error [%d], out of memory?\n",
- err);
+ pr2serr("posix_memalign: error [%d], out of memory?\n", err);
return NULL;
}
memset(wp, 0, length);
if (wrkBuffp)
*wrkBuffp = (unsigned char *)wp;
- return (unsigned char *)wp;
+ res = (unsigned char *)wp;
+ if (op->do_verbose > 3)
+ pr2serr("%s: posix, len=%d, wrkBuffp=%p, psz=%d, rp=%p\n",
+ __func__, length, *wrkBuffp, (int)psz, res);
+ return res;
}
#else
{
@@ -301,8 +325,12 @@ my_memalign(int length, unsigned char ** wrkBuffp)
return NULL;
} else if (wrkBuffp)
*wrkBuffp = wrkBuff;
- return (unsigned char *)(((uintptr_t)wrkBuff + psz - 1) &
- (~(psz - 1)));
+ res = (unsigned char *)(((uintptr_t)wrkBuff + psz - 1) &
+ (~(psz - 1)));
+ if (op->do_verbose > 3)
+ pr2serr("%s: hack, len=%d, wrkBuffp=%p, psz=%d, rp=%p\n",
+ __func__, length, *wrkBuffp, (int)psz, res);
+ return res;
}
#endif
}
@@ -328,7 +356,7 @@ skip(int fd, off_t offset)
perror("Error reading input data");
return SG_LIB_FILE_ERROR;
} else if (done == 0) {
- fprintf(stderr, "EOF on input file/stream\n");
+ pr2serr("EOF on input file/stream\n");
return SG_LIB_FILE_ERROR;
} else {
remain -= done;
@@ -367,7 +395,7 @@ fetch_dataout(struct opts_t * op)
}
}
- buf = my_memalign(op->dataout_len, &wrkBuf);
+ buf = my_memalign(op->dataout_len, &wrkBuf, op);
if (buf == NULL) {
perror("malloc");
goto bail;
@@ -378,7 +406,7 @@ fetch_dataout(struct opts_t * op)
perror("Failed to read input data");
goto bail;
} else if (len < op->dataout_len) {
- fprintf(stderr, "EOF on input file/stream\n");
+ pr2serr("EOF on input file/stream\n");
goto bail;
}
@@ -439,7 +467,7 @@ main(int argc, char *argv[])
unsigned char sense_buffer[32];
unsigned char * dxfer_buffer_in = NULL;
unsigned char * dxfer_buffer_out = NULL;
- unsigned char *wrkBuf = NULL;
+ unsigned char * wrkBuf = NULL;
struct opts_t opts;
struct opts_t * op;
char b[128];
@@ -462,29 +490,32 @@ main(int argc, char *argv[])
sg_fd = scsi_pt_open_device(op->device_name, op->readonly,
op->do_verbose);
if (sg_fd < 0) {
- fprintf(stderr, "%s: %s\n", op->device_name, safe_strerror(-sg_fd));
+ pr2serr("%s: %s\n", op->device_name, safe_strerror(-sg_fd));
ret = SG_LIB_FILE_ERROR;
goto done;
}
ptvp = construct_scsi_pt_obj();
if (ptvp == NULL) {
- fprintf(stderr, "out of memory\n");
+ pr2serr("out of memory\n");
ret = SG_LIB_CAT_OTHER;
goto done;
}
if (op->do_verbose) {
- fprintf(stderr, " cdb to send: ");
+ pr2serr(" cdb to send: ");
for (k = 0; k < op->cdb_length; ++k)
- fprintf(stderr, "%02x ", op->cdb[k]);
- fprintf(stderr, "\n");
- if (op->do_verbose > 2) {
+ pr2serr("%02x ", op->cdb[k]);
+ pr2serr("\n");
+ if (op->do_verbose > 1) {
sg_get_command_name(op->cdb, 0, sizeof(b) - 1, b);
b[sizeof(b) - 1] = '\0';
- fprintf(stderr, " Command name: %s\n", b);
+ pr2serr(" Command name: %s\n", b);
}
}
set_scsi_pt_cdb(ptvp, op->cdb, op->cdb_length);
+ if (op->do_verbose > 2)
+ pr2serr("sense_buffer=%p, length=%d\n", sense_buffer,
+ (int)sizeof(sense_buffer));
set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer));
if (op->do_dataout) {
@@ -493,31 +524,37 @@ main(int argc, char *argv[])
ret = SG_LIB_CAT_OTHER;
goto done;
}
+ if (op->do_verbose > 2)
+ pr2serr("dxfer_buffer_out=%p, length=%d\n", dxfer_buffer_out,
+ op->dataout_len);
set_scsi_pt_data_out(ptvp, dxfer_buffer_out, op->dataout_len);
}
if (op->do_datain) {
- dxfer_buffer_in = my_memalign(op->datain_len, &wrkBuf);
+ dxfer_buffer_in = my_memalign(op->datain_len, &wrkBuf, op);
if (dxfer_buffer_in == NULL) {
perror("malloc");
ret = SG_LIB_CAT_OTHER;
goto done;
}
+ if (op->do_verbose > 2)
+ pr2serr("dxfer_buffer_in=%p, length=%d\n", dxfer_buffer_in,
+ op->datain_len);
set_scsi_pt_data_in(ptvp, dxfer_buffer_in, op->datain_len);
}
ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->do_verbose);
if (ret > 0) {
if (SCSI_PT_DO_BAD_PARAMS == ret) {
- fprintf(stderr, "do_scsi_pt: bad pass through setup\n");
+ pr2serr("do_scsi_pt: bad pass through setup\n");
ret = SG_LIB_CAT_OTHER;
} else if (SCSI_PT_DO_TIMEOUT == ret) {
- fprintf(stderr, "do_scsi_pt: timeout\n");
+ pr2serr("do_scsi_pt: timeout\n");
ret = SG_LIB_CAT_TIMEOUT;
} else
ret = SG_LIB_CAT_OTHER;
goto done;
} else if (ret < 0) {
- fprintf(stderr, "do_scsi_pt: %s\n", safe_strerror(-ret));
+ pr2serr("do_scsi_pt: %s\n", safe_strerror(-ret));
ret = SG_LIB_CAT_OTHER;
goto done;
}
@@ -534,35 +571,34 @@ main(int argc, char *argv[])
break;
case SCSI_PT_RESULT_TRANSPORT_ERR:
get_scsi_pt_transport_err_str(ptvp, sizeof(b), b);
- fprintf(stderr, ">>> transport error: %s\n", b);
+ pr2serr(">>> transport error: %s\n", b);
ret = SG_LIB_CAT_OTHER;
break;
case SCSI_PT_RESULT_OS_ERR:
get_scsi_pt_os_err_str(ptvp, sizeof(b), b);
- fprintf(stderr, ">>> os error: %s\n", b);
+ pr2serr(">>> os error: %s\n", b);
ret = SG_LIB_CAT_OTHER;
break;
default:
- fprintf(stderr, ">>> unknown pass through result category (%d)\n",
- res_cat);
+ pr2serr(">>> unknown pass through result category (%d)\n", res_cat);
ret = SG_LIB_CAT_OTHER;
break;
}
status = get_scsi_pt_status_response(ptvp);
- fprintf(stderr, "SCSI Status: ");
+ pr2serr("SCSI Status: ");
sg_print_scsi_status(status);
- fprintf(stderr, "\n\n");
+ pr2serr("\n\n");
if ((SAM_STAT_CHECK_CONDITION == status) && (! op->no_sense)) {
if (SCSI_PT_RESULT_SENSE != res_cat)
slen = get_scsi_pt_sense_len(ptvp);
if (0 == slen)
- fprintf(stderr, ">>> Strange: status is CHECK CONDITION but no "
- "Sense Information\n");
+ pr2serr(">>> Strange: status is CHECK CONDITION but no Sense "
+ "Information\n");
else {
- fprintf(stderr, "Sense Information:\n");
+ pr2serr("Sense Information:\n");
sg_print_sense(NULL, sense_buffer, slen, (op->do_verbose > 0));
- fprintf(stderr, "\n");
+ pr2serr("\n");
}
}
if (SAM_STAT_RESERVATION_CONFLICT == status)
@@ -573,12 +609,12 @@ main(int argc, char *argv[])
if (ret && !(SG_LIB_CAT_RECOVERED == ret ||
SG_LIB_CAT_NO_SENSE == ret))
- fprintf(stderr, "Error %d occurred, no data received\n", ret);
+ pr2serr("Error %d occurred, no data received\n", ret);
else if (data_len == 0) {
- fprintf(stderr, "No data received\n");
+ pr2serr("No data received\n");
} else {
if (op->datain_file == NULL && !op->datain_binary) {
- fprintf(stderr, "Received %d bytes of data:\n", data_len);
+ pr2serr("Received %d bytes of data:\n", data_len);
dStrHexErr((const char *)dxfer_buffer_in, data_len, 0);
} else {
const char * cp = "stdout";
@@ -587,8 +623,7 @@ main(int argc, char *argv[])
! ((1 == strlen(op->datain_file)) &&
('-' == op->datain_file[0])))
cp = op->datain_file;
- fprintf(stderr, "Writing %d bytes of data to %s\n", data_len,
- cp);
+ pr2serr("Writing %d bytes of data to %s\n", data_len, cp);
ret2 = write_dataout(op->datain_file, dxfer_buffer_in,
data_len);
if (0 != ret2) {
@@ -603,7 +638,7 @@ main(int argc, char *argv[])
done:
if (op->do_verbose) {
sg_get_category_sense_str(ret, sizeof(b), b, op->do_verbose - 1);
- fprintf(stderr, "%s\n", b);
+ pr2serr("%s\n", b);
}
if (wrkBuf)
free(wrkBuf);
diff --git a/src/sg_referrals.c b/src/sg_referrals.c
index 6f64c57b..118f604d 100644
--- a/src/sg_referrals.c
+++ b/src/sg_referrals.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2014 Hannes Reinecke.
+ * Copyright (c) 2010-2015 Hannes Reinecke.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
diff --git a/src/sg_rtpg.c b/src/sg_rtpg.c
index 0440c4ea..8ed11ff4 100644
--- a/src/sg_rtpg.c
+++ b/src/sg_rtpg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2014 Christophe Varoqui and Douglas Gilbert.
+ * Copyright (c) 2004-2015 Christophe Varoqui and 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.
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 5a327c7d..56b18935 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -36,7 +36,7 @@
*/
-static const char * version_str = "1.07 20151123"; /* spc5r04 + sbc4r07 */
+static const char * version_str = "1.08 20151127"; /* spc5r07 + sbc4r07 */
/* These structures are duplicates of those of the same name in
diff --git a/utils/tst_sg_lib.c b/utils/tst_sg_lib.c
index 188cf038..f1c20d91 100644
--- a/utils/tst_sg_lib.c
+++ b/utils/tst_sg_lib.c
@@ -14,15 +14,18 @@
#include <getopt.h>
#include <ctype.h>
#include <errno.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
#include "sg_lib.h"
+#include "sg_unaligned.h"
/* A utility program to test sg_libs string handling, specifically
* related to snprintf().
*
*/
-static char * version_str = "1.01 20140427";
+static char * version_str = "1.02 20151127";
#define MAX_LINE_LEN 1024
@@ -33,6 +36,7 @@ static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"printf", 0, 0, 'p'},
{"sense", 0, 0, 's'},
+ {"unaligned", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
{0, 0, 0, 0},
@@ -75,12 +79,13 @@ usage()
{
fprintf(stderr, "Usage: "
"tst_sg_lib [--dstrhex] [--help] [--printf] [--sense] "
- "[--verbose]\n"
- " [--version]\n"
+ "[--unaligned]\n"
+ " [--verbose] [--version]\n"
" where: --dstrhex|-d test dStrHex* variants\n"
" --help|-h print out usage message\n"
" --printf|-p test library printf variants\n"
" --sense|-s test sense data handling\n"
+ " --unaligned|-u test unaligned data handling\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
"Test various parts of sg_lib, see options\n"
@@ -115,6 +120,7 @@ main(int argc, char * argv[])
int do_dstrhex = 0;
int do_printf = 0;
int do_sense = 0;
+ int do_unaligned = 0;
int did_something = 0;
int verbose = 0;
int ret = 0;
@@ -124,7 +130,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "dhpsvV", long_options,
+ c = getopt_long(argc, argv, "dhpsuvV", long_options,
&option_index);
if (c == -1)
break;
@@ -143,6 +149,9 @@ main(int argc, char * argv[])
case 's':
++do_sense;
break;
+ case 'u':
+ ++do_unaligned;
+ break;
case 'v':
++verbose;
break;
@@ -281,6 +290,83 @@ main(int argc, char * argv[])
printf("\n");
}
}
+ if (do_unaligned) {
+ uint16_t u16 = 0x55aa;
+ uint16_t u16r;
+ uint32_t u24 = 0x224488;
+ uint32_t u24r;
+ uint32_t u32 = 0x224488ff;
+ uint32_t u32r;
+ uint64_t u48 = 0x112233445566ULL;
+ uint64_t u48r;
+ uint64_t u64 = 0x1122334455667788ULL;
+ uint64_t u64r;
+ uint8_t u8[64];
+
+ ++did_something;
+ if (verbose)
+ memset(u8, 0, sizeof(u8));
+ printf("u16=0x%" PRIx16 "\n", u16);
+ sg_put_unaligned_le16(u16, u8);
+ printf(" le16:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 2, -1);
+ u16r = sg_get_unaligned_le16(u8);
+ printf(" u16r=0x%" PRIx16 "\n", u16r);
+ sg_put_unaligned_be16(u16, u8);
+ printf(" be16:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 2, -1);
+ u16r = sg_get_unaligned_be16(u8);
+ printf(" u16r=0x%" PRIx16 "\n\n", u16r);
+
+ printf("u24=0x%" PRIx32 "\n", u24);
+ sg_put_unaligned_le24(u24, u8);
+ printf(" le24:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 3, -1);
+ u24r = sg_get_unaligned_le24(u8);
+ printf(" u24r=0x%" PRIx32 "\n", u24r);
+ sg_put_unaligned_be24(u24, u8);
+ printf(" be24:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 3, -1);
+ u24r = sg_get_unaligned_be24(u8);
+ printf(" u24r=0x%" PRIx32 "\n\n", u24r);
+
+ printf("u32=0x%" PRIx32 "\n", u32);
+ sg_put_unaligned_le32(u32, u8);
+ printf(" le32:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 4, -1);
+ u32r = sg_get_unaligned_le32(u8);
+ printf(" u32r=0x%" PRIx32 "\n", u32r);
+ sg_put_unaligned_be32(u32, u8);
+ printf(" be32:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 4, -1);
+ u32r = sg_get_unaligned_be32(u8);
+ printf(" u32r=0x%" PRIx32 "\n\n", u32r);
+
+ printf("u48=0x%" PRIx64 "\n", u48);
+ sg_put_unaligned_le48(u48, u8);
+ printf(" le48:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 6, -1);
+ u48r = sg_get_unaligned_le48(u8);
+ printf(" u48r=0x%" PRIx64 "\n", u48r);
+ sg_put_unaligned_be48(u48, u8);
+ printf(" be48:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 6, -1);
+ u48r = sg_get_unaligned_be48(u8);
+ printf(" u48r=0x%" PRIx64 "\n\n", u48r);
+
+ printf("u64=0x%" PRIx64 "\n", u64);
+ sg_put_unaligned_le64(u64, u8);
+ printf(" le64:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 8, -1);
+ u64r = sg_get_unaligned_le64(u8);
+ printf(" u64r=0x%" PRIx64 "\n", u64r);
+ sg_put_unaligned_be64(u64, u8);
+ printf(" be64:\n");
+ dStrHex((const char *)u8, verbose ? 10 : 8, -1);
+ u64r = sg_get_unaligned_be64(u8);
+ printf(" u64r=0x%" PRIx64 "\n\n", u64r);
+
+ }
if (0 == did_something)
printf("Looks like no tests done, check usage with '-h'\n");