diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2014-09-23 15:01:28 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2014-09-23 15:01:28 +0000 |
commit | c9095aa14eac1d52c4232da68db91cdaf5c6575f (patch) | |
tree | caa72029af32d5631c11ff2910b6defff1b81f96 | |
parent | 3bb7224c7cc629054f3d1b1a1ea5d85433c620f4 (diff) | |
download | sg3_utils-c9095aa14eac1d52c4232da68db91cdaf5c6575f.tar.gz |
sg_sanitize: add --desc and --zero options
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@609 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | doc/sg_sanitize.8 | 58 | ||||
-rw-r--r-- | src/sg_sanitize.c | 145 |
3 files changed, 130 insertions, 76 deletions
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and some description at the top of its ".c" file. All utilities in the main directory have their own "man" pages. There is also a sg3_utils man page. -Changelog for sg3_utils-1.40 [20140821] [svn: r608] +Changelog for sg3_utils-1.40 [20140923] [svn: r609] - sg_write_verify: new utility for WRITE AND VERIFY - sg_senddiag: add --maxlen= option - sg_copy_results: correct response length calculations @@ -18,6 +18,7 @@ Changelog for sg3_utils-1.40 [20140821] [svn: r608] trailing NULL - add --warn option mainly for broken joins - add optional descriptions to -ee output + - sg_sanitize: add --desc and --zero options - sg_logs: refine tape drive output - sg_raw: with -vvv decode T10 CDB name - sg_opcodes: add --compact field diff --git a/doc/sg_sanitize.8 b/doc/sg_sanitize.8 index 0e86bb90..2ba0b5d5 100644 --- a/doc/sg_sanitize.8 +++ b/doc/sg_sanitize.8 @@ -1,13 +1,14 @@ -.TH SG_SANITIZE "8" "September 2013" "sg3_utils\-1.37" SG3_UTILS +.TH SG_SANITIZE "8" "September 2014" "sg3_utils\-1.40" SG3_UTILS .SH NAME sg_sanitize \- remove all user data from disk with SCSI SANITIZE command .SH SYNOPSIS .B sg_sanitize [\fI\-\-ause\fR] [\fI\-\-block\fR] [\fI\-\-count=OC\fR] [\fI\-\-crypto\fR] -[\fI\-\-early\fR] [\fI\-\-fail\fR] [\fI\-\-help\fR] [\fI\-\-invert\fR] -[\fI\-\-ipl=LEN\fR] [\fI\-\-overwrite\fR] [\fI\-\-pattern=PF\fR] -[\fI\-\-quick\fR] [\fI\-\-test=TE\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] -[\fI\-\-wait\fR] \fIDEVICE\fR +[\fI\-\-desc\fR] [\fI\-\-early\fR] [\fI\-\-fail\fR] [\fI\-\-help\fR] +[\fI\-\-invert\fR] [\fI\-\-ipl=LEN\fR] [\fI\-\-overwrite\fR] +[\fI\-\-pattern=PF\fR] [\fI\-\-quick\fR] [\fI\-\-test=TE\fR] +[\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fI\-\-wait\fR] [\fI\-\-zero\fR] +\fIDEVICE\fR .SH DESCRIPTION .\" Add any additional description here .PP @@ -32,7 +33,7 @@ the \fI\-\-quick\fR option is given in which case the sanitize operation starts immediately. The disk's INQUIRY response strings are printed out just in case the wrong \fIDEVICE\fR has been given. .PP -If the \fI\-\-early\fR option is given this utility will exit soon +If the \fI\-\-early\fR option is given then this utility will exit soon after starting the SANITIZE command with the IMMED bit set. The user can monitor the progress of the sanitize operation with the "sg_request \-\-num=9999 \-\-progress" which sends a REQUEST SENSE @@ -51,7 +52,7 @@ option name. .TP \fB\-A\fR, \fB\-\-ause\fR sets the AUSE bit in the cdb. AUSE is an acronym for "allow unrestricted -sanitize exit". Default action is to leave the bit cleared. +sanitize exit". The default action is to leave the AUSE bit cleared. .TP \fB\-B\fR, \fB\-\-block\fR perform a "block erase" sanitize operation. @@ -64,11 +65,19 @@ the default. \fB\-C\fR, \fB\-\-crypto\fR perform a "cryptographic erase" sanitize operation. .TP +\fB\-d\fR, \fB\-\-desc\fR +sets the DESC field in the REQUEST SENSE command used for polling. By +default this field is set to zero. A REQUEST SENSE polling loop is +used after the SANITIZE command is issued (assuming that neither the +\fI\-\-early\fR nor the \fI\-\-wait\fR option have been given) to check +on the progress of this command as it can take some time. +.TP \fB\-e\fR, \fB\-\-early\fR the default action of this utility is to poll the disk every 60 seconds to fetch the progress indication until the sanitize is finished. When this -option is given this utility will exit "early" as soon as the sanitize -has commenced. This option and \fI\-\-wait\fR cannot both be given. +option is given this utility will exit "early" as soon as the SANITIZE +command with the IMMED bit set to 1 has been acknowledged. This option and +\fI\-\-wait\fR cannot both be given. .TP \fB\-F\fR, \fB\-\-fail\fR perform an "exit failure mode" sanitize operation. Typically requires the @@ -79,10 +88,11 @@ print out the usage information then exit. .TP \fB\-i\fR, \fB\-\-ipl\fR=\fILEN\fR set the initialization pattern length to \fILEN\fR bytes. By default it is -set to the length of the pattern file (\fIPF\fR). Only active when the -\fI\-\-overwrite\fR option is also given. It is the number of bytes from -the \fIPF\fR file that will be used as the initialization pattern. The -minimum size is 1 byte and the maximum is the logical block size of the +set to the length of the pattern file (\fIPF\fR) or 4 if the \fI\-\-zero\fR +option is given. Only active when the \fI\-\-overwrite\fR option is also +given. It is the number of bytes from the \fIPF\fR file that will be used +as the initialization pattern (if the \fI\-\-zero\fR option is not given). +The minimum size is 1 byte and the maximum is the logical block size of the \fIDEVICE\fR (and not to exceed 65535). If \fILEN\fR exceeds the \fIPF\fR file size then the initialization pattern is padded with zeros. .TP @@ -93,8 +103,8 @@ INVERT bit. When the INVERT bit is set then the initialization pattern is inverted between consecutive overwrite passes. .TP \fB\-O\fR, \fB\-\-overwrite\fR -perform an "overwrite" sanitize operation. When this option is given -then the \fI\-\-pattern=PF\fR option is required. +perform an "overwrite" sanitize operation. When this option is given then +the \fI\-\-pattern=PF\fR or the \fI\-\-zero\fR option is required. .TP \fB\-p\fR, \fB\-\-pattern\fR=\fIPF\fR where \fIPF\fR is the filename of a file containing the initialization @@ -128,12 +138,24 @@ operation is complete (or fails). When this option is given (and the \fI\-\-early\fR option is not given) then the SANITIZE command is started with the IMMED bit clear. For a large disk this might take hours. [A cryptographic erase operation could potentially be very quick.] +.TP +\fB\-z\fR, \fB\-\-zero\fR +with an "overwrite" sanitize operation this option causes the initialization +pattern to be zero (4 zeros are used as the initialization pattern). Cannot +be used with the \fI\-\-pattern=PF\fR option. If this option is given +twice (e.g. '\-zz') then 0xff is used as the initialization byte. .SH NOTES The SCSI SANITIZE command is closely related to the ATA SANITIZE command, both are relatively new with the ATA command being the first one defined. The SCSI to ATA Translation (SAT) definition for the SCSI SANITIZE command appeared in the SAT\-3 revision 4 draft. .PP +When a SAT layer is used to a (S)ATA disk then for OVERWRITE the +initialization pattern must be 4 bytes long. So this means either the +\fI\-\-zero\fR option may be given, or a pattern file (with the +\fI\-\-pattern=PF\fR option) that is 4 bytes long or set to that +length with the \fI\-\-ipl=LEN\fR option. +.PP The SCSI SANITIZE command is related to the SCSI FORMAT UNIT command. It is likely that a block erase sanitize operation would take a similar amount of time as a format on the same disk (e.g. 9 hours for a 2 Terabyte @@ -183,7 +205,7 @@ If the 15 second reconsideration time is not required add the .PP sg_sanitize \-\-block \-\-quick \-\-early /dev/sdm .PP -To do an "overwrite" sanitize a pattern file is required: +To do an "overwrite" sanitize a pattern file may be given: .PP sg_sanitize \-\-overwrite \-\-pattern=rand.img /dev/sdm .PP @@ -193,6 +215,8 @@ sanitize operation: .PP sg_sanitize \-\-overwrite \-\-pattern=rand.img \-\-ipl=17 /dev/sdm .PP +To overwrite with zeros use: + sg_sanitize \-\-overwrite \-\-zero /dev/sdm .SH EXIT STATUS The exit status of sg_sanitize is 0 when it is successful. Otherwise see the sg3_utils(8) man page. Unless the \fI\-\-wait\fR option is given, the @@ -202,7 +226,7 @@ Written by Douglas Gilbert. .SH "REPORTING BUGS" Report bugs to <dgilbert at interlog dot com>. .SH COPYRIGHT -Copyright \(co 2011\-2013 Douglas Gilbert +Copyright \(co 2011\-2014 Douglas Gilbert .br This software is distributed under a FreeBSD license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/src/sg_sanitize.c b/src/sg_sanitize.c index a21cb7b6..30522b76 100644 --- a/src/sg_sanitize.c +++ b/src/sg_sanitize.c @@ -26,7 +26,7 @@ #include "sg_cmds_basic.h" #include "sg_cmds_extra.h" -static const char * version_str = "0.94 20140516"; +static const char * version_str = "0.95 20140923"; /* Not all environments support the Unix sleep() */ #if defined(MSC_VER) || defined(__MINGW32__) @@ -64,6 +64,7 @@ static struct option long_options[] = { {"block", no_argument, 0, 'B'}, {"count", required_argument, 0, 'c'}, {"crypto", no_argument, 0, 'C'}, + {"desc", no_argument, 0, 'd'}, {"early", no_argument, 0, 'e'}, {"fail", no_argument, 0, 'F'}, {"help", no_argument, 0, 'h'}, @@ -76,6 +77,7 @@ static struct option long_options[] = { {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"wait", no_argument, 0, 'w'}, + {"zero", no_argument, 0, 'z'}, {0, 0, 0, 0}, }; @@ -84,6 +86,7 @@ struct opts_t { int block; int count; int crypto; + int desc; int early; int fail; int invert; @@ -93,6 +96,7 @@ struct opts_t { int quick; int verbose; int wait; + int zero; const char * pattern_fn; }; @@ -114,6 +118,9 @@ usage() " --count=OC|-c OC OC is overwrite count field (from 1 " "(def) to 31)\n" " --crypto|-C do CRYPTOGRAPHIC ERASE sanitize\n" + " --desc|-d polling request sense sets 'desc' " + "field\n" + " (def: clear 'desc' field)\n" " --early|-e exit once sanitize started (IMMED set " "in cdb)\n" " user can monitor progress with REQUEST " @@ -137,9 +144,11 @@ usage() " --verbose|-v increase verbosity\n" " --version|-V print version string then exit\n" " --wait|-w wait for command to finish (could " - "take hours)\n\n" + "take hours)\n" + " --zero|-z use pattern of zeros for " + "OVERWRITE\n\n" "Performs a SCSI SANITIZE command.\n <<<WARNING>>>: all data " - "on DEVICE will lost.\nDefault action is to give user time to " + "on DEVICE will be lost.\nDefault action is to give user time to " "reconsider; then execute SANITIZE\ncommand with IMMED bit set; " "then use REQUEST SENSE command every 60\nseconds to poll for a " "progress indication; then exit when there is no\nmore progress " @@ -238,7 +247,7 @@ do_sanitize(int sg_fd, const struct opts_t * op, const void * param_lstp, int main(int argc, char * argv[]) { - int sg_fd, k, res, c, infd, progress, vb, n, desc, resp_len; + int sg_fd, k, res, c, infd, progress, vb, n, resp_len; int got_stdin = 0; int param_lst_len = 0; const char * device_name = NULL; @@ -259,7 +268,7 @@ main(int argc, char * argv[]) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "ABc:CeFhi:IOp:QT:vVw", long_options, + c = getopt_long(argc, argv, "ABc:CdeFhi:IOp:QT:vVwz", long_options, &option_index); if (c == -1) break; @@ -282,6 +291,9 @@ main(int argc, char * argv[]) case 'C': ++op->crypto; break; + case 'd': + ++op->desc; + break; case 'e': ++op->early; break; @@ -328,6 +340,9 @@ main(int argc, char * argv[]) case 'w': ++op->wait; break; + case 'z': + ++op->zero; + break; default: fprintf(stderr, "unrecognised option code 0x%x ??\n", c); usage(); @@ -360,34 +375,42 @@ main(int argc, char * argv[]) return SG_LIB_SYNTAX_ERROR; } if (op->overwrite) { - if (NULL == op->pattern_fn) { - fprintf(stderr, "'--overwrite' requires '--pattern=PF' " - "option\n"); - return SG_LIB_SYNTAX_ERROR; - } - got_stdin = (0 == strcmp(op->pattern_fn, "-")) ? 1 : 0; - if (! got_stdin) { - memset(&a_stat, 0, sizeof(a_stat)); - if (stat(op->pattern_fn, &a_stat) < 0) { - fprintf(stderr, "pattern file: unable to stat(%s): %s\n", - op->pattern_fn, safe_strerror(errno)); - return SG_LIB_FILE_ERROR; + if (op->zero) { + if (op->pattern_fn) { + fprintf(stderr, "confused: both '--pattern=PF' and '--zero' " + "options\n"); + return SG_LIB_SYNTAX_ERROR; } - if (op->ipl <= 0) { - op->ipl = (int)a_stat.st_size; - if (op->ipl > MAX_XFER_LEN) { - fprintf(stderr, "pattern file length exceeds 65535 " - "bytes, need '--ipl=LEN' option\n"); - return SG_LIB_FILE_ERROR; + op->ipl = 4; + } else { + if (NULL == op->pattern_fn) { + fprintf(stderr, "'--overwrite' requires '--pattern=PF' " + "or '--zero' option\n"); + return SG_LIB_SYNTAX_ERROR; + } + got_stdin = (0 == strcmp(op->pattern_fn, "-")) ? 1 : 0; + if (! got_stdin) { + memset(&a_stat, 0, sizeof(a_stat)); + if (stat(op->pattern_fn, &a_stat) < 0) { + fprintf(stderr, "pattern file: unable to stat(%s): %s\n", + op->pattern_fn, safe_strerror(errno)); + return SG_LIB_FILE_ERROR; + } + if (op->ipl <= 0) { + op->ipl = (int)a_stat.st_size; + if (op->ipl > MAX_XFER_LEN) { + fprintf(stderr, "pattern file length exceeds 65535 " + "bytes, need '--ipl=LEN' option\n"); + return SG_LIB_FILE_ERROR; + } } } + if (op->ipl < 1) { + fprintf(stderr, "'--overwrite' requires '--ipl=LEN' " + "option if can't get PF length\n"); + return SG_LIB_SYNTAX_ERROR; + } } - if (op->ipl < 1) { - fprintf(stderr, "'--overwrite' requires '--ipl=LEN' " - "option if can't get PF length\n"); - return SG_LIB_SYNTAX_ERROR; - } - } sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, vb); @@ -419,38 +442,44 @@ main(int argc, char * argv[]) ret = SG_LIB_SYNTAX_ERROR; goto err_out; } - if (got_stdin) { - infd = STDIN_FILENO; - if (sg_set_binary_mode(STDIN_FILENO) < 0) - perror("sg_set_binary_mode"); + if (op->zero) { + if (2 == op->zero) /* treat -zz as fill with 0xff bytes */ + memset(wBuff + 4, 0xff, op->ipl); + else + memset(wBuff + 4, 0, op->ipl); } else { - if ((infd = open(op->pattern_fn, O_RDONLY)) < 0) { - snprintf(ebuff, EBUFF_SZ, - ME "could not open %s for reading", op->pattern_fn); + if (got_stdin) { + infd = STDIN_FILENO; + if (sg_set_binary_mode(STDIN_FILENO) < 0) + perror("sg_set_binary_mode"); + } else { + if ((infd = open(op->pattern_fn, O_RDONLY)) < 0) { + snprintf(ebuff, EBUFF_SZ, ME "could not open %s for " + "reading", op->pattern_fn); + perror(ebuff); + ret = SG_LIB_FILE_ERROR; + goto err_out; + } else if (sg_set_binary_mode(infd) < 0) + perror("sg_set_binary_mode"); + } + res = read(infd, wBuff + 4, op->ipl); + if (res < 0) { + snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", + op->pattern_fn); perror(ebuff); + if (! got_stdin) + close(infd); ret = SG_LIB_FILE_ERROR; goto err_out; - } else if (sg_set_binary_mode(infd) < 0) - perror("sg_set_binary_mode"); - } - res = read(infd, wBuff + 4, op->ipl); - if (res < 0) { - snprintf(ebuff, EBUFF_SZ, ME "couldn't read from %s", - op->pattern_fn); - perror(ebuff); + } + if (res < op->ipl) { + fprintf(stderr, "tried to read %d bytes from %s, got %d " + "bytes\n", op->ipl, op->pattern_fn, res); + fprintf(stderr, " so pad with 0x0 bytes and continue\n"); + } if (! got_stdin) close(infd); - ret = SG_LIB_FILE_ERROR; - goto err_out; } - if (res < op->ipl) { - fprintf(stderr, "tried to read %d bytes from %s, got %d " - "bytes\n", op->ipl, op->pattern_fn, res); - fprintf(stderr, " so pad with 0x0 bytes and continue\n"); - } - if (! got_stdin) - close(infd); - wBuff[0] = op->count & 0x1f;; if (op->test) wBuff[0] |= ((op->test & 0x3) << 5); @@ -482,10 +511,10 @@ main(int argc, char * argv[]) } if ((0 == ret) && (0 == op->early) && (0 == op->wait)) { - for (k = 0, desc = 1 ;; ++k) { + for (k = 0 ;; ++k) { sleep_for(POLL_DURATION_SECS); memset(requestSenseBuff, 0x0, sizeof(requestSenseBuff)); - res = sg_ll_request_sense(sg_fd, desc, requestSenseBuff, + res = sg_ll_request_sense(sg_fd, op->desc, requestSenseBuff, sizeof(requestSenseBuff), 1, vb); if (res) { ret = res; @@ -493,10 +522,10 @@ main(int argc, char * argv[]) fprintf(stderr, "Request Sense command not supported\n"); else if (SG_LIB_CAT_ILLEGAL_REQ == res) { fprintf(stderr, "bad field in Request Sense cdb\n"); - if (1 == desc) { + if (1 == op->desc) { fprintf(stderr, "Descriptor type sense may not be " "supported, try again with fixed type\n"); - desc = 0; + op->desc = 0; continue; } } else { |