From 4ca8449c2826be469bc9558f2a037236c6703d64 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 13 Oct 2020 20:27:48 +0000 Subject: sg_dd: add oflag=nocreat and conv=nocreat : OFILE must exist; similar in testing sgh_dd+sg_mrq_dd git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@865 6180dd3e-e324-4e3e-922d-17de1ae2f315 --- testing/sg_mrq_dd.cpp | 82 +++++++++++++++++++++++++++++++++++++++++---------- testing/sgh_dd.cpp | 72 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 131 insertions(+), 23 deletions(-) (limited to 'testing') diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp index 5cd9da49..f304eb51 100644 --- a/testing/sg_mrq_dd.cpp +++ b/testing/sg_mrq_dd.cpp @@ -30,7 +30,7 @@ * */ -static const char * version_str = "1.14 20201008"; +static const char * version_str = "1.15 20201012"; #define _XOPEN_SOURCE 600 #ifndef _GNU_SOURCE @@ -180,6 +180,7 @@ struct flags_t { bool fua; bool masync; /* more async sg v4 driver fd flag */ bool no_dur; + bool nocreat; bool order; bool qhead; bool qtail; @@ -816,11 +817,11 @@ usage(int pg_num) else if (pg_num > 1) goto page2; - pr2serr("Usage: sg_mrq_dd [bs=BS] [count=COUNT] [ibs=BS] [if=IFILE]" - " [iflag=FLAGS]\n" - " [obs=BS] [of=OFILE] [oflag=FLAGS] " - "[seek=SEEK]\n" - " [skip=SKIP] [--help] [--verify] " + pr2serr("Usage: sg_mrq_dd [bs=BS] [conv=CONV] [count=COUNT] [ibs=BS] " + "[if=IFILE]\n" + " [iflag=FLAGS] [obs=BS] [of=OFILE] " + "[oflag=FLAGS]\n" + " [seek=SEEK] [skip=SKIP] [--help] [--verify] " "[--version]\n\n"); pr2serr(" [bpt=BPT] [cdbsz=6|10|12|16] [dio=0|1] " "[elemsz_kb=EKB]\n" @@ -838,6 +839,9 @@ usage(int pg_num) "above) are:\n" " bs must be device logical block size (default " "512)\n" + " conv comma separated list from: [nocreat,noerror," + "notrunc,\n" + " null,sync]\n" " count number of blocks to copy (def: device size)\n" " if file or device to read from (def: stdin)\n" " iflag comma separated list from: [coe,dio," @@ -848,8 +852,8 @@ usage(int pg_num) "N.B. different\n" " from dd it defaults to stdout). If 'of=.' " "uses /dev/null\n" - " oflag comma separated list from: [append,<>]\n" + " oflag comma separated list from: [append,nocreat,\n" + " <>]\n" " seek block position to start writing to OFILE\n" " skip block position to start reading from IFILE\n" " --help|-h output this usage message then exit\n" @@ -928,6 +932,7 @@ page3: " masync set 'more async' flag on this sg device\n" " mmap setup mmap IO on IFILE or OFILE\n" " mmap,mmap when used twice, doesn't call munmap()\n" + " nocreat will fail rather than create OFILE\n" " nodur turns off command duration calculations\n" " order require write ordering on sg->sg copy; only " "for oflag\n" @@ -3032,6 +3037,46 @@ sg_out_open(struct global_collection *clp, const char *outf, uint8_t **mmpp, return fd; } +/* Process arguments given to 'conv=" option. Returns 0 on success, + * 1 on error. */ +static int +process_conv(const char * arg, struct flags_t * ifp, struct flags_t * ofp) +{ + char buff[256]; + char * cp; + char * np; + + strncpy(buff, arg, sizeof(buff)); + buff[sizeof(buff) - 1] = '\0'; + if ('\0' == buff[0]) { + pr2serr("no conversions found\n"); + return 1; + } + cp = buff; + do { + np = strchr(cp, ','); + if (np) + *np++ = '\0'; + if (0 == strcmp(cp, "nocreat")) + ofp->nocreat = true; + else if (0 == strcmp(cp, "noerror")) + ifp->coe = true; /* will still fail on write error */ + else if (0 == strcmp(cp, "notrunc")) + ; /* this is the default action of sg_dd so ignore */ + else if (0 == strcmp(cp, "null")) + ; + else if (0 == strcmp(cp, "sync")) + ; /* dd(susv4): pad errored block(s) with zeros but sg_dd does + * that by default. Typical dd use: 'conv=noerror,sync' */ + else { + pr2serr("unrecognised flag: %s\n", cp); + return 1; + } + cp = np; + } while (cp); + return 0; +} + #define STR_SZ 1024 #define INOUTF_SZ 512 @@ -3087,6 +3132,11 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, /* not documented, for compat with sgh_dd */ clp->in_flags.coe = !! sg_get_num(buf); clp->out_flags.coe = clp->in_flags.coe; + } else if (0 == strcmp(key, "conv")) { + if (process_conv(buf, &clp->in_flags, &clp->out_flags)) { + pr2serr("%s: bad argument to 'conv='\n", my_name); + return SG_LIB_SYNTAX_ERROR; + } } else if (0 == strcmp(key, "count")) { if (clp->count_given) { pr2serr("second 'count=' argument detected, only one " @@ -3664,14 +3714,14 @@ main(int argc, char * argv[]) clp->infd = STDIN_FILENO; clp->outfd = STDOUT_FILENO; if (clp->in_flags.ff) { - ccp = "<0xff bytes>"; - cc2p = "ff"; + ccp = "<0xff bytes>"; + cc2p = "ff"; } else if (clp->in_flags.random) { - ccp = ""; - cc2p = "random"; + ccp = ""; + cc2p = "random"; } else if (clp->in_flags.zero) { - ccp = ""; - cc2p = "00"; + ccp = ""; + cc2p = "00"; } if (ccp) { if (inf[0]) { @@ -3737,7 +3787,9 @@ main(int argc, char * argv[]) clp->outfd = -1; /* don't bother opening */ else { if (FT_RAW != clp->out_type) { - flags = O_WRONLY | O_CREAT; + flags = O_WRONLY; + if (! clp->out_flags.nocreat) + flags |= O_CREAT; if (clp->out_flags.direct) flags |= O_DIRECT; if (clp->out_flags.excl) diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp index 82d9869d..b7381f44 100644 --- a/testing/sgh_dd.cpp +++ b/testing/sgh_dd.cpp @@ -36,7 +36,7 @@ * renamed [20181221] */ -static const char * version_str = "1.94 20200927"; +static const char * version_str = "1.95 20201012"; #define _XOPEN_SOURCE 600 #ifndef _GNU_SOURCE @@ -177,6 +177,7 @@ struct flags_t { bool mrq_immed; /* mrq submit non-blocking */ bool mrq_svb; /* mrq shared_variable_block, for sg->sg copy */ bool no_dur; + bool nocreat; bool noshare; bool no_unshare; /* leave it for driver close/release */ bool no_waitq; @@ -889,11 +890,11 @@ usage(int pg_num) else if (pg_num > 1) goto page2; - pr2serr("Usage: sgh_dd [bs=BS] [count=COUNT] [ibs=BS] [if=IFILE]" - " [iflag=FLAGS]\n" - " [obs=BS] [of=OFILE] [oflag=FLAGS] " - "[seek=SEEK] [skip=SKIP]\n" - " [--help] [--version]\n\n"); + pr2serr("Usage: sgh_dd [bs=BS] [conv=CONVS] [count=COUNT] [ibs=BS] " + "[if=IFILE]\n" + " [iflag=FLAGS] [obs=BS] [of=OFILE] [oflag=FLAGS] " + "[seek=SEEK]\n" + " [skip=SKIP] [--help] [--version]\n\n"); pr2serr(" [ae=AEN[,MAEN]] [bpt=BPT] [cdbsz=6|10|12|16] " "[coe=0|1]\n" " [dio=0|1] [elemsz_kb=EKB] [fail_mask=FM] " @@ -908,6 +909,9 @@ usage(int pg_num) " where the main options (shown in first group above) are:\n" " bs must be device logical block size (default " "512)\n" + " conv comma separated list from: [nocreat,noerror," + "notrunc,\n" + " null,sync]\n" " count number of blocks to copy (def: device size)\n" " if file or device to read from (def: stdin)\n" " iflag comma separated list from: [coe,defres,dio," @@ -1021,6 +1025,7 @@ page3: " blocking)\n" " mrq_svb if mrq and sg->sg copy, do shared_variable_" "blocking\n" + " nocreat will fail rather than create OFILE\n" " nodur turns off command duration calculations\n" " no_waitq when non-blocking (async) don't use wait " "queue\n" @@ -3660,6 +3665,8 @@ process_flags(const char * arg, struct flags_t * fp) fp->no_dur = true; else if (0 == strcmp(cp, "no_dur")) fp->no_dur = true; + else if (0 == strcmp(cp, "nocreat")) + fp->nocreat = true; else if (0 == strcmp(cp, "noshare")) fp->noshare = true; else if (0 == strcmp(cp, "no_share")) @@ -3784,6 +3791,46 @@ sg_out_open(struct global_collection *clp, const char *outf, uint8_t **mmpp, return fd; } +/* Process arguments given to 'conv=" option. Returns 0 on success, + * 1 on error. */ +static int +process_conv(const char * arg, struct flags_t * ifp, struct flags_t * ofp) +{ + char buff[256]; + char * cp; + char * np; + + strncpy(buff, arg, sizeof(buff)); + buff[sizeof(buff) - 1] = '\0'; + if ('\0' == buff[0]) { + pr2serr("no conversions found\n"); + return 1; + } + cp = buff; + do { + np = strchr(cp, ','); + if (np) + *np++ = '\0'; + if (0 == strcmp(cp, "nocreat")) + ofp->nocreat = true; + else if (0 == strcmp(cp, "noerror")) + ifp->coe = true; /* will still fail on write error */ + else if (0 == strcmp(cp, "notrunc")) + ; /* this is the default action of sg_dd so ignore */ + else if (0 == strcmp(cp, "null")) + ; + else if (0 == strcmp(cp, "sync")) + ; /* dd(susv4): pad errored block(s) with zeros but sg_dd does + * that by default. Typical dd use: 'conv=noerror,sync' */ + else { + pr2serr("unrecognised flag: %s\n", cp); + return 1; + } + cp = np; + } while (cp); + return 0; +} + #define STR_SZ 1024 #define INOUTF_SZ 512 @@ -3853,6 +3900,11 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, } else if (0 == strcmp(key, "coe")) { clp->in_flags.coe = !! sg_get_num(buf); clp->out_flags.coe = clp->in_flags.coe; + } else if (0 == strcmp(key, "conv")) { + if (process_conv(buf, &clp->in_flags, &clp->out_flags)) { + pr2serr("%s: bad argument to 'conv='\n", my_name); + return SG_LIB_SYNTAX_ERROR; + } } else if (0 == strcmp(key, "count")) { if (0 != strcmp("-1", buf)) { dd_count = sg_get_llnum(buf); @@ -4327,7 +4379,9 @@ main(int argc, char * argv[]) clp->outfd = -1; /* don't bother opening */ else { if (FT_RAW != clp->out_type) { - flags = O_WRONLY | O_CREAT; + flags = O_WRONLY; + if (! clp->out_flags.nocreat) + flags |= O_CREAT; if (clp->out_flags.direct) flags |= O_DIRECT; if (clp->out_flags.excl) @@ -4395,7 +4449,9 @@ main(int argc, char * argv[]) clp->out2fd = -1; /* don't bother opening */ else { if (FT_RAW != clp->out2_type) { - flags = O_WRONLY | O_CREAT; + flags = O_WRONLY; + if (! clp->out_flags.nocreat) + flags |= O_CREAT; if (clp->out_flags.direct) flags |= O_DIRECT; if (clp->out_flags.excl) -- cgit v1.2.3