aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-05-09 13:51:44 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2014-05-09 13:51:44 +0000
commit7c5eb1f951e4349bef24fe9056fdc6c190217d95 (patch)
tree439d5ed60b9b7bb123c5c9a1fec6a21417476414
parent7a8a2dc95dec418172e43bdf46c89914f7020219 (diff)
downloadsg3_utils-7c5eb1f951e4349bef24fe9056fdc6c190217d95.tar.gz
sg_ses, sg_persist, sg_logs, sg_readcap, sg_read_buffer, sg_luns: add --readonly option; SG_PERSIST_O_RDONLY ev
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@573 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog12
-rw-r--r--doc/scsi_logging_level.811
-rw-r--r--doc/sg_logs.858
-rw-r--r--doc/sg_luns.823
-rw-r--r--doc/sg_modes.87
-rw-r--r--doc/sg_read_buffer.86
-rw-r--r--doc/sg_readcap.815
-rw-r--r--doc/sg_ses.88
-rwxr-xr-xexamples/sg_persist_tst.sh73
-rw-r--r--src/sg_logs.c70
-rw-r--r--src/sg_luns.c37
-rw-r--r--src/sg_modes.c316
-rw-r--r--src/sg_read_buffer.c33
-rw-r--r--src/sg_readcap.c200
-rw-r--r--src/sg_ses.c15
-rw-r--r--src/sg_write_buffer.c9
16 files changed, 544 insertions, 349 deletions
diff --git a/ChangeLog b/ChangeLog
index 2dca0545..0913e9b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,17 +2,23 @@ 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.39 [20140504] [svn: r572]
+Changelog for sg3_utils-1.39 [20140508] [svn: r573]
- sg_ses: add --eiioe=auto|force option
- fix AES dpage element indexing problems
+ - add --readonly option
- sg_write_buffer: add --bpw=CS option to call
write buffer multiple times for big blobs
- sg_format: add --ip_def option to fully provision
- sg_opcodes: add --mask option
- sg_logs: add --in=FN option for log select params
- add --filter=PARC (parameter code)
- - sg_persist: add --readonly option
- - or environment variable SG_PERSIST_O_RDONLY
+ - add --no_inq for suppress initial INQUIRY call
+ - add --readonly option
+ - sg_persist: add --readonly option, implicit if
+ environment variable SG_PERSIST_O_RDONLY present
+ - sg_read_buffer: add --readonly option
+ - sg_readcap: add --readonly option
+ - sg_luns: add --readonly option
- sginfo: strip trailing spaces from INQUIRY text
- sg_sat_set_features: add --readonly option
- sg_rbuf: add --echo option (to use echo buffer)
diff --git a/doc/scsi_logging_level.8 b/doc/scsi_logging_level.8
index 4256876f..19bf1e3d 100644
--- a/doc/scsi_logging_level.8
+++ b/doc/scsi_logging_level.8
@@ -1,4 +1,4 @@
-.TH SCSI_LOGGING_LEVEL "8" "April 2014" "sg3_utils\-1.39" SG3_UTILS
+.TH SCSI_LOGGING_LEVEL "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
scsi_logging_level \- access Linux SCSI logging level information
.SH SYNOPSIS
@@ -94,6 +94,15 @@ requires root permissions:
.PP
scsi_logging_level \-s \-E 5
.PP
+So as to not interfere with other SCSI subsystem upper level drivers (ULDs)
+which most likely will be active at the same time, the Linux sg driver uses
+SCSI_LOG_TIMEOUT. To see full debugging and trace from the sg driver use:
+.PP
+ scsi_logging_level \-s \-T 7
+.PP
+The output from the sg driver caused by this will go to the system
+logs (e.g. /var/log/syslog). To reduce the amount of output use a number
+lower than 7. Using 0 will turn off the tracing and debug.
.SH AUTHORS
Written by IBM. Small alterations by Douglas Gilbert.
.SH "REPORTING BUGS"
diff --git a/doc/sg_logs.8 b/doc/sg_logs.8
index 62504384..a3b2d34c 100644
--- a/doc/sg_logs.8
+++ b/doc/sg_logs.8
@@ -5,18 +5,19 @@ sg_logs \- access log pages with SCSI LOG SENSE command
.B sg_logs
[\fI\-\-all\fR] [\fI\-\-brief\fR] [\fI\-\-control=PC\fR]
[\fI\-\-filter=PARC\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-in=FN\fR]
-[\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR]
+[\fI\-\-list\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-name\fR] [\fI\-\-no_inq\fR]
[\fI\-\-page=PG[,SPG]\fR] [\fI\-\-paramp=PP\fR] [\fI\-\-pcb\fR]
-[\fI\-\-ppc\fR] [\fI\-\-raw\fR] [\fI\-\-reset\fR] [\fI\-\-select\fR]
-[\fI\-\-sp\fR] [\fI\-\-temperature\fR] [\fI\-\-transport\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-ppc\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-reset\fR]
+[\fI\-\-select\fR] [\fI\-\-sp\fR] [\fI\-\-temperature\fR]
+[\fI\-\-transport\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_logs
[\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-c=PC\fR] [\fI\-f=PARC\fR]
[\fI\-h\fR] [\fI\-H\fR] [\fI\-i=FN\fR] [\fI\-l\fR] [\fI\-L\fR]
[\fI\-m=LEN\fR] [\fI\-n\fR] [\fI\-p=PG[,SPG]\fR] [\fI\-paramp=PP\fR]
-[\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-select\fR] [\fI\-sp\fR]
-[\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR] \fIDEVICE\fR
+[\fI\-pcb\fR] [\fI\-ppc\fR] [\fI\-r\fR] [\fI\-R\fR] [\fI\-select\fR]
+[\fI\-sp\fR] [\fI\-t\fR] [\fI\-T\fR] [\fI\-v\fR] [\fI\-V\fR] [\fI\-?\fR]
+[\fI\-x\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -68,6 +69,9 @@ The \fB\-\-hex\fR option outputs log parameter in hexadecimal rather than
decoding it. If the \fB\-\-hex\fR option is used twice then the leading
address on each kine of hex is removed. If the \fB\-\-raw\fR option is
given then the log parameter is output in binary.
+.br
+Most log pages contain one or more log parameters. Examples of those that
+don't are those pages that list supported log pages.
.TP
\fB\-h\fR, \fB\-\-help\fR
print out the usage message then exit.
@@ -108,6 +112,18 @@ contains no space and may be abbreviated and the value is decimal unless
prefixed by '0x'. Nesting is indicated by leading spaces. This form
is meant to be relatively easy to parse.
.TP
+\fB\-x\fR, \fB\-\-no_inq\fR
+suppresses the output of information obtained from an initial call to the
+INQUIRY command for the standard response. The default (assuming some other
+options that suppress this output are also not given) is to output several
+device identification strings.
+.br
+If this option is given twice (or more) then no INQUIRY command is sent
+hence there will be no device identification string output either. Also the
+peripheral device type (PDT) field will not be obtained so this utility will
+not be able to differentiate between some log pages that are device
+dependent. It will assume a PDT of 0 (i.e. a disk).
+.TP
\fB\-O\fR, \fB\-\-old\fR
switch to older style options.
.TP
@@ -136,6 +152,15 @@ is 0 (i.e. cleared). This bit was made obsolete in SPC\-4 revision 18.
output the response in binary to stdout. Error messages and warnings are
output to stderr.
.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag). The
+default action is to try and open \fIDEVICE\fR read\-write then if that
+fails try to open again with read\-only. However when a read\-write open
+succeeds there may still be unwanted actions on the close (e.g. some OSes
+try to do a SYNCHRONIZE CACHE command). So this option forces a read\-only
+open on \fIDEVICE\fR and if it fails, this utility will exit. Note that
+options like \fI\-\-select\fR most likely need a read\-write open.
+.TP
\fB\-R\fR, \fB\-\-reset\fR
use SCSI LOG SELECT command (PCR bit set) to reset the all log pages (or
the given page). Exactly what is reset depends on the accompanying SP
@@ -195,10 +220,16 @@ Other options that are active with the LOG SELECT command are
APPLICATION CLIENT
This is the name of a log page that acts as a container for data provided
by the user. An application client is a SCSI term for the program that issues
-commands to a SCSI initiator (often known as a Host Bus Adapter (HBA)).
+commands to a SCSI initiator (often known as a Host Bus Adapter (HBA)). So,
+for example, this utility is a SCSI application client.
.PP
-The Application client log page has 64 log parameters with parameters codes
-0 to 63. Each can hold 252 bytes of user binary data.
+The Application Client log page has 64 log parameters with parameters codes
+0 to 63. Each can hold 252 bytes of user binary data. That 252 bytes (or
+less) of user data, with a 4 byte prefix (for a total of 256 bytes) can be
+provided with the \fI\-\-in=FN\fR option. A typical prefix would
+be '0,n,83,fc'. The "n" is the parameter code in hex so the last log
+parameter would be '0,3f,83,fc'. That log parameter could be read back at
+some later time with '\-\-page=0xf \-\-filter=0x<n>'.
.SH NOTES
This utility will usually do a double fetch of log pages with the SCSI LOG
SENSE command. The first fetch requests a 4 byte response (i.e. place 4 in
@@ -355,6 +386,9 @@ sets the Parameter Pointer Control (PPC) bit. Default is 0 (i.e. cleared).
use SCSI LOG SELECT command (PCR bit set) to reset the all log pages (or
the given page). Equivalent to \fI\-\-reset\fR in the main description.
.TP
+\fB\-R\fR
+Equivalent to \fI\-\-readonly\fR in the main description.
+.TP
\fB\-select\fR
use a LOG SELECT command. Equivalent to \fI\-\-select\fR in the main
description.
@@ -364,7 +398,7 @@ sets the Saving Parameters (SP) bit. Default is 0 (i.e. cleared).
Equivalent to \fI\-\-sp\fR in the main description.
.TP
\fB\-t\fR
-outputs the temperature. Equivalent to \fI\-\-temperature in the main
+outputs the temperature. Equivalent to \fI\-\-temperature\fR in the main
description.
.TP
\fB\-T\fR
@@ -377,6 +411,10 @@ increase level of verbosity.
\fB\-V\fR
print out version string then exit.
.TP
+\fB\-x\fR
+suppress the INQUIRY command. Equivalent to \fI\-\-no_inq\fR in the main
+description.
+.TP
\fB\-?\fR
output usage message then exit.
.SH AUTHOR
diff --git a/doc/sg_luns.8 b/doc/sg_luns.8
index 43ce5f3f..529b38a0 100644
--- a/doc/sg_luns.8
+++ b/doc/sg_luns.8
@@ -1,10 +1,10 @@
-.TH SG_LUNS "8" "March" "sg3_utils\-1.38" SG3_UTILS
+.TH SG_LUNS "8" "May" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_luns \- send SCSI REPORT LUNS command or decode given LUN
.SH SYNOPSIS
.B sg_luns
[\fI\-\-decode\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-linux\fR]
-[\fI\-\-maxlen=LEN\fR] [\fI\-\-quiet\fR] [\fI\-\-raw\fR]
+[\fI\-\-maxlen=LEN\fR] [\fI\-\-quiet\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR]
[\fI\-\-select=SR\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_luns
@@ -65,18 +65,31 @@ before the LUN listing.
\fB\-r\fR, \fB\-\-raw\fR
output the SCSI response (i.e. the data-out buffer) in binary (to stdout).
.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
+The default is to open it read\-write.
+.TP
\fB\-s\fR, \fB\-\-select\fR=\fISR\fR
this option sets the SELECT REPORT field (\fISR\fR) in the SCSI REPORT
-LUNS command. The default value is 0. For detailed information see the
+LUNS command. The default value is 0. Hexadecimal values may be given with
+a leading "0x" or a trailing "h". For detailed information see the
REPORT LUNS command in SPC (most recent is SPC\-4 revision 36s in section
6.33). To simplify, for the I_T nexus associated with the \fIDEVICE\fR, the
meanings of the \fISR\fR values defined to date for SPC\-4 are:
.br
- \fB0\fR : all LUNs excluding well known logical units
+ \fB0\fR : most LUs excluding well known logical units
.br
\fB1\fR : well known logical units
.br
- \fB2\fR : all LUNs
+ \fB2\fR : all LUs accessible to this I_T nexus
+.br
+ \fB0x10\fR : only accessible administrative LUs
+.br
+ \fB0x11\fR : administrative LUs and associated LUs (see SPC\-4)
+.br
+ \fB0x12\fR : if the addressed LU is administrative, then reports its
+.br
+ subsidiary LUs
.br
Values between 0xf8 and 0xff (inclusive) are vendor specific (SPC\-4 rev
36e), other values greater than 2 are reserved. This utility will accept
diff --git a/doc/sg_modes.8 b/doc/sg_modes.8
index ece91008..e118a989 100644
--- a/doc/sg_modes.8
+++ b/doc/sg_modes.8
@@ -1,4 +1,4 @@
-.TH SG_MODES "8" "December 2012" "sg3_utils\-1.35" SG3_UTILS
+.TH SG_MODES "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_modes \- reads mode pages with SCSI MODE SENSE command
.SH SYNOPSIS
@@ -172,6 +172,9 @@ type of the device (e.g. 0 \-> Direct Access Device (disk)) prior to
sending a MODE SENSE command. This helps in decoding the block
descriptor and mode pages.
.PP
+This utility opens \fIDEVICE\fR with a read\-only flag (e.g. in Unix with
+the O_RDONLY flag).
+.PP
In the 2.4 series of Linux kernels the \fIDEVICE\fR must be a SCSI
generic (sg) device. In the 2.6 series block devices (e.g. SCSI disks
and DVD drives) can also be specified. For example "sg_modes \-a /dev/sda"
@@ -266,7 +269,7 @@ Written by Douglas Gilbert
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2000\-2012 Douglas Gilbert
+Copyright \(co 2000\-2014 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.
diff --git a/doc/sg_read_buffer.8 b/doc/sg_read_buffer.8
index 482bc13e..fd9296cf 100644
--- a/doc/sg_read_buffer.8
+++ b/doc/sg_read_buffer.8
@@ -5,7 +5,7 @@ sg_read_buffer \- send SCSI READ BUFFER command
.B sg_read_buffer
[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-id=ID\fR] [\fI\-\-length=LEN\fR]
[\fI\-\-mode=MO\fR] [\fI\-\-offset=OFF\fR] [\fI\-\-raw\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -50,6 +50,10 @@ between 0 (default) and 2**24\-1 . It is a byte offset.
\fB\-r\fR, \fB\-\-raw\fR
if a response is received then it is sent in binary to stdout.
.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
+The default is to open it read\-write.
+.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase the level of verbosity, (i.e. debug output).
.TP
diff --git a/doc/sg_readcap.8 b/doc/sg_readcap.8
index 7bcff04a..9a8dc273 100644
--- a/doc/sg_readcap.8
+++ b/doc/sg_readcap.8
@@ -1,15 +1,15 @@
-.TH SG_READCAP "8" "January 2014" "sg3_utils\-1.38" SG3_UTILS
+.TH SG_READCAP "8" "May 2014" "sg3_utils\-1.39" SG3_UTILS
.SH NAME
sg_readcap \- send SCSI READ CAPACITY command
.SH SYNOPSIS
.B sg_readcap
[\fI\-\-16\fR] [\fI\-\-brief\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR]
[\fI\-\-lba=LBA\fR] [\fI\-\-long\fR] [\fI\-\-pmi\fR] [\fI\-\-raw\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-readonly\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.PP
.B sg_readcap
[\fI\-16\fR] [\fI\-b\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-lba=LBA\fR]
-[\fI\-pmi\fR] [\fI\-r\fR] [\fI\-v\fR] [\fI\-V\fR] \fIDEVICE\fR
+[\fI\-pmi\fR] [\fI\-r\fR] [\fI\-R\fR] [\fI\-v\fR] [\fI\-V\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -92,6 +92,12 @@ made obsolete in SBC\-3 revision 26.
\fB\-r\fR, \fB\-\-raw\fR
output response in binary to stdout.
.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
+The default for READ CAPACITY(16) is to open it read\-write. The default
+for READ CAPACITY(10) is to open it read\-only so this option does not
+change anything for this case.
+.TP
\fB\-v\fR, \fB\-\-verbose\fR
increase level of verbosity. Can be used multiple times.
.TP
@@ -148,6 +154,9 @@ Equivalent to \fI\-\-pmi\fR in the main description.
\fB\-r\fR
output response in binary (to stdout).
.TP
+\fB\-R\fR
+Equivalent to \fI\-\-readonly\fR in the main description.
+.TP
\fB\-v\fR
verbose: print out cdb of issued commands prior to execution. '\-vv'
and '\-vvv' are also accepted yielding greater verbosity.
diff --git a/doc/sg_ses.8 b/doc/sg_ses.8
index bd283a88..2d8df640 100644
--- a/doc/sg_ses.8
+++ b/doc/sg_ses.8
@@ -10,8 +10,8 @@ sg_ses \- access a SCSI Enclosure Services (SES) device
[\fI\-\-index=IIA\fR | \fI\-\-index=TIA,II\fR] [\fI\-\-inner\-hex\fR]
[\fI\-\-join\fR] [\fI\-\-list\fR] [\fI\-\-nickname=SEN\fR]
[\fI\-\-nickid=SEID\fR] [\fI\-\-page=PG\fR] [\fI\-\-raw\fR]
-[\fI\-\-sas\-addr=SA\fR] [\fI\-\-set=STR\fR] [\fI\-\-status\fR]
-[\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
+[\fI\-\-readonly\fR] [\fI\-\-sas\-addr=SA\fR] [\fI\-\-set=STR\fR]
+[\fI\-\-status\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] \fIDEVICE\fR
.SH DESCRIPTION
.\" Add any additional description here
.PP
@@ -217,6 +217,10 @@ later invocation using the \fI\-\-data=\fR option. A page less its first
4 bytes (page code and length) is output. When used twice (e.g. \fI\-rr\fR)
the full page contents is output in binary to stdout.
.TP
+\fB\-R\fR, \fB\-\-readonly\fR
+open the \fIDEVICE\fR read\-only (e.g. in Unix with the O_RDONLY flag).
+The default is to open it read\-write.
+.TP
\fB\-A\fR, \fB\-\-sas\-addr\fR=\fISA\fR
this is an indexing method for SAS end devices (e.g. SAS disks). The utility
will try to find the element or slot in the Additional Element Status page
diff --git a/examples/sg_persist_tst.sh b/examples/sg_persist_tst.sh
index 52dac061..e2640e5c 100755
--- a/examples/sg_persist_tst.sh
+++ b/examples/sg_persist_tst.sh
@@ -3,20 +3,49 @@
# in the sg3_utils package. This script works as expected on the
# author's Fujitsu MAM3184, Seagate ST373455 and ST9146803SS disks.
#
-# Version 1.6 20090608
+# Version 1.7 20140508
# N.B. make sure the device name is correct for your environment.
-if [ ! -n "$1" ];then
- echo "Usage: `basename $0` <device_name>"
- echo
- echo "Tests various SCSI Persistent Reserve (in + out) commands."
- echo "Should be harmless (unless key 0x123abc is already in use)."
- exit 1
+key="123abc"
+key2="333aaa"
+kk=${key}
+verbose=""
+
+usage()
+{
+ echo "Usage: sg_persist_tst.sh [-h] [-s] [-v] <device>"
+ echo " where:"
+ echo " -h, --help print usage message"
+ echo " -s, --second use second key"
+ echo " -v, --verbose more verbose output"
+ echo ""
+ echo "Test SCSI Persistent Reservations with sg_persist utility."
+ echo "Default key is ${key} and alternate, second key is ${key2} ."
+ echo "Should be harmless (unless one of those keys is already in use)."
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 0 ;;
+ s|-second) kk=${key2} ;;
+ v|-verbose) verbose="-v" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
fi
echo ">>> try to report capabilities:"
-sg_persist -c $1
+sg_persist -c ${verbose} $1
res=$?
case "$res" in
0) ;;
@@ -40,50 +69,50 @@ echo ""
sleep 1
echo ">>> check if any keys are registered:"
-sg_persist --no-inquiry --read-keys $1
+sg_persist --no-inquiry --read-keys ${verbose} $1
sleep 1
echo
echo ">>> register a key:"
-sg_persist -n --out --register --param-sark=123abc $1
+sg_persist -n --out --register --param-sark=${kk} ${verbose} $1
sleep 1
echo
-echo ">>> now key 123abc should be registered:"
-sg_persist -n --read-keys $1
+echo ">>> now key ${kk} should be registered:"
+sg_persist -n --read-keys ${verbose} $1
sleep 1
echo
-echo ">>> reserve the device (based on key 123abc):"
-sg_persist -n --out --reserve --param-rk=123abc --prout-type=1 $1
+echo ">>> reserve the device (based on key ${kk}):"
+sg_persist -n --out --reserve --param-rk=${kk} --prout-type=1 ${verbose} $1
sleep 1
echo
echo ">>> check if the device is reserved (it should be now):"
-sg_persist -n --read-reservation $1
+sg_persist -n --read-reservation ${verbose} $1
sleep 1
echo
echo ">>> try to 'read full status' (may not be supported):"
-sg_persist -n --read-full-status $1
+sg_persist -n --read-full-status ${verbose} $1
sleep 1
echo
echo ">>> now release reservation:"
-sg_persist -n --out --release --param-rk=123abc --prout-type=1 $1
+sg_persist -n --out --release --param-rk=${kk} --prout-type=1 ${verbose} $1
sleep 1
echo
echo ">>> check if the device is reserved (it should _not_ be now):"
-sg_persist -n --read-reservation $1
+sg_persist -n --read-reservation ${verbose} $1
sleep 1
echo
-echo ">>> unregister key 123abc:"
-sg_persist -n --out --register --param-rk=123abc $1
+echo ">>> unregister key ${kk}:"
+sg_persist -n --out --register --param-rk=${kk} ${verbose} $1
sleep 1
echo
-echo ">>> now key 123abc should not be registered:"
-sg_persist -n -k $1
+echo ">>> now key ${kk} should not be registered:"
+sg_persist -n -k ${verbose} $1
sleep 1
diff --git a/src/sg_logs.c b/src/sg_logs.c
index ebd1ec13..aa7740cc 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -27,7 +27,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
-static const char * version_str = "1.18 20140504"; /* spc4r36t + sbc4r01 */
+static const char * version_str = "1.19 20140505"; /* spc4r36t + sbc4r01 */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -78,12 +78,14 @@ static struct option long_options[] = {
{"maxlen", required_argument, 0, 'm'},
{"name", no_argument, 0, 'n'},
{"new", no_argument, 0, 'N'},
+ {"no_inq", no_argument, 0, 'x'},
{"old", no_argument, 0, 'O'},
{"page", required_argument, 0, 'p'},
{"paramp", required_argument, 0, 'P'},
{"pcb", no_argument, 0, 'q'},
{"ppc", no_argument, 0, 'Q'},
{"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'X'},
{"reset", no_argument, 0, 'R'},
{"sp", no_argument, 0, 's'},
{"select", no_argument, 0, 'S'},
@@ -104,6 +106,7 @@ struct opts_t {
int do_pcb;
int do_ppc;
int do_raw;
+ int o_readonly;
int do_pcreset;
int do_select;
int do_sp;
@@ -119,6 +122,7 @@ struct opts_t {
int subpg_code;
int paramp;
int opt_new;
+ int no_inq;
const char * device_name;
const char * in_fn;
};
@@ -149,13 +153,15 @@ usage()
{
pr2serr("Usage: sg_logs [--all] [--brief] [--control=PC] [--filter=PARC] "
" [--help]\n"
- " [--hex] [--in=FN] [--list] [--maxlen=LEN] "
- "[--name]\n"
- " [--page=PG[,SPG]] [--paramp=PP] [--pcb] [--ppc] "
- "[--raw]\n"
- " [--reset] [--select] [--sp] [--temperature] "
- "[--transport]\n"
- " [--verbose] [--version] DEVICE\n"
+ " [--hex] [--in=FN] [--list] [--no_inq] "
+ "[--maxlen=LEN]\n"
+ " [--name] [--page=PG[,SPG]] [--paramp=PP] [--pcb] "
+ "[--ppc]\n"
+ " [--raw] [--readonly] [--reset] [--select] "
+ "[--sp]\n"
+ " [--temperature] [--transport] [--verbose] "
+ "[--version]\n"
+ " DEVICE\n"
" where:\n"
" --all|-a fetch and decode all log pages\n"
" use twice to fetch and decode all log pages "
@@ -179,6 +185,8 @@ usage()
"'-p 0')\n"
" use twice to list supported log page and "
"subpage names\n"
+ " --no_inq|-x no initial INQUIRY output (twice: no "
+ "INQUIRY call)\n"
" --maxlen=LEN|-m LEN max response length (def: 0 "
"-> everything)\n"
" when > 1 will request LEN bytes\n"
@@ -194,6 +202,9 @@ usage()
pr2serr(" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
"(def: 0)\n"
" --raw|-r output response in binary to stdout\n"
+ " --readonly|-X open DEVICE read-only (def: first "
+ "read-write then if\n"
+ " fails try open again read-only)\n"
" --reset|-R reset log parameters (takes PC and SP into "
"account)\n"
" (uses PCR bit in LOG SELECT)\n"
@@ -218,7 +229,7 @@ usage_old()
"[-paramp=PP]\n"
" [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] "
"[-v] [-V]\n"
- " [-?] DEVICE\n"
+ " [-x] [-X] [-?] DEVICE\n"
" where:\n"
" -a fetch and decode all log pages\n"
" -A fetch and decode all log pages and subpages\n"
@@ -258,6 +269,10 @@ usage_old()
"page (0x18)\n"
" -v increase verbosity\n"
" -V output version string\n"
+ " -x no initial INQUIRY output (twice: no INQUIRY call)\n"
+ " -X open DEVICE read-only (def: first read-write then "
+ "if fails\n"
+ " try open again with read-only)\n"
" -? output this usage message\n\n"
"Performs a SCSI LOG SENSE (or LOG SELECT) command\n");
}
@@ -282,7 +297,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "aAbc:f:hHi:lLm:nNOp:P:qQrRsStTvV",
+ c = getopt_long(argc, argv, "aAbc:f:hHi:lLm:nNOp:P:qQrRsStTvVxX",
long_options, &option_index);
if (c == -1)
break;
@@ -410,6 +425,12 @@ process_cl_new(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'x':
+ ++op->no_inq;
+ break;
+ case 'X':
+ ++op->o_readonly;
+ break;
default:
pr2serr("unrecognised option code %c [0x%x]\n", c, c);
if (op->do_help)
@@ -493,6 +514,12 @@ process_cl_old(struct opts_t * op, int argc, char * argv[])
case 'V':
++op->do_version;
break;
+ case 'x':
+ ++op->no_inq;
+ break;
+ case 'X':
+ ++op->o_readonly;
+ break;
case '?':
++op->do_help;
break;
@@ -5334,14 +5361,15 @@ main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
}
- if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /* rw */,
- op->do_verbose)) < 0) {
- if ((sg_fd = sg_cmds_open_device(op->device_name, 1 /* r0 */,
- op->do_verbose)) < 0) {
- pr2serr("error opening file: %s: %s \n", op->device_name,
- safe_strerror(-sg_fd));
- return SG_LIB_FILE_ERROR;
- }
+ sg_fd = sg_cmds_open_device(op->device_name, op->o_readonly,
+ op->do_verbose);
+ if ((sg_fd < 0) && (0 == op->o_readonly))
+ sg_fd = sg_cmds_open_device(op->device_name, 1 /* ro */,
+ op->do_verbose);
+ if (sg_fd < 0) {
+ pr2serr("error opening file: %s: %s \n", op->device_name,
+ safe_strerror(-sg_fd));
+ return SG_LIB_FILE_ERROR;
}
if (op->do_list || op->do_all) {
op->pg_code = SUPP_PAGES_LPAGE;
@@ -5359,13 +5387,15 @@ main(int argc, char * argv[])
}
pg_len = 0;
- if ((0 == op->do_raw) && (0 == op->do_select)) {
+ if (op->no_inq < 2) {
if (sg_simple_inquiry(sg_fd, &inq_out, 1, op->do_verbose)) {
pr2serr("%s doesn't respond to a SCSI INQUIRY\n",
op->device_name);
sg_cmds_close_device(sg_fd);
return SG_LIB_CAT_OTHER;
- } else if ((0 == op->do_hex) && (0 == op->do_name))
+ }
+ if ((0 == op->do_raw) && (0 == op->do_hex) && (0 == op->do_name) &&
+ (0 == op->no_inq))
printf(" %.8s %.16s %.4s\n", inq_out.vendor,
inq_out.product, inq_out.revision);
} else
diff --git a/src/sg_luns.c b/src/sg_luns.c
index 497b2c51..4e7bb2b2 100644
--- a/src/sg_luns.c
+++ b/src/sg_luns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2013 Douglas Gilbert.
+ * Copyright (c) 2004-2014 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.
@@ -28,7 +28,7 @@
* and decodes the response.
*/
-static const char * version_str = "1.24 20131029";
+static const char * version_str = "1.25 20140508";
#define MAX_RLUNS_BUFF_LEN (1024 * 1024)
#define DEF_RLUNS_BUFF_LEN (1024 * 8)
@@ -45,6 +45,7 @@ static struct option long_options[] = {
{"maxlen", required_argument, 0, 'm'},
{"quiet", no_argument, 0, 'q'},
{"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'R'},
{"select", required_argument, 0, 's'},
{"test", required_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
@@ -59,16 +60,16 @@ usage()
fprintf(stderr, "Usage: "
"sg_luns [--decode] [--help] [--hex] [--linux] "
"[--maxlen=LEN]\n"
- " [--quiet] [--raw] [--select=SR] "
- "[--verbose]\n"
- " [--version] DEVICE\n");
+ " [--quiet] [--raw] [--readonly] "
+ "[--select=SR]\n"
+ " [--verbose] [--version] DEVICE\n");
#else
fprintf(stderr, "Usage: "
"sg_luns [--decode] [--help] [--hex] [--maxlen=LEN] "
"[--quiet]\n"
- " [--raw] [--select=SR] [--verbose] "
- "[--version]\n"
- " DEVICE\n");
+ " [--raw] [--readonly] [--select=SR] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n");
#endif
fprintf(stderr,
" or\n"
@@ -90,12 +91,15 @@ usage()
" (def: 0 -> %d bytes)\n"
" --quiet|-q output only ASCII hex lun values\n"
" --raw|-r output response in binary\n"
+ " --readonly|-R open DEVICE read-only (def: "
+ "read-write)\n"
" --select=SR|-s SR select report SR (def: 0)\n"
" 0 -> luns apart from 'well "
"known' lus\n"
" 1 -> only 'well known' "
"logical unit numbers\n"
" 2 -> all luns\n"
+ " spc4r36 added 0x10, 0x11 and 0x12\n"
" --test=ALUN|-t ALUN decode ALUN and ignore most other "
"options\n"
" and DEVICE (apart from '-H')\n"
@@ -341,6 +345,7 @@ main(int argc, char * argv[])
int maxlen = 0;
int do_quiet = 0;
int do_raw = 0;
+ int o_readonly = 0;
int select_rep = 0;
int verbose = 0;
#ifdef SG_LIB_LINUX
@@ -360,10 +365,10 @@ main(int argc, char * argv[])
int option_index = 0;
#ifdef SG_LIB_LINUX
- c = getopt_long(argc, argv, "dhHlm:qrs:t:vV", long_options,
+ c = getopt_long(argc, argv, "dhHlm:qrRs:t:vV", long_options,
&option_index);
#else
- c = getopt_long(argc, argv, "dhHm:qrs:t:vV", long_options,
+ c = getopt_long(argc, argv, "dhHm:qrRs:t:vV", long_options,
&option_index);
#endif
if (c == -1)
@@ -399,10 +404,14 @@ main(int argc, char * argv[])
case 'r':
++do_raw;
break;
+ case 'R':
+ ++o_readonly;
+ break;
case 's':
- if ((1 != sscanf(optarg, "%d", &select_rep)) ||
- (select_rep < 0) || (select_rep > 255)) {
- fprintf(stderr, "bad argument to '--select'\n");
+ select_rep = sg_get_num(optarg);
+ if ((select_rep < 0) || (select_rep > 255)) {
+ fprintf(stderr, "bad argument to '--select', expect 0 to "
+ "255\n");
return SG_LIB_SYNTAX_ERROR;
}
break;
@@ -533,7 +542,7 @@ main(int argc, char * argv[])
}
}
- sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
+ sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
fprintf(stderr, "open error: %s: %s\n", device_name,
safe_strerror(-sg_fd));
diff --git a/src/sg_modes.c b/src/sg_modes.c
index 5392a565..d4e2aec8 100644
--- a/src/sg_modes.c
+++ b/src/sg_modes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2013 D. Gilbert
+ * Copyright (C) 2000-2014 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -25,7 +25,7 @@
#include "sg_lib.h"
#include "sg_cmds_basic.h"
-static const char * version_str = "1.42 20130604";
+static const char * version_str = "1.43 20140508";
#define DEF_ALLOC_LEN (1024 * 4)
#define DEF_6_ALLOC_LEN 252
@@ -99,8 +99,7 @@ usage()
" use twice to get all mode pages and subpages\n"
" --control=PC|-c PC page control (default: 0)\n"
" 0: current, 1: changeable,\n"
- " 2: (manufacturer's) defaults, "
- "3: saved\n"
+ " 2: (manufacturer's) defaults, 3: saved\n"
" --dbd|-d disable block descriptors (DBD field in cdb)\n"
" --dbout|-D disable block descriptor output\n"
" --examine|-e examine pages # 0 through to 0x3e, note if "
@@ -176,9 +175,9 @@ usage_old()
}
static void
-usage_for(const struct opts_t * optsp)
+usage_for(const struct opts_t * op)
{
- if (optsp->opt_new)
+ if (op->opt_new)
usage();
else
usage_old();
@@ -187,7 +186,7 @@ usage_for(const struct opts_t * optsp)
/* Processes command line options according to new option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_new(struct opts_t * optsp, int argc, char * argv[])
+process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c, n, nn;
char * cp;
@@ -202,13 +201,13 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
switch (c) {
case '6':
- ++optsp->do_six;
+ ++op->do_six;
break;
case 'a':
- ++optsp->do_all;
+ ++op->do_all;
break;
case 'A':
- optsp->do_all += 2;
+ op->do_all += 2;
break;
case 'c':
n = sg_get_num(optarg);
@@ -217,32 +216,32 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->page_control = n;
+ op->page_control = n;
break;
case 'd':
- ++optsp->do_dbd;
+ ++op->do_dbd;
break;
case 'D':
- ++optsp->do_dbout;
+ ++op->do_dbout;
break;
case 'e':
- ++optsp->do_examine;
+ ++op->do_examine;
break;
case 'f':
- ++optsp->do_flexible;
+ ++op->do_flexible;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'l':
- ++optsp->do_list;
+ ++op->do_list;
break;
case 'L':
- ++optsp->do_llbaa;
+ ++op->do_llbaa;
break;
case 'm':
n = sg_get_num(optarg);
@@ -251,12 +250,12 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->maxlen = n;
+ op->maxlen = n;
break;
case 'N':
break; /* ignore */
case 'O':
- optsp->opt_new = 0;
+ op->opt_new = 0;
return 0;
case 'p':
cp = strchr(optarg, ',');
@@ -274,38 +273,38 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->subpg_code = nn;
- optsp->subpg_code_set = 1;
+ op->subpg_code = nn;
+ op->subpg_code_set = 1;
} else
nn = 0;
- optsp->pg_code = n;
+ op->pg_code = n;
break;
case 'r':
- ++optsp->do_raw;
+ ++op->do_raw;
break;
case 'R':
- optsp->do_raw += 2;
+ op->do_raw += 2;
break;
case 's':
- ++optsp->do_six;
+ ++op->do_six;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
default:
fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
- if (optsp->do_help)
+ if (op->do_help)
break;
usage();
return SG_LIB_SYNTAX_ERROR;
}
}
if (optind < argc) {
- if (NULL == optsp->device_name) {
- optsp->device_name = argv[optind];
+ if (NULL == op->device_name) {
+ op->device_name = argv[optind];
++optind;
}
if (optind < argc) {
@@ -322,7 +321,7 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
/* Processes command line options according to old option format. Returns
* 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */
static int
-process_cl_old(struct opts_t * optsp, int argc, char * argv[])
+process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, num, n;
unsigned int u, uu;
@@ -337,52 +336,52 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) {
switch (*cp) {
case '6':
- ++optsp->do_six;
+ ++op->do_six;
break;
case 'a':
- ++optsp->do_all;
+ ++op->do_all;
break;
case 'A':
- optsp->do_all += 2;
+ op->do_all += 2;
break;
case 'd':
- ++optsp->do_dbd;
+ ++op->do_dbd;
break;
case 'D':
- ++optsp->do_dbout;
+ ++op->do_dbout;
break;
case 'e':
- ++optsp->do_examine;
+ ++op->do_examine;
break;
case 'f':
- ++optsp->do_flexible;
+ ++op->do_flexible;
break;
case 'h':
case 'H':
- optsp->do_hex += 2;
+ op->do_hex += 2;
break;
case 'l':
- ++optsp->do_list;
+ ++op->do_list;
break;
case 'L':
- ++optsp->do_llbaa;
+ ++op->do_llbaa;
break;
case 'N':
- optsp->opt_new = 1;
+ op->opt_new = 1;
return 0;
case 'O':
break;
case 'r':
- optsp->do_raw += 2;
+ op->do_raw += 2;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
default:
jmp_out = 1;
@@ -400,7 +399,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->page_control = u;
+ op->page_control = u;
} else if (0 == strncmp("m=", cp, 2)) {
num = sscanf(cp + 2, "%d", &n);
if ((1 != num) || (n < 0) || (n > 65535)) {
@@ -408,7 +407,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->maxlen = n;
+ op->maxlen = n;
} else if (0 == strncmp("p=", cp, 2)) {
if (NULL == strchr(cp + 2, ',')) {
num = sscanf(cp + 2, "%x", &u);
@@ -418,7 +417,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->pg_code = u;
+ op->pg_code = u;
} else if (2 == sscanf(cp + 2, "%x,%x", &u, &uu)) {
if (uu > 255) {
fprintf(stderr, "Bad sub page code value after 'p=' "
@@ -426,9 +425,9 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->pg_code = u;
- optsp->subpg_code = uu;
- optsp->subpg_code_set = 1;
+ op->pg_code = u;
+ op->subpg_code = uu;
+ op->subpg_code_set = 1;
} else {
fprintf(stderr, "Bad page code, subpage code sequence "
"after 'p=' option\n");
@@ -443,10 +442,10 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->subpg_code = u;
- optsp->subpg_code_set = 1;
- if (-1 == optsp->pg_code)
- optsp->pg_code = 0;
+ op->subpg_code = u;
+ op->subpg_code_set = 1;
+ if (-1 == op->pg_code)
+ op->pg_code = 0;
} else if (0 == strncmp("-old", cp, 4))
;
else if (jmp_out) {
@@ -454,11 +453,11 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == optsp->device_name)
- optsp->device_name = cp;
+ } else if (0 == op->device_name)
+ op->device_name = cp;
else {
fprintf(stderr, "too many arguments, got: %s, not expecting: "
- "%s\n", optsp->device_name, cp);
+ "%s\n", op->device_name, cp);
usage_old();
return SG_LIB_SYNTAX_ERROR;
}
@@ -473,22 +472,22 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[])
* of these options is detected (when processing the other format), processing
* stops and is restarted using the other format. Clear? */
static int
-process_cl(struct opts_t * optsp, int argc, char * argv[])
+process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
- optsp->opt_new = 0;
- res = process_cl_old(optsp, argc, argv);
- if ((0 == res) && optsp->opt_new)
- res = process_cl_new(optsp, argc, argv);
+ op->opt_new = 0;
+ res = process_cl_old(op, argc, argv);
+ if ((0 == res) && op->opt_new)
+ res = process_cl_new(op, argc, argv);
} else {
- optsp->opt_new = 1;
- res = process_cl_new(optsp, argc, argv);
- if ((0 == res) && (0 == optsp->opt_new))
- res = process_cl_old(optsp, argc, argv);
+ op->opt_new = 1;
+ res = process_cl_new(op, argc, argv);
+ if ((0 == res) && (0 == op->opt_new))
+ res = process_cl_old(op, argc, argv);
}
return res;
}
@@ -857,17 +856,17 @@ list_page_codes(int scsi_ptype, int inq_byte6, int t_proto)
static int
examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
- const struct opts_t * optsp)
+ const struct opts_t * op)
{
int k, res, header, mresp_len, len;
unsigned char rbuf[256];
const char * cp;
- mresp_len = (optsp->do_raw || optsp->do_hex) ? sizeof(rbuf) : 4;
+ mresp_len = (op->do_raw || op->do_hex) ? sizeof(rbuf) : 4;
for (header = 0, k = 0; k < PG_CODE_MAX; ++k) {
- if (optsp->do_six) {
+ if (op->do_six) {
res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len,
- 1, optsp->do_verbose);
+ 1, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res) {
fprintf(stderr, ">>>>>> try again without the '-6' "
"switch for a 10 byte MODE SENSE command\n");
@@ -878,7 +877,7 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
}
} else {
res = sg_ll_mode_sense10(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len,
- 1, optsp->do_verbose);
+ 1, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res) {
fprintf(stderr, ">>>>>> try again with a '-6' "
"switch for a 6 byte MODE SENSE command\n");
@@ -889,11 +888,11 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
}
}
if (0 == res) {
- len = optsp->do_six ? (rbuf[0] + 1) :
+ len = op->do_six ? (rbuf[0] + 1) :
((rbuf[0] << 8) + rbuf[1] + 2);
if (len > mresp_len)
len = mresp_len;
- if (optsp->do_raw) {
+ if (op->do_raw) {
dStrRaw((const char *)rbuf, len);
continue;
}
@@ -906,7 +905,7 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
printf(" %s\n", cp);
else
printf(" [0x%x]\n", k);
- if (optsp->do_hex)
+ if (op->do_hex)
dStrHex((const char *)rbuf, len, 1);
}
}
@@ -939,166 +938,167 @@ main(int argc, char * argv[])
struct sg_simple_inquiry_resp inq_out;
char pdt_name[64];
struct opts_t opts;
+ struct opts_t * op;
- memset(&opts, 0, sizeof(opts));
- opts.pg_code = -1;
- res = process_cl(&opts, argc, argv);
+ op = &opts;
+ memset(op, 0, sizeof(opts));
+ op->pg_code = -1;
+ res = process_cl(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
- if (opts.do_help) {
- usage_for(&opts);
+ if (op->do_help) {
+ usage_for(op);
return 0;
}
- if (opts.do_version) {
+ if (op->do_version) {
fprintf(stderr, "Version string: %s\n", version_str);
return 0;
}
- if (NULL == opts.device_name) {
- if (opts.do_list) {
- if ((opts.pg_code < 0) || (opts.pg_code > PG_CODE_MAX)) {
+ if (NULL == op->device_name) {
+ if (op->do_list) {
+ if ((op->pg_code < 0) || (op->pg_code > PG_CODE_MAX)) {
printf(" Assume peripheral device type: disk\n");
list_page_codes(0, 0, -1);
} else {
printf(" peripheral device type: %s\n",
- sg_get_pdt_str(opts.pg_code, sizeof(pdt_name),
+ sg_get_pdt_str(op->pg_code, sizeof(pdt_name),
pdt_name));
- if (opts.subpg_code_set)
- list_page_codes(opts.pg_code, 0, opts.subpg_code);
+ if (op->subpg_code_set)
+ list_page_codes(op->pg_code, 0, op->subpg_code);
else
- list_page_codes(opts.pg_code, 0, -1);
+ list_page_codes(op->pg_code, 0, -1);
}
return 0;
}
fprintf(stderr, "No DEVICE argument given\n");
- usage_for(&opts);
+ usage_for(op);
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.do_examine && (opts.pg_code >= 0)) {
+ if (op->do_examine && (op->pg_code >= 0)) {
fprintf(stderr, "can't give '-e' and a page number\n");
return SG_LIB_SYNTAX_ERROR;
}
- if ((opts.do_six) && (opts.do_llbaa)) {
+ if ((op->do_six) && (op->do_llbaa)) {
fprintf(stderr, "LLBAA not defined for MODE SENSE 6, try "
"without '-L'\n");
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.maxlen > 0) {
- if (opts.do_six && (opts.maxlen > 255)) {
+ if (op->maxlen > 0) {
+ if (op->do_six && (op->maxlen > 255)) {
fprintf(stderr, "For Mode Sense (6) maxlen cannot exceed "
"255\n");
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.maxlen > DEF_ALLOC_LEN) {
- malloc_rsp_buff = (unsigned char *)malloc(opts.maxlen);
+ if (op->maxlen > DEF_ALLOC_LEN) {
+ malloc_rsp_buff = (unsigned char *)malloc(op->maxlen);
if (NULL == malloc_rsp_buff) {
fprintf(stderr, "Unable to malloc maxlen=%d bytes\n",
- opts.maxlen);
+ op->maxlen);
return SG_LIB_SYNTAX_ERROR;
}
rsp_buff = malloc_rsp_buff;
} else
rsp_buff = def_rsp_buff;
- rsp_buff_size = opts.maxlen;
+ rsp_buff_size = op->maxlen;
} else { /* maxlen == 0 */
- rsp_buff_size = opts.do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN;
+ rsp_buff_size = op->do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN;
rsp_buff = def_rsp_buff;
}
/* If no pages or list selected than treat as 'a' */
- if (! ((opts.pg_code >= 0) || opts.do_all || opts.do_list ||
- opts.do_examine))
- opts.do_all = 1;
+ if (! ((op->pg_code >= 0) || op->do_all || op->do_list || op->do_examine))
+ op->do_all = 1;
- if (opts.do_raw) {
+ if (op->do_raw) {
if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
perror("sg_set_binary_mode");
return SG_LIB_FILE_ERROR;
}
}
- if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* ro */,
- opts.do_verbose)) < 0) {
+ if ((sg_fd = sg_cmds_open_device(op->device_name, 1 /* ro */,
+ op->do_verbose)) < 0) {
fprintf(stderr, "error opening file: %s: %s\n",
- opts.device_name, safe_strerror(-sg_fd));
+ op->device_name, safe_strerror(-sg_fd));
if (malloc_rsp_buff)
free(malloc_rsp_buff);
return SG_LIB_FILE_ERROR;
}
- if (sg_simple_inquiry(sg_fd, &inq_out, 1, opts.do_verbose)) {
+ if (sg_simple_inquiry(sg_fd, &inq_out, 1, op->do_verbose)) {
fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n",
- opts.device_name);
+ op->device_name);
ret = SG_LIB_CAT_OTHER;
goto finish;
}
inq_pdt = inq_out.peripheral_type;
inq_byte6 = inq_out.byte_6;
- if (0 == opts.do_raw)
+ if (0 == op->do_raw)
printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n",
inq_out.vendor, inq_out.product, inq_out.revision,
sg_get_pdt_str(inq_pdt, sizeof(pdt_name), pdt_name), inq_pdt);
- if (opts.do_list) {
- if (opts.subpg_code_set)
- list_page_codes(inq_pdt, inq_byte6, opts.subpg_code);
+ if (op->do_list) {
+ if (op->subpg_code_set)
+ list_page_codes(inq_pdt, inq_byte6, op->subpg_code);
else
list_page_codes(inq_pdt, inq_byte6, -1);
goto finish;
}
- if (opts.do_examine) {
- ret = examine_pages(sg_fd, inq_pdt, inq_byte6, &opts);
+ if (op->do_examine) {
+ ret = examine_pages(sg_fd, inq_pdt, inq_byte6, op);
goto finish;
}
- if (PG_CODE_ALL == opts.pg_code) {
- if (0 == opts.do_all)
- ++opts.do_all;
- } else if (opts.do_all)
- opts.pg_code = PG_CODE_ALL;
- if (opts.do_all > 1)
- opts.subpg_code = SPG_CODE_ALL;
+ if (PG_CODE_ALL == op->pg_code) {
+ if (0 == op->do_all)
+ ++op->do_all;
+ } else if (op->do_all)
+ op->pg_code = PG_CODE_ALL;
+ if (op->do_all > 1)
+ op->subpg_code = SPG_CODE_ALL;
- if (opts.do_raw > 1) {
- if (opts.do_all) {
- if (opts.opt_new)
+ if (op->do_raw > 1) {
+ if (op->do_all) {
+ if (op->opt_new)
fprintf(stderr, "'-R' requires a specific (sub)page, not "
"all\n");
else
fprintf(stderr, "'-r' requires a specific (sub)page, not "
"all\n");
- usage_for(&opts);
+ usage_for(op);
ret = SG_LIB_SYNTAX_ERROR;
goto finish;
}
}
memset(rsp_buff, 0, rsp_buff_size);
- if (opts.do_six) {
- res = sg_ll_mode_sense6(sg_fd, opts.do_dbd, opts.page_control,
- opts.pg_code, opts.subpg_code, rsp_buff,
- rsp_buff_size, 1, opts.do_verbose);
+ if (op->do_six) {
+ res = sg_ll_mode_sense6(sg_fd, op->do_dbd, op->page_control,
+ op->pg_code, op->subpg_code, rsp_buff,
+ rsp_buff_size, 1, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, ">>>>>> try again without the '-6' "
"switch for a 10 byte MODE SENSE command\n");
} else {
- res = sg_ll_mode_sense10(sg_fd, opts.do_llbaa, opts.do_dbd,
- opts.page_control, opts.pg_code,
- opts.subpg_code, rsp_buff, rsp_buff_size,
- 1, opts.do_verbose);
+ res = sg_ll_mode_sense10(sg_fd, op->do_llbaa, op->do_dbd,
+ op->page_control, op->pg_code,
+ op->subpg_code, rsp_buff, rsp_buff_size,
+ 1, op->do_verbose);
if (SG_LIB_CAT_INVALID_OP == res)
fprintf(stderr, ">>>>>> try again with a '-6' "
"switch for a 6 byte MODE SENSE command\n");
}
if (SG_LIB_CAT_ILLEGAL_REQ == res) {
- if (opts.subpg_code > 0)
+ if (op->subpg_code > 0)
fprintf(stderr, "invalid field in cdb (perhaps subpages "
"not supported)\n");
- else if (opts.page_control > 0)
+ else if (op->page_control > 0)
fprintf(stderr, "invalid field in cdb (perhaps "
"page control (PC) not supported)\n");
else
fprintf(stderr, "invalid field in cdb (perhaps "
- "page 0x%x not supported)\n", opts.pg_code);
+ "page 0x%x not supported)\n", op->pg_code);
} else if (SG_LIB_CAT_NOT_READY == res)
fprintf(stderr, "device not ready\n");
else if (SG_LIB_CAT_UNIT_ATTENTION == res)
@@ -1110,12 +1110,12 @@ main(int argc, char * argv[])
int medium_type, specific, headerlen;
ret = 0;
- resp_mode6 = opts.do_six;
- if (opts.do_flexible) {
+ resp_mode6 = op->do_six;
+ if (op->do_flexible) {
num = rsp_buff[0];
- if (opts.do_six && (num < 3))
+ if (op->do_six && (num < 3))
resp_mode6 = 0;
- if ((0 == opts.do_six) && (num > 5)) {
+ if ((0 == op->do_six) && (num > 5)) {
if ((num > 11) && (0 == (num % 2)) && (0 == rsp_buff[4]) &&
(0 == rsp_buff[5]) && (0 == rsp_buff[6])) {
rsp_buff[1] = num;
@@ -1126,14 +1126,14 @@ main(int argc, char * argv[])
resp_mode6 = 1;
}
}
- if ((! opts.do_raw) && (1 != opts.do_hex)) {
- if (resp_mode6 == opts.do_six)
+ if ((! op->do_raw) && (1 != op->do_hex)) {
+ if (resp_mode6 == op->do_six)
printf("Mode parameter header from MODE SENSE(%s):\n",
- (opts.do_six ? "6" : "10"));
+ (op->do_six ? "6" : "10"));
else
printf(" >>> Mode parameter header from MODE SENSE(%s),\n"
" decoded as %s byte response:\n",
- (opts.do_six ? "6" : "10"), (resp_mode6 ? "6" : "10"));
+ (op->do_six ? "6" : "10"), (resp_mode6 ? "6" : "10"));
}
if (resp_mode6) {
headerlen = 4;
@@ -1155,8 +1155,8 @@ main(int argc, char * argv[])
bd_len);
bd_len = 0;
}
- if (opts.do_raw) {
- if (1 == opts.do_raw)
+ if (op->do_raw) {
+ if (1 == op->do_raw)
dStrRaw((const char *)rsp_buff, md_len);
else {
ucp = rsp_buff + bd_len + headerlen;
@@ -1169,10 +1169,10 @@ main(int argc, char * argv[])
}
goto finish;
}
- if (1 == opts.do_hex) {
+ if (1 == op->do_hex) {
dStrHex((const char *)rsp_buff, md_len, 1);
goto finish;
- } else if (opts.do_hex > 1)
+ } else if (op->do_hex > 1)
dStrHex((const char *)rsp_buff, headerlen, 1);
if (0 == inq_pdt)
printf(" Mode data length=%d, medium type=0x%.2x, WP=%d,"
@@ -1189,7 +1189,7 @@ main(int argc, char * argv[])
if (bd_len + headerlen > rsp_buff_size)
bd_len = rsp_buff_size - headerlen;
}
- if (! opts.do_dbout) {
+ if (! op->do_dbout) {
printf(" Block descriptor length=%d\n", bd_len);
if (bd_len > 0) {
len = 8;
@@ -1223,8 +1223,8 @@ main(int argc, char * argv[])
md_len -= bd_len + headerlen; /* length of mode page(s) */
num_ua_pages = 0;
for (k = 0; md_len > 0; ++k) { /* got mode page(s) */
- if ((k > 0) && (! opts.do_all) &&
- (SPG_CODE_ALL != opts.subpg_code)) {
+ if ((k > 0) && (! op->do_all) &&
+ (SPG_CODE_ALL != op->subpg_code)) {
fprintf(stderr, "Unexpectedly received extra mode page "
"responses, ignore\n");
break;
@@ -1243,13 +1243,13 @@ main(int argc, char * argv[])
break;
}
}
- if (opts.do_hex) {
+ if (op->do_hex) {
if (spf)
printf(">> page_code=0x%x, subpage_code=0x%x, page_cont"
- "rol=%d\n", page_num, ucp[1], opts.page_control);
+ "rol=%d\n", page_num, ucp[1], op->page_control);
else
printf(">> page_code=0x%x, page_control=%d\n", page_num,
- opts.page_control);
+ op->page_control);
} else {
descp = NULL;
if ((0x18 == page_num) || (0x19 == page_num)) {
@@ -1268,10 +1268,10 @@ main(int argc, char * argv[])
}
if (descp)
printf(">> %s, page_control: %s\n", descp,
- pg_control_str_arr[opts.page_control]);
+ pg_control_str_arr[op->page_control]);
else
printf(">> page_code: %s, page_control: %s\n", ebuff,
- pg_control_str_arr[opts.page_control]);
+ pg_control_str_arr[op->page_control]);
}
num = (len > md_len) ? md_len : len;
if ((k > 0) && (num > 256)) {
diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c
index 1924c7de..5d0f75b7 100644
--- a/src/sg_read_buffer.c
+++ b/src/sg_read_buffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2013 Luben Tuikov and Douglas Gilbert.
+ * Copyright (c) 2006-2014 Luben Tuikov 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.
@@ -25,7 +25,7 @@
* This utility issues the SCSI READ BUFFER command to the given device.
*/
-static const char * version_str = "1.09 20130507";
+static const char * version_str = "1.10 20140507";
static struct option long_options[] = {
@@ -36,6 +36,7 @@ static struct option long_options[] = {
{"mode", 1, 0, 'm'},
{"offset", 1, 0, 'o'},
{"raw", 0, 0, 'r'},
+ {"readonly", 0, 0, 'R'},
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
{0, 0, 0, 0},
@@ -48,8 +49,9 @@ usage()
fprintf(stderr, "Usage: "
"sg_read_buffer [--help] [--hex] [--id=ID] [--length=LEN] "
"[--mode=MO]\n"
- " [--offset=OFF] [--raw] [--verbose] "
- "[--version] DEVICE\n"
+ " [--offset=OFF] [--raw] [--readonly] "
+ "[--verbose]\n"
+ " [--version] DEVICE\n"
" where:\n"
" --help|-h print out usage message\n"
" --hex|-H print output in hex\n"
@@ -57,13 +59,13 @@ usage()
" --length=LEN|-l LEN length in bytes to read (def: 4)\n"
" --mode=MO|-m MO read buffer mode, MO is number or "
"acronym (def: 0)\n"
- " --off=OFF|-o OFF buffer offset (unit: bytes, def: 0)\n"
+ " --offset=OFF|-o OFF buffer offset (unit: bytes, def: 0)\n"
" --raw|-r output response to stdout\n"
+ " --readonly|-R open DEVICE read-only (def: read-write)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
- " Numbers given in options are decimal unless they have a "
- "hex indicator\n"
- "Performs a SCSI READ BUFFER command\n"
+ "Performs a SCSI READ BUFFER command. Numbers given in options are "
+ "decimal\nunless they have a hex indicator (e.g. a leading '0x').\n"
);
}
@@ -124,6 +126,7 @@ main(int argc, char * argv[])
int sg_fd, res, c, len, k;
int do_help = 0;
int do_hex = 0;
+ int o_readonly = 0;
int rb_id = 0;
int rb_len = 4;
int rb_mode = 0;
@@ -137,7 +140,7 @@ main(int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "hHi:l:m:o:rvV", long_options,
+ c = getopt_long(argc, argv, "hHi:l:m:o:rRvV", long_options,
&option_index);
if (c == -1)
break;
@@ -197,6 +200,9 @@ main(int argc, char * argv[])
case 'r':
++do_raw;
break;
+ case 'R':
+ ++o_readonly;
+ break;
case 'v':
++verbose;
break;
@@ -265,7 +271,7 @@ main(int argc, char * argv[])
#endif
#endif
- sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose);
+ sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
if (sg_fd < 0) {
fprintf(stderr, "open error: %s: %s\n", device_name,
safe_strerror(-sg_fd));
@@ -293,7 +299,12 @@ main(int argc, char * argv[])
fprintf(stderr, "bad field in Read buffer cdb\n");
break;
default:
- fprintf(stderr, "Read buffer failed res=%d\n", res);
+ if (-1 == res) {
+ fprintf(stderr, "Read buffer command failed\n");
+ } else
+ fprintf(stderr, "Read buffer failed, res=%d\n", res);
+ if (0 == verbose)
+ fprintf(stderr, "... try again with -v or -vv\n");
break;
}
} else if (rb_len > 0) {
diff --git a/src/sg_readcap.c b/src/sg_readcap.c
index 57302177..dbb7e786 100644
--- a/src/sg_readcap.c
+++ b/src/sg_readcap.c
@@ -29,7 +29,7 @@
#include "sg_cmds_basic.h"
-static const char * version_str = "3.89 20140115";
+static const char * version_str = "3.90 20140407";
#define ME "sg_readcap: "
@@ -47,6 +47,7 @@ static struct option long_options[] = {
{"old", 0, 0, 'O'},
{"pmi", 0, 0, 'p'},
{"raw", 0, 0, 'r'},
+ {"readonly", 0, 0, 'R'},
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
{0, 0, 0, 0},
@@ -60,6 +61,7 @@ struct opts_t {
int do_long;
int do_pmi;
int do_raw;
+ int o_readonly;
int do_verbose;
int do_version;
uint64_t llba;
@@ -71,8 +73,9 @@ static void usage()
{
fprintf(stderr, "Usage: sg_readcap [--brief] [--help] [--hex] "
"[--lba=LBA] [--long] [--16]\n"
- " [--pmi] [--raw] [--verbose] [--version] "
- "DEVICE\n"
+ " [--pmi] [--raw] [--readonly] [--verbose] "
+ "[--version]\n"
+ " DEVICE\n"
" where:\n"
" --brief|-b brief, two hex numbers: number of blocks "
"and block size\n"
@@ -91,6 +94,8 @@ static void usage()
" total disk capacity) [made obsolete in "
"sbc3r26]\n"
" --raw|-r output response in binary to stdout\n"
+ " --readonly|-R open DEVICE read-only (def: RCAP(16) "
+ "read-write)\n"
" --verbose|-v increase verbosity\n"
" --version|-V print version string and exit\n\n"
"Perform a SCSI READ CAPACITY (10 or 16) command\n");
@@ -99,7 +104,7 @@ static void usage()
static void usage_old()
{
fprintf(stderr, "Usage: sg_readcap [-16] [-b] [-h] [-H] [-lba=LBA] "
- "[-pmi] [-r] [-v] [-V]\n"
+ "[-pmi] [-r] [-R] [-v] [-V]\n"
" DEVICE\n"
" where:\n"
" -16 use READ CAPACITY (16) cdb (def: use "
@@ -116,20 +121,21 @@ static void usage_old()
"shows total\n"
" disk capacity)\n"
" -r output response in binary to stdout\n"
+ " -R open DEVICE read-only (def: RCAP(16) read-write)\n"
" -v increase verbosity\n"
" -V print version string and exit\n\n"
"Perform a SCSI READ CAPACITY command\n");
}
-static void usage_for(const struct opts_t * optsp)
+static void usage_for(const struct opts_t * op)
{
- if (optsp->opt_new)
+ if (op->opt_new)
usage();
else
usage_old();
}
-static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
+static int process_cl_new(struct opts_t * op, int argc, char * argv[])
{
int c;
int a_one = 0;
@@ -138,7 +144,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "16bhHlL:NOprvV", long_options,
+ c = getopt_long(argc, argv, "16bhHlL:NOprRvV", long_options,
&option_index);
if (c == -1)
break;
@@ -149,20 +155,20 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
break;
case '6':
if (a_one)
- ++optsp->do_long;
+ ++op->do_long;
break;
case 'b':
- ++optsp->do_brief;
+ ++op->do_brief;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'l':
- ++optsp->do_long;
+ ++op->do_long;
break;
case 'L':
nn = sg_get_llnum(optarg);
@@ -171,40 +177,43 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- optsp->llba = nn;
+ op->llba = nn;
/* force READ_CAPACITY16 for large lbas */
- if (optsp->llba > 0xfffffffeULL)
- ++optsp->do_long;
- ++optsp->do_lba;
+ if (op->llba > 0xfffffffeULL)
+ ++op->do_long;
+ ++op->do_lba;
break;
case 'N':
break; /* ignore */
case 'O':
- optsp->opt_new = 0;
+ op->opt_new = 0;
return 0;
case 'p':
- ++optsp->do_pmi;
+ ++op->do_pmi;
break;
case 'r':
- ++optsp->do_raw;
+ ++op->do_raw;
+ break;
+ case 'R':
+ ++op->o_readonly;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
default:
fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c);
- if (optsp->do_help)
+ if (op->do_help)
break;
usage();
return SG_LIB_SYNTAX_ERROR;
}
}
if (optind < argc) {
- if (NULL == optsp->device_name) {
- optsp->device_name = argv[optind];
+ if (NULL == op->device_name) {
+ op->device_name = argv[optind];
++optind;
}
if (optind < argc) {
@@ -218,7 +227,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[])
return 0;
}
-static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
+static int process_cl_old(struct opts_t * op, int argc, char * argv[])
{
int k, jmp_out, plen, num;
const char * cp;
@@ -234,43 +243,46 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
switch (*cp) {
case '1':
if ('6' == *(cp + 1)) {
- ++optsp->do_long;
+ ++op->do_long;
++cp;
--plen;
} else
jmp_out = 1;
break;
case 'b':
- ++optsp->do_brief;
+ ++op->do_brief;
break;
case 'h':
case '?':
- ++optsp->do_help;
+ ++op->do_help;
break;
case 'H':
- ++optsp->do_hex;
+ ++op->do_hex;
break;
case 'N':
- optsp->opt_new = 1;
+ op->opt_new = 1;
return 0;
case 'O':
break;
case 'p':
if (0 == strncmp("pmi", cp, 3)) {
- ++optsp->do_pmi;
+ ++op->do_pmi;
cp += 2;
plen -= 2;
} else
jmp_out = 1;
break;
case 'r':
- ++optsp->do_raw;
+ ++op->do_raw;
+ break;
+ case 'R':
+ ++op->o_readonly;
break;
case 'v':
- ++optsp->do_verbose;
+ ++op->do_verbose;
break;
case 'V':
- ++optsp->do_version;
+ ++op->do_version;
break;
default:
jmp_out = 1;
@@ -290,9 +302,9 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
}
/* force READ_CAPACITY16 for large lbas */
if (uu > 0xfffffffeULL)
- ++optsp->do_long;
- optsp->llba = uu;
- ++optsp->do_lba;
+ ++op->do_long;
+ op->llba = uu;
+ ++op->do_lba;
} else if (0 == strncmp("-old", cp, 4))
;
else if (jmp_out) {
@@ -300,11 +312,11 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
usage();
return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == optsp->device_name)
- optsp->device_name = cp;
+ } else if (0 == op->device_name)
+ op->device_name = cp;
else {
fprintf(stderr, "too many arguments, got: %s, not expecting: "
- "%s\n", optsp->device_name, cp);
+ "%s\n", op->device_name, cp);
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -312,22 +324,22 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[])
return 0;
}
-static int process_cl(struct opts_t * optsp, int argc, char * argv[])
+static int process_cl(struct opts_t * op, int argc, char * argv[])
{
int res;
char * cp;
cp = getenv("SG3_UTILS_OLD_OPTS");
if (cp) {
- optsp->opt_new = 0;
- res = process_cl_old(optsp, argc, argv);
- if ((0 == res) && optsp->opt_new)
- res = process_cl_new(optsp, argc, argv);
+ op->opt_new = 0;
+ res = process_cl_old(op, argc, argv);
+ if ((0 == res) && op->opt_new)
+ res = process_cl_new(op, argc, argv);
} else {
- optsp->opt_new = 1;
- res = process_cl_new(optsp, argc, argv);
- if ((0 == res) && (0 == optsp->opt_new))
- res = process_cl_old(optsp, argc, argv);
+ op->opt_new = 1;
+ res = process_cl_new(op, argc, argv);
+ if ((0 == res) && (0 == op->opt_new))
+ res = process_cl_old(op, argc, argv);
}
return res;
}
@@ -342,32 +354,34 @@ static void dStrRaw(const char* str, int len)
int main(int argc, char * argv[])
{
- int sg_fd, k, res, prot_en, p_type, lbppbe;
+ int sg_fd, k, res, prot_en, p_type, lbppbe, rw_0_flag;
uint64_t llast_blk_addr;
int ret = 0;
unsigned int last_blk_addr, block_size;
unsigned char resp_buff[RCAP16_REPLY_LEN];
struct opts_t opts;
+ struct opts_t * op;
- memset(&opts, 0, sizeof(opts));
- res = process_cl(&opts, argc, argv);
+ op = &opts;
+ memset(op, 0, sizeof(opts));
+ res = process_cl(op, argc, argv);
if (res)
return SG_LIB_SYNTAX_ERROR;
- if (opts.do_help) {
- usage_for(&opts);
+ if (op->do_help) {
+ usage_for(op);
return 0;
}
- if (opts.do_version) {
+ if (op->do_version) {
fprintf(stderr, "Version string: %s\n", version_str);
return 0;
}
- if (NULL == opts.device_name) {
+ if (NULL == op->device_name) {
fprintf(stderr, "No DEVICE argument given\n");
- usage_for(&opts);
+ usage_for(op);
return SG_LIB_SYNTAX_ERROR;
}
- if (opts.do_raw) {
+ if (op->do_raw) {
if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
perror("sg_set_binary_mode");
return SG_LIB_FILE_ERROR;
@@ -376,25 +390,29 @@ int main(int argc, char * argv[])
memset(resp_buff, 0, sizeof(resp_buff));
- if ((0 == opts.do_pmi) && (opts.llba > 0)) {
+ if ((0 == op->do_pmi) && (op->llba > 0)) {
fprintf(stderr, ME "lba can only be non-zero when '--pmi' is set\n");
- usage_for(&opts);
+ usage_for(op);
return SG_LIB_SYNTAX_ERROR;
}
- if ((sg_fd = sg_cmds_open_device(opts.device_name,
- (opts.do_long ? 0 /* rw */ : 1), opts.do_verbose)) < 0) {
- fprintf(stderr, ME "error opening file: %s: %s\n", opts.device_name,
+ if (op->do_long)
+ rw_0_flag = op->o_readonly;
+ else
+ rw_0_flag = 1; /* RCAP(10) has opened RO in past, so leave */
+ if ((sg_fd = sg_cmds_open_device(op->device_name, rw_0_flag,
+ op->do_verbose)) < 0) {
+ fprintf(stderr, ME "error opening file: %s: %s\n", op->device_name,
safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (! opts.do_long) {
- res = sg_ll_readcap_10(sg_fd, opts.do_pmi, (unsigned int)opts.llba,
- resp_buff, RCAP_REPLY_LEN, 1, opts.do_verbose);
+ if (! op->do_long) {
+ res = sg_ll_readcap_10(sg_fd, op->do_pmi, (unsigned int)op->llba,
+ resp_buff, RCAP_REPLY_LEN, 1, op->do_verbose);
ret = res;
if (0 == res) {
- if (opts.do_hex || opts.do_raw) {
- if (opts.do_raw)
+ if (op->do_hex || op->do_raw) {
+ if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP_REPLY_LEN);
else
dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, 1);
@@ -405,20 +423,20 @@ int main(int argc, char * argv[])
if (0xffffffff != last_blk_addr) {
block_size = ((resp_buff[4] << 24) | (resp_buff[5] << 16) |
(resp_buff[6] << 8) | resp_buff[7]);
- if (opts.do_brief) {
+ if (op->do_brief) {
printf("0x%x 0x%x\n", last_blk_addr + 1, block_size);
goto good;
}
printf("Read Capacity results:\n");
- if (opts.do_pmi)
+ if (op->do_pmi)
printf(" PMI mode: given lba=0x%" PRIx64 ", last lba "
- "before delay=0x%x\n", opts.llba, last_blk_addr);
+ "before delay=0x%x\n", op->llba, last_blk_addr);
else
printf(" Last logical block address=%u (0x%x), Number "
"of blocks=%u\n", last_blk_addr, last_blk_addr,
last_blk_addr + 1);
printf(" Logical block length=%u bytes\n", block_size);
- if (! opts.do_pmi) {
+ if (! op->do_pmi) {
uint64_t total_sz = last_blk_addr + 1;
double sz_mb, sz_gb;
@@ -440,19 +458,19 @@ int main(int argc, char * argv[])
} else {
printf("READ CAPACITY (10) indicates device capacity too "
"large\n now trying 16 byte cdb variant\n");
- opts.do_long = 1;
+ op->do_long = 1;
}
} else if (SG_LIB_CAT_INVALID_OP == res) {
- opts.do_long = 1;
+ op->do_long = 1;
sg_cmds_close_device(sg_fd);
- if ((sg_fd = sg_cmds_open_device(opts.device_name, 0 /*rw */,
- opts.do_verbose))
+ if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /*rw */,
+ op->do_verbose))
< 0) {
fprintf(stderr, ME "error re-opening file: %s (rw): %s\n",
- opts.device_name, safe_strerror(-sg_fd));
+ op->device_name, safe_strerror(-sg_fd));
return SG_LIB_FILE_ERROR;
}
- if (opts.do_verbose)
+ if (op->do_verbose)
fprintf(stderr, "READ CAPACITY (10) not supported, trying "
"READ CAPACITY (16)\n");
} else if (SG_LIB_CAT_ILLEGAL_REQ == res)
@@ -461,17 +479,17 @@ int main(int argc, char * argv[])
fprintf(stderr, "READ CAPACITY (10) failed, device not ready\n");
else if (SG_LIB_CAT_ABORTED_COMMAND == res)
fprintf(stderr, "READ CAPACITY (10) failed, aborted command\n");
- else if (! opts.do_verbose)
+ else if (! op->do_verbose)
fprintf(stderr, "READ CAPACITY (10) failed [res=%d], try "
"with '-v'\n", res);
}
- if (opts.do_long) {
- res = sg_ll_readcap_16(sg_fd, opts.do_pmi, opts.llba, resp_buff,
- RCAP16_REPLY_LEN, 1, opts.do_verbose);
+ if (op->do_long) {
+ res = sg_ll_readcap_16(sg_fd, op->do_pmi, op->llba, resp_buff,
+ RCAP16_REPLY_LEN, 1, op->do_verbose);
ret = res;
if (0 == res) {
- if (opts.do_hex || opts.do_raw) {
- if (opts.do_raw)
+ if (op->do_hex || op->do_raw) {
+ if (op->do_raw)
dStrRaw((const char *)resp_buff, RCAP16_REPLY_LEN);
else
dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, 1);
@@ -483,7 +501,7 @@ int main(int argc, char * argv[])
}
block_size = ((resp_buff[8] << 24) | (resp_buff[9] << 16) |
(resp_buff[10] << 8) | resp_buff[11]);
- if (opts.do_brief) {
+ if (op->do_brief) {
printf("0x%" PRIx64 " 0x%x\n", llast_blk_addr + 1, block_size);
goto good;
}
@@ -498,9 +516,9 @@ int main(int argc, char * argv[])
printf("\n");
printf(" Logical block provisioning: lbpme=%d, lbprz=%d\n",
!!(resp_buff[14] & 0x80), !!(resp_buff[14] & 0x40));
- if (opts.do_pmi)
+ if (op->do_pmi)
printf(" PMI mode: given lba=0x%" PRIx64 ", last lba "
- "before delay=0x%" PRIx64 "\n", opts.llba,
+ "before delay=0x%" PRIx64 "\n", op->llba,
llast_blk_addr);
else
printf(" Last logical block address=%" PRIu64 " (0x%"
@@ -517,7 +535,7 @@ int main(int argc, char * argv[])
printf("\n");
printf(" Lowest aligned logical block address=%d\n",
((resp_buff[14] & 0x3f) << 8) + resp_buff[15]);
- if (! opts.do_pmi) {
+ if (! op->do_pmi) {
uint64_t total_sz = llast_blk_addr + 1;
double sz_mb, sz_gb;
@@ -546,11 +564,11 @@ int main(int argc, char * argv[])
else if (SG_LIB_CAT_ILLEGAL_REQ == res)
fprintf(stderr, "bad field in READ CAPACITY (16) cdb "
"including unsupported service action\n");
- else if (! opts.do_verbose)
+ else if (! op->do_verbose)
fprintf(stderr, "READ CAPACITY (16) failed [res=%d], try "
"with '-v'\n", res);
}
- if (opts.do_brief)
+ if (op->do_brief)
printf("0x0 0x0\n");
good:
diff --git a/src/sg_ses.c b/src/sg_ses.c
index 57008bc7..acf5194e 100644
--- a/src/sg_ses.c
+++ b/src/sg_ses.c
@@ -28,7 +28,7 @@
* commands tailored for SES (enclosure) devices.
*/
-static const char * version_str = "1.88 20140414"; /* ses3r06 */
+static const char * version_str = "1.89 20140507"; /* ses3r06 */
#define MX_ALLOC_LEN ((64 * 1024) - 1) /* max allowable for big enclosures */
#define MX_ELEM_HDR 1024
@@ -119,6 +119,7 @@ struct opts_t {
int page_code;
int page_code_given;
int do_raw;
+ int o_readonly;
int do_status;
int verbose;
int do_version;
@@ -486,6 +487,7 @@ static struct option long_options[] = {
{"maxlen", required_argument, 0, 'm'},
{"page", required_argument, 0, 'p'},
{"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'R'},
{"sas-addr", required_argument, 0, 'A'},
{"set", required_argument, 0, 'S'},
{"status", no_argument, 0, 's'},
@@ -613,6 +615,8 @@ usage(int help_num)
"for '-d';\n"
" when used twice outputs page in binary "
"to stdout\n"
+ " --readonly|-R open DEVICE read-only (def: "
+ "read-write)\n"
" --status|-s fetch status information (default "
"action)\n"
" --verbose|-v increase verbosity\n"
@@ -770,8 +774,8 @@ cl_process(struct opts_t *op, int argc, char *argv[])
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:p:rsS:vVx:",
- long_options, &option_index);
+ c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:p:rRsS:v"
+ "Vx:", long_options, &option_index);
if (c == -1)
break;
@@ -905,6 +909,9 @@ cl_process(struct opts_t *op, int argc, char *argv[])
case 'r':
++op->do_raw;
break;
+ case 'R':
+ ++op->o_readonly;
+ break;
case 's':
++op->do_status;
break;
@@ -3994,7 +4001,7 @@ main(int argc, char * argv[])
}
}
- sg_fd = sg_cmds_open_device(op->dev_name, 0 /* rw */, op->verbose);
+ sg_fd = sg_cmds_open_device(op->dev_name, op->o_readonly, op->verbose);
if (sg_fd < 0) {
pr2serr("open error: %s: %s\n", op->dev_name,
safe_strerror(-sg_fd));
diff --git a/src/sg_write_buffer.c b/src/sg_write_buffer.c
index d555899e..3f1bf1a9 100644
--- a/src/sg_write_buffer.c
+++ b/src/sg_write_buffer.c
@@ -26,7 +26,7 @@
* This utility issues the SCSI WRITE BUFFER command to the given device.
*/
-static const char * version_str = "1.12 20140414"; /* spc4r36s */
+static const char * version_str = "1.13 20140507"; /* spc4r36s */
#define ME "sg_write_buffer: "
#define DEF_XFER_LEN (8 * 1024 * 1024)
@@ -544,7 +544,12 @@ main(int argc, char * argv[])
pr2serr("bad field in Write buffer cdb\n");
break;
default:
- pr2serr("Write buffer failed res=%d\n", res);
+ if (-1 == res) {
+ fprintf(stderr, "Write buffer command failed\n");
+ } else
+ fprintf(stderr, "Write buffer failed, res=%d\n", res);
+ if (0 == verbose)
+ fprintf(stderr, "... try again with -v or -vv\n");
break;
}
}