aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2014-05-09 13:51:44 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2014-05-09 13:51:44 +0000
commit7c5eb1f951e4349bef24fe9056fdc6c190217d95 (patch)
tree439d5ed60b9b7bb123c5c9a1fec6a21417476414 /src
parent7a8a2dc95dec418172e43bdf46c89914f7020219 (diff)
downloadsg3_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.c70
-rw-r--r--src/sg_luns.c37
-rw-r--r--src/sg_modes.c316
-rw-r--r--src/sg_read_buffer.c33
-rw-r--r--src/sg_readcap.c200
-rw-r--r--src/sg_ses.c15
-rw-r--r--src/sg_write_buffer.c9
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;
}
}