From: Pat LaVarre <p.lavarre@ieee.org>
To: patmans@us.ibm.com
Cc: dougg@torque.net, linux-scsi@vger.kernel.org
Subject: Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
Date: 07 Nov 2003 11:27:19 -0700 [thread overview]
Message-ID: <1068229639.3417.46.camel@patrh9> (raw)
In-Reply-To: <1068228695.3417.34.camel@patrh9>
> > The command line plscsi could support both long and short names (-i or
> > --gcs-in).
>
> Ouch, sorry, yes I left that part of the patch out, I find I have to
> sneaker net it here, please stay tuned.
As follows. --yes, --in, --out, etc., very much like plscsi --help
says. Perhaps the key fragment is the zero or one arg per option usage
and default values description:
"-b --beyond $length // else 0\n"
"-c --compare\n"
"-e --each\n"
"-f --from $fn // else stdin\n"
"-h --help\n"
"-i --in $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-l --late $seconds // else 100800.000 = 28 hours\n"
"-n --no $hex\n"
"-o --out $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-p --please // else audit cdb length, etc.\n"
"-q --quiet\n"
"-r --repeat $count // else 1\n"
"-s --sense $length // else 18.4.0 = x12 aligned at 4 bytes\n"
"-t --to $fn // else stdout\n"
"-v --verbose\n"
"-w --with $hex // else -w \"AE\"\n"
"-y --yes $hex // else -i x24 -y \"12 00:00:00 24 00\"\n"
"\n" ...
"gsc $dev -v -i 0x24 -y \"12 00:00:00 24 00\" // Inquiry\n"
"gsc $dev -v -i 8 -y \"25 00 00:00:00:00 00 00:00 00\" // Read Max LBA\n"
"gsc $dev -v -y \"00 00:00:00 00 00\" // Test Unit Ready\n"
"gsc $dev -v -y \"1B 00:00:00 00 00\" // Stop Unit\n"
"gsc $dev -v -y \"1B 00:00:00 01 00\" // Start Unit\n"
"gsc $dev -v -y \"1B 00:00:00 02 00\" // Stop Then Eject\n"
Again I say I'm not happy with the treatment of misalignment.
Diff'ed against this version, striving to keep the gccscsi.c small, I
find maybe now I'm learning towards a deeply arcane multi-arg option
such as:
--align 0x1000 -1 0x234 0x345 0x456
By that I mean, with respect to what kind of interesting alignment
boundary (x1000), say where to position the sg_io_hdr_t (-1), the cdb
(0x234), the sense (x345), and the data (x456).
> > Do you have a tar ball ...
>
> Yes release early release often.
Tar ball to list is forbidden, no? So I launched this thread with a
normal small patch, but then in this post I have included a version of
the command line parser as plain text inline.
Pat LaVarre
--- gsc.c
/* gsc.c
*
* Interpret a command line in terms of "gccscsi.h".
*/
/* Link with local C libraries. */
#include "gccscsi.h"
#include "version.h"
/* Step thru implicit and command line args. */
static char const * const * args;
/* Remember some command line args. */
static int interpret_dash = 1;
static int interpret_compare = 0;
static int interpret_please = 0;
static int interpret_repeat = 1;
static int interpret_yes = -1;
static char const * interpret_from = NULL;
static char const * interpret_to = NULL;
/* Summarise command line syntax. */
#define USAGE \
"gsc $dev... -e -yiowp -acfnlrst -bhqv $args... // $comment..."
/* Complain of command line syntax. */
static void confused_exit(void)
{
fprintf(stderr, "Usage: %s\nMore details at: gss --help\n", USAGE);
exit(-__LINE__);
}
/* Convert to CDB length from CDB[0]. */
static int to_cdb_length(int op, int guess)
{
switch (op & 0xE0) { /* &xE0 = "group" */
case 0x00: return 6; /* x00 .. x1F */
case 0x20: return 10;/* x20 .. x3F */
case 0x40: return 10; /* x40 .. x5F */
case 0x60: break; /* x60 .. x7F reserved */
case 0x80: break; /* x80 .. x9F reserved */
case 0xA0: return 12; /* xA0 .. xBF */
case 0xC0: break; /* xC0 .. xDF vendor-specific */
case 0xE0: break; /* xE0 .. xFF vendor-specific */
}
return guess;
}
/* Complain of SCSI pass thru known to crash operating systems. */
static void displeased_exit(char const * st)
{
fprintf(stderr, "Say --please to pass thru %s\n", st);
exit(-__LINE__);
}
/* Exit without risking a crash. */
static void audit_gss(struct gss * gss)
{
char const * cdb = gss_get_cdb(gss);
int op = (cdb[0] & 0xFF);
int enough = to_cdb_length(op, -1);
if (gss_get_cdb_enough(gss) != enough) {
displeased_exit("non-standard CDB length");
}
if (cdb[0] == 0x04) {
displeased_exit("op x04 Format");
}
if ((cdb[0] == 0x12) && (gss_get_chars_length(gss) == 0)) {
displeased_exit("op x12 Inquiry for zero");
}
if ((cdb[0] == 0x1A) && (gss_get_chars_length(gss) < 8)) {
displeased_exit("op x1A Mode Sense 6 for less than 8");
}
}
/* Open a file to read from. */
static FILE * open_from(char const * fn)
{
if (*fn == '\0') {
return stdin; /* FIXME: might be opened "rt" */
} else {
FILE * fi = fopen(fn, "rb");
if (fi != NULL) {
return fi;
}
perror("gss:from:fopen");
exit(-__LINE__);
}
}
/* Fill with copies of the beginning. */
static void fill(char * chars, int index, int length)
{
char const * home = chars;
int step = index;
for (;;) {
chars += step; length -= step;
step = ((length < index) ? length : index);
if (step <= 0) break;
memmove(chars, home, step);
index += step;
}
}
/* Read once to fill with copies, else fill with '\0' nul. */
static void read_to_fill(FILE * fi)
{
int length = gss_get_chars_length(gss_first);
if (0 < length) {
char * chars = gss_get_chars(gss_first);
int io = fread(chars, 1, length, fi);
if ((0 <= io) && (io <= length)) {
chars[0] = '\0';
if (io == 0) ++io;
fill(chars, io, length);
} else {
if (ferror(fi)) {
perror("gss:from:fread");
} else {
fprintf(stderr, "gss:from:feof\n");
}
exit(-__LINE__);
}
}
}
/* Copy the data before passing the data out. */
char const * new_copy(struct gss * gss)
{
int length = gss_get_chars_length(gss);
if (0 < length) {
char * chars = gss_get_chars(gss);
char * new_chars = calloc(1, length);
if (new_chars != NULL) {
memcpy(new_chars, chars, length);
return new_chars;
}
perror("gss:compare:calloc");
exit(-__LINE__);
}
return NULL;
}
/* Compare the data passed out to the data passed in. */
static int compare_copy(struct gss * gss, int rc, char const * was)
{
int enough = gss_get_chars_enough(gss);
if (0 < enough) {
char * chars = gss_get_chars(gss);
if (memcmp(was, chars, enough) != 0) {
if (0 < rc) rc = SP_RESIDUE;
rc |= SP_PASS_THRU;
rc |= SP_COMPARE;
}
}
return rc;
}
/* Open a file to write to. */
static FILE * open_to(char const * fn)
{
if (*fn == '\0') {
return stdout; /* FIXME: might be opened "wt" */
} else {
FILE * fi = fopen(fn, "wb");
if (fi != NULL) {
return fi;
}
perror("gss:to:fopen");
exit(-__LINE__);
}
}
/* Write once. */
static void write_to(FILE * fi)
{
int length = gss_get_chars_length(gss_first);
if (0 < length) {
char * chars = gss_get_chars(gss_first);
int io = fwrite(chars, 1, length, fi);
if (io != length) {
perror("gss:to:fwrite");
exit(-__LINE__);
}
}
}
/* Interpret --yes or --no. */
static void run(char const * hex)
{
struct gss * gss = gss_first;
int please = interpret_please;
int compare = interpret_compare;
int repeat = interpret_repeat;
int yes = interpret_yes;
char const * from_fn = interpret_from;
char const * to_fn = interpret_to;
FILE * from_fi = NULL;
FILE * to_fi = NULL;
char const * was = NULL;
int tolerable = 0;
int rc = 0;
/* Audit. */
if (!please) {
audit_gss(gss);
}
if (to_fn != NULL) {
to_fi = open_to(to_fn);
}
/* Start up. */
if (from_fn != NULL) {
from_fi = open_from(from_fn);
}
if (from_fi != NULL) {
read_to_fill(from_fi);
}
if (compare) {
was = new_copy(gss);
}
/* Speak, maybe repeatedly. */
while (0 < repeat--) {
rc = gss_hex_try(gss, hex);
if (compare) {
rc = compare_copy(gss, rc, was);
}
if (tolerable == 0) {
tolerable = ((0 < rc) ? rc : -1);
}
if ((0 < rc) && (rc == tolerable)) {
rc = 0;
}
if (yes != (rc == 0)) {
break;
}
}
/* Shut down. */
if (to_fi != NULL) {
write_to(to_fi);
}
exit(rc);
}
static char const * arg_read(void)
{
if (*args == NULL) {
confused_exit();
}
return *args++;
}
static int to_int(char const * st)
{
st = st;
return 0;
}
static void helpful_exit(void)
{
char const * st = /* one line per option, sorted by name */
"-b --beyond $length // else 0\n"
"-c --compare\n"
"-e --each\n"
"-f --from $fn // else stdin\n"
"-h --help\n"
"-i --in $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-l --late $seconds // else 100800.000 = 28 hours\n"
"-n --no $hex\n"
"-o --out $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-p --please // else audit cdb length, etc.\n"
"-q --quiet\n"
"-r --repeat $count // else 1\n"
"-s --sense $length // else 18.4.0 = x12 aligned at 4 bytes\n"
"-t --to $fn // else stdout\n"
"-v --verbose\n"
"-w --with $hex // else -w \"AE\"\n"
"-y --yes $hex // else -i x24 -y \"12 00:00:00 24 00\"\n"
"\n" /*" 1234567 1234567 1234567 1234567 1234567 1234567 1234567 tab stops */
"gsc $dev -v -i 0x24 -y \"12 00:00:00 24 00\" // Inquiry\n"
"gsc $dev -v -i 8 -y \"25 00 00:00:00:00 00 00:00 00\" // Read Max LBA\n"
"gsc $dev -v -y \"00 00:00:00 00 00\" // Test Unit Ready\n"
"gsc $dev -v -y \"1B 00:00:00 00 00\" // Stop Unit\n"
"gsc $dev -v -y \"1B 00:00:00 01 00\" // Start Unit\n"
"gsc $dev -v -y \"1B 00:00:00 02 00\" // Stop Then Eject\n"
"...\n"
;
printf("Usage: %s\n\n%s\n\n%s\n", USAGE, st, VERSION);
exit(0);
}
static char const * abbreviate(char const * st)
{
if (strcmp(st, "--align")) return "-a";
if (strcmp(st, "--beyond")) return "-b";
if (strcmp(st, "--compare")) return "-c";
if (strcmp(st, "--each")) return "-e";
if (strcmp(st, "--from")) return "-f";
if (strcmp(st, "--help")) return "-h";
if (strcmp(st, "--in")) return "-i";
if (strcmp(st, "--late")) return "-l";
if (strcmp(st, "--no")) return "-n";
if (strcmp(st, "--out")) return "-o";
if (strcmp(st, "--please")) return "-p";
if (strcmp(st, "--quiet")) return "-q";
if (strcmp(st, "--repeat")) return "-r";
if (strcmp(st, "--sense")) return "-s";
if (strcmp(st, "--to")) return "-t";
if (strcmp(st, "--verbose")) return "-v";
if (strcmp(st, "--with")) return "-w";
if (strcmp(st, "--yes")) return "-y";
return st;
}
static void step(char const * st)
{
if (strcmp(st, "--")) {
interpret_dash = 0;
} else if (strcmp(st, "-a")) { /* align $page $offset */
int l = to_int(arg_read());
int o = to_int(arg_read());
gss_align(gss_first, l, o);
} else if (strcmp(st, "-b")) { /* beyond $length */
int b = to_int(arg_read());
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-c")) { /* compare */
interpret_compare = 1;
} else if (strcmp(st, "-e")) { /* each */
gss_each(NULL);
} else if (strcmp(st, "-f")) { /* from $fn */
interpret_from = arg_read();
} else if (strcmp(st, "-h")) { /* help */
helpful_exit();
} else if (strcmp(st, "-i")) { /* in $length */
int i = to_int(arg_read());
gss_in_limit(gss_first, i);
} else if (strcmp(st, "-l")) { /* late $s $ns */
int s = to_int(arg_read());
int ns = to_int(arg_read());
gss_define_late(gss_first, s, ns);
} else if (strcmp(st, "-n")) { /* no $hex */
interpret_yes = 0;
run(arg_read());
} else if (strcmp(st, "-o")) { /* out $length */
int o = to_int(arg_read());
gss_out_limit(gss_first, o);
} else if (strcmp(st, "-p")) { /* please */
interpret_please = 1;
} else if (strcmp(st, "-q")) { /* quiet */
int b = 0;
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-r")) { /* repeat $count */
interpret_repeat = to_int(arg_read());
} else if (strcmp(st, "-s")) { /* sense $length $page $offset */
int s = to_int(arg_read());
int l = to_int(arg_read());
int o = to_int(arg_read());
gss_sense_stress(gss_first, s, l, o);
} else if (strcmp(st, "-t")) { /* to $fn */
interpret_to = arg_read();
} else if (strcmp(st, "-v")) { /* verbose */
int b = 1;
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-w")) { /* with $hex */
gss_hex_with(gss_first, arg_read());
} else if (strcmp(st, "-y")) { /* yes $hex */
interpret_yes = 1;
run(arg_read());
} else {
char const * name = arg_read();
if ((name[0] == '-') && interpret_dash) {
confused_exit();
}
gss_also(gss_first, name);
}
}
static void interpret(char const * const * argv)
{
args = argv;
while (*args != NULL) {
step(abbreviate(arg_read()));
}
}
int main(int argc, char const * const * argv)
{
char const * const preface[] = {
"--align", "4096", "0",
"--beyond", "0",
"--in", "0",
"--late", "100800", "0", /* 100800 = 28 * 60 * 60 */
"--out", "0",
"--quiet",
"--repeat", "1",
"--sense", "12", "16", "0",
"--with", "AE",
NULL
};
char const * const inquiry[] = {
"--in", "x24", "--yes", "12 00:00:00 24 00",
NULL
};
interpret(preface);
interpret(argv);
if (interpret_yes < 0) {
interpret(inquiry);
}
return 0;
}
/* end of file */
next prev parent reply other threads:[~2003-11-07 18:27 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-11-07 0:38 sg utils sg_io -i 0x24 -y "12 00:00:00 24 00" Pat LaVarre
2003-11-07 16:24 ` Pat LaVarre
2003-11-07 16:56 ` Pat LaVarre
2003-11-07 17:09 ` Pat LaVarre
2003-11-07 17:17 ` Pat LaVarre
2003-11-07 17:51 ` Patrick Mansfield
2003-11-07 18:11 ` Pat LaVarre
2003-11-07 18:27 ` Pat LaVarre [this message]
2003-11-07 18:31 ` Pat LaVarre
2003-11-11 23:52 ` Pat LaVarre
2003-11-14 3:09 ` Douglas Gilbert
2003-11-26 16:15 ` Pat LaVarre
-- strict thread matches above, loose matches on Subject: below --
2003-11-27 17:15 Pat LaVarre
2003-12-03 0:17 Pat LaVarre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1068229639.3417.46.camel@patrh9 \
--to=p.lavarre@ieee.org \
--cc=dougg@torque.net \
--cc=linux-scsi@vger.kernel.org \
--cc=patmans@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox