aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COVERAGE3
-rw-r--r--ChangeLog8
-rw-r--r--debian/changelog2
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/Makefile.in18
-rw-r--r--doc/sg_rep_density.897
-rw-r--r--doc/sg_rep_pip.86
-rw-r--r--inhex/README10
-rw-r--r--inhex/inq_standard.hex23
-rw-r--r--inhex/rep_density.hex18
-rw-r--r--inhex/rep_density_media.hex13
-rw-r--r--inhex/rep_density_media_typem.hex13
-rw-r--r--inhex/rep_density_typem.hex31
-rw-r--r--lib/sg_lib.c1
-rw-r--r--sg3_utils.spec2
-rw-r--r--src/BSD_LICENSE2
-rw-r--r--src/Makefile.am17
-rw-r--r--src/Makefile.in72
-rw-r--r--src/sg_rep_density.c478
-rw-r--r--src/sg_rep_pip.c27
20 files changed, 775 insertions, 72 deletions
diff --git a/COVERAGE b/COVERAGE
index 1ab56b1b..ab60a6c1 100644
--- a/COVERAGE
+++ b/COVERAGE
@@ -73,6 +73,7 @@ RECEIVE DIAGNOSTIC RESULTS sg_senddiag, sg_ses, sg_ses_microcode ++
RECEIVE ROD TOKEN INFORMATION ddpt, ddptctl ++
REMOVE ELEMENT AND MODIFY ZONES sg_zone
REPORT ALL ROD TOKENS ddptctl ++
+REPORT DENSITY SUPPORT sg_rep_density
REPORT IDENTIFYING INFORMATION sg_ident, ++ (2)
REPORT LUNS sg_luns, ++
REPORT PROVISIONING INITIALIZATION PATTERN sg_rep_pip, ++
@@ -182,4 +183,4 @@ THIRD PARTY COPY IN (0x83).
Douglas Gilbert
-20th November 2021
+21st January 2022
diff --git a/ChangeLog b/ChangeLog
index 6c99fb64..16cc7e5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,12 +2,14 @@ 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 pre-release sg3_utils-1.48 [20220119] [svn: r931]
+Changelog for pre-release sg3_utils-1.48 [20220121] [svn: r932]
+ - sg_z_act_query: new utility for sending either a
+ Zone activate or Zone query command
+ - sg_rep_density: new utility for decoding the response of
+ Report density support command [ssc (tape)]
- rescan-scsi-bus.sh: with '-r' it crashed due to change in
rev 867 in sg_inq.c from Device_type= to PDT= .
Change script to use either
- - sg_z_act_query: new utility for sending either a
- Zone activate or Zone query command
- sg_rep_zones: add Report zone starting LBA granularity
field in REPORT ZONES response [zbc2r12]
- sg_decode_sense: add --nodecode option
diff --git a/debian/changelog b/debian/changelog
index 84ddb62a..c3e329eb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.48-0.1) unstable; urgency=low
* New upstream version
- -- Douglas Gilbert <dgilbert@interlog.com> Sat, 01 Jan 2022 13:00:00 -0500
+ -- Douglas Gilbert <dgilbert@interlog.com> Fri, 21 Jan 2022 14:00:00 -0500
sg3-utils (1.47-0.1) unstable; urgency=low
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 3cb12ebf..8a09982e 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -7,9 +7,9 @@ man_MANS = \
sg_logs.8 sg_luns.8 sg_modes.8 sg_opcodes.8 sg_persist.8 \
sg_prevent.8 sg_raw.8 sg_rdac.8 sg_read_attr.8 \
sg_read_block_limits.8 sg_read_buffer.8 sg_read_long.8 sg_readcap.8 \
- sg_reassign.8 sg_referrals.8 sg_rep_pip.8 sg_rep_zones.8 \
- sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 \
- sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8 \
+ sg_reassign.8 sg_referrals.8 sg_rep_density.8 sg_rep_pip.8 \
+ sg_rep_zones.8 sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 \
+ sg_safte.8 sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8 \
sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 \
sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 \
sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 sg_vpd.8 \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index c1e2bdbd..b69648e5 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -293,15 +293,15 @@ man_MANS = scsi_mandat.8 scsi_readcap.8 scsi_ready.8 scsi_satl.8 \
sg_modes.8 sg_opcodes.8 sg_persist.8 sg_prevent.8 sg_raw.8 \
sg_rdac.8 sg_read_attr.8 sg_read_block_limits.8 \
sg_read_buffer.8 sg_read_long.8 sg_readcap.8 sg_reassign.8 \
- sg_referrals.8 sg_rep_pip.8 sg_rep_zones.8 sg_requests.8 \
- sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 sg_sanitize.8 \
- sg_sat_identify.8 sg_sat_phy_event.8 sg_sat_read_gplog.8 \
- sg_sat_set_features.8 sg_seek.8 sg_senddiag.8 sg_ses.8 \
- sg_ses_microcode.8 sg_start.8 sg_stpg.8 sg_stream_ctl.8 \
- sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 sg_verify.8 \
- sg_vpd.8 sg_wr_mode.8 sg_write_buffer.8 sg_write_long.8 \
- sg_write_same.8 sg_write_verify.8 sg_write_x.8 sg_zone.8 \
- sg_z_act_query.8 $(am__append_1) $(am__append_3) \
+ sg_referrals.8 sg_rep_density.8 sg_rep_pip.8 sg_rep_zones.8 \
+ sg_requests.8 sg_reset_wp.8 sg_rmsn.8 sg_rtpg.8 sg_safte.8 \
+ sg_sanitize.8 sg_sat_identify.8 sg_sat_phy_event.8 \
+ sg_sat_read_gplog.8 sg_sat_set_features.8 sg_seek.8 \
+ sg_senddiag.8 sg_ses.8 sg_ses_microcode.8 sg_start.8 sg_stpg.8 \
+ sg_stream_ctl.8 sg_sync.8 sg_timestamp.8 sg_turs.8 sg_unmap.8 \
+ sg_verify.8 sg_vpd.8 sg_wr_mode.8 sg_write_buffer.8 \
+ sg_write_long.8 sg_write_same.8 sg_write_verify.8 sg_write_x.8 \
+ sg_zone.8 sg_z_act_query.8 $(am__append_1) $(am__append_3) \
$(am__append_5)
CLEANFILES = $(am__append_2) $(am__append_4) $(am__append_6)
all: all-am
diff --git a/doc/sg_rep_density.8 b/doc/sg_rep_density.8
new file mode 100644
index 00000000..6734796a
--- /dev/null
+++ b/doc/sg_rep_density.8
@@ -0,0 +1,97 @@
+.TH SG_REP_DENSITY "8" "January 2022" "sg3_utils\-1.48" SG3_UTILS
+.SH NAME
+sg_rep_density \- send SCSI REPORT DENSITY SUPPORT command
+.SH SYNOPSIS
+.B sg_rep_density
+[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-inhex=FN\fR] [\fI\-\-maxlen=LEN\fR]
+[\fI\-\-media\fR] [\fI\-\-raw\fR] [\fI\-\-readonly\fR] [\fI\-\-typem\fR]
+[\fI\-\-verbose\fR] [\fI\-\-version\fR]
+\fIDEVICE\fR
+.SH DESCRIPTION
+.\" Add any additional description here
+.PP
+Sends a SCSI REPORT DENSITY command to \fIDEVICE\fR and outputs the data
+returned. This command is tape drive specific. This command is found in
+the SSC\-5 draft standard, revision 6 (ssc5r06.pdf). This command was
+present in the SSC\-2 standard (ANSI INCITS 380\-2003).
+.PP
+By default this utility requests the density code descriptors supported by
+the \fIDEVICE\fR (e.g. a tape drive) and decodes the response. If the
+\fI\-\-typem\fR option is given it fetches the medium type descriptors
+supported by the \fIDEVICE\fR and decodes the response. When the
+\fI\-\-media\fR option is given the density code or medium type descriptors
+supported by the media inside the \fIDEVICE\fR (e.g. a tape cartridge) are
+fetched.
+.SH OPTIONS
+Arguments to long options are mandatory for short options as well.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+output the usage message then exit.
+.TP
+\fB\-H\fR, \fB\-\-hex\fR
+output the response in hexadecimal to stdout. When used once the whole
+response is output in ASCII hexadecimal, prefixed by an address (starting at
+0) on each line. When used twice the whole response is output in hexadecimal
+with no leading address (on each line).
+.br
+Using this option three times will produce output that can be redirected to
+a file and later given to another invocation using the \fI\-\-inhex=FN\fR
+option.
+.TP
+\fB\-i\fR, \fB\-\-inhex\fR=\fIFN\fR
+where \fIFN\fR is a file name whose contents are assumed to be ASCII
+hexadecimal. If \fIDEVICE\fR is also given then \fIDEVICE\fR is ignored,
+a warning is issued and the utility continues, decoding the file named
+\fIFN\fR. See the "FORMAT OF FILES CONTAINING ASCII HEX" section in the
+sg3_utils manpage for more information. If the \fI\-\-raw\fR option is
+also given then the contents of \fIFN\fR are treated as binary.
+.TP
+\fB\-m\fR, \fB\-\-maxlen\fR=\fILEN\fR
+where \fILEN\fR is the (maximum) response length in bytes. It is placed in
+the cdb's "allocation length" field. If not given (or \fILEN\fR is zero)
+then 8192 is used. The maximum allowed value of \fILEN\fR is 65535.
+.TP
+\fB\-M\fR, \fB\-\-media\fR
+sets the MEDIA bit in the cdb which causes the density codes (or medium
+types) supported by the tape cartridge in the drive to be placed in the
+response. The default is to request the density codes (or medium types)
+supported by the tape drive itself.
+.br
+If there is no "medium" (e.g. tape cartridge) present in the drive the SCSI
+command will fail with a "not ready" sense key.
+.TP
+\fB\-r\fR, \fB\-\-raw\fR
+output the SCSI response (i.e. the data\-out buffer) in binary (to stdout)
+unless the \fI\-\-inhex=FN\fR option is given.
+.br
+When used together with the \fI\-\-inhex=FN\fR option then the contents of
+\fIFN\fR are treated as binary (rather than hexadecimal).
+.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\-t\fR, \fB\-\-typem\fR
+sets the MEDIUM TYPE bit in the cdb which causes the medium types supported
+by the tape drive (or tape cartridge) to be placed in the response. The
+default is to request the density codes.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+increase the level of verbosity, (i.e. debug output).
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+print the version string and then exit.
+.SH EXIT STATUS
+The exit status of sg_rep_density is 0 when it is successful. Otherwise see
+the sg3_utils(8) man page.
+.SH AUTHORS
+Written by Douglas Gilbert.
+.SH "REPORTING BUGS"
+Report bugs to <dgilbert at interlog dot com>.
+.SH COPYRIGHT
+Copyright \(co 2022 Douglas Gilbert
+.br
+This software is distributed under a FreeBSD license. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH "SEE ALSO"
+.B sg3_utils(sg3_utils)
diff --git a/doc/sg_rep_pip.8 b/doc/sg_rep_pip.8
index d054cd2b..fb615ee7 100644
--- a/doc/sg_rep_pip.8
+++ b/doc/sg_rep_pip.8
@@ -1,4 +1,4 @@
-.TH SG_REP_PIP "8" "July 2020" "sg3_utils\-1.46" SG3_UTILS
+.TH SG_REP_PIP "8" "January 2022" "sg3_utils\-1.48" SG3_UTILS
.SH NAME
sg_rep_pip \- send SCSI REPORT PROVISIONING INITIALIZATION PATTERN command
.SH SYNOPSIS
@@ -11,7 +11,7 @@ sg_rep_pip \- send SCSI REPORT PROVISIONING INITIALIZATION PATTERN command
.PP
Sends a SCSI REPORT PROVISIONING INITIALIZATION PATTERN command to
\fIDEVICE\fR and outputs the data returned. This command is found in the
-SBC\-4 draft standard, revision 21 (sbc\4r21.pdf).
+SBC\-4 draft standard, revision 21 (sbc4r21.pdf).
.SH OPTIONS
Arguments to long options are mandatory for short options as well.
.TP
@@ -50,7 +50,7 @@ Written by Douglas Gilbert.
.SH "REPORTING BUGS"
Report bugs to <dgilbert at interlog dot com>.
.SH COPYRIGHT
-Copyright \(co 2020 Douglas Gilbert
+Copyright \(co 2020\-2022 Douglas Gilbert
.br
This software is distributed under a FreeBSD license. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/inhex/README b/inhex/README
index 42337e02..d1a50b19 100644
--- a/inhex/README
+++ b/inhex/README
@@ -4,8 +4,8 @@
The files in this folder contain hexadecimal data (in ASCII) and associated
comments (prefixed with the hash mark symbol: '#' ).
-The utility that each hex file is associated with can be determined by
-prepending "sg_" to these filenames then going to the 'src' folder (a
+The utility that each hex file is associated with can be determined in most
+case by prepending "sg_" to these filenames. Then go to the 'src' folder (a
sibling folder to this one) and look for a match or partial match on
the name.
@@ -41,6 +41,10 @@ Device Identification VPD page:
SCSI name string:
naa.5000C5003011CB28
+Not all the hex files follow the "prepend sg_" pattern. Those hex files
+starting with 'nvme_' are examples of invoking NVMe commands with the
+sg_raw utility.
+
Binary <--> Hexadecimal
-----------------------
The vpd_zbdc.raw file is binary and was created by:
@@ -79,4 +83,4 @@ that support --inhex and don't have hex data already. Special cases are
also welcome. They help the author test this code.
Douglas Gilbert
-20th November 2021
+21st January 2022
diff --git a/inhex/inq_standard.hex b/inhex/inq_standard.hex
new file mode 100644
index 00000000..0c793fed
--- /dev/null
+++ b/inhex/inq_standard.hex
@@ -0,0 +1,23 @@
+# This file contains the ASCII hex of a SCSI INQUIRY command
+# 'standard' response. In this case non-standard responses refers
+# to responses contain VPD page that are also fetched with the
+# SCSI INQUIRY command.
+
+# The response in this file can be decoded with:
+# sg_inq --inhex=sg_inq_standard.hex
+# or
+# sg_vpd --inhex=sg_inq_standard.hex --page=sinq
+#
+# The sg_inq utility defaults to the 'standard' INQUIRY while the
+# sg_vpd utility defaults to the "Supported VPD pages" VPD page.
+# Hence sg_vpd needs the extra option '--page=sinq' which says the
+# VPD page is the standard inquiry. Strictly speaking the standard
+# INQUIRY is not a VPD page but probably would be if SCSI was not
+# 40 years old and highly values backward compatibility.
+
+00 00 07 02 5b 00 10 0a 4c 69 6e 75 78 20 20 20
+73 63 73 69 5f 64 65 62 75 67 20 20 20 20 20 20
+30 31 39 31 32 30 32 31 30 35 32 30 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 c0 05 c0 06 00
+21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
diff --git a/inhex/rep_density.hex b/inhex/rep_density.hex
new file mode 100644
index 00000000..0aba1b50
--- /dev/null
+++ b/inhex/rep_density.hex
@@ -0,0 +1,18 @@
+#
+# This file contains the response to SCSI REPORT DENSITY SUPPORTED command
+# using the sg_rep_density utility. This file was generated with:
+# sg_rep_density -HHH /dev/sg4 > rep_density.hex
+# where /dev/sg4 was a LTO-4 tape drive. To decode that file containing
+# hexadecimal in ASCII use:
+# sg_rep_density --inhex=rep_density.hex
+
+00 9e 00 00 44 44 00 00 00 00 25 a6 00 7f 02 c0
+00 06 1a 80 4c 54 4f 2d 43 56 45 20 55 2d 33 31
+36 20 20 20 55 6c 74 72 69 75 6d 20 33 2f 31 36
+54 20 20 20 20 20 20 20 46 46 80 00 00 00 31 b5
+00 7f 03 80 00 0c 35 00 4c 54 4f 2d 43 56 45 20
+55 2d 34 31 36 20 20 20 55 6c 74 72 69 75 6d 20
+34 2f 31 36 54 20 20 20 20 20 20 20 58 58 a0 00
+00 00 3b 26 00 7f 05 00 00 16 e3 60 4c 54 4f 2d
+43 56 45 20 55 2d 35 31 36 20 20 20 55 6c 74 72
+69 75 6d 20 35 2f 31 36 54 20 20 20 20 20 20 20
diff --git a/inhex/rep_density_media.hex b/inhex/rep_density_media.hex
new file mode 100644
index 00000000..22312fdf
--- /dev/null
+++ b/inhex/rep_density_media.hex
@@ -0,0 +1,13 @@
+#
+# This file contains the response to SCSI REPORT DENSITY SUPPORTED command
+# using the sg_rep_density utility. This file was generated with:
+# sg_rep_density --media -HHH /dev/sg4 > rep_density_media.hex
+# where /dev/sg4 was a LTO-4 tape drive. To decode that file containing
+# hexadecimal in ASCII use:
+# sg_rep_density --inhex=rep_density_media.hex
+# The --media option is not needed in the decode invocation.
+
+00 36 00 00 58 58 a0 00 00 00 3b 26 00 7f 05 00
+00 17 85 3e 4c 54 4f 2d 43 56 45 20 55 2d 35 31
+36 20 20 20 55 6c 74 72 69 75 6d 20 35 2f 31 36
+54 20 20 20 20 20 20 20
diff --git a/inhex/rep_density_media_typem.hex b/inhex/rep_density_media_typem.hex
new file mode 100644
index 00000000..57918fe8
--- /dev/null
+++ b/inhex/rep_density_media_typem.hex
@@ -0,0 +1,13 @@
+#
+# This file contains the response to SCSI REPORT DENSITY SUPPORTED command
+# using the sg_rep_density utility. This file was generated with:
+# sg_rep_density -M -t -HHH /dev/sg4 > rep_density_media_typem.hex
+# where /dev/sg4 was a LTO-4 tape drive. To decode that file containing
+# hexadecimal in ASCII use:
+# sg_rep_density --typem -i rep_density_media_typem.hex
+# The --typem option is required in the decode invocation.
+
+00 3a 00 00 00 00 00 34 01 58 00 00 00 00 00 00
+00 00 00 7f 03 4e 00 00 48 50 20 20 20 20 20 20
+4c 54 4f 35 44 61 74 61 55 6c 74 72 69 75 6d 20
+35 20 44 61 74 61 20 54 61 70 65 20
diff --git a/inhex/rep_density_typem.hex b/inhex/rep_density_typem.hex
new file mode 100644
index 00000000..315d6907
--- /dev/null
+++ b/inhex/rep_density_typem.hex
@@ -0,0 +1,31 @@
+#
+# This file contains the response to SCSI REPORT DENSITY SUPPORTED command
+# using the sg_rep_density utility. This file was generated with:
+# sg_rep_density --typem -HHH /dev/sg4 > rep_density_typem.hex
+# where /dev/sg4 was a LTO-4 tape drive. To decode that file containing
+# hexadecimal in ASCII use:
+# sg_rep_density --typem -i rep_density_typem.hex
+# The --typem option is required in the decode invocation.
+
+01 52 00 00 00 00 00 34 01 44 00 00 00 00 00 00
+00 00 00 7f 02 a8 00 00 48 50 20 20 20 20 20 20
+4c 54 4f 33 44 61 74 61 55 6c 74 72 69 75 6d 20
+33 20 44 61 74 61 20 54 61 70 65 20 00 00 00 34
+01 46 00 00 00 00 00 00 00 00 00 7f 03 34 00 00
+48 50 20 20 20 20 20 20 4c 54 4f 34 44 61 74 61
+55 6c 74 72 69 75 6d 20 34 20 44 61 74 61 20 54
+61 70 65 20 00 00 00 34 01 58 00 00 00 00 00 00
+00 00 00 7f 03 4e 00 00 48 50 20 20 20 20 20 20
+4c 54 4f 35 44 61 74 61 55 6c 74 72 69 75 6d 20
+35 20 44 61 74 61 20 54 61 70 65 20 01 00 00 34
+01 44 00 00 00 00 00 00 00 00 00 7f 02 a8 00 00
+48 50 20 20 20 20 20 20 4c 54 4f 33 57 4f 52 4d
+55 6c 74 72 69 75 6d 20 33 20 57 4f 52 4d 20 54
+61 70 65 20 01 00 00 34 01 46 00 00 00 00 00 00
+00 00 00 7f 03 34 00 00 48 50 20 20 20 20 20 20
+4c 54 4f 34 57 4f 52 4d 55 6c 74 72 69 75 6d 20
+34 20 57 4f 52 4d 20 54 61 70 65 20 01 00 00 34
+01 58 00 00 00 00 00 00 00 00 00 7f 03 4e 00 00
+48 50 20 20 20 20 20 20 4c 54 4f 35 57 4f 52 4d
+55 6c 74 72 69 75 6d 20 35 20 57 4f 52 4d 20 54
+61 70 65 20
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 1b267e44..d1cc5cdd 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -2839,6 +2839,7 @@ dStrHexFp(const char* str, int len, int no_ascii, FILE * fp)
int bpos = bpstart;
int i, k, blen;
+fprintf(stderr, "%s: no_ascii=%d\n", __func__, no_ascii);
if (len <= 0)
return;
blen = (int)sizeof(buff);
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 9060e663..4f493684 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -84,7 +84,7 @@ fi
%{_libdir}/*.la
%changelog
-* Sat Jan 01 2022 - dgilbert at interlog dot com
+* Fri Jan 21 2022 - dgilbert at interlog dot com
- track t10 changes
* sg3_utils-1.48
diff --git a/src/BSD_LICENSE b/src/BSD_LICENSE
index 15e3da3f..975506ad 100644
--- a/src/BSD_LICENSE
+++ b/src/BSD_LICENSE
@@ -1,5 +1,5 @@
-Copyright (c) 1999-2019, Douglas Gilbert
+Copyright (c) 1999-2022, Douglas Gilbert
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/src/Makefile.am b/src/Makefile.am
index cd9d8b9d..676f61fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,13 +4,14 @@ bin_PROGRAMS = \
sg_get_config sg_get_elem_status sg_get_lba_status sg_ident sg_inq \
sg_logs sg_luns sg_modes sg_opcodes sg_persist sg_prevent sg_raw \
sg_rdac sg_read_attr sg_read_block_limits sg_read_buffer \
- sg_read_long sg_readcap sg_reassign sg_referrals sg_rep_pip \
- sg_rep_zones sg_requests sg_reset_wp sg_rmsn sg_rtpg sg_safte \
- sg_sanitize sg_sat_identify sg_sat_phy_event sg_sat_read_gplog \
- sg_sat_set_features sg_seek sg_senddiag sg_ses sg_ses_microcode \
- sg_start sg_stpg sg_stream_ctl sg_sync sg_timestamp sg_turs sg_unmap \
- sg_verify sg_vpd sg_wr_mode sg_write_buffer sg_write_long \
- sg_write_same sg_write_verify sg_write_x sg_zone sg_z_act_query
+ sg_read_long sg_readcap sg_reassign sg_referrals sg_rep_density \
+ sg_rep_pip sg_rep_zones sg_requests sg_reset_wp sg_rmsn sg_rtpg \
+ sg_safte sg_sanitize sg_sat_identify sg_sat_phy_event \
+ sg_sat_read_gplog sg_sat_set_features sg_seek sg_senddiag sg_ses \
+ sg_ses_microcode sg_start sg_stpg sg_stream_ctl sg_sync sg_timestamp \
+ sg_turs sg_unmap sg_verify sg_vpd sg_wr_mode sg_write_buffer \
+ sg_write_long sg_write_same sg_write_verify sg_write_x sg_zone \
+ sg_z_act_query
sg_scan_SOURCES =
@@ -134,6 +135,8 @@ sg_requests_LDADD = ../lib/libsgutils2.la
sg_referrals_LDADD = ../lib/libsgutils2.la
+sg_rep_density_LDADD = ../lib/libsgutils2.la
+
sg_rep_pip_LDADD = ../lib/libsgutils2.la
sg_rep_zones_LDADD = ../lib/libsgutils2.la
diff --git a/src/Makefile.in b/src/Makefile.in
index 39648d8c..b87b6af5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -97,8 +97,8 @@ bin_PROGRAMS = sg_bg_ctl$(EXEEXT) sg_compare_and_write$(EXEEXT) \
sg_raw$(EXEEXT) sg_rdac$(EXEEXT) sg_read_attr$(EXEEXT) \
sg_read_block_limits$(EXEEXT) sg_read_buffer$(EXEEXT) \
sg_read_long$(EXEEXT) sg_readcap$(EXEEXT) sg_reassign$(EXEEXT) \
- sg_referrals$(EXEEXT) sg_rep_pip$(EXEEXT) \
- sg_rep_zones$(EXEEXT) sg_requests$(EXEEXT) \
+ sg_referrals$(EXEEXT) sg_rep_density$(EXEEXT) \
+ sg_rep_pip$(EXEEXT) sg_rep_zones$(EXEEXT) sg_requests$(EXEEXT) \
sg_reset_wp$(EXEEXT) sg_rmsn$(EXEEXT) sg_rtpg$(EXEEXT) \
sg_safte$(EXEEXT) sg_sanitize$(EXEEXT) \
sg_sat_identify$(EXEEXT) sg_sat_phy_event$(EXEEXT) \
@@ -246,6 +246,9 @@ sg_reassign_DEPENDENCIES = ../lib/libsgutils2.la
sg_referrals_SOURCES = sg_referrals.c
sg_referrals_OBJECTS = sg_referrals.$(OBJEXT)
sg_referrals_DEPENDENCIES = ../lib/libsgutils2.la
+sg_rep_density_SOURCES = sg_rep_density.c
+sg_rep_density_OBJECTS = sg_rep_density.$(OBJEXT)
+sg_rep_density_DEPENDENCIES = ../lib/libsgutils2.la
sg_rep_pip_SOURCES = sg_rep_pip.c
sg_rep_pip_OBJECTS = sg_rep_pip.$(OBJEXT)
sg_rep_pip_DEPENDENCIES = ../lib/libsgutils2.la
@@ -405,12 +408,13 @@ am__depfiles_remade = ./$(DEPDIR)/sg_bg_ctl.Po \
./$(DEPDIR)/sg_read_block_limits.Po \
./$(DEPDIR)/sg_read_buffer.Po ./$(DEPDIR)/sg_read_long.Po \
./$(DEPDIR)/sg_readcap.Po ./$(DEPDIR)/sg_reassign.Po \
- ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rep_pip.Po \
- ./$(DEPDIR)/sg_rep_zones.Po ./$(DEPDIR)/sg_requests.Po \
- ./$(DEPDIR)/sg_reset.Po ./$(DEPDIR)/sg_reset_wp.Po \
- ./$(DEPDIR)/sg_rmsn.Po ./$(DEPDIR)/sg_rtpg.Po \
- ./$(DEPDIR)/sg_safte.Po ./$(DEPDIR)/sg_sanitize.Po \
- ./$(DEPDIR)/sg_sat_identify.Po ./$(DEPDIR)/sg_sat_phy_event.Po \
+ ./$(DEPDIR)/sg_referrals.Po ./$(DEPDIR)/sg_rep_density.Po \
+ ./$(DEPDIR)/sg_rep_pip.Po ./$(DEPDIR)/sg_rep_zones.Po \
+ ./$(DEPDIR)/sg_requests.Po ./$(DEPDIR)/sg_reset.Po \
+ ./$(DEPDIR)/sg_reset_wp.Po ./$(DEPDIR)/sg_rmsn.Po \
+ ./$(DEPDIR)/sg_rtpg.Po ./$(DEPDIR)/sg_safte.Po \
+ ./$(DEPDIR)/sg_sanitize.Po ./$(DEPDIR)/sg_sat_identify.Po \
+ ./$(DEPDIR)/sg_sat_phy_event.Po \
./$(DEPDIR)/sg_sat_read_gplog.Po \
./$(DEPDIR)/sg_sat_set_features.Po \
./$(DEPDIR)/sg_scan_linux.Po ./$(DEPDIR)/sg_scan_win32.Po \
@@ -454,17 +458,17 @@ SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c sg_dd.c \
sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \
sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \
sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \
- sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_pip.c \
- sg_rep_zones.c sg_requests.c sg_reset.c sg_reset_wp.c \
- sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c sg_sat_identify.c \
- sg_sat_phy_event.c sg_sat_read_gplog.c sg_sat_set_features.c \
- $(sg_scan_SOURCES) sg_seek.c sg_senddiag.c sg_ses.c \
- sg_ses_microcode.c sg_start.c sg_stpg.c sg_stream_ctl.c \
- sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
- sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
- sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \
- sg_xcopy.c sg_z_act_query.c sg_zone.c sginfo.c sgm_dd.c \
- sgp_dd.c
+ sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_density.c \
+ sg_rep_pip.c sg_rep_zones.c sg_requests.c sg_reset.c \
+ sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c \
+ sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \
+ sg_sat_set_features.c $(sg_scan_SOURCES) sg_seek.c \
+ sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \
+ sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c sg_timestamp.c \
+ sg_turs.c sg_unmap.c sg_verify.c $(sg_vpd_SOURCES) \
+ sg_wr_mode.c sg_write_buffer.c sg_write_long.c sg_write_same.c \
+ sg_write_verify.c sg_write_x.c sg_xcopy.c sg_z_act_query.c \
+ sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
sg_dd.c sg_decode_sense.c sg_emc_trespass.c sg_format.c \
sg_get_config.c sg_get_elem_status.c sg_get_lba_status.c \
@@ -472,17 +476,17 @@ DIST_SOURCES = sg_bg_ctl.c sg_compare_and_write.c sg_copy_results.c \
sg_map26.c sg_modes.c sg_opcodes.c sg_persist.c sg_prevent.c \
sg_raw.c sg_rbuf.c sg_rdac.c sg_read.c sg_read_attr.c \
sg_read_block_limits.c sg_read_buffer.c sg_read_long.c \
- sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_pip.c \
- sg_rep_zones.c sg_requests.c sg_reset.c sg_reset_wp.c \
- sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c sg_sat_identify.c \
- sg_sat_phy_event.c sg_sat_read_gplog.c sg_sat_set_features.c \
- $(am__sg_scan_SOURCES_DIST) sg_seek.c sg_senddiag.c sg_ses.c \
- sg_ses_microcode.c sg_start.c sg_stpg.c sg_stream_ctl.c \
- sg_sync.c sg_test_rwbuf.c sg_timestamp.c sg_turs.c sg_unmap.c \
- sg_verify.c $(sg_vpd_SOURCES) sg_wr_mode.c sg_write_buffer.c \
- sg_write_long.c sg_write_same.c sg_write_verify.c sg_write_x.c \
- sg_xcopy.c sg_z_act_query.c sg_zone.c sginfo.c sgm_dd.c \
- sgp_dd.c
+ sg_readcap.c sg_reassign.c sg_referrals.c sg_rep_density.c \
+ sg_rep_pip.c sg_rep_zones.c sg_requests.c sg_reset.c \
+ sg_reset_wp.c sg_rmsn.c sg_rtpg.c sg_safte.c sg_sanitize.c \
+ sg_sat_identify.c sg_sat_phy_event.c sg_sat_read_gplog.c \
+ sg_sat_set_features.c $(am__sg_scan_SOURCES_DIST) sg_seek.c \
+ sg_senddiag.c sg_ses.c sg_ses_microcode.c sg_start.c sg_stpg.c \
+ sg_stream_ctl.c sg_sync.c sg_test_rwbuf.c sg_timestamp.c \
+ sg_turs.c sg_unmap.c sg_verify.c $(sg_vpd_SOURCES) \
+ sg_wr_mode.c sg_write_buffer.c sg_write_long.c sg_write_same.c \
+ sg_write_verify.c sg_write_x.c sg_xcopy.c sg_z_act_query.c \
+ sg_zone.c sginfo.c sgm_dd.c sgp_dd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -689,6 +693,7 @@ sg_read_long_LDADD = ../lib/libsgutils2.la
sg_reassign_LDADD = ../lib/libsgutils2.la
sg_requests_LDADD = ../lib/libsgutils2.la
sg_referrals_LDADD = ../lib/libsgutils2.la
+sg_rep_density_LDADD = ../lib/libsgutils2.la
sg_rep_pip_LDADD = ../lib/libsgutils2.la
sg_rep_zones_LDADD = ../lib/libsgutils2.la
sg_reset_wp_LDADD = ../lib/libsgutils2.la
@@ -934,6 +939,10 @@ sg_referrals$(EXEEXT): $(sg_referrals_OBJECTS) $(sg_referrals_DEPENDENCIES) $(EX
@rm -f sg_referrals$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_referrals_OBJECTS) $(sg_referrals_LDADD) $(LIBS)
+sg_rep_density$(EXEEXT): $(sg_rep_density_OBJECTS) $(sg_rep_density_DEPENDENCIES) $(EXTRA_sg_rep_density_DEPENDENCIES)
+ @rm -f sg_rep_density$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sg_rep_density_OBJECTS) $(sg_rep_density_LDADD) $(LIBS)
+
sg_rep_pip$(EXEEXT): $(sg_rep_pip_OBJECTS) $(sg_rep_pip_DEPENDENCIES) $(EXTRA_sg_rep_pip_DEPENDENCIES)
@rm -f sg_rep_pip$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sg_rep_pip_OBJECTS) $(sg_rep_pip_LDADD) $(LIBS)
@@ -1132,6 +1141,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_readcap.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_reassign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_referrals.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_density.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_pip.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_rep_zones.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_requests.Po@am__quote@ # am--include-marker
@@ -1366,6 +1376,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/sg_readcap.Po
-rm -f ./$(DEPDIR)/sg_reassign.Po
-rm -f ./$(DEPDIR)/sg_referrals.Po
+ -rm -f ./$(DEPDIR)/sg_rep_density.Po
-rm -f ./$(DEPDIR)/sg_rep_pip.Po
-rm -f ./$(DEPDIR)/sg_rep_zones.Po
-rm -f ./$(DEPDIR)/sg_requests.Po
@@ -1485,6 +1496,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/sg_readcap.Po
-rm -f ./$(DEPDIR)/sg_reassign.Po
-rm -f ./$(DEPDIR)/sg_referrals.Po
+ -rm -f ./$(DEPDIR)/sg_rep_density.Po
-rm -f ./$(DEPDIR)/sg_rep_pip.Po
-rm -f ./$(DEPDIR)/sg_rep_zones.Po
-rm -f ./$(DEPDIR)/sg_requests.Po
diff --git a/src/sg_rep_density.c b/src/sg_rep_density.c
new file mode 100644
index 00000000..5c68b679
--- /dev/null
+++ b/src/sg_rep_density.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <getopt.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "sg_lib.h"
+#include "sg_lib_data.h"
+#include "sg_pt.h"
+#include "sg_cmds_basic.h"
+#include "sg_unaligned.h"
+#include "sg_pr2serr.h"
+
+/* A utility program originally written for the Linux OS SCSI subsystem.
+ *
+ *
+ * This program issues the SCSI REPORT DENSITY SUPPORT command to the given
+ * SCSI (tape) device and outputs the response. Based on ssc5r06.pdf
+ */
+
+static const char * version_str = "1.00 20220120";
+
+#define MAX_RDS_BUFF_LEN (64 * 1024 - 1)
+#define DEF_RDS_BUFF_LEN 4096
+
+#define REPORT_DENSITY_SUPPORT_CMD 0x44
+#define REPORT_DENSITY_SUPPORT_CMDLEN 10
+
+#define RDS_DENSITY_DESC_LEN 52
+#define RDS_MEDIUM_T_DESC_LEN 56
+
+#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
+#define DEF_PT_TIMEOUT 60 /* 60 seconds */
+
+static const char * rds_s = "Report density support";
+
+
+static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"hex", no_argument, 0, 'H'},
+ {"in", required_argument, 0, 'i'}, /* silent, same as --inhex= */
+ {"inhex", required_argument, 0, 'i'},
+ {"maxlen", required_argument, 0, 'm'},
+ {"media", no_argument, 0, 'M'}, /* Media field; byte 1, bit 0 */
+ {"raw", no_argument, 0, 'r'},
+ {"readonly", no_argument, 0, 'R'},
+ {"typem", no_argument, 0, 't'}, /* Medium type field, byte 1, bit 1 */
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0},
+};
+
+
+static void
+usage(void)
+{
+ pr2serr("Usage: "
+ "sg_rep_density [--help] [--hex] [--inhex=FN] [--maxlen=LEN] "
+ "[--media]\n"
+ " [--raw] [--readonly] [--typem] [--verbose] "
+ "[--version]\n"
+ " DEVICE\n");
+ pr2serr(" where:\n"
+ " --help|-h prints out this usage message\n"
+ " --hex|-H output response in hexadecimal "
+ "(default); used\n"
+ " twice: hex without addresses at start "
+ "of line\n"
+ " --inhex=FN decode contents of FN, ignore DEVICE\n"
+ " --maxlen=LEN|-m LEN max response length (allocation "
+ "length in cdb)\n"
+ " (def: 512 bytes)\n"
+ " --media|-M report on media in drive (def: report "
+ "on drive)\n"
+ " --raw|-r output response in binary\n"
+ " --readonly|-R open DEVICE read-only (def: read-write)\n"
+ " --typem|-t report medium types (def: density "
+ "codes)\n"
+ " --verbose|-v increase verbosity\n"
+ " --version|-V print version string and exit\n\n"
+ "Sends a SCSI REPORT DENSITY SUPPORT command outputs the "
+ "response in\nASCII hexadecimal or binary. By default it reports "
+ "on density codes supported\nby the drive (LU).\n");
+}
+
+/* Invokes a SCSI REPORT PROVISIONING INITIALIZATION PATTERN command (SBC).
+ * Return of 0 -> success, various SG_LIB_CAT_* positive values or
+ * -1 -> other errors */
+static int
+sg_ll_report_density(int sg_fd, bool media, bool m_type, void * resp,
+ int mx_resp_len, int * residp, bool noisy, int verbose)
+{
+ int ret, res, sense_cat;
+ uint8_t rds_cdb[REPORT_DENSITY_SUPPORT_CMDLEN] =
+ {REPORT_DENSITY_SUPPORT_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t sense_b[SENSE_BUFF_LEN] = {0};
+ struct sg_pt_base * ptvp;
+
+ if (media)
+ rds_cdb[1] |= 0x1;
+ if (m_type)
+ rds_cdb[1] |= 0x2;
+ sg_put_unaligned_be16((uint16_t)mx_resp_len, rds_cdb + 7);
+ if (verbose) {
+ char b[128];
+
+ pr2serr(" %s cdb: %s\n", rds_s,
+ sg_get_command_str(rds_cdb, REPORT_DENSITY_SUPPORT_CMDLEN,
+ false, sizeof(b), b));
+ }
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ pr2serr("%s: out of memory\n", __func__);
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, rds_cdb, sizeof(rds_cdb));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, rds_s, res, noisy, verbose, &sense_cat);
+ if (-1 == ret) {
+ if (get_scsi_pt_transport_err(ptvp))
+ ret = SG_LIB_TRANSPORT_ERROR;
+ else
+ ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
+ } else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = sense_cat;
+ break;
+ }
+ } else
+ ret = 0;
+ if (residp)
+ *residp = get_scsi_pt_resid(ptvp);
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
+static void
+decode_medium_type(const uint8_t * up, int num_desc)
+{
+ int k, j, n, q;
+
+ for (k = 0; k < num_desc; ++k, up += RDS_MEDIUM_T_DESC_LEN) {
+ if (0 == k)
+ printf("Medium type descriptor%s\n", ((num_desc > 1) ? "s" : ""));
+ printf(" descriptor %d\n", k + 1);
+ printf(" Medium type: %u\n", up[0]);
+ n = up[4];
+ printf(" Number of density codes: %d\n", n);
+ if (n > 9)
+ n = 9;
+ for (j = 0; j < n; ++j) {
+ q = up[5 + j];
+ if (q > 0)
+ printf(" Primary density code: %d\n", q);
+ }
+ printf(" Media width: %u\n", sg_get_unaligned_be16(up + 14));
+ printf(" Medium length: %u\n", sg_get_unaligned_be16(up + 16));
+ printf(" Assigning organization: %.8s\n", (const char *)(up + 20));
+ printf(" Medium type name: %.8s\n", (const char *)(up + 28));
+ printf(" Description: %.20s\n", (const char *)(up + 36));
+ }
+}
+
+static void
+decode_density_code(const uint8_t * up, int num_desc)
+{
+ int k;
+
+ for (k = 0; k < num_desc; ++k, up += RDS_DENSITY_DESC_LEN) {
+ if (0 == k)
+ printf("Density support data block descriptor%s\n",
+ ((num_desc > 1) ? "s" : ""));
+ printf(" descriptor %d\n", k + 1);
+ printf(" Primary density code: %u\n", up[0]);
+ printf(" Secondary density code: %u\n", up[1]);
+ printf(" WRT: %u\n", !!(0x80 & up[2]));
+ printf(" DUP: %u\n", !!(0x40 & up[2]));
+ printf(" DEFLT: %u\n", !!(0x20 & up[2]));
+ printf(" DLV: %u\n", !!(0x1 & up[2]));
+ printf(" Bits per mm: %u\n", sg_get_unaligned_be24(up + 5));
+ printf(" Media width: %u\n", sg_get_unaligned_be16(up + 8));
+ printf(" Tracks: %u\n", sg_get_unaligned_be16(up + 10));
+ printf(" Capacity: %u\n", sg_get_unaligned_be32(up + 12));
+ printf(" Assigning organization: %.8s\n", (const char *)(up + 16));
+ printf(" Density name: %.8s\n", (const char *)(up + 24));
+ printf(" Description: %.20s\n", (const char *)(up + 32));
+ }
+}
+
+static void
+dStrRaw(const uint8_t * str, int len)
+{
+ int k;
+
+ for (k = 0; k < len; ++k)
+ printf("%c", str[k]);
+}
+
+
+int
+main(int argc, char * argv[])
+{
+ bool do_raw = false;
+ bool media = false;
+ bool m_type = false;
+ bool no_final_msg = false;
+ bool o_readonly = false;
+ bool verbose_given = false;
+ bool version_given = false;
+ int res, c, rlen, desc_len, ads_len, num_desc;
+ int resid = 0;
+ int sg_fd = -1;
+ int do_help = 0;
+ int do_hex = 0;
+ int maxlen = 0;
+ int in_len = 0;
+ int ret = 0;
+ int verbose = 0;
+ const char * device_name = NULL;
+ const char * inhex_fn = NULL;
+ uint8_t * rdsBuff = NULL;
+ uint8_t * free_rds = NULL;
+ char b[80];
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hHi:m:MrRtvV", long_options,
+ &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ ++do_help;
+ break;
+ case 'H':
+ ++do_hex;
+ break;
+ case 'i':
+ inhex_fn = optarg;
+ break;
+ case 'm':
+ maxlen = sg_get_num(optarg);
+ if ((maxlen < 0) || (maxlen > MAX_RDS_BUFF_LEN)) {
+ pr2serr("argument to '--maxlen' should be %d or less\n",
+ MAX_RDS_BUFF_LEN);
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ break;
+ case 'M':
+ media = true;
+ break;
+ case 'r':
+ do_raw = true;
+ break;
+ case 'R':
+ o_readonly = true;
+ break;
+ case 't':
+ m_type = true;
+ break;
+ case 'v':
+ verbose_given = true;
+ ++verbose;
+ break;
+ case 'V':
+ version_given = true;
+ break;
+ default:
+ pr2serr("unrecognised option code 0x%x ??\n", c);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+ if (optind < argc) {
+ if (NULL == device_name) {
+ device_name = argv[optind];
+ ++optind;
+ }
+ if (optind < argc) {
+ for (; optind < argc; ++optind)
+ pr2serr("Unexpected extra argument: %s\n", argv[optind]);
+ usage();
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ }
+#ifdef DEBUG
+ pr2serr("In DEBUG mode, ");
+ if (verbose_given && version_given) {
+ pr2serr("but override: '-vV' given, zero verbose and continue\n");
+ verbose_given = false;
+ version_given = false;
+ verbose = 0;
+ } else if (! verbose_given) {
+ pr2serr("set '-vv'\n");
+ verbose = 2;
+ } else
+ pr2serr("keep verbose=%d\n", verbose);
+#else
+ if (verbose_given && version_given)
+ pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
+#endif
+ if (version_given) {
+ pr2serr("version: %s\n", version_str);
+ return 0;
+ }
+
+ if (do_help) {
+ usage();
+ return 0;
+ }
+ if (device_name && inhex_fn) {
+ pr2serr("ignoring DEVICE, best to give DEVICE or --inhex=FN, but "
+ "not both\n");
+ device_name = NULL;
+ }
+ if (0 == maxlen)
+ maxlen = DEF_RDS_BUFF_LEN;
+ rdsBuff = (uint8_t *)sg_memalign(maxlen, 0, &free_rds, verbose > 3);
+ if (NULL == rdsBuff) {
+ pr2serr("unable to sg_memalign %d bytes\n", maxlen);
+ return sg_convert_errno(ENOMEM);
+ }
+ if (NULL == device_name) {
+ if (inhex_fn) {
+ if ((ret = sg_f2hex_arr(inhex_fn, do_raw, false, rdsBuff,
+ &in_len, maxlen))) {
+ if (SG_LIB_LBA_OUT_OF_RANGE == ret) {
+ no_final_msg = true;
+ pr2serr("... decode what we have, --maxlen=%d needs to "
+ "be increased\n", maxlen);
+ } else
+ goto the_end;
+ }
+ if (verbose > 2)
+ pr2serr("Read %d [0x%x] bytes of user supplied data\n",
+ in_len, in_len);
+ if (do_raw)
+ do_raw = false; /* otherwise interferes with decoding */
+ if (in_len < 4) {
+ pr2serr("--inhex=%s only decoded %d bytes (needs 4 at "
+ "least)\n", inhex_fn, in_len);
+ ret = SG_LIB_SYNTAX_ERROR;
+ goto the_end;
+ }
+ res = 0;
+ maxlen = in_len;
+ goto start_response;
+ } else {
+ pr2serr("missing device name!\n\n");
+ usage();
+ ret = SG_LIB_FILE_ERROR;
+ no_final_msg = true;
+ goto the_end;
+ }
+ } else
+ in_len = 0;
+
+ if (do_raw) {
+ if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
+ perror("sg_set_binary_mode");
+ ret = SG_LIB_FILE_ERROR;
+ no_final_msg = true;
+ goto the_end;
+ }
+ }
+
+ sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
+ if (sg_fd < 0) {
+ if (verbose)
+ pr2serr("open error: %s: %s\n", device_name,
+ safe_strerror(-sg_fd));
+ ret = sg_convert_errno(-sg_fd);
+ goto the_end;
+ }
+
+ res = sg_ll_report_density(sg_fd, media, m_type, rdsBuff, maxlen, &resid,
+ true, verbose);
+start_response:
+ ret = res;
+ if (0 == res) {
+ rlen = maxlen - resid;
+ if (rlen < 4) {
+ pr2serr("Response length (%d) too short\n", rlen);
+ ret = SG_LIB_CAT_MALFORMED;
+ goto the_end;
+ }
+ if (do_raw) {
+ dStrRaw(rdsBuff, rlen);
+ goto the_end;
+ }
+ if (do_hex) {
+ if (2 != do_hex)
+ hex2stdout(rdsBuff, rlen, ((1 == do_hex) ? 1 : -1));
+ else
+ hex2stdout(rdsBuff, rlen, 0);
+ goto the_end;
+ }
+ desc_len = m_type ? RDS_MEDIUM_T_DESC_LEN : RDS_DENSITY_DESC_LEN;
+ ads_len = sg_get_unaligned_be16(rdsBuff + 0) + 2;
+ if (4 == ads_len)
+ goto the_end;
+ if (ads_len < 4) {
+ pr2serr("Badly formatted response, ads_len=%d\n", ads_len - 2);
+ ret = SG_LIB_CAT_MALFORMED;
+ goto the_end;
+ }
+ if (ads_len > rlen) {
+ if (verbose)
+ pr2serr("Trimming response from %d to %d bytes\n", ads_len,
+ rlen);
+ ads_len = rlen;
+ if (4 == ads_len)
+ goto the_end;
+ }
+ num_desc = (ads_len - 4) / desc_len;
+ if (0 != ((ads_len - 4) % desc_len)) {
+ if (verbose)
+ pr2serr("Truncating response to %d descriptors\n", num_desc);
+ }
+ if (m_type)
+ decode_medium_type(rdsBuff + 4, num_desc);
+ else
+ decode_density_code(rdsBuff + 4, num_desc);
+ } else if (SG_LIB_CAT_INVALID_OP == res)
+ pr2serr("%s command not supported\n", rds_s);
+ else {
+ sg_get_category_sense_str(res, sizeof(b), b, verbose);
+ pr2serr("%s command: %s\n", rds_s, b);
+ }
+
+the_end:
+ if (free_rds)
+ free(free_rds);
+ if (sg_fd >= 0) {
+ res = sg_cmds_close_device(sg_fd);
+ if (res < 0) {
+ pr2serr("close error: %s\n", safe_strerror(-res));
+ if (0 == ret)
+ ret = sg_convert_errno(-res);
+ }
+ }
+ if ((0 == verbose) && (! no_final_msg)) {
+ if (! sg_if_can2stderr("sg_rep_density failed: ", ret))
+ pr2serr("Some error occurred, try again with '-v' "
+ "or '-vv' for more information\n");
+ }
+ return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
+}
diff --git a/src/sg_rep_pip.c b/src/sg_rep_pip.c
index 2f6127e1..d3ed0852 100644
--- a/src/sg_rep_pip.c
+++ b/src/sg_rep_pip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2021 Douglas Gilbert.
+ * Copyright (c) 2014-2022 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.
@@ -39,7 +39,7 @@
* sbc4r21.pdf
*/
-static const char * version_str = "1.03 20211114";
+static const char * version_str = "1.04 20220120";
#define MAX_RPIP_BUFF_LEN (1024 * 1024)
#define DEF_RPIP_BUFF_LEN 512
@@ -99,18 +99,18 @@ sg_ll_report_pip(int sg_fd, void * resp, int mx_resp_len, int * residp,
bool noisy, int verbose)
{
int ret, res, sense_cat;
- uint8_t rz_cdb[SG_MAINT_IN_CMDLEN] =
+ uint8_t rpip_cdb[SG_MAINT_IN_CMDLEN] =
{SG_MAINTENANCE_IN, REPORT_PROVISIONING_INITIALIZATION_PATTERN_SA,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t sense_b[SENSE_BUFF_LEN] = {0};
struct sg_pt_base * ptvp;
- sg_put_unaligned_be32((uint32_t)mx_resp_len, rz_cdb + 6);
+ sg_put_unaligned_be32((uint32_t)mx_resp_len, rpip_cdb + 6);
if (verbose) {
char b[128];
pr2serr(" %s cdb: %s\n", rpip_s,
- sg_get_command_str(rz_cdb, SG_MAINT_IN_CMDLEN, false,
+ sg_get_command_str(rpip_cdb, SG_MAINT_IN_CMDLEN, false,
sizeof(b), b));
}
ptvp = construct_scsi_pt_obj();
@@ -118,7 +118,7 @@ sg_ll_report_pip(int sg_fd, void * resp, int mx_resp_len, int * residp,
pr2serr("%s: out of memory\n", __func__);
return -1;
}
- set_scsi_pt_cdb(ptvp, rz_cdb, sizeof(rz_cdb));
+ set_scsi_pt_cdb(ptvp, rpip_cdb, sizeof(rpip_cdb));
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
@@ -166,7 +166,7 @@ main(int argc, char * argv[])
int res, c, resid, rlen;
int sg_fd = -1;
int do_help = 0;
- int do_hex = 1;
+ int do_hex = 0;
int maxlen = 0;
int ret = 0;
int verbose = 0;
@@ -256,7 +256,7 @@ main(int argc, char * argv[])
return 0;
}
if (NULL == device_name) {
- pr2serr("missing device name!\n");
+ pr2serr("missing device name!\n\n");
usage();
return SG_LIB_SYNTAX_ERROR;
}
@@ -297,8 +297,15 @@ main(int argc, char * argv[])
dStrRaw(rpipBuff, rlen);
goto the_end;
}
- if (do_hex && (2 != do_hex)) {
- hex2stdout(rpipBuff, rlen, ((1 == do_hex) ? 1 : -1));
+ if (do_hex) {
+ if (2 != do_hex)
+ hex2stdout(rpipBuff, rlen, ((1 == do_hex) ? 1 : -1));
+ else
+ hex2stdout(rpipBuff, rlen, 0);
+ goto the_end;
+ } else {
+ printf("Printing response in hex:\n");
+ hex2stdout(rpipBuff, rlen, 1);
goto the_end;
}
} else if (SG_LIB_CAT_INVALID_OP == res)