diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2013-06-28 17:44:32 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2013-06-28 17:44:32 +0000 |
commit | 43c7d125abce23c3d72346ae3e0b18287047e3be (patch) | |
tree | 85b7550513005c640b9ff9756328e250ea8d7122 /src | |
parent | e9d9937bb92e1b630020c3a9c2d8b09e5bd20036 (diff) | |
download | sg3_utils-43c7d125abce23c3d72346ae3e0b18287047e3be.tar.gz |
sg_persist+sg_unmap: fix crash on option decode; sg_logs: expand for tape; sg_xcopy+: clean
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@500 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_copy_results.c | 8 | ||||
-rw-r--r-- | src/sg_logs.c | 679 | ||||
-rw-r--r-- | src/sg_persist.c | 4 | ||||
-rw-r--r-- | src/sg_unmap.c | 6 | ||||
-rw-r--r-- | src/sg_xcopy.c | 204 |
5 files changed, 635 insertions, 266 deletions
diff --git a/src/sg_copy_results.c b/src/sg_copy_results.c index b8c7599c..20c32815 100644 --- a/src/sg_copy_results.c +++ b/src/sg_copy_results.c @@ -34,7 +34,7 @@ and the optional list identifier passed as the list_id argument. */ -static const char * version_str = "1.1 20130507"; +static const char * version_str = "1.2 20130627"; #define MAX_XFER_LEN 10000 @@ -399,6 +399,12 @@ main(int argc, char * argv[]) "\t\txfer_len= %d (0x%x), sa=%d, list_id=%d\n", device_name, xfer_len, xfer_len, sa, list_id); + /* In SPC-4 opcode 0x84, service actions have command names: + * 0x0 RECEIVE COPY STATUS(LID1) + * 0x1 RECEIVE COPY DATA(LID1) + * 0x3 RECEIVE COPY OPERATING PARAMETERS + * 0x4 RECEIVE COPY FAILURE DETAILS(LID1) + */ res = sg_ll_receive_copy_results(sg_fd, sa, list_id, cpResultBuff, xfer_len, 0, verbose); ret = res; diff --git a/src/sg_logs.c b/src/sg_logs.c index 6b04165f..c765b041 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -25,7 +25,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" -static const char * version_str = "1.11 20130517"; /* spc4r35 + sbc3r30 */ +static const char * version_str = "1.12 20130621"; /* spc4r35 + sbc3r30 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -170,7 +170,8 @@ usage() "0x18) log page\n" " --verbose|-v increase verbosity\n" " --version|-V output version string then exit\n\n" - "Performs a SCSI LOG SENSE (or LOG SELECT) command\n"); + "Performs a SCSI LOG SENSE (or LOG SELECT) command and decodes " + "the response.\n"); } static void @@ -568,6 +569,28 @@ dStrRaw(const char* str, int len) printf("%c", str[k]); } +/* Decode counter up to 8 chars long (big endian) into an uint64_t. + * In the unlikely event that the counter is larger than 8 chars long + * then take the last 8 chars. */ +static uint64_t +decode_count(const unsigned char * xp, int len) +{ + int j; + uint64_t ull; + + if (len > (int)sizeof(ull)) { + xp += (len - sizeof(ull)); + len = sizeof(ull); + } + ull = 0; + for (j = 0; j < len; ++j) { + if (j > 0) + ull <<= 8; + ull |= xp[j]; + } + return ull; +} + /* Call LOG SENSE twice: the first time ask for 4 byte response to determine actual length of response; then a second time requesting the min(actual_len, mx_resp_len) bytes. If the calculated length for the @@ -785,11 +808,9 @@ show_page_name(int pg_code, int subpg_code, break; case 0x16: printf("%sTape diagnostic (ssc-3)\n", b); - done = 0; break; case 0x17: printf("%sVolume statistics (ssc-4)\n", b); - done = 0; break; case 0x1b: printf("%sData compression (ssc-4)\n", b); @@ -854,11 +875,9 @@ show_page_name(int pg_code, int subpg_code, break; case 0x15: printf("%sService buffers information (adc)\n", b); - done = 0; break; case 0x16: printf("%sTape diagnostic (adc)\n", b); - done = 0; break; default: done = 0; @@ -908,10 +927,8 @@ get_pcb_str(int pcb, char * outp, int maxoutlen) static void show_buffer_under_overrun_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, count_basis, cause, pcb; + int num, pl, count_basis, cause, pcb; unsigned char * ucp; - unsigned char * xp; - uint64_t ull; char pcb_str[PCB_STR_LEN]; printf("Buffer over-run/under-run page\n"); @@ -945,19 +962,7 @@ show_buffer_under_overrun_page(unsigned char * resp, int len, int show_pcb) else printf("under-run"); printf(", count"); - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } - printf(" = %" PRIu64 "", ull); + printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); } if (show_pcb) { pcb = ucp[2]; @@ -975,10 +980,8 @@ show_buffer_under_overrun_page(unsigned char * resp, int len, int show_pcb) static void show_error_counter_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; - uint64_t ull; char pcb_str[PCB_STR_LEN]; switch(resp[0] & 0x3f) { @@ -1016,19 +1019,7 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb) case 0x8015: printf(" Positioning errors [Hitachi]"); break; default: printf(" Reserved or vendor specific [0x%x]", pc); break; } - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } - printf(" = %" PRIu64 "", ull); + printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -1043,10 +1034,8 @@ show_error_counter_page(unsigned char * resp, int len, int show_pcb) static void show_non_medium_error_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; - uint64_t ull; char pcb_str[PCB_STR_LEN]; printf("Non-medium error page\n"); @@ -1066,19 +1055,7 @@ show_non_medium_error_page(unsigned char * resp, int len, int show_pcb) printf(" Vendor specific [0x%x]", pc); break; } - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } - printf(" = %" PRIu64 "", ull); + printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -1094,10 +1071,8 @@ static void show_power_condition_transitions_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; - uint64_t ull; char pcb_str[PCB_STR_LEN]; printf("Power condition transitions page\n"); @@ -1123,19 +1098,7 @@ show_power_condition_transitions_page(unsigned char * resp, int len, default: printf(" Reserved [0x%x]", pc); } - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } - printf(" = %" PRIu64 "", ull); + printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -2683,7 +2646,7 @@ show_non_volatile_cache_page(unsigned char * resp, int len, int show_pcb) } if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); - printf("\n <%s>\n", pcb_str); + printf(" <%s>\n", pcb_str); } num -= pl; ucp += pl; @@ -2752,12 +2715,12 @@ show_lb_provisioning_page(unsigned char * resp, int len, int show_pcb) printf(" Vendor specific [0x%x]:", pc); dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); } else { - printf(" Reserved [parameter_code=0x%x]:", pc); + printf(" Reserved [parameter_code=0x%x]:\n", pc); dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); } if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -2792,12 +2755,136 @@ show_solid_state_media_page(unsigned char * resp, int len, int show_pcb) } printf(" %d%%\n", ucp[7]); } else { - printf(" Reserved [parameter_code=0x%x]:", pc); + printf(" Reserved [parameter_code=0x%x]:\n", pc); + dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); + } + if (show_pcb) { + get_pcb_str(pcb, str, sizeof(str)); + printf(" <%s>\n", str); + } + num -= pl; + ucp += pl; + } +} + +static const char * dt_dev_activity[] = { + "No DT device activity", + "Cleaning operation in progress", + "Volume is being loaded", + "Volume is being unloaded", + "Other medium activity", + "Reading from medium", + "Writing to medium", + "Locating medium", + "Rewinding medium", /* 8 */ + "Erasing volume", + "Formatting volume", + "Calibrating", + "Other DT device activity", + "Microcode update in progress", + "Reading encrypted from medium", + "Writing encrypted to medium", + "Diagnostic operation in progress", /* 10 */ +}; + +/* DT device status [0x11] (ssc, adc) */ +static void +show_dt_device_status_page(unsigned char * resp, int len, int show_pcb) +{ + int num, pl, pc, pcb, j; + unsigned char * ucp; + char str[PCB_STR_LEN]; + + printf("DT device status page (ssc-3, adc-3) [0x11]\n"); + num = len - 4; + ucp = &resp[0] + 4; + while (num > 3) { + pc = (ucp[0] << 8) | ucp[1]; + pcb = ucp[2]; + pl = ucp[3] + 4; + switch (pc) { + case 0x0: + printf(" Very high frequency data:\n"); + if ((pl < 8) || (num < 8)) { + if (num < 8) + fprintf(stderr, " truncated by response length, " + "expected at least 8 bytes\n"); + else + fprintf(stderr, " parameter length >= 8 expected, " + "got %d\n", pl); + break; + } + printf(" PAMR=%d HUI=%d MACC=%d CMPR=%d ", !!(0x80 & ucp[4]), + !!(0x40 & ucp[4]), !!(0x20 & ucp[4]), !!(0x10 & ucp[4])); + printf("WRTP=%d CRQST=%d CRQRD=%d DINIT=%d\n", !!(0x8 & ucp[4]), + !!(0x4 & ucp[4]), !!(0x2 & ucp[4]), !!(0x1 & ucp[4])); + printf(" INXTN=%d RAA=%d MPRSNT=%d ", !!(0x80 & ucp[5]), + !!(0x20 & ucp[5]), !!(0x10 & ucp[5])); + printf("MSTD=%d MTHRD=%d MOUNTED=%d\n", + !!(0x4 & ucp[5]), !!(0x2 & ucp[5]), !!(0x1 & ucp[5])); + printf(" DT device activity: "); + j = ucp[6]; + if (j < (int)(sizeof(dt_dev_activity) / + sizeof(dt_dev_activity[0]))) + printf("%s\n", dt_dev_activity[j]); + else if (j < 0x80) + printf("Reserved [0x%x]\n", j); + else + printf("Vendor specific [0x%x]\n", j); + printf(" VS=%d TDDEC=%d EPP=%d ", !!(0x80 & ucp[7]), + !!(0x20 & ucp[7]), !!(0x10 & ucp[7])); + printf("ESR=%d RRQST=%d INTFC=%d TAFC=%d\n", !!(0x8 & ucp[7]), + !!(0x4 & ucp[7]), !!(0x2 & ucp[7]), !!(0x1 & ucp[7])); + break; + case 0x1: + printf(" Very high frequency polling delay: "); + if ((pl < 6) || (num < 6)) { + if (num < 6) + fprintf(stderr, "\n truncated by response length, " + "expected at least 6 bytes\n"); + else + fprintf(stderr, "\n parameter length >= 6 expected, " + "got %d\n", pl); + break; + } + printf(" %d milliseconds\n", (ucp[4] << 8) + ucp[5]); + break; + case 0x2: + printf(" DT device ADC data encryption control status (hex " + "only now):\n"); + if ((pl < 12) || (num < 12)) { + if (num < 12) + fprintf(stderr, " truncated by response length, " + "expected at least 12 bytes\n"); + else + fprintf(stderr, " parameter length >= 12 expected, " + "got %d\n", pl); + break; + } + dStrHex((const char *)ucp + 4, 8, 1); + break; + case 0x3: + printf(" Key management error data (hex only now):\n"); + if ((pl < 16) || (num < 16)) { + if (num < 16) + fprintf(stderr, " truncated by response length, " + "expected at least 16 bytes\n"); + else + fprintf(stderr, " parameter length >= 16 expected, " + "got %d\n", pl); + break; + } + dStrHex((const char *)ucp + 4, 12, 1); + break; + default: + printf(" Reserved [parameter_code=0x%x]:\n", pc); dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); + break; } +// xxxxxxxxxxxxxxx if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -2836,12 +2923,12 @@ show_ata_pt_results_page(unsigned char * resp, int len, int show_pcb) printf(" lba=0x%02x%02x%02x\n", dp[11], dp[9], dp[7]); printf(" device=0x%x status=0x%x\n", dp[12], dp[13]); } else { - printf(" Reserved [parameter_code=0x%x]:", pc); + printf(" Reserved [parameter_code=0x%x]:\n", pc); dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); } if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -2979,7 +3066,7 @@ show_background_scan_results_page(unsigned char * resp, int len, int show_pcb, } if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -2991,9 +3078,8 @@ static void show_sequential_access_page(unsigned char * resp, int len, int show_pcb, int verbose) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; uint64_t ull, gbytes; char pcb_str[PCB_STR_LEN]; @@ -3004,18 +3090,7 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb, pc = (ucp[0] << 8) | ucp[1]; pcb = ucp[2]; pl = ucp[3] + 4; - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } + ull = decode_count(ucp + 4, pl - 4); gbytes = ull / 1000000000; switch (pc) { case 0: @@ -3085,9 +3160,8 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb, } if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); - printf("\n <%s>\n", pcb_str); - } else - printf("\n"); + printf(" <%s>\n", pcb_str); + } num -= pl; ucp += pl; } @@ -3097,9 +3171,8 @@ show_sequential_access_page(unsigned char * resp, int len, int show_pcb, static void show_device_stats_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; uint64_t ull; char pcb_str[PCB_STR_LEN]; @@ -3111,18 +3184,7 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb) pcb = ucp[2]; pl = ucp[3] + 4; if (pc < 0x1000) { - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } + ull = decode_count(ucp + 4, pl - 4); switch (pc) { case 0: printf(" Lifetime media loads: %" PRIu64 "\n", ull); @@ -3181,6 +3243,7 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb) printf(" Media motion (head) hours for each medium type:\n"); printf(" <<to be decoded, dump in hex for now>>:\n"); dStrHex((const char *)ucp, pl, 0); + // xxxxxxxxxxx break; default: printf(" Reserved parameter [0x%x], dump in hex:\n", pc); @@ -3190,9 +3253,8 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb) } if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); - printf("\n <%s>\n", pcb_str); - } else - printf("\n"); + printf(" <%s>\n", pcb_str); + } num -= pl; ucp += pl; } @@ -3202,9 +3264,8 @@ show_device_stats_page(unsigned char * resp, int len, int show_pcb) static void show_media_stats_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; uint64_t ull; char pcb_str[PCB_STR_LEN]; @@ -3215,18 +3276,7 @@ show_media_stats_page(unsigned char * resp, int len, int show_pcb) pc = (ucp[0] << 8) | ucp[1]; pcb = ucp[2]; pl = ucp[3] + 4; - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } + ull = decode_count(ucp + 4, pl - 4); switch (pc) { case 0: printf(" Number of moves: %" PRIu64 "\n", ull); @@ -3325,9 +3375,8 @@ show_media_stats_page(unsigned char * resp, int len, int show_pcb) } if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); - printf("\n <%s>\n", pcb_str); - } else - printf("\n"); + printf(" <%s>\n", pcb_str); + } num -= pl; ucp += pl; } @@ -3364,7 +3413,59 @@ show_element_stats_page(unsigned char * resp, int len, int show_pcb) printf(" Number of unreadable volume identifiers: %u\n", v); if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); + } + num -= pl; + ucp += pl; + } +} + +/* 0x16 for tape */ +static void +show_tape_diag_data_page(unsigned char * resp, int len, int show_pcb) +{ + int num, pl, pc, pcb; + unsigned int v; + unsigned char * ucp; + char str[PCB_STR_LEN]; + + printf("Tape diagnostics data page (ssc-3) [0x16]\n"); + num = len - 4; + ucp = &resp[0] + 4; + while (num > 3) { + pc = (ucp[0] << 8) | ucp[1]; + pcb = ucp[2]; + pl = ucp[3] + 4; + printf(" Parameter code: %d\n", pc); + printf(" Density code: 0x%x\n", ucp[6]); + printf(" Medium type: 0x%x\n", ucp[7]); + v = (ucp[8] << 24) + (ucp[9] << 16) + (ucp[10] << 8) + ucp[11]; + printf(" Lifetime media motion hours: 0x%x\n", v); + printf(" Repeat: %d\n", !!(ucp[13] & 0x80)); + printf(" Sense key: 0x%x\n", ucp[13] & 0xf); + printf(" Additional sense code: 0x%x\n", ucp[14]); + printf(" Additional sense code qualifier: 0x%x\n", ucp[15]); + v = (ucp[16] << 24) + (ucp[17] << 16) + (ucp[18] << 8) + ucp[19]; + printf(" Vendor specific code qualifier: 0x%x\n", v); + v = (ucp[20] << 24) + (ucp[21] << 16) + (ucp[22] << 8) + ucp[23]; + printf(" Product revision level: %u\n", v); + v = (ucp[24] << 24) + (ucp[25] << 16) + (ucp[26] << 8) + ucp[27]; + printf(" Hours since last clean: %u\n", v); + printf(" Operation code: 0x%x\n", ucp[28]); + printf(" Service action: 0x%x\n", ucp[29] & 0xf); + printf(" Medium id number (in hex):\n"); + // ssc4r03.pdf does not define this field, why? xxxxxx + dStrHex((const char *)(ucp + 32), 32, 0); + printf(" Timestamp origin: 0x%x\n", ucp[64] & 0xf); + printf(" Timestamp:\n"); + dStrHex((const char *)(ucp + 66), 6, 1); + if (pl > 72) { + printf(" Vendor specific:\n"); + dStrHex((const char *)(ucp + 72), pl - 72, 0); + } + if (show_pcb) { + get_pcb_str(pcb, str, sizeof(str)); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -3436,7 +3537,269 @@ show_mchanger_diag_data_page(unsigned char * resp, int len, int show_pcb) } if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); + } + num -= pl; + ucp += pl; + } +} + +static void +volume_stats_partition(const unsigned char * xp, int len, int hex) +{ + int dl; + + while (len > 3) { + dl = xp[0] + 1; + if (dl < 3) + return; + if (hex) + printf(" partition number: %d, partition record data " + "counter: 0x%" PRIx64 "\n", (xp[2] << 8) + xp[3], + decode_count(xp + 4, dl - 4)); + else { + int k; + int all_ffs = 0; + int ffs_last_fe = 0; + unsigned char uc; + + for (k = 0; k < (dl - 4); ++k) { + uc = xp[4 + k]; + if (uc < 0xfe) + break; + if ((k < (dl - 5)) && (0xfe == uc)) + break; + if (k == (dl - 5)) { + if (0xff == uc) + all_ffs = 1; + else if (0xfe == uc) + ffs_last_fe = 1; + } + } + + if (0 == (all_ffs + ffs_last_fe)) + printf(" partition number: %d, partition record data " + "counter: %" PRIu64 "\n", (xp[2] << 8) + xp[3], + decode_count(xp + 4, dl - 4)); + else if (all_ffs) + printf(" partition number: %d, partition record data " + "counter is all 0xFFs\n", (xp[2] << 8) + xp[3]); + else + printf(" partition number: %d, partition record data " + "counter is all 0xFFs apart\n from a trailing " + "0xFE\n", (xp[2] << 8) + xp[3]); + } + xp += dl; + len -= dl; + } +} + +/* Volume Statistics log page (ssc-4) [0x17, 0x1-0xf] */ +static void +show_volume_stats_page(unsigned char * resp, int len, int show_pcb) +{ + int num, pl, pc, pcb, spf, subpg_code; + unsigned char * ucp; + char pcb_str[PCB_STR_LEN]; + + spf = !!(resp[0] & 0x40); + subpg_code = spf ? resp[1] : 0; + if (0 == subpg_code) + printf("Volume statistics page (ssc-4) but subpage=0, abnormal: " + "treat like subpage=1\n"); + else if (subpg_code < 0x10) + printf("Volume statistics page (ssc-4), subpage=%d\n", subpg_code); + else { + printf("Volume statistics page (ssc-4), subpage=%d; Reserved, " + "skip\n", subpg_code); + return; + } + num = len - 4; + ucp = &resp[0] + 4; + while (num > 3) { + pc = (ucp[0] << 8) | ucp[1]; + pcb = ucp[2]; + pl = ucp[3] + 4; + + switch (pc) { + case 0: + printf(" Page valid: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 1: + printf(" Thread count: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 2: + printf(" Total data sets written: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 3: + printf(" Total write retries: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 4: + printf(" Total unrecovered write errors: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 5: + printf(" Total suspended writes: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 6: + printf(" Total fatal suspended writes: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 7: + printf(" Total data sets read: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 8: + printf(" Total read retries: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 9: + printf(" Total unrecovered read errors: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xa: + printf(" Total suspended reads: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xb: + printf(" Total fatal suspended reads: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xc: + printf(" Last mount unrecovered write errors: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xd: + printf(" Last mount unrecovered read errors: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xe: + printf(" Last mount megabytes written: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0xf: + printf(" Last mount megabytes read: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x10: + printf(" Lifetime megabytes written: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x11: + printf(" Lifetime megabytes read: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x12: + printf(" Last load write compression ratio: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x13: + printf(" Last load read compression ratio: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x14: + printf(" Medium mount time: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x15: + printf(" Medium ready time: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x16: + printf(" Total native capacity: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x17: + printf(" Total used native capacity: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x40: + printf(" Volume serial number: %.*s\n", pl - 4, ucp + 4); + break; + case 0x41: + printf(" Tape lot identifier: %.*s\n", pl - 4, ucp + 4); + break; + case 0x42: + printf(" Volume barcode: %.*s\n", pl - 4, ucp + 4); + break; + case 0x43: + printf(" Volume manufacturer: %.*s\n", pl - 4, ucp + 4); + break; + case 0x44: + printf(" Volume license code: %.*s\n", pl - 4, ucp + 4); + break; + case 0x45: + printf(" Volume personality: %.*s\n", pl - 4, ucp + 4); + break; + case 0x80: + printf(" Write protect: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x81: + printf(" WORM: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x82: + printf(" Maximum recommended tape path temperature exceeded: %" + PRIu64 "\n", decode_count(ucp + 4, pl - 4)); + break; + case 0x100: + printf(" Volume write mounts: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x101: + printf(" Beginning of medium passes: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x102: + printf(" Middle of medium passes: %" PRIu64 "\n", + decode_count(ucp + 4, pl - 4)); + break; + case 0x200: + printf(" Logical position of first encrypted logical object:\n"); + volume_stats_partition(ucp + 4, pl - 4, 1); + break; + case 0x201: + printf(" Logical position of first unencrypted logical object " + "after first\n encrypted logical object:\n"); + volume_stats_partition(ucp + 4, pl - 4, 1); + break; + case 0x202: + printf(" Native capacity partition(s):\n"); + volume_stats_partition(ucp + 4, pl - 4, 0); + break; + case 0x203: + printf(" Used native capacity partition(s):\n"); + volume_stats_partition(ucp + 4, pl - 4, 0); + break; + case 0x204: + printf(" Remaining native capacity partition(s):\n"); + volume_stats_partition(ucp + 4, pl - 4, 0); + break; + case 0x300: + printf(" Mount history, payload in hex:\n"); + // xxxxxxxxxxxxxxxxx + dStrHex((const char *)(ucp + 4), pl - 4, 0); + break; + + default: + if (pc >= 0xf000) + printf(" Vendor specific parameter code (0x%x), payload " + "in hex\n", pc); + else + printf(" Reserved parameter code (0x%x), payload in hex\n", + pc); + dStrHex((const char *)(ucp + 4), pl - 4, 0); + break; + } + if (show_pcb) { + get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); + printf(" <%s>\n", pcb_str); } num -= pl; ucp += pl; @@ -3537,7 +3900,7 @@ show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb, } if (show_pcb) { get_pcb_str(pcb, str, sizeof(str)); - printf("\n <%s>\n", str); + printf(" <%s>\n", str); } num -= pl; ucp += pl; @@ -3548,10 +3911,8 @@ show_tape_alert_ssc_page(unsigned char * resp, int len, int show_pcb, static void show_seagate_cache_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb; + int num, pl, pc, pcb; unsigned char * ucp; - unsigned char * xp; - uint64_t ull; char pcb_str[PCB_STR_LEN]; printf("Seagate cache page [0x37]\n"); @@ -3576,19 +3937,7 @@ show_seagate_cache_page(unsigned char * resp, int len, int show_pcb) "> segment size"); break; default: printf(" Unknown Seagate parameter code = 0x%x", pc); break; } - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } - printf(" = %" PRIu64 "", ull); + printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); if (show_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -3603,9 +3952,8 @@ show_seagate_cache_page(unsigned char * resp, int len, int show_pcb) static void show_seagate_factory_page(unsigned char * resp, int len, int show_pcb) { - int k, j, num, pl, pc, pcb, valid; + int num, pl, pc, pcb, valid; unsigned char * ucp; - unsigned char * xp; uint64_t ull; char pcb_str[PCB_STR_LEN]; @@ -3627,18 +3975,7 @@ show_seagate_factory_page(unsigned char * resp, int len, int show_pcb) break; } if (valid) { - k = pl - 4; - xp = ucp + 4; - if (k > (int)sizeof(ull)) { - xp += (k - sizeof(ull)); - k = sizeof(ull); - } - ull = 0; - for (j = 0; j < k; ++j) { - if (j > 0) - ull <<= 8; - ull |= xp[j]; - } + ull = decode_count(ucp + 4, pl - 4); if (0 == pc) printf(" = %.2f", ((double)ull) / 60.0 ); else @@ -3749,7 +4086,17 @@ show_ascii_page(unsigned char * resp, int len, show_self_test_page(resp, len, optsp->do_pcb); break; case SOLID_STATE_MEDIA_LPAGE: /* 0x11 */ - show_solid_state_media_page(resp, len, optsp->do_pcb); + switch (inq_dat->peripheral_type) { + case PDT_DISK: case PDT_WO: case PDT_OPTICAL: case PDT_RBC: + show_solid_state_media_page(resp, len, optsp->do_pcb); + break; + case PDT_TAPE: case PDT_ADC: + show_dt_device_status_page(resp, len, optsp->do_pcb); + break; + default: + done = 0; + break; + } break; case 0x14: { @@ -3791,6 +4138,9 @@ show_ascii_page(unsigned char * resp, int len, /* disk (direct access) type devices */ show_ata_pt_results_page(resp, len, optsp->do_pcb); break; + case PDT_TAPE: /* ssc-4 */ + show_tape_diag_data_page(resp, len, optsp->do_pcb); + break; case PDT_MCHANGER: /* smc-3 */ show_mchanger_diag_data_page(resp, len, optsp->do_pcb); break; @@ -3807,6 +4157,9 @@ show_ascii_page(unsigned char * resp, int len, /* disk (direct access) type devices */ show_non_volatile_cache_page(resp, len, optsp->do_pcb); break; + case PDT_TAPE: /* ssc-4, subpages 1 to 0xf */ + show_volume_stats_page(resp, len, optsp->do_pcb); + break; default: done = 0; break; diff --git a/src/sg_persist.c b/src/sg_persist.c index bfc345fd..a4e00225 100644 --- a/src/sg_persist.c +++ b/src/sg_persist.c @@ -26,7 +26,7 @@ #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" -static const char * version_str = "0.39 20130604"; +static const char * version_str = "0.40 20130626"; #define PRIN_RKEY_SA 0x0 @@ -992,7 +992,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "AcCd:GHhiIkK:l:LMnoPQrRsS:T:UvVX:YZ", + c = getopt_long(argc, argv, "AcCd:GHhiIkK:l:LMnoPQ:rRsS:T:UvVX:YZ", long_options, &option_index); if (c == -1) break; diff --git a/src/sg_unmap.c b/src/sg_unmap.c index 1f6f9f41..899df84f 100644 --- a/src/sg_unmap.c +++ b/src/sg_unmap.c @@ -29,7 +29,7 @@ * logical blocks. */ -static const char * version_str = "1.02 20130507"; +static const char * version_str = "1.03 20130627"; #define DEF_TIMEOUT_SECS 60 @@ -347,7 +347,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "aghIHl:n:t:vV", long_options, + c = getopt_long(argc, argv, "ag:hIHl:n:t:vV", long_options, &option_index); if (c == -1) break; @@ -361,7 +361,7 @@ main(int argc, char * argv[]) if ((1 == num) && ((res < 0) || (res > 31))) grpnum = res; else { - fprintf(stderr, "value for '--grpnum=' must be 0 to31\n"); + fprintf(stderr, "value for '--grpnum=' must be 0 to 31\n"); return SG_LIB_SYNTAX_ERROR; } break; diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c index 13f986e8..6ffddf8d 100644 --- a/src/sg_xcopy.c +++ b/src/sg_xcopy.c @@ -61,7 +61,7 @@ #include "sg_cmds_extra.h" #include "sg_io_linux.h" -static const char * version_str = "0.35 20130603"; +static const char * version_str = "0.36 20130627"; #define ME "sg_xcopy: " @@ -164,8 +164,8 @@ struct xcopy_fp_t { #endif }; -static struct xcopy_fp_t ifp; -static struct xcopy_fp_t ofp; +static struct xcopy_fp_t ixcf; +static struct xcopy_fp_t oxcf; static void calc_duration_throughput(int contin); @@ -578,10 +578,12 @@ scsi_extended_copy(int sg_fd, unsigned char list_id, xcopyBuff[11] = seg_desc_len; /* One segment descriptor */ desc_offset += seg_desc_len; if (verbose > 3) { - fprintf(stderr, "\nParameter list in hex (length %d):\n", desc_offset); + fprintf(stderr, "\nParameter list in hex (length %d):\n", + desc_offset); dStrHex((const char *)xcopyBuff, desc_offset, 1); } - return sg_ll_extended_copy(sg_fd, xcopyBuff, desc_offset, 0, verb); + /* set noisy so if a UA happens it will be printed to stderr */ + return sg_ll_extended_copy(sg_fd, xcopyBuff, desc_offset, 1, verb); } /* Return of 0 -> success, see sg_ll_read_capacity*() otherwise */ @@ -595,7 +597,7 @@ scsi_read_capacity(struct xcopy_fp_t *xfp) verb = (verbose ? verbose - 1: 0); res = sg_ll_readcap_10(xfp->sg_fd, 0, 0, rcBuff, - READ_CAP_REPLY_LEN, 0, verb); + READ_CAP_REPLY_LEN, 1, verb); if (0 != res) return res; @@ -604,7 +606,7 @@ scsi_read_capacity(struct xcopy_fp_t *xfp) int64_t ls; res = sg_ll_readcap_16(xfp->sg_fd, 0, 0, rcBuff, - RCAP16_REPLY_LEN, 0, verb); + RCAP16_REPLY_LEN, 1, verb); if (0 != res) return res; for (k = 0, ls = 0; k < 8; ++k) { @@ -640,8 +642,10 @@ scsi_operating_parameter(struct xcopy_fp_t *xfp, int is_target) int verb, valid = 0; verb = (verbose ? verbose - 1: 0); + /* In SPC-4 opcode 0x84, service action 0x3 is called RECEIVE COPY + * OPERATING PARAMETERS */ res = sg_ll_receive_copy_results(xfp->sg_fd, 0x03, 0, rcBuff, rcBuffLen, - 0, verb); + 1, verb); if (0 != res) return -res; @@ -667,7 +671,8 @@ scsi_operating_parameter(struct xcopy_fp_t *xfp, int is_target) if (verbose) { printf(" >> Receive copy results (report operating parameters):\n"); printf(" Maximum target descriptor count: %lu\n", max_target_num); - printf(" Maximum segment descriptor count: %lu\n", max_segment_num); + printf(" Maximum segment descriptor count: %lu\n", + max_segment_num); printf(" Maximum descriptor list length: %lu\n", max_desc_len); printf(" Maximum segment length: %lu\n", max_segment_len); printf(" Maximum inline data length: %lu\n", max_inline_data); @@ -1389,10 +1394,10 @@ main(int argc, char * argv[]) int on_src = 0; int on_dst = 0; - ifp.fname[0] = '\0'; - ofp.fname[0] = '\0'; - ifp.num_sect = -1; - ofp.num_sect = -1; + ixcf.fname[0] = '\0'; + oxcf.fname[0] = '\0'; + ixcf.num_sect = -1; + oxcf.num_sect = -1; if (argc < 2) { fprintf(stderr, @@ -1412,8 +1417,8 @@ main(int argc, char * argv[]) if (*buf) *buf++ = '\0'; if (0 == strncmp(key, "app", 3)) { - ifp.append = sg_get_num(buf); - ofp.append = ifp.append; + ixcf.append = sg_get_num(buf); + oxcf.append = ixcf.append; } else if (0 == strcmp(key, "bpt")) { bpt = sg_get_num(buf); if (-1 == bpt) { @@ -1443,7 +1448,7 @@ main(int argc, char * argv[]) else if (!strncmp(buf, "disable", 7)) list_id_usage = 3; else { - fprintf(stderr, ME "bad argument to 'list_id_usage='\n"); + fprintf(stderr, ME "bad argument to 'id_usage='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "conv")) @@ -1473,34 +1478,34 @@ main(int argc, char * argv[]) } else if (0 == strcmp(key, "ibs")) { ibs = sg_get_num(buf); } else if (strcmp(key, "if") == 0) { - if ('\0' != ifp.fname[0]) { + if ('\0' != ixcf.fname[0]) { fprintf(stderr, "Second IFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; } else - strncpy(ifp.fname, buf, INOUTF_SZ); + strncpy(ixcf.fname, buf, INOUTF_SZ); } else if (0 == strcmp(key, "iflag")) { - if (process_flags(buf, &ifp)) { + if (process_flags(buf, &ixcf)) { fprintf(stderr, ME "bad argument to 'iflag='\n"); return SG_LIB_SYNTAX_ERROR; } } else if (0 == strcmp(key, "obs")) { obs = sg_get_num(buf); } else if (strcmp(key, "of") == 0) { - if ('\0' != ofp.fname[0]) { + if ('\0' != oxcf.fname[0]) { fprintf(stderr, "Second OFILE argument??\n"); return SG_LIB_SYNTAX_ERROR; } else - strncpy(ofp.fname, buf, INOUTF_SZ); + strncpy(oxcf.fname, buf, INOUTF_SZ); } else if (0 == strcmp(key, "oflag")) { - if (process_flags(buf, &ofp)) { + if (process_flags(buf, &oxcf)) { fprintf(stderr, ME "bad argument to 'oflag='\n"); return SG_LIB_SYNTAX_ERROR; } #if 0 } else if (0 == strcmp(key, "retries")) { - ifp.retries = sg_get_num(buf); - ofp.retries = ifp.retries; - if (-1 == ifp.retries) { + ixcf.retries = sg_get_num(buf); + oxcf.retries = ixcf.retries; + if (-1 == ixcf.retries) { fprintf(stderr, ME "bad argument to 'retries='\n"); return SG_LIB_SYNTAX_ERROR; } @@ -1575,7 +1580,7 @@ main(int argc, char * argv[]) fprintf(stderr, "skip and seek cannot be negative\n"); return SG_LIB_SYNTAX_ERROR; } - if ((ofp.append > 0) && (seek > 0)) { + if ((oxcf.append > 0) && (seek > 0)) { fprintf(stderr, "Can't use both append and seek switches\n"); return SG_LIB_SYNTAX_ERROR; } @@ -1595,7 +1600,7 @@ main(int argc, char * argv[]) #ifdef SG_DEBUG fprintf(stderr, ME "%s if=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%" PRId64 "\n", (on_src)?"on-source":"on-destination", - ifp.fname, skip, ofp.fname, seek, dd_count); + ixcf.fname, skip, oxcf.fname, seek, dd_count); #endif install_handler(SIGINT, interrupt_handler); install_handler(SIGQUIT, interrupt_handler); @@ -1604,24 +1609,24 @@ main(int argc, char * argv[]) infd = STDIN_FILENO; outfd = STDOUT_FILENO; - ifp.pdt = -1; - ofp.pdt = -1; - if (ifp.fname[0] && ('-' != ifp.fname[0])) { - infd = open_if(&ifp, verbose); + ixcf.pdt = -1; + oxcf.pdt = -1; + if (ixcf.fname[0] && ('-' != ixcf.fname[0])) { + infd = open_if(&ixcf, verbose); if (infd < 0) return -infd; } - if (ofp.fname[0] && ('-' != ofp.fname[0])) { - outfd = open_of(&ofp, verbose); + if (oxcf.fname[0] && ('-' != oxcf.fname[0])) { + outfd = open_of(&oxcf, verbose); if (outfd < -1) return -outfd; } - if (open_sg(&ifp, verbose) < 0) + if (open_sg(&ixcf, verbose) < 0) return SG_LIB_CAT_INVALID_OP; - if (open_sg(&ofp, verbose) < 0) + if (open_sg(&oxcf, verbose) < 0) return SG_LIB_CAT_INVALID_OP; if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) { @@ -1631,107 +1636,111 @@ main(int argc, char * argv[]) return SG_LIB_SYNTAX_ERROR; } - res = scsi_read_capacity(&ifp); + res = scsi_read_capacity(&ixcf); if (SG_LIB_CAT_UNIT_ATTENTION == res) { fprintf(stderr, "Unit attention (readcap in), continuing\n"); - res = scsi_read_capacity(&ifp); + res = scsi_read_capacity(&ixcf); } else if (SG_LIB_CAT_ABORTED_COMMAND == res) { fprintf(stderr, "Aborted command (readcap in), continuing\n"); - res = scsi_read_capacity(&ifp); + res = scsi_read_capacity(&ixcf); } if (0 != res) { if (res == SG_LIB_CAT_INVALID_OP) fprintf(stderr, "read capacity not supported on %s\n", - ifp.fname); + ixcf.fname); else if (res == SG_LIB_CAT_NOT_READY) fprintf(stderr, "read capacity failed on %s - not " - "ready\n", ifp.fname); + "ready\n", ixcf.fname); else - fprintf(stderr, "Unable to read capacity on %s\n", ifp.fname); - ifp.num_sect = -1; - } else if (ibs && ifp.sect_sz != ibs) { + fprintf(stderr, "Unable to read capacity on %s\n", ixcf.fname); + ixcf.num_sect = -1; + } else if (ibs && ixcf.sect_sz != ibs) { fprintf(stderr, ">> warning: block size on %s confusion: " - "ibs=%d, device claims=%d\n", ifp.fname, ibs, ifp.sect_sz); + "ibs=%d, device claims=%d\n", ixcf.fname, ibs, ixcf.sect_sz); } - if (skip && ifp.num_sect < skip) { + if (skip && ixcf.num_sect < skip) { fprintf(stderr, "argument to 'skip=' exceeds device size " - "(max %" PRId64 ")\n", ifp.num_sect); + "(max %" PRId64 ")\n", ixcf.num_sect); return SG_LIB_SYNTAX_ERROR; } - res = scsi_read_capacity(&ofp); + res = scsi_read_capacity(&oxcf); if (SG_LIB_CAT_UNIT_ATTENTION == res) { fprintf(stderr, "Unit attention (readcap out), continuing\n"); - res = scsi_read_capacity(&ofp); + res = scsi_read_capacity(&oxcf); } else if (SG_LIB_CAT_ABORTED_COMMAND == res) { fprintf(stderr, "Aborted command (readcap out), continuing\n"); - res = scsi_read_capacity(&ofp); + res = scsi_read_capacity(&oxcf); } if (0 != res) { if (res == SG_LIB_CAT_INVALID_OP) fprintf(stderr, "read capacity not supported on %s\n", - ofp.fname); + oxcf.fname); else - fprintf(stderr, "Unable to read capacity on %s\n", ofp.fname); - ofp.num_sect = -1; - } else if (obs && obs != ofp.sect_sz) { + fprintf(stderr, "Unable to read capacity on %s\n", oxcf.fname); + oxcf.num_sect = -1; + } else if (obs && obs != oxcf.sect_sz) { fprintf(stderr, ">> warning: block size on %s confusion: " - "obs=%d, device claims=%d\n", ofp.fname, obs, ofp.sect_sz); + "obs=%d, device claims=%d\n", oxcf.fname, obs, oxcf.sect_sz); } - if (seek && ofp.num_sect < seek) { + if (seek && oxcf.num_sect < seek) { fprintf(stderr, "argument to 'seek=' exceeds device size " - "(max %" PRId64 ")\n", ofp.num_sect); + "(max %" PRId64 ")\n", oxcf.num_sect); return SG_LIB_SYNTAX_ERROR; } if ((dd_count < 0) || ((verbose > 0) && (0 == dd_count))) { if (xcopy_flag_dc == 0) { - dd_count = ifp.num_sect - skip; - if (dd_count * ifp.sect_sz > (ofp.num_sect - seek) * ofp.sect_sz) - dd_count = (ofp.num_sect - seek) * ofp.sect_sz / ifp.sect_sz; + dd_count = ixcf.num_sect - skip; + if ((dd_count * ixcf.sect_sz) > + ((oxcf.num_sect - seek) * oxcf.sect_sz)) + dd_count = (oxcf.num_sect - seek) * oxcf.sect_sz / + ixcf.sect_sz; } else { - dd_count = ofp.num_sect - seek; - if (dd_count * ofp.sect_sz > (ifp.num_sect - skip) * ifp.sect_sz) - dd_count = (ifp.num_sect - skip) * ifp.sect_sz / ofp.sect_sz; + dd_count = oxcf.num_sect - seek; + if ((dd_count * oxcf.sect_sz) > + ((ixcf.num_sect - skip) * ixcf.sect_sz)) + dd_count = (ixcf.num_sect - skip) * ixcf.sect_sz / + oxcf.sect_sz; } } else { int64_t dd_bytes; if (xcopy_flag_dc) - dd_bytes = dd_count * ofp.sect_sz; + dd_bytes = dd_count * oxcf.sect_sz; else - dd_bytes = dd_count * ifp.sect_sz; + dd_bytes = dd_count * ixcf.sect_sz; - if (dd_bytes > ifp.num_sect * ifp.sect_sz) { + if (dd_bytes > ixcf.num_sect * ixcf.sect_sz) { fprintf(stderr, "access beyond end of source device " - "(max %" PRId64 ")\n", ifp.num_sect); + "(max %" PRId64 ")\n", ixcf.num_sect); return SG_LIB_SYNTAX_ERROR; } - if (dd_bytes > ofp.num_sect * ofp.sect_sz) { + if (dd_bytes > oxcf.num_sect * oxcf.sect_sz) { fprintf(stderr, "access beyond end of target device " - "(max %" PRId64 ")\n", ofp.num_sect); + "(max %" PRId64 ")\n", oxcf.num_sect); return SG_LIB_SYNTAX_ERROR; } } - res = scsi_operating_parameter(&ifp, 0); + res = scsi_operating_parameter(&ixcf, 0); if (res < 0) { if (SG_LIB_CAT_UNIT_ATTENTION == -res) { fprintf(stderr, "Unit attention (oper parm), continuing\n"); - res = scsi_operating_parameter(&ifp, 0); + res = scsi_operating_parameter(&ixcf, 0); } else { if (-res == SG_LIB_CAT_INVALID_OP) { fprintf(stderr, "receive copy results not supported on %s\n", - ifp.fname); + ixcf.fname); #ifndef SG_DEBUG return EINVAL; #endif } else if (-res == SG_LIB_CAT_NOT_READY) fprintf(stderr, "receive copy results failed on %s - not " - "ready\n", ifp.fname); + "ready\n", ixcf.fname); else { fprintf(stderr, "Unable to receive copy results on %s\n", - ifp.fname); + ixcf.fname); return -res; } } @@ -1740,10 +1749,11 @@ main(int argc, char * argv[]) if (res & TD_VPD) { if (verbose) - printf(" >> using VPD identification for source %s\n", ifp.fname); - src_desc_len = desc_from_vpd_id(ifp.sg_fd, src_desc, 256, - ifp.sect_sz, ifp.pad); - if (src_desc_len > 256) { + printf(" >> using VPD identification for source %s\n", + ixcf.fname); + src_desc_len = desc_from_vpd_id(ixcf.sg_fd, src_desc, + sizeof(src_desc), ixcf.sect_sz, ixcf.pad); + if (src_desc_len > (int)sizeof(src_desc)) { fprintf(stderr, "source descriptor too large (%d bytes)\n", res); return SG_LIB_CAT_MALFORMED; } @@ -1751,24 +1761,24 @@ main(int argc, char * argv[]) return SG_LIB_CAT_INVALID_OP; } - res = scsi_operating_parameter(&ofp, 1); + res = scsi_operating_parameter(&oxcf, 1); if (res < 0) { if (SG_LIB_CAT_UNIT_ATTENTION == -res) { fprintf(stderr, "Unit attention (oper parm), continuing\n"); - res = scsi_operating_parameter(&ofp, 1); + res = scsi_operating_parameter(&oxcf, 1); } else { if (-res == SG_LIB_CAT_INVALID_OP) { fprintf(stderr, "receive copy results not supported on %s\n", - ofp.fname); + oxcf.fname); #ifndef SG_DEBUG return EINVAL; #endif } else if (-res == SG_LIB_CAT_NOT_READY) fprintf(stderr, "receive copy results failed on %s - not " - "ready\n", ofp.fname); + "ready\n", oxcf.fname); else { fprintf(stderr, "Unable to receive copy results on %s\n", - ofp.fname); + oxcf.fname); return -res; } } @@ -1778,10 +1788,10 @@ main(int argc, char * argv[]) if (res & TD_VPD) { if (verbose) printf(" >> using VPD identification for destination %s\n", - ofp.fname); - dst_desc_len = desc_from_vpd_id(ofp.sg_fd, dst_desc, 256, - ofp.sect_sz, ofp.pad); - if (dst_desc_len > 256) { + oxcf.fname); + dst_desc_len = desc_from_vpd_id(oxcf.sg_fd, dst_desc, + sizeof(dst_desc), oxcf.sect_sz, oxcf.pad); + if (dst_desc_len > (int)sizeof(dst_desc)) { fprintf(stderr, "destination descriptor too large (%d bytes)\n", res); return SG_LIB_CAT_MALFORMED; @@ -1795,39 +1805,39 @@ main(int argc, char * argv[]) return SG_LIB_CAT_OTHER; } - if ((unsigned long)dd_count < ifp.min_bytes / ifp.sect_sz) { + if ((unsigned long)dd_count < ixcf.min_bytes / ixcf.sect_sz) { fprintf(stderr, "not enough data to read (min %ld bytes)\n", - ofp.min_bytes); + oxcf.min_bytes); return SG_LIB_CAT_OTHER; } - if ((unsigned long)dd_count < ofp.min_bytes / ofp.sect_sz) { + if ((unsigned long)dd_count < oxcf.min_bytes / oxcf.sect_sz) { fprintf(stderr, "not enough data to write (min %ld bytes)\n", - ofp.min_bytes); + oxcf.min_bytes); return SG_LIB_CAT_OTHER; } if (bpt_given) { if (xcopy_flag_dc) { - if ((unsigned long)bpt * ofp.sect_sz > ofp.max_bytes) { + if ((unsigned long)bpt * oxcf.sect_sz > oxcf.max_bytes) { fprintf(stderr, "bpt too large (max %ld blocks)\n", - ofp.max_bytes / ofp.sect_sz); + oxcf.max_bytes / oxcf.sect_sz); return SG_LIB_SYNTAX_ERROR; } } else { - if ((unsigned long)bpt * ifp.sect_sz > ifp.max_bytes) { + if ((unsigned long)bpt * ixcf.sect_sz > ixcf.max_bytes) { fprintf(stderr, "bpt too large (max %ld blocks)\n", - ifp.max_bytes / ifp.sect_sz); + ixcf.max_bytes / ixcf.sect_sz); return SG_LIB_SYNTAX_ERROR; } } } else { if (xcopy_flag_dc) - bpt = ofp.max_bytes / ofp.sect_sz; + bpt = oxcf.max_bytes / oxcf.sect_sz; else - bpt = ifp.max_bytes / ifp.sect_sz; + bpt = ixcf.max_bytes / ixcf.sect_sz; } - seg_desc_type = seg_desc_from_dd_type(ifp.sg_type, 0, ofp.sg_type, 0); + seg_desc_type = seg_desc_from_dd_type(ixcf.sg_type, 0, oxcf.sg_type, 0); if (do_time) { start_tm.tv_sec = 0; |