aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-01-23 16:25:58 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-01-23 16:25:58 +0000
commita918d1a30569c4d3f09cc87836ff19215db6d8b7 (patch)
tree9d75cdc5dc54583fd103800abbd732e4d1fe5023 /src
parente168d3764b642fd96aac1c65f83a64af994ee111 (diff)
downloadsg3_utils-a918d1a30569c4d3f09cc87836ff19215db6d8b7.tar.gz
sg_xcopy: add --fco (fast copy only) (spc5r20), implement --app=1 (append) on regular OFILE type; sg_tst_bidi work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@808 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r--src/sg_vpd.c88
-rw-r--r--src/sg_xcopy.c17
2 files changed, 74 insertions, 31 deletions
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index 04d5110d..ed55d90f 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -40,7 +40,7 @@
*/
-static const char * version_str = "1.49 20190109"; /* spc5r20 + sbc4r15 */
+static const char * version_str = "1.50 20190119"; /* spc5r20 + sbc4r15 */
/* standard VPD pages, in ascending page number order */
#define VPD_SUPPORTED_VPDS 0x0
@@ -152,9 +152,10 @@ static int svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue,
static int svpd_unable_to_decode(int sg_fd, struct opts_t * op, int subvalue,
int off);
-static int decode_dev_ids(const char * print_if_found, uint8_t * buff,
- int len, int m_assoc, int m_desig_type,
- int m_code_set, const struct opts_t * op);
+static int decode_dev_ids(const char * print_if_found, int num_leading,
+ uint8_t * buff, int len, int m_assoc,
+ int m_desig_type, int m_code_set,
+ const struct opts_t * op);
uint8_t * rsp_buff;
const int rsp_buff_sz = MX_ALLOC_LEN + 2;
@@ -746,23 +747,23 @@ decode_id_vpd(uint8_t * buff, int len, int subvalue,
m_d = -1;
m_cs = -1;
if (0 == subvalue) {
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), b, blen,
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
VPD_ASSOC_LU, m_d, m_cs, op);
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), b, blen,
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b, blen,
VPD_ASSOC_TPORT, m_d, m_cs, op);
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), b, blen,
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0, b, blen,
VPD_ASSOC_TDEVICE, m_d, m_cs, op);
} else if (VPD_DI_SEL_AS_IS == subvalue)
- decode_dev_ids(NULL, b, blen, m_a, m_d, m_cs, op);
+ decode_dev_ids(NULL, 0, b, blen, m_a, m_d, m_cs, op);
else {
if (VPD_DI_SEL_LU & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), b, blen,
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_LU), 0, b, blen,
VPD_ASSOC_LU, m_d, m_cs, op);
if (VPD_DI_SEL_TPORT & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), b, blen,
- VPD_ASSOC_TPORT, m_d, m_cs, op);
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TPORT), 0, b,
+ blen, VPD_ASSOC_TPORT, m_d, m_cs, op);
if (VPD_DI_SEL_TARGET & subvalue)
- decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE),
+ decode_dev_ids(sg_get_desig_assoc_str(VPD_ASSOC_TDEVICE), 0,
b, blen, VPD_ASSOC_TDEVICE, m_d, m_cs, op);
}
}
@@ -925,8 +926,8 @@ decode_scsi_ports_vpd(uint8_t * buff, int len, const struct opts_t * op)
} else {
if ((0 == op->do_quiet) || (ip_tid_len > 0))
printf(" Target port descriptor(s):\n");
- decode_dev_ids("SCSI Ports", bp + bump + 4, tpd_len,
- VPD_ASSOC_TPORT, -1, -1, op);
+ decode_dev_ids("", 2 /* leading spaces */, bp + bump + 4,
+ tpd_len, VPD_ASSOC_TPORT, -1, -1, op);
}
}
bump += tpd_len + 4;
@@ -1133,18 +1134,25 @@ decode_dev_ids_quiet(uint8_t * buff, int len, int m_assoc,
/* Prints outs designation descriptors (dd_s)selected by association,
designator type and/or code set. */
static int
-decode_dev_ids(const char * print_if_found, uint8_t * buff, int len,
- int m_assoc, int m_desig_type, int m_code_set,
+decode_dev_ids(const char * print_if_found, int num_leading, uint8_t * buff,
+ int len, int m_assoc, int m_desig_type, int m_code_set,
const struct opts_t * op)
{
int assoc, off, u, i_len;
bool printed;
const uint8_t * bp;
char b[1024];
+ char sp[82];
if (op->do_quiet)
return decode_dev_ids_quiet(buff, len, m_assoc, m_desig_type,
m_code_set);
+ if (num_leading > (int)(sizeof(sp) - 2))
+ num_leading = sizeof(sp) - 2;
+ if (num_leading > 0)
+ snprintf(sp, sizeof(sp), "%*c", num_leading, ' ');
+ else
+ sp[0] = '\0';
if (buff[2] != 0) { /* all valid dd_s should have 0 in this byte */
if (op->verbose)
pr2serr("%s: designation descriptors byte 2 should be 0\n"
@@ -1166,11 +1174,12 @@ decode_dev_ids(const char * print_if_found, uint8_t * buff, int len,
assoc = ((bp[1] >> 4) & 0x3);
if (print_if_found && (! printed)) {
printed = true;
- printf(" %s:\n", print_if_found);
+ if (strlen(print_if_found) > 0)
+ printf(" %s:\n", print_if_found);
}
if (NULL == print_if_found)
- printf(" %s:\n", sg_get_desig_assoc_str(assoc));
- sg_get_designation_descriptor_str("", bp, i_len + 4, false,
+ printf(" %s%s:\n", sp, sg_get_desig_assoc_str(assoc));
+ sg_get_designation_descriptor_str(sp, bp, i_len + 4, false,
op->do_long, sizeof(b), b);
printf("%s", b);
}
@@ -1603,6 +1612,7 @@ decode_rod_descriptor(const uint8_t * buff, int len)
{
const uint8_t * bp = buff;
int k, bump;
+ uint64_t ul;
for (k = 0; k < len; k += bump, bp += bump) {
bump = sg_get_unaligned_be16(bp + 2) + 4;
@@ -1613,26 +1623,46 @@ decode_rod_descriptor(const uint8_t * buff, int len)
sg_get_unaligned_be16(bp + 6));
printf(" Maximum Bytes in block ROD: %" PRIu64 "\n",
sg_get_unaligned_be64(bp + 8));
- printf(" Optimal Bytes in block ROD transfer: %" PRIu64 "\n",
- sg_get_unaligned_be64(bp + 16));
- printf(" Optimal Bytes to token per segment: %" PRIu64 "\n",
- sg_get_unaligned_be64(bp + 24));
- printf(" Optimal Bytes from token per segment:"
- " %" PRIu64 "\n", sg_get_unaligned_be64(bp + 32));
+ ul = sg_get_unaligned_be64(bp + 16);
+ printf(" Optimal Bytes in block ROD transfer: ");
+ if (SG_LIB_UNBOUNDED_64BIT == ul)
+ printf("-1 [no limit]\n");
+ else
+ printf("%" PRIu64 "\n", ul);
+ ul = sg_get_unaligned_be64(bp + 24);
+ printf(" Optimal Bytes to token per segment: ");
+ if (SG_LIB_UNBOUNDED_64BIT == ul)
+ printf("-1 [no limit]\n");
+ else
+ printf("%" PRIu64 "\n", ul);
+ ul = sg_get_unaligned_be64(bp + 32);
+ printf(" Optimal Bytes from token per segment: ");
+ if (SG_LIB_UNBOUNDED_64BIT == ul)
+ printf("-1 [no limit]\n");
+ else
+ printf("%" PRIu64 "\n", ul);
break;
case 1:
/* Stream ROD device type specific descriptor */
printf(" Maximum Bytes in stream ROD: %" PRIu64 "\n",
sg_get_unaligned_be64(bp + 8));
- printf(" Optimal Bytes in stream ROD transfer:"
- " %" PRIu64 "\n", sg_get_unaligned_be64(bp + 16));
+ ul = sg_get_unaligned_be64(bp + 16);
+ printf(" Optimal Bytes in stream ROD transfer: ");
+ if (SG_LIB_UNBOUNDED_64BIT == ul)
+ printf("-1 [no limit]\n");
+ else
+ printf("%" PRIu64 "\n", ul);
break;
case 3:
/* Copy manager ROD device type specific descriptor */
printf(" Maximum Bytes in processor ROD: %" PRIu64 "\n",
sg_get_unaligned_be64(bp + 8));
- printf(" Optimal Bytes in processor ROD transfer:"
- " %" PRIu64 "\n", sg_get_unaligned_be64(bp + 16));
+ ul = sg_get_unaligned_be64(bp + 16);
+ printf(" Optimal Bytes in processor ROD transfer: ");
+ if (SG_LIB_UNBOUNDED_64BIT == ul)
+ printf("-1 [no limit]\n");
+ else
+ printf("%" PRIu64 "\n", ul);
break;
default:
printf(" Unhandled descriptor (format %d, device type %d)\n",
diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c
index 6bfd1dba..c0b53a88 100644
--- a/src/sg_xcopy.c
+++ b/src/sg_xcopy.c
@@ -1,7 +1,7 @@
/* A utility program for copying files. Similar to 'dd' but using
* the 'Extended Copy' command.
*
- * Copyright (c) 2011-2018 Hannes Reinecke, SUSE Labs
+ * Copyright (c) 2011-2019 Hannes Reinecke, SUSE Labs
*
* Largely taken from 'sg_dd', which has the
*
@@ -69,7 +69,7 @@
#include "sg_unaligned.h"
#include "sg_pr2serr.h"
-static const char * version_str = "0.68 20180811";
+static const char * version_str = "0.69 20190120";
#define ME "sg_xcopy: "
@@ -172,6 +172,7 @@ static bool do_time = false;
static bool start_tm_valid = false;
static bool xcopy_flag_cat = false;
static bool xcopy_flag_dc = false;
+static bool xcopy_flag_fco = false; /* fast copy only, spc5r20 */
static int blk_sz = 0;
static int list_id_usage = -1;
static int priority = 1;
@@ -533,6 +534,7 @@ primary_help:
" conv ignored\n"
" count number of blocks to copy (def: device size)\n"
" dc xcopy segment descriptor DC bit (default: 0)\n"
+ " fco xcopy segment descriptor FCO bit (default: 0)\n"
" ibs input block size (if given must be same as "
"'bs=')\n"
" id_usage sets list_id_usage field to hold (0), "
@@ -596,6 +598,8 @@ scsi_encode_seg_desc(uint8_t *seg_desc, int seg_desc_type,
seg_desc[1] |= 0x1;
if (xcopy_flag_dc)
seg_desc[1] |= 0x2;
+ if (xcopy_flag_fco)
+ seg_desc[1] |= 0x4;
if (seg_desc_type == 0x02) {
seg_desc_len = 0x18;
seg_desc[4] = 0;
@@ -1260,6 +1264,8 @@ open_of(struct xcopy_fp_t * ofp, int vb)
flags = O_RDWR | O_NONBLOCK;
if (ofp->excl)
flags |= O_EXCL;
+ if (ofp->append)
+ flags |= O_APPEND;
if ((outfd = open(ofp->fname, flags)) < 0) {
err = errno;
snprintf(ebuff, EBUFF_SZ,
@@ -1409,6 +1415,13 @@ main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
xcopy_flag_dc = !! n;
+ } else if (0 == strcmp(key, "fco")) {
+ n = sg_get_num(buf);
+ if (n < 0 || n > 1) {
+ pr2serr(ME "bad argument to 'fco='\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
+ xcopy_flag_fco = !! n;
} else if (0 == strcmp(key, "ibs")) {
ibs = sg_get_num(buf);
} else if (strcmp(key, "if") == 0) {