diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2014-05-09 13:51:44 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2014-05-09 13:51:44 +0000 |
commit | 7c5eb1f951e4349bef24fe9056fdc6c190217d95 (patch) | |
tree | 439d5ed60b9b7bb123c5c9a1fec6a21417476414 /src | |
parent | 7a8a2dc95dec418172e43bdf46c89914f7020219 (diff) | |
download | sg3_utils-7c5eb1f951e4349bef24fe9056fdc6c190217d95.tar.gz |
sg_ses, sg_persist, sg_logs, sg_readcap, sg_read_buffer, sg_luns: add --readonly option; SG_PERSIST_O_RDONLY ev
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@573 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'src')
-rw-r--r-- | src/sg_logs.c | 70 | ||||
-rw-r--r-- | src/sg_luns.c | 37 | ||||
-rw-r--r-- | src/sg_modes.c | 316 | ||||
-rw-r--r-- | src/sg_read_buffer.c | 33 | ||||
-rw-r--r-- | src/sg_readcap.c | 200 | ||||
-rw-r--r-- | src/sg_ses.c | 15 | ||||
-rw-r--r-- | src/sg_write_buffer.c | 9 |
7 files changed, 380 insertions, 300 deletions
diff --git a/src/sg_logs.c b/src/sg_logs.c index ebd1ec13..aa7740cc 100644 --- a/src/sg_logs.c +++ b/src/sg_logs.c @@ -27,7 +27,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" -static const char * version_str = "1.18 20140504"; /* spc4r36t + sbc4r01 */ +static const char * version_str = "1.19 20140505"; /* spc4r36t + sbc4r01 */ #define MX_ALLOC_LEN (0xfffc) #define SHORT_RESP_LEN 128 @@ -78,12 +78,14 @@ static struct option long_options[] = { {"maxlen", required_argument, 0, 'm'}, {"name", no_argument, 0, 'n'}, {"new", no_argument, 0, 'N'}, + {"no_inq", no_argument, 0, 'x'}, {"old", no_argument, 0, 'O'}, {"page", required_argument, 0, 'p'}, {"paramp", required_argument, 0, 'P'}, {"pcb", no_argument, 0, 'q'}, {"ppc", no_argument, 0, 'Q'}, {"raw", no_argument, 0, 'r'}, + {"readonly", no_argument, 0, 'X'}, {"reset", no_argument, 0, 'R'}, {"sp", no_argument, 0, 's'}, {"select", no_argument, 0, 'S'}, @@ -104,6 +106,7 @@ struct opts_t { int do_pcb; int do_ppc; int do_raw; + int o_readonly; int do_pcreset; int do_select; int do_sp; @@ -119,6 +122,7 @@ struct opts_t { int subpg_code; int paramp; int opt_new; + int no_inq; const char * device_name; const char * in_fn; }; @@ -149,13 +153,15 @@ usage() { pr2serr("Usage: sg_logs [--all] [--brief] [--control=PC] [--filter=PARC] " " [--help]\n" - " [--hex] [--in=FN] [--list] [--maxlen=LEN] " - "[--name]\n" - " [--page=PG[,SPG]] [--paramp=PP] [--pcb] [--ppc] " - "[--raw]\n" - " [--reset] [--select] [--sp] [--temperature] " - "[--transport]\n" - " [--verbose] [--version] DEVICE\n" + " [--hex] [--in=FN] [--list] [--no_inq] " + "[--maxlen=LEN]\n" + " [--name] [--page=PG[,SPG]] [--paramp=PP] [--pcb] " + "[--ppc]\n" + " [--raw] [--readonly] [--reset] [--select] " + "[--sp]\n" + " [--temperature] [--transport] [--verbose] " + "[--version]\n" + " DEVICE\n" " where:\n" " --all|-a fetch and decode all log pages\n" " use twice to fetch and decode all log pages " @@ -179,6 +185,8 @@ usage() "'-p 0')\n" " use twice to list supported log page and " "subpage names\n" + " --no_inq|-x no initial INQUIRY output (twice: no " + "INQUIRY call)\n" " --maxlen=LEN|-m LEN max response length (def: 0 " "-> everything)\n" " when > 1 will request LEN bytes\n" @@ -194,6 +202,9 @@ usage() pr2serr(" --ppc|-Q set the Parameter Pointer Control (PPC) bit " "(def: 0)\n" " --raw|-r output response in binary to stdout\n" + " --readonly|-X open DEVICE read-only (def: first " + "read-write then if\n" + " fails try open again read-only)\n" " --reset|-R reset log parameters (takes PC and SP into " "account)\n" " (uses PCR bit in LOG SELECT)\n" @@ -218,7 +229,7 @@ usage_old() "[-paramp=PP]\n" " [-pcb] [-ppc] [-r] [-select] [-sp] [-t] [-T] " "[-v] [-V]\n" - " [-?] DEVICE\n" + " [-x] [-X] [-?] DEVICE\n" " where:\n" " -a fetch and decode all log pages\n" " -A fetch and decode all log pages and subpages\n" @@ -258,6 +269,10 @@ usage_old() "page (0x18)\n" " -v increase verbosity\n" " -V output version string\n" + " -x no initial INQUIRY output (twice: no INQUIRY call)\n" + " -X open DEVICE read-only (def: first read-write then " + "if fails\n" + " try open again with read-only)\n" " -? output this usage message\n\n" "Performs a SCSI LOG SENSE (or LOG SELECT) command\n"); } @@ -282,7 +297,7 @@ process_cl_new(struct opts_t * op, int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "aAbc:f:hHi:lLm:nNOp:P:qQrRsStTvV", + c = getopt_long(argc, argv, "aAbc:f:hHi:lLm:nNOp:P:qQrRsStTvVxX", long_options, &option_index); if (c == -1) break; @@ -410,6 +425,12 @@ process_cl_new(struct opts_t * op, int argc, char * argv[]) case 'V': ++op->do_version; break; + case 'x': + ++op->no_inq; + break; + case 'X': + ++op->o_readonly; + break; default: pr2serr("unrecognised option code %c [0x%x]\n", c, c); if (op->do_help) @@ -493,6 +514,12 @@ process_cl_old(struct opts_t * op, int argc, char * argv[]) case 'V': ++op->do_version; break; + case 'x': + ++op->no_inq; + break; + case 'X': + ++op->o_readonly; + break; case '?': ++op->do_help; break; @@ -5334,14 +5361,15 @@ main(int argc, char * argv[]) return SG_LIB_FILE_ERROR; } - if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /* rw */, - op->do_verbose)) < 0) { - if ((sg_fd = sg_cmds_open_device(op->device_name, 1 /* r0 */, - op->do_verbose)) < 0) { - pr2serr("error opening file: %s: %s \n", op->device_name, - safe_strerror(-sg_fd)); - return SG_LIB_FILE_ERROR; - } + sg_fd = sg_cmds_open_device(op->device_name, op->o_readonly, + op->do_verbose); + if ((sg_fd < 0) && (0 == op->o_readonly)) + sg_fd = sg_cmds_open_device(op->device_name, 1 /* ro */, + op->do_verbose); + if (sg_fd < 0) { + pr2serr("error opening file: %s: %s \n", op->device_name, + safe_strerror(-sg_fd)); + return SG_LIB_FILE_ERROR; } if (op->do_list || op->do_all) { op->pg_code = SUPP_PAGES_LPAGE; @@ -5359,13 +5387,15 @@ main(int argc, char * argv[]) } pg_len = 0; - if ((0 == op->do_raw) && (0 == op->do_select)) { + if (op->no_inq < 2) { if (sg_simple_inquiry(sg_fd, &inq_out, 1, op->do_verbose)) { pr2serr("%s doesn't respond to a SCSI INQUIRY\n", op->device_name); sg_cmds_close_device(sg_fd); return SG_LIB_CAT_OTHER; - } else if ((0 == op->do_hex) && (0 == op->do_name)) + } + if ((0 == op->do_raw) && (0 == op->do_hex) && (0 == op->do_name) && + (0 == op->no_inq)) printf(" %.8s %.16s %.4s\n", inq_out.vendor, inq_out.product, inq_out.revision); } else diff --git a/src/sg_luns.c b/src/sg_luns.c index 497b2c51..4e7bb2b2 100644 --- a/src/sg_luns.c +++ b/src/sg_luns.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2013 Douglas Gilbert. + * Copyright (c) 2004-2014 Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -28,7 +28,7 @@ * and decodes the response. */ -static const char * version_str = "1.24 20131029"; +static const char * version_str = "1.25 20140508"; #define MAX_RLUNS_BUFF_LEN (1024 * 1024) #define DEF_RLUNS_BUFF_LEN (1024 * 8) @@ -45,6 +45,7 @@ static struct option long_options[] = { {"maxlen", required_argument, 0, 'm'}, {"quiet", no_argument, 0, 'q'}, {"raw", no_argument, 0, 'r'}, + {"readonly", no_argument, 0, 'R'}, {"select", required_argument, 0, 's'}, {"test", required_argument, 0, 't'}, {"verbose", no_argument, 0, 'v'}, @@ -59,16 +60,16 @@ usage() fprintf(stderr, "Usage: " "sg_luns [--decode] [--help] [--hex] [--linux] " "[--maxlen=LEN]\n" - " [--quiet] [--raw] [--select=SR] " - "[--verbose]\n" - " [--version] DEVICE\n"); + " [--quiet] [--raw] [--readonly] " + "[--select=SR]\n" + " [--verbose] [--version] DEVICE\n"); #else fprintf(stderr, "Usage: " "sg_luns [--decode] [--help] [--hex] [--maxlen=LEN] " "[--quiet]\n" - " [--raw] [--select=SR] [--verbose] " - "[--version]\n" - " DEVICE\n"); + " [--raw] [--readonly] [--select=SR] " + "[--verbose]\n" + " [--version] DEVICE\n"); #endif fprintf(stderr, " or\n" @@ -90,12 +91,15 @@ usage() " (def: 0 -> %d bytes)\n" " --quiet|-q output only ASCII hex lun values\n" " --raw|-r output response in binary\n" + " --readonly|-R open DEVICE read-only (def: " + "read-write)\n" " --select=SR|-s SR select report SR (def: 0)\n" " 0 -> luns apart from 'well " "known' lus\n" " 1 -> only 'well known' " "logical unit numbers\n" " 2 -> all luns\n" + " spc4r36 added 0x10, 0x11 and 0x12\n" " --test=ALUN|-t ALUN decode ALUN and ignore most other " "options\n" " and DEVICE (apart from '-H')\n" @@ -341,6 +345,7 @@ main(int argc, char * argv[]) int maxlen = 0; int do_quiet = 0; int do_raw = 0; + int o_readonly = 0; int select_rep = 0; int verbose = 0; #ifdef SG_LIB_LINUX @@ -360,10 +365,10 @@ main(int argc, char * argv[]) int option_index = 0; #ifdef SG_LIB_LINUX - c = getopt_long(argc, argv, "dhHlm:qrs:t:vV", long_options, + c = getopt_long(argc, argv, "dhHlm:qrRs:t:vV", long_options, &option_index); #else - c = getopt_long(argc, argv, "dhHm:qrs:t:vV", long_options, + c = getopt_long(argc, argv, "dhHm:qrRs:t:vV", long_options, &option_index); #endif if (c == -1) @@ -399,10 +404,14 @@ main(int argc, char * argv[]) case 'r': ++do_raw; break; + case 'R': + ++o_readonly; + break; case 's': - if ((1 != sscanf(optarg, "%d", &select_rep)) || - (select_rep < 0) || (select_rep > 255)) { - fprintf(stderr, "bad argument to '--select'\n"); + select_rep = sg_get_num(optarg); + if ((select_rep < 0) || (select_rep > 255)) { + fprintf(stderr, "bad argument to '--select', expect 0 to " + "255\n"); return SG_LIB_SYNTAX_ERROR; } break; @@ -533,7 +542,7 @@ main(int argc, char * argv[]) } } - sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose); + sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); diff --git a/src/sg_modes.c b/src/sg_modes.c index 5392a565..d4e2aec8 100644 --- a/src/sg_modes.c +++ b/src/sg_modes.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2013 D. Gilbert + * Copyright (C) 2000-2014 D. Gilbert * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -25,7 +25,7 @@ #include "sg_lib.h" #include "sg_cmds_basic.h" -static const char * version_str = "1.42 20130604"; +static const char * version_str = "1.43 20140508"; #define DEF_ALLOC_LEN (1024 * 4) #define DEF_6_ALLOC_LEN 252 @@ -99,8 +99,7 @@ usage() " use twice to get all mode pages and subpages\n" " --control=PC|-c PC page control (default: 0)\n" " 0: current, 1: changeable,\n" - " 2: (manufacturer's) defaults, " - "3: saved\n" + " 2: (manufacturer's) defaults, 3: saved\n" " --dbd|-d disable block descriptors (DBD field in cdb)\n" " --dbout|-D disable block descriptor output\n" " --examine|-e examine pages # 0 through to 0x3e, note if " @@ -176,9 +175,9 @@ usage_old() } static void -usage_for(const struct opts_t * optsp) +usage_for(const struct opts_t * op) { - if (optsp->opt_new) + if (op->opt_new) usage(); else usage_old(); @@ -187,7 +186,7 @@ usage_for(const struct opts_t * optsp) /* Processes command line options according to new option format. Returns * 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */ static int -process_cl_new(struct opts_t * optsp, int argc, char * argv[]) +process_cl_new(struct opts_t * op, int argc, char * argv[]) { int c, n, nn; char * cp; @@ -202,13 +201,13 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[]) switch (c) { case '6': - ++optsp->do_six; + ++op->do_six; break; case 'a': - ++optsp->do_all; + ++op->do_all; break; case 'A': - optsp->do_all += 2; + op->do_all += 2; break; case 'c': n = sg_get_num(optarg); @@ -217,32 +216,32 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[]) usage(); return SG_LIB_SYNTAX_ERROR; } - optsp->page_control = n; + op->page_control = n; break; case 'd': - ++optsp->do_dbd; + ++op->do_dbd; break; case 'D': - ++optsp->do_dbout; + ++op->do_dbout; break; case 'e': - ++optsp->do_examine; + ++op->do_examine; break; case 'f': - ++optsp->do_flexible; + ++op->do_flexible; break; case 'h': case '?': - ++optsp->do_help; + ++op->do_help; break; case 'H': - ++optsp->do_hex; + ++op->do_hex; break; case 'l': - ++optsp->do_list; + ++op->do_list; break; case 'L': - ++optsp->do_llbaa; + ++op->do_llbaa; break; case 'm': n = sg_get_num(optarg); @@ -251,12 +250,12 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[]) usage(); return SG_LIB_SYNTAX_ERROR; } - optsp->maxlen = n; + op->maxlen = n; break; case 'N': break; /* ignore */ case 'O': - optsp->opt_new = 0; + op->opt_new = 0; return 0; case 'p': cp = strchr(optarg, ','); @@ -274,38 +273,38 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[]) usage(); return SG_LIB_SYNTAX_ERROR; } - optsp->subpg_code = nn; - optsp->subpg_code_set = 1; + op->subpg_code = nn; + op->subpg_code_set = 1; } else nn = 0; - optsp->pg_code = n; + op->pg_code = n; break; case 'r': - ++optsp->do_raw; + ++op->do_raw; break; case 'R': - optsp->do_raw += 2; + op->do_raw += 2; break; case 's': - ++optsp->do_six; + ++op->do_six; break; case 'v': - ++optsp->do_verbose; + ++op->do_verbose; break; case 'V': - ++optsp->do_version; + ++op->do_version; break; default: fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c); - if (optsp->do_help) + if (op->do_help) break; usage(); return SG_LIB_SYNTAX_ERROR; } } if (optind < argc) { - if (NULL == optsp->device_name) { - optsp->device_name = argv[optind]; + if (NULL == op->device_name) { + op->device_name = argv[optind]; ++optind; } if (optind < argc) { @@ -322,7 +321,7 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[]) /* Processes command line options according to old option format. Returns * 0 is ok, else SG_LIB_SYNTAX_ERROR is returned. */ static int -process_cl_old(struct opts_t * optsp, int argc, char * argv[]) +process_cl_old(struct opts_t * op, int argc, char * argv[]) { int k, jmp_out, plen, num, n; unsigned int u, uu; @@ -337,52 +336,52 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) for (--plen, ++cp, jmp_out = 0; plen > 0; --plen, ++cp) { switch (*cp) { case '6': - ++optsp->do_six; + ++op->do_six; break; case 'a': - ++optsp->do_all; + ++op->do_all; break; case 'A': - optsp->do_all += 2; + op->do_all += 2; break; case 'd': - ++optsp->do_dbd; + ++op->do_dbd; break; case 'D': - ++optsp->do_dbout; + ++op->do_dbout; break; case 'e': - ++optsp->do_examine; + ++op->do_examine; break; case 'f': - ++optsp->do_flexible; + ++op->do_flexible; break; case 'h': case 'H': - optsp->do_hex += 2; + op->do_hex += 2; break; case 'l': - ++optsp->do_list; + ++op->do_list; break; case 'L': - ++optsp->do_llbaa; + ++op->do_llbaa; break; case 'N': - optsp->opt_new = 1; + op->opt_new = 1; return 0; case 'O': break; case 'r': - optsp->do_raw += 2; + op->do_raw += 2; break; case 'v': - ++optsp->do_verbose; + ++op->do_verbose; break; case 'V': - ++optsp->do_version; + ++op->do_version; break; case '?': - ++optsp->do_help; + ++op->do_help; break; default: jmp_out = 1; @@ -400,7 +399,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - optsp->page_control = u; + op->page_control = u; } else if (0 == strncmp("m=", cp, 2)) { num = sscanf(cp + 2, "%d", &n); if ((1 != num) || (n < 0) || (n > 65535)) { @@ -408,7 +407,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - optsp->maxlen = n; + op->maxlen = n; } else if (0 == strncmp("p=", cp, 2)) { if (NULL == strchr(cp + 2, ',')) { num = sscanf(cp + 2, "%x", &u); @@ -418,7 +417,7 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - optsp->pg_code = u; + op->pg_code = u; } else if (2 == sscanf(cp + 2, "%x,%x", &u, &uu)) { if (uu > 255) { fprintf(stderr, "Bad sub page code value after 'p=' " @@ -426,9 +425,9 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - optsp->pg_code = u; - optsp->subpg_code = uu; - optsp->subpg_code_set = 1; + op->pg_code = u; + op->subpg_code = uu; + op->subpg_code_set = 1; } else { fprintf(stderr, "Bad page code, subpage code sequence " "after 'p=' option\n"); @@ -443,10 +442,10 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - optsp->subpg_code = u; - optsp->subpg_code_set = 1; - if (-1 == optsp->pg_code) - optsp->pg_code = 0; + op->subpg_code = u; + op->subpg_code_set = 1; + if (-1 == op->pg_code) + op->pg_code = 0; } else if (0 == strncmp("-old", cp, 4)) ; else if (jmp_out) { @@ -454,11 +453,11 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage_old(); return SG_LIB_SYNTAX_ERROR; } - } else if (0 == optsp->device_name) - optsp->device_name = cp; + } else if (0 == op->device_name) + op->device_name = cp; else { fprintf(stderr, "too many arguments, got: %s, not expecting: " - "%s\n", optsp->device_name, cp); + "%s\n", op->device_name, cp); usage_old(); return SG_LIB_SYNTAX_ERROR; } @@ -473,22 +472,22 @@ process_cl_old(struct opts_t * optsp, int argc, char * argv[]) * of these options is detected (when processing the other format), processing * stops and is restarted using the other format. Clear? */ static int -process_cl(struct opts_t * optsp, int argc, char * argv[]) +process_cl(struct opts_t * op, int argc, char * argv[]) { int res; char * cp; cp = getenv("SG3_UTILS_OLD_OPTS"); if (cp) { - optsp->opt_new = 0; - res = process_cl_old(optsp, argc, argv); - if ((0 == res) && optsp->opt_new) - res = process_cl_new(optsp, argc, argv); + op->opt_new = 0; + res = process_cl_old(op, argc, argv); + if ((0 == res) && op->opt_new) + res = process_cl_new(op, argc, argv); } else { - optsp->opt_new = 1; - res = process_cl_new(optsp, argc, argv); - if ((0 == res) && (0 == optsp->opt_new)) - res = process_cl_old(optsp, argc, argv); + op->opt_new = 1; + res = process_cl_new(op, argc, argv); + if ((0 == res) && (0 == op->opt_new)) + res = process_cl_old(op, argc, argv); } return res; } @@ -857,17 +856,17 @@ list_page_codes(int scsi_ptype, int inq_byte6, int t_proto) static int examine_pages(int sg_fd, int inq_pdt, int inq_byte6, - const struct opts_t * optsp) + const struct opts_t * op) { int k, res, header, mresp_len, len; unsigned char rbuf[256]; const char * cp; - mresp_len = (optsp->do_raw || optsp->do_hex) ? sizeof(rbuf) : 4; + mresp_len = (op->do_raw || op->do_hex) ? sizeof(rbuf) : 4; for (header = 0, k = 0; k < PG_CODE_MAX; ++k) { - if (optsp->do_six) { + if (op->do_six) { res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len, - 1, optsp->do_verbose); + 1, op->do_verbose); if (SG_LIB_CAT_INVALID_OP == res) { fprintf(stderr, ">>>>>> try again without the '-6' " "switch for a 10 byte MODE SENSE command\n"); @@ -878,7 +877,7 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, } } else { res = sg_ll_mode_sense10(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len, - 1, optsp->do_verbose); + 1, op->do_verbose); if (SG_LIB_CAT_INVALID_OP == res) { fprintf(stderr, ">>>>>> try again with a '-6' " "switch for a 6 byte MODE SENSE command\n"); @@ -889,11 +888,11 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, } } if (0 == res) { - len = optsp->do_six ? (rbuf[0] + 1) : + len = op->do_six ? (rbuf[0] + 1) : ((rbuf[0] << 8) + rbuf[1] + 2); if (len > mresp_len) len = mresp_len; - if (optsp->do_raw) { + if (op->do_raw) { dStrRaw((const char *)rbuf, len); continue; } @@ -906,7 +905,7 @@ examine_pages(int sg_fd, int inq_pdt, int inq_byte6, printf(" %s\n", cp); else printf(" [0x%x]\n", k); - if (optsp->do_hex) + if (op->do_hex) dStrHex((const char *)rbuf, len, 1); } } @@ -939,166 +938,167 @@ main(int argc, char * argv[]) struct sg_simple_inquiry_resp inq_out; char pdt_name[64]; struct opts_t opts; + struct opts_t * op; - memset(&opts, 0, sizeof(opts)); - opts.pg_code = -1; - res = process_cl(&opts, argc, argv); + op = &opts; + memset(op, 0, sizeof(opts)); + op->pg_code = -1; + res = process_cl(op, argc, argv); if (res) return SG_LIB_SYNTAX_ERROR; - if (opts.do_help) { - usage_for(&opts); + if (op->do_help) { + usage_for(op); return 0; } - if (opts.do_version) { + if (op->do_version) { fprintf(stderr, "Version string: %s\n", version_str); return 0; } - if (NULL == opts.device_name) { - if (opts.do_list) { - if ((opts.pg_code < 0) || (opts.pg_code > PG_CODE_MAX)) { + if (NULL == op->device_name) { + if (op->do_list) { + if ((op->pg_code < 0) || (op->pg_code > PG_CODE_MAX)) { printf(" Assume peripheral device type: disk\n"); list_page_codes(0, 0, -1); } else { printf(" peripheral device type: %s\n", - sg_get_pdt_str(opts.pg_code, sizeof(pdt_name), + sg_get_pdt_str(op->pg_code, sizeof(pdt_name), pdt_name)); - if (opts.subpg_code_set) - list_page_codes(opts.pg_code, 0, opts.subpg_code); + if (op->subpg_code_set) + list_page_codes(op->pg_code, 0, op->subpg_code); else - list_page_codes(opts.pg_code, 0, -1); + list_page_codes(op->pg_code, 0, -1); } return 0; } fprintf(stderr, "No DEVICE argument given\n"); - usage_for(&opts); + usage_for(op); return SG_LIB_SYNTAX_ERROR; } - if (opts.do_examine && (opts.pg_code >= 0)) { + if (op->do_examine && (op->pg_code >= 0)) { fprintf(stderr, "can't give '-e' and a page number\n"); return SG_LIB_SYNTAX_ERROR; } - if ((opts.do_six) && (opts.do_llbaa)) { + if ((op->do_six) && (op->do_llbaa)) { fprintf(stderr, "LLBAA not defined for MODE SENSE 6, try " "without '-L'\n"); return SG_LIB_SYNTAX_ERROR; } - if (opts.maxlen > 0) { - if (opts.do_six && (opts.maxlen > 255)) { + if (op->maxlen > 0) { + if (op->do_six && (op->maxlen > 255)) { fprintf(stderr, "For Mode Sense (6) maxlen cannot exceed " "255\n"); return SG_LIB_SYNTAX_ERROR; } - if (opts.maxlen > DEF_ALLOC_LEN) { - malloc_rsp_buff = (unsigned char *)malloc(opts.maxlen); + if (op->maxlen > DEF_ALLOC_LEN) { + malloc_rsp_buff = (unsigned char *)malloc(op->maxlen); if (NULL == malloc_rsp_buff) { fprintf(stderr, "Unable to malloc maxlen=%d bytes\n", - opts.maxlen); + op->maxlen); return SG_LIB_SYNTAX_ERROR; } rsp_buff = malloc_rsp_buff; } else rsp_buff = def_rsp_buff; - rsp_buff_size = opts.maxlen; + rsp_buff_size = op->maxlen; } else { /* maxlen == 0 */ - rsp_buff_size = opts.do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN; + rsp_buff_size = op->do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN; rsp_buff = def_rsp_buff; } /* If no pages or list selected than treat as 'a' */ - if (! ((opts.pg_code >= 0) || opts.do_all || opts.do_list || - opts.do_examine)) - opts.do_all = 1; + if (! ((op->pg_code >= 0) || op->do_all || op->do_list || op->do_examine)) + op->do_all = 1; - if (opts.do_raw) { + if (op->do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } - if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* ro */, - opts.do_verbose)) < 0) { + if ((sg_fd = sg_cmds_open_device(op->device_name, 1 /* ro */, + op->do_verbose)) < 0) { fprintf(stderr, "error opening file: %s: %s\n", - opts.device_name, safe_strerror(-sg_fd)); + op->device_name, safe_strerror(-sg_fd)); if (malloc_rsp_buff) free(malloc_rsp_buff); return SG_LIB_FILE_ERROR; } - if (sg_simple_inquiry(sg_fd, &inq_out, 1, opts.do_verbose)) { + if (sg_simple_inquiry(sg_fd, &inq_out, 1, op->do_verbose)) { fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n", - opts.device_name); + op->device_name); ret = SG_LIB_CAT_OTHER; goto finish; } inq_pdt = inq_out.peripheral_type; inq_byte6 = inq_out.byte_6; - if (0 == opts.do_raw) + if (0 == op->do_raw) printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n", inq_out.vendor, inq_out.product, inq_out.revision, sg_get_pdt_str(inq_pdt, sizeof(pdt_name), pdt_name), inq_pdt); - if (opts.do_list) { - if (opts.subpg_code_set) - list_page_codes(inq_pdt, inq_byte6, opts.subpg_code); + if (op->do_list) { + if (op->subpg_code_set) + list_page_codes(inq_pdt, inq_byte6, op->subpg_code); else list_page_codes(inq_pdt, inq_byte6, -1); goto finish; } - if (opts.do_examine) { - ret = examine_pages(sg_fd, inq_pdt, inq_byte6, &opts); + if (op->do_examine) { + ret = examine_pages(sg_fd, inq_pdt, inq_byte6, op); goto finish; } - if (PG_CODE_ALL == opts.pg_code) { - if (0 == opts.do_all) - ++opts.do_all; - } else if (opts.do_all) - opts.pg_code = PG_CODE_ALL; - if (opts.do_all > 1) - opts.subpg_code = SPG_CODE_ALL; + if (PG_CODE_ALL == op->pg_code) { + if (0 == op->do_all) + ++op->do_all; + } else if (op->do_all) + op->pg_code = PG_CODE_ALL; + if (op->do_all > 1) + op->subpg_code = SPG_CODE_ALL; - if (opts.do_raw > 1) { - if (opts.do_all) { - if (opts.opt_new) + if (op->do_raw > 1) { + if (op->do_all) { + if (op->opt_new) fprintf(stderr, "'-R' requires a specific (sub)page, not " "all\n"); else fprintf(stderr, "'-r' requires a specific (sub)page, not " "all\n"); - usage_for(&opts); + usage_for(op); ret = SG_LIB_SYNTAX_ERROR; goto finish; } } memset(rsp_buff, 0, rsp_buff_size); - if (opts.do_six) { - res = sg_ll_mode_sense6(sg_fd, opts.do_dbd, opts.page_control, - opts.pg_code, opts.subpg_code, rsp_buff, - rsp_buff_size, 1, opts.do_verbose); + if (op->do_six) { + res = sg_ll_mode_sense6(sg_fd, op->do_dbd, op->page_control, + op->pg_code, op->subpg_code, rsp_buff, + rsp_buff_size, 1, op->do_verbose); if (SG_LIB_CAT_INVALID_OP == res) fprintf(stderr, ">>>>>> try again without the '-6' " "switch for a 10 byte MODE SENSE command\n"); } else { - res = sg_ll_mode_sense10(sg_fd, opts.do_llbaa, opts.do_dbd, - opts.page_control, opts.pg_code, - opts.subpg_code, rsp_buff, rsp_buff_size, - 1, opts.do_verbose); + res = sg_ll_mode_sense10(sg_fd, op->do_llbaa, op->do_dbd, + op->page_control, op->pg_code, + op->subpg_code, rsp_buff, rsp_buff_size, + 1, op->do_verbose); if (SG_LIB_CAT_INVALID_OP == res) fprintf(stderr, ">>>>>> try again with a '-6' " "switch for a 6 byte MODE SENSE command\n"); } if (SG_LIB_CAT_ILLEGAL_REQ == res) { - if (opts.subpg_code > 0) + if (op->subpg_code > 0) fprintf(stderr, "invalid field in cdb (perhaps subpages " "not supported)\n"); - else if (opts.page_control > 0) + else if (op->page_control > 0) fprintf(stderr, "invalid field in cdb (perhaps " "page control (PC) not supported)\n"); else fprintf(stderr, "invalid field in cdb (perhaps " - "page 0x%x not supported)\n", opts.pg_code); + "page 0x%x not supported)\n", op->pg_code); } else if (SG_LIB_CAT_NOT_READY == res) fprintf(stderr, "device not ready\n"); else if (SG_LIB_CAT_UNIT_ATTENTION == res) @@ -1110,12 +1110,12 @@ main(int argc, char * argv[]) int medium_type, specific, headerlen; ret = 0; - resp_mode6 = opts.do_six; - if (opts.do_flexible) { + resp_mode6 = op->do_six; + if (op->do_flexible) { num = rsp_buff[0]; - if (opts.do_six && (num < 3)) + if (op->do_six && (num < 3)) resp_mode6 = 0; - if ((0 == opts.do_six) && (num > 5)) { + if ((0 == op->do_six) && (num > 5)) { if ((num > 11) && (0 == (num % 2)) && (0 == rsp_buff[4]) && (0 == rsp_buff[5]) && (0 == rsp_buff[6])) { rsp_buff[1] = num; @@ -1126,14 +1126,14 @@ main(int argc, char * argv[]) resp_mode6 = 1; } } - if ((! opts.do_raw) && (1 != opts.do_hex)) { - if (resp_mode6 == opts.do_six) + if ((! op->do_raw) && (1 != op->do_hex)) { + if (resp_mode6 == op->do_six) printf("Mode parameter header from MODE SENSE(%s):\n", - (opts.do_six ? "6" : "10")); + (op->do_six ? "6" : "10")); else printf(" >>> Mode parameter header from MODE SENSE(%s),\n" " decoded as %s byte response:\n", - (opts.do_six ? "6" : "10"), (resp_mode6 ? "6" : "10")); + (op->do_six ? "6" : "10"), (resp_mode6 ? "6" : "10")); } if (resp_mode6) { headerlen = 4; @@ -1155,8 +1155,8 @@ main(int argc, char * argv[]) bd_len); bd_len = 0; } - if (opts.do_raw) { - if (1 == opts.do_raw) + if (op->do_raw) { + if (1 == op->do_raw) dStrRaw((const char *)rsp_buff, md_len); else { ucp = rsp_buff + bd_len + headerlen; @@ -1169,10 +1169,10 @@ main(int argc, char * argv[]) } goto finish; } - if (1 == opts.do_hex) { + if (1 == op->do_hex) { dStrHex((const char *)rsp_buff, md_len, 1); goto finish; - } else if (opts.do_hex > 1) + } else if (op->do_hex > 1) dStrHex((const char *)rsp_buff, headerlen, 1); if (0 == inq_pdt) printf(" Mode data length=%d, medium type=0x%.2x, WP=%d," @@ -1189,7 +1189,7 @@ main(int argc, char * argv[]) if (bd_len + headerlen > rsp_buff_size) bd_len = rsp_buff_size - headerlen; } - if (! opts.do_dbout) { + if (! op->do_dbout) { printf(" Block descriptor length=%d\n", bd_len); if (bd_len > 0) { len = 8; @@ -1223,8 +1223,8 @@ main(int argc, char * argv[]) md_len -= bd_len + headerlen; /* length of mode page(s) */ num_ua_pages = 0; for (k = 0; md_len > 0; ++k) { /* got mode page(s) */ - if ((k > 0) && (! opts.do_all) && - (SPG_CODE_ALL != opts.subpg_code)) { + if ((k > 0) && (! op->do_all) && + (SPG_CODE_ALL != op->subpg_code)) { fprintf(stderr, "Unexpectedly received extra mode page " "responses, ignore\n"); break; @@ -1243,13 +1243,13 @@ main(int argc, char * argv[]) break; } } - if (opts.do_hex) { + if (op->do_hex) { if (spf) printf(">> page_code=0x%x, subpage_code=0x%x, page_cont" - "rol=%d\n", page_num, ucp[1], opts.page_control); + "rol=%d\n", page_num, ucp[1], op->page_control); else printf(">> page_code=0x%x, page_control=%d\n", page_num, - opts.page_control); + op->page_control); } else { descp = NULL; if ((0x18 == page_num) || (0x19 == page_num)) { @@ -1268,10 +1268,10 @@ main(int argc, char * argv[]) } if (descp) printf(">> %s, page_control: %s\n", descp, - pg_control_str_arr[opts.page_control]); + pg_control_str_arr[op->page_control]); else printf(">> page_code: %s, page_control: %s\n", ebuff, - pg_control_str_arr[opts.page_control]); + pg_control_str_arr[op->page_control]); } num = (len > md_len) ? md_len : len; if ((k > 0) && (num > 256)) { diff --git a/src/sg_read_buffer.c b/src/sg_read_buffer.c index 1924c7de..5d0f75b7 100644 --- a/src/sg_read_buffer.c +++ b/src/sg_read_buffer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2013 Luben Tuikov and Douglas Gilbert. + * Copyright (c) 2006-2014 Luben Tuikov and Douglas Gilbert. * All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the BSD_LICENSE file. @@ -25,7 +25,7 @@ * This utility issues the SCSI READ BUFFER command to the given device. */ -static const char * version_str = "1.09 20130507"; +static const char * version_str = "1.10 20140507"; static struct option long_options[] = { @@ -36,6 +36,7 @@ static struct option long_options[] = { {"mode", 1, 0, 'm'}, {"offset", 1, 0, 'o'}, {"raw", 0, 0, 'r'}, + {"readonly", 0, 0, 'R'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {0, 0, 0, 0}, @@ -48,8 +49,9 @@ usage() fprintf(stderr, "Usage: " "sg_read_buffer [--help] [--hex] [--id=ID] [--length=LEN] " "[--mode=MO]\n" - " [--offset=OFF] [--raw] [--verbose] " - "[--version] DEVICE\n" + " [--offset=OFF] [--raw] [--readonly] " + "[--verbose]\n" + " [--version] DEVICE\n" " where:\n" " --help|-h print out usage message\n" " --hex|-H print output in hex\n" @@ -57,13 +59,13 @@ usage() " --length=LEN|-l LEN length in bytes to read (def: 4)\n" " --mode=MO|-m MO read buffer mode, MO is number or " "acronym (def: 0)\n" - " --off=OFF|-o OFF buffer offset (unit: bytes, def: 0)\n" + " --offset=OFF|-o OFF buffer offset (unit: bytes, def: 0)\n" " --raw|-r output response to stdout\n" + " --readonly|-R open DEVICE read-only (def: read-write)\n" " --verbose|-v increase verbosity\n" " --version|-V print version string and exit\n\n" - " Numbers given in options are decimal unless they have a " - "hex indicator\n" - "Performs a SCSI READ BUFFER command\n" + "Performs a SCSI READ BUFFER command. Numbers given in options are " + "decimal\nunless they have a hex indicator (e.g. a leading '0x').\n" ); } @@ -124,6 +126,7 @@ main(int argc, char * argv[]) int sg_fd, res, c, len, k; int do_help = 0; int do_hex = 0; + int o_readonly = 0; int rb_id = 0; int rb_len = 4; int rb_mode = 0; @@ -137,7 +140,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "hHi:l:m:o:rvV", long_options, + c = getopt_long(argc, argv, "hHi:l:m:o:rRvV", long_options, &option_index); if (c == -1) break; @@ -197,6 +200,9 @@ main(int argc, char * argv[]) case 'r': ++do_raw; break; + case 'R': + ++o_readonly; + break; case 'v': ++verbose; break; @@ -265,7 +271,7 @@ main(int argc, char * argv[]) #endif #endif - sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose); + sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); @@ -293,7 +299,12 @@ main(int argc, char * argv[]) fprintf(stderr, "bad field in Read buffer cdb\n"); break; default: - fprintf(stderr, "Read buffer failed res=%d\n", res); + if (-1 == res) { + fprintf(stderr, "Read buffer command failed\n"); + } else + fprintf(stderr, "Read buffer failed, res=%d\n", res); + if (0 == verbose) + fprintf(stderr, "... try again with -v or -vv\n"); break; } } else if (rb_len > 0) { diff --git a/src/sg_readcap.c b/src/sg_readcap.c index 57302177..dbb7e786 100644 --- a/src/sg_readcap.c +++ b/src/sg_readcap.c @@ -29,7 +29,7 @@ #include "sg_cmds_basic.h" -static const char * version_str = "3.89 20140115"; +static const char * version_str = "3.90 20140407"; #define ME "sg_readcap: " @@ -47,6 +47,7 @@ static struct option long_options[] = { {"old", 0, 0, 'O'}, {"pmi", 0, 0, 'p'}, {"raw", 0, 0, 'r'}, + {"readonly", 0, 0, 'R'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {0, 0, 0, 0}, @@ -60,6 +61,7 @@ struct opts_t { int do_long; int do_pmi; int do_raw; + int o_readonly; int do_verbose; int do_version; uint64_t llba; @@ -71,8 +73,9 @@ static void usage() { fprintf(stderr, "Usage: sg_readcap [--brief] [--help] [--hex] " "[--lba=LBA] [--long] [--16]\n" - " [--pmi] [--raw] [--verbose] [--version] " - "DEVICE\n" + " [--pmi] [--raw] [--readonly] [--verbose] " + "[--version]\n" + " DEVICE\n" " where:\n" " --brief|-b brief, two hex numbers: number of blocks " "and block size\n" @@ -91,6 +94,8 @@ static void usage() " total disk capacity) [made obsolete in " "sbc3r26]\n" " --raw|-r output response in binary to stdout\n" + " --readonly|-R open DEVICE read-only (def: RCAP(16) " + "read-write)\n" " --verbose|-v increase verbosity\n" " --version|-V print version string and exit\n\n" "Perform a SCSI READ CAPACITY (10 or 16) command\n"); @@ -99,7 +104,7 @@ static void usage() static void usage_old() { fprintf(stderr, "Usage: sg_readcap [-16] [-b] [-h] [-H] [-lba=LBA] " - "[-pmi] [-r] [-v] [-V]\n" + "[-pmi] [-r] [-R] [-v] [-V]\n" " DEVICE\n" " where:\n" " -16 use READ CAPACITY (16) cdb (def: use " @@ -116,20 +121,21 @@ static void usage_old() "shows total\n" " disk capacity)\n" " -r output response in binary to stdout\n" + " -R open DEVICE read-only (def: RCAP(16) read-write)\n" " -v increase verbosity\n" " -V print version string and exit\n\n" "Perform a SCSI READ CAPACITY command\n"); } -static void usage_for(const struct opts_t * optsp) +static void usage_for(const struct opts_t * op) { - if (optsp->opt_new) + if (op->opt_new) usage(); else usage_old(); } -static int process_cl_new(struct opts_t * optsp, int argc, char * argv[]) +static int process_cl_new(struct opts_t * op, int argc, char * argv[]) { int c; int a_one = 0; @@ -138,7 +144,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "16bhHlL:NOprvV", long_options, + c = getopt_long(argc, argv, "16bhHlL:NOprRvV", long_options, &option_index); if (c == -1) break; @@ -149,20 +155,20 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[]) break; case '6': if (a_one) - ++optsp->do_long; + ++op->do_long; break; case 'b': - ++optsp->do_brief; + ++op->do_brief; break; case 'h': case '?': - ++optsp->do_help; + ++op->do_help; break; case 'H': - ++optsp->do_hex; + ++op->do_hex; break; case 'l': - ++optsp->do_long; + ++op->do_long; break; case 'L': nn = sg_get_llnum(optarg); @@ -171,40 +177,43 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[]) usage(); return SG_LIB_SYNTAX_ERROR; } - optsp->llba = nn; + op->llba = nn; /* force READ_CAPACITY16 for large lbas */ - if (optsp->llba > 0xfffffffeULL) - ++optsp->do_long; - ++optsp->do_lba; + if (op->llba > 0xfffffffeULL) + ++op->do_long; + ++op->do_lba; break; case 'N': break; /* ignore */ case 'O': - optsp->opt_new = 0; + op->opt_new = 0; return 0; case 'p': - ++optsp->do_pmi; + ++op->do_pmi; break; case 'r': - ++optsp->do_raw; + ++op->do_raw; + break; + case 'R': + ++op->o_readonly; break; case 'v': - ++optsp->do_verbose; + ++op->do_verbose; break; case 'V': - ++optsp->do_version; + ++op->do_version; break; default: fprintf(stderr, "unrecognised option code %c [0x%x]\n", c, c); - if (optsp->do_help) + if (op->do_help) break; usage(); return SG_LIB_SYNTAX_ERROR; } } if (optind < argc) { - if (NULL == optsp->device_name) { - optsp->device_name = argv[optind]; + if (NULL == op->device_name) { + op->device_name = argv[optind]; ++optind; } if (optind < argc) { @@ -218,7 +227,7 @@ static int process_cl_new(struct opts_t * optsp, int argc, char * argv[]) return 0; } -static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) +static int process_cl_old(struct opts_t * op, int argc, char * argv[]) { int k, jmp_out, plen, num; const char * cp; @@ -234,43 +243,46 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) switch (*cp) { case '1': if ('6' == *(cp + 1)) { - ++optsp->do_long; + ++op->do_long; ++cp; --plen; } else jmp_out = 1; break; case 'b': - ++optsp->do_brief; + ++op->do_brief; break; case 'h': case '?': - ++optsp->do_help; + ++op->do_help; break; case 'H': - ++optsp->do_hex; + ++op->do_hex; break; case 'N': - optsp->opt_new = 1; + op->opt_new = 1; return 0; case 'O': break; case 'p': if (0 == strncmp("pmi", cp, 3)) { - ++optsp->do_pmi; + ++op->do_pmi; cp += 2; plen -= 2; } else jmp_out = 1; break; case 'r': - ++optsp->do_raw; + ++op->do_raw; + break; + case 'R': + ++op->o_readonly; break; case 'v': - ++optsp->do_verbose; + ++op->do_verbose; break; case 'V': - ++optsp->do_version; + ++op->do_version; break; default: jmp_out = 1; @@ -290,9 +302,9 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) } /* force READ_CAPACITY16 for large lbas */ if (uu > 0xfffffffeULL) - ++optsp->do_long; - optsp->llba = uu; - ++optsp->do_lba; + ++op->do_long; + op->llba = uu; + ++op->do_lba; } else if (0 == strncmp("-old", cp, 4)) ; else if (jmp_out) { @@ -300,11 +312,11 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) usage(); return SG_LIB_SYNTAX_ERROR; } - } else if (0 == optsp->device_name) - optsp->device_name = cp; + } else if (0 == op->device_name) + op->device_name = cp; else { fprintf(stderr, "too many arguments, got: %s, not expecting: " - "%s\n", optsp->device_name, cp); + "%s\n", op->device_name, cp); usage(); return SG_LIB_SYNTAX_ERROR; } @@ -312,22 +324,22 @@ static int process_cl_old(struct opts_t * optsp, int argc, char * argv[]) return 0; } -static int process_cl(struct opts_t * optsp, int argc, char * argv[]) +static int process_cl(struct opts_t * op, int argc, char * argv[]) { int res; char * cp; cp = getenv("SG3_UTILS_OLD_OPTS"); if (cp) { - optsp->opt_new = 0; - res = process_cl_old(optsp, argc, argv); - if ((0 == res) && optsp->opt_new) - res = process_cl_new(optsp, argc, argv); + op->opt_new = 0; + res = process_cl_old(op, argc, argv); + if ((0 == res) && op->opt_new) + res = process_cl_new(op, argc, argv); } else { - optsp->opt_new = 1; - res = process_cl_new(optsp, argc, argv); - if ((0 == res) && (0 == optsp->opt_new)) - res = process_cl_old(optsp, argc, argv); + op->opt_new = 1; + res = process_cl_new(op, argc, argv); + if ((0 == res) && (0 == op->opt_new)) + res = process_cl_old(op, argc, argv); } return res; } @@ -342,32 +354,34 @@ static void dStrRaw(const char* str, int len) int main(int argc, char * argv[]) { - int sg_fd, k, res, prot_en, p_type, lbppbe; + int sg_fd, k, res, prot_en, p_type, lbppbe, rw_0_flag; uint64_t llast_blk_addr; int ret = 0; unsigned int last_blk_addr, block_size; unsigned char resp_buff[RCAP16_REPLY_LEN]; struct opts_t opts; + struct opts_t * op; - memset(&opts, 0, sizeof(opts)); - res = process_cl(&opts, argc, argv); + op = &opts; + memset(op, 0, sizeof(opts)); + res = process_cl(op, argc, argv); if (res) return SG_LIB_SYNTAX_ERROR; - if (opts.do_help) { - usage_for(&opts); + if (op->do_help) { + usage_for(op); return 0; } - if (opts.do_version) { + if (op->do_version) { fprintf(stderr, "Version string: %s\n", version_str); return 0; } - if (NULL == opts.device_name) { + if (NULL == op->device_name) { fprintf(stderr, "No DEVICE argument given\n"); - usage_for(&opts); + usage_for(op); return SG_LIB_SYNTAX_ERROR; } - if (opts.do_raw) { + if (op->do_raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; @@ -376,25 +390,29 @@ int main(int argc, char * argv[]) memset(resp_buff, 0, sizeof(resp_buff)); - if ((0 == opts.do_pmi) && (opts.llba > 0)) { + if ((0 == op->do_pmi) && (op->llba > 0)) { fprintf(stderr, ME "lba can only be non-zero when '--pmi' is set\n"); - usage_for(&opts); + usage_for(op); return SG_LIB_SYNTAX_ERROR; } - if ((sg_fd = sg_cmds_open_device(opts.device_name, - (opts.do_long ? 0 /* rw */ : 1), opts.do_verbose)) < 0) { - fprintf(stderr, ME "error opening file: %s: %s\n", opts.device_name, + if (op->do_long) + rw_0_flag = op->o_readonly; + else + rw_0_flag = 1; /* RCAP(10) has opened RO in past, so leave */ + if ((sg_fd = sg_cmds_open_device(op->device_name, rw_0_flag, + op->do_verbose)) < 0) { + fprintf(stderr, ME "error opening file: %s: %s\n", op->device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } - if (! opts.do_long) { - res = sg_ll_readcap_10(sg_fd, opts.do_pmi, (unsigned int)opts.llba, - resp_buff, RCAP_REPLY_LEN, 1, opts.do_verbose); + if (! op->do_long) { + res = sg_ll_readcap_10(sg_fd, op->do_pmi, (unsigned int)op->llba, + resp_buff, RCAP_REPLY_LEN, 1, op->do_verbose); ret = res; if (0 == res) { - if (opts.do_hex || opts.do_raw) { - if (opts.do_raw) + if (op->do_hex || op->do_raw) { + if (op->do_raw) dStrRaw((const char *)resp_buff, RCAP_REPLY_LEN); else dStrHex((const char *)resp_buff, RCAP_REPLY_LEN, 1); @@ -405,20 +423,20 @@ int main(int argc, char * argv[]) if (0xffffffff != last_blk_addr) { block_size = ((resp_buff[4] << 24) | (resp_buff[5] << 16) | (resp_buff[6] << 8) | resp_buff[7]); - if (opts.do_brief) { + if (op->do_brief) { printf("0x%x 0x%x\n", last_blk_addr + 1, block_size); goto good; } printf("Read Capacity results:\n"); - if (opts.do_pmi) + if (op->do_pmi) printf(" PMI mode: given lba=0x%" PRIx64 ", last lba " - "before delay=0x%x\n", opts.llba, last_blk_addr); + "before delay=0x%x\n", op->llba, last_blk_addr); else printf(" Last logical block address=%u (0x%x), Number " "of blocks=%u\n", last_blk_addr, last_blk_addr, last_blk_addr + 1); printf(" Logical block length=%u bytes\n", block_size); - if (! opts.do_pmi) { + if (! op->do_pmi) { uint64_t total_sz = last_blk_addr + 1; double sz_mb, sz_gb; @@ -440,19 +458,19 @@ int main(int argc, char * argv[]) } else { printf("READ CAPACITY (10) indicates device capacity too " "large\n now trying 16 byte cdb variant\n"); - opts.do_long = 1; + op->do_long = 1; } } else if (SG_LIB_CAT_INVALID_OP == res) { - opts.do_long = 1; + op->do_long = 1; sg_cmds_close_device(sg_fd); - if ((sg_fd = sg_cmds_open_device(opts.device_name, 0 /*rw */, - opts.do_verbose)) + if ((sg_fd = sg_cmds_open_device(op->device_name, 0 /*rw */, + op->do_verbose)) < 0) { fprintf(stderr, ME "error re-opening file: %s (rw): %s\n", - opts.device_name, safe_strerror(-sg_fd)); + op->device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } - if (opts.do_verbose) + if (op->do_verbose) fprintf(stderr, "READ CAPACITY (10) not supported, trying " "READ CAPACITY (16)\n"); } else if (SG_LIB_CAT_ILLEGAL_REQ == res) @@ -461,17 +479,17 @@ int main(int argc, char * argv[]) fprintf(stderr, "READ CAPACITY (10) failed, device not ready\n"); else if (SG_LIB_CAT_ABORTED_COMMAND == res) fprintf(stderr, "READ CAPACITY (10) failed, aborted command\n"); - else if (! opts.do_verbose) + else if (! op->do_verbose) fprintf(stderr, "READ CAPACITY (10) failed [res=%d], try " "with '-v'\n", res); } - if (opts.do_long) { - res = sg_ll_readcap_16(sg_fd, opts.do_pmi, opts.llba, resp_buff, - RCAP16_REPLY_LEN, 1, opts.do_verbose); + if (op->do_long) { + res = sg_ll_readcap_16(sg_fd, op->do_pmi, op->llba, resp_buff, + RCAP16_REPLY_LEN, 1, op->do_verbose); ret = res; if (0 == res) { - if (opts.do_hex || opts.do_raw) { - if (opts.do_raw) + if (op->do_hex || op->do_raw) { + if (op->do_raw) dStrRaw((const char *)resp_buff, RCAP16_REPLY_LEN); else dStrHex((const char *)resp_buff, RCAP16_REPLY_LEN, 1); @@ -483,7 +501,7 @@ int main(int argc, char * argv[]) } block_size = ((resp_buff[8] << 24) | (resp_buff[9] << 16) | (resp_buff[10] << 8) | resp_buff[11]); - if (opts.do_brief) { + if (op->do_brief) { printf("0x%" PRIx64 " 0x%x\n", llast_blk_addr + 1, block_size); goto good; } @@ -498,9 +516,9 @@ int main(int argc, char * argv[]) printf("\n"); printf(" Logical block provisioning: lbpme=%d, lbprz=%d\n", !!(resp_buff[14] & 0x80), !!(resp_buff[14] & 0x40)); - if (opts.do_pmi) + if (op->do_pmi) printf(" PMI mode: given lba=0x%" PRIx64 ", last lba " - "before delay=0x%" PRIx64 "\n", opts.llba, + "before delay=0x%" PRIx64 "\n", op->llba, llast_blk_addr); else printf(" Last logical block address=%" PRIu64 " (0x%" @@ -517,7 +535,7 @@ int main(int argc, char * argv[]) printf("\n"); printf(" Lowest aligned logical block address=%d\n", ((resp_buff[14] & 0x3f) << 8) + resp_buff[15]); - if (! opts.do_pmi) { + if (! op->do_pmi) { uint64_t total_sz = llast_blk_addr + 1; double sz_mb, sz_gb; @@ -546,11 +564,11 @@ int main(int argc, char * argv[]) else if (SG_LIB_CAT_ILLEGAL_REQ == res) fprintf(stderr, "bad field in READ CAPACITY (16) cdb " "including unsupported service action\n"); - else if (! opts.do_verbose) + else if (! op->do_verbose) fprintf(stderr, "READ CAPACITY (16) failed [res=%d], try " "with '-v'\n", res); } - if (opts.do_brief) + if (op->do_brief) printf("0x0 0x0\n"); good: diff --git a/src/sg_ses.c b/src/sg_ses.c index 57008bc7..acf5194e 100644 --- a/src/sg_ses.c +++ b/src/sg_ses.c @@ -28,7 +28,7 @@ * commands tailored for SES (enclosure) devices. */ -static const char * version_str = "1.88 20140414"; /* ses3r06 */ +static const char * version_str = "1.89 20140507"; /* ses3r06 */ #define MX_ALLOC_LEN ((64 * 1024) - 1) /* max allowable for big enclosures */ #define MX_ELEM_HDR 1024 @@ -119,6 +119,7 @@ struct opts_t { int page_code; int page_code_given; int do_raw; + int o_readonly; int do_status; int verbose; int do_version; @@ -486,6 +487,7 @@ static struct option long_options[] = { {"maxlen", required_argument, 0, 'm'}, {"page", required_argument, 0, 'p'}, {"raw", no_argument, 0, 'r'}, + {"readonly", no_argument, 0, 'R'}, {"sas-addr", required_argument, 0, 'A'}, {"set", required_argument, 0, 'S'}, {"status", no_argument, 0, 's'}, @@ -613,6 +615,8 @@ usage(int help_num) "for '-d';\n" " when used twice outputs page in binary " "to stdout\n" + " --readonly|-R open DEVICE read-only (def: " + "read-write)\n" " --status|-s fetch status information (default " "action)\n" " --verbose|-v increase verbosity\n" @@ -770,8 +774,8 @@ cl_process(struct opts_t *op, int argc, char *argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:p:rsS:vVx:", - long_options, &option_index); + c = getopt_long(argc, argv, "A:b:cC:d:D:eE:fG:hHiI:jln:N:m:p:rRsS:v" + "Vx:", long_options, &option_index); if (c == -1) break; @@ -905,6 +909,9 @@ cl_process(struct opts_t *op, int argc, char *argv[]) case 'r': ++op->do_raw; break; + case 'R': + ++op->o_readonly; + break; case 's': ++op->do_status; break; @@ -3994,7 +4001,7 @@ main(int argc, char * argv[]) } } - sg_fd = sg_cmds_open_device(op->dev_name, 0 /* rw */, op->verbose); + sg_fd = sg_cmds_open_device(op->dev_name, op->o_readonly, op->verbose); if (sg_fd < 0) { pr2serr("open error: %s: %s\n", op->dev_name, safe_strerror(-sg_fd)); diff --git a/src/sg_write_buffer.c b/src/sg_write_buffer.c index d555899e..3f1bf1a9 100644 --- a/src/sg_write_buffer.c +++ b/src/sg_write_buffer.c @@ -26,7 +26,7 @@ * This utility issues the SCSI WRITE BUFFER command to the given device. */ -static const char * version_str = "1.12 20140414"; /* spc4r36s */ +static const char * version_str = "1.13 20140507"; /* spc4r36s */ #define ME "sg_write_buffer: " #define DEF_XFER_LEN (8 * 1024 * 1024) @@ -544,7 +544,12 @@ main(int argc, char * argv[]) pr2serr("bad field in Write buffer cdb\n"); break; default: - pr2serr("Write buffer failed res=%d\n", res); + if (-1 == res) { + fprintf(stderr, "Write buffer command failed\n"); + } else + fprintf(stderr, "Write buffer failed, res=%d\n", res); + if (0 == verbose) + fprintf(stderr, "... try again with -v or -vv\n"); break; } } |