diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2016-02-02 04:21:27 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2016-02-02 04:21:27 +0000 |
commit | c68b788ce091800ab12ad6a37681d0c1ee275ca0 (patch) | |
tree | 87fcb51f0e9ba2b6bdf98e732ae097238b116ba2 /src | |
parent | 572d431816271830cc321c2c7b596236e5708ea0 (diff) | |
download | sg3_utils-c68b788ce091800ab12ad6a37681d0c1ee275ca0.tar.gz |
sg_unaligned.h: gets for variable length unsigned integers; sg_inq: version descriptor list to 20160125
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@658 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_get_config.c | 97 | ||||
-rw-r--r-- | src/sg_inq.c | 28 | ||||
-rw-r--r-- | src/sg_inq_data.c | 21 | ||||
-rw-r--r-- | src/sg_logs.c | 558 | ||||
-rw-r--r-- | src/sg_persist.c | 33 | ||||
-rw-r--r-- | src/sg_read_buffer.c | 9 | ||||
-rw-r--r-- | src/sg_referrals.c | 10 | ||||
-rw-r--r-- | src/sg_ses.c | 66 | ||||
-rw-r--r-- | src/sg_unmap.c | 45 | ||||
-rw-r--r-- | src/sg_vpd.c | 29 | ||||
-rw-r--r-- | src/sg_xcopy.c | 4 |
11 files changed, 517 insertions, 383 deletions
diff --git a/src/sg_get_config.c b/src/sg_get_config.c index d98341b6..2e20a6b4 100644 --- a/src/sg_get_config.c +++ b/src/sg_get_config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2015 Douglas Gilbert. + * Copyright (c) 2004-2016 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. @@ -19,6 +19,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" #include "sg_cmds_mmc.h" +#include "sg_unaligned.h" #include "sg_pr2serr.h" /* A utility program originally written for the Linux OS SCSI subsystem. @@ -28,7 +29,7 @@ */ -static const char * version_str = "0.40 20151219"; /* mmc6r02 */ +static const char * version_str = "0.41 20160131"; /* mmc6r02 */ #define MX_ALLOC_LEN 8192 #define NAME_BUFF_SZ 64 @@ -255,7 +256,7 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" available profiles [more recent typically higher " "in list]:\n"); for (k = 4; k < len; k += 4) { - profile = (ucp[k] << 8) + ucp[k + 1]; + profile = sg_get_unaligned_be16(ucp + k); printf(" profile: %s , currentP=%d\n", get_profile_str(profile, buff), !!(ucp[k + 2] & 1)); } @@ -268,7 +269,7 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" additional length [%d] too short\n", len - 4); break; } - num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; + num = sg_get_unaligned_be32(ucp + 4); switch (num) { case 0: cp = "unspecified"; break; case 1: cp = "SCSI family"; break; @@ -347,9 +348,9 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" additional length [%d] too short\n", len - 4); break; } - num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; + num = sg_get_unaligned_be32(ucp + 4); printf(" Logical block size=0x%x, blocking=0x%x, PP=%d\n", - num, ((ucp[8] << 8) + ucp[9]), !!(ucp[10] & 0x1)); + num, sg_get_unaligned_be16(ucp + 8), !!(ucp[10] & 0x1)); break; case 0x1d: /* Multi-read */ case 0x22: /* Sector erasable */ @@ -393,10 +394,10 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" additional length [%d] too short\n", len - 4); break; } - num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; - n = (ucp[8] << 24) + (ucp[9] << 16) + (ucp[10] << 8) + ucp[11]; + num = sg_get_unaligned_be32(ucp + 4); + n = sg_get_unaligned_be32(ucp + 8); printf(" Last lba=0x%x, Logical block size=0x%x, blocking=0x%x," - " PP=%d\n", num, n, ((ucp[12] << 8) + ucp[13]), + " PP=%d\n", num, n, sg_get_unaligned_be16(ucp + 12), !!(ucp[14] & 0x1)); break; case 0x21: /* Incremental streaming writable */ @@ -408,7 +409,7 @@ decode_feature(int feature, unsigned char * ucp, int len) break; } printf(" Data block types supported=0x%x, TRIO=%d, ARSV=%d, " - "BUF=%d\n", ((ucp[4] << 8) + ucp[5]), !!(ucp[6] & 0x4), + "BUF=%d\n", sg_get_unaligned_be16(ucp + 4), !!(ucp[6] & 0x4), !!(ucp[6] & 0x2), !!(ucp[6] & 0x1)); num = ucp[7]; printf(" Number of link sizes=%d\n", num); @@ -442,9 +443,9 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" additional length [%d] too short\n", len - 4); break; } - num = (ucp[4] << 24) + (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]; + num = sg_get_unaligned_be16(ucp + 4); printf(" Logical block size=0x%x, blocking=0x%x, PP=%d\n", - num, ((ucp[8] << 8) + ucp[9]), !!(ucp[10] & 0x1)); + num, sg_get_unaligned_be16(ucp + 8), !!(ucp[10] & 0x1)); break; /* case 0x26: Restricted overwrite -> see 0x1d entry */ /* case 0x27: CDRW CAV write -> see 0x1d entry */ @@ -466,7 +467,7 @@ decode_feature(int feature, unsigned char * ucp, int len) } printf(" DRT-DM=%d, number of DBI cache zones=0x%x, number of " "entries=0x%x\n", !!(ucp[4] & 0x1), ucp[5], - ((ucp[6] << 8) + ucp[7])); + sg_get_unaligned_be16(ucp + 6)); break; case 0x2a: /* DVD+RW */ printf(" version=%d, persist=%d, current=%d [0x%x]\n", @@ -513,7 +514,8 @@ decode_feature(int feature, unsigned char * ucp, int len) !!(ucp[4] & 0x40), !!(ucp[4] & 0x10), !!(ucp[4] & 0x8), !!(ucp[4] & 0x4)); printf(" CD-RW=%d, R-W sub-code=%d, Data type supported=%d\n", - !!(ucp[4] & 0x2), !!(ucp[4] & 0x1), (ucp[6] << 8) + ucp[7]); + !!(ucp[4] & 0x2), !!(ucp[4] & 0x1), + sg_get_unaligned_be16(ucp + 6)); break; case 0x2e: /* CD mastering (session at once) */ printf(" version=%d, persist=%d, current=%d [0x%x]\n", @@ -529,7 +531,7 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" Test write=%d, CD-RW=%d, R-W=%d\n", !!(ucp[4] & 0x4), !!(ucp[4] & 0x2), !!(ucp[4] & 0x1)); printf(" Maximum cue sheet length=0x%x\n", - (ucp[5] << 16) + (ucp[6] << 8) + ucp[7]); + sg_get_unaligned_be24(ucp + 5)); break; case 0x2f: /* DVD-R/-RW write */ printf(" version=%d, persist=%d, current=%d [0x%x]\n", @@ -610,22 +612,22 @@ decode_feature(int feature, unsigned char * ucp, int len) } printf(" Bitmaps for BD-RE read support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[8] << 8) + ucp[9], - (ucp[10] << 8) + ucp[11], - (ucp[12] << 8) + ucp[13], - (ucp[14] << 8) + ucp[15]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 8), + sg_get_unaligned_be16(ucp + 10), + sg_get_unaligned_be16(ucp + 12), + sg_get_unaligned_be16(ucp + 14)); printf(" Bitmaps for BD-R read support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[16] << 8) + ucp[17], - (ucp[18] << 8) + ucp[19], - (ucp[20] << 8) + ucp[21], - (ucp[22] << 8) + ucp[23]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 16), + sg_get_unaligned_be16(ucp + 18), + sg_get_unaligned_be16(ucp + 20), + sg_get_unaligned_be16(ucp + 22)); printf(" Bitmaps for BD-ROM read support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[24] << 8) + ucp[25], - (ucp[26] << 8) + ucp[27], - (ucp[28] << 8) + ucp[29], - (ucp[30] << 8) + ucp[31]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 24), + sg_get_unaligned_be16(ucp + 26), + sg_get_unaligned_be16(ucp + 28), + sg_get_unaligned_be16(ucp + 30)); break; case 0x41: /* BD Write */ printf(" version=%d, persist=%d, current=%d [0x%x]\n", @@ -638,22 +640,22 @@ decode_feature(int feature, unsigned char * ucp, int len) printf(" SVNR=%d\n", !!(ucp[4] & 0x1)); printf(" Bitmaps for BD-RE write support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[8] << 8) + ucp[9], - (ucp[10] << 8) + ucp[11], - (ucp[12] << 8) + ucp[13], - (ucp[14] << 8) + ucp[15]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 8), + sg_get_unaligned_be16(ucp + 10), + sg_get_unaligned_be16(ucp + 12), + sg_get_unaligned_be16(ucp + 14)); printf(" Bitmaps for BD-R write support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[16] << 8) + ucp[17], - (ucp[18] << 8) + ucp[19], - (ucp[20] << 8) + ucp[21], - (ucp[22] << 8) + ucp[23]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 16), + sg_get_unaligned_be16(ucp + 18), + sg_get_unaligned_be16(ucp + 20), + sg_get_unaligned_be16(ucp + 22)); printf(" Bitmaps for BD-ROM write support:\n"); printf(" Class 0=0x%x, Class 1=0x%x, Class 2=0x%x, " - "Class 3=0x%x\n", (ucp[24] << 8) + ucp[25], - (ucp[26] << 8) + ucp[27], - (ucp[28] << 8) + ucp[29], - (ucp[30] << 8) + ucp[31]); + "Class 3=0x%x\n", sg_get_unaligned_be16(ucp + 24), + sg_get_unaligned_be16(ucp + 26), + sg_get_unaligned_be16(ucp + 28), + sg_get_unaligned_be16(ucp + 30)); break; /* case 0x42: TSR (timely safe recording) -> see 0x1d entry */ case 0x50: /* HD DVD Read */ @@ -730,7 +732,7 @@ decode_feature(int feature, unsigned char * ucp, int len) } printf(" Scan=%d, SCM=%d, SV=%d, number of volume levels=%d\n", !!(ucp[4] & 0x4), !!(ucp[4] & 0x2), !!(ucp[4] & 0x1), - (ucp[6] << 8) + ucp[7]); + sg_get_unaligned_be16(ucp + 6)); break; case 0x104: /* Firmware upgrade */ printf(" version=%d, persist=%d, current=%d [0x%x]\n", @@ -749,7 +751,7 @@ decode_feature(int feature, unsigned char * ucp, int len) feature); if (len > 7) { printf(" Group 3=%d, unit length=%d\n", - !!(ucp[4] & 0x1), (ucp[6] << 8) + ucp[7]); + !!(ucp[4] & 0x1), sg_get_unaligned_be16(ucp + 6)); } break; case 0x106: /* DVD CSS */ @@ -792,8 +794,7 @@ decode_feature(int feature, unsigned char * ucp, int len) feature); printf(" Disc control blocks:\n"); for (k = 4; k < len; k += 4) { - printf(" 0x%x\n", ((unsigned int)ucp[k] << 24) + - (ucp[k + 1] << 16) + (ucp[k + 2] << 8) + ucp[k + 3]); + printf(" 0x%x\n", sg_get_unaligned_be32(ucp + k)); } break; case 0x10b: /* DVD CPRM */ @@ -868,8 +869,7 @@ decode_feature(int feature, unsigned char * ucp, int len) num = ucp[5]; printf(" Profile numbers:\n"); for (k = 6; (num > 0) && (k < len); --num, k += 2) { - printf(" %d\n", - ((unsigned int)ucp[k] << 8) + ucp[k + 1]); + printf(" %u\n", sg_get_unaligned_be16(ucp + k)); } break; default: @@ -898,7 +898,7 @@ decode_config(unsigned char * resp, int max_resp_len, int len, int brief, pr2serr("response length too short: %d\n", len); return; } - curr_profile = (resp[6] << 8) + resp[7]; + curr_profile = sg_get_unaligned_be16(resp + 6); if (0 == curr_profile) pr2serr("No current profile\n"); else @@ -908,7 +908,7 @@ decode_config(unsigned char * resp, int max_resp_len, int len, int brief, len -= 8; for (k = 0; k < len; k += extra_len, ucp += extra_len) { extra_len = 4 + ucp[3]; - feature = (ucp[0] << 8) + ucp[1]; + feature = sg_get_unaligned_be16(ucp + 0); printf(" %s feature\n", get_feature_str(feature, buff)); if (brief) continue; @@ -1085,8 +1085,7 @@ main(int argc, char * argv[]) sizeof(resp_buffer), 1, verbose); ret = res; if (0 == res) { - len = (resp_buffer[0] << 24) + (resp_buffer[1] << 16) + - (resp_buffer[2] << 8) + resp_buffer[3] + 4; + len = sg_get_unaligned_be32(resp_buffer + 0) + 4; if (do_hex) { if (len > (int)sizeof(resp_buffer)) len = sizeof(resp_buffer); diff --git a/src/sg_inq.c b/src/sg_inq.c index 11b7badc..7148acec 100644 --- a/src/sg_inq.c +++ b/src/sg_inq.c @@ -19,6 +19,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <ctype.h> #include <getopt.h> @@ -42,7 +43,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "1.55 20160126"; /* SPC-5 rev 08 */ +static const char * version_str = "1.56 20160201"; /* SPC-5 rev 08 */ /* INQUIRY notes: * It is recommended that the initial allocation length given to a @@ -741,7 +742,8 @@ static int f2hex_arr(const char * fname, int as_binary, int no_space, unsigned char * mp_arr, int * mp_arr_len, int max_arr_len) { - int fn_len, in_len, k, j, m, split_line, fd, has_stdin; + int fn_len, in_len, k, j, m, split_line, fd; + bool has_stdin; unsigned int h; const char * lcp; FILE * fp; @@ -820,8 +822,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space, if (1 == sscanf(carry_over, "%x", &h)) mp_arr[off - 1] = h; /* back up and overwrite */ else { - pr2serr("f2hex_arr: carry_over error ['%s'] around line " - "%d\n", carry_over, j + 1); + pr2serr("%s: carry_over error ['%s'] around line %d\n", + __func__, carry_over, j + 1); goto bad; } lcp = line + 1; @@ -841,7 +843,7 @@ f2hex_arr(const char * fname, int as_binary, int no_space, continue; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if ((k < in_len) && ('#' != lcp[k]) && ('\r' != lcp[k])) { - pr2serr("f2hex_arr: syntax error at line %d, pos %d\n", + pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1, m + k + 1); goto bad; } @@ -849,12 +851,12 @@ f2hex_arr(const char * fname, int as_binary, int no_space, for (k = 0; isxdigit(*lcp) && isxdigit(*(lcp + 1)); ++k, lcp += 2) { if (1 != sscanf(lcp, "%2x", &h)) { - pr2serr("f2hex_arr: bad hex number in line %d, " - "pos %d\n", j + 1, (int)(lcp - line + 1)); + pr2serr("%s: bad hex number in line %d, pos %d\n", + __func__, j + 1, (int)(lcp - line + 1)); goto bad; } if ((off + k) >= max_arr_len) { - pr2serr("f2hex_arr: array length exceeded\n"); + pr2serr("%s: array length exceeded\n", __func__); goto bad; } mp_arr[off + k] = h; @@ -866,8 +868,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space, for (k = 0; k < 1024; ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { - pr2serr("f2hex_arr: hex number larger than " - "0xff in line %d, pos %d\n", j + 1, + pr2serr("%s: hex number larger than 0xff in line %d, " + "pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); goto bad; } @@ -876,7 +878,7 @@ f2hex_arr(const char * fname, int as_binary, int no_space, carry_over[0] = *lcp; } if ((off + k) >= max_arr_len) { - pr2serr("f2hex_arr: array length exceeded\n"); + pr2serr("%s: array length exceeded\n", __func__); goto bad; } mp_arr[off + k] = h; @@ -891,8 +893,8 @@ f2hex_arr(const char * fname, int as_binary, int no_space, --k; break; } - pr2serr("f2hex_arr: error in line %d, at pos %d\n", j + 1, - (int)(lcp - line + 1)); + pr2serr("%s: error in line %d, at pos %d\n", __func__, + j + 1, (int)(lcp - line + 1)); goto bad; } } diff --git a/src/sg_inq_data.c b/src/sg_inq_data.c index a76384b9..a0a0f7fe 100644 --- a/src/sg_inq_data.c +++ b/src/sg_inq_data.c @@ -1,5 +1,5 @@ /* A utility program originally written for the Linux OS SCSI subsystem. -* Copyright (C) 2000-2015 D. Gilbert +* Copyright (C) 2000-2016 D. Gilbert * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -26,10 +26,10 @@ const char * sg_ansi_version_arr[] = "no conformance claimed", "SCSI-1", /* obsolete, ANSI X3.131-1986 */ "SCSI-2", /* obsolete, ANSI X3.131-1994 */ - "SPC", /* withdrawn */ - "SPC-2", - "SPC-3", - "SPC-4", + "SPC", /* withdrawn, ANSI INCITS 301-1997 */ + "SPC-2", /* ANSI INCITS 351-2001, ISO/IEC 14776-452 */ + "SPC-3", /* ANSI INCITS 408-2005, ISO/IEC 14776-453 */ + "SPC-4", /* ANSI INCITS 513-2015 */ "SPC-5", "ecma=1, [8h]", "ecma=1, [9h]", @@ -48,8 +48,8 @@ struct sg_version_descriptor { const char * name; }; -/* table from SPC-5 revision 06 [sorted numerically (from Annex E.9)] */ -/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20151101 */ +/* table from SPC-5 revision 08 [sorted numerically (from Annex E.9)] */ +/* Can also be obtained from : http://www.t10.org/lists/stds.txt 20160125 */ #ifdef SG_SCSI_STRINGS @@ -233,7 +233,9 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = { {0x600, "SBC-4 (no version claimed)"}, {0x620, "ZBC (no version claimed)"}, {0x622, "ZBC BSR INCITS 536 revision 02"}, + {0x624, "ZBC BSR INCITS 536 revision 05"}, {0x640, "ADC-4 (no version claimed)"}, + {0x660, "ZBC-2 (no version claimed)"}, {0x820, "SSA-TL2 (no version claimed)"}, {0x83b, "SSA-TL2 T10/1147-D revision 05b"}, {0x83c, "SSA-TL2 ANSI INCITS 308-1998"}, @@ -277,7 +279,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = { {0x99a, "SBP-3 T10/1467-D revision 4"}, {0x99b, "SBP-3 T10/1467-D revision 5"}, {0x99c, "SBP-3 ANSI INCITS 375-2004"}, - /* {0x9a0, "SRP-2 (no version claimed)"}, */ + {0x9a0, "SRP-2 (no version claimed)"}, {0x9c0, "ADP (no version claimed)"}, {0x9e0, "ADT (no version claimed)"}, {0x9f9, "ADT T10/1557-D revision 11"}, @@ -518,8 +520,9 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = { {0x2204, "PQI T10/BSR INCITS 490 revision 6"}, {0x2206, "PQI T10/BSR INCITS 490 revision 7"}, {0x2208, "PQI ANSI INCITS 490-2014"}, - {0x2220, "SOP-2 (no version claimed)"}, + {0x2220, "SOP-2 (no draft published)"}, {0x2240, "PQI-2 (no version claimed)"}, + {0x2242, "PQI-2 T10/BSR INCITS 507 revision 01"}, {0xffc0, "IEEE 1667 (no version claimed)"}, {0xffc1, "IEEE 1667-2006"}, {0xffc2, "IEEE 1667-2009"}, diff --git a/src/sg_logs.c b/src/sg_logs.c index 204b0f81..be7cc0de 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -31,7 +31,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "1.37 20160124"; /* spc5r07 + sbc4r10 */ +static const char * version_str = "1.38 20160130"; /* spc5r08 + sbc4r10 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -72,6 +72,7 @@ static const char * version_str = "1.37 20160124"; /* spc5r07 + sbc4r10 */ #define LPS_MISALIGNMENT_SUBPG 0x3 #define VENDOR_M 0x1000 +#define LTO5_M 0x2000 #define PCB_STR_LEN 128 @@ -84,6 +85,7 @@ static struct option long_options[] = { {"brief", no_argument, 0, 'b'}, {"control", required_argument, 0, 'c'}, {"enumerate", no_argument, 0, 'e'}, + {"enum_vendor", no_argument, 0, 'E'}, {"filter", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"hex", no_argument, 0, 'H'}, @@ -114,6 +116,7 @@ struct opts_t { int do_all; int do_brief; int do_enumerate; + int do_enum_vendor; int do_help; int do_hex; int do_list; @@ -341,44 +344,44 @@ static struct log_elem log_arr[] = { {IE_LPAGE, 0, 0, -1, 0, "Informational exceptions", "ie", show_ie_page}, /* 0x2f, 0 */ /* vendor specific */ - {0x30, 0, 0, PDT_TAPE, VENDOR_M, "Performance counters (Hitachi)", "pc_hi", - NULL}, /* 0x30, 0 SBC */ - {0x30, 0, 0, PDT_TAPE, VENDOR_M, "Tape usage (lto-5, 6)", "ta_", + {0x30, 0, 0, PDT_DISK, VENDOR_M, "Performance counters (Hitachi)", + "pc_hi", NULL}, /* 0x30, 0 SBC */ + {0x30, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Tape usage (lto-5, 6)", "ta_", show_tape_usage_page}, /* 0x30, 0 SSC */ - {0x31, 0, 0, PDT_TAPE, VENDOR_M, "Tape capacity (lto-5, 6)", "tc_", - show_tape_capacity_page}, /* 0x31, 0 SSC */ - {0x32, 0, 0, PDT_TAPE, VENDOR_M, "Data compression (ibm)", "dc_", + {0x31, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Tape capacity (lto-5, 6)", + "tc_", show_tape_capacity_page}, /* 0x31, 0 SSC */ + {0x32, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Data compression (ibm)", "dc_", show_data_compression_page}, /* 0x32, 0 SSC; redirect to 0x1b */ - {0x33, 0, 0, PDT_TAPE, VENDOR_M, "Write errors (lto-5)", "we_", + {0x33, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Write errors (lto-5)", "we_", NULL}, /* 0x33, 0 SSC */ - {0x34, 0, 0, PDT_TAPE, VENDOR_M, "Read forward errors (lto-5)", "rfe_", - NULL}, /* 0x34, 0 SSC */ - {0x35, 0, 0, PDT_TAPE, VENDOR_M, "DT Device Error (lto-6)", "dtde_", - NULL}, /* 0x35, 0 SSC */ + {0x34, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Read forward errors (lto-5)", + "rfe_", NULL}, /* 0x34, 0 SSC */ + {0x35, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "DT Device Error (lto-5, 6)", + "dtde_", NULL}, /* 0x35, 0 SSC */ {0x37, 0, 0, PDT_DISK, VENDOR_M, "Cache (seagate)", "c_se", show_seagate_cache_page}, /* 0x37, 0 SBC */ {0x37, 0, 0, PDT_DISK, VENDOR_M, "Miscellaneous (hitachi)", "mi_hi", NULL}, /* 0x37, 0 SBC */ - {0x37, 0, 0, PDT_TAPE, VENDOR_M, "Performance characteristics (lto-5)", - "pc_", NULL}, /* 0x37, 0 SSC */ - {0x38, 0, 0, PDT_TAPE, VENDOR_M, "Blocks/bytes transferred (lto-5)", - "bbt_", NULL}, /* 0x38, 0 SSC */ - {0x39, 0, 0, PDT_TAPE, VENDOR_M, "Host port 0 interface errors (lto-5)", - "hp0_", NULL}, /* 0x39, 0 SSC */ - {0x3a, 0, 0, PDT_TAPE, VENDOR_M, "Drive control verification (lto-5)", - "dcv_", NULL}, /* 0x3a, 0 SSC */ - {0x3b, 0, 0, PDT_TAPE, VENDOR_M, "Host port 1 interface errors (lto-5)", - "hp1_", NULL}, /* 0x3b, 0 SSC */ - {0x3c, 0, 0, PDT_TAPE, VENDOR_M, "Drive usage information (lto-5)", - "dui_", NULL}, /* 0x3c, 0 SSC */ - {0x3d, 0, 0, PDT_TAPE, VENDOR_M, "Subsystem statistics (lto-5)", "ss_", - NULL}, /* 0x3d, 0 SSC */ + {0x37, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Performance characteristics " + "(lto-5)", "pc_", NULL}, /* 0x37, 0 SSC */ + {0x38, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Blocks/bytes transferred " + "(lto-5)", "bbt_", NULL}, /* 0x38, 0 SSC */ + {0x39, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Host port 0 interface errors " + "(lto-5)", "hp0_", NULL}, /* 0x39, 0 SSC */ + {0x3a, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Drive control verification " + "(lto-5)", "dcv_", NULL}, /* 0x3a, 0 SSC */ + {0x3b, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Host port 1 interface errors " + "(lto-5)", "hp1_", NULL}, /* 0x3b, 0 SSC */ + {0x3c, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Drive usage information " + "(lto-5)", "dui_", NULL}, /* 0x3c, 0 SSC */ + {0x3d, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Subsystem statistics (lto-5)", + "ss_", NULL}, /* 0x3d, 0 SSC */ {0x3e, 0, 0, PDT_DISK, VENDOR_M, "Factory (seagate)", "f_se", show_seagate_factory_page}, /* 0x3e, 0 SBC */ {0x3e, 0, 0, PDT_DISK, VENDOR_M, "Factory (hitachi)", "f_hi", NULL}, /* 0x3e, 0 SBC */ - {0x3e, 0, 0, PDT_TAPE, VENDOR_M, "Device Status (lto-6)", "ds_", - NULL}, /* 0x3e, 0 SSC */ + {0x3e, 0, 0, PDT_TAPE, VENDOR_M | LTO5_M, "Device Status (lto-5, 6)", + "ds_", NULL}, /* 0x3e, 0 SSC */ {-1, -1, -1, -1, -1, NULL, "zzzzz", NULL}, /* end sentinel */ }; @@ -395,14 +398,15 @@ usage(int hval) if (1 == hval) { pr2serr( "Usage: sg_logs [--all] [--brief] [--control=PC] [--enumerate] " - "[--filter=FI]\n" - " [--help] [--hex] [--in=FN] [--list] [--no_inq] " - "[--maxlen=LEN]\n" - " [--name] [--page=PG] [--paramp=PP] [--pcb] " - "[--ppc] [--raw]\n" - " [--readonly] [--reset] [--select] [--sp] " - "[--temperature]\n" - " [--transport] [--verbose] [--version] DEVICE\n" + "[--enum_vendor]\n" + " [--filter=FI] [--help] [--hex] [--in=FN] [--list] " + "[--no_inq]\n" + " [--maxlen=LEN] [--name] [--page=PG] [--paramp=PP] " + "[--pcb]\n" + " [--ppc] [--raw] [--readonly] [--reset] [--select] " + "[--sp]\n" + " [--temperature] [--transport] [--verbose] " + "[--version] DEVICE\n" " where the main options are:\n" " --all|-a fetch and decode all log pages, but not " "subpages; use\n" @@ -415,6 +419,8 @@ usage(int hval) "by acronym;\n" " '-eee': all numerically; '-eeee': " "non-v numerically\n" + " --enum_vendor|-E enumerate known specific vendor pages " + "only\n" " --filter=FI|-f FI FI is parameter code to display (def: " "all); with\n" " '-e' then FI>=0 enumerate that pdt + " @@ -489,13 +495,13 @@ usage(int hval) static void usage_old() { - printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-e] [-f=FI] [-h] [-H] " - "[-i=FN]\n" - " [-l] [-L] [-m=LEN] [-n] [-p=PG] " + printf("Usage: sg_logs [-a] [-A] [-b] [-c=PC] [-e] [-E] [-f=FI] [-h] " + "[-H]\n" + " [-i=FN] [-l] [-L] [-m=LEN] [-n] [-p=PG] " "[-paramp=PP]\n" - " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] " + " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] " "[-v] [-V]\n" - " [-x] [-X] [-?] DEVICE\n" + " [-x] [-X] [-?] DEVICE\n" " where:\n" " -a fetch and decode all log pages\n" " -A fetch and decode all log pages and subpages\n" @@ -504,6 +510,7 @@ usage_old() " 0: current threshhold, 1: current cumulative\n" " 2: default threshhold, 3: default cumulative\n" " -e enumerate known log pages\n" + " -E enumerate known vendor specific log pages only\n" " -f=FI filter match parameter code or pdt\n" " -h output in hex (default: decode if known)\n" " -H output in hex (same as '-h')\n" @@ -572,6 +579,8 @@ enumerate_helper(const struct log_elem * lep, int pos, printf("===================================================\n"); } } + if ((op->do_enum_vendor > 0) && !(VENDOR_M & lep->flags)) + return; if ((0 == (op->do_enumerate % 2)) && (VENDOR_M & lep->flags)) return; /* if do_enumerate is even then skip vendor pages */ else if ((! op->filter_given) || (-1 == op->filter)) @@ -662,6 +671,8 @@ pg_subpg_pdt_search(int pg_code, int subpg_code, int pdt) return lep; else if (d_pdt == lep->pdt) return lep; + else if (pdt == sg_lib_pdt_decay(lep->pdt)) + return lep; } else if ((lep->subpg_high > 0) && (subpg_code > lep->subpg_code) && (subpg_code <= lep->subpg_high)) @@ -690,7 +701,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "aAbc:ef:hHi:lLm:nNOp:P:qQrRsStTvVxX", + c = getopt_long(argc, argv, "aAbc:eEf:hHi:lLm:nNOp:P:qQrRsStTvVxX", long_options, &option_index); if (c == -1) break; @@ -717,6 +728,9 @@ process_cl_new(struct opts_t * op, int argc, char * argv[]) case 'e': ++op->do_enumerate; break; + case 'E': + ++op->do_enum_vendor; + break; case 'f': if ('-' == optarg[0]) { n = sg_get_num(optarg + 1); @@ -871,6 +885,9 @@ process_cl_old(struct opts_t * op, int argc, char * argv[]) case 'e': ++op->do_enumerate; break; + case 'E': + ++op->do_enum_vendor; + break; case 'h': case 'H': ++op->do_hex; @@ -1089,17 +1106,35 @@ 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 uint8_t * xp, int len) +/* Assumes an integral numbers of bytes pointed to by 'xp' of length + * 'num_bytes' given. [So the number of bits modulo 8 must be zero.] + * Returns true if all bytes are 0xff (which is the same as all bits + * being set), else returns false. */ +static bool +all_bits_set(const uint8_t * xp, int num_bytes) { - if (len > (int)sizeof(uint64_t)) { - xp += (len - sizeof(uint64_t)); - len = sizeof(uint64_t); + for ( ; num_bytes > 0; ++xp, --num_bytes) { + if (0xff != *xp) + return false; } - return sg_get_unaligned_be64(xp + 0); + return true; +} + +static char * +num_or_unknown(const uint8_t * xp, int num_bytes, bool in_hex, char * b, + int blen) +{ + if (all_bits_set(xp, num_bytes)) + snprintf(b, blen, "unknown"); + else { + uint64_t num = sg_get_unaligned_be(num_bytes, xp); + + if (in_hex) + snprintf(b, blen, "0x%" PRIx64, num); + else + snprintf(b, blen, "%" PRIu64, num); + } + return b; } /* Read ASCII hex bytes or binary from fname (a file named '-' taken as @@ -1475,7 +1510,7 @@ show_buffer_over_under_run_page(const uint8_t * resp, int len, while (num > 3) { cp = NULL; pl = ucp[3] + 4; - count = (pl > 4) ? decode_count(ucp + 4, pl - 4) : 0; + count = (pl > 4) ? sg_get_unaligned_be(pl - 4, ucp + 4) : 0; pc = sg_get_unaligned_be16(ucp + 0); if (op->filter_given) { if (pc != op->filter) @@ -1645,7 +1680,7 @@ show_error_counter_page(const uint8_t * resp, int len, case 0x8015: printf(" Positioning errors [Hitachi]"); break; default: printf(" Reserved or vendor specific [0x%x]", pc); break; } - printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); + printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4)); if (op->do_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -1699,7 +1734,7 @@ show_non_medium_error_page(const uint8_t * resp, int len, printf(" Vendor specific [0x%x]", pc); break; } - printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); + printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4)); if (op->do_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -1758,7 +1793,7 @@ show_power_condition_transitions_page(const uint8_t * resp, int len, default: printf(" Reserved [0x%x]", pc); } - printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); + printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4)); if (op->do_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -2409,9 +2444,11 @@ show_self_test_page(const uint8_t * resp, int len, const struct opts_t * op) printf(" self-test result: %s [%d]\n", self_test_result[res], res); if (ucp[5]) printf(" self-test number = %d\n", (int)ucp[5]); - ull = sg_get_unaligned_be64(ucp + 8); - if ((0xffffffffffffffffULL != ull) && (res > 0) && ( res < 0xf)) - printf(" address of first error = 0x%" PRIx64 "\n", ull); + if (! all_bits_set(ucp + 8, 8)) { + ull = sg_get_unaligned_be64(ucp + 8); + if ((res > 0) && ( res < 0xf)) + printf(" address of first error = 0x%" PRIx64 "\n", ull); + } v = ucp[16] & 0xf; if (v) { printf(" sense key = 0x%x [%s] , asc = 0x%x, ascq = 0x%x", @@ -2512,7 +2549,6 @@ static bool show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op) { int k, num, extra, pc, pcb; - unsigned int n; const uint8_t * ucp; char pcb_str[PCB_STR_LEN]; @@ -2567,42 +2603,40 @@ show_start_stop_page(const uint8_t * resp, int len, const struct opts_t * op) break; case 3: if (extra > 7) { - n = sg_get_unaligned_be32(ucp + 4); - if (0xffffffff == n) + if (all_bits_set(ucp + 4, 4)) printf(" Specified cycle count over device lifetime " "= -1"); else printf(" Specified cycle count over device lifetime " - "= %u", n); + "= %u", sg_get_unaligned_be32(ucp + 4)); } break; case 4: if (extra > 7) { - n = sg_get_unaligned_be32(ucp + 4); - if (0xffffffff == n) + if (all_bits_set(ucp + 4, 4)) printf(" Accumulated start-stop cycles = -1"); else - printf(" Accumulated start-stop cycles = %u", n); + printf(" Accumulated start-stop cycles = %u", + sg_get_unaligned_be32(ucp + 4)); } break; case 5: if (extra > 7) { - n = sg_get_unaligned_be32(ucp + 4); - if (0xffffffff == n) + if (all_bits_set(ucp + 4, 4)) printf(" Specified load-unload count over device " "lifetime = -1"); else printf(" Specified load-unload count over device " - "lifetime = %u", n); + "lifetime = %u", sg_get_unaligned_be32(ucp + 4)); } break; case 6: if (extra > 7) { - n = sg_get_unaligned_be32(ucp + 4); - if (0xffffffff == n) + if (all_bits_set(ucp + 4, 4)) printf(" Accumulated load-unload cycles = -1"); else - printf(" Accumulated load-unload cycles = %u", n); + printf(" Accumulated load-unload cycles = %u", + sg_get_unaligned_be32(ucp + 4)); } break; default: @@ -2904,6 +2938,37 @@ show_sas_phy_event_info(int pes, unsigned int val, unsigned int thresh_val) } } +static const char * sas_link_rate_arr[16] = { + "phy enabled; unknown rate", + "phy disabled", + "phy enabled; speed negotiation failed", + "phy enabled; SATA spinup hold state", + "phy enabled; port selector", + "phy enabled; reset in progress", + "phy enabled; unsupported phy attached", + "reserved [0x7]", + "1.5 Gbps", /* 0x8 */ + "3 Gbps", + "6 Gbps", + "12 Gbps", + "22.5 Gbps", + "reserved [0xd]", + "reserved [0xe]", + "reserved [0xf]", +}; + +static char * +sas_negot_link_rate(int lrate, char * b, int blen) +{ + int mask = 0xf; + + if (~mask & lrate) + snprintf(b, blen, "bad link_rate value=0x%x\n", lrate); + else + snprintf(b, blen, "%s", sas_link_rate_arr[lrate]); + return b; +} + /* helper for SAS port of PROTO_SPECIFIC_LPAGE [0x18] */ static void show_sas_port_param(const uint8_t * ucp, int param_len, @@ -3018,49 +3083,8 @@ show_sas_port_param(const uint8_t * ucp, int param_len, default: snprintf(s, sz, "reserved [0x%x]", t); break; } printf(" reason: %s\n", s); - t = (0xf & vcp[5]); - switch (t) { - case 0: - snprintf(s, sz, "phy enabled; unknown reason"); - break; - case 1: - snprintf(s, sz, "phy disabled"); - break; - case 2: - snprintf(s, sz, "phy enabled; speed negotiation failed"); - break; - case 3: - snprintf(s, sz, "phy enabled; SATA spinup hold state"); - break; - case 4: - snprintf(s, sz, "phy enabled; port selector"); - break; - case 5: - snprintf(s, sz, "phy enabled; reset in progress"); - break; - case 6: - snprintf(s, sz, "phy enabled; unsupported phy attached"); - break; - case 8: - snprintf(s, sz, "1.5 Gbps"); - break; - case 9: - snprintf(s, sz, "3 Gbps"); - break; - case 0xa: - snprintf(s, sz, "6 Gbps"); - break; - case 0xb: - snprintf(s, sz, "12 Gbps"); - break; - case 0xc: - snprintf(s, sz, "22.5 Gbps"); - break; - default: - snprintf(s, sz, "reserved [%d]", t); - break; - } - printf(" negotiated logical link rate: %s\n", s); + printf(" negotiated logical link rate: %s\n", + sas_negot_link_rate((0xf & vcp[5]), s, sz)); printf(" attached initiator port: ssp=%d stp=%d smp=%d\n", !! (vcp[6] & 8), !! (vcp[6] & 4), !! (vcp[6] & 2)); printf(" attached target port: ssp=%d stp=%d smp=%d\n", @@ -4041,6 +4065,7 @@ show_dt_device_status_page(const uint8_t * resp, int len, int num, pl, pc, pcb, j; const uint8_t * ucp; char str[PCB_STR_LEN]; + char b[64]; if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex))) printf("DT device status page (ssc-3, adc-3) [0x11]\n"); @@ -4136,11 +4161,32 @@ show_dt_device_status_page(const uint8_t * resp, int len, 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); + if ((pc >= 0x101) && (pc <= 0x1ff)) { + printf(" Primary port %d status:\n", pc - 0x100); + if (12 == ucp[3]) { /* if length of desc is 12, assume SAS */ + printf(" SAS: negotiated physical link rate: %s\n", + sas_negot_link_rate((0xf & (ucp[4] >> 4)), b, + sizeof(b))); + printf(" signal=%d, pic=%d, ", !!(0x2 & ucp[4]), + !!(0x1 & ucp[4])); + printf("hashed SAS addr: 0x%u\n", + sg_get_unaligned_be24(ucp + 5)); + printf(" SAS addr: 0x%" PRIx64 "\n", + sg_get_unaligned_be64(ucp + 8)); + } else { + printf(" non-SAS transport, in hex:\n"); + dStrHex((const char *)ucp + 4, + ((pl < num) ? pl : num) - 4, 0); + } + } else if (pc >= 0x8000) { + printf(" Vendor specific [parameter_code=0x%x]:\n", pc); + dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); + } else { + printf(" Reserved [parameter_code=0x%x]:\n", pc); + dStrHex((const char *)ucp, ((pl < num) ? pl : num), 0); + } break; } -// xxxxxxxxxxxxxxx if (op->do_pcb) { get_pcb_str(pcb, str, sizeof(str)); printf(" <%s>\n", str); @@ -4575,6 +4621,7 @@ show_sequential_access_page(const uint8_t * resp, int len, int num, pl, pc, pcb; const uint8_t * ucp; uint64_t ull, gbytes; + bool all_set; char pcb_str[PCB_STR_LEN]; if (op->verbose || ((0 == op->do_raw) && (0 == op->do_hex))) @@ -4596,7 +4643,8 @@ show_sequential_access_page(const uint8_t * resp, int len, break; } } - ull = decode_count(ucp + 4, pl - 4); + ull = sg_get_unaligned_be(pl - 4, ucp + 4); + all_set = all_bits_set(ucp + 4, pl - 4); gbytes = ull / 1000000000; switch (pc) { case 0: @@ -4628,24 +4676,29 @@ show_sequential_access_page(const uint8_t * resp, int len, printf("\n"); break; case 4: - printf(" Native capacity from BOP to EOD: %" PRIu64 " MB\n", - ull); + if (! all_set) + printf(" Native capacity from BOP to EOD: %" PRIu64 " MB\n", + ull); break; case 5: - printf(" Native capacity from BOP to EW of current partition: " - "%" PRIu64 " MB\n", ull); + if (! all_set) + printf(" Native capacity from BOP to EW of current " + "partition: %" PRIu64 " MB\n", ull); break; case 6: - printf(" Minimum native capacity from EW to EOP of current " - "partition: %" PRIu64 " MB\n", ull); + if (! all_set) + printf(" Minimum native capacity from EW to EOP of current " + "partition: %" PRIu64 " MB\n", ull); break; case 7: - printf(" Native capacity from BOP to current position: %" - PRIu64 " MB\n", ull); + if (! all_set) + printf(" Native capacity from BOP to current position: %" + PRIu64 " MB\n", ull); break; case 8: - printf(" Maximum native capacity in device object buffer: %" - PRIu64 " MB\n", ull); + if (! all_set) + printf(" Maximum native capacity in device object buffer: %" + PRIu64 " MB\n", ull); break; case 0x100: if (ull > 0) @@ -4707,7 +4760,7 @@ show_device_stats_page(const uint8_t * resp, int len, } } if (pc < 0x1000) { - ull = decode_count(ucp + 4, pl - 4); + ull = sg_get_unaligned_be(pl - 4, ucp + 4); switch (pc) { case 0: printf(" Lifetime media loads: %" PRIu64 "\n", ull); @@ -4755,21 +4808,88 @@ show_device_stats_page(const uint8_t * resp, int len, "initiated forced reset\n and/or emergency " "eject occurred: %" PRIu64 "\n", ull); break; + case 0xc: + printf(" Lifetime power cycles: %" PRIu64 "\n", ull); + break; + case 0xd: + printf(" Volume loads since last parameter reset: %" PRIu64 + "\n", ull); + break; + case 0xe: + printf(" Hard write errors: %" PRIu64 "\n", ull); + break; + case 0xf: + printf(" Hard read errors: %" PRIu64 "\n", ull); + break; + case 0x10: + printf(" Duty cycle sample time: %" PRIu64 " ms\n", ull); + break; + case 0x11: + printf(" Read duty cycle: %" PRIu64 "\n", ull); + break; + case 0x12: + printf(" Write duty cycle: %" PRIu64 "\n", ull); + break; + case 0x13: + printf(" Activity duty cycle: %" PRIu64 "\n", ull); + break; + case 0x14: + printf(" Volume not present duty cycle: %" PRIu64 "\n", ull); + break; + case 0x15: + printf(" Ready duty cycle: %" PRIu64 "\n", ull); + break; + case 0x16: + printf(" MBs transferred from app client in duty cycle " + "sample time: %" PRIu64 "\n", ull); + break; + case 0x17: + printf(" MBs transferred to app client in duty cycle " + "sample time: %" PRIu64 "\n", ull); + break; + case 0x40: + printf(" Drive manufacturer's serial number: %" PRIu64 "\n", + ull); + break; + case 0x41: + printf(" Drive serial number: %" PRIu64 "\n", ull); + break; + case 0x80: + printf(" Medium removal prevented: %" PRIu64 "\n", ull); + break; + case 0x81: + printf(" Maximum recommended mechanism temperature " + "exceeded: %" PRIu64 "\n", ull); + break; + case 0x1000: + printf(" Medium motion hours for each medium type: %" PRIu64 + "\n", ull); + break; default: - printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n", - pc, ull); + printf(" Reserved parameter [0x%x] value: %" PRIu64 "\n", pc, + ull); break; } } else { + int k; + const uint8_t * p = ucp + 4; + switch (pc) { case 0x1000: 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 + for (k = 0; ((pl - 4) - k) >= 8; k += 8, p += 8) { + printf(" Density code: 0x%x, Medium type: 0x%x\n", + p[2], p[3]); + printf(" Medium motion hours: %u\n", + sg_get_unaligned_be32(p + 4)); + } break; default: - printf(" Reserved parameter [0x%x], dump in hex:\n", pc); + if (pc >= 0x8000) + printf(" Vendor specific parameter [0x%x], dump in " + "hex:\n", pc); + else + printf(" Reserved parameter [0x%x], dump in hex:\n", pc); dStrHex((const char *)ucp, pl, 0); break; } @@ -4815,7 +4935,7 @@ show_media_stats_page(const uint8_t * resp, int len, const struct opts_t * op) break; } } - ull = decode_count(ucp + 4, pl - 4); + ull = sg_get_unaligned_be(pl - 4, ucp + 4); switch (pc) { case 0: printf(" Number of moves: %" PRIu64 "\n", ull); @@ -5170,51 +5290,46 @@ skip: /* Helper for show_volume_stats_page() */ static void -volume_stats_partition(const uint8_t * xp, int len, int hex) +volume_stats_partition(const uint8_t * xp, int len, bool in_hex) { - int dl, pn; + int dl, pn, k; + bool all_ffs, ffs_last_fe; + uint8_t uc; + uint64_t ull; while (len > 3) { dl = xp[0] + 1; if (dl < 3) return; pn = sg_get_unaligned_be16(xp + 2); - if (hex) - printf(" partition number: %d, partition record data " - "counter: 0x%" PRIx64 "\n", pn, - decode_count(xp + 4, dl - 4)); - else { - int k; - int all_ffs = 0; - int ffs_last_fe = 0; - uint8_t 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; - } + for (k = 0, all_ffs = false, ffs_last_fe = false; 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 = true; + else if (0xfe == uc) + ffs_last_fe = true; } - - if (0 == (all_ffs + ffs_last_fe)) - printf(" partition number: %d, partition record data " - "counter: %" PRIu64 "\n", pn, - decode_count(xp + 4, dl - 4)); - else if (all_ffs) + } + if ((! all_ffs) && (! ffs_last_fe)) { + ull = sg_get_unaligned_be(dl - 4, xp + 4); + if (in_hex) printf(" partition number: %d, partition record data " - "counter is all 0xFFs\n", pn); + "counter: 0x%" PRIx64 "\n", pn, ull); else printf(" partition number: %d, partition record data " - "counter is all 0xFFs apart\n from a trailing " - "0xFE\n", pn); - } + "counter: %" PRIu64 "\n", pn, ull); + } else if (all_ffs) + printf(" partition number: %d, partition record data " + "counter is all 0xFFs\n", pn); + else + printf(" partition number: %d, partition record data " + "counter is all 0xFFs apart\n from a trailing " + "0xFE\n", pn); xp += dl; len -= dl; } @@ -5228,6 +5343,7 @@ show_volume_stats_page(const uint8_t * resp, int len, int num, pl, pc, pcb, spf, subpg_code; const uint8_t * ucp; char pcb_str[PCB_STR_LEN]; + char b[64]; spf = !!(resp[0] & 0x40); subpg_code = spf ? resp[1] : 0; @@ -5265,99 +5381,99 @@ show_volume_stats_page(const uint8_t * resp, int len, switch (pc) { case 0: printf(" Page valid: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 1: printf(" Thread count: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 2: printf(" Total data sets written: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 3: printf(" Total write retries: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 4: printf(" Total unrecovered write errors: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 5: printf(" Total suspended writes: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 6: printf(" Total fatal suspended writes: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 7: printf(" Total data sets read: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 8: printf(" Total read retries: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 9: printf(" Total unrecovered read errors: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xa: printf(" Total suspended reads: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xb: printf(" Total fatal suspended reads: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xc: printf(" Last mount unrecovered write errors: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xd: printf(" Last mount unrecovered read errors: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xe: printf(" Last mount megabytes written: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0xf: printf(" Last mount megabytes read: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x10: printf(" Lifetime megabytes written: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x11: printf(" Lifetime megabytes read: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x12: printf(" Last load write compression ratio: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x13: printf(" Last load read compression ratio: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x14: printf(" Medium mount time: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x15: printf(" Medium ready time: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x16: - printf(" Total native capacity: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + printf(" Total native capacity [MB]: %s\n", + num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b))); break; case 0x17: - printf(" Total used native capacity: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + printf(" Total used native capacity [MB]: %s\n", + num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b))); break; case 0x40: printf(" Volume serial number: %.*s\n", pl - 4, ucp + 4); @@ -5378,49 +5494,50 @@ show_volume_stats_page(const uint8_t * resp, int len, printf(" Volume personality: %.*s\n", pl - 4, ucp + 4); break; case 0x80: - printf(" Write protect: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + printf(" Write protect: %s\n", + num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b))); break; case 0x81: - printf(" WORM: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + printf(" WORM: %s\n", + num_or_unknown(ucp + 4, pl - 4, false, b, sizeof(b))); break; case 0x82: - printf(" Maximum recommended tape path temperature exceeded: %" - PRIu64 "\n", decode_count(ucp + 4, pl - 4)); + printf(" Maximum recommended tape path temperature exceeded: " + "%s\n", num_or_unknown(ucp + 4, pl - 4, false, b, + sizeof(b))); break; case 0x100: printf(" Volume write mounts: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x101: printf(" Beginning of medium passes: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x102: printf(" Middle of medium passes: %" PRIu64 "\n", - decode_count(ucp + 4, pl - 4)); + sg_get_unaligned_be(pl - 4, ucp + 4)); break; case 0x200: printf(" Logical position of first encrypted logical object:\n"); - volume_stats_partition(ucp + 4, pl - 4, 1); + volume_stats_partition(ucp + 4, pl - 4, true); 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); + volume_stats_partition(ucp + 4, pl - 4, true); break; case 0x202: - printf(" Native capacity partition(s):\n"); - volume_stats_partition(ucp + 4, pl - 4, 0); + printf(" Native capacity partition(s) [MB]:\n"); + volume_stats_partition(ucp + 4, pl - 4, false); break; case 0x203: - printf(" Used native capacity partition(s):\n"); - volume_stats_partition(ucp + 4, pl - 4, 0); + printf(" Used native capacity partition(s) [MB]:\n"); + volume_stats_partition(ucp + 4, pl - 4, false); break; case 0x204: - printf(" Remaining native capacity partition(s):\n"); - volume_stats_partition(ucp + 4, pl - 4, 0); + printf(" Remaining native capacity partition(s) [MB]:\n"); + volume_stats_partition(ucp + 4, pl - 4, false); break; case 0x300: printf(" Mount history, payload in hex:\n"); @@ -5611,7 +5728,7 @@ show_seagate_cache_page(const uint8_t * resp, int len, "> segment size"); break; default: printf(" Unknown Seagate parameter code = 0x%x", pc); break; } - printf(" = %" PRIu64 "", decode_count(ucp + 4, pl - 4)); + printf(" = %" PRIu64 "", sg_get_unaligned_be(pl - 4, ucp + 4)); if (op->do_pcb) { get_pcb_str(pcb, pcb_str, sizeof(pcb_str)); printf("\n <%s>\n", pcb_str); @@ -5666,7 +5783,7 @@ show_seagate_factory_page(const uint8_t * resp, int len, break; } if (valid) { - ull = decode_count(ucp + 4, pl - 4); + ull = sg_get_unaligned_be(pl - 4, ucp + 4); if (0 == pc) printf(" = %.2f", ((double)ull) / 60.0 ); else @@ -5711,11 +5828,10 @@ show_ascii_page(const uint8_t * resp, int len, const struct opts_t * op) if (! done) { if (spf) - printf("No ascii information for page = 0x%x, subpage = 0x%x, " - "here is hex:\n", pg_code, subpg_code); + printf("Unable to decode page = 0x%x, subpage = 0x%x, here is " + "hex:\n", pg_code, subpg_code); else - printf("No ascii information for page = 0x%x, here is hex:\n", - pg_code); + printf("Unable to decode page = 0x%x, here is hex:\n", pg_code); if (len > 128) { dStrHex((const char *)resp, 64, 1); printf(" ..... [truncated after 64 of %d bytes (use '-H' to " @@ -5853,10 +5969,12 @@ main(int argc, char * argv[]) pr2serr("Version string: %s\n", version_str); return 0; } - if (op->do_enumerate > 0) { + if ((op->do_enumerate > 0) || (op->do_enum_vendor > 0)) { if (op->device_name && op->verbose) pr2serr("Warning: device: %s is being ignored\n", op->device_name); + if ((op->do_enum_vendor > 0) && (0 == op->do_enumerate)) + op->do_enumerate = 1; enumerate_pages(op); return 0; } diff --git a/src/sg_persist.c b/src/sg_persist.c index 957525d4..9d19e79d 100644 --- a/src/sg_persist.c +++ b/src/sg_persist.c @@ -1,5 +1,5 @@ /* A utility program originally written for the Linux OS SCSI subsystem. - * Copyright (C) 2004-2015 D. Gilbert + * Copyright (C) 2004-2016 D. Gilbert * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -28,7 +28,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "0.51 20151219"; +static const char * version_str = "0.52 20160201"; #define PRIN_RKEY_SA 0x0 @@ -779,8 +779,8 @@ decode_sym_transportid(const char * lcp, unsigned char * tidp) return 0; } -/* Read one or more TransportIDs from the given file or from stdin. - * Returns 0 if successful, 1 otherwise. */ +/* Read one or more TransportIDs from the given file or stdin. Reads from + * stdin when 'fnp' is NULL. Returns 0 if successful, 1 otherwise. */ static int decode_file_tids(const char * fnp, struct opts_t * op) { @@ -797,7 +797,7 @@ decode_file_tids(const char * fnp, struct opts_t * op) if (fnp) { fp = fopen(fnp, "r"); if (NULL == fp) { - pr2serr("decode_file_tids: unable to open %s\n", fnp); + pr2serr("%s: unable to open %s\n", __func__, fnp); return 1; } } @@ -825,8 +825,8 @@ decode_file_tids(const char * fnp, struct opts_t * op) if (1 == sscanf(carry_over, "%x", &h)) tid_arr[off - 1] = h; /* back up and overwrite */ else { - pr2serr("decode_file_tids: carry_over error ['%s'] " - "around line %d\n", carry_over, j + 1); + pr2serr("%s: carry_over error ['%s'] around line %d\n", + __func__, carry_over, j + 1); goto bad; } lcp = line + 1; @@ -847,16 +847,15 @@ decode_file_tids(const char * fnp, struct opts_t * op) goto my_cont_a; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if ((k < in_len) && ('#' != lcp[k])) { - pr2serr("decode_file_tids: syntax error at line %d, pos %d\n", - j + 1, m + k + 1); + pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1, + m + k + 1); goto bad; } for (k = 0; k < 1024; ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { - pr2serr("decode_file_tids: hex number larger than 0xff " - "in line %d, pos %d\n", j + 1, - (int)(lcp - line + 1)); + pr2serr("%s: hex number larger than 0xff in line %d, pos " + "%d\n", __func__, j + 1, (int)(lcp - line + 1)); goto bad; } if (split_line && (1 == strlen(lcp))) { @@ -864,7 +863,7 @@ decode_file_tids(const char * fnp, struct opts_t * op) carry_over[0] = *lcp; } if ((off + k) >= (int)sizeof(op->transportid_arr)) { - pr2serr("decode_file_tids: array length exceeded\n"); + pr2serr("%s: array length exceeded\n", __func__); goto bad; } tid_arr[off + k] = h; @@ -879,20 +878,22 @@ decode_file_tids(const char * fnp, struct opts_t * op) --k; break; } - pr2serr("decode_file_tids: error in line %d, at pos %d\n", - j + 1, (int)(lcp - line + 1)); + pr2serr("%s: error in line %d, at pos %d\n", __func__, j + 1, + (int)(lcp - line + 1)); goto bad; } } my_cont_a: off += MX_TID_LEN; if (off >= (MX_TIDS * MX_TID_LEN)) { - pr2serr("decode_file_tids: array length exceeded\n"); + pr2serr("%s: array length exceeded\n", __func__); goto bad; } ++num; } op->num_transportids = num; + if (fnp) + fclose(fp); return 0; bad: diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c index 4b89a5f4..384bb18d 100644 --- a/src/sg_read_buffer.c +++ b/src/sg_read_buffer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2015 Luben Tuikov and Douglas Gilbert. + * Copyright (c) 2006-2016 Luben Tuikov and Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -30,7 +30,7 @@ * device. */ -static const char * version_str = "1.14 20151219"; +static const char * version_str = "1.15 20160131"; #ifndef SG_READ_BUFFER_10_CMD @@ -484,14 +484,13 @@ main(int argc, char * argv[]) else { switch (rb_mode) { case MODE_DESCRIPTOR: - k = (resp[1] << 16) | (resp[2] << 8) | resp[3]; + k = sg_get_unaligned_be24(resp + 1); printf("OFFSET BOUNDARY: %d, Buffer offset alignment: " "%d-byte\n", resp[0], (1 << resp[0])); printf("BUFFER CAPACITY: %d (0x%x)\n", k, k); break; case MODE_ECHO_BDESC: - k = ((resp[2] & 0x1F) << 8) | resp[3]; - + k = sg_get_unaligned_be16(resp + 2) & 0x1fff; printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0); printf("Echo buffer capacity: %d (0x%x)\n", k, k); break; diff --git a/src/sg_referrals.c b/src/sg_referrals.c index 051f3520..de65010d 100644 --- a/src/sg_referrals.c +++ b/src/sg_referrals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Hannes Reinecke. + * Copyright (c) 2010-2016 Hannes Reinecke. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -31,7 +31,7 @@ * SCSI device. */ -static const char * version_str = "1.05 20151219"; /* sbc4r01 */ +static const char * version_str = "1.06 20160131"; /* sbc4r10 */ #define MAX_REFER_BUFF_LEN (1024 * 1024) #define DEF_REFER_BUFF_LEN 256 @@ -154,7 +154,8 @@ decode_referral_desc(const unsigned char * ucp, int bytes) return -1; printf(" target port descriptor %d:\n", j); printf(" port group %x state (%s)\n", - (ucp[n+2] << 8) | (ucp[n+3]), decode_tpgs_state(ucp[n] & 0xf)); + sg_get_unaligned_be16(ucp + n + 2), + decode_tpgs_state(ucp[n] & 0xf)); n += 4; bytes -= 4; } @@ -284,8 +285,7 @@ main(int argc, char * argv[]) * possible user segments. * And maybe someone takes a pity and updates the spec ... */ - rlen = (referralBuffp[0] << 24) + (referralBuffp[1] << 16) + - (referralBuffp[2] << 8) + referralBuffp[3] + 4; + rlen = sg_get_unaligned_be32(referralBuffp + 0) + 4; else rlen = maxlen; k = (rlen > maxlen) ? maxlen : rlen; diff --git a/src/sg_ses.c b/src/sg_ses.c index c04a5797..64996641 100644 --- a/src/sg_ses.c +++ b/src/sg_ses.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2015 Douglas Gilbert. + * Copyright (c) 2004-2016 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. @@ -30,7 +30,7 @@ * commands tailored for SES (enclosure) devices. */ -static const char * version_str = "2.06 20151219"; /* ses3r08->11 */ +static const char * version_str = "2.07 20160201"; /* ses3r08->11 */ #define MX_ALLOC_LEN ((64 * 1024) - 4) /* max allowable for big enclosures */ #define MX_ELEM_HDR 1024 @@ -1615,14 +1615,14 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, resp = (unsigned char *)calloc(op->maxlen, 1); if (NULL == resp) { - pr2serr("populate: unable to allocate %d bytes on heap\n", + pr2serr("%s: unable to allocate %d bytes on heap\n", __func__, op->maxlen); ret = -1; goto the_end; } res = do_rec_diag(fd, DPC_CONFIGURATION, resp, op->maxlen, op, &resp_len); if (res) { - pr2serr("populate: couldn't read config page, res=%d\n", res); + pr2serr("%s: couldn't read config page, res=%d\n", __func__, res); ret = -1; goto the_end; } @@ -1643,7 +1643,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, el = ucp[3] + 4; sum_type_dheaders += ucp[2]; if (el < 40) { - pr2serr("populate: short enc descriptor len=%d ??\n", el); + pr2serr("%s: short enc descriptor len=%d ??\n", __func__, el); continue; } if ((0 == k) && primary_ip) { @@ -1660,7 +1660,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, if ((ucp + 3) > last_ucp) goto p_truncated; if (k >= MX_ELEM_HDR) { - pr2serr("populate: too many elements\n"); + pr2serr("%s: too many elements\n", __func__); ret = -1; goto the_end; } @@ -1683,10 +1683,10 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, op->ind_th = k; else { if (op->ind_et_inst) - pr2serr("populate: unable to find element type '%s%d'\n", + pr2serr("%s: unable to find element type '%s%d'\n", __func__, op->ind_etp->abbrev, op->ind_et_inst); else - pr2serr("populate: unable to find element type '%s'\n", + pr2serr("%s: unable to find element type '%s'\n", __func__, op->ind_etp->abbrev); ret = -1; goto the_end; @@ -1696,7 +1696,7 @@ populate_type_desc_hdr_arr(int fd, struct type_desc_hdr_t * tdhp, goto the_end; p_truncated: - pr2serr("populate: config too short\n"); + pr2serr("%s: config too short\n", __func__); ret = -1; the_end: @@ -3010,16 +3010,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) return 1; lcp = inp; in_len = strlen(inp); - if (0 == in_len) { + if (0 == in_len) *arr_len = 0; - } if (('-' == inp[0]) || ('@' == inp[0])) { /* read from stdin or file */ if ('-' == inp[0]) fp = stdin; else { fp = fopen(inp + 1, "r"); if (NULL == fp) { - pr2serr("read_hex: unable to open file: %s\n", inp + 1); + pr2serr("%s: unable to open file: %s\n", __func__, inp + 1); return 1; } } @@ -3048,8 +3047,8 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) if (1 == sscanf(carry_over, "%x", &h)) arr[off - 1] = h; /* back up and overwrite */ else { - pr2serr("read_hex: carry_over error ['%s'] around " - "line %d\n", carry_over, j + 1); + pr2serr("%s: carry_over error ['%s'] around line " + "%d\n", __func__, carry_over, j + 1); goto err_with_fp; } lcp = line + 1; @@ -3068,15 +3067,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) continue; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if (in_len != k) { - pr2serr("read_hex: syntax error at line %d, pos %d\n", j + 1, - m + k + 1); + pr2serr("%s: syntax error at line %d, pos %d\n", __func__, + j + 1, m + k + 1); goto err_with_fp; } for (k = 0; k < (MX_DATA_IN - off); ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { - pr2serr("read_hex: hex number larger than 0xff in " - "line %d, pos %d\n", j + 1, + pr2serr("%s: hex number larger than 0xff in line %d, " + "pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); goto err_with_fp; } @@ -3092,8 +3091,8 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) if ('\0' == *lcp) break; } else { - pr2serr("read_hex: error in line %d, at pos %d\n", j + 1, - (int)(lcp - line + 1)); + pr2serr("%s: error in line %d, at pos %d\n", __func__, + j + 1, (int)(lcp - line + 1)); goto err_with_fp; } } @@ -3105,15 +3104,15 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) } else { /* hex string on command line */ k = strspn(inp, "0123456789aAbBcCdDeEfF, "); if (in_len != k) { - pr2serr("read_hex: error at pos %d\n", k + 1); - return 1; + pr2serr("%s: error at pos %d\n", __func__, k + 1); + goto err_with_fp; } for (k = 0; k < MX_DATA_IN; ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { - pr2serr("read_hex: hex number larger than 0xff at pos " - "%d\n", (int)(lcp - inp + 1)); - return 1; + pr2serr("%s: hex number larger than 0xff at pos %d\n", + __func__, (int)(lcp - inp + 1)); + goto err_with_fp; } arr[k] = h; cp = (char *)strchr(lcp, ','); @@ -3126,8 +3125,9 @@ read_hex(const char * inp, unsigned char * arr, int * arr_len, int verb) cp = c2p; lcp = cp + 1; } else { - pr2serr("read_hex: error at pos %d\n", (int)(lcp - inp + 1)); - return 1; + pr2serr("%s: error at pos %d\n", __func__, + (int)(lcp - inp + 1)); + goto err_with_fp; } } *arr_len = k + 1; @@ -3157,7 +3157,7 @@ ses_process_status_page(int sg_fd, struct opts_t * op) resp = (unsigned char *)calloc(op->maxlen, 1); if (NULL == resp) { - pr2serr("process_status_page: unable to allocate %d bytes on heap\n", + pr2serr("%s: unable to allocate %d bytes on heap\n", __func__, op->maxlen); ret = -1; goto fini; @@ -4158,21 +4158,21 @@ ses_set_nickname(int sg_fd, struct opts_t * op) /* Only after the generation code, offset 4 for 4 bytes */ res = do_rec_diag(sg_fd, DPC_SUBENC_NICKNAME, b, 8, op, &resp_len); if (res) { - pr2serr("set_nickname: Subenclosure nickname status page, res=%d\n", + pr2serr("%s: Subenclosure nickname status page, res=%d\n", __func__, res); return -1; } if (resp_len < 8) { - pr2serr("set_nickname: Subenclosure nickname status page, response " - "length too short: %d\n", resp_len); + pr2serr("%s: Subenclosure nickname status page, response length too " + "short: %d\n", __func__, resp_len); return -1; } if (op->verbose) { uint32_t gc; gc = sg_get_unaligned_be32(b + 4); - pr2serr("set_nickname: generation code from status page: %" PRIu32 - "\n", gc); + pr2serr("%s: generation code from status page: %" PRIu32 "\n", + __func__, gc); } b[0] = (unsigned char)DPC_SUBENC_NICKNAME; /* just in case */ b[1] = (unsigned char)op->seid; diff --git a/src/sg_unmap.c b/src/sg_unmap.c index cdaba327..024499d0 100644 --- a/src/sg_unmap.c +++ b/src/sg_unmap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015 Douglas Gilbert. + * Copyright (c) 2009-2016 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. @@ -9,6 +9,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <ctype.h> #include <getopt.h> @@ -31,7 +32,7 @@ * logical blocks. */ -static const char * version_str = "1.09 20151219"; +static const char * version_str = "1.10 20160201"; #define DEF_TIMEOUT_SECS 60 @@ -252,7 +253,8 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr, { char line[1024]; int off = 0; - int in_len, k, j, m, have_stdin, ind, bit0; + int in_len, k, j, m, ind, bit0; + bool have_stdin; char * lcp; FILE * fp; int64_t ll; @@ -263,7 +265,7 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr, else { fp = fopen(file_name, "r"); if (NULL == fp) { - pr2serr("build_joint_arr: unable to open %s\n", file_name); + pr2serr("%s: unable to open %s\n", __func__, file_name); return 1; } } @@ -291,9 +293,9 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr, continue; k = strspn(lcp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP ,\t"); if ((k < in_len) && ('#' != lcp[k])) { - pr2serr("build_joint_arr: syntax error at line %d, pos %d\n", - j + 1, m + k + 1); - return 1; + pr2serr("%s: syntax error at line %d, pos %d\n", __func__, j + 1, + m + k + 1); + goto bad_exit; } for (k = 0; k < 1024; ++k) { ll = sg_get_llnum(lcp); @@ -301,15 +303,15 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr, ind = ((off + k) >> 1); bit0 = 0x1 & (off + k); if (ind >= max_arr_len) { - pr2serr("build_joint_arr: array length exceeded\n"); - return 1; + pr2serr("%s: array length exceeded\n", __func__); + goto bad_exit; } if (bit0) { if (ll > UINT32_MAX) { - pr2serr("build_joint_arr: number exceeds 32 bits in " - "line %d, at pos %d\n", j + 1, + pr2serr("%s: number exceeds 32 bits in line %d, at " + "pos %d\n", __func__, j + 1, (int)(lcp - line + 1)); - return 1; + goto bad_exit; } num_arr[ind] = (uint32_t)ll; } else @@ -325,20 +327,27 @@ build_joint_arr(const char * file_name, uint64_t * lba_arr, uint32_t * num_arr, --k; break; } - pr2serr("build_joint_arr: error on line %d, at pos %d\n", - j + 1, (int)(lcp - line + 1)); - return 1; + pr2serr("%s: error on line %d, at pos %d\n", __func__, j + 1, + (int)(lcp - line + 1)); + goto bad_exit; } } off += (k + 1); } if (0x1 & off) { - pr2serr("build_joint_arr: expect LBA,NUM pairs but decoded odd " - "number\n from %s\n", have_stdin ? "stdin" : file_name); - return 1; + pr2serr("%s: expect LBA,NUM pairs but decoded odd number\n from " + "%s\n", __func__, have_stdin ? "stdin" : file_name); + goto bad_exit; } *arr_len = off >> 1; + if (fp && (stdin != fp)) + fclose(fp); return 0; + +bad_exit: + if (fp && (stdin != fp)) + fclose(fp); + return 1; } diff --git a/src/sg_vpd.c b/src/sg_vpd.c index d7591054..f6ba4bb7 100644 --- a/src/sg_vpd.c +++ b/src/sg_vpd.c @@ -9,6 +9,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <ctype.h> #include <getopt.h> @@ -36,7 +37,7 @@ */ -static const char * version_str = "1.12 20160126"; /* spc5r08 + sbc4r10 */ +static const char * version_str = "1.12 20160201"; /* spc5r08 + sbc4r10 */ /* These structures are duplicates of those of the same name in @@ -286,7 +287,8 @@ static int f2hex_arr(const char * fname, int as_binary, int no_space, unsigned char * mp_arr, int * mp_arr_len, int max_arr_len) { - int fn_len, in_len, k, j, m, split_line, fd, has_stdin; + int fn_len, in_len, k, j, m, split_line, fd; + bool has_stdin; unsigned int h; const char * lcp; FILE * fp; @@ -499,7 +501,7 @@ pt_inquiry(int sg_fd, int evpd, int pg_op, void * resp, int mx_resp_len, } ptvp = construct_scsi_pt_obj(); if (NULL == ptvp) { - pr2serr("inquiry: out of memory\n"); + pr2serr("%s: out of memory\n", __func__); return -1; } set_scsi_pt_cdb(ptvp, inqCmdBlk, sizeof(inqCmdBlk)); @@ -526,7 +528,7 @@ pt_inquiry(int sg_fd, int evpd, int pg_op, void * resp, int mx_resp_len, } } else if (ret < 4) { if (verbose) - pr2serr("inquiry: got too few bytes (%d)\n", ret); + pr2serr("%s: got too few bytes (%d)\n", __func__, ret); ret = SG_LIB_CAT_MALFORMED; } else ret = 0; @@ -1892,14 +1894,14 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex) { int k, j, bump, cd_len; unsigned char * ucp; + const char * dcp = "Device constituents VPD page"; if ((1 == do_hex) || (do_hex > 2)) { dStrHex((const char *)buff, len, (1 == do_hex) ? 0 : -1); return; } if (len < 4) { - pr2serr("Deice constituents VPD page length too short=%d\n", - len); + pr2serr("%s length too short=%d\n", dcp, len); return; } len -= 4; @@ -1909,8 +1911,8 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex) printf(" Constituent descriptor %d:\n", j + 1); if ((k + 36) > len) { - pr2serr("Device constituents VPD page, short descriptor " - "length=36, left=%d\n", (len - k)); + pr2serr("%s, short descriptor length=36, left=%d\n", dcp, + (len - k)); return; } printf(" Constituent type: 0x%x\n", @@ -1922,8 +1924,8 @@ decode_dev_const_vpd(unsigned char * buff, int len, int do_hex) cd_len = sg_get_unaligned_be16(ucp + 34); bump = 36 + cd_len; if ((k + bump) > len) { - pr2serr("Device constituents VPD page, short descriptor " - "length=%d, left=%d\n", bump, (len - k)); + pr2serr("%s, short descriptor length=%d, left=%d\n", dcp, bump, + (len - k)); return; } if (cd_len > 0) { @@ -1952,13 +1954,14 @@ decode_power_consumption_vpd(unsigned char * buff, int len, int do_hex) int k, bump; unsigned char * ucp; unsigned int value; + const char * pcp = "Power consumption VPD page"; if ((1 == do_hex) || (do_hex > 2)) { dStrHex((const char *)buff, len, (1 == do_hex) ? 1 : -1); return; } if (len < 4) { - pr2serr("Power consumption VPD page length too short=%d\n", len); + pr2serr("%s length too short=%d\n", pcp,len); return; } len -= 4; @@ -1966,8 +1969,8 @@ decode_power_consumption_vpd(unsigned char * buff, int len, int do_hex) for (k = 0; k < len; k += bump, ucp += bump) { bump = 4; if ((k + bump) > len) { - pr2serr("Power consumption VPD page, short descriptor " - "length=%d, left=%d\n", bump, (len - k)); + pr2serr("%s, short descriptor length=%d, left=%d\n", pcp, bump, + (len - k)); return; } if (do_hex > 1) diff --git a/src/sg_xcopy.c b/src/sg_xcopy.c index 57369bc8..a6a6ca17 100644 --- a/src/sg_xcopy.c +++ b/src/sg_xcopy.c @@ -63,7 +63,7 @@ #include "sg_unaligned.h" #include "sg_pr2serr.h" -static const char * version_str = "0.53 20160126"; +static const char * version_str = "0.53 20160201"; #define ME "sg_xcopy: " @@ -992,7 +992,7 @@ decode_designation_descriptor(const unsigned char * ucp, int i_len) char c[2048]; sg_get_designation_descriptor_str(NULL, ucp, i_len, 1, verbose, - sizeof(c), c); + sizeof(c), c); pr2serr("%s", c); } |