1 /*
2 * Copyright (c) 2017-2022 Douglas Gilbert.
3 * All rights reserved.
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the BSD_LICENSE file.
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * The utility can send six variants of the SCSI WRITE command: (normal)
10 * WRITE(16 or 32), WRITE ATOMIC(16 or 32), ORWRITE(16 or 32),
11 * WRITE SAME(16 or 32), WRITE SCATTERED (16 or 32) or WRITE
12 * STREAM(16 or 32).
13 */
14
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <ctype.h>
25 #include <sys/types.h> /* needed for lseek() */
26 #include <sys/stat.h>
27 #include <getopt.h>
28 #define __STDC_FORMAT_MACROS 1
29 #include <inttypes.h>
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #include "sg_lib.h"
35 #include "sg_pt.h"
36 #include "sg_cmds_basic.h"
37 #include "sg_cmds_extra.h"
38 #include "sg_unaligned.h"
39 #include "sg_pr2serr.h"
40
41 static const char * version_str = "1.31 20220217";
42
43 /* Protection Information refers to 8 bytes of extra information usually
44 * associated with each logical block and is often abbreviated to PI while
45 * its fields: reference-tag (4 bytes), application-tag (2 bytes) and
46 * tag-mask (2 bytes) are often abbreviated to RT, AT and TM respectively.
47 * And the LBA Range Descriptor associated with the WRITE SCATTERED command
48 * is abbreviated to RD. A degenerate RD is one where length components,
49 ( and perhaps the LBA, are zero; it is not illegal according to T10 but are
50 * a little tricky to handle when scanning and little extra information
51 * is provided. */
52
53 #define ORWRITE16_OP 0x8b
54 #define WRITE_16_OP 0x8a
55 #define WRITE_ATOMIC16_OP 0x9c
56 #define WRITE_SAME16_OP 0x93
57 #define SERVICE_ACTION_OUT_16_OP 0x9f /* WRITE SCATTERED (16) uses this */
58 #define WRITE_SCATTERED16_SA 0x12
59 #define WRITE_STREAM16_OP 0x9a
60 #define VARIABLE_LEN_OP 0x7f
61 #define ORWRITE32_SA 0xe
62 #define WRITE_32_SA 0xb
63 #define WRITE_ATOMIC32_SA 0xf
64 #define WRITE_SAME_SA 0xd
65 #define WRITE_SCATTERED32_SA 0x11
66 #define WRITE_STREAM32_SA 0x10
67 #define WRITE_X_16_LEN 16
68 #define WRITE_X_32_LEN 32
69 #define WRITE_X_32_ADD 0x18
70 #define RCAP10_RESP_LEN 8
71 #define RCAP16_RESP_LEN 32
72 #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
73 #define DEF_TIMEOUT_SECS 120 /* might need more for large NUM */
74 #define DEF_WR_NUMBLOCKS 0 /* do nothing; for safety */
75 #define DEF_RT 0xffffffff
76 #define DEF_AT 0xffff
77 #define DEF_TM 0xffff
78 #define EBUFF_SZ 256
79
80 #define MAX_NUM_ADDR 128
81
82 #ifndef UINT32_MAX
83 #define UINT32_MAX ((uint32_t)-1)
84 #endif
85 #ifndef UINT16_MAX
86 #define UINT16_MAX ((uint16_t)-1)
87 #endif
88
89 static struct option long_options[] = {
90 {"32", no_argument, 0, '3'},
91 {"16", no_argument, 0, '6'},
92 {"app-tag", required_argument, 0, 'a'},
93 {"app_tag", required_argument, 0, 'a'},
94 {"atomic", required_argument, 0, 'A'},
95 {"bmop", required_argument, 0, 'B'},
96 {"bs", required_argument, 0, 'b'},
97 {"combined", required_argument, 0, 'c'},
98 {"dld", required_argument, 0, 'D'},
99 {"dpo", no_argument, 0, 'd'},
100 {"dry-run", no_argument, 0, 'x'},
101 {"dry_run", no_argument, 0, 'x'},
102 {"fua", no_argument, 0, 'f'},
103 {"grpnum", required_argument, 0, 'g'},
104 {"generation", required_argument, 0, 'G'},
105 {"help", no_argument, 0, 'h'},
106 {"in", required_argument, 0, 'i'},
107 {"lba", required_argument, 0, 'l'},
108 {"normal", no_argument, 0, 'N'},
109 {"num", required_argument, 0, 'n'},
110 {"offset", required_argument, 0, 'o'},
111 {"or", no_argument, 0, 'O'},
112 {"quiet", no_argument, 0, 'Q'},
113 {"ref-tag", required_argument, 0, 'r'},
114 {"ref_tag", required_argument, 0, 'r'},
115 {"same", required_argument, 0, 'M'},
116 {"scat-file", required_argument, 0, 'q'},
117 {"scat_file", required_argument, 0, 'q'},
118 {"scat-raw", no_argument, 0, 'R'},
119 {"scat_raw", no_argument, 0, 'R'},
120 {"scattered", required_argument, 0, 'S'},
121 {"stream", required_argument, 0, 'T'},
122 {"strict", no_argument, 0, 's'},
123 {"tag-mask", required_argument, 0, 't'},
124 {"tag_mask", required_argument, 0, 't'},
125 {"timeout", required_argument, 0, 'I'},
126 {"unmap", required_argument, 0, 'u'},
127 {"verbose", no_argument, 0, 'v'},
128 {"version", no_argument, 0, 'V'},
129 {"wrprotect", required_argument, 0, 'w'},
130 {0, 0, 0, 0},
131 };
132
133 struct opts_t {
134 bool do_16; /* default when --32 not given */
135 bool do_32;
136 bool do_anchor; /* from --unmap=U_A , bit 1; WRITE SAME */
137 bool do_atomic; /* selects WRITE ATOMIC(16 or 32) */
138 /* --atomic=AB AB --> .atomic_boundary */
139 bool do_combined; /* -c DOF --> .scat_lbdof */
140 bool do_or; /* -O ORWRITE(16 or 32) */
141 bool do_quiet; /* -Q suppress some messages */
142 bool do_scat_raw;
143 bool do_same; /* -M WRITE SAME(16 or 32) */
144 /* --same=NDOB NDOB --> .ndob */
145 bool do_scattered; /* -S WRITE SCATTERED(16 or 32) */
146 /* --scattered=RD RD --> .scat_num_lbard */
147 bool do_stream; /* -T WRITE STREAM(16 or 32) */
148 /* --stream=ID ID --> .str_id */
149 bool do_unmap; /* from --unmap=U_A , bit 0; WRITE SAME */
150 bool do_write_normal; /* -N WRITE (16 or 32) */
151 bool expect_pi_do; /* expect protection information (PI) which
152 * is 8 bytes long following each logical
153 * block in the data out buffer. */
154 bool dpo; /* "Disable Page Out" bit field */
155 bool fua; /* "Force Unit Access" bit field */
156 bool ndob; /* "No Data-Out Buffer" from --same=NDOB */
157 bool verbose_given;
158 bool version_given;
159 int dld; /* "Duration Limit Descriptor" bit mask; bit 0 -->
160 * DLD0, bit 1 --> DLD1, bit 2 --> DLD2
161 * only WRITE(16) and WRITE SCATTERED(16) */
162 int dry_run; /* temporary write when used more than once */
163 int grpnum; /* "Group Number", 0 to 0x3f (GRPNUM_MASK) */
164 int help;
165 int pi_type; /* -1: unknown: 0: type 0 (none): 1: type 1 */
166 int strict; /* > 0, report then exit on questionable meta data */
167 int timeout; /* timeout (in seconds) to abort SCSI commands */
168 int verbose; /* incremented for each -v */
169 int wrprotect; /* is ORPROTECT field for ORWRITE */
170 uint8_t bmop; /* bit mask operators for ORWRITE(32) */
171 uint8_t pgp; /* previous generation processing for ORWRITE(32) */
172 uint16_t app_tag; /* part of protection information (def: 0xffff) */
173 uint16_t atomic_boundary; /* when 0 atomic write spans given length */
174 uint16_t scat_lbdof; /* by construction this must be >= 1 */
175 uint16_t scat_num_lbard; /* RD from --scattered=RD, number of LBA
176 * Range Descriptors */
177 uint16_t str_id; /* (stream ID) is for WRITE STREAM */
178 uint16_t tag_mask; /* part of protection information (def: 0xffff) */
179 uint32_t bs; /* logical block size (def: 0). 0 implies use READ
180 * CAPACITY(10 or 16) to determine */
181 uint32_t bs_pi_do; /* logical block size plus PI, if any. This value is
182 * used as the actual block size */
183 uint32_t if_dlen; /* bytes to read after .if_offset from .if_name,
184 * if 0 given, read rest of .if_name */
185 uint32_t numblocks; /* defaults to 0, number of blocks (of user data) to
186 * write */
187 uint32_t orw_eog; /* from --generation=EOG,NOG (first argument) */
188 uint32_t orw_nog; /* from --generation=EOG,NOG (for ORWRITE) */
189 uint32_t ref_tag; /* part of protection information (def: 0xffffffff) */
190 uint64_t lba; /* "Logical Block Address", for non-scattered use */
191 uint64_t if_offset; /* byte offset in .if_name to start reading */
192 uint64_t tot_lbs; /* from READ CAPACITY */
193 ssize_t xfer_bytes; /* derived value: bs_pi_do * numblocks */
194 /* for WRITE SCATTERED .xfer_bytes < do_len */
195 const char * device_name;
196 const char * if_name; /* from --in=IF */
197 const char * scat_filename; /* from --scat-file=SF */
198 const char * cmd_name; /* e.g. 'Write atomic' */
199 char cdb_name[24]; /* e.g. 'Write atomic(16)' */
200 };
201
202 static const char * xx_wr_fname = "sg_write_x.bin";
203 static const uint32_t lbard_sz = 32;
204 static const char * lbard_str = "LBA range descriptor";
205
206
207 static void
usage(int do_help)208 usage(int do_help)
209 {
210 if (do_help < 2) {
211 pr2serr("Usage:\n"
212 "sg_write_x [--16] [--32] [--app-tag=AT] [--atomic=AB] "
213 "[--bmop=OP,PGP]\n"
214 " [--bs=BS] [--combined=DOF] [--dld=DLD] [--dpo] "
215 "[--dry-run]\n"
216 " [--fua] [--generation=EOG,NOG] [--grpnum=GN] "
217 "[--help] --in=IF\n"
218 " [--lba=LBA,LBA...] [--normal] [--num=NUM,NUM...]\n"
219 " [--offset=OFF[,DLEN]] [--or] [--quiet] "
220 "[--ref-tag=RT]\n"
221 " [--same=NDOB] [--scat-file=SF] [--scat-raw] "
222 "[--scattered=RD]\n"
223 " [--stream=ID] [--strict] [--tag-mask=TM] "
224 "[--timeout=TO]\n"
225 " [--unmap=U_A] [--verbose] [--version] "
226 "[--wrprotect=WRP]\n"
227 " DEVICE\n");
228 if (1 != do_help) {
229 pr2serr("\nOr the corresponding short option usage:\n"
230 "sg_write_x [-6] [-3] [-a AT] [-A AB] [-B OP,PGP] [-b BS] "
231 "[-c DOF] [-D DLD]\n"
232 " [-d] [-x] [-f] [-G EOG,NOG] [-g GN] [-h] -i IF "
233 "[-l LBA,LBA...]\n"
234 " [-N] [-n NUM,NUM...] [-o OFF[,DLEN]] [-O] [-Q] "
235 "[-r RT] [-M NDOB]\n"
236 " [-q SF] [-R] [-S RD] [-T ID] [-s] [-t TM] [-I TO] "
237 "[-u U_A] [-v]\n"
238 " [-V] [-w WPR] DEVICE\n"
239 );
240 pr2serr("\nUse '-h' or '--help' for more help\n");
241 return;
242 }
243 pr2serr(" where:\n"
244 " --16|-6 send 16 byte cdb variant (this is "
245 "default action)\n"
246 " --32|-3 send 32 byte cdb variant of command "
247 "(def: 16 byte)\n"
248 " --app-tag=AT|-a AT expected application tag field "
249 "(def: 0xffff)\n"
250 " --atomic=AB|-A AB send WRITE ATOMIC command with AB "
251 "being its\n"
252 " Atomic Boundary field (0 to 0xffff)\n"
253 " --bmop=OP,PGP|-p OP,PGP set BMOP field to OP and "
254 " Previous\n"
255 " Generation Processing field "
256 "to PGP\n"
257 " --bs=BS|-b BS block size (def: use READ CAPACITY), "
258 "if power of\n"
259 " 2: logical block size, otherwise: "
260 "actual block size\n"
261 " --combined=DOF|-c DOF scatter list and data combined "
262 "for WRITE\n"
263 " SCATTERED, data starting at "
264 "offset DOF which\n"
265 " has units of sizeof(LB+PI); "
266 "sizeof(PI)=8n or 0\n"
267 " --dld=DLD|-D DLD set duration limit descriptor (dld) "
268 "bits (def: 0)\n"
269 " --dpo|-d set DPO (disable page out) field "
270 "(def: clear)\n"
271 " --dry-run|-x exit just before sending SCSI write "
272 "command\n"
273 " --fua|-f set FUA (force unit access) field "
274 "(def: clear)\n"
275 " --generation=EOG,NOG set Expected ORWgeneration field "
276 "to EOG\n"
277 " |-G EOG,NOG and New ORWgeneration field to "
278 "NOG\n"
279 );
280 pr2serr(
281 " --grpnum=GN|-g GN GN is group number field (def: 0, "
282 "range: 0 to 31)\n"
283 " --help|-h use multiple times for different "
284 "usage messages\n"
285 " --in=IF|-i IF IF is file to fetch NUM blocks of "
286 "data from.\n"
287 " Blocks written to DEVICE. 1 or no "
288 "blocks read\n"
289 " in the case of WRITE SAME\n"
290 " --lba=LBA,LBA... list of LBAs (Logical Block Addresses) "
291 "to start\n"
292 " |-l LBA,LBA... writes (def: --lba=0). Alternative is "
293 "--scat-file=SF\n"
294 " --normal|-N send 'normal' WRITE command (default "
295 "when no other\n"
296 " command option given)\n"
297 " --num=NUM,NUM... NUM is number of logical blocks to "
298 "write (def:\n"
299 " |-n NUM,NUM... --num=0). Number of block sent is "
300 "sum of NUMs\n"
301 " --offset=OFF[,DLEN] OFF is byte offset in IF to start "
302 "reading from\n"
303 " |-o OFF[,DLEN] (def: 0), then read DLEN bytes(def: "
304 "rest of IF)\n"
305 " --or|-O send ORWRITE command\n"
306 " --quiet|-Q suppress some informational messages\n"
307 " --ref-tag=RT|-r RT expected reference tag field (def: "
308 "0xffffffff)\n"
309 " --same=NDOB|-M NDOB send WRITE SAME command. NDOB (no "
310 "data out buffer)\n"
311 " can be either 0 (do send buffer) or "
312 "1 (don't)\n"
313 " --scat-file=SF|-q SF file containing LBA, NUM pairs, "
314 "see manpage\n"
315 " --scat-raw|-R read --scat_file=SF as binary (def: "
316 "ASCII hex)\n"
317 " --scattered=RD|-S RD send WRITE SCATTERED command with "
318 "RD range\n"
319 " descriptors (RD can be 0 when "
320 "--combined= given)\n"
321 " --stream=ID|-T ID send WRITE STREAM command with its "
322 "STR_ID\n"
323 " field set to ID\n"
324 " --strict|-s exit if read less than requested from "
325 "IF ;\n"
326 " require variety of WRITE to be given "
327 "as option\n"
328 " --tag-mask=TM|-t TM tag mask field (def: 0xffff)\n"
329 " --timeout=TO|-I TO command timeout (unit: seconds) "
330 "(def: 120)\n"
331 " --unmap=U_A|-u U_A 0 clears both UNMAP and ANCHOR bits "
332 "(default),\n"
333 " 1 sets UNMAP, 2 sets ANCHOR, 3 sets "
334 "both\n"
335 " --verbose|-v increase verbosity\n"
336 " --version|-V print version string then exit\n"
337 " --wrprotect=WPR|-w WPR WPR is the WRPROTECT field "
338 "value (def: 0)\n\n"
339 "Performs a SCSI WRITE (normal), ORWRITE, WRITE ATOMIC, WRITE "
340 "SAME, WRITE\nSCATTERED, or WRITE STREAM command. A 16 or 32 "
341 "byte cdb variant can be\nselected. The --in=IF option (data to "
342 "be written) is required apart from\nwhen --same=1 (i.e. when "
343 "NDOB is set). If no WRITE variant option is given\nthen, in "
344 "the absence of --strict, a (normal) WRITE is performed. Only "
345 "WRITE\nSCATTERED uses multiple LBAs and NUMs, or a SF file "
346 "with multiple pairs.\nThe --num=NUM field defaults to 0 (do "
347 "nothing) for safety. Using '-h'\nmultiple times shows the "
348 "applicable options for each command variant.\n"
349 );
350 } else if (2 == do_help) {
351 printf("WRITE ATOMIC (16 or 32) applicable options:\n"
352 " sg_write_x --atomic=AB --in=IF [--16] [--32] [--app-tag=AT] "
353 "[--bs=BS]\n"
354 " [--dpo] [--fua] [--grpnum=GN] [--lba=LBA] "
355 "[--num=NUM]\n"
356 " [--offset=OFF[,DLEN]] [--ref-tag=RT] [--strict] "
357 "[--tag-mask=TM]\n"
358 " [--timeout=TO] [--wrprotect=WRP] DEVICE\n"
359 "\n"
360 "normal WRITE (32) applicable options:\n"
361 " sg_write_x --normal --in=IF --32 [--app-tag=AT] [--bs=BS] "
362 "[--dpo] [--fua]\n"
363 " [--grpnum=GN] [--lba=LBA] [--num=NUM] "
364 "[--offset=OFF[,DLEN]]\n"
365 " [--ref-tag=RT] [--strict] [--tag-mask=TM] "
366 "[--timeout=TO]\n"
367 " [--wrprotect=WRP] DEVICE\n"
368 "\n"
369 "normal WRITE (16) applicable options:\n"
370 " sg_write_x --normal --in=IF [--16] [--bs=BS] [--dld=DLD] "
371 "[--dpo] [--fua]\n"
372 " [--grpnum=GN] [--lba=LBA] [--num=NUM] "
373 "[--offset=OFF[,DLEN]]\n"
374 " [--strict] [--timeout=TO] [--verbose] "
375 "[--wrprotect=WRP] DEVICE\n"
376 "\n"
377 "ORWRITE (32) applicable options:\n"
378 " sg_write_x --or --in=IF --32 [--bmop=OP,PGP] [--bs=BS] "
379 "[--dpo] [--fua]\n"
380 " [--generation=EOG,NOG] [--grpnum=GN] [--lba=LBA] "
381 "[--num=NUM]\n"
382 " [--offset=OFF{,DLEN]] [--strict] [--timeout=TO]\n"
383 " [--wrprotect=ORP] DEVICE\n"
384 "\n"
385 "ORWRITE (16) applicable options:\n"
386 " sg_write_x --or --in=IF [--16] [--bs=BS] [--dpo] [--fua] "
387 "[--grpnum=GN]\n"
388 " [--lba=LBA] [--num=NUM] [--offset=OFF[,DLEN]] "
389 "[--strict]\n"
390 " [--timeout=TO] [--wrprotect=ORP] DEVICE\n"
391 "\n"
392 );
393 } else if (3 == do_help) {
394 printf("WRITE SAME (32) applicable options:\n"
395 " sg_write_x --same=NDOB --32 [--app-tag=AT] [--bs=BS] "
396 "[--grpnum=GN]\n"
397 " [--in=IF] [--lba=LBA] [--num=NUM] "
398 "[--offset=OFF[,DLEN]]\n"
399 " [--ref-tag=RT] [--strict] [--tag-mask=TM] "
400 "[--timeout=TO]\n"
401 " [--unmap=U_A] [--wrprotect=WRP] DEVICE\n"
402 "\n"
403 "WRITE SCATTERED (32) applicable options:\n"
404 " sg_write_x --scattered --in=IF --32 [--app-tag=AT] "
405 "[--bs=BS]\n"
406 " [--combined=DOF] [--dpo] [--fua] [--grpnum=GN]\n"
407 " [--lba=LBA,LBA...] [--num=NUM,NUM...] "
408 "[--offset=OFF[,DLEN]]\n"
409 " [--ref-tag=RT] [--scat-file=SF] [--scat-raw] "
410 "[--strict]\n"
411 " [--tag-mask=TM] [--timeout=TO] [--wrprotect=WRP] "
412 "DEVICE\n"
413 "\n"
414 "WRITE SCATTERED (16) applicable options:\n"
415 " sg_write_x --scattered --in=IF [--bs=BS] [--combined=DOF] "
416 "[--dld=DLD]\n"
417 " [--dpo] [--fua] [--grpnum=GN] [--lba=LBA,LBA...]\n"
418 " [--num=NUM,NUM...] [--offset=OFF[,DLEN]] "
419 "[--scat-raw]\n"
420 " [--scat-file=SF] [--strict] [--timeout=TO] "
421 "[--wrprotect=WRP]\n"
422 " DEVICE\n"
423 "\n"
424 "WRITE STREAM (32) applicable options:\n"
425 " sg_write_x --stream=ID --in=IF --32 [--app-tag=AT] "
426 "[--bs=BS] [--dpo]\n"
427 " [--fua] [--grpnum=GN] [--lba=LBA] [--num=NUM]\n"
428 " [--offset=OFF[,DLEN]] [--ref-tag=RT] [--strict] "
429 "[--tag-mask=TM]\n"
430 " [--timeout=TO] [--verbose] [--wrprotect=WRP] "
431 "DEVICE\n"
432 "\n"
433 "WRITE STREAM (16) applicable options:\n"
434 " sg_write_x --stream=ID --in=IF [--16] [--bs=BS] [--dpo] "
435 "[--fua]\n"
436 " [--grpnum=GN] [--lba=LBA] [--num=NUM] "
437 "[--offset=OFF[,DLEN]]\n"
438 " [--strict] [--timeout=TO] [--wrprotect=WRP] "
439 "DEVICE\n"
440 "\n"
441 );
442 } else {
443 printf("Notes:\n"
444 " - all 32 byte cdb variants, apart from ORWRITE(32), need type "
445 "1, 2, or 3\n"
446 " protection information active on the DEVICE\n"
447 " - all commands can take one or more --verbose (-v) options "
448 "and/or the\n"
449 " --dry-run option\n"
450 " - all WRITE X commands will accept --scat-file=SF and "
451 "optionally --scat-raw\n"
452 " options but only the first lba,num pair is used (any "
453 "more are ignored)\n"
454 " - when '--rscat-aw --scat-file=SF' are used then the binary "
455 "format expected in\n"
456 " SF is as defined for the WRITE SCATTERED commands. "
457 "That is 32 bytes\n"
458 " of zeros followed by the first LBA range descriptor "
459 "followed by the\n"
460 " second LBA range descriptor, etc. Each LBA range "
461 "descriptor is 32 bytes\n"
462 " long with an 8 byte LBA at offset 0 and a 4 byte "
463 "number_of_logical_\n"
464 " blocks at offset 8 (both big endian). The 'pad' following "
465 "the last LBA\n"
466 " range descriptor does not need to be given\n"
467 " - WRITE SCATTERED(32) additionally has expected initial "
468 "LB reference tag,\n"
469 " application tag and LB application tag mask fields in the "
470 "LBA range\n"
471 " descriptor. If --strict is given then all reserved fields "
472 "are checked\n"
473 " for zeros, an error is generated for non zero bytes.\n"
474 " - when '--lba=LBA,LBA...' is used on commands other than "
475 "WRITE SCATTERED\n"
476 " then only the first LBA value is used.\n"
477 " - when '--num=NUM,NUM...' is used on commands other than "
478 "WRITE SCATTERED\n"
479 " then only the first NUM value is used.\n"
480 " - whenever '--lba=LBA,LBA...' is used then "
481 "'--num=NUM,NUM...' should\n"
482 " also be used. Also they should have the same number of "
483 "elements.\n"
484 );
485 }
486 }
487
488 /* Returns 0 if successful, else sg3_utils error code. */
489 static int
bin_read(int fd,uint8_t * up,uint32_t len,const char * fname)490 bin_read(int fd, uint8_t * up, uint32_t len, const char * fname)
491 {
492 int res, err;
493
494 res = read(fd, up, len);
495 if (res < 0) {
496 err = errno;
497 pr2serr("Error doing read of %s file: %s\n", fname,
498 safe_strerror(err));
499 return sg_convert_errno(err);
500 }
501 if ((uint32_t)res < len) {
502 pr2serr("Short (%u) read of %s file, wanted %u\n", (unsigned int)res,
503 fname, len);
504 return SG_LIB_FILE_ERROR;
505 }
506 return 0;
507 }
508
509 /* Returns true if num_of_f_chars of ASCII 'f' or 'F' characters are found
510 * in sequence. Any leading "0x" or "0X" is ignored; otherwise false is
511 * returned (and the comparison stops when the first mismatch is found).
512 * For example a sequence of 'f' characters in a null terminated C string
513 * that is two characters shorter than the requested num_of_f_chars will
514 * compare the null character in the string with 'f', find them unequal,
515 * stop comparing and return false. */
516 static bool
all_ascii_f_s(const char * cp,int num_of_f_chars)517 all_ascii_f_s(const char * cp, int num_of_f_chars)
518 {
519 if ((NULL == cp) || (num_of_f_chars < 1))
520 return false; /* define degenerate cases */
521 if (('0' == cp[0]) && (('x' == cp[1]) || ('X' == cp[1])))
522 cp += 2;
523 for ( ; num_of_f_chars >= 0 ; --num_of_f_chars, ++cp) {
524 if ('F' != toupper((uint8_t)*cp))
525 return false;
526 }
527 return true;
528 }
529
530 /* Read numbers (up to 64 bits in size) from command line (comma (or
531 * (single) space) separated list). Assumed decimal unless prefixed
532 * by '0x', '0X' or contains trailing 'h' or 'H' (which indicate hex).
533 * Returns 0 if ok, or 1 if error. */
534 static int
build_lba_arr(const char * inp,uint64_t * lba_arr,uint32_t * lba_arr_len,int max_arr_len)535 build_lba_arr(const char * inp, uint64_t * lba_arr, uint32_t * lba_arr_len,
536 int max_arr_len)
537 {
538 int in_len, k;
539 int64_t ll;
540 const char * lcp;
541 char * cp;
542 char * c2p;
543
544 if ((NULL == inp) || (NULL == lba_arr) ||
545 (NULL == lba_arr_len))
546 return 1;
547 lcp = inp;
548 in_len = strlen(inp);
549 if (0 == in_len)
550 *lba_arr_len = 0;
551 if ('-' == inp[0]) { /* read from stdin */
552 pr2serr("'--lba' cannot be read from stdin\n");
553 return 1;
554 } else { /* list of numbers (default decimal) on command line */
555 k = strspn(inp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP, ");
556 if (in_len != k) {
557 pr2serr("build_lba_arr: error at pos %d\n", k + 1);
558 return 1;
559 }
560 for (k = 0; k < max_arr_len; ++k) {
561 ll = sg_get_llnum(lcp);
562 if (-1 != ll) {
563 lba_arr[k] = (uint64_t)ll;
564 cp = (char *)strchr(lcp, ',');
565 c2p = (char *)strchr(lcp, ' ');
566 if (NULL == cp)
567 cp = c2p;
568 if (NULL == cp)
569 break;
570 if (c2p && (c2p < cp))
571 cp = c2p;
572 lcp = cp + 1;
573 } else {
574 pr2serr("build_lba_arr: error at pos %d\n",
575 (int)(lcp - inp + 1));
576 return 1;
577 }
578 }
579 *lba_arr_len = (uint32_t)(k + 1);
580 if (k == max_arr_len) {
581 pr2serr("build_lba_arr: array length exceeded\n");
582 return 1;
583 }
584 }
585 return 0;
586 }
587
588 /* Read numbers (up to 32 bits in size) from command line (comma (or
589 * (single) space) separated list). Assumed decimal unless prefixed
590 * by '0x', '0X' or contains trailing 'h' or 'H' (which indicate hex).
591 * Returns 0 if ok, else a sg3_utils error code is returned. */
592 static int
build_num_arr(const char * inp,uint32_t * num_arr,uint32_t * num_arr_len,int max_arr_len)593 build_num_arr(const char * inp, uint32_t * num_arr, uint32_t * num_arr_len,
594 int max_arr_len)
595 {
596 int in_len, k;
597 const char * lcp;
598 int64_t ll;
599 char * cp;
600 char * c2p;
601
602 if ((NULL == inp) || (NULL == num_arr) ||
603 (NULL == num_arr_len))
604 return SG_LIB_LOGIC_ERROR;
605 lcp = inp;
606 in_len = strlen(inp);
607 if (0 == in_len)
608 *num_arr_len = 0;
609 if ('-' == inp[0]) { /* read from stdin */
610 pr2serr("'--len' cannot be read from stdin\n");
611 return SG_LIB_SYNTAX_ERROR;
612 } else { /* list of numbers (default decimal) on command line */
613 k = strspn(inp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP, ");
614 if (in_len != k) {
615 pr2serr("%s: error at pos %d\n", __func__, k + 1);
616 return SG_LIB_SYNTAX_ERROR;
617 }
618 for (k = 0; k < max_arr_len; ++k) {
619 ll = sg_get_llnum(lcp);
620 if (-1 != ll) {
621 if (ll > UINT32_MAX) {
622 pr2serr("%s: number exceeds 32 bits at pos %d\n",
623 __func__, (int)(lcp - inp + 1));
624 return SG_LIB_SYNTAX_ERROR;
625 }
626 num_arr[k] = (uint32_t)ll;
627 cp = (char *)strchr(lcp, ',');
628 c2p = (char *)strchr(lcp, ' ');
629 if (NULL == cp)
630 cp = c2p;
631 if (NULL == cp)
632 break;
633 if (c2p && (c2p < cp))
634 cp = c2p;
635 lcp = cp + 1;
636 } else {
637 pr2serr("%s: error at pos %d\n", __func__,
638 (int)(lcp - inp + 1));
639 return SG_LIB_SYNTAX_ERROR;
640 }
641 }
642 *num_arr_len = (uint32_t)(k + 1);
643 if (k == max_arr_len) {
644 pr2serr("%s: array length exceeded\n", __func__);
645 return SG_LIB_SYNTAX_ERROR;
646 }
647 }
648 return 0;
649 }
650
651 /* Tries to parse LBA,NUM[,RT,AP,TM] on one line, comma separated. Returns
652 * 0 if parsed ok, else 999 if nothing parsed, else error (currently always
653 * SG_LIB_SYNTAX_ERROR). If protection information fields not given, then
654 * default values are given (i.e. all 0xff bytes). Ignores all spaces and
655 * tabs and everything after '#' on lcp (assumed to be an ASCII line that
656 * is null terminated). If successful and 'up' is non NULL then writes a
657 * LBA range descriptor starting at 'up'. */
658 static int
parse_scat_pi_line(const char * lcp,uint8_t * up,uint32_t * sum_num)659 parse_scat_pi_line(const char * lcp, uint8_t * up, uint32_t * sum_num)
660 {
661 bool ok;
662 int k;
663 int64_t ll;
664 const char * cp;
665 const char * bp;
666 char c[1024];
667
668 bp = c;
669 cp = strchr(lcp, '#');
670 lcp += strspn(lcp, " \t");
671 if (('\0' == *lcp) || (cp && (lcp >= cp)))
672 return 999; /* blank line or blank prior to first '#' */
673 if (cp) { /* copy from first non whitespace ... */
674 memcpy(c, lcp, cp - lcp); /* ... to just prior to first '#' */
675 c[cp - lcp] = '\0';
676 } else {
677 /* ... to end of line, including null */
678 snprintf(c, sizeof(c), "%s", lcp);
679 }
680 ll = sg_get_llnum(bp);
681 ok = ((-1 != ll) || all_ascii_f_s(bp, 16));
682 if (! ok) {
683 pr2serr("%s: error reading LBA (first) item on ", __func__);
684 return SG_LIB_SYNTAX_ERROR;
685 }
686 if (up)
687 sg_put_unaligned_be64((uint64_t)ll, up + 0);
688 ok = false;
689 cp = strchr(bp, ',');
690 if (cp) {
691 bp = cp + 1;
692 if (*bp) {
693 ll = sg_get_llnum(bp);
694 if (-1 != ll)
695 ok = true;
696 }
697 }
698 if ((! ok) || (ll > UINT32_MAX)) {
699 pr2serr("%s: error reading NUM (second) item on ", __func__);
700 return SG_LIB_SYNTAX_ERROR;
701 }
702 if (up)
703 sg_put_unaligned_be32((uint32_t)ll, up + 8);
704 if (sum_num)
705 *sum_num += (uint32_t)ll;
706 /* now for 3 PI items */
707 for (k = 0; k < 3; ++k) {
708 ok = true;
709 cp = strchr(bp, ',');
710 if (NULL == cp)
711 break;
712 bp = cp + 1;
713 if (*bp) {
714 cp += strspn(bp, " \t");
715 if ('\0' == *cp)
716 break;
717 else if (',' == *cp) {
718 if (0 == k)
719 ll = DEF_RT;
720 else
721 ll = DEF_AT; /* DEF_AT and DEF_TM have same value */
722 } else {
723 ll = sg_get_llnum(bp);
724 if (-1 == ll)
725 ok = false;
726 }
727 }
728 if (! ok) {
729 pr2serr("%s: error reading item %d NUM item on ", __func__,
730 k + 3);
731 break;
732 }
733 switch (k) {
734 case 0:
735 if (ll > UINT32_MAX) {
736 pr2serr("%s: error with item 3, >0xffffffff; on ", __func__);
737 ok = false;
738 } else if (up)
739 sg_put_unaligned_be32((uint32_t)ll, up + 12);
740 break;
741 case 1:
742 if (ll > UINT16_MAX) {
743 pr2serr("%s: error with item 4, >0xffff; on ", __func__);
744 ok = false;
745 } else if (up)
746 sg_put_unaligned_be16((uint16_t)ll, up + 16);
747 break;
748 case 2:
749 if (ll > UINT16_MAX) {
750 pr2serr("%s: error with item 5, >0xffff; on ", __func__);
751 ok = false;
752 } else if (up)
753 sg_put_unaligned_be16((uint16_t)ll, up + 18);
754 break;
755 }
756 if (! ok)
757 break;
758 }
759 if (! ok)
760 return SG_LIB_SYNTAX_ERROR;
761 for ( ; k < 3; ++k) {
762 switch (k) {
763 case 0:
764 if (up)
765 sg_put_unaligned_be32((uint32_t)DEF_RT, up + 12);
766 break;
767 case 1:
768 if (up)
769 sg_put_unaligned_be16((uint16_t)DEF_AT, up + 16);
770 break;
771 case 2:
772 if (up)
773 sg_put_unaligned_be16((uint16_t)DEF_TM, up + 18);
774 break;
775 }
776 }
777 return 0;
778 }
779
780 /* Read pairs or quintets from a scat_file and places them in a T10 scatter
781 * list array is built starting at at t10_scat_list_out (i.e. as per T10 the
782 * first 32 bytes are zeros followed by the first LBA range descriptor (also
783 * 32 bytes long) then the second LBA range descriptor, etc. The pointer
784 * t10_scat_list_out may be NULL in which case the T10 list array is not
785 * built but all other operations take place; this can be useful for sizing
786 * how large the area holding that list needs to be. The max_list_blen may
787 * also be 0. If do_16 is true then only LBA,NUM pairs are expected,
788 * loosely formatted with numbers found alternating between LBA and NUM, with
789 * an even number of elements required overall. If do_16 is false then a
790 * stricter format for quintets is expected: each non comment line should
791 * contain: LBA,NUM[,RT,AT,TM] . If RT,AT,TM are not given then they assume
792 * their defaults (i.e. 0xffffffff, 0xffff, 0xffff). Each number (64 bits for
793 * the LBA, 32 bits for NUM and RT, 16 bit for AT and TM) may be a comma,
794 * space or tab separated list. Assumed decimal unless prefixed by '0x', '0X'
795 * or contains trailing 'h' or 'H' (which indicate hex). Returns 0 if ok,
796 * else error number. If ok also yields the number of LBA range descriptors
797 * written in num_scat_elems and the sum of NUM elements found. Note that
798 * sum_num is not initialized to 0. If parse_one is true then exits
799 * after one LBA range descriptor is decoded. */
800 static int
build_t10_scat(const char * scat_fname,bool do_16,bool parse_one,uint8_t * t10_scat_list_out,uint16_t * num_scat_elems,uint32_t * sum_num,uint32_t max_list_blen)801 build_t10_scat(const char * scat_fname, bool do_16, bool parse_one,
802 uint8_t * t10_scat_list_out, uint16_t * num_scat_elems,
803 uint32_t * sum_num, uint32_t max_list_blen)
804 {
805 bool have_stdin = false;
806 bool del_fp = false;
807 bool bit0, ok;
808 int off = 0;
809 int in_len, k, j, m, n, res, err;
810 int64_t ll;
811 char * lcp;
812 uint8_t * up = t10_scat_list_out;
813 FILE * fp = NULL;
814 char line[1024];
815
816 if (up) {
817 if (max_list_blen < 64) {
818 pr2serr("%s: t10_scat_list_out is too short\n", __func__);
819 return SG_LIB_SYNTAX_ERROR;
820 }
821 memset(up, 0, max_list_blen);
822 }
823 n = lbard_sz;
824
825 have_stdin = ((1 == strlen(scat_fname)) && ('-' == scat_fname[0]));
826 if (have_stdin) {
827 fp = stdin;
828 scat_fname = "<stdin>";
829 } else {
830 fp = fopen(scat_fname, "r");
831 if (NULL == fp) {
832 err = errno;
833 pr2serr("%s: unable to open %s: %s\n", __func__, scat_fname,
834 safe_strerror(err));
835 return sg_convert_errno(err);
836 }
837 del_fp = true;
838 }
839 for (j = 0; j < 1024; ++j) {/* loop over lines in file */
840 if ((max_list_blen > 0) && ((n + lbard_sz) > max_list_blen))
841 goto fini;
842 if (NULL == fgets(line, sizeof(line), fp))
843 break;
844 // could improve with carry_over logic if sizeof(line) too small
845 in_len = strlen(line);
846 if (in_len > 0) {
847 if ('\n' == line[in_len - 1]) {
848 --in_len;
849 line[in_len] = '\0';
850 }
851 }
852 if (in_len < 1)
853 continue;
854 lcp = line;
855 m = strspn(lcp, " \t");
856 if (m == in_len)
857 continue;
858 lcp += m;
859 in_len -= m;
860 if ('#' == *lcp) /* Comment? If so skip rest of line */
861 continue;
862 k = strspn(lcp, "0123456789aAbBcCdDeEfFhHxXiIkKmMgGtTpP ,\t");
863 if ((k < in_len) && ('#' != lcp[k])) {
864 pr2serr("%s: syntax error in %s at line %d, pos %d\n",
865 __func__, scat_fname, j + 1, m + k + 1);
866 goto bad_exit;
867 }
868 if (! do_16) {
869 res = parse_scat_pi_line(lcp, up ? (up + n) : up, sum_num);
870 if (999 == res)
871 ;
872 else if (0 == res) {
873 n += lbard_sz;
874 if (parse_one)
875 goto fini;
876 } else {
877 if (SG_LIB_CAT_NOT_READY == res)
878 goto bad_mem_exit;
879 pr2serr("line %d in %s\n", j + 1, scat_fname);
880 goto bad_exit;
881 }
882 continue;
883 }
884 for (k = 0; k < 1024; ++k) {
885 ll = sg_get_llnum(lcp);
886 ok = ((-1 != ll) || all_ascii_f_s(lcp, 16));
887 if (ok) {
888 bit0 = !! (0x1 & (off + k));
889 if (bit0) {
890 if (ll > UINT32_MAX) {
891 pr2serr("%s: number exceeds 32 bits in line %d, at "
892 "pos %d of %s\n", __func__, j + 1,
893 (int)(lcp - line + 1), scat_fname);
894 goto bad_exit;
895 }
896 if (up)
897 sg_put_unaligned_be32((uint32_t)ll, up + n + 8);
898 if (sum_num)
899 *sum_num += (uint32_t)ll;
900 n += lbard_sz; /* skip to next LBA range descriptor */
901 if (parse_one)
902 goto fini;
903 } else {
904 if (up)
905 sg_put_unaligned_be64((uint64_t)ll, up + n + 0);
906 }
907 lcp = strpbrk(lcp, " ,\t");
908 if (NULL == lcp)
909 break;
910 lcp += strspn(lcp, " ,\t");
911 if ('\0' == *lcp)
912 break;
913 } else { /* no valid number found */
914 if ('#' == *lcp) {
915 --k;
916 break;
917 }
918 pr2serr("%s: error on line %d, at pos %d\n", __func__, j + 1,
919 (int)(lcp - line + 1));
920 goto bad_exit;
921 }
922 } /* inner for loop(k) over line elements */
923 off += (k + 1);
924 } /* outer for loop(j) over lines */
925 if (do_16 && (0x1 & off)) {
926 pr2serr("%s: expect LBA,NUM pairs but decoded odd number\n from "
927 "%s\n", __func__, scat_fname);
928 goto bad_exit;
929 }
930 fini:
931 *num_scat_elems = (n / lbard_sz) - 1;
932 if (del_fp)
933 fclose(fp);
934 return 0;
935 bad_exit:
936 if (del_fp)
937 fclose(fp);
938 return SG_LIB_SYNTAX_ERROR;
939 bad_mem_exit:
940 if (del_fp)
941 fclose(fp);
942 return SG_LIB_CAT_NOT_READY; /* flag output buffer too small */
943 }
944
945 static bool
is_pi_default(const struct opts_t * op)946 is_pi_default(const struct opts_t * op)
947 {
948 return ((DEF_AT == op->app_tag) && (DEF_RT == op->ref_tag) &&
949 (DEF_TM == op->tag_mask));
950 }
951
952 /* Given a t10 parameter list header (32 zero bytes) for WRITE SCATTERED
953 * (16 or 32) followed by n RDs with a total length of at least
954 * max_lbrds_blen bytes, find "n" and increment where num_lbard points
955 * n times. Further get the LBA length component from each RD and add each
956 * length into where sum_num points. Note: the caller probably wants to zero
957 * where num_lbard and sum_num point before invoking this function. If all
958 * goes well return true, else false. If a degenerate RD is detected then
959 * if 'RD' (from --scattered=RD) is 0 then stop looking for further RDs;
960 * otherwise keep going. Currently overlapping LBA range descriptors are no
961 * checked for. If op->strict > 0 then the first 32 bytes are checked for
962 * zeros; any non-zero bytes will report to stderr, stop the check and
963 * return false. If op->strict > 0 then the trailing 20 or 12 bytes (only
964 * 12 if RT, AT and TM fields (for PI) are present) are checked for zeros;
965 * any non-zero bytes cause the same action as the previous check. If
966 * the number of RDs (when 'RD' from --scattered=RD > 0) is greater than
967 * the number of RDs found then a report is sent to stderr and if op->strict
968 * > 0 then returns false, else returns true. */
969 static bool
check_lbrds(const uint8_t * up,uint32_t max_lbrds_blen,const struct opts_t * op,uint16_t * num_lbard,uint32_t * sum_num)970 check_lbrds(const uint8_t * up, uint32_t max_lbrds_blen,
971 const struct opts_t * op, uint16_t * num_lbard,
972 uint32_t * sum_num)
973 {
974 bool ok;
975 int k, j, n;
976 const int max_lbrd_start = max_lbrds_blen - lbard_sz;
977 int vb = op->verbose;
978
979 if (op->strict) {
980 if (max_lbrds_blen < lbard_sz) {
981 pr2serr("%s: %ss too short (%d < 32)\n", __func__, lbard_str,
982 max_lbrds_blen);
983 return false;
984 }
985 if (! sg_all_zeros(up, lbard_sz)) {
986 pr2serr("%s: first 32 bytes of WRITE SCATTERED data-out buffer "
987 "should be zero.\nFound non-zero byte.\n", __func__);
988 return false;
989 }
990 }
991 if (max_lbrds_blen < (2 * lbard_sz)) {
992 *num_lbard = 0;
993 return true;
994 }
995 n = op->scat_num_lbard ? (int)op->scat_num_lbard : -1;
996 for (k = lbard_sz, j = 0; k < max_lbrd_start; k += lbard_sz, ++j) {
997 if ((n < 0) && sg_all_zeros(up + k + 0, 12)) { /* degenerate LBA */
998 if (vb) /* ... range descriptor terminator if --scattered=0 */
999 pr2serr("%s: degenerate %s stops scan at k=%d (num_rds=%d)\n",
1000 __func__, lbard_str, k, j);
1001 break;
1002 }
1003 *sum_num += sg_get_unaligned_be32(up + k + 8);
1004 *num_lbard += 1;
1005 if (op->strict) {
1006 ok = true;
1007 if (op->wrprotect) {
1008 if (! sg_all_zeros(up + k + 20, 12))
1009 ok = false;
1010 } else if (! sg_all_zeros(up + k + 12, 20))
1011 ok = false;
1012 if (! ok) {
1013 pr2serr("%s: %s %d non zero in reserved fields\n", __func__,
1014 lbard_str, (k / lbard_sz) - 1);
1015 return false;
1016 }
1017 }
1018 if (n >= 0) {
1019 if (--n <= 0)
1020 break;
1021 }
1022 }
1023 if ((k < max_lbrd_start) && op->strict) { /* check pad all zeros */
1024 k += lbard_sz;
1025 j = max_lbrds_blen - k;
1026 if (! sg_all_zeros(up + k, j)) {
1027 pr2serr("%s: pad (%d bytes) following %ss is non zero\n",
1028 __func__, j, lbard_str);
1029 return false;
1030 }
1031 }
1032 if (vb > 2)
1033 pr2serr("%s: about to return true, num_lbard=%u, sum_num=%u "
1034 "[k=%d, n=%d]\n", __func__, *num_lbard, *sum_num, k, n);
1035 return true;
1036 }
1037
1038 static int
sum_num_lbards(const uint8_t * up,int num_lbards)1039 sum_num_lbards(const uint8_t * up, int num_lbards)
1040 {
1041 int sum = 0;
1042 int k, n;
1043
1044 for (k = 0, n = lbard_sz; k < num_lbards; ++k, n += lbard_sz)
1045 sum += sg_get_unaligned_be32(up + n + 8);
1046 return sum;
1047 }
1048
1049 /* Returns 0 if successful, else sg3_utils error code. */
1050 static int
do_write_x(int sg_fd,const void * dataoutp,int dout_len,const struct opts_t * op)1051 do_write_x(int sg_fd, const void * dataoutp, int dout_len,
1052 const struct opts_t * op)
1053 {
1054 int k, ret, res, sense_cat, cdb_len, vb, err;
1055 uint8_t x_cdb[WRITE_X_32_LEN]; /* use for both lengths */
1056 uint8_t sense_b[SENSE_BUFF_LEN] SG_C_CPP_ZERO_INIT;
1057 struct sg_pt_base * ptvp;
1058
1059 memset(x_cdb, 0, sizeof(x_cdb));
1060 vb = op->verbose;
1061 cdb_len = op->do_16 ? WRITE_X_16_LEN : WRITE_X_32_LEN;
1062 if (16 == cdb_len) {
1063 if (! op->do_scattered)
1064 sg_put_unaligned_be64(op->lba, x_cdb + 2);
1065 x_cdb[14] = (op->grpnum & GRPNUM_MASK);
1066 } else {
1067 x_cdb[0] = VARIABLE_LEN_OP;
1068 x_cdb[6] = (op->grpnum & GRPNUM_MASK);
1069 x_cdb[7] = WRITE_X_32_ADD;
1070 if (! op->do_scattered)
1071 sg_put_unaligned_be64(op->lba, x_cdb + 12);
1072 }
1073 if (op->do_write_normal) {
1074 if (16 == cdb_len) {
1075 x_cdb[0] = WRITE_16_OP;
1076 x_cdb[1] = ((op->wrprotect & 0x7) << 5);
1077 if (op->dpo)
1078 x_cdb[1] |= 0x10;
1079 if (op->fua)
1080 x_cdb[1] |= 0x8;
1081 if (op->dld) {
1082 if (op->dld & 1)
1083 x_cdb[14] |= 0x40;
1084 if (op->dld & 2)
1085 x_cdb[14] |= 0x80;
1086 if (op->dld & 4)
1087 x_cdb[1] |= 0x1;
1088 }
1089 sg_put_unaligned_be32(op->numblocks, x_cdb + 10);
1090 } else { /* 32 byte WRITE */
1091 sg_put_unaligned_be16((uint16_t)WRITE_32_SA, x_cdb + 8);
1092 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1093 if (op->dpo)
1094 x_cdb[10] |= 0x10;
1095 if (op->fua)
1096 x_cdb[10] |= 0x8;
1097 if (op->dld) { /* added in sbc4r19 */
1098 if (op->dld & 1)
1099 x_cdb[11] |= 0x1;
1100 if (op->dld & 2)
1101 x_cdb[11] |= 0x2;
1102 if (op->dld & 4)
1103 x_cdb[11] |= 0x4;
1104 }
1105 sg_put_unaligned_be32(op->ref_tag, x_cdb + 20);
1106 sg_put_unaligned_be16(op->app_tag, x_cdb + 24);
1107 sg_put_unaligned_be16(op->tag_mask, x_cdb + 26);
1108 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1109 }
1110 } else if (op->do_atomic) {
1111 if (16 == cdb_len) {
1112 if (op->numblocks > UINT16_MAX) {
1113 pr2serr("Need WRITE ATOMIC(32) since blocks exceed 65535\n");
1114 return SG_LIB_SYNTAX_ERROR;
1115 }
1116 x_cdb[0] = WRITE_ATOMIC16_OP;
1117 x_cdb[1] = ((op->wrprotect & 0x7) << 5);
1118 if (op->dpo)
1119 x_cdb[1] |= 0x10;
1120 if (op->fua)
1121 x_cdb[1] |= 0x8;
1122 sg_put_unaligned_be16(op->atomic_boundary, x_cdb + 10);
1123 sg_put_unaligned_be16((uint16_t)op->numblocks, x_cdb + 12);
1124 } else { /* 32 byte WRITE ATOMIC */
1125 sg_put_unaligned_be16(op->atomic_boundary, x_cdb + 4);
1126 sg_put_unaligned_be16((uint16_t)WRITE_ATOMIC32_SA, x_cdb + 8);
1127 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1128 if (op->dpo)
1129 x_cdb[10] |= 0x10;
1130 if (op->fua)
1131 x_cdb[10] |= 0x8;
1132 sg_put_unaligned_be32(op->ref_tag, x_cdb + 20);
1133 sg_put_unaligned_be16(op->app_tag, x_cdb + 24);
1134 sg_put_unaligned_be16(op->tag_mask, x_cdb + 26);
1135 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1136 }
1137 } else if (op->do_or) { /* ORWRITE(16 or 32) */
1138 if (16 == cdb_len) {
1139 x_cdb[0] = ORWRITE16_OP;
1140 x_cdb[1] = ((op->wrprotect & 0x7) << 5); /* actually ORPROTECT */
1141 if (op->dpo)
1142 x_cdb[1] |= 0x10;
1143 if (op->fua)
1144 x_cdb[1] |= 0x8;
1145 sg_put_unaligned_be32(op->numblocks, x_cdb + 10);
1146 } else {
1147 x_cdb[2] = op->bmop;
1148 x_cdb[3] = op->pgp;
1149 sg_put_unaligned_be16((uint16_t)ORWRITE32_SA, x_cdb + 8);
1150 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1151 if (op->dpo)
1152 x_cdb[10] |= 0x10;
1153 if (op->fua)
1154 x_cdb[10] |= 0x8;
1155 sg_put_unaligned_be32(op->orw_eog, x_cdb + 20);
1156 sg_put_unaligned_be32(op->orw_nog, x_cdb + 24);
1157 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1158 }
1159 } else if (op->do_same) {
1160 if (16 == cdb_len) {
1161 x_cdb[0] = WRITE_SAME16_OP;
1162 x_cdb[1] = ((op->wrprotect & 0x7) << 5);
1163 if (op->do_anchor)
1164 x_cdb[1] |= 0x10;
1165 if (op->do_unmap)
1166 x_cdb[1] |= 0x8;
1167 if (op->ndob)
1168 x_cdb[1] |= 0x1;
1169 sg_put_unaligned_be32(op->numblocks, x_cdb + 10);
1170 } else {
1171 sg_put_unaligned_be16((uint16_t)WRITE_SAME_SA, x_cdb + 8);
1172 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1173 if (op->do_anchor)
1174 x_cdb[10] |= 0x10;
1175 if (op->do_unmap)
1176 x_cdb[10] |= 0x8;
1177 if (op->ndob)
1178 x_cdb[10] |= 0x1;
1179 /* Expected initial logical block reference tag */
1180 sg_put_unaligned_be32(op->ref_tag, x_cdb + 20);
1181 sg_put_unaligned_be16(op->app_tag, x_cdb + 24);
1182 sg_put_unaligned_be16(op->tag_mask, x_cdb + 26);
1183 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1184 }
1185 } else if (op->do_scattered) {
1186 if (16 == cdb_len) {
1187 x_cdb[0] = SERVICE_ACTION_OUT_16_OP;
1188 x_cdb[1] = WRITE_SCATTERED16_SA;
1189 x_cdb[2] = ((op->wrprotect & 0x7) << 5);
1190 if (op->dpo)
1191 x_cdb[2] |= 0x10;
1192 if (op->fua)
1193 x_cdb[2] |= 0x8;
1194 if (op->dld) {
1195 if (op->dld & 1)
1196 x_cdb[14] |= 0x40;
1197 if (op->dld & 2)
1198 x_cdb[14] |= 0x80;
1199 if (op->dld & 4)
1200 x_cdb[2] |= 0x1;
1201 }
1202 sg_put_unaligned_be16(op->scat_lbdof, x_cdb + 4);
1203 sg_put_unaligned_be16(op->scat_num_lbard, x_cdb + 8);
1204 /* Spec says Buffer Transfer Length field (BTL) is the number
1205 * of (user) Logical Blocks in the data-out buffer and that BTL
1206 * may be 0. So the total data-out buffer length in bytes is:
1207 * (scat_lbdof + numblocks) * actual_block_size */
1208 sg_put_unaligned_be32(op->numblocks, x_cdb + 10);
1209 } else {
1210 sg_put_unaligned_be16((uint16_t)WRITE_SCATTERED32_SA, x_cdb + 8);
1211 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1212 if (op->dpo)
1213 x_cdb[10] |= 0x10;
1214 if (op->fua)
1215 x_cdb[10] |= 0x8;
1216 sg_put_unaligned_be16(op->scat_lbdof, x_cdb + 12);
1217 sg_put_unaligned_be16(op->scat_num_lbard, x_cdb + 16);
1218 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1219 /* ref_tag, app_tag and tag_mask placed in scatter list */
1220 }
1221 } else if (op->do_stream) {
1222 if (16 == cdb_len) {
1223 x_cdb[0] = WRITE_STREAM16_OP;
1224 x_cdb[1] = ((op->wrprotect & 0x7) << 5);
1225 if (op->dpo)
1226 x_cdb[1] |= 0x10;
1227 if (op->fua)
1228 x_cdb[1] |= 0x8;
1229 sg_put_unaligned_be16(op->str_id, x_cdb + 10);
1230 sg_put_unaligned_be16((uint16_t)op->numblocks, x_cdb + 12);
1231 } else {
1232 sg_put_unaligned_be16(op->str_id, x_cdb + 4);
1233 sg_put_unaligned_be16((uint16_t)WRITE_STREAM32_SA, x_cdb + 8);
1234 x_cdb[10] = ((op->wrprotect & 0x7) << 5);
1235 if (op->dpo)
1236 x_cdb[10] |= 0x10;
1237 if (op->fua)
1238 x_cdb[10] |= 0x8;
1239 sg_put_unaligned_be32(op->ref_tag, x_cdb + 20);
1240 sg_put_unaligned_be16(op->app_tag, x_cdb + 24);
1241 sg_put_unaligned_be16(op->tag_mask, x_cdb + 26);
1242 sg_put_unaligned_be32(op->numblocks, x_cdb + 28);
1243 }
1244 } else {
1245 pr2serr("%s: bad cdb name or length (%d)\n", __func__, cdb_len);
1246 return SG_LIB_SYNTAX_ERROR;
1247 }
1248
1249 if (vb > 1) {
1250 char b[128];
1251
1252 pr2serr(" %s cdb: %s\n", op->cdb_name,
1253 sg_get_command_str(x_cdb, cdb_len, false, sizeof(b), b));
1254 }
1255 if (op->do_scattered && (vb > 2) && (dout_len > 31)) {
1256 uint32_t sod_off = op->bs_pi_do * op->scat_lbdof;
1257 const uint8_t * up = (const uint8_t *)dataoutp;
1258
1259 pr2serr(" %s scatter list, number of %ss: %u\n", op->cdb_name,
1260 lbard_str, op->scat_num_lbard);
1261 pr2serr(" byte offset of data_to_write: %u, dout_len: %d\n",
1262 sod_off, dout_len);
1263 up += lbard_sz; /* step over parameter list header */
1264 for (k = 0; k < (int)op->scat_num_lbard; ++k, up += lbard_sz) {
1265 pr2serr(" desc %d: LBA=0x%" PRIx64 " numblocks=%" PRIu32
1266 "%s", k, sg_get_unaligned_be64(up + 0),
1267 sg_get_unaligned_be32(up + 8), (op->do_16 ? "\n" : " "));
1268 if (op->do_32)
1269 pr2serr("rt=0x%x at=0x%x tm=0x%x\n",
1270 sg_get_unaligned_be32(up + 12),
1271 sg_get_unaligned_be16(up + 16),
1272 sg_get_unaligned_be16(up + 18));
1273 if ((uint32_t)(((k + 2) * lbard_sz) + 20) > sod_off) {
1274 pr2serr("Warning: possible clash of descriptor %u with "
1275 "data_to_write\n", k);
1276 if (op->strict > 1)
1277 return SG_LIB_FILE_ERROR;
1278 }
1279 }
1280 }
1281 if ((vb > 3) && (dout_len > 0)) {
1282 if ((dout_len > 1024) && (vb < 7)) {
1283 pr2serr(" Data-out buffer contents (first 1024 of %u "
1284 "bytes):\n", dout_len);
1285 hex2stdout((const uint8_t *)dataoutp, 1024, 1);
1286 pr2serr(" Above: dout's first 1024 of %u bytes [%s]\n",
1287 dout_len, op->cdb_name);
1288 } else {
1289 pr2serr(" Data-out buffer contents (length=%u):\n", dout_len);
1290 hex2stderr((const uint8_t *)dataoutp, (int)dout_len, 1);
1291 }
1292 }
1293 if (op->dry_run) {
1294 if (vb)
1295 pr2serr("Exit just before sending %s due to --dry-run\n",
1296 op->cdb_name);
1297 if (op->dry_run > 1) {
1298 int w_fd;
1299
1300 w_fd = open(xx_wr_fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1301 if (w_fd < 0) {
1302 err = errno;
1303 perror(xx_wr_fname);
1304 return sg_convert_errno(err);
1305 }
1306 res = write(w_fd, dataoutp, dout_len);
1307 if (res < 0) {
1308 err = errno;
1309 perror(xx_wr_fname);
1310 close(w_fd);
1311 return sg_convert_errno(err);
1312 }
1313 close(w_fd);
1314 printf("Wrote %u bytes to %s", dout_len, xx_wr_fname);
1315 if (op->do_scattered)
1316 printf(", LB data offset: %u\nNumber of %ss: %u\n",
1317 op->scat_lbdof, lbard_str, op->scat_num_lbard);
1318 else
1319 printf("\n");
1320 }
1321 return 0;
1322 }
1323 ptvp = construct_scsi_pt_obj();
1324 if (NULL == ptvp) {
1325 pr2serr("%s: out of memory\n", op->cdb_name);
1326 return sg_convert_errno(ENOMEM);
1327 }
1328 set_scsi_pt_cdb(ptvp, x_cdb, cdb_len);
1329 set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
1330 if (dout_len > 0)
1331 set_scsi_pt_data_out(ptvp, (uint8_t *)dataoutp, dout_len);
1332 else if (vb && (! op->ndob))
1333 pr2serr("%s: dout_len==0, so empty dout buffer\n",
1334 op->cdb_name);
1335 res = do_scsi_pt(ptvp, sg_fd, op->timeout, vb);
1336 ret = sg_cmds_process_resp(ptvp, op->cdb_name, res, true /*noisy */, vb,
1337 &sense_cat);
1338 if (-1 == ret) {
1339 if (get_scsi_pt_transport_err(ptvp))
1340 ret = SG_LIB_TRANSPORT_ERROR;
1341 else
1342 ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
1343 } else if (-2 == ret) {
1344 switch (sense_cat) {
1345 case SG_LIB_CAT_RECOVERED:
1346 case SG_LIB_CAT_NO_SENSE:
1347 ret = 0;
1348 break;
1349 case SG_LIB_CAT_MEDIUM_HARD:
1350 {
1351 bool valid;
1352 int slen;
1353 uint64_t ull = 0;
1354
1355 slen = get_scsi_pt_sense_len(ptvp);
1356 valid = sg_get_sense_info_fld(sense_b, slen, &ull);
1357 if (valid) {
1358 pr2serr("Medium or hardware error starting at ");
1359 if (op->do_scattered) {
1360 if (0 == ull)
1361 pr2serr("%s=<not reported>\n", lbard_str);
1362 else
1363 pr2serr("%s=%" PRIu64 " (origin 0)\n", lbard_str,
1364 ull - 1);
1365 if (sg_get_sense_cmd_spec_fld(sense_b, slen, &ull)) {
1366 if (0 == ull)
1367 pr2serr(" Number of successfully written "
1368 "%ss is 0 or not reported\n",
1369 lbard_str);
1370 else
1371 pr2serr(" Number of successfully written "
1372 "%ss is %u\n", lbard_str,
1373 (uint32_t)ull);
1374 }
1375 } else
1376 pr2serr("lba=%" PRIu64 " [0x%" PRIx64 "]\n", ull,
1377 ull);
1378 }
1379 }
1380 ret = sense_cat;
1381 break;
1382 case SG_LIB_CAT_ILLEGAL_REQ:
1383 if (vb)
1384 sg_print_command_len(x_cdb, cdb_len);
1385 ret = sense_cat;
1386 break;
1387 default:
1388 ret = sense_cat;
1389 break;
1390 }
1391 } else
1392 ret = 0;
1393
1394 destruct_scsi_pt_obj(ptvp);
1395 return ret;
1396 }
1397
1398 /* Returns 0 if successful, else sg3_utils error code. */
1399 static int
do_read_capacity(int sg_fd,struct opts_t * op)1400 do_read_capacity(int sg_fd, struct opts_t *op)
1401 {
1402 bool prot_en = false;
1403 int res;
1404 int vb = op->verbose;
1405 char b[80];
1406 uint8_t resp_buff[RCAP16_RESP_LEN];
1407
1408 res = sg_ll_readcap_16(sg_fd, false /* pmi */, 0 /* llba */, resp_buff,
1409 RCAP16_RESP_LEN, true, (vb ? (vb - 1): 0));
1410 if (SG_LIB_CAT_UNIT_ATTENTION == res) {
1411 pr2serr("Read capacity(16) unit attention, try again\n");
1412 res = sg_ll_readcap_16(sg_fd, false, 0, resp_buff, RCAP16_RESP_LEN,
1413 true, (vb ? (vb - 1): 0));
1414 }
1415 if (0 == res) {
1416 uint32_t pi_len = 0;
1417
1418 if (vb > 3) {
1419 pr2serr("Read capacity(16) response:\n");
1420 hex2stderr(resp_buff, RCAP16_RESP_LEN, 1);
1421 }
1422 op->bs = sg_get_unaligned_be32(resp_buff + 8);
1423 op->tot_lbs = sg_get_unaligned_be64(resp_buff + 0) + 1;
1424 prot_en = !!(resp_buff[12] & 0x1);
1425 if (prot_en) {
1426 uint32_t pi_exp;
1427
1428 op->pi_type = ((resp_buff[12] >> 1) & 0x7) + 1;
1429 pi_exp = 0xf & (resp_buff[13] >> 4);
1430 pi_len = 8 * (1 << pi_exp);
1431 if (op->wrprotect > 0) {
1432 op->bs_pi_do = op->bs + pi_len;
1433 if (vb > 1)
1434 pr2serr(" For data out buffer purposes the effective "
1435 "block size is %u (lb size\n is %u) because "
1436 "PROT_EN=1, PI_EXP=%u and WRPROTECT>0\n", op->bs,
1437 pi_exp, op->bs_pi_do);
1438 }
1439 } else { /* device formatted to PI type 0 (i.e. none) */
1440 op->pi_type = 0;
1441 if (op->wrprotect > 0) {
1442 if (vb)
1443 pr2serr("--wrprotect (%d) expects PI but %s says it "
1444 "has none\n", op->wrprotect, op->device_name);
1445 if (op->strict)
1446 return SG_LIB_FILE_ERROR;
1447 else if (vb)
1448 pr2serr(" ... continue but could be dangerous\n");
1449 }
1450 }
1451 if (vb) {
1452 uint8_t d[2];
1453
1454 pr2serr("Read capacity(16) response fields:\n");
1455 pr2serr(" Last_LBA=0x%" PRIx64 " LB size: %u (with PI: "
1456 "%u) bytes p_type=%u\n", op->tot_lbs - 1,
1457 op->bs, op->bs + (prot_en ? pi_len : 0),
1458 ((resp_buff[12] >> 1) & 0x7));
1459 pr2serr(" prot_en=%u [PI type=%u] p_i_exp=%u lbppb_exp=%u "
1460 "lbpme,rz=%u,", prot_en, op->pi_type,
1461 ((resp_buff[13] >> 4) & 0xf), (resp_buff[13] & 0xf),
1462 !!(resp_buff[14] & 0x80));
1463 memcpy(d, resp_buff + 14, 2);
1464 d[0] &= 0x3f;
1465 pr2serr("%u low_ali_lba=%u\n", !!(resp_buff[14] & 0x40),
1466 sg_get_unaligned_be16(d));
1467 }
1468 } else if ((SG_LIB_CAT_INVALID_OP == res) ||
1469 (SG_LIB_CAT_ILLEGAL_REQ == res)) {
1470 if (vb)
1471 pr2serr("Read capacity(16) not supported, try Read "
1472 "capacity(10)\n");
1473 res = sg_ll_readcap_10(sg_fd, false /* pmi */, 0 /* lba */,
1474 resp_buff, RCAP10_RESP_LEN, true,
1475 (vb ? (vb - 1): 0));
1476 if (0 == res) {
1477 if (vb > 3) {
1478 pr2serr("Read capacity(10) response:\n");
1479 hex2stderr(resp_buff, RCAP10_RESP_LEN, 1);
1480 }
1481 op->tot_lbs = sg_get_unaligned_be32(resp_buff + 0) + 1;
1482 op->bs = sg_get_unaligned_be32(resp_buff + 4);
1483 } else {
1484 strcpy(b,"OS error");
1485 if (res > 0)
1486 sg_get_category_sense_str(res, sizeof(b), b, vb);
1487 else
1488 snprintf(b, sizeof(b), "error: %d", res);
1489 pr2serr("Read capacity(10): %s\n", b);
1490 pr2serr("Unable to calculate block size\n");
1491 return (res > 0) ? res : SG_LIB_FILE_ERROR;
1492 }
1493 } else {
1494 if (vb) {
1495 strcpy(b,"OS error");
1496 if (res > 0)
1497 sg_get_category_sense_str(res, sizeof(b), b, vb);
1498 pr2serr("Read capacity(16): %s\n", b);
1499 pr2serr("Unable to calculate block size\n");
1500 }
1501 return (res > 0) ? res : SG_LIB_FILE_ERROR;
1502 }
1503 op->bs_pi_do = op->expect_pi_do ? (op->bs + 8) : op->bs;
1504 return 0;
1505 }
1506
1507 #define WANT_ZERO_EXIT 9999
1508 static const char * const opt_long_ctl_str =
1509 "36a:A:b:B:c:dD:Efg:G:hi:I:l:M:n:No:Oq:Qr:RsS:t:T:u:vVw:x";
1510
1511 /* command line processing, options and arguments. Returns 0 if ok,
1512 * returns WANT_ZERO_EXIT so upper level yields an exist status of zero.
1513 * Other return values (mainly SG_LIB_SYNTAX_ERROR) indicate errors. */
1514 static int
parse_cmd_line(struct opts_t * op,int argc,char * argv[],const char ** lba_opp,const char ** num_opp)1515 parse_cmd_line(struct opts_t *op, int argc, char *argv[],
1516 const char ** lba_opp, const char ** num_opp)
1517 {
1518 bool fail_if_strict = false;
1519 int c, j;
1520 int64_t ll;
1521 const char * cp;
1522
1523 while (1) {
1524 int opt_ind = 0;
1525
1526 c = getopt_long(argc, argv, opt_long_ctl_str, long_options, &opt_ind);
1527 if (c == -1)
1528 break;
1529
1530 switch (c) {
1531 case '3': /* same as --32 */
1532 op->do_32 = true;
1533 break;
1534 case '6': /* same as --16 */
1535 op->do_16 = true;
1536 break;
1537 case 'a':
1538 j = sg_get_num(optarg);
1539 if ((j < 0) || (j > (int)UINT16_MAX)) {
1540 pr2serr("bad argument to '--app-tag='. Expect 0 to 0xffff "
1541 "inclusive\n");
1542 return SG_LIB_SYNTAX_ERROR;
1543 }
1544 op->app_tag = (uint16_t)j;
1545 break;
1546 case 'A':
1547 j = sg_get_num(optarg);
1548 if ((j < 0) || (j > (int)UINT16_MAX)) {
1549 pr2serr("bad argument to '--atomic='. Expect 0 to 0xffff "
1550 "inclusive\n");
1551 return SG_LIB_SYNTAX_ERROR;
1552 }
1553 op->atomic_boundary = (uint16_t)j;
1554 op->do_atomic = true;
1555 op->cmd_name = "Write atomic";
1556 break;
1557 case 'b': /* logical block size in bytes */
1558 j = sg_get_num(optarg); /* 0 -> look up with READ CAPACITY */
1559 if ((j < 0) || (j > (1 << 28))) {
1560 pr2serr("bad argument to '--bs='. Expect 0 or greater\n");
1561 return SG_LIB_SYNTAX_ERROR;
1562 }
1563 if (j > 0) {
1564 int k;
1565 int m = j;
1566 int highest_ind;
1567
1568 if (j < 512) {
1569 pr2serr("warning: --bs=BS value is < 512 which seems too "
1570 "small, continue\n");
1571 fail_if_strict = true;
1572 }
1573 if (0 != (j % 8)) {
1574 pr2serr("warning: --bs=BS value is not a multiple of 8, "
1575 "unexpected, continue\n");
1576 fail_if_strict = true;
1577 }
1578 for (k = 0, highest_ind = 0; k < 28; ++ k, m >>= 1) {
1579 if (1 & m)
1580 highest_ind = k;
1581 } /* loop should get log_base2(j) */
1582 k = 1 << highest_ind;
1583 if (j == k) { /* j is a power of two; actual and logical
1584 * block size is assumed to be the same */
1585 op->bs = (uint32_t)j;
1586 op->bs_pi_do = op->bs;
1587 } else { /* j is not power_of_two, use as actual LB size */
1588 op->bs = (uint32_t)k; /* power_of_two less than j */
1589 op->bs_pi_do = (uint32_t)j;
1590 }
1591 } else { /* j==0, let READCAP sort this out */
1592 op->bs = 0;
1593 op->bs_pi_do = 0;
1594 }
1595 break;
1596 case 'B': /* --bmop=OP,PGP (for ORWRITE(32)) */
1597 j = sg_get_num(optarg);
1598 if ((j < 0) || (j > 7)) {
1599 pr2serr("bad first argument to '--bmop='\n");
1600 return SG_LIB_SYNTAX_ERROR;
1601 }
1602 op->bmop = (uint8_t)j;
1603 if ((cp = strchr(optarg, ','))) {
1604 j = sg_get_num(cp + 1);
1605 if ((j < 0) || (j > 15)) {
1606 pr2serr("bad second argument to '--bmop='\n");
1607 return SG_LIB_SYNTAX_ERROR;
1608 }
1609 op->pgp = (uint8_t)j;
1610 }
1611 break;
1612 case 'c': /* --combined=DOF for W SCATTERED, DOF: data offset */
1613 j = sg_get_num(optarg);
1614 if (j < 0) {
1615 pr2serr("bad argument to '--combined='. Expect 0 to "
1616 "0x7fffffff\n");
1617 return SG_LIB_SYNTAX_ERROR;
1618 }
1619 op->scat_lbdof = (uint16_t)j;
1620 op->do_combined = true;
1621 break;
1622 case 'd':
1623 op->dpo = true;
1624 break;
1625 case 'D':
1626 op->dld = sg_get_num(optarg);
1627 if ((op->dld < 0) || (op->dld > 7)) {
1628 pr2serr("bad argument to '--dld=', expect 0 to 7 "
1629 "inclusive\n");
1630 return SG_LIB_SYNTAX_ERROR;
1631 }
1632 break;
1633 case 'f':
1634 op->fua = true;
1635 break;
1636 case 'g':
1637 op->grpnum = sg_get_num(optarg);
1638 if ((op->grpnum < 0) || (op->grpnum > 63)) {
1639 pr2serr("bad argument to '--grpnum'\n");
1640 return SG_LIB_SYNTAX_ERROR;
1641 }
1642 break;
1643 case 'G': /* --generation=EOG,NOG */
1644 ll = sg_get_llnum(optarg);
1645 if ((ll < 0) || (ll > UINT32_MAX)) {
1646 pr2serr("bad first argument to '--generation='\n");
1647 return SG_LIB_SYNTAX_ERROR;
1648 }
1649 op->orw_eog = (uint32_t)ll;
1650 if ((cp = strchr(optarg, ','))) {
1651 ll = sg_get_llnum(cp + 1);
1652 if ((ll < 0) || (ll > UINT32_MAX)) {
1653 pr2serr("bad second argument to '--generation='\n");
1654 return SG_LIB_SYNTAX_ERROR;
1655 }
1656 op->orw_nog = (uint32_t)ll;
1657 } else {
1658 pr2serr("need two arguments with --generation=EOG,NOG and "
1659 "they must be comma separated\n");
1660 return SG_LIB_SYNTAX_ERROR;
1661 }
1662 break;
1663 case 'h':
1664 ++op->help;
1665 break;
1666 case '?':
1667 pr2serr("\n");
1668 usage((op->help > 0) ? op->help : 0);
1669 return SG_LIB_SYNTAX_ERROR;
1670 case 'i':
1671 op->if_name = optarg;
1672 break;
1673 case 'I':
1674 op->timeout = sg_get_num(optarg);
1675 if (op->timeout < 0) {
1676 pr2serr("bad argument to '--timeout='\n");
1677 return SG_LIB_SYNTAX_ERROR;
1678 }
1679 break;
1680 case 'l':
1681 if (*lba_opp) {
1682 pr2serr("only expect '--lba=' option once\n");
1683 return SG_LIB_SYNTAX_ERROR;
1684 }
1685 *lba_opp = optarg;
1686 break;
1687 case 'M': /* WRITE SAME */
1688 j = sg_get_num(optarg);
1689 if ((j < 0) || (j > 1)) {
1690 pr2serr("bad argument to '--same', expect 0 or 1\n");
1691 return SG_LIB_SYNTAX_ERROR;
1692 }
1693 op->ndob = (bool)j;
1694 op->do_same = true;
1695 op->cmd_name = "Write same";
1696 break;
1697 case 'n':
1698 if (*num_opp) {
1699 pr2serr("only expect '--num=' option once\n");
1700 return SG_LIB_SYNTAX_ERROR;
1701 }
1702 *num_opp = optarg;
1703 break;
1704 case 'N':
1705 op->do_write_normal = true;
1706 op->cmd_name = "Write";
1707 break;
1708 case 'o':
1709 ll = sg_get_llnum(optarg);
1710 if (-1 == ll) {
1711 pr2serr("bad first argument to '--offset='\n");
1712 return SG_LIB_SYNTAX_ERROR;
1713 }
1714 op->if_offset = (uint64_t)ll;
1715 if ((cp = strchr(optarg, ','))) {
1716 ll = sg_get_llnum(cp + 1);
1717 if (-1 == ll) {
1718 pr2serr("bad second argument to '--offset='\n");
1719 return SG_LIB_SYNTAX_ERROR;
1720 }
1721 if (ll > UINT32_MAX) {
1722 pr2serr("bad second argument to '--offset=', cannot "
1723 "exceed 32 bits\n");
1724 return SG_LIB_SYNTAX_ERROR;
1725 }
1726 op->if_dlen = (uint32_t)ll;
1727 }
1728 break;
1729 case 'O':
1730 op->do_or = true;
1731 op->cmd_name = "Orwrite";
1732 break;
1733 case 'q':
1734 op->scat_filename = optarg;
1735 break;
1736 case 'Q':
1737 op->do_quiet = true;
1738 break;
1739 case 'R':
1740 op->do_scat_raw = true;
1741 break;
1742 case 'r': /* same as --ref-tag= */
1743 ll = sg_get_llnum(optarg);
1744 if ((ll < 0) || (ll > UINT32_MAX)) {
1745 pr2serr("bad argument to '--ref-tag='. Expect 0 to "
1746 "0xffffffff inclusive\n");
1747 return SG_LIB_SYNTAX_ERROR;
1748 }
1749 op->ref_tag = (uint32_t)ll;
1750 break;
1751 case 's':
1752 ++op->strict;
1753 break;
1754 case 'S':
1755 j = sg_get_num(optarg);
1756 if ((j < 0) || (j > (int)UINT16_MAX)) {
1757 pr2serr("bad argument to '--scattered='. Expect 0 to 0xffff "
1758 "inclusive\n");
1759 return SG_LIB_SYNTAX_ERROR;
1760 }
1761 op->scat_num_lbard = (uint16_t)j;
1762 op->do_scattered = true;
1763 op->cmd_name = "Write scattered";
1764 break;
1765 case 't': /* same as --tag-mask= */
1766 j = sg_get_num(optarg);
1767 if ((j < 0) || (j > (int)UINT16_MAX)) {
1768 pr2serr("bad argument to '--tag-mask='. Expect 0 to 0xffff "
1769 "inclusive\n");
1770 return SG_LIB_SYNTAX_ERROR;
1771 }
1772 op->tag_mask = (uint16_t)j;
1773 break;
1774 case 'T': /* WRITE STREAM */
1775 j = sg_get_num(optarg);
1776 if ((j < 0) || (j > (int)UINT16_MAX)) {
1777 pr2serr("bad argument to '--stream=', expect 0 to 65535\n");
1778 return SG_LIB_SYNTAX_ERROR;
1779 }
1780 op->str_id = (uint16_t)j;
1781 op->do_stream = true;
1782 op->cmd_name = "Write stream";
1783 break;
1784 case 'u': /* WRITE SAME, UNMAP and ANCHOR bit */
1785 j = sg_get_num(optarg);
1786 if ((j < 0) || (j > 3)) {
1787 pr2serr("bad argument to '--unmap=', expect 0 to "
1788 "3\n");
1789 return SG_LIB_SYNTAX_ERROR;
1790 }
1791 op->do_unmap = !!(1 & j);
1792 op->do_anchor = !!(2 & j);
1793 break;
1794 case 'v':
1795 op->verbose_given = true;
1796 ++op->verbose;
1797 break;
1798 case 'V':
1799 op->version_given = true;
1800 break;
1801 case 'w': /* WRPROTECT field (or ORPROTECT for ORWRITE) */
1802 op->wrprotect = sg_get_num(optarg);
1803 if ((op->wrprotect < 0) || (op->wrprotect > 7)) {
1804 pr2serr("bad argument to '--wrprotect'\n");
1805 return SG_LIB_SYNTAX_ERROR;
1806 }
1807 op->expect_pi_do = (op->wrprotect > 0);
1808 break;
1809 case 'x':
1810 ++op->dry_run;
1811 break;
1812 default:
1813 pr2serr("unrecognised option code 0x%x ??\n", c);
1814 usage((op->help > 0) ? op->help : 0);
1815 return SG_LIB_SYNTAX_ERROR;
1816 }
1817 }
1818 if (optind < argc) {
1819 if (NULL == op->device_name) {
1820 op->device_name = argv[optind];
1821 ++optind;
1822 }
1823 if (optind < argc) {
1824 for (; optind < argc; ++optind)
1825 pr2serr("Unexpected extra argument: %s\n", argv[optind]);
1826 usage((op->help > 0) ? op->help : 0);
1827 return SG_LIB_SYNTAX_ERROR;
1828 }
1829 }
1830 if (op->strict && fail_if_strict)
1831 return SG_LIB_SYNTAX_ERROR;
1832 return 0;
1833 }
1834
1835 static int
process_scattered(int sg_fd,int infd,uint32_t if_len,uint32_t if_rlen,int sfr_fd,uint32_t sf_len,uint64_t * addr_arr,uint32_t addr_arr_len,uint32_t * num_arr,uint16_t num_lbard,uint32_t sum_num,struct opts_t * op)1836 process_scattered(int sg_fd, int infd, uint32_t if_len, uint32_t if_rlen,
1837 int sfr_fd, uint32_t sf_len, uint64_t * addr_arr,
1838 uint32_t addr_arr_len, uint32_t * num_arr,
1839 uint16_t num_lbard, uint32_t sum_num, struct opts_t * op)
1840 {
1841 int k, n, ret;
1842 int vb = op->verbose;
1843 uint32_t d, dd, nn, do_len;
1844 uint8_t * up = NULL;
1845 uint8_t * free_up = NULL;
1846 char b[80];
1847
1848 if (op->do_combined) { /* --combined=DOF (.scat_lbdof) */
1849 if (op->scat_lbdof > 0)
1850 d = op->scat_lbdof * op->bs_pi_do;
1851 else if (op->scat_num_lbard > 0) {
1852 d = lbard_sz * (1 + op->scat_num_lbard);
1853 if (0 != (d % op->bs_pi_do))
1854 d = ((d / op->bs_pi_do) + 1) * op->bs_pi_do;
1855 } else if (if_len > 0) {
1856 d = if_len;
1857 if (0 != (d % op->bs_pi_do))
1858 d = ((d / op->bs_pi_do) + 1) * op->bs_pi_do;
1859 } else {
1860 pr2serr("With --combined= if DOF, RD are 0 and IF has an "
1861 "unknown length\nthen give up\n");
1862 return SG_LIB_CONTRADICT;
1863 }
1864 up = sg_memalign(d, 0, &free_up, false);
1865 if (NULL == up) {
1866 pr2serr("unable to allocate aligned memory for "
1867 "scatterlist+data\n");
1868 return sg_convert_errno(ENOMEM);
1869 }
1870 ret = bin_read(infd, up, ((if_len < d) ? if_len : d), "IF c1");
1871 if (ret)
1872 goto finii;
1873 if (! check_lbrds(up, d, op, &num_lbard, &sum_num))
1874 goto file_err_outt;
1875 if ((op->scat_num_lbard > 0) && (op->scat_num_lbard != num_lbard)) {
1876 bool rd_gt = (op->scat_num_lbard > num_lbard);
1877
1878 if (rd_gt || op->strict || vb) {
1879 pr2serr("RD (%u) %s number of %ss (%u) found in IF\n",
1880 op->scat_num_lbard, (rd_gt ? ">" : "<"), lbard_str,
1881 num_lbard);
1882 if (rd_gt)
1883 goto file_err_outt;
1884 else if (op->strict)
1885 goto file_err_outt;
1886 }
1887 num_lbard = op->scat_num_lbard;
1888 sum_num = sum_num_lbards(up, op->scat_num_lbard);
1889 } else
1890 op->scat_num_lbard = num_lbard;
1891 dd = lbard_sz * (num_lbard + 1);
1892 if (0 != (dd % op->bs_pi_do))
1893 dd = ((dd / op->bs_pi_do) + 1) * op->bs_pi_do; /* round up */
1894 nn = op->scat_lbdof * op->bs_pi_do;
1895 if (dd != nn) {
1896 bool dd_gt = (dd > nn);
1897
1898 if (dd_gt) {
1899 pr2serr("%s: Cannot fit %ss (%u) in given LB data offset "
1900 "(%u)\n", __func__, lbard_str, num_lbard,
1901 op->scat_lbdof);
1902 goto file_err_outt;
1903 }
1904 if (vb || op->strict)
1905 pr2serr("%s: empty blocks before LB data offset (%u), could "
1906 "be okay\n", __func__, op->scat_lbdof);
1907 if (op->strict) {
1908 pr2serr("Exiting due to --strict; perhaps try again with "
1909 "--combined=%u\n", dd / op->bs_pi_do);
1910 goto file_err_outt;
1911 }
1912 dd = nn;
1913 }
1914 dd += (sum_num * op->bs_pi_do);
1915 if (dd > d) {
1916 uint8_t * u2p;
1917 uint8_t * free_u2p;
1918
1919 if (dd != if_len) {
1920 bool dd_gt = (dd > if_len);
1921
1922 if (dd_gt || op->strict || vb) {
1923 pr2serr("Calculated dout length (%u) %s bytes available "
1924 "in IF (%u)\n", dd, (dd_gt ? ">" : "<"), if_len);
1925 if (dd_gt)
1926 goto file_err_outt;
1927 else if (op->strict)
1928 goto file_err_outt;
1929 }
1930 }
1931 u2p = sg_memalign(dd, 0, &free_u2p, false);
1932 if (NULL == u2p) {
1933 pr2serr("unable to allocate memory for final "
1934 "scatterlist+data\n");
1935 ret = sg_convert_errno(ENOMEM);
1936 goto finii;
1937 }
1938 memcpy(u2p, up, d);
1939 free(free_up);
1940 up = u2p;
1941 free_up = free_u2p;
1942 ret = bin_read(infd, up + d, dd - d, "IF c2");
1943 if (ret)
1944 goto finii;
1945 }
1946 do_len = dd;
1947 op->numblocks = sum_num;
1948 op->xfer_bytes = sum_num * op->bs_pi_do;
1949 goto do_io;
1950 }
1951
1952 /* other than do_combined, so --scat-file= or --lba= */
1953 if (addr_arr_len > 0)
1954 num_lbard = addr_arr_len;
1955
1956 if (op->scat_filename && (! op->do_scat_raw)) {
1957 d = lbard_sz * (num_lbard + 1);
1958 nn = d;
1959 op->scat_lbdof = d / op->bs_pi_do;
1960 if (0 != (d % op->bs_pi_do)) /* if not multiple, round up */
1961 op->scat_lbdof += 1;
1962 dd = op->scat_lbdof * op->bs_pi_do;
1963 d = sum_num * op->bs_pi_do;
1964 do_len = dd + d;
1965 /* zeroed data-out buffer for SL+DATA */
1966 up = sg_memalign(do_len, 0, &free_up, false);
1967 if (NULL == up) {
1968 pr2serr("unable to allocate aligned memory for "
1969 "scatterlist+data\n");
1970 return sg_convert_errno(ENOMEM);
1971 }
1972 num_lbard = 0;
1973 sum_num = 0;
1974 nn = (nn > lbard_sz) ? nn : (op->scat_lbdof * op->bs_pi_do);
1975 ret = build_t10_scat(op->scat_filename, op->do_16, ! op->do_scattered,
1976 up, &num_lbard, &sum_num, nn);
1977 if (ret)
1978 goto finii;
1979 /* Calculate number of bytes to read from IF (place in 'd') */
1980 d = sum_num * op->bs_pi_do;
1981 if (op->if_dlen > d) {
1982 if (op->strict || vb) {
1983 pr2serr("DLEN > than bytes implied by sum of scatter "
1984 "list NUMs (%u)\n", d);
1985 if (vb > 1)
1986 pr2serr(" num_lbard=%u, sum_num=%u actual_bs=%u",
1987 num_lbard, sum_num, op->bs_pi_do);
1988 if (op->strict)
1989 goto file_err_outt;
1990 }
1991 } else if ((op->if_dlen > 0) && (op->if_dlen < d))
1992 d = op->if_dlen;
1993 if ((if_rlen > 0) && (if_rlen != d)) {
1994 bool readable_lt = (if_rlen < d);
1995
1996 if (vb)
1997 pr2serr("readable length (%u) of IF %s bytes implied by "
1998 "sum of\nscatter list NUMs (%u) and DLEN\n",
1999 (uint32_t)if_rlen,
2000 readable_lt ? "<" : ">", d);
2001 if (op->strict) {
2002 if ((op->strict > 1) || (! readable_lt))
2003 goto file_err_outt;
2004 }
2005 if (readable_lt)
2006 d = if_rlen;
2007 }
2008 if (0 != (d % op->bs_pi_do)) {
2009 if (vb || (op->strict > 1)) {
2010 pr2serr("Calculated data-out length (0x%x) not a "
2011 "multiple of BS (%u", d, op->bs);
2012 if (op->bs != op->bs_pi_do)
2013 pr2serr(" + %d(PI)", (int)op->bs_pi_do - (int)op->bs);
2014 if (op->strict > 1) {
2015 pr2serr(")\nexiting ...\n");
2016 goto file_err_outt;
2017 } else
2018 pr2serr(")\nzero pad and continue ...\n");
2019 }
2020 }
2021 ret = bin_read(infd, up + (op->scat_lbdof * op->bs_pi_do), d,
2022 "IF 3");
2023 if (ret)
2024 goto finii;
2025 do_len = ((op->scat_lbdof + sum_num) * op->bs_pi_do);
2026 op->numblocks = sum_num;
2027 op->xfer_bytes = sum_num * op->bs_pi_do;
2028 /* dout for scattered write with ASCII scat_file ready */
2029 } else if (op->do_scat_raw) {
2030 bool if_len_gt = false;
2031
2032 /* guessing game for length of buffer */
2033 if (op->scat_num_lbard > 0) {
2034 dd = (op->scat_num_lbard + 1) * lbard_sz;
2035 if (sf_len < dd) {
2036 pr2serr("SF not long enough (%u bytes) to provide RD "
2037 "(%u) %ss\n", sf_len, dd, lbard_str);
2038 goto file_err_outt;
2039 }
2040 nn = dd / op->bs_pi_do;
2041 if (0 != (dd % op->bs_pi_do))
2042 nn +=1;
2043 dd = nn * op->bs_pi_do;
2044 } else
2045 dd = op->bs_pi_do; /* guess */
2046 if (if_len > 0) {
2047 nn = if_len / op->bs_pi_do;
2048 if (0 != (if_len % op->bs_pi_do))
2049 nn += 1;
2050 d = nn * op->bs_pi_do;
2051 } else
2052 d = op->bs_pi_do; /* guess one LB */
2053 /* zero data-out buffer for SL+DATA */
2054 nn = dd + d;
2055 up = sg_memalign(nn, 0, &free_up, false);
2056 if (NULL == up) {
2057 pr2serr("unable to allocate aligned memory for "
2058 "scatterlist+data\n");
2059 ret = sg_convert_errno(ENOMEM);
2060 goto finii;
2061 }
2062 ret = bin_read(sfr_fd, up, sf_len, "SF");
2063 if (ret)
2064 goto finii;
2065 if (! check_lbrds(up, dd, op, &num_lbard, &sum_num))
2066 goto file_err_outt;
2067 if (num_lbard != op->scat_num_lbard) {
2068 pr2serr("Try again with --scattered=%u\n", num_lbard);
2069 goto file_err_outt;
2070 }
2071 if ((sum_num * op->bs_pi_do) > d) {
2072 uint8_t * u2p;
2073 uint8_t * free_u2p;
2074
2075 d = sum_num * op->bs_pi_do;
2076 nn = dd + d;
2077 u2p = sg_memalign(nn, 0, &free_u2p, false);
2078 if (NULL == u2p) {
2079 pr2serr("unable to allocate memory for final "
2080 "scatterlist+data\n");
2081 ret = sg_convert_errno(ENOMEM);
2082 goto finii;
2083 }
2084 memcpy(u2p, up, dd);
2085 free(free_up);
2086 up = u2p;
2087 free_up = free_u2p;
2088 }
2089 if ((if_len != (nn - d)) && (op->strict || vb)) {
2090 if_len_gt = (if_len > (nn - d));
2091 pr2serr("IF length (%u) %s 'sum_num' bytes (%u), ", if_len,
2092 (if_len_gt ? ">" : "<"), nn - d);
2093 if (op->strict > 1) {
2094 pr2serr("exiting (strict=%d)\n", op->strict);
2095 goto file_err_outt;
2096 } else
2097 pr2serr("continuing ...\n");
2098 }
2099 ret = bin_read(infd, up + d, (if_len_gt ? nn - d : if_len), "IF 4");
2100 if (ret)
2101 goto finii;
2102 do_len = (num_lbard + sum_num) * op->bs_pi_do;
2103 op->numblocks = sum_num;
2104 op->xfer_bytes = sum_num * op->bs_pi_do;
2105 } else if (addr_arr_len > 0) { /* build RDs for --lba= --num= */
2106 if ((op->scat_num_lbard > 0) && (op->scat_num_lbard > addr_arr_len)) {
2107 pr2serr("%s: number given to --scattered= (%u) exceeds number of "
2108 "--lba= elements (%u)\n", __func__, op->scat_num_lbard,
2109 addr_arr_len);
2110 return SG_LIB_CONTRADICT;
2111 }
2112 d = lbard_sz * (num_lbard + 1);
2113 op->scat_lbdof = d / op->bs_pi_do;
2114 if (0 != (d % op->bs_pi_do)) /* if not multiple, round up */
2115 op->scat_lbdof += 1;
2116 for (sum_num = 0, k = 0; k < (int)addr_arr_len; ++k)
2117 sum_num += num_arr[k];
2118 do_len = ((op->scat_lbdof + sum_num) * op->bs_pi_do);
2119 up = sg_memalign(do_len, 0, &free_up, false);
2120 if (NULL == up) {
2121 pr2serr("unable to allocate aligned memory for "
2122 "scatterlist+data\n");
2123 ret = sg_convert_errno(ENOMEM);
2124 goto finii;
2125 }
2126 for (n = lbard_sz, k = 0; k < (int)addr_arr_len; ++k,
2127 n += lbard_sz) {
2128 sg_put_unaligned_be64(addr_arr[k], up + n + 0);
2129 sg_put_unaligned_be32(num_arr[k], up + n + 8);
2130 if (op->do_32) {
2131 if (0 == k) {
2132 sg_put_unaligned_be32(op->ref_tag, up + n + 12);
2133 sg_put_unaligned_be16(op->app_tag, up + n + 16);
2134 sg_put_unaligned_be16(op->tag_mask, up + n + 18);
2135 } else {
2136 sg_put_unaligned_be32((uint32_t)DEF_RT, up + n + 12);
2137 sg_put_unaligned_be16((uint16_t)DEF_AT, up + n + 16);
2138 sg_put_unaligned_be16((uint16_t)DEF_TM, up + n + 18);
2139 }
2140 }
2141 }
2142 op->numblocks = sum_num;
2143 } else {
2144 pr2serr("How did we get here??\n");
2145 goto syntax_err_outt;
2146 }
2147 do_io:
2148 ret = do_write_x(sg_fd, up, do_len, op);
2149 if (ret) {
2150 strcpy(b,"OS error");
2151 if (ret > 0)
2152 sg_get_category_sense_str(ret, sizeof(b), b, vb);
2153 pr2serr("%s: %s\n", op->cdb_name, b);
2154 }
2155 goto finii;
2156
2157 syntax_err_outt:
2158 ret = SG_LIB_SYNTAX_ERROR;
2159 goto finii;
2160 file_err_outt:
2161 ret = SG_LIB_FILE_ERROR;
2162 finii:
2163 if (free_up)
2164 free(free_up);
2165 return ret;
2166 }
2167
2168
2169 int
main(int argc,char * argv[])2170 main(int argc, char * argv[])
2171 {
2172 bool got_stdin = false;
2173 bool got_stat = false;
2174 bool if_reg_file = false;
2175 int n, err, vb;
2176 int infd = -1;
2177 int sg_fd = -1;
2178 int sfr_fd = -1;
2179 int ret = -1;
2180 uint32_t nn, addr_arr_len, num_arr_len; /* --lba= */
2181 uint32_t do_len = 0;
2182 uint16_t num_lbard = 0;
2183 uint32_t if_len = 0; /* after accounting for OFF,DLEN and moving file
2184 * file pointer to OFF, is bytes available in IF */
2185 uint32_t sf_len = 0;
2186 uint32_t sum_num = 0;
2187 ssize_t res;
2188 off_t if_readable_len = 0; /* similar to if_len but doesn't take DLEN
2189 * into account */
2190 struct opts_t * op;
2191 const char * lba_op = NULL;
2192 const char * num_op = NULL;
2193 uint8_t * up = NULL;
2194 uint8_t * free_up = NULL;
2195 char ebuff[EBUFF_SZ];
2196 char b[80];
2197 uint64_t addr_arr[MAX_NUM_ADDR];
2198 uint32_t num_arr[MAX_NUM_ADDR];
2199 struct stat if_stat, sf_stat;
2200 struct opts_t opts SG_C_CPP_ZERO_INIT;
2201
2202 op = &opts;
2203 memset(&if_stat, 0, sizeof(if_stat));
2204 memset(&sf_stat, 0, sizeof(sf_stat));
2205 op->numblocks = DEF_WR_NUMBLOCKS;
2206 op->pi_type = -1; /* Protection information type unknown */
2207 op->ref_tag = DEF_RT; /* first 4 bytes of 8 byte protection info */
2208 op->app_tag = DEF_AT; /* 2 bytes of protection information */
2209 op->tag_mask = DEF_TM; /* final 2 bytes of protection information */
2210 op->timeout = DEF_TIMEOUT_SECS;
2211
2212 /* Process command line */
2213 ret = parse_cmd_line(op, argc, argv, &lba_op, &num_op);
2214 if (ret) {
2215 if (WANT_ZERO_EXIT == ret)
2216 return 0;
2217 return ret;
2218 }
2219 if (op->help > 0) {
2220 usage(op->help);
2221 return 0;
2222 }
2223
2224 #ifdef DEBUG
2225 pr2serr("In DEBUG mode, ");
2226 if (op->verbose_given && op->version_given) {
2227 pr2serr("but override: '-vV' given, zero verbose and continue\n");
2228 op->verbose_given = false;
2229 op->version_given = false;
2230 op->verbose = 0;
2231 } else if (! op->verbose_given) {
2232 pr2serr("set '-vv'\n");
2233 op->verbose = 2;
2234 } else
2235 pr2serr("keep verbose=%d\n", op->verbose);
2236 #else
2237 if (op->verbose_given && op->version_given)
2238 pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
2239 #endif
2240 if (op->version_given) {
2241 pr2serr("sg_write_x version: %s\n", version_str);
2242 return WANT_ZERO_EXIT;
2243 }
2244
2245 vb = op->verbose;
2246 /* sanity checks */
2247 if ((! op->do_16) && (! op->do_32)) {
2248 op->do_16 = true;
2249 if (vb > 1)
2250 pr2serr("Since neither --16 nor --32 given, choose --16\n");
2251 } else if (op->do_16 && op->do_32) {
2252 op->do_16 = false;
2253 if (vb > 1)
2254 pr2serr("Since both --16 and --32 given, choose --32\n");
2255 }
2256 n = (int)op->do_atomic + (int)op->do_write_normal + (int)op->do_or +
2257 (int)op->do_same + (int)op->do_scattered + (int)op->do_stream;
2258 if (n > 1) {
2259 pr2serr("Can only select one command; so only one of --atomic, "
2260 "--normal, --or,\n--same=, --scattered= or --stream=\n") ;
2261 return SG_LIB_CONTRADICT;
2262 } else if (n < 1) {
2263 if (op->strict) {
2264 pr2serr("With --strict won't default to a normal WRITE, add "
2265 "--normal\n");
2266 return SG_LIB_CONTRADICT;
2267 } else {
2268 op->do_write_normal = true;
2269 op->cmd_name = "Write";
2270 if (vb)
2271 pr2serr("No command selected so choose 'normal' WRITE\n");
2272 }
2273 }
2274 snprintf(op->cdb_name, sizeof(op->cdb_name), "%s(%d)", op->cmd_name,
2275 (op->do_16 ? 16 : 32));
2276 if (op->do_combined) {
2277 if (! op->do_scattered) {
2278 pr2serr("--combined=DOF only allowed with --scattered=RD (i.e. "
2279 "only with\nWRITE SCATTERED command)\n");
2280 return SG_LIB_CONTRADICT;
2281 }
2282 if (op->scat_filename) {
2283 pr2serr("Ambiguous: got --combined=DOF and --scat-file=SF .\n"
2284 "Give one, the other or neither\n");
2285 return SG_LIB_CONTRADICT;
2286 }
2287 if (lba_op || num_op) {
2288 pr2serr("--scattered=RD --combined=DOF does not use --lba= or "
2289 "--num=\nPlease remove.\n");
2290 return SG_LIB_CONTRADICT;
2291 }
2292 if (op->do_scat_raw) {
2293 pr2serr("Ambiguous: don't expect --combined=DOF and --scat-raw\n"
2294 "Give one or the other\n");
2295 return SG_LIB_CONTRADICT;
2296 }
2297 }
2298 if ((NULL == op->scat_filename) && op->do_scat_raw) {
2299 pr2serr("--scat-raw only applies to the --scat-file=SF option\n"
2300 "--scat-raw without the --scat-file=SF option is an "
2301 "error\n");
2302 return SG_LIB_CONTRADICT;
2303 }
2304 n = (!! op->scat_filename) + (!! (lba_op || num_op)) +
2305 (!! op->do_combined);
2306 if (n > 1) {
2307 pr2serr("want one and only one of: (--lba=LBA and/or --num=NUM), or\n"
2308 "--scat-file=SF, or --combined=DOF\n");
2309 return SG_LIB_CONTRADICT;
2310 }
2311 if (op->scat_filename && (1 == strlen(op->scat_filename)) &&
2312 ('-' == op->scat_filename[0])) {
2313 pr2serr("don't accept '-' (implying stdin) as a filename in "
2314 "--scat-file=SF\n");
2315 return SG_LIB_CONTRADICT;
2316 }
2317 if (vb && op->do_16 && (! is_pi_default(op)))
2318 pr2serr("--app-tag=, --ref-tag= and --tag-mask= options ignored "
2319 "with 16 byte commands\n");
2320
2321 /* examine .if_name . Open, move to .if_offset, calculate length that we
2322 * want to read. */
2323 if (! op->ndob) { /* as long as --same=1 is not active */
2324 if_len = op->if_dlen; /* from --offset=OFF,DLEN; defaults to 0 */
2325 if (NULL == op->if_name) {
2326 pr2serr("Need --if=FN option to be given, exiting.\n");
2327 if (vb > 1)
2328 pr2serr("To write zeros use --in=/dev/zero\n");
2329 pr2serr("\n");
2330 usage((op->help > 0) ? op->help : 0);
2331 return SG_LIB_SYNTAX_ERROR;
2332 }
2333 if ((1 == strlen(op->if_name)) && ('-' == op->if_name[0])) {
2334 got_stdin = true;
2335 infd = STDIN_FILENO;
2336 if (sg_set_binary_mode(STDIN_FILENO) < 0) {
2337 perror("sg_set_binary_mode");
2338 return SG_LIB_FILE_ERROR;
2339 }
2340 } else {
2341 if ((infd = open(op->if_name, O_RDONLY)) < 0) {
2342 err = errno;
2343 snprintf(ebuff, EBUFF_SZ, "could not open %s for reading",
2344 op->if_name);
2345 perror(ebuff);
2346 return sg_convert_errno(err);
2347 }
2348 if (sg_set_binary_mode(infd) < 0) {
2349 perror("sg_set_binary_mode");
2350 return SG_LIB_FILE_ERROR;
2351 }
2352 if (fstat(infd, &if_stat) < 0) {
2353 err = errno;
2354 snprintf(ebuff, EBUFF_SZ, "could not fstat %s", op->if_name);
2355 perror(ebuff);
2356 return sg_convert_errno(err);
2357 }
2358 got_stat = true;
2359 if (S_ISREG(if_stat.st_mode)) {
2360 if_reg_file = true;
2361 if_readable_len = if_stat.st_size;
2362 if (0 == if_len)
2363 if_len = if_readable_len;
2364 }
2365 }
2366 if (got_stat && if_readable_len &&
2367 ((int64_t)op->if_offset >= (if_readable_len - 1))) {
2368 pr2serr("Offset (%" PRIu64 ") is at or beyond IF byte length (%"
2369 PRIu64 ")\n", op->if_offset, (uint64_t)if_readable_len);
2370 goto file_err_out;
2371 }
2372 if (op->if_offset > 0) {
2373 off_t off = op->if_offset;
2374 off_t h = if_readable_len;
2375
2376 if (if_reg_file) {
2377 /* lseek() won't work with stdin, pipes or sockets, etc */
2378 if (lseek(infd, off, SEEK_SET) < 0) {
2379 err = errno;
2380 snprintf(ebuff, EBUFF_SZ, "couldn't offset to required "
2381 "position on %s", op->if_name);
2382 perror(ebuff);
2383 ret = sg_convert_errno(err);
2384 goto err_out;
2385 }
2386 if_readable_len -= op->if_offset;
2387 if (if_readable_len <= 0) {
2388 pr2serr("--offset [0x%" PRIx64 "] at or beyond file "
2389 "length[0x%" PRIx64 "]\n",
2390 (uint64_t)op->if_offset, (uint64_t)h);
2391 goto file_err_out;
2392 }
2393 if (op->strict && ((off_t)op->if_dlen > if_readable_len)) {
2394 pr2serr("after accounting for OFF, DLEN exceeds %s "
2395 "remaining length (%u bytes)\n",
2396 op->if_name, (uint32_t)if_readable_len);
2397 goto file_err_out;
2398 }
2399 if_len = (uint32_t)((if_readable_len < (off_t)if_len) ?
2400 if_readable_len : (off_t)if_len);
2401 if (vb > 2)
2402 pr2serr("Moved IF byte pointer to %u, if_len=%u, "
2403 "if_readable_len=%u\n", (uint32_t)op->if_offset,
2404 if_len, (uint32_t)if_readable_len);
2405 } else {
2406 if (vb)
2407 pr2serr("--offset=OFF ignored when IF is stdin, pipe, "
2408 "socket, etc\nDLEN, if given, is used\n");
2409 }
2410 }
2411 }
2412 /* Check device name has been given */
2413 if (NULL == op->device_name) {
2414 pr2serr("missing device name!\n");
2415 usage((op->help > 0) ? op->help : 0);
2416 goto syntax_err_out;
2417 }
2418
2419 /* Open device file, do READ CAPACITY(16, maybe 10) if no BS */
2420 sg_fd = sg_cmds_open_device(op->device_name, false /* rw */, vb);
2421 if (sg_fd < 0) {
2422 if (op->verbose)
2423 pr2serr("open error: %s: %s\n", op->device_name,
2424 safe_strerror(-sg_fd));
2425 ret = sg_convert_errno(-sg_fd);
2426 goto fini;
2427 }
2428 if (0 == op->bs) { /* ask DEVICE about logical/actual block size */
2429 ret = do_read_capacity(sg_fd, op);
2430 if (ret)
2431 goto err_out;
2432 }
2433 if ((0 == op->bs_pi_do) || (0 == op->bs)) {
2434 pr2serr("Logic error, need block size by now\n");
2435 goto syntax_err_out;
2436 }
2437 if (! op->ndob) {
2438 if (0 != (if_len % op->bs_pi_do)) {
2439 if (op->strict > 1) {
2440 pr2serr("Error: number of bytes to read from IF [%u] is "
2441 "not a multiple\nblock size %u (including "
2442 "protection information)\n", (unsigned int)if_len,
2443 op->bs_pi_do);
2444 goto file_err_out;
2445 }
2446 if (op->strict || vb)
2447 pr2serr("Warning: number of bytes to read from IF [%u] is "
2448 "not a multiple\nof actual block size %u; pad with "
2449 "zeros\n", (unsigned int)if_len, op->bs_pi_do);
2450 }
2451 }
2452
2453 /* decode --lba= and --num= options */
2454 memset(addr_arr, 0, sizeof(addr_arr));
2455 memset(num_arr, 0, sizeof(num_arr));
2456 addr_arr_len = 0;
2457 num_arr_len = 0;
2458 if (lba_op) {
2459 if (0 != build_lba_arr(lba_op, addr_arr, &addr_arr_len,
2460 MAX_NUM_ADDR)) {
2461 pr2serr("bad argument to '--lba'\n");
2462 goto syntax_err_out;
2463 }
2464 }
2465 if (num_op) {
2466 if (0 != build_num_arr(num_op, num_arr, &num_arr_len,
2467 MAX_NUM_ADDR)) {
2468 pr2serr("bad argument to '--num'\n");
2469 goto err_out;
2470 }
2471 }
2472 if (((addr_arr_len > 1) && (addr_arr_len != num_arr_len)) ||
2473 ((0 == addr_arr_len) && (num_arr_len > 1))) {
2474 /* allow all combinations of 0 or 1 element --lba= with 0 or 1
2475 * element --num=, otherwise this error ... */
2476 pr2serr("need same number of arguments to '--lba=' and '--num=' "
2477 "options\n");
2478 ret = SG_LIB_CONTRADICT;
2479 goto err_out;
2480 }
2481 if ((0 == addr_arr_len) && (1 == num_arr_len)) {
2482 if (num_arr[0] > 0) {
2483 pr2serr("won't write %u blocks without an explicit --lba= "
2484 "option\n", num_arr[0]);
2485 goto syntax_err_out;
2486 }
2487 addr_arr_len = 1; /* allow --num=0 without --lba= since it is safe */
2488 }
2489 /* Everything can use a SF, except --same=1 (when op->ndob==true) */
2490 if (op->scat_filename) {
2491 if (stat(op->scat_filename, &sf_stat) < 0) {
2492 err = errno;
2493 pr2serr("Unable to stat(%s) as SF: %s\n", op->scat_filename,
2494 safe_strerror(err));
2495 ret = sg_convert_errno(err);
2496 goto err_out;
2497 }
2498 if (op->do_scat_raw) {
2499 if (! S_ISREG(sf_stat.st_mode)) {
2500 pr2serr("Expect scatter file to be a regular file\n");
2501 goto file_err_out;
2502 }
2503 sf_len = sf_stat.st_size;
2504 sfr_fd = open(op->scat_filename, O_RDONLY);
2505 if (sfr_fd < 0) {
2506 err = errno;
2507 pr2serr("Failed to open %s for raw read: %s\n",
2508 op->scat_filename, safe_strerror(err));
2509 ret = sg_convert_errno(err);
2510 goto err_out;
2511 }
2512 if (sg_set_binary_mode(sfr_fd) < 0) {
2513 perror("sg_set_binary_mode");
2514 goto file_err_out;
2515 }
2516 } else { /* scat_file should contain ASCII hex, preliminary parse */
2517 nn = (op->scat_num_lbard > 0) ?
2518 lbard_sz * (1 + op->scat_num_lbard) : 0;
2519 ret = build_t10_scat(op->scat_filename, op->do_16,
2520 ! op->do_scattered, NULL, &num_lbard,
2521 &sum_num, nn);
2522 if (ret)
2523 goto err_out;
2524 if ((op->scat_num_lbard > 0) &&
2525 (num_lbard != op->scat_num_lbard)) {
2526 bool rd_gt = (op->scat_num_lbard > num_lbard);
2527
2528 if (rd_gt || op->strict || vb) {
2529 pr2serr("RD (%u) %s number of %ss (%u) found in SF\n",
2530 op->scat_num_lbard, (rd_gt ? ">" : "<"),
2531 lbard_str, num_lbard);
2532 if (rd_gt)
2533 goto file_err_out;
2534 else if (op->strict)
2535 goto file_err_out;
2536 }
2537 }
2538 }
2539 }
2540
2541 if (op->do_scattered) {
2542 ret = process_scattered(sg_fd, infd, if_len, if_readable_len, sfr_fd,
2543 sf_len, addr_arr, addr_arr_len, num_arr,
2544 num_lbard, sum_num, op);
2545 goto fini;
2546 }
2547
2548 /* other than scattered */
2549 if (addr_arr_len > 0) {
2550 op->lba = addr_arr[0];
2551 op->numblocks = num_arr[0];
2552 if (vb && (addr_arr_len > 1))
2553 pr2serr("warning: %d LBA,number_of_blocks pairs found, only "
2554 "taking first\n", addr_arr_len);
2555 } else if (op->scat_filename && (! op->do_scat_raw)) {
2556 uint8_t upp[96];
2557
2558 sum_num = 0;
2559 ret = build_t10_scat(op->scat_filename, op->do_16,
2560 true /* parse one */, upp, &num_lbard,
2561 &sum_num, sizeof(upp));
2562 if (ret)
2563 goto err_out;
2564 if (vb && (num_lbard > 1))
2565 pr2serr("warning: %d LBA,number_of_blocks pairs found, only "
2566 "taking first\n", num_lbard);
2567 if (vb > 2)
2568 pr2serr("after build_t10_scat, num_lbard=%u, sum_num=%u\n",
2569 num_lbard, sum_num);
2570 if (1 != num_lbard) {
2571 pr2serr("Unable to decode one LBA range descriptor from %s\n",
2572 op->scat_filename);
2573 goto file_err_out;
2574 }
2575 op->lba = sg_get_unaligned_be64(upp + 32 + 0);
2576 op->numblocks = sg_get_unaligned_be32(upp + 32 + 8);
2577 if (op->do_32) {
2578 op->ref_tag = sg_get_unaligned_be32(upp + 32 + 12);
2579 op->app_tag = sg_get_unaligned_be16(upp + 32 + 16);
2580 op->tag_mask = sg_get_unaligned_be16(upp + 32 + 18);
2581 }
2582 } else if (op->do_scat_raw) {
2583 uint8_t upp[64];
2584
2585 if (sf_len < (2 * lbard_sz)) {
2586 pr2serr("raw scatter file must be at least 64 bytes long "
2587 "(length: %u)\n", sf_len);
2588 goto file_err_out;
2589 }
2590 ret = bin_read(sfr_fd, upp, sizeof(upp), "SF");
2591 if (ret)
2592 goto err_out;
2593 if (! check_lbrds(upp, sizeof(upp), op, &num_lbard, &sum_num))
2594 goto file_err_out;
2595 if (1 != num_lbard) {
2596 pr2serr("No %ss found in SF (num=%u)\n", lbard_str, num_lbard);
2597 goto file_err_out;
2598 }
2599 op->lba = sg_get_unaligned_be64(upp + 16);
2600 op->numblocks = sg_get_unaligned_be32(upp + 16 + 8);
2601 do_len = sum_num * op->bs_pi_do;
2602 op->xfer_bytes = do_len;
2603 } else {
2604 pr2serr("No LBA or number_of_blocks given, try using --lba= and "
2605 "--num=\n");
2606 goto syntax_err_out;
2607 }
2608 if (op->do_same)
2609 op->xfer_bytes = op->ndob ? 0 : op->bs_pi_do;
2610 else /* WRITE, ORWRITE, WRITE ATOMIC or WRITE STREAM */
2611 op->xfer_bytes = op->numblocks * op->bs_pi_do;
2612 do_len = op->xfer_bytes;
2613
2614 if (do_len > 0) {
2615 /* fill allocated buffer with zeros */
2616 up = sg_memalign(do_len, 0, &free_up, false);
2617 if (NULL == up) {
2618 pr2serr("unable to allocate %u bytes of memory\n", do_len);
2619 ret = sg_convert_errno(ENOMEM);
2620 goto err_out;
2621 }
2622 ret = bin_read(infd, up, ((if_len < do_len) ? if_len : do_len),
2623 "IF 5");
2624 if (ret)
2625 goto fini;
2626 } else
2627 up = NULL;
2628
2629 ret = do_write_x(sg_fd, up, do_len, op);
2630 if (ret && (! op->do_quiet)) {
2631 strcpy(b,"OS error");
2632 if (ret > 0)
2633 sg_get_category_sense_str(ret, sizeof(b), b, vb);
2634 pr2serr("%s: %s\n", op->cdb_name, b);
2635 }
2636 goto fini;
2637
2638 syntax_err_out:
2639 ret = SG_LIB_SYNTAX_ERROR;
2640 goto err_out;
2641 file_err_out:
2642 ret = SG_LIB_FILE_ERROR;
2643 err_out:
2644 fini:
2645 if (free_up)
2646 free(free_up);
2647 if (sg_fd >= 0) {
2648 res = sg_cmds_close_device(sg_fd);
2649 if (res < 0) {
2650 if (! op->do_quiet)
2651 pr2serr("sg_fd close error: %s\n", safe_strerror(-res));
2652 if (0 == ret)
2653 ret = SG_LIB_FILE_ERROR;
2654 }
2655 }
2656 if (sfr_fd >= 0) {
2657 if (close(sfr_fd) < 0) {
2658 if (! op->do_quiet)
2659 perror("sfr_fd close error");
2660 if (0 == ret)
2661 ret = SG_LIB_FILE_ERROR;
2662 }
2663 }
2664 if ((! got_stdin) && (infd >= 0)) {
2665 if (close(infd) < 0) {
2666 if (! op->do_quiet)
2667 perror("infd close error");
2668 if (0 == ret)
2669 ret = SG_LIB_FILE_ERROR;
2670 }
2671 }
2672 if ((0 == op->verbose) && (! op->do_quiet)) {
2673 if (! sg_if_can2stderr("sg_write_x failed: ", ret))
2674 pr2serr("Some error occurred, try again with '-v' or '-vv' for "
2675 "more information\n");
2676 }
2677 return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
2678 }
2679