1 /*
2 * sg_format : format a SCSI disk
3 * potentially with a different number of blocks and block size
4 *
5 * formerly called blk512-linux.c (v0.4)
6 *
7 * Copyright (C) 2003 Grant Grundler grundler at parisc-linux dot org
8 * Copyright (C) 2003 James Bottomley jejb at parisc-linux dot org
9 * Copyright (C) 2005-2022 Douglas Gilbert dgilbert at interlog dot com
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 *
18 * See https://www.t10.org for relevant standards and drafts. The most recent
19 * draft is SBC-4 revision 2.
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <getopt.h>
29 #include <unistd.h>
30 #define __STDC_FORMAT_MACROS 1
31 #include <inttypes.h>
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 #include "sg_lib.h"
37 #include "sg_cmds_basic.h"
38 #include "sg_cmds_extra.h"
39 #include "sg_unaligned.h"
40 #include "sg_pr2serr.h"
41 #include "sg_pt.h"
42
43 static const char * version_str = "1.68 20220609";
44
45
46 #define RW_ERROR_RECOVERY_PAGE 1 /* can give alternate with --mode=MP */
47
48 #define SHORT_TIMEOUT 20 /* 20 seconds unless --wait given */
49 #define FORMAT_TIMEOUT (20 * 3600) /* 20 hours ! */
50 #define FOUR_TBYTE (4LL * 1000 * 1000 * 1000 * 1000)
51 #define LONG_FORMAT_TIMEOUT (40 * 3600) /* 40 hours */
52 #define EIGHT_TBYTE (FOUR_TBYTE * 2)
53 #define VLONG_FORMAT_TIMEOUT (80 * 3600) /* 3 days, 8 hours */
54
55 #define POLL_DURATION_SECS 60
56 #define POLL_DURATION_FFMT_SECS 10
57 #define DEF_POLL_TYPE_RS false /* false -> test unit ready;
58 true -> request sense */
59 #define MAX_BUFF_SZ 252
60
61 /* FORMAT UNIT (SBC) and FORMAT MEDIUM (SSC) share the same opcode */
62 #define SG_FORMAT_MEDIUM_CMD 0x4
63 #define SG_FORMAT_MEDIUM_CMDLEN 6
64
65 /* FORMAT WITH PRESET (new in sbc4r18) */
66 #define SG_FORMAT_WITH_PRESET_CMD 0x38
67 #define SG_FORMAT_WITH_PRESET_CMDLEN 10
68
69 #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
70
71 struct opts_t {
72 bool cmplst; /* -C value */
73 bool cmplst_given;
74 bool dry_run; /* -d */
75 bool early; /* -e */
76 bool fmtmaxlba; /* -b (only with F_WITH_PRESET) */
77 bool fwait; /* -w (negated form IMMED) */
78 bool ip_def; /* -I */
79 bool long_lba; /* -l */
80 bool mode6; /* -6 */
81 bool pinfo; /* -p, deprecated, prefer fmtpinfo */
82 bool poll_type; /* -x 0|1 */
83 bool poll_type_given;
84 bool preset; /* -E */
85 bool quick; /* -Q */
86 bool do_rcap16; /* -l */
87 bool resize; /* -r */
88 bool rto_req; /* -R, deprecated, prefer fmtpinfo */
89 bool verbose_given;
90 bool verify; /* -y */
91 bool version_given;
92 int dcrt; /* -D (can be given once or twice) */
93 int lblk_sz; /* -s value */
94 int ffmt; /* -t value; fast_format if > 0 */
95 int fmtpinfo;
96 int format; /* -F */
97 uint32_t p_id; /* set by argument of --preset=id */
98 int mode_page; /* -M value */
99 int pfu; /* -P value */
100 int pie; /* -q value */
101 int sec_init; /* -S */
102 int tape; /* -T <format>, def: -1 */
103 int timeout; /* -m SECS, def: depends on IMMED bit */
104 int verbose; /* -v */
105 int64_t blk_count; /* -c value */
106 int64_t total_byte_count; /* from READ CAPACITY command */
107 const char * device_name;
108 };
109
110
111
112 static struct option long_options[] = {
113 {"count", required_argument, 0, 'c'},
114 {"cmplst", required_argument, 0, 'C'},
115 {"dcrt", no_argument, 0, 'D'},
116 {"dry-run", no_argument, 0, 'd'},
117 {"dry_run", no_argument, 0, 'd'},
118 {"early", no_argument, 0, 'e'},
119 {"ffmt", required_argument, 0, 't'},
120 {"fmtmaxlba", no_argument, 0, 'b'},
121 {"fmtpinfo", required_argument, 0, 'f'},
122 {"format", no_argument, 0, 'F'},
123 {"help", no_argument, 0, 'h'},
124 {"ip-def", no_argument, 0, 'I'},
125 {"ip_def", no_argument, 0, 'I'},
126 {"long", no_argument, 0, 'l'},
127 {"mode", required_argument, 0, 'M'},
128 {"pinfo", no_argument, 0, 'p'},
129 {"pfu", required_argument, 0, 'P'},
130 {"pie", required_argument, 0, 'q'},
131 {"poll", required_argument, 0, 'x'},
132 {"preset", required_argument, 0, 'E'},
133 {"quick", no_argument, 0, 'Q'},
134 {"resize", no_argument, 0, 'r'},
135 {"rto_req", no_argument, 0, 'R'},
136 {"security", no_argument, 0, 'S'},
137 {"six", no_argument, 0, '6'},
138 {"size", required_argument, 0, 's'},
139 {"tape", required_argument, 0, 'T'},
140 {"timeout", required_argument, 0, 'm'},
141 {"verbose", no_argument, 0, 'v'},
142 {"verify", no_argument, 0, 'y'},
143 {"version", no_argument, 0, 'V'},
144 {"wait", no_argument, 0, 'w'},
145 {0, 0, 0, 0},
146 };
147
148 static const char * fu_s = "Format unit";
149 static const char * fm_s = "Format medium";
150 static const char * fwp_s = "Format with preset";
151
152
153 static void
usage()154 usage()
155 {
156 printf("Usage:\n"
157 " sg_format [--cmplst=0|1] [--count=COUNT] [--dcrt] "
158 "[--dry-run] [--early]\n"
159 " [--ffmt=FFMT] [--fmtmaxlba] [--fmtpinfo=FPI] "
160 "[--format] [--help]\n"
161 " [--ip-def] [--long] [--mode=MP] [--pfu=PFU] "
162 "[--pie=PIE]\n"
163 " [--pinfo] [--poll=PT] [--preset=ID] [--quick] "
164 "[--resize]\n"
165 " [--rto_req] [--security] [--six] [--size=LB_SZ] "
166 "[--tape=FM]\n"
167 " [--timeout=SECS] [--verbose] [--verify] "
168 "[--version] [--wait]\n"
169 " DEVICE\n"
170 " where:\n"
171 " --cmplst=0|1\n"
172 " -C 0|1 sets CMPLST bit in format cdb "
173 "(def: 1; if FFMT: 0)\n"
174 " --count=COUNT|-c COUNT number of blocks to report "
175 "after format or\n"
176 " resize. Format default is "
177 "same as current\n"
178 " --dcrt|-D disable certification (doesn't "
179 "verify media)\n"
180 " use twice to enable certification and "
181 "set FOV bit\n"
182 " --dry-run|-d bypass device modifying commands (i.e. "
183 "don't format)\n"
184 " --early|-e exit once format started (user can "
185 "monitor progress)\n"
186 " --ffmt=FFMT|-t FFMT fast format (def: 0 -> slow, "
187 "may visit every\n"
188 " block). 1 and 2 are fast formats; "
189 "1: after\n"
190 " format, unwritten data read "
191 "without error\n"
192 " --fmtpinfo=FPI|-f FPI FMTPINFO field value "
193 "(default: 0)\n"
194 " --format|-F do FORMAT UNIT (default: report current "
195 "count and size)\n"
196 " use thrice for FORMAT UNIT command "
197 "only\n"
198 " --fmtmaxlba|-b sets FMTMAXLBA field in FORMAT WITH "
199 "PRESET\n"
200 " --help|-h prints out this usage message\n"
201 " --ip-def|-I use default initialization pattern\n"
202 " --long|-l allow for 64 bit lbas (default: assume "
203 "32 bit lbas)\n"
204 " --mode=MP|-M MP mode page (def: 1 -> RW error "
205 "recovery mpage)\n"
206 " --pie=PIE|-q PIE Protection Information Exponent "
207 "(default: 0)\n"
208 " --pinfo|-p set upper bit of FMTPINFO field\n"
209 " (deprecated, use '--fmtpinfo=FPI' "
210 "instead)\n"
211 " --poll=PT|-x PT PT is poll type, 0 for test unit "
212 "ready\n"
213 " 1 for request sense (def: 0 (1 "
214 "for tape and\n"
215 " format with preset))\n");
216 printf(" --preset=ID|-E ID do FORMAT WITH PRESET command "
217 "with PRESET\n"
218 " IDENTIFIER field set to ID\n"
219 " --quick|-Q start format without pause for user "
220 "intervention\n"
221 " (i.e. no time to reconsider)\n"
222 " --resize|-r resize (rather than format) to COUNT "
223 "value\n"
224 " --rto_req|-R set lower bit of FMTPINFO field\n"
225 " (deprecated use '--fmtpinfo=FPI' "
226 "instead)\n"
227 " --security|-S set security initialization (SI) bit\n"
228 " --six|-6 use 6 byte MODE SENSE/SELECT to probe "
229 "disk\n"
230 " (def: use 10 byte MODE SENSE/SELECT)\n"
231 " --size=LB_SZ|-s LB_SZ bytes per logical block, "
232 "defaults to DEVICE's\n"
233 " current logical block size. Only "
234 "needed to\n"
235 " change current logical block "
236 "size\n"
237 " --tape=FM|-T FM request FORMAT MEDIUM with FORMAT "
238 "field set\n"
239 " to FM (def: 0 --> default format)\n"
240 " --timeout=SECS|-m SECS FORMAT UNIT/MEDIUM command "
241 "timeout in seconds\n"
242 " --verbose|-v increase verbosity\n"
243 " --verify|-y sets VERIFY bit in FORMAT MEDIUM (tape)\n"
244 " --version|-V print version details and exit\n"
245 " --wait|-w format commands wait until format "
246 "operations complete\n"
247 " (default: set IMMED=1 and poll with "
248 "Test Unit Ready)\n\n"
249 "\tExample: sg_format --format /dev/sdc\n\n"
250 "This utility formats a SCSI disk [FORMAT UNIT] or resizes "
251 "it. Alternatively\nif '--tape=FM' is given formats a tape "
252 "[FORMAT MEDIUM]. Another alternative\nis doing the FORMAT "
253 "WITH PRESET command when '--preset=ID' is given.\n\n");
254 printf("WARNING: This utility will destroy all the data on the "
255 "DEVICE when\n\t '--format', '--tape=FM' or '--preset=ID' "
256 "is given. Double check\n\t that you have specified the "
257 "correct DEVICE.\n");
258 }
259
260 /* Invokes a SCSI FORMAT MEDIUM command (SSC). Return of 0 -> success,
261 * various SG_LIB_CAT_* positive values or -1 -> other errors */
262 static int
sg_ll_format_medium(int sg_fd,bool verify,bool immed,int format,void * paramp,int transfer_len,int timeout,bool noisy,int verbose)263 sg_ll_format_medium(int sg_fd, bool verify, bool immed, int format,
264 void * paramp, int transfer_len, int timeout, bool noisy,
265 int verbose)
266 {
267 int ret, res, sense_cat;
268 uint8_t fm_cdb[SG_FORMAT_MEDIUM_CMDLEN] =
269 {SG_FORMAT_MEDIUM_CMD, 0, 0, 0, 0, 0};
270 uint8_t sense_b[SENSE_BUFF_LEN] SG_C_CPP_ZERO_INIT;
271 struct sg_pt_base * ptvp;
272
273 if (verify)
274 fm_cdb[1] |= 0x2;
275 if (immed)
276 fm_cdb[1] |= 0x1;
277 if (format)
278 fm_cdb[2] |= (0xf & format);
279 if (transfer_len > 0)
280 sg_put_unaligned_be16(transfer_len, fm_cdb + 3);
281 if (verbose) {
282 char b[128];
283
284 pr2serr(" %s cdb: %s\n", fm_s,
285 sg_get_command_str(fm_cdb, SG_FORMAT_MEDIUM_CMDLEN,
286 false, sizeof(b), b));
287 }
288
289 ptvp = construct_scsi_pt_obj();
290 if (NULL == ptvp) {
291 pr2serr("%s: out of memory\n", __func__);
292 return sg_convert_errno(ENOMEM);
293 }
294 set_scsi_pt_cdb(ptvp, fm_cdb, sizeof(fm_cdb));
295 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
296 set_scsi_pt_data_out(ptvp, (uint8_t *)paramp, transfer_len);
297 res = do_scsi_pt(ptvp, sg_fd, timeout, verbose);
298 ret = sg_cmds_process_resp(ptvp, fm_s, res, noisy, verbose,
299 &sense_cat);
300 if (-1 == ret) {
301 if (get_scsi_pt_transport_err(ptvp))
302 ret = SG_LIB_TRANSPORT_ERROR;
303 else
304 ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
305 } else if (-2 == ret) {
306 switch (sense_cat) {
307 case SG_LIB_CAT_RECOVERED:
308 case SG_LIB_CAT_NO_SENSE:
309 ret = 0;
310 break;
311 default:
312 ret = sense_cat;
313 break;
314 }
315 } else {
316 ret = 0;
317 if (verbose)
318 pr2serr("%s command %s without error\n", fm_s,
319 (immed ? "launched" : "completed"));
320 }
321 destruct_scsi_pt_obj(ptvp);
322 return ret;
323 }
324
325 /* Invokes a SCSI FORMAT WITH PRESET command (SBC). Return of 0 -> success,
326 * various SG_LIB_CAT_* positive values or -1 -> other errors */
327 static int
sg_ll_format_with_preset(int sg_fd,bool immed,bool fmtmaxlba,uint32_t preset_id,int timeout,bool noisy,int verbose)328 sg_ll_format_with_preset(int sg_fd, bool immed, bool fmtmaxlba,
329 uint32_t preset_id, int timeout, bool noisy,
330 int verbose)
331 {
332 int ret, res, sense_cat;
333 uint8_t fwp_cdb[SG_FORMAT_WITH_PRESET_CMDLEN] =
334 {SG_FORMAT_WITH_PRESET_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
335 uint8_t sense_b[SENSE_BUFF_LEN] SG_C_CPP_ZERO_INIT;
336 struct sg_pt_base * ptvp;
337
338 if (immed)
339 fwp_cdb[1] |= 0x80;
340 if (fmtmaxlba)
341 fwp_cdb[1] |= 0x40;
342 if (preset_id > 0)
343 sg_put_unaligned_be32(preset_id, fwp_cdb + 2);
344 if (verbose) {
345 char b[128];
346
347 pr2serr(" %s cdb: %s\n", fwp_s,
348 sg_get_command_str(fwp_cdb,
349 SG_FORMAT_WITH_PRESET_CMDLEN,
350 false, sizeof(b), b));
351 }
352 ptvp = construct_scsi_pt_obj();
353 if (NULL == ptvp) {
354 pr2serr("%s: out of memory\n", __func__);
355 return sg_convert_errno(ENOMEM);
356 }
357 set_scsi_pt_cdb(ptvp, fwp_cdb, sizeof(fwp_cdb));
358 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
359 res = do_scsi_pt(ptvp, sg_fd, timeout, verbose);
360 ret = sg_cmds_process_resp(ptvp, fwp_s, res, noisy, verbose,
361 &sense_cat);
362 if (-1 == ret) {
363 if (get_scsi_pt_transport_err(ptvp))
364 ret = SG_LIB_TRANSPORT_ERROR;
365 else
366 ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
367 } else if (-2 == ret) {
368 switch (sense_cat) {
369 case SG_LIB_CAT_RECOVERED:
370 case SG_LIB_CAT_NO_SENSE:
371 ret = 0;
372 break;
373 default:
374 ret = sense_cat;
375 break;
376 }
377 } else {
378 ret = 0;
379 if (verbose)
380 pr2serr("%s command %s without error\n", fwp_s,
381 (immed ? "launched" : "completed"));
382 }
383 destruct_scsi_pt_obj(ptvp);
384 return ret;
385 }
386
387 /* Return 0 on success, else see sg_ll_format_unit_v2() */
388 static int
scsi_format_unit(int fd,const struct opts_t * op)389 scsi_format_unit(int fd, const struct opts_t * op)
390 {
391 bool need_param_lst, longlist, ip_desc, first;
392 bool immed = ! op->fwait;
393 int res, progress, pr, rem, param_sz, off, resp_len, tmout;
394 int poll_wait_secs;
395 int vb = op->verbose;
396 const int SH_FORMAT_HEADER_SZ = 4;
397 const int LONG_FORMAT_HEADER_SZ = 8;
398 const int INIT_PATTERN_DESC_SZ = 4;
399 const int max_param_sz = LONG_FORMAT_HEADER_SZ + INIT_PATTERN_DESC_SZ;
400 uint8_t * param;
401 uint8_t * free_param = NULL;
402 char b[80];
403
404 param = sg_memalign(max_param_sz, 0, &free_param, false);
405 if (NULL == param) {
406 pr2serr("%s: unable to obtain heap for parameter list\n",
407 __func__);
408 return sg_convert_errno(ENOMEM);
409 }
410 if (immed)
411 tmout = SHORT_TIMEOUT;
412 else {
413 if (op->total_byte_count > EIGHT_TBYTE)
414 tmout = VLONG_FORMAT_TIMEOUT;
415 else if (op->total_byte_count > FOUR_TBYTE)
416 tmout = LONG_FORMAT_TIMEOUT;
417 else
418 tmout = FORMAT_TIMEOUT;
419 }
420 if (op->timeout > tmout)
421 tmout = op->timeout;
422 longlist = (op->pie > 0); /* only set LONGLIST if PI_EXPONENT>0 */
423 ip_desc = (op->ip_def || op->sec_init);
424 off = longlist ? LONG_FORMAT_HEADER_SZ : SH_FORMAT_HEADER_SZ;
425 param[0] = op->pfu & 0x7; /* PROTECTION_FIELD_USAGE (bits 2-0) */
426 param[1] = (immed ? 0x2 : 0); /* FOV=0, [DPRY,DCRT,STPF,IP=0] */
427 if (1 == op->dcrt)
428 param[1] |= 0xa0; /* FOV=1, DCRT=1 */
429 else if (op->dcrt > 1)
430 param[1] |= 0x80; /* FOV=1, DCRT=0 */
431 if (ip_desc) {
432 param[1] |= 0x88; /* FOV=1, IP=1 */
433 if (op->sec_init)
434 param[off + 0] = 0x20; /* SI=1 in IP desc */
435 }
436 if (longlist)
437 param[3] = (op->pie & 0xf);/* PROTECTION_INTERVAL_EXPONENT */
438 /* with the long parameter list header, P_I_INFORMATION is always 0 */
439
440 need_param_lst = (immed || op->cmplst || (op->dcrt > 0) || ip_desc ||
441 (op->pfu > 0) || (op->pie > 0));
442 param_sz = need_param_lst ?
443 (off + (ip_desc ? INIT_PATTERN_DESC_SZ : 0)) : 0;
444
445 if (op->dry_run) {
446 res = 0;
447 pr2serr("Due to --dry-run option bypassing FORMAT UNIT "
448 "command\n");
449 if (vb) {
450 if (need_param_lst) {
451 pr2serr(" %s would have received parameter "
452 "list: ", fu_s);
453 hex2stderr(param, max_param_sz, -1);
454 } else
455 pr2serr(" %s would not have received a "
456 "parameter list\n", fu_s);
457 pr2serr(" %s cdb fields: fmtpinfo=0x%x, "
458 "longlist=%d, fmtdata=%d, cmplst=%d, "
459 "ffmt=%d [timeout=%d secs]\n", fu_s,
460 op->fmtpinfo, longlist, need_param_lst,
461 op->cmplst, op->ffmt, tmout);
462 }
463 } else
464 res = sg_ll_format_unit_v2(fd, op->fmtpinfo, longlist,
465 need_param_lst, op->cmplst, 0,
466 op->ffmt, tmout, param, param_sz,
467 true, vb);
468 if (free_param)
469 free(free_param);
470
471 if (res) {
472 sg_get_category_sense_str(res, sizeof(b), b, vb);
473 pr2serr("%s command: %s\n", fu_s, b);
474 return res;
475 } else if (op->verbose)
476 pr2serr("%s command %s without error\n", fu_s,
477 (immed ? "launched" : "completed"));
478 if (! immed)
479 return 0;
480
481 if (! op->dry_run)
482 printf("\n%s has started\n", fu_s);
483
484 if (op->early) {
485 if (immed)
486 printf("%s continuing,\n request sense or "
487 "test unit ready can be used to monitor "
488 "progress\n", fu_s);
489 return 0;
490 }
491
492 if (op->dry_run) {
493 printf("No point in polling for progress, so exit\n");
494 return 0;
495 }
496 poll_wait_secs = op->ffmt ? POLL_DURATION_FFMT_SECS :
497 POLL_DURATION_SECS;
498 if (! op->poll_type) {
499 for(first = true; ; first = false) {
500 sg_sleep_secs(poll_wait_secs);
501 progress = -1;
502 res = sg_ll_test_unit_ready_progress(fd, 0, &progress,
503 true, (vb > 1) ? (vb - 1) : 0);
504 if (progress >= 0) {
505 pr = (progress * 100) / 65536;
506 rem = ((progress * 100) % 65536) / 656;
507 printf("%s in progress, %d.%02d%% done\n",
508 fu_s, pr, rem);
509 } else {
510 if (first && op->verbose)
511 pr2serr("%s seems to be successful "
512 "and finished quickly\n",
513 fu_s);
514 break;
515 }
516 }
517 }
518 if (op->poll_type || (SG_LIB_CAT_NOT_READY == res)) {
519 uint8_t * reqSense;
520 uint8_t * free_reqSense = NULL;
521
522 reqSense = sg_memalign(MAX_BUFF_SZ, 0, &free_reqSense, false);
523 if (NULL == reqSense) {
524 pr2serr("%s: unable to obtain heap for Request "
525 "Sense\n", __func__);
526 return sg_convert_errno(ENOMEM);
527 }
528 for(first = true; ; first = false) {
529 sg_sleep_secs(poll_wait_secs);
530 memset(reqSense, 0x0, MAX_BUFF_SZ);
531 res = sg_ll_request_sense(fd, false, reqSense,
532 MAX_BUFF_SZ, false,
533 (vb > 1) ? (vb - 1) : 0);
534 if (res) {
535 pr2serr("polling with Request Sense command "
536 "failed [res=%d]\n", res);
537 break;
538 }
539 resp_len = reqSense[7] + 8;
540 if (vb > 1) {
541 pr2serr("Parameter data in hex:\n");
542 hex2stderr(reqSense, resp_len, 1);
543 }
544 progress = -1;
545 sg_get_sense_progress_fld(reqSense, resp_len,
546 &progress);
547 if (progress >= 0) {
548 pr = (progress * 100) / 65536;
549 rem = ((progress * 100) % 65536) / 656;
550 printf("%s in progress, %d.%02d%% done\n",
551 fu_s, pr, rem);
552 } else {
553 if (first && op->verbose)
554 pr2serr("%s seems to be successful "
555 "and finished quickly\n",
556 fu_s);
557 break;
558 }
559 }
560 if (free_reqSense)
561 free(free_reqSense);
562 }
563 printf("FORMAT UNIT Complete\n");
564 return 0;
565 }
566
567 /* Return 0 on success, else see sg_ll_format_medium() above */
568 static int
scsi_format_medium(int fd,const struct opts_t * op)569 scsi_format_medium(int fd, const struct opts_t * op)
570 {
571 bool first;
572 bool immed = ! op->fwait;
573 int res, progress, pr, rem, resp_len, tmout;
574 int vb = op->verbose;
575 char b[80];
576
577 if (immed)
578 tmout = SHORT_TIMEOUT;
579 else {
580 if (op->total_byte_count > EIGHT_TBYTE)
581 tmout = VLONG_FORMAT_TIMEOUT;
582 else if (op->total_byte_count > FOUR_TBYTE)
583 tmout = LONG_FORMAT_TIMEOUT;
584 else
585 tmout = FORMAT_TIMEOUT;
586 }
587 if (op->timeout > tmout)
588 tmout = op->timeout;
589 if (op->dry_run) {
590 res = 0;
591 pr2serr("Due to --dry-run option bypassing %s command\n",
592 fm_s);
593 } else
594 res = sg_ll_format_medium(fd, op->verify, immed,
595 0xf & op->tape, NULL, 0, tmout,
596 true, vb);
597 if (res) {
598 sg_get_category_sense_str(res, sizeof(b), b, vb);
599 pr2serr("%s command: %s\n", fm_s, b);
600 return res;
601 }
602 if (! immed)
603 return 0;
604
605 if (! op->dry_run)
606 printf("\n%s has started\n", fm_s);
607 if (op->early) {
608 if (immed)
609 printf("%s continuing,\n request sense or "
610 "test unit ready can be used to monitor "
611 "progress\n", fm_s);
612 return 0;
613 }
614
615 if (op->dry_run) {
616 printf("No point in polling for progress, so exit\n");
617 return 0;
618 }
619 if (! op->poll_type) {
620 for(first = true; ; first = false) {
621 sg_sleep_secs(POLL_DURATION_SECS);
622 progress = -1;
623 res = sg_ll_test_unit_ready_progress(fd, 0, &progress,
624 true, (vb > 1) ? (vb - 1) : 0);
625 if (progress >= 0) {
626 pr = (progress * 100) / 65536;
627 rem = ((progress * 100) % 65536) / 656;
628 printf("%s in progress, %d.%02d%% done\n",
629 fm_s, pr, rem);
630 } else {
631 if (first && op->verbose)
632 pr2serr("%s seems to be successful "
633 "and finished quickly\n",
634 fm_s);
635 break;
636 }
637 }
638 }
639 if (op->poll_type || (SG_LIB_CAT_NOT_READY == res)) {
640 uint8_t * reqSense;
641 uint8_t * free_reqSense = NULL;
642
643 reqSense = sg_memalign(MAX_BUFF_SZ, 0, &free_reqSense, false);
644 if (NULL == reqSense) {
645 pr2serr("%s: unable to obtain heap for Request "
646 "Sense\n", __func__);
647 return sg_convert_errno(ENOMEM);
648 }
649 for(first = true; ; first = false) {
650 sg_sleep_secs(POLL_DURATION_SECS);
651 memset(reqSense, 0x0, MAX_BUFF_SZ);
652 res = sg_ll_request_sense(fd, false, reqSense,
653 MAX_BUFF_SZ, false,
654 (vb > 1) ? (vb - 1) : 0);
655 if (res) {
656 pr2serr("polling with Request Sense command "
657 "failed [res=%d]\n", res);
658 break;
659 }
660 resp_len = reqSense[7] + 8;
661 if (vb > 1) {
662 pr2serr("Parameter data in hex:\n");
663 hex2stderr(reqSense, resp_len, 1);
664 }
665 progress = -1;
666 sg_get_sense_progress_fld(reqSense, resp_len,
667 &progress);
668 if (progress >= 0) {
669 pr = (progress * 100) / 65536;
670 rem = ((progress * 100) % 65536) / 656;
671 printf("%s in progress, %d.%02d%% done\n",
672 fm_s, pr, rem);
673 } else {
674 if (first && op->verbose)
675 pr2serr("%s seems to be successful "
676 "and finished quickly\n",
677 fm_s);
678 break;
679 }
680 }
681 if (free_reqSense)
682 free(free_reqSense);
683 }
684 printf("FORMAT MEDIUM Complete\n");
685 return 0;
686 }
687
688 /* Return 0 on success, else see sg_ll_format_medium() above */
689 static int
scsi_format_with_preset(int fd,const struct opts_t * op)690 scsi_format_with_preset(int fd, const struct opts_t * op)
691 {
692 bool first;
693 bool immed = ! op->fwait;
694 int res, progress, pr, rem, resp_len, tmout;
695 int vb = op->verbose;
696 char b[80];
697
698 if (immed)
699 tmout = SHORT_TIMEOUT;
700 else {
701 if (op->total_byte_count > EIGHT_TBYTE)
702 tmout = VLONG_FORMAT_TIMEOUT;
703 else if (op->total_byte_count > FOUR_TBYTE)
704 tmout = LONG_FORMAT_TIMEOUT;
705 else
706 tmout = FORMAT_TIMEOUT;
707 }
708 if (op->timeout > tmout)
709 tmout = op->timeout;
710 if (op->dry_run) {
711 res = 0;
712 pr2serr("Due to --dry-run option bypassing FORMAT WITH "
713 "PRESET command\n");
714 } else
715 res = sg_ll_format_with_preset(fd, immed, op->fmtmaxlba,
716 op->p_id, tmout, true, vb);
717 if (res) {
718 sg_get_category_sense_str(res, sizeof(b), b, vb);
719 pr2serr("%s command: %s\n", fwp_s, b);
720 return res;
721 }
722 if (! immed)
723 return 0;
724
725 if (! op->dry_run)
726 printf("\n%s has started\n", fwp_s);
727 if (op->early) {
728 if (immed)
729 printf("%s continuing,\n Request sense can "
730 "be used to monitor progress\n", fwp_s);
731 return 0;
732 }
733
734 if (op->dry_run) {
735 printf("No point in polling for progress, so exit\n");
736 return 0;
737 }
738 if (! op->poll_type) {
739 for(first = true; ; first = false) {
740 sg_sleep_secs(POLL_DURATION_SECS);
741 progress = -1;
742 res = sg_ll_test_unit_ready_progress(fd, 0, &progress,
743 true, (vb > 1) ? (vb - 1) : 0);
744 if (progress >= 0) {
745 pr = (progress * 100) / 65536;
746 rem = ((progress * 100) % 65536) / 656;
747 printf("%s in progress, %d.%02d%% done\n",
748 fwp_s, pr, rem);
749 } else {
750 if (first && op->verbose)
751 pr2serr("%s seems to be successful "
752 "and finished quickly\n",
753 fwp_s);
754 break;
755 }
756 }
757 }
758 if (op->poll_type || (SG_LIB_CAT_NOT_READY == res)) {
759 uint8_t * reqSense;
760 uint8_t * free_reqSense = NULL;
761
762 reqSense = sg_memalign(MAX_BUFF_SZ, 0, &free_reqSense, false);
763 if (NULL == reqSense) {
764 pr2serr("%s: unable to obtain heap for Request "
765 "Sense\n", __func__);
766 return sg_convert_errno(ENOMEM);
767 }
768 for(first = true; ; first = false) {
769 sg_sleep_secs(POLL_DURATION_SECS);
770 memset(reqSense, 0x0, MAX_BUFF_SZ);
771 res = sg_ll_request_sense(fd, false, reqSense,
772 MAX_BUFF_SZ, false,
773 (vb > 1) ? (vb - 1) : 0);
774 if (res) {
775 pr2serr("polling with Request Sense command "
776 "failed [res=%d]\n", res);
777 break;
778 }
779 resp_len = reqSense[7] + 8;
780 if (vb > 1) {
781 pr2serr("Parameter data in hex:\n");
782 hex2stderr(reqSense, resp_len, 1);
783 }
784 progress = -1;
785 sg_get_sense_progress_fld(reqSense, resp_len,
786 &progress);
787 if (progress >= 0) {
788 pr = (progress * 100) / 65536;
789 rem = ((progress * 100) % 65536) / 656;
790 printf("%s in progress, %d.%02d%% done\n",
791 fwp_s, pr, rem);
792 } else {
793 if (first && op->verbose)
794 pr2serr("%s seems to be successful "
795 "and finished quickly\n",
796 fwp_s);
797 break;
798 }
799 }
800 if (free_reqSense)
801 free(free_reqSense);
802 }
803 printf("FORMAT WITH PRESET Complete\n");
804 return 0;
805 }
806
807 #define VPD_DEVICE_ID 0x83
808 #define VPD_ASSOC_LU 0
809 #define VPD_ASSOC_TPORT 1
810 #define TPROTO_ISCSI 5
811
812 static char *
get_lu_name(const uint8_t * bp,int u_len,char * b,int b_len)813 get_lu_name(const uint8_t * bp, int u_len, char * b, int b_len)
814 {
815 int len, off, sns_dlen, dlen, k;
816 uint8_t u_sns[512];
817 char * cp;
818
819 len = u_len - 4;
820 bp += 4;
821 off = -1;
822 if (0 == sg_vpd_dev_id_iter(bp, len, &off, VPD_ASSOC_LU,
823 8 /* SCSI name string (sns) */,
824 3 /* UTF-8 */)) {
825 sns_dlen = bp[off + 3];
826 memcpy(u_sns, bp + off + 4, sns_dlen);
827 /* now want to check if this is iSCSI */
828 off = -1;
829 if (0 == sg_vpd_dev_id_iter(bp, len, &off, VPD_ASSOC_TPORT,
830 8 /* SCSI name string (sns) */,
831 3 /* UTF-8 */)) {
832 if ((0x80 & bp[1]) &&
833 (TPROTO_ISCSI == (bp[0] >> 4))) {
834 snprintf(b, b_len, "%.*s", sns_dlen, u_sns);
835 return b;
836 }
837 }
838 } else
839 sns_dlen = 0;
840 if (0 == sg_vpd_dev_id_iter(bp, len, &off, VPD_ASSOC_LU,
841 3 /* NAA */, 1 /* binary */)) {
842 dlen = bp[off + 3];
843 if (! ((8 == dlen) || (16 ==dlen)))
844 return b;
845 cp = b;
846 for (k = 0; ((k < dlen) && (b_len > 1)); ++k) {
847 snprintf(cp, b_len, "%02x", bp[off + 4 + k]);
848 cp += 2;
849 b_len -= 2;
850 }
851 } else if (0 == sg_vpd_dev_id_iter(bp, len, &off, VPD_ASSOC_LU,
852 2 /* EUI */, 1 /* binary */)) {
853 dlen = bp[off + 3];
854 if (! ((8 == dlen) || (12 == dlen) || (16 ==dlen)))
855 return b;
856 cp = b;
857 for (k = 0; ((k < dlen) && (b_len > 1)); ++k) {
858 snprintf(cp, b_len, "%02x", bp[off + 4 + k]);
859 cp += 2;
860 b_len -= 2;
861 }
862 } else if (sns_dlen > 0)
863 snprintf(b, b_len, "%.*s", sns_dlen, u_sns);
864 return b;
865 }
866
867 #define SAFE_STD_INQ_RESP_LEN 36
868 #define VPD_SUPPORTED_VPDS 0x0
869 #define VPD_UNIT_SERIAL_NUM 0x80
870 #define VPD_DEVICE_ID 0x83
871 #define MAX_VPD_RESP_LEN 256
872
873 static int
print_dev_id(int fd,uint8_t * sinq_resp,int max_rlen,const struct opts_t * op)874 print_dev_id(int fd, uint8_t * sinq_resp, int max_rlen,
875 const struct opts_t * op)
876 {
877 int k, n, verb, pdt, has_sn, has_di;
878 int res = 0;
879 uint8_t * b;
880 uint8_t * free_b = NULL;
881 char a[MAX_VPD_RESP_LEN];
882 char pdt_name[64];
883
884 verb = (op->verbose > 1) ? op->verbose - 1 : 0;
885 memset(sinq_resp, 0, max_rlen);
886 b = sg_memalign(MAX_VPD_RESP_LEN, 0, &free_b, false);
887 if (NULL == b) {
888 res = sg_convert_errno(ENOMEM);
889 goto out;
890 }
891 /* Standard INQUIRY */
892 res = sg_ll_inquiry(fd, false, false, 0, b, SAFE_STD_INQ_RESP_LEN,
893 true, verb);
894 if (res)
895 goto out;
896 n = b[4] + 5;
897 if (n > SAFE_STD_INQ_RESP_LEN)
898 n = SAFE_STD_INQ_RESP_LEN;
899 memcpy(sinq_resp, b, (n < max_rlen) ? n : max_rlen);
900 if (n == SAFE_STD_INQ_RESP_LEN) {
901 pdt = b[0] & PDT_MASK;
902 printf(" %.8s %.16s %.4s peripheral_type: %s [0x%x]\n",
903 (const char *)(b + 8), (const char *)(b + 16),
904 (const char *)(b + 32),
905 sg_get_pdt_str(pdt, sizeof(pdt_name), pdt_name), pdt);
906 if (op->verbose)
907 printf(" PROTECT=%d\n", !!(b[5] & 1));
908 if (b[5] & 1)
909 printf(" << supports protection information>>"
910 "\n");
911 } else {
912 pr2serr("Short INQUIRY response: %d bytes, expect at least "
913 "36\n", n);
914 res = SG_LIB_CAT_OTHER;
915 goto out;
916 }
917 res = sg_ll_inquiry(fd, false, true, VPD_SUPPORTED_VPDS, b,
918 SAFE_STD_INQ_RESP_LEN, true, verb);
919 if (res) {
920 if (op->verbose)
921 pr2serr("VPD_SUPPORTED_VPDS gave res=%d\n", res);
922 res = 0;
923 goto out;
924 }
925 if (VPD_SUPPORTED_VPDS != b[1]) {
926 if (op->verbose)
927 pr2serr("VPD_SUPPORTED_VPDS corrupted\n");
928 goto out;
929 }
930 n = sg_get_unaligned_be16(b + 2);
931 if (n > (SAFE_STD_INQ_RESP_LEN - 4))
932 n = (SAFE_STD_INQ_RESP_LEN - 4);
933 for (k = 0, has_sn = 0, has_di = 0; k < n; ++k) {
934 if (VPD_UNIT_SERIAL_NUM == b[4 + k])
935 ++has_sn;
936 else if (VPD_DEVICE_ID == b[4 + k]) {
937 ++has_di;
938 break;
939 }
940 }
941 if (has_sn) {
942 res = sg_ll_inquiry(fd, false, true /* evpd */,
943 VPD_UNIT_SERIAL_NUM, b, MAX_VPD_RESP_LEN,
944 true, verb);
945 if (res) {
946 if (op->verbose)
947 pr2serr("VPD_UNIT_SERIAL_NUM gave res=%d\n",
948 res);
949 res = 0;
950 goto out;
951 }
952 if (VPD_UNIT_SERIAL_NUM != b[1]) {
953 if (op->verbose)
954 pr2serr("VPD_UNIT_SERIAL_NUM corrupted\n");
955 goto out;
956 }
957 n = sg_get_unaligned_be16(b + 2);
958 if (n > (int)(MAX_VPD_RESP_LEN - 4))
959 n = (MAX_VPD_RESP_LEN - 4);
960 printf(" Unit serial number: %.*s\n", n,
961 (const char *)(b + 4));
962 }
963 if (has_di) {
964 res = sg_ll_inquiry(fd, false, true /* evpd */, VPD_DEVICE_ID,
965 b, MAX_VPD_RESP_LEN, true, verb);
966 if (res) {
967 if (op->verbose)
968 pr2serr("VPD_DEVICE_ID gave res=%d\n", res);
969 res = 0;
970 goto out;
971 }
972 if (VPD_DEVICE_ID != b[1]) {
973 if (op->verbose)
974 pr2serr("VPD_DEVICE_ID corrupted\n");
975 goto out;
976 }
977 n = sg_get_unaligned_be16(b + 2);
978 if (n > (int)(MAX_VPD_RESP_LEN - 4))
979 n = (MAX_VPD_RESP_LEN - 4);
980 n = strlen(get_lu_name(b, n + 4, a, sizeof(a)));
981 if (n > 0)
982 printf(" LU name: %.*s\n", n, a);
983 }
984 out:
985 if (free_b)
986 free(free_b);
987 return res;
988 }
989
990 #define RCAP_REPLY_LEN 32
991
992 /* Returns block size or -2 if do_16==0 and the number of blocks is too
993 * big, or returns -1 for other error. */
994 static int
print_read_cap(int fd,struct opts_t * op)995 print_read_cap(int fd, struct opts_t * op)
996 {
997 int res = 0;
998 uint8_t * resp_buff;
999 uint8_t * free_resp_buff = NULL;
1000 unsigned int last_blk_addr, block_size;
1001 uint64_t llast_blk_addr;
1002 int64_t ll;
1003 char b[80];
1004
1005 resp_buff = sg_memalign(RCAP_REPLY_LEN, 0, &free_resp_buff, false);
1006 if (NULL == resp_buff) {
1007 pr2serr("%s: unable to obtain heap\n", __func__);
1008 res = -1;
1009 goto out;
1010 }
1011 if (op->do_rcap16) {
1012 res = sg_ll_readcap_16(fd, false /* pmi */, 0 /* llba */,
1013 resp_buff, RCAP_REPLY_LEN, true,
1014 op->verbose);
1015 if (0 == res) {
1016 llast_blk_addr = sg_get_unaligned_be64(resp_buff + 0);
1017 block_size = sg_get_unaligned_be32(resp_buff + 8);
1018 printf("Read Capacity (16) results:\n");
1019 printf(" Protection: prot_en=%d, p_type=%d, "
1020 "p_i_exponent=%d\n",
1021 !!(resp_buff[12] & 0x1),
1022 ((resp_buff[12] >> 1) & 0x7),
1023 ((resp_buff[13] >> 4) & 0xf));
1024 printf(" Logical block provisioning: lbpme=%d, "
1025 "lbprz=%d\n", !!(resp_buff[14] & 0x80),
1026 !!(resp_buff[14] & 0x40));
1027 printf(" Logical blocks per physical block "
1028 "exponent=%d\n", resp_buff[13] & 0xf);
1029 printf(" Lowest aligned logical block address=%d\n",
1030 0x3fff & sg_get_unaligned_be16(resp_buff +
1031 14));
1032 printf(" Number of logical blocks=%" PRIu64 "\n",
1033 llast_blk_addr + 1);
1034 printf(" Logical block size=%u bytes\n",
1035 block_size);
1036 ll = (int64_t)(llast_blk_addr + 1) * block_size;
1037 if (ll > op->total_byte_count)
1038 op->total_byte_count = ll;
1039 res = (int)block_size;
1040 goto out;
1041 }
1042 } else {
1043 res = sg_ll_readcap_10(fd, false /* pmi */, 0 /* lba */,
1044 resp_buff, 8, true, op->verbose);
1045 if (0 == res) {
1046 last_blk_addr = sg_get_unaligned_be32(resp_buff + 0);
1047 block_size = sg_get_unaligned_be32(resp_buff + 4);
1048 if (0xffffffff == last_blk_addr) {
1049 if (op->verbose)
1050 printf("Read Capacity (10) response "
1051 "indicates that Read Capacity "
1052 "(16) is required\n");
1053 res = -2;
1054 goto out;
1055 }
1056 printf("Read Capacity (10) results:\n");
1057 printf(" Number of logical blocks=%u\n",
1058 last_blk_addr + 1);
1059 printf(" Logical block size=%u bytes\n",
1060 block_size);
1061 ll = (int64_t)(last_blk_addr + 1) * block_size;
1062 if (ll > op->total_byte_count)
1063 op->total_byte_count = ll;
1064 res = (int)block_size;
1065 goto out;
1066 }
1067 }
1068 sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
1069 pr2serr("READ CAPACITY (%d): %s\n", (op->do_rcap16 ? 16 : 10), b);
1070 res = -1;
1071 out:
1072 if (free_resp_buff)
1073 free(free_resp_buff);
1074 return res;
1075 }
1076
1077 /* Use MODE SENSE(6 or 10) to fetch blocks descriptor(s), if any. Analyze
1078 * the first block descriptor and if required, start preparing for a
1079 * MODE SELECT(6 or 10). Returns 0 on success. */
1080 static int
fetch_block_desc(int fd,uint8_t * dbuff,int * calc_lenp,int * bd_lb_szp,struct opts_t * op)1081 fetch_block_desc(int fd, uint8_t * dbuff, int * calc_lenp, int * bd_lb_szp,
1082 struct opts_t * op)
1083 {
1084 bool first = true;
1085 bool prob;
1086 int bd_lbsz, bd_len, dev_specific_param, offset, res, rq_lb_sz;
1087 int rsp_len;
1088 int resid = 0;
1089 int vb = op->verbose;
1090 uint64_t ull;
1091 int64_t ll;
1092 char b[80];
1093
1094 again_with_long_lba:
1095 memset(dbuff, 0, MAX_BUFF_SZ);
1096 if (op->mode6)
1097 res = sg_ll_mode_sense6(fd, false /* DBD */, 0 /* current */,
1098 op->mode_page, 0 /* subpage */, dbuff,
1099 MAX_BUFF_SZ, true, vb);
1100 else
1101 res = sg_ll_mode_sense10_v2(fd, op->long_lba, false /* DBD */,
1102 0 /* current */, op->mode_page,
1103 0 /* subpage */, dbuff,
1104 MAX_BUFF_SZ, 0, &resid, true,
1105 vb);
1106 if (res) {
1107 if (SG_LIB_CAT_ILLEGAL_REQ == res) {
1108 if (op->long_lba && (! op->mode6))
1109 pr2serr("bad field in MODE SENSE (%d) "
1110 "[longlba flag not supported?]\n",
1111 (op->mode6 ? 6 : 10));
1112 else
1113 pr2serr("bad field in MODE SENSE (%d) "
1114 "[mode_page %d not supported?]\n",
1115 (op->mode6 ? 6 : 10), op->mode_page);
1116 } else {
1117 sg_get_category_sense_str(res, sizeof(b), b, vb);
1118 pr2serr("MODE SENSE (%d) command: %s\n",
1119 (op->mode6 ? 6 : 10), b);
1120 }
1121 if (0 == vb)
1122 pr2serr(" try '-v' for more information\n");
1123 return res;
1124 }
1125 rsp_len = (resid > 0) ? (MAX_BUFF_SZ - resid) : MAX_BUFF_SZ;
1126 if (rsp_len < 0) {
1127 pr2serr("%s: resid=%d implies negative response "
1128 "length of %d\n", __func__, resid, rsp_len);
1129 return SG_LIB_WILD_RESID;
1130 }
1131 *calc_lenp = sg_msense_calc_length(dbuff, rsp_len, op->mode6, &bd_len);
1132 if (op->mode6) {
1133 if (rsp_len < 4) {
1134 pr2serr("%s: MS(6) response length too short (%d)\n",
1135 __func__, rsp_len);
1136 return SG_LIB_CAT_MALFORMED;
1137 }
1138 dev_specific_param = dbuff[2];
1139 op->long_lba = false;
1140 offset = 4;
1141 /* prepare for mode select */
1142 dbuff[0] = 0;
1143 dbuff[1] = 0;
1144 dbuff[2] = 0;
1145 } else { /* MODE SENSE(10) */
1146 if (rsp_len < 8) {
1147 pr2serr("%s: MS(10) response length too short (%d)\n",
1148 __func__, rsp_len);
1149 return SG_LIB_CAT_MALFORMED;
1150 }
1151 dev_specific_param = dbuff[3];
1152 op->long_lba = !! (dbuff[4] & 1);
1153 offset = 8;
1154 /* prepare for mode select */
1155 dbuff[0] = 0;
1156 dbuff[1] = 0;
1157 dbuff[2] = 0;
1158 dbuff[3] = 0;
1159 }
1160 if (rsp_len < *calc_lenp) {
1161 pr2serr("%s: MS response length truncated (%d < %d)\n",
1162 __func__, rsp_len, *calc_lenp);
1163 return SG_LIB_CAT_MALFORMED;
1164 }
1165 if ((offset + bd_len) < *calc_lenp)
1166 dbuff[offset + bd_len] &= 0x7f; /* clear PS bit in mpage */
1167 prob = false;
1168 bd_lbsz = 0;
1169 *bd_lb_szp = bd_lbsz;
1170 rq_lb_sz = op->lblk_sz;
1171 if (first) {
1172 first = false;
1173 printf("Mode Sense (block descriptor) data, prior to "
1174 "changes:\n");
1175 }
1176 if (dev_specific_param & 0x40)
1177 printf(" <<< Write Protect (WP) bit set >>>\n");
1178 if (bd_len > 0) {
1179 ull = op->long_lba ? sg_get_unaligned_be64(dbuff + offset) :
1180 sg_get_unaligned_be32(dbuff + offset);
1181 bd_lbsz = op->long_lba ?
1182 sg_get_unaligned_be32(dbuff + offset + 12) :
1183 sg_get_unaligned_be24(dbuff + offset + 5);
1184 *bd_lb_szp = bd_lbsz;
1185 if (! op->long_lba) {
1186 if (0xffffffff == ull) {
1187 if (vb)
1188 pr2serr("block count maxed out, set "
1189 "<<longlba>>\n");
1190 op->long_lba = true;
1191 op->mode6 = false;
1192 op->do_rcap16 = true;
1193 goto again_with_long_lba;
1194 } else if ((rq_lb_sz > 0) && (rq_lb_sz < bd_lbsz) &&
1195 (((ull * bd_lbsz) / rq_lb_sz) >=
1196 0xffffffff)) {
1197 if (vb)
1198 pr2serr("number of blocks will max "
1199 "out, set <<longlba>>\n");
1200 op->long_lba = true;
1201 op->mode6 = false;
1202 op->do_rcap16 = true;
1203 goto again_with_long_lba;
1204 }
1205 }
1206 if (op->long_lba) {
1207 printf(" <<< longlba flag set (64 bit lba) >>>\n");
1208 if (bd_len != 16)
1209 prob = true;
1210 } else if (bd_len != 8)
1211 prob = true;
1212 printf(" Number of blocks=%" PRIu64 " [0x%" PRIx64 "]\n",
1213 ull, ull);
1214 printf(" Block size=%d [0x%x]\n", bd_lbsz, bd_lbsz);
1215 ll = (int64_t)ull * bd_lbsz;
1216 if (ll > op->total_byte_count)
1217 op->total_byte_count = ll;
1218 } else {
1219 printf(" No block descriptors present\n");
1220 prob = true;
1221 }
1222 if (op->resize || (op->format && ((op->blk_count != 0) ||
1223 ((rq_lb_sz > 0) && (rq_lb_sz != bd_lbsz))))) {
1224 /* want to run MODE SELECT, prepare now */
1225
1226 if (prob) {
1227 pr2serr("Need to perform MODE SELECT (to change "
1228 "number or blocks or block length)\n");
1229 pr2serr("but (single) block descriptor not found "
1230 "in earlier MODE SENSE\n");
1231 return SG_LIB_CAT_MALFORMED;
1232 }
1233 if (op->blk_count != 0) { /* user supplied blk count */
1234 if (op->long_lba)
1235 sg_put_unaligned_be64(op->blk_count,
1236 dbuff + offset);
1237 else
1238 sg_put_unaligned_be32(op->blk_count,
1239 dbuff + offset);
1240 } else if ((rq_lb_sz > 0) && (rq_lb_sz != bd_lbsz))
1241 /* 0 implies max capacity with new LB size */
1242 memset(dbuff + offset, 0, op->long_lba ? 8 : 4);
1243
1244 if ((rq_lb_sz > 0) && (rq_lb_sz != bd_lbsz)) {
1245 if (op->long_lba)
1246 sg_put_unaligned_be32((uint32_t)rq_lb_sz,
1247 dbuff + offset + 12);
1248 else
1249 sg_put_unaligned_be24((uint32_t)rq_lb_sz,
1250 dbuff + offset + 5);
1251 }
1252 }
1253 return 0;
1254 }
1255
1256 static int
parse_cmd_line(struct opts_t * op,int argc,char ** argv)1257 parse_cmd_line(struct opts_t * op, int argc, char **argv)
1258 {
1259 int j;
1260 int64_t ll;
1261
1262 op->cmplst = true; /* will be set false if FFMT > 0 */
1263 op->mode_page = RW_ERROR_RECOVERY_PAGE;
1264 op->poll_type = DEF_POLL_TYPE_RS;
1265 op->tape = -1;
1266 while (1) {
1267 int option_index = 0;
1268 int c;
1269
1270 c = getopt_long(argc, argv,
1271 "bc:C:dDeE:f:FhIlm:M:pP:q:QrRs:St:T:vVwx:y6",
1272 long_options, &option_index);
1273 if (c == -1)
1274 break;
1275
1276 switch (c) {
1277 case 'b':
1278 op->fmtmaxlba = true;
1279 break;
1280 case 'c':
1281 if (0 == strcmp("-1", optarg))
1282 op->blk_count = -1;
1283 else {
1284 op->blk_count = sg_get_llnum(optarg);
1285 if (-1 == op->blk_count) {
1286 pr2serr("bad argument to '--count'\n");
1287 return SG_LIB_SYNTAX_ERROR;
1288 }
1289 }
1290 break;
1291 case 'C':
1292 j = sg_get_num(optarg);
1293 if ((j < 0) || (j > 1)) {
1294 pr2serr("bad argument to '--cmplst', want 0 "
1295 "or 1\n");
1296 return SG_LIB_SYNTAX_ERROR;
1297 }
1298 op->cmplst_given = true;
1299 op->cmplst = !! j;
1300 break;
1301 case 'd':
1302 op->dry_run = true;
1303 break;
1304 case 'D':
1305 ++op->dcrt;
1306 break;
1307 case 'e':
1308 op->early = true;
1309 break;
1310 case 'E':
1311 ll = sg_get_llnum(optarg);
1312 if ((ll < 0) || (ll > UINT32_MAX)) {
1313 pr2serr("bad argument to '--preset', need 32 "
1314 "bit integer\n");
1315 return SG_LIB_SYNTAX_ERROR;
1316 }
1317 op->p_id = (uint32_t)ll;
1318 op->preset = true;
1319 op->poll_type = 1; /* poll with REQUEST SENSE */
1320 break;
1321 case 'f':
1322 op->fmtpinfo = sg_get_num(optarg);
1323 if ((op->fmtpinfo < 0) || ( op->fmtpinfo > 3)) {
1324 pr2serr("bad argument to '--fmtpinfo', "
1325 "accepts 0 to 3 inclusive\n");
1326 return SG_LIB_SYNTAX_ERROR;
1327 }
1328 break;
1329 case 'F':
1330 ++op->format;
1331 break;
1332 case 'h':
1333 usage();
1334 return SG_LIB_OK_FALSE;
1335 case 'I':
1336 op->ip_def = true;
1337 break;
1338 case 'l':
1339 op->long_lba = true;
1340 op->do_rcap16 = true;
1341 break;
1342 case 'm':
1343 op->timeout = sg_get_num(optarg);
1344 if (op->timeout < 0) {
1345 pr2serr("bad argument to '--timeout=', "
1346 "accepts 0 or more\n");
1347 return SG_LIB_SYNTAX_ERROR;
1348 }
1349 break;
1350 case 'M':
1351 op->mode_page = sg_get_num(optarg);
1352 if ((op->mode_page < 0) || ( op->mode_page > 62)) {
1353 pr2serr("bad argument to '--mode', accepts "
1354 "0 to 62 inclusive\n");
1355 return SG_LIB_SYNTAX_ERROR;
1356 }
1357 break;
1358 case 'p':
1359 op->pinfo = true;
1360 break;
1361 case 'P':
1362 op->pfu = sg_get_num(optarg);
1363 if ((op->pfu < 0) || ( op->pfu > 7)) {
1364 pr2serr("bad argument to '--pfu', accepts 0 "
1365 "to 7 inclusive\n");
1366 return SG_LIB_SYNTAX_ERROR;
1367 }
1368 break;
1369 case 'q':
1370 op->pie = sg_get_num(optarg);
1371 if ((op->pie < 0) || (op->pie > 15)) {
1372 pr2serr("bad argument to '--pie', accepts 0 "
1373 "to 15 inclusive\n");
1374 return SG_LIB_SYNTAX_ERROR;
1375 }
1376 break;
1377 case 'Q':
1378 op->quick = true;
1379 break;
1380 case 'r':
1381 op->resize = true;
1382 break;
1383 case 'R':
1384 op->rto_req = true;
1385 break;
1386 case 's':
1387 op->lblk_sz = sg_get_num(optarg);
1388 if (op->lblk_sz <= 0) {
1389 pr2serr("bad argument to '--size', want arg "
1390 "> 0\n");
1391 return SG_LIB_SYNTAX_ERROR;
1392 }
1393 break;
1394 case 'S':
1395 op->sec_init = true;
1396 break;
1397 case 't':
1398 op->ffmt = sg_get_num(optarg);
1399 if ((op->ffmt < 0) || ( op->ffmt > 3)) {
1400 pr2serr("bad argument to '--ffmt', "
1401 "accepts 0 to 3 inclusive\n");
1402 return SG_LIB_SYNTAX_ERROR;
1403 }
1404 break;
1405 case 'T':
1406 if (('-' == optarg[0]) && ('1' == optarg[1]) &&
1407 ('\0' == optarg[2])) {
1408 op->tape = -1;
1409 break;
1410 }
1411 op->tape = sg_get_num(optarg);
1412 if ((op->tape < 0) || ( op->tape > 15)) {
1413 pr2serr("bad argument to '--tape', accepts "
1414 "0 to 15 inclusive\n");
1415 return SG_LIB_SYNTAX_ERROR;
1416 }
1417 break;
1418 case 'v':
1419 op->verbose_given = true;
1420 op->verbose++;
1421 break;
1422 case 'V':
1423 op->version_given = true;
1424 break;
1425 case 'w':
1426 op->fwait = true;
1427 break;
1428 case 'x': /* false: TUR; true: request sense */
1429 op->poll_type = !! sg_get_num(optarg);
1430 op->poll_type_given = true;
1431 break;
1432 case 'y':
1433 op->verify = true;
1434 break;
1435 case '6':
1436 op->mode6 = true;
1437 break;
1438 default:
1439 usage();
1440 return SG_LIB_SYNTAX_ERROR;
1441 }
1442 }
1443 if (optind < argc) {
1444 if (NULL == op->device_name) {
1445 op->device_name = argv[optind];
1446 ++optind;
1447 }
1448 }
1449 if (optind < argc) {
1450 for (; optind < argc; ++optind)
1451 pr2serr("Unexpected extra argument: %s\n",
1452 argv[optind]);
1453 usage();
1454 return SG_LIB_SYNTAX_ERROR;
1455 }
1456 #ifdef DEBUG
1457 pr2serr("In DEBUG mode, ");
1458 if (op->verbose_given && op->version_given) {
1459 pr2serr("but override: '-vV' given, zero verbose and "
1460 "continue\n");
1461 op->verbose_given = false;
1462 op->version_given = false;
1463 op->verbose = 0;
1464 } else if (! op->verbose_given) {
1465 pr2serr("set '-vv'\n");
1466 op->verbose = 2;
1467 } else
1468 pr2serr("keep verbose=%d\n", op->verbose);
1469 #else
1470 if (op->verbose_given && op->version_given)
1471 pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
1472 #endif
1473 if (op->version_given) {
1474 pr2serr("sg_format version: %s\n", version_str);
1475 return SG_LIB_OK_FALSE;
1476 }
1477 if (NULL == op->device_name) {
1478 pr2serr("no DEVICE name given\n\n");
1479 usage();
1480 return SG_LIB_SYNTAX_ERROR;
1481 }
1482 if (((int)(op->format > 0) + (int)(op->tape >= 0) + (int)op->preset)
1483 > 1) {
1484 pr2serr("Can choose only one of: '--format', '--tape=' and "
1485 "'--preset='\n");
1486 return SG_LIB_CONTRADICT;
1487 }
1488 if (op->ip_def && op->sec_init) {
1489 pr2serr("'--ip_def' and '--security' contradict, choose "
1490 "one\n");
1491 return SG_LIB_CONTRADICT;
1492 }
1493 if (op->resize) {
1494 if (op->format) {
1495 pr2serr("both '--format' and '--resize' not "
1496 "permitted\n");
1497 usage();
1498 return SG_LIB_CONTRADICT;
1499 } else if (0 == op->blk_count) {
1500 pr2serr("'--resize' needs a '--count' (other than "
1501 "0)\n");
1502 usage();
1503 return SG_LIB_CONTRADICT;
1504 } else if (0 != op->lblk_sz) {
1505 pr2serr("'--resize' not compatible with '--size'\n");
1506 usage();
1507 return SG_LIB_CONTRADICT;
1508 }
1509 }
1510 if ((op->pinfo > 0) || (op->rto_req > 0) || (op->fmtpinfo > 0)) {
1511 if ((op->pinfo || op->rto_req) && op->fmtpinfo) {
1512 pr2serr("confusing with both '--pinfo' or "
1513 "'--rto_req' together with\n'--fmtpinfo', "
1514 "best use '--fmtpinfo' only\n");
1515 usage();
1516 return SG_LIB_CONTRADICT;
1517 }
1518 if (op->pinfo)
1519 op->fmtpinfo |= 2;
1520 if (op->rto_req)
1521 op->fmtpinfo |= 1;
1522 }
1523 if ((op->ffmt > 0) && (! op->cmplst_given))
1524 op->cmplst = false; /* SBC-4 silent; FFMT&&CMPLST unlikely */
1525 return 0;
1526 }
1527
1528
1529 int
main(int argc,char ** argv)1530 main(int argc, char **argv)
1531 {
1532 int bd_lb_sz, calc_len, pdt, res, rq_lb_sz, vb;
1533 int fd = -1;
1534 int ret = 0;
1535 const int dbuff_sz = MAX_BUFF_SZ;
1536 const int inq_resp_sz = SAFE_STD_INQ_RESP_LEN;
1537 struct opts_t * op;
1538 uint8_t * dbuff;
1539 uint8_t * free_dbuff = NULL;
1540 uint8_t * inq_resp;
1541 uint8_t * free_inq_resp = NULL;
1542 struct opts_t opts;
1543 char b[80];
1544
1545 op = &opts;
1546 memset(op, 0, sizeof(opts));
1547 ret = parse_cmd_line(op, argc, argv);
1548 if (ret)
1549 return (SG_LIB_OK_FALSE == ret) ? 0 : ret;
1550 vb = op->verbose;
1551
1552 dbuff = sg_memalign(dbuff_sz, 0, &free_dbuff, false);
1553 inq_resp = sg_memalign(inq_resp_sz, 0, &free_inq_resp, false);
1554 if ((NULL == dbuff) || (NULL == inq_resp)) {
1555 pr2serr("Unable to allocate heap\n");
1556 ret = sg_convert_errno(ENOMEM);
1557 goto out;
1558 }
1559
1560 if ((fd = sg_cmds_open_device(op->device_name, false, vb)) < 0) {
1561 pr2serr("error opening device file: %s: %s\n",
1562 op->device_name, safe_strerror(-fd));
1563 ret = sg_convert_errno(-fd);
1564 goto out;
1565 }
1566
1567 if (op->format > 2)
1568 goto format_only;
1569
1570 ret = print_dev_id(fd, inq_resp, inq_resp_sz, op);
1571 if (ret) {
1572 if (op->dry_run) {
1573 pr2serr("INQUIRY failed, assume device is a disk\n");
1574 pdt = 0;
1575 } else
1576 goto out;
1577 } else
1578 pdt = PDT_MASK & inq_resp[0];
1579 if (op->format) {
1580 if ((PDT_DISK != pdt) && (PDT_OPTICAL != pdt) &&
1581 (PDT_RBC != pdt) && (PDT_ZBC != pdt)) {
1582 pr2serr("This format is only defined for disks "
1583 "(using SBC-2+, ZBC or RBC) and MO media\n");
1584 ret = SG_LIB_CAT_MALFORMED;
1585 goto out;
1586 }
1587 } else if (op->tape >= 0) {
1588 if (! ((PDT_TAPE == pdt) || (PDT_MCHANGER == pdt) ||
1589 (PDT_ADC == pdt))) {
1590 pr2serr("This format is only defined for tapes\n");
1591 ret = SG_LIB_CAT_MALFORMED;
1592 goto out;
1593 }
1594 goto format_med;
1595 } else if (op->preset)
1596 goto format_with_pre;
1597
1598 ret = fetch_block_desc(fd, dbuff, &calc_len, &bd_lb_sz, op);
1599 if (ret) {
1600 if (op->dry_run) {
1601 /* pick some numbers ... */
1602 calc_len = 1024 * 1024 * 1024;
1603 bd_lb_sz = 512;
1604 } else
1605 goto out;
1606 }
1607 rq_lb_sz = op->lblk_sz;
1608 if (op->resize || (op->format && ((op->blk_count != 0) ||
1609 ((rq_lb_sz > 0) && (rq_lb_sz != bd_lb_sz))))) {
1610 /* want to run MODE SELECT */
1611 if (op->dry_run) {
1612 pr2serr("Due to --dry-run option bypass MODE "
1613 "SELECT(%d) command\n", (op->mode6 ? 6 : 10));
1614 res = 0;
1615 } else {
1616 bool sp = true; /* may not be able to save pages */
1617
1618 again_sp_false:
1619 if (op->mode6)
1620 res = sg_ll_mode_select6(fd, true /* PF */,
1621 sp, dbuff, calc_len,
1622 true, vb);
1623 else
1624 res = sg_ll_mode_select10(fd, true /* PF */,
1625 sp, dbuff, calc_len,
1626 true, vb);
1627 if ((SG_LIB_CAT_ILLEGAL_REQ == res) && sp) {
1628 pr2serr("Try MODE SELECT again with SP=0 "
1629 "this time\n");
1630 sp = false;
1631 goto again_sp_false;
1632 }
1633 }
1634 ret = res;
1635 if (res) {
1636 sg_get_category_sense_str(res, sizeof(b), b, vb);
1637 pr2serr("MODE SELECT command: %s\n", b);
1638 if (0 == vb)
1639 pr2serr(" try '-v' for more information\n");
1640 goto out;
1641 }
1642 }
1643 if (op->resize) {
1644 printf("Resize operation seems to have been successful\n");
1645 goto out;
1646 } else if (! op->format) {
1647 res = print_read_cap(fd, op);
1648 if (-2 == res) {
1649 op->do_rcap16 = true;
1650 res = print_read_cap(fd, op);
1651 }
1652 if (res < 0)
1653 ret = -1;
1654 if ((res > 0) && (bd_lb_sz > 0) &&
1655 (res != (int)bd_lb_sz)) {
1656 printf(" Warning: mode sense and read capacity "
1657 "report different block sizes [%d,%d]\n",
1658 bd_lb_sz, res);
1659 printf(" Probably needs format\n");
1660 }
1661 if ((PDT_TAPE == pdt) || (PDT_MCHANGER == pdt) ||
1662 (PDT_ADC == pdt))
1663 printf("No changes made. To format use '--tape='.\n");
1664 else
1665 printf("No changes made. To format use '--format'. "
1666 "To resize use '--resize'\n");
1667 goto out;
1668 }
1669
1670 if (op->format) {
1671 format_only:
1672 if (! op->quick)
1673 sg_warn_and_wait("FORMAT UNIT", op->device_name, true);
1674 res = scsi_format_unit(fd, op);
1675 ret = res;
1676 if (res) {
1677 pr2serr("FORMAT UNIT failed\n");
1678 if (0 == vb)
1679 pr2serr(" try '-v' for more "
1680 "information\n");
1681 }
1682 }
1683 goto out;
1684
1685 format_med:
1686 if (! op->poll_type_given) /* SSC-5 specifies REQUEST SENSE polling */
1687 op->poll_type = true;
1688 if (! op->quick)
1689 sg_warn_and_wait("FORMAT MEDIUM", op->device_name, true);
1690 res = scsi_format_medium(fd, op);
1691 ret = res;
1692 if (res) {
1693 pr2serr("FORMAT MEDIUM failed\n");
1694 if (0 == vb)
1695 pr2serr(" try '-v' for more information\n");
1696 }
1697 goto out;
1698
1699 format_with_pre:
1700 if (! op->quick)
1701 sg_warn_and_wait("FORMAT WITH PRESET", op->device_name, true);
1702 res = scsi_format_with_preset(fd, op);
1703 ret = res;
1704 if (res) {
1705 pr2serr("FORMAT WITH PRESET failed\n");
1706 if (0 == vb)
1707 pr2serr(" try '-v' for more information\n");
1708 }
1709
1710 out:
1711 if (free_dbuff)
1712 free(free_dbuff);
1713 if (free_inq_resp)
1714 free(free_inq_resp);
1715 if (fd >= 0) {
1716 res = sg_cmds_close_device(fd);
1717 if (res < 0) {
1718 pr2serr("close error: %s\n", safe_strerror(-res));
1719 if (0 == ret)
1720 ret = sg_convert_errno(-res);
1721 }
1722 }
1723 if (0 == vb) {
1724 if (! sg_if_can2stderr("sg_format failed: ", ret))
1725 pr2serr("Some error occurred, try again with '-v' "
1726 "or '-vv' for more information\n");
1727 }
1728 return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
1729 }
1730