1 /*
2 * Copyright (c) 2008-2014 Douglas Gilbert.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 /* ddpt is a utility program for copying files. It broadly follows the syntax
31 * and semantics of the "dd" program found in Unix. ddpt is specialised for
32 * "files" that represent storage devices, especially those that understand
33 * the SCSI command set accessed via a pass-through.
34 */
35
36 /*
37 * The ddpt utility is a rewritten and extended version of the sg_dd utility
38 * found in the sg3_utils package. sg_dd has a GPL (version 2) which has been
39 * changed to a somewhat freer FreeBSD style license in ddpt.
40 * Both licenses are considered "open source".
41 *
42 * Windows "block" devices, when _not_ accessed via the pass-through, don't
43 * seem to work when POSIX/Unix like IO calls are used (e.g. write()).
44 * So need CreateFile, ReadFile, WriteFile, SetFilePointer and friends.
45 */
46
47 /* Need _GNU_SOURCE for O_DIRECT */
48 #ifndef _GNU_SOURCE
49 #define _GNU_SOURCE
50 #endif
51
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <ctype.h>
57 #include <errno.h>
58 #include <limits.h>
59 #include <fcntl.h>
60 #define __STDC_FORMAT_MACROS 1
61 #include <inttypes.h>
62 #include <sys/types.h>
63 #include <sys/stat.h>
64
65 /* N.B. config.h must precede anything that depends on HAVE_* */
66 #ifdef HAVE_CONFIG_H
67 #include "config.h"
68 #endif
69
70
71 static const char * ddpt_version_str = "0.95 20141226 [svn: r307]";
72
73 #ifdef SG_LIB_LINUX
74 #include <sys/ioctl.h>
75 #include <sys/sysmacros.h>
76 #include <sys/file.h>
77 #include <linux/major.h>
78 #include <linux/fs.h> /* <sys/mount.h> */
79 #include <linux/mtio.h> /* For tape ioctls */
80 #ifndef MTWEOFI
81 #define MTWEOFI 35 /* write an end-of-file record (mark) in immediate mode */
82 #endif
83
84 #ifdef HAVE_FALLOCATE
85 #include <linux/falloc.h>
86 #ifndef FALLOC_FL_KEEP_SIZE
87 #define FALLOC_FL_KEEP_SIZE 0x01 /* from lk 3.1 linux/falloc.h */
88 #endif
89 #endif
90
91 #endif /* SG_LIB_LINUX */
92
93 #ifdef SG_LIB_FREEBSD
94 #include <sys/ioctl.h>
95 #include <libgen.h>
96 #ifndef __DragonFly__
97 #include <sys/disk.h>
98 #endif
99 #include <sys/filio.h>
100 #endif
101
102 #ifdef SG_LIB_SOLARIS
103 #include <sys/ioctl.h>
104 #include <sys/dkio.h>
105 #endif
106
107 #ifdef SG_LIB_WIN32
108 #ifndef SG_LIB_MINGW
109 /* cygwin */
110 #include <sys/ioctl.h>
111 #endif
112 #endif
113
114 #include "ddpt.h"
115 #include "sg_lib.h"
116
117 #ifndef EREMOTEIO
118 #define EREMOTEIO EIO
119 #endif
120
121 /* Used for outputting diagnostic messages for oflag=pre-alloc */
122 #define PREALLOC_DEBUG 1
123
124
125
126 /* Returns open input file descriptor (>= 0) or a negative value
127 * (-SG_LIB_FILE_ERROR or -SG_LIB_CAT_OTHER) if error.
128 */
129 static int
open_if(struct opts_t * op)130 open_if(struct opts_t * op)
131 {
132 int flags;
133 int fd = -SG_LIB_FILE_ERROR;
134 char ebuff[EBUFF_SZ];
135 struct flags_t * ifp = op->iflagp;
136 struct dev_info_t * idip = op->idip;
137 const char * ifn = idip->fn;
138
139 idip->d_type = dd_filetype(ifn, op->verbose);
140 if (FT_ERROR & idip->d_type) {
141 pr2serr("unable to access %s\n", ifn);
142 goto file_err;
143 } else if (((FT_BLOCK | FT_TAPE | FT_OTHER) & idip->d_type) && ifp->pt)
144 idip->d_type |= FT_PT;
145 if (op->verbose)
146 pr2serr(" >> Input file type: %s\n",
147 dd_filetype_str(idip->d_type, ebuff, EBUFF_SZ, ifn));
148 if (!(FT_PT & idip->d_type) && op->rdprotect)
149 pr2serr("rdprotect ignored on non-pt device\n");
150 if ((FT_FIFO | FT_CHAR | FT_TAPE) & idip->d_type)
151 ++op->reading_fifo;
152
153 if ((FT_TAPE & idip->d_type) && (FT_PT & idip->d_type)) {
154 pr2serr("SCSI tape device %s not supported via pt\n", ifn);
155 goto file_err;
156 }
157 if (FT_PT & idip->d_type) {
158 fd = pt_open_if(op, NULL);
159 if (-1 == fd)
160 goto file_err;
161 else if (fd < -1)
162 goto other_err;
163 }
164 #ifdef SG_LIB_WIN32
165 else if (FT_BLOCK & idip->d_type) {
166 if (win32_open_if(op, (ifp->excl ? O_EXCL : 0), op->verbose))
167 goto file_err;
168 fd = 0;
169 }
170 #endif
171 else {
172 flags = O_RDONLY;
173 if (ifp->direct)
174 flags |= O_DIRECT;
175 if (ifp->excl)
176 flags |= O_EXCL;
177 if (ifp->sync)
178 flags |= O_SYNC;
179 fd = open(ifn, flags);
180 if (fd < 0) {
181 pr2serr("could not open %s for reading: %s\n", ifn,
182 safe_strerror(errno));
183 goto file_err;
184 } else {
185 if (sg_set_binary_mode(fd) < 0)
186 perror("sg_set_binary_mode");
187 if (op->verbose)
188 pr2serr(" open %s, flags=0x%x\n", ifn, flags);
189 #ifdef HAVE_POSIX_FADVISE
190 if (ifp->nocache) {
191 int rt;
192
193 rt = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
194 if (rt)
195 pr2serr("%s: posix_fadvise(SEQUENTIAL), err=%d\n",
196 __func__, rt);
197 }
198 #endif
199 }
200 }
201 #ifdef SG_LIB_LINUX
202 if (ifp->flock) {
203 int res;
204
205 res = flock(fd, LOCK_EX | LOCK_NB);
206 if (res < 0) {
207 close(fd);
208 pr2serr("flock(LOCK_EX | LOCK_NB) on %s failed: %s\n",
209 ifn, safe_strerror(errno));
210 return -SG_LIB_FLOCK_ERR;
211 }
212 }
213 #endif
214 return fd;
215
216 file_err:
217 return -SG_LIB_FILE_ERROR;
218 other_err:
219 return -SG_LIB_CAT_OTHER;
220 }
221
222 /* Returns open output file descriptor (>= 0), -1 for don't
223 * bother opening (e.g. /dev/null), or a more negative value
224 * (-SG_LIB_FILE_ERROR or -SG_LIB_CAT_OTHER) if error.
225 */
226 static int
open_of(struct opts_t * op)227 open_of(struct opts_t * op)
228 {
229 int flags;
230 int fd = -SG_LIB_FILE_ERROR;
231 int outf_exists = 0;
232 char ebuff[EBUFF_SZ];
233 struct stat st;
234 struct flags_t * ofp = op->oflagp;
235 struct dev_info_t * odip = op->odip;
236 const char * ofn = odip->fn;
237
238 odip->d_type = dd_filetype(ofn, op->verbose);
239 if (((FT_BLOCK | FT_TAPE | FT_OTHER) & odip->d_type) && ofp->pt)
240 odip->d_type |= FT_PT;
241 odip->d_type_hold = odip->d_type;
242 if (op->verbose)
243 pr2serr(" >> Output file type: %s\n",
244 dd_filetype_str(odip->d_type, ebuff, EBUFF_SZ, ofn));
245 if (!(FT_PT & odip->d_type) && op->wrprotect)
246 pr2serr("wrprotect ignored on non-pt device\n");
247
248 if ((FT_TAPE & odip->d_type) && (FT_PT & odip->d_type)) {
249 pr2serr("SCSI tape device %s not supported via pt\n", ofn);
250 goto file_err;
251 }
252 if (FT_PT & odip->d_type) {
253 fd = pt_open_of(op, NULL);
254 if (-1 == fd)
255 goto file_err;
256 else if (fd < -1)
257 goto other_err;
258 } else if (FT_DEV_NULL & odip->d_type)
259 fd = -1; /* don't bother opening */
260 #ifdef SG_LIB_WIN32
261 else if (FT_BLOCK & odip->d_type) {
262 if (win32_open_of(op, (ofp->excl ? O_EXCL : 0), op->verbose))
263 goto file_err;
264 fd = 0;
265 }
266 #endif
267 else { /* typically regular file or block device node */
268 int needs_ftruncate = 0;
269 int64_t offset = 0;
270
271 memset(&st, 0, sizeof(st));
272 if (0 == stat(ofn, &st))
273 outf_exists = 1;
274 else if (ofp->pt) {
275 /* if oflag=pt, then creating a regular file is unhelpful */
276 pr2serr("Cannot create a regular file called %s as a pt\n", ofn);
277 goto other_err;
278 }
279 flags = ofp->sparing ? O_RDWR : O_WRONLY;
280 if (0 == outf_exists)
281 flags |= O_CREAT;
282 if (ofp->direct)
283 flags |= O_DIRECT;
284 if (ofp->excl)
285 flags |= O_EXCL;
286 if (ofp->sync)
287 flags |= O_SYNC;
288 if (ofp->append)
289 flags |= O_APPEND;
290 if ((FT_REG & odip->d_type) && outf_exists && ofp->trunc &&
291 (! ofp->nowrite)) {
292 if (op->seek > 0) {
293 offset = op->seek * op->obs;
294 if (st.st_size > offset)
295 ++needs_ftruncate; // only truncate to shorten
296 } else
297 flags |= O_TRUNC;
298 }
299 if ((fd = open(ofn, flags, 0666)) < 0) {
300 pr2serr("could not open %s for writing: %s\n", ofn,
301 safe_strerror(errno));
302 goto file_err;
303 }
304 if (needs_ftruncate && (offset > 0)) {
305 if (ftruncate(fd, offset) < 0) {
306 pr2serr("could not ftruncate %s after open (seek): %s\n",
307 ofn, safe_strerror(errno));
308 goto file_err;
309 }
310 /* N.B. file offset (pointer) not changed by ftruncate */
311 }
312 if ((! outf_exists) && (FT_ERROR & odip->d_type)) {
313 odip->d_type = FT_REG; /* exists now */
314 odip->d_type_hold = odip->d_type;
315 }
316 if (sg_set_binary_mode(fd) < 0)
317 perror("sg_set_binary_mode");
318 if (op->verbose) {
319 pr2serr(" %s %s, flags=0x%x\n",
320 (outf_exists ? "open" : "create"), ofn, flags);
321 if (needs_ftruncate && (offset > 0))
322 pr2serr(" truncated file at byte offset "
323 "%" PRId64 " \n", offset);
324 }
325 }
326 #ifdef SG_LIB_LINUX
327 if (ofp->flock) {
328 int res;
329
330 res = flock(fd, LOCK_EX | LOCK_NB);
331 if (res < 0) {
332 close(fd);
333 pr2serr("flock(LOCK_EX | LOCK_NB) on %s failed: %s\n",
334 ofn, safe_strerror(errno));
335 return -SG_LIB_FLOCK_ERR;
336 }
337 }
338 #endif
339 return fd;
340
341 file_err:
342 return -SG_LIB_FILE_ERROR;
343 other_err:
344 return -SG_LIB_CAT_OTHER;
345 }
346
347 /* Helper for calc_count(). Attempts to size IFILE. Returns 0 if no error
348 * detected. */
349 static int
calc_count_in(struct opts_t * op,int64_t * in_num_blksp)350 calc_count_in(struct opts_t * op, int64_t * in_num_blksp)
351 {
352 int res;
353 struct stat st;
354 int in_blk_sz, in_type;
355 #ifndef SG_LIB_WIN32
356 int64_t num_blks, t;
357 int blk_sz;
358 #endif
359 const char * ifn = op->idip->fn;
360
361 *in_num_blksp = -1;
362 in_type = op->idip->d_type;
363 if (FT_PT & in_type) {
364 if (op->iflagp->norcap) {
365 if ((FT_BLOCK & in_type) && (0 == op->iflagp->force)) {
366 pr2serr(">> warning: norcap on input block device "
367 "accessed via pt is risky.\n");
368 pr2serr(">> Abort copy, use iflag=force to override.\n");
369 return -1;
370 }
371 return 0;
372 }
373 res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp, &in_blk_sz);
374 if (SG_LIB_CAT_UNIT_ATTENTION == res) {
375 pr2serr("Unit attention (readcap in), continuing\n");
376 res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp,
377 &in_blk_sz);
378 } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
379 pr2serr("Aborted command (readcap in), continuing\n");
380 res = pt_read_capacity(op, DDPT_ARG_IN, in_num_blksp,
381 &in_blk_sz);
382 }
383 if (0 != res) {
384 if (res == SG_LIB_CAT_INVALID_OP)
385 pr2serr("read capacity not supported on %s\n", ifn);
386 else if (res == SG_LIB_CAT_NOT_READY)
387 pr2serr("read capacity failed on %s - not ready\n", ifn);
388 else
389 pr2serr("Unable to read capacity on %s\n", ifn);
390 *in_num_blksp = -1;
391 return res;
392 } else {
393 if (op->verbose) {
394 print_blk_sizes(ifn, "readcap", *in_num_blksp, in_blk_sz, 1);
395 if (op->idip->prot_type > 0)
396 pr2serr(" reports Protection_type=%d, p_i_exp=%d\n",
397 op->idip->prot_type, op->idip->p_i_exp);
398 }
399 if ((*in_num_blksp > 0) && (in_blk_sz != op->ibs)) {
400 pr2serr(">> warning: %s block size confusion: ibs=%d, "
401 "device claims=%d\n", ifn, op->ibs, in_blk_sz);
402 if (0 == op->iflagp->force) {
403 pr2serr(">> abort copy, use iflag=force to override\n");
404 return -1;
405 }
406 }
407 }
408 #ifndef SG_LIB_WIN32
409 if ((FT_BLOCK & in_type) && (0 == op->iflagp->force) &&
410 (0 == get_blkdev_capacity(op, DDPT_ARG_IN, &num_blks,
411 &blk_sz))) {
412 t = (*in_num_blksp) * in_blk_sz;
413 if (t != (num_blks * blk_sz)) {
414 pr2serr(">> warning: Size of input block device is "
415 "different from pt size.\n>> Pass-through on block "
416 "partition can give unexpected offsets.\n");
417 pr2serr(">> Abort copy, use iflag=force to override.\n");
418 return -1;
419 }
420 }
421 #endif
422 } else if ((op->dd_count > 0) && (0 == op->oflagp->resume))
423 return 0;
424 else if (FT_BLOCK & in_type) {
425 if (0 != get_blkdev_capacity(op, DDPT_ARG_IN, in_num_blksp,
426 &in_blk_sz)) {
427 pr2serr("Unable to read block capacity on %s\n", ifn);
428 *in_num_blksp = -1;
429 }
430 if (op->verbose)
431 print_blk_sizes(ifn, "blk", *in_num_blksp, in_blk_sz, 1);
432 if ((*in_num_blksp > 0) && (op->ibs != in_blk_sz)) {
433 pr2serr(">> warning: %s block size confusion: bs=%d, "
434 "device claims=%d\n", ifn, op->ibs, in_blk_sz);
435 *in_num_blksp = -1;
436 }
437 } else if (FT_REG & in_type) {
438 if (fstat(op->idip->fd, &st) < 0) {
439 perror("fstat(idip->fd) error");
440 *in_num_blksp = -1;
441 } else {
442 *in_num_blksp = st.st_size / op->ibs;
443 res = st.st_size % op->ibs;
444 if (op->verbose) {
445 print_blk_sizes(ifn, "reg", *in_num_blksp, op->ibs, 1);
446 if (res)
447 pr2serr(" residual_bytes=%d\n", res);
448 }
449 if (res)
450 ++*in_num_blksp;
451 }
452 }
453 return 0;
454 }
455
456 /* Helper for calc_count(). Attempts to size OFILE. Returns 0 if no error
457 * detected. */
458 static int
calc_count_out(struct opts_t * op,int64_t * out_num_blksp)459 calc_count_out(struct opts_t * op, int64_t * out_num_blksp)
460 {
461 int res;
462 struct stat st;
463 int out_blk_sz, out_type;
464 #ifndef SG_LIB_WIN32
465 int64_t num_blks, t;
466 int blk_sz;
467 #endif
468 const char * ofn = op->odip->fn;
469
470 *out_num_blksp = -1;
471 out_type = op->odip->d_type;
472 if (FT_PT & out_type) {
473 if (op->oflagp->norcap) {
474 if ((FT_BLOCK & out_type) && (0 == op->oflagp->force)) {
475 pr2serr(">> warning: norcap on output block device "
476 "accessed via pt is risky.\n");
477 pr2serr(">> Abort copy, use oflag=force to override.\n");
478 return -1;
479 }
480 return 0;
481 }
482 res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp, &out_blk_sz);
483 if (SG_LIB_CAT_UNIT_ATTENTION == res) {
484 pr2serr("Unit attention (readcap out), continuing\n");
485 res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp,
486 &out_blk_sz);
487 } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
488 pr2serr("Aborted command (readcap out), continuing\n");
489 res = pt_read_capacity(op, DDPT_ARG_OUT, out_num_blksp,
490 &out_blk_sz);
491 }
492 if (0 != res) {
493 if (res == SG_LIB_CAT_INVALID_OP)
494 pr2serr("read capacity not supported on %s\n", ofn);
495 else
496 pr2serr("Unable to read capacity on %s\n", ofn);
497 *out_num_blksp = -1;
498 return res;
499 } else {
500 if (op->verbose) {
501 print_blk_sizes(ofn, "readcap", *out_num_blksp, out_blk_sz,
502 1);
503 if (op->odip->prot_type > 0)
504 pr2serr(" reports Protection_type=%d, p_i_exp=%d\n",
505 op->odip->prot_type, op->odip->p_i_exp);
506 }
507 if ((*out_num_blksp > 0) && (op->obs != out_blk_sz)) {
508 pr2serr(">> warning: %s block size confusion: "
509 "obs=%d, device claims=%d\n", ofn, op->obs,
510 out_blk_sz);
511 if (0 == op->oflagp->force) {
512 pr2serr(">> abort copy, use oflag=force to override\n");
513 return -1;
514 }
515 }
516 }
517 #ifndef SG_LIB_WIN32
518 if ((FT_BLOCK & out_type) && (0 == op->oflagp->force) &&
519 (0 == get_blkdev_capacity(op, DDPT_ARG_OUT, &num_blks,
520 &blk_sz))) {
521 t = (*out_num_blksp) * out_blk_sz;
522 if (t != (num_blks * blk_sz)) {
523 pr2serr(">> warning: size of output block device is "
524 "different from pt size.\n>> Pass-through on block "
525 "partition can give unexpected results.\n");
526 pr2serr(">> abort copy, use oflag=force to override\n");
527 return -1;
528 }
529 }
530 #endif
531 } else if ((op->dd_count > 0) && (0 == op->oflagp->resume))
532 return 0;
533 if (FT_BLOCK & out_type) {
534 if (0 != get_blkdev_capacity(op, DDPT_ARG_OUT, out_num_blksp,
535 &out_blk_sz)) {
536 pr2serr("Unable to read block capacity on %s\n", ofn);
537 *out_num_blksp = -1;
538 } else {
539 if (op->verbose)
540 print_blk_sizes(ofn, "blk", *out_num_blksp, out_blk_sz, 1);
541 if ((*out_num_blksp > 0) && (op->obs != out_blk_sz)) {
542 pr2serr(">> warning: %s block size confusion: obs=%d, "
543 "device claims=%d\n", ofn, op->obs, out_blk_sz);
544 *out_num_blksp = -1;
545 }
546 }
547 } else if (FT_REG & out_type) {
548 if (fstat(op->odip->fd, &st) < 0) {
549 perror("fstat(odip->fd) error");
550 *out_num_blksp = -1;
551 } else {
552 *out_num_blksp = st.st_size / op->obs;
553 res = st.st_size % op->obs;
554 if (op->verbose) {
555 print_blk_sizes(ofn, "reg", *out_num_blksp, op->obs, 1);
556 if (res)
557 pr2serr(" residual_bytes=%d\n", res);
558 }
559 if (res)
560 ++*out_num_blksp;
561 }
562 }
563 return 0;
564 }
565
566
567 /* Calculates the number of blocks associated with the in and out files.
568 * May also yield the block size in bytes of devices. For regular files
569 * uses ibs or obs as the logical block size. Returns 0 for continue,
570 * otherwise bypass copy and exit. */
571 static int
calc_count(struct opts_t * op,int64_t * in_num_blksp,int64_t * out_num_blksp)572 calc_count(struct opts_t * op, int64_t * in_num_blksp,
573 int64_t * out_num_blksp)
574 {
575 int res;
576
577 res = calc_count_in(op, in_num_blksp);
578 if (res) {
579 *out_num_blksp = -1;
580 return res;
581 }
582 return calc_count_out(op, out_num_blksp);
583 }
584
585 #ifdef HAVE_POSIX_FADVISE
586 /* Used by iflag=nocache and oflag=nocache to suggest (via posix_fadvise()
587 * system call) that the OS doesn't cache data it has just read or written
588 * since it is unlikely to be used again in the short term. iflag=nocache
589 * additionally increases the read-ahead. Errors ignored. */
590 static void
do_fadvise(struct opts_t * op,int bytes_if,int bytes_of,int bytes_of2)591 do_fadvise(struct opts_t * op, int bytes_if, int bytes_of, int bytes_of2)
592 {
593 int rt, in_valid, out2_valid, out_valid, id_type, od_type, o2d_type;
594
595 id_type = op->idip->d_type;
596 od_type = op->odip->d_type;
597 o2d_type = op->o2dip->d_type;
598 in_valid = ((FT_REG == id_type) || (FT_BLOCK == id_type));
599 out2_valid = ((FT_REG == o2d_type) || (FT_BLOCK == o2d_type));
600 out_valid = ((FT_REG == od_type) || (FT_BLOCK == od_type));
601 if (op->iflagp->nocache && (bytes_if > 0) && in_valid) {
602 if ((op->lowest_skip < 0) || (op->skip > op->lowest_skip))
603 op->lowest_skip = op->skip;
604 rt = posix_fadvise(op->idip->fd, (op->lowest_skip * op->ibs),
605 ((op->skip - op->lowest_skip) * op->ibs) + bytes_if,
606 POSIX_FADV_DONTNEED);
607 if (rt) /* returns error as result */
608 pr2serr("posix_fadvise on read, skip=%" PRId64 " ,err=%d\n",
609 op->skip, rt);
610 }
611 if ((op->oflagp->nocache & 2) && (bytes_of2 > 0) && out2_valid) {
612 rt = posix_fadvise(op->o2dip->fd, 0, 0, POSIX_FADV_DONTNEED);
613 if (rt)
614 pr2serr("posix_fadvise on of2, seek=%" PRId64 " ,err=%d\n",
615 op->seek, rt);
616 }
617 if ((op->oflagp->nocache & 1) && (bytes_of > 0) && out_valid) {
618 if ((op->lowest_seek < 0) || (op->seek > op->lowest_seek))
619 op->lowest_seek = op->seek;
620 rt = posix_fadvise(op->odip->fd, (op->lowest_seek * op->obs),
621 ((op->seek - op->lowest_seek) * op->obs) + bytes_of,
622 POSIX_FADV_DONTNEED);
623 if (rt)
624 pr2serr("posix_fadvise on output, seek=%" PRId64 " , err=%d\n",
625 op->seek, rt);
626 }
627 }
628 #endif
629
630 /* Main copy loop's read (input) via pt. Returns 0 on success, else see
631 * pt_read()'s return values. */
632 static int
cp_read_pt(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)633 cp_read_pt(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp)
634 {
635 int res;
636 int blks_read = 0;
637
638 res = pt_read(op, 0, bp, csp->icbpt, &blks_read);
639 if (res) {
640 if (0 == blks_read) {
641 pr2serr("pt_read failed,%s at or after lba=%" PRId64 " "
642 "[0x%" PRIx64 "]\n",
643 ((-2 == res) ? " try reducing bpt," : ""),
644 op->skip, op->skip);
645 return res;
646 }
647 /* limp on if data, should stop after write; hold err number */
648 op->err_to_report = res;
649 }
650 if (blks_read < csp->icbpt) {
651 /* assume close to end, or some data prior to read error */
652 if (op->verbose > 1)
653 pr2serr("short read, requested %d blocks, got %d blocks\n",
654 csp->icbpt, blks_read);
655 ++csp->leave_after_write;
656 /* csp->leave_reason = 0; assume at end rather than error */
657 csp->icbpt = blks_read;
658 /* round down since don't do partial writes from pt reads */
659 csp->ocbpt = (blks_read * op->ibs) / op->obs;
660 }
661 op->in_full += csp->icbpt;
662 return 0;
663 }
664
665 /* Error occurred on block/regular read. coe active so assume all full
666 * blocks prior to error are good (if any) and start to read from the
667 * block containing the error, one block at a time, until ibpt. Supply
668 * zeros for unreadable blocks. Return 0 if successful, SG_LIB_CAT_OTHER
669 * if error other than EIO or EREMOTEIO, SG_LIB_FILE_ERROR if lseek fails,
670 * and SG_LIB_CAT_MEDIUM_HARD if the coe_limit is exceeded. */
671 static int
coe_cp_read_block_reg(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp,int numread_errno)672 coe_cp_read_block_reg(struct opts_t * op, struct cp_state_t * csp,
673 unsigned char * bp, int numread_errno)
674 {
675 int res, res2, k, total_read, num_read;
676 int ibs = op->ibs_pi;
677 int64_t offset, off_res, my_skip;
678
679 if (0 == numread_errno) {
680 csp->icbpt = 0;
681 csp->ocbpt = 0;
682 ++csp->leave_after_write;
683 csp->leave_reason = 0;
684 return 0; /* EOF */
685 } else if (numread_errno < 0) {
686 if ((-EIO == numread_errno) || (-EREMOTEIO == numread_errno)) {
687 num_read = 0;
688 if (1 == csp->icbpt) {
689 // Don't read again, this must be bad block
690 memset(bp, 0, ibs);
691 if ((res2 = coe_process_eio(op, op->skip)))
692 return res2;
693 ++op->in_full;
694 csp->bytes_read += ibs;
695 return 0;
696 }
697 } else
698 return SG_LIB_CAT_OTHER;
699 } else
700 num_read = (numread_errno / ibs) * ibs;
701
702 k = num_read / ibs;
703 if (k > 0) {
704 op->in_full += k;
705 zero_coe_limit_count(op);
706 }
707 csp->bytes_read = num_read;
708 my_skip = op->skip + k;
709 offset = my_skip * ibs;
710 bp += num_read;
711 for ( ; k < csp->icbpt; ++k, ++my_skip, bp += ibs, offset += ibs) {
712 if (offset != csp->if_filepos) {
713 if (op->verbose > 2)
714 pr2serr("moving if filepos: new_pos=%" PRId64 "\n",
715 (int64_t)offset);
716 off_res = lseek(op->idip->fd, offset, SEEK_SET);
717 if (off_res < 0) {
718 pr2serr("failed moving if filepos: new_pos="
719 "%" PRId64 "\nlseek on input: %s\n", (int64_t)offset,
720 safe_strerror(errno));
721 return SG_LIB_FILE_ERROR;
722 }
723 csp->if_filepos = offset;
724 }
725 memset(bp, 0, ibs);
726 while (((res = read(op->idip->fd, bp, ibs)) < 0) &&
727 (EINTR == errno))
728 ++op->interrupted_retries;
729 if (0 == res) {
730 csp->leave_reason = 0;
731 goto short_read;
732 } else if (res < 0) {
733 if ((EIO == errno) || (EREMOTEIO == errno)) {
734 if ((res2 = coe_process_eio(op, my_skip)))
735 return res2;
736 } else {
737 pr2serr("reading 1 block, skip=%" PRId64 " : %s\n", my_skip,
738 safe_strerror(errno));
739 csp->leave_reason = SG_LIB_CAT_OTHER;
740 goto short_read;
741 }
742 } else if (res < ibs) {
743 if (op->verbose)
744 pr2serr("short read at skip=%" PRId64 " , wanted=%d, "
745 "got=%d bytes\n", my_skip, ibs, res);
746 csp->leave_reason = 0; /* assume EOF */
747 goto short_read;
748 } else { /* if (res == ibs) */
749 zero_coe_limit_count(op);
750 csp->if_filepos += ibs;
751 if (op->verbose > 2)
752 pr2serr("reading 1 block, skip=%" PRId64 " : okay\n",
753 my_skip);
754 }
755 ++op->in_full;
756 csp->bytes_read += ibs;
757 }
758 return 0;
759
760 short_read:
761 total_read = (ibs * k) + ((res > 0) ? res : 0);
762 csp->icbpt = total_read / ibs;
763 if ((total_read % ibs) > 0) {
764 ++csp->icbpt;
765 ++op->in_partial;
766 }
767 csp->ocbpt = total_read / op->obs;
768 ++csp->leave_after_write;
769 if (0 == csp->leave_reason) {
770 csp->partial_write_bytes = total_read % op->obs;
771 } else {
772 /* if short read (not EOF) implies partial writes, bump obpt */
773 if ((total_read % op->obs) > 0)
774 ++csp->ocbpt;
775 }
776 return 0;
777 }
778
779 /* Main copy loop's read (input) for block device or regular file.
780 * Returns 0 on success, else SG_LIB_FILE_ERROR, SG_LIB_CAT_MEDIUM_HARD,
781 * SG_LIB_CAT_OTHER or -1 . */
782 static int
cp_read_block_reg(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)783 cp_read_block_reg(struct opts_t * op, struct cp_state_t * csp,
784 unsigned char * bp)
785 {
786 int res, res2, in_type;
787 int64_t offset = op->skip * op->ibs_pi;
788 int numbytes = csp->icbpt * op->ibs_pi;
789 int ibs = op->ibs_pi;
790
791 if (op->verbose > 4)
792 pr2serr("%s: offset=0x%" PRIx64 ", numbytes=%d\n", __func__, offset,
793 numbytes);
794 in_type = op->idip->d_type;
795 #ifdef SG_LIB_WIN32
796 if (FT_BLOCK & in_type) {
797 int ifull_extra;
798
799 if ((res = win32_cp_read_block(op, csp, bp, &ifull_extra,
800 op->verbose)))
801 return res;
802 op->in_full += ifull_extra;
803 return 0;
804 }
805 #endif
806 if (offset != csp->if_filepos) {
807 int64_t off_res;
808
809 if (op->verbose > 2)
810 pr2serr("moving if filepos: new_pos=%" PRId64 "\n",
811 (int64_t)offset);
812 off_res = lseek(op->idip->fd, offset, SEEK_SET);
813 if (off_res < 0) {
814 pr2serr("failed moving if filepos: new_pos="
815 "%" PRId64 "\nlseek on input: %s\n", (int64_t)offset,
816 safe_strerror(errno));
817 return SG_LIB_FILE_ERROR;
818 }
819 csp->if_filepos = offset;
820 }
821 while (((res = read(op->idip->fd, bp, numbytes)) < 0) &&
822 (EINTR == errno))
823 ++op->interrupted_retries;
824
825 if (op->verbose > 2)
826 pr2serr("read(unix): requested bytes=%d, res=%d\n", numbytes, res);
827 if ((op->iflagp->coe) && (res < numbytes)) {
828 res2 = (res >= 0) ? res : -errno;
829 if ((res < 0) && op->verbose) {
830 pr2serr("reading, skip=%" PRId64 " : %s, go to coe\n",
831 op->skip, safe_strerror(errno));
832 } else if (op->verbose)
833 pr2serr("reading, skip=%" PRId64 " : short read, go to coe\n",
834 op->skip);
835 if (res2 > 0)
836 csp->if_filepos += res2;
837 return coe_cp_read_block_reg(op, csp, bp, res2);
838 }
839 if (res < 0) {
840 pr2serr("reading, skip=%" PRId64 " : %s\n", op->skip,
841 safe_strerror(errno));
842 if ((EIO == errno) || (EREMOTEIO == errno))
843 return SG_LIB_CAT_MEDIUM_HARD;
844 else
845 return SG_LIB_CAT_OTHER;
846 } else if (res < numbytes) {
847 csp->icbpt = res / ibs;
848 if ((res % ibs) > 0) {
849 ++csp->icbpt;
850 ++op->in_partial;
851 --op->in_full;
852 }
853 csp->ocbpt = res / op->obs;
854 ++csp->leave_after_write;
855 csp->leave_reason = 0; /* fall through is assumed EOF */
856 if (op->verbose > 1) {
857 if (FT_BLOCK & in_type)
858 pr2serr("short read at skip=%" PRId64 ", requested "
859 "%d blocks, got %d blocks\n", op->skip,
860 numbytes / ibs, csp->icbpt);
861 else
862 pr2serr("short read, requested %d bytes, got %d bytes\n",
863 numbytes, res);
864 }
865 res2 = 0;
866 if ((res >= ibs) && (res <= (numbytes - ibs))) {
867 /* Want to check for a EIO lurking */
868 while (((res2 = read(op->idip->fd, bp + res, ibs)) < 0) &&
869 (EINTR == errno))
870 ++op->interrupted_retries;
871 if (res2 < 0) {
872 if ((EIO == errno) || (EREMOTEIO == errno)) {
873 csp->leave_reason = SG_LIB_CAT_MEDIUM_HARD;
874 ++op->unrecovered_errs;
875 } else
876 csp->leave_reason = SG_LIB_CAT_OTHER;
877 if (op->verbose)
878 pr2serr("after short read, read at skip=%" PRId64
879 ": %s\n", op->skip + csp->icbpt,
880 safe_strerror(errno));
881 } else { /* actually expect 0==res2 indicating EOF */
882 csp->if_filepos += res2; /* could have moved filepos */
883 if (op->verbose > 1)
884 pr2serr("extra read after short read, res=%d\n", res2);
885 }
886 }
887 if (0 == csp->leave_reason) /* if EOF, allow for partial write */
888 csp->partial_write_bytes = (res + res2) % op->obs;
889 else if ((res % op->obs) > 0) /* else if extra bytes bump obpt */
890 ++csp->ocbpt;
891 }
892 csp->if_filepos += res;
893 csp->bytes_read = res;
894 op->in_full += csp->icbpt;
895 return 0;
896 }
897
898 #ifdef SG_LIB_LINUX
899
900 /* Main copy loop's read (input) for tape device. Returns 0 on success,
901 * else SG_LIB_CAT_MEDIUM_HARD, SG_LIB_CAT_OTHER or -1 . */
902 static int
cp_read_tape(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)903 cp_read_tape(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp)
904 {
905 int res, err, num;
906
907 num = csp->icbpt * op->ibs;
908 op->read_tape_numbytes = num;
909 while (((res = read(op->idip->fd, bp, num)) < 0) && (EINTR == errno))
910 ++op->interrupted_retries;
911
912 err = errno;
913
914 /* Summarise previous consecutive same-length reads. */
915 print_tape_summary(op, res, "");
916
917 if (op->verbose > 2)
918 pr2serr("read(tape%s): requested bytes=%d, res=%d\n",
919 ((res >= num) || (res < 0)) ? "" : ", short", num, res);
920
921 if (op->verbose > 3)
922 print_tape_pos("", "", op);
923
924 if (res < 0) {
925 /* If a tape block larger than the requested read length is
926 * encountered, the Linux st driver returns ENOMEM. Handle that case
927 * otherwise we would print a confusing/incorrect message
928 * "Cannot allocate memory". */
929 pr2serr("reading, skip=%" PRId64 " : %s\n", op->skip,
930 (ENOMEM == err) ? "Tape block larger than requested read"
931 " length" : safe_strerror(err));
932
933 /* So print_stats() doesn't print summary. */
934 op->last_tape_read_len = 0;
935
936 if ((EIO == err) || (EREMOTEIO == err))
937 return SG_LIB_CAT_MEDIUM_HARD;
938 else
939 return SG_LIB_CAT_OTHER;
940 } else {
941 if (op->verbose > 1) {
942 if (res == op->last_tape_read_len)
943 op->consec_same_len_reads++;
944 else {
945 op->last_tape_read_len = res;
946 op->consec_same_len_reads = 1;
947 }
948 }
949 if (res < num) {
950 csp->icbpt = res / op->ibs;
951 if ((res % op->ibs) > 0) {
952 ++csp->icbpt;
953 ++op->in_partial;
954 --op->in_full;
955 }
956 csp->ocbpt = res / op->obs;
957 ++csp->leave_after_write;
958 csp->leave_reason = REASON_TAPE_SHORT_READ;
959 csp->partial_write_bytes = res % op->obs;
960 if ((op->verbose == 2) && (op->consec_same_len_reads == 1))
961 pr2serr("short read: requested %d bytes, got %d\n",
962 op->read_tape_numbytes, res);
963 }
964 }
965 csp->if_filepos += res;
966 csp->bytes_read = res;
967 op->in_full += csp->icbpt;
968 return 0;
969 }
970
971 #endif /* SG_LIB_LINUX */
972
973 /* Main copy loop's read (input) for a fifo. Returns 0 on success, else
974 * SG_LIB_CAT_OTHER or -1 . */
975 static int
cp_read_fifo(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)976 cp_read_fifo(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp)
977 {
978 int res, k, err;
979 int64_t offset = op->skip * op->ibs;
980 int numbytes = csp->icbpt * op->ibs;
981
982 if (offset != csp->if_filepos) {
983 if (op->verbose > 2)
984 pr2serr("%s: _not_ moving IFILE filepos to %" PRId64 "\n",
985 __func__, (int64_t)offset);
986 csp->if_filepos = offset;
987 }
988
989 for (k = 0; k < numbytes; k += res) {
990 while (((res = read(op->idip->fd, bp + k, numbytes - k)) < 0) &&
991 (EINTR == errno))
992 ++op->interrupted_retries;
993
994 err = errno;
995 if (op->verbose > 2)
996 pr2serr("%s: requested bytes=%d, res=%d\n", __func__, numbytes,
997 res);
998 if (res < 0) {
999 pr2serr("%s: skip=%" PRId64 " : %s\n", __func__, op->skip,
1000 safe_strerror(err));
1001 return SG_LIB_CAT_OTHER;
1002 } else if (0 == res) {
1003 csp->icbpt = k / op->ibs;
1004 if ((k % op->ibs) > 0) {
1005 ++csp->icbpt;
1006 ++op->in_partial;
1007 --op->in_full;
1008 }
1009 csp->ocbpt = k / op->obs;
1010 ++csp->leave_after_write;
1011 csp->leave_reason = 0; /* EOF */
1012 csp->partial_write_bytes = k % op->obs;
1013 break;
1014 }
1015 }
1016 csp->if_filepos += k;
1017 csp->bytes_read = k;
1018 op->in_full += csp->icbpt;
1019 return 0;
1020 }
1021
1022 /* Main copy loop's write (to of2) for regular file. Returns 0 if success,
1023 * else -1 on error. */
1024 static int
cp_write_of2(struct opts_t * op,struct cp_state_t * csp,const unsigned char * bp)1025 cp_write_of2(struct opts_t * op, struct cp_state_t * csp,
1026 const unsigned char * bp)
1027 {
1028 int res, off, part, err;
1029 int numbytes = (csp->ocbpt * op->obs) + csp->partial_write_bytes;
1030
1031 // write to fifo (reg file ?) is non-atomic so loop if making progress
1032 off = 0;
1033 part = 0;
1034 do {
1035 while (((res = write(op->o2dip->fd, bp + off, numbytes - off)) < 0) &&
1036 (EINTR == errno))
1037 ++op->interrupted_retries;
1038 err = errno;
1039 if ((res > 0) && (res < (numbytes - off)))
1040 ++part;
1041 } while ((FT_FIFO & op->o2dip->d_type) && (res > 0) &&
1042 ((off += res) < numbytes));
1043 if (off >= numbytes) {
1044 res = numbytes;
1045 if (part && op->verbose)
1046 pr2serr("write to of2 splintered\n");
1047 } else if (off > 0)
1048 pr2serr("write to of2 fifo problem: count=%d, off=%d, res=%d\n",
1049 numbytes, off, res);
1050 if ((op->verbose > 2) && (0 == off))
1051 pr2serr("write to of2: count=%d, res=%d\n", numbytes, res);
1052 if (res < 0) {
1053 pr2serr("writing to of2, seek=%" PRId64 " : %s\n", op->seek,
1054 safe_strerror(err));
1055 return -1;
1056 }
1057 csp->bytes_of2 = res;
1058 return 0;
1059 }
1060
1061 /* Main copy loop's read (output (of)) via pt. Returns 0 on success, else
1062 * see pt_read()'s return values. */
1063 static int
cp_read_of_pt(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)1064 cp_read_of_pt(struct opts_t * op, struct cp_state_t * csp, unsigned char * bp)
1065 {
1066 int res, blks_read;
1067
1068 res = pt_read(op, 1, bp, csp->ocbpt, &blks_read);
1069 if (res) {
1070 pr2serr("pt_read(sparing) failed, at or after "
1071 "lba=%" PRId64 " [0x%" PRIx64 "]\n", op->seek,
1072 op->seek);
1073 return res;
1074 } else if (blks_read != csp->ocbpt)
1075 return 1;
1076 return 0;
1077 }
1078
1079 /* Main copy loop's read (output (of)) for block device or regular file.
1080 * Returns 0 on success, else SG_LIB_FILE_ERROR, SG_LIB_CAT_MEDIUM_HARD
1081 * or -1 . */
1082 static int
cp_read_of_block_reg(struct opts_t * op,struct cp_state_t * csp,unsigned char * bp)1083 cp_read_of_block_reg(struct opts_t * op, struct cp_state_t * csp,
1084 unsigned char * bp)
1085 {
1086 int res, err;
1087 int64_t offset = op->seek * op->obs;
1088 int numbytes = csp->ocbpt * op->obs;
1089
1090 #ifdef SG_LIB_WIN32
1091 if (FT_BLOCK & op->odip->d_type) {
1092 if (offset != csp->of_filepos) {
1093 if (op->verbose > 2)
1094 pr2serr("moving of filepos: new_pos=%" PRId64 "\n",
1095 (int64_t)offset);
1096 if (win32_set_file_pos(op, DDPT_ARG_OUT, offset, op->verbose))
1097 return SG_LIB_FILE_ERROR;
1098 csp->of_filepos = offset;
1099 }
1100 res = win32_block_read_from_of(op, bp, numbytes, op->verbose);
1101 if (op->verbose > 2)
1102 pr2serr("read(sparing): requested bytes=%d, res=%d\n", numbytes,
1103 res);
1104 if (res < 0) {
1105 pr2serr("read(sparing), seek=%" PRId64 "\n", op->seek);
1106 return (-SG_LIB_CAT_MEDIUM_HARD == res) ? -res : -1;
1107 } else if (res == numbytes) {
1108 csp->of_filepos += numbytes;
1109 return 0;
1110 } else {
1111 if (op->verbose > 2)
1112 pr2serr("short read\n");
1113 return -1;
1114 }
1115 } else
1116 #endif
1117 {
1118 if (offset != csp->of_filepos) {
1119 int64_t off_res;
1120
1121 if (op->verbose > 2)
1122 pr2serr("moving of filepos: new_pos=%" PRId64 "\n",
1123 (int64_t)offset);
1124 off_res = lseek(op->odip->fd, offset, SEEK_SET);
1125 if (off_res < 0) {
1126 pr2serr("failed moving of filepos: new_pos="
1127 "%" PRId64 "\nlseek on output: %s\n", (int64_t)offset,
1128 safe_strerror(errno));
1129 return SG_LIB_FILE_ERROR;
1130 }
1131 csp->of_filepos = offset;
1132 }
1133 if (csp->partial_write_bytes > 0) {
1134 numbytes += csp->partial_write_bytes;
1135 if (op->verbose)
1136 pr2serr("read(sparing): %d bytes extra to fetch "
1137 "due to partial read\n", csp->partial_write_bytes);
1138 }
1139 while (((res = read(op->odip->fd, bp, numbytes)) < 0) &&
1140 (EINTR == errno))
1141 ++op->interrupted_retries;
1142
1143 err = errno;
1144 if (op->verbose > 2)
1145 pr2serr("read(sparing): requested bytes=%d, res=%d\n", numbytes,
1146 res);
1147 if (res < 0) {
1148 pr2serr("read(sparing), seek=%" PRId64 " : %s\n", op->seek,
1149 safe_strerror(err));
1150 return -1;
1151 } else if (res == numbytes) {
1152 csp->of_filepos += numbytes;
1153 return 0;
1154 } else {
1155 if (op->verbose > 2)
1156 pr2serr("short read\n");
1157 return 1;
1158 }
1159 }
1160 }
1161
1162
1163 /* Main copy loop's write (output (of)) via pt. Returns 0 on success, else
1164 * see pt_write()'s return values. */
1165 static int
cp_write_pt(struct opts_t * op,struct cp_state_t * csp,int seek_delta,int blks,const unsigned char * bp)1166 cp_write_pt(struct opts_t * op, struct cp_state_t * csp, int seek_delta,
1167 int blks, const unsigned char * bp)
1168 {
1169 int res;
1170 int numbytes;
1171 int64_t aseek = op->seek + seek_delta;
1172
1173 if (op->oflagp->nowrite)
1174 return 0;
1175 if (csp->partial_write_bytes > 0) {
1176 if (op->oflagp->pad) {
1177 unsigned char * ncbp = (unsigned char *)bp;
1178
1179 numbytes = blks * op->obs;
1180 numbytes += csp->partial_write_bytes;
1181 ++csp->ocbpt;
1182 ++blks;
1183 res = blks * op->obs;
1184 if (res > numbytes)
1185 memset(ncbp + numbytes, 0, res - numbytes);
1186 if (op->verbose > 1)
1187 pr2serr("%s: padding probable final write at seek=%" PRId64
1188 "\n", __func__, aseek);
1189 } else
1190 pr2serr(">>> ignore partial write of %d bytes to pt "
1191 "(unless oflag=pad given)\n", csp->partial_write_bytes);
1192 }
1193 res = pt_write(op, bp, blks, aseek);
1194 if (0 != res) {
1195 pr2serr("%s: failed,%s seek=%" PRId64 "\n", __func__,
1196 ((-2 == res) ? " try reducing bpt," : ""), aseek);
1197 return res;
1198 } else
1199 op->out_full += blks;
1200 return 0;
1201 }
1202
1203 #ifdef SG_LIB_LINUX
1204
1205 /* Main copy loop's write (output (of)) for a tape device.
1206 * Returns 0 on success, else SG_LIB_CAT_OTHER, SG_LIB_CAT_MEDIUM_HARD
1207 * or -1 . */
1208 static int
cp_write_tape(struct opts_t * op,struct cp_state_t * csp,const unsigned char * bp,int could_be_last)1209 cp_write_tape(struct opts_t * op, struct cp_state_t * csp,
1210 const unsigned char * bp, int could_be_last)
1211 {
1212 int res, err;
1213 int numbytes;
1214 int partial = 0;
1215 int blks = csp->ocbpt;
1216 int64_t aseek = op->seek;
1217 int got_early_warning = 0;
1218 /* Only print early warning message once when verbose=2 */
1219 static int printed_ew_message = 0;
1220
1221 numbytes = blks * op->obs;
1222 if (op->oflagp->nowrite)
1223 return 0;
1224 if (csp->partial_write_bytes > 0) {
1225 ++partial;
1226 numbytes += csp->partial_write_bytes;
1227 if (op->oflagp->nopad)
1228 ++op->out_partial;
1229 else {
1230 unsigned char * ncbp = (unsigned char *)bp;
1231
1232 ++csp->ocbpt;
1233 ++blks;
1234 res = blks * op->obs;
1235 if (res > numbytes)
1236 memset(ncbp + numbytes, 0, res - numbytes);
1237 numbytes = res;
1238 }
1239 }
1240
1241 ew_retry:
1242 while (((res = write(op->odip->fd, bp, numbytes)) < 0) &&
1243 (EINTR == errno))
1244 ++op->interrupted_retries;
1245
1246 err = errno;
1247 if ((op->verbose > 2) || ((op->verbose > 0) && could_be_last)) {
1248 const char * cp;
1249
1250 cp = ((! op->oflagp->nopad) && partial) ? ", padded" : "";
1251 pr2serr("write(tape%s%s): requested bytes=%d, res=%d\n",
1252 (partial ? ", partial" : ""), cp, numbytes, res);
1253 }
1254
1255 /* Handle EOM early warning. */
1256 /* The Linux st driver returns -1 and ENOSPC to indicate the drive has reached
1257 * end of medium early warning. It is still possible to write a significant
1258 * amount of data before reaching end of tape (e.g. over 200MB for LTO 1). If
1259 * the user specified oflag=ignoreew (ignore early warning) retry the write.
1260 * The st driver should allow it; writes alternate until EOM, i.e. write okay,
1261 * ENOSPC, write okay, ENOSPC, etc. Exit if more than one ENOSPC in a row. */
1262 if ((op->oflagp->ignoreew) && (-1 == res) && (ENOSPC == err) &&
1263 (0 == got_early_warning)) {
1264 got_early_warning = 1;
1265 if (0 == printed_ew_message) {
1266 if (op->verbose > 1)
1267 pr2serr("writing, seek=%" PRId64 " : EOM early "
1268 "warning, continuing...\n", aseek);
1269 if (2 == op->verbose) {
1270 pr2serr("(suppressing further early warning messages)\n");
1271 printed_ew_message = 1;
1272 }
1273 }
1274 goto ew_retry;
1275 }
1276
1277 if (op->verbose > 3)
1278 print_tape_pos("", "", op);
1279
1280 if (res < 0) {
1281 pr2serr("writing, seek=%" PRId64 " : %s\n", aseek,
1282 safe_strerror(err));
1283 if ((EIO == err) || (EREMOTEIO == err))
1284 return SG_LIB_CAT_MEDIUM_HARD;
1285 else
1286 return SG_LIB_CAT_OTHER;
1287 } else if (res < numbytes) {
1288 pr2serr("write(tape): wrote less than requested, exit\n");
1289 csp->of_filepos += res;
1290 csp->bytes_of = res;
1291 op->out_full += res / op->obs;
1292 /* can get a partial write due to a short write */
1293 if ((res % op->obs) > 0) {
1294 ++op->out_partial;
1295 ++op->out_full;
1296 }
1297 return -1;
1298 } else { /* successful write */
1299 csp->of_filepos += numbytes;
1300 csp->bytes_of = numbytes;
1301 op->out_full += blks;
1302 }
1303 return 0;
1304 }
1305
1306 #endif /* SG_LIB_LINUX */
1307
1308 /* Main copy loop's write (output (of)) for block device fifo or regular
1309 * file. Returns 0 on success, else SG_LIB_FILE_ERROR,
1310 * SG_LIB_CAT_MEDIUM_HARD or -1 . */
1311 static int
cp_write_block_reg(struct opts_t * op,struct cp_state_t * csp,int seek_delta,int blks,const unsigned char * bp)1312 cp_write_block_reg(struct opts_t * op, struct cp_state_t * csp,
1313 int seek_delta, int blks, const unsigned char * bp)
1314 {
1315 int64_t offset;
1316 int64_t aseek = op->seek + seek_delta;
1317 int res, off, part, out_type, err;
1318 int numbytes = blks * op->obs_pi;
1319 int obs = op->obs_pi;
1320
1321 if (op->oflagp->nowrite)
1322 return 0;
1323 out_type = op->odip->d_type;
1324 offset = aseek * obs;
1325 #ifdef SG_LIB_WIN32
1326 if (FT_BLOCK & out_type) {
1327 if (csp->partial_write_bytes > 0) {
1328 if (op->oflagp->pad) {
1329 numbytes += csp->partial_write_bytes;
1330 ++csp->ocbpt;
1331 ++blks;
1332 res = blks * obs;
1333 if (res > numbytes)
1334 memset((unsigned char *)bp + numbytes, 0,
1335 res - numbytes);
1336 numbytes = res;
1337 if (op->verbose > 1)
1338 pr2serr("write(win32_block): padding probable "
1339 "final write at seek=%" PRId64 "\n", aseek);
1340 } else
1341 pr2serr(">>> ignore partial write of %d bytes to "
1342 "block device\n", csp->partial_write_bytes);
1343 }
1344 if (offset != csp->of_filepos) {
1345 if (op->verbose > 2)
1346 pr2serr("moving of filepos: new_pos=%" PRId64 "\n",
1347 (int64_t)offset);
1348 if (win32_set_file_pos(op, DDPT_ARG_OUT, offset, op->verbose))
1349 return SG_LIB_FILE_ERROR;
1350 csp->of_filepos = offset;
1351 }
1352 res = win32_block_write(op, bp, numbytes, op->verbose);
1353 if (res < 0) {
1354 pr2serr("write(win32_block), seek=%" PRId64 " ", aseek);
1355 return (-SG_LIB_CAT_MEDIUM_HARD == res) ? -res : -1;
1356 } else if (res < numbytes) {
1357 pr2serr("output file probably full, seek=%" PRId64 " ",
1358 aseek);
1359 csp->of_filepos += res;
1360 csp->bytes_of = res;
1361 op->out_full += res / obs;
1362 /* can get a partial write due to a short write */
1363 if ((res % obs) > 0) {
1364 ++op->out_partial;
1365 ++op->out_full;
1366 }
1367 return -1;
1368 } else {
1369 csp->of_filepos += numbytes;
1370 csp->bytes_of = numbytes;
1371 op->out_full += blks;
1372 }
1373 return 0;
1374 } else
1375 #endif
1376 {
1377 if (csp->partial_write_bytes > 0) {
1378 if (op->oflagp->pad) {
1379 unsigned char * ncbp = (unsigned char *)bp;
1380
1381 numbytes += csp->partial_write_bytes;
1382 ++csp->ocbpt;
1383 ++blks;
1384 res = blks * obs;
1385 if (res > numbytes)
1386 memset(ncbp + numbytes, 0, res - numbytes);
1387 numbytes = res;
1388 if (op->verbose > 1)
1389 pr2serr("write(unix): padding probable final "
1390 "write at seek=%" PRId64 "\n", aseek);
1391 } else {
1392 if (FT_BLOCK & out_type)
1393 pr2serr(">>> ignore partial write of %d bytes to block "
1394 "device\n", csp->partial_write_bytes);
1395 else {
1396 numbytes += csp->partial_write_bytes;
1397 ++op->out_partial;
1398 }
1399 }
1400 }
1401 if ((offset != csp->of_filepos) &&
1402 (! (REASON_TAPE_SHORT_READ == csp->leave_reason))) {
1403 int64_t off_res;
1404
1405 if (op->verbose > 2)
1406 pr2serr("moving of filepos: new_pos=%" PRId64 "\n",
1407 (int64_t)offset);
1408 off_res = lseek(op->odip->fd, offset, SEEK_SET);
1409 if (off_res < 0) {
1410 pr2serr("failed moving of filepos: new_pos="
1411 "%" PRId64 "\nlseek on output: %s\n", (int64_t)offset,
1412 safe_strerror(errno));
1413 return SG_LIB_FILE_ERROR;
1414 }
1415 csp->of_filepos = offset;
1416 }
1417 // write to fifo (reg file ?) is non-atomic so loop if making progress
1418 off = 0;
1419 part = 0;
1420 do {
1421 while (((res = write(op->odip->fd, bp + off,
1422 numbytes - off)) < 0) && (EINTR == errno))
1423 ++op->interrupted_retries;
1424 err = errno;
1425 if ((res > 0) && (res < (numbytes - off)))
1426 ++part;
1427 } while ((FT_FIFO & out_type) && (res > 0) &&
1428 ((off += res) < numbytes));
1429 if (off >= numbytes) {
1430 res = numbytes;
1431 if (part && op->verbose)
1432 pr2serr("write to output file splintered\n");
1433 } else if (off > 0)
1434 pr2serr("write to of fifo problem: count=%d, off=%d, "
1435 "res=%d\n", numbytes, off, res);
1436 if ((op->verbose > 2) && (0 == off))
1437 pr2serr("write(unix): requested bytes=%d, res=%d\n", numbytes,
1438 res);
1439 if (res < 0) {
1440 pr2serr("writing, seek=%" PRId64 " : %s\n", aseek,
1441 safe_strerror(err));
1442 if ((EIO == err) || (EREMOTEIO == err))
1443 return SG_LIB_CAT_MEDIUM_HARD;
1444 else
1445 return SG_LIB_CAT_OTHER;
1446 } else if (res < numbytes) {
1447 pr2serr("output file probably full, seek=%" PRId64 "\n", aseek);
1448 csp->of_filepos += res;
1449 csp->bytes_of = res;
1450 op->out_full += res / obs;
1451 /* can get a partial write due to a short write */
1452 if ((res % obs) > 0) {
1453 ++op->out_partial;
1454 ++op->out_full;
1455 }
1456 return -1;
1457 } else { /* successful write */
1458 csp->of_filepos += numbytes;
1459 csp->bytes_of = numbytes;
1460 op->out_full += blks;
1461 }
1462 return 0;
1463 }
1464 }
1465
1466 /* Only for regular OFILE. Check what to do if last blocks where
1467 * not written, may require OFILE length adjustment */
1468 static void
cp_sparse_cleanup(struct opts_t * op,struct cp_state_t * csp)1469 cp_sparse_cleanup(struct opts_t * op, struct cp_state_t * csp)
1470 {
1471 int64_t offset = (op->seek * op->obs) + csp->partial_write_bytes;
1472 struct stat a_st;
1473
1474 if (offset > csp->of_filepos) {
1475 if ((0 == op->oflagp->strunc) && (op->oflagp->sparse > 1)) {
1476 if (op->verbose > 1)
1477 pr2serr("asked to bypass writing sparse last block of "
1478 "zeros\n");
1479 return;
1480 }
1481 if (fstat(op->odip->fd, &a_st) < 0) {
1482 pr2serr("%s: fstat: %s\n", __func__, safe_strerror(errno));
1483 return;
1484 }
1485 if (offset == a_st.st_size) {
1486 if (op->verbose > 1)
1487 pr2serr("%s: OFILE already correct length\n", __func__);
1488 return;
1489 }
1490 if (offset < a_st.st_size) {
1491 if (op->verbose > 1)
1492 pr2serr("%s: OFILE longer than required, do nothing\n",
1493 __func__);
1494 return;
1495 }
1496 if (op->oflagp->strunc) {
1497 if (op->verbose > 1)
1498 pr2serr("About to truncate %s to byte offset "
1499 "%" PRId64 "\n", op->odip->fn, offset);
1500 if (ftruncate(op->odip->fd, offset) < 0) {
1501 pr2serr("could not ftruncate after copy: %s\n",
1502 safe_strerror(errno));
1503 return;
1504 }
1505 /* N.B. file offset (pointer) not changed by ftruncate */
1506 } else if (1 == op->oflagp->sparse) {
1507 if (op->verbose > 1)
1508 pr2serr("writing sparse last block of zeros\n");
1509 signals_process_delay(op, DELAY_WRITE);
1510 if (cp_write_block_reg(op, csp, -1, 1, op->zeros_buff) < 0)
1511 pr2serr("writing sparse last block of zeros "
1512 "error, seek=%" PRId64 "\n", op->seek - 1);
1513 else
1514 --op->out_sparse;
1515 }
1516 } else if (op->verbose > 1)
1517 pr2serr("%s: bypass as output_offset <= output_filepos\n", __func__);
1518 }
1519
1520 /* Main copy loop's finer grain comparison and possible write (to OFILE)
1521 * for all file types. Returns 0 on success. */
1522 static int
cp_finer_comp_wr(struct opts_t * op,struct cp_state_t * csp,const unsigned char * b1p,const unsigned char * b2p)1523 cp_finer_comp_wr(struct opts_t * op, struct cp_state_t * csp,
1524 const unsigned char * b1p, const unsigned char * b2p)
1525 {
1526 int res, k, n, oblks, numbytes, chunk, need_wr, wr_len, wr_k, obs;
1527 int trim_check, need_tr, tr_len, tr_k, out_type;
1528 int done_sigs_delay = 0;
1529
1530 oblks = csp->ocbpt;
1531 obs = op->obs;
1532 out_type = op->odip->d_type;
1533 if (op->obpch >= oblks) {
1534 if (FT_DEV_NULL & out_type)
1535 ;
1536 else if (FT_PT & out_type) {
1537 signals_process_delay(op, DELAY_WRITE);
1538 if ((res = cp_write_pt(op, csp, 0, oblks, b1p)))
1539 return res;
1540 } else {
1541 signals_process_delay(op, DELAY_WRITE);
1542 if ((res = cp_write_block_reg(op, csp, 0, oblks, b1p)))
1543 return res;
1544 }
1545 return 0;
1546 }
1547 numbytes = oblks * obs;
1548 if ((FT_REG & out_type) && (csp->partial_write_bytes > 0))
1549 numbytes += csp->partial_write_bytes;
1550 chunk = op->obpch * obs;
1551 trim_check = (op->oflagp->sparse && op->oflagp->wsame16 &&
1552 (FT_PT & out_type));
1553 need_tr = 0;
1554 tr_len = 0;
1555 tr_k = 0;
1556 for (k = 0, need_wr = 0, wr_len = 0, wr_k = 0; k < numbytes; k += chunk) {
1557 n = ((k + chunk) < numbytes) ? chunk : (numbytes - k);
1558 if (0 == memcmp(b1p + k, b2p + k, n)) {
1559 if (need_wr) {
1560 if (FT_DEV_NULL & out_type)
1561 ;
1562 else if (FT_PT & out_type) {
1563 if (! done_sigs_delay) {
1564 done_sigs_delay = 1;
1565 signals_process_delay(op, DELAY_WRITE);
1566 }
1567 if ((res = cp_write_pt(op, csp, wr_k / obs,
1568 wr_len / obs, b1p + wr_k)))
1569 return res;
1570 } else {
1571 if (! done_sigs_delay) {
1572 done_sigs_delay = 1;
1573 signals_process_delay(op, DELAY_WRITE);
1574 }
1575 if ((res = cp_write_block_reg(op, csp, wr_k / obs,
1576 wr_len / obs, b1p + wr_k)))
1577 return res;
1578 }
1579 need_wr = 0;
1580 }
1581 if (need_tr)
1582 tr_len += n;
1583 else if (trim_check) {
1584 need_tr = 1;
1585 tr_len = n;
1586 tr_k = k;
1587 }
1588 op->out_sparse += (n / obs);
1589 } else { /* look for a sequence of unequals */
1590 if (need_wr)
1591 wr_len += n;
1592 else {
1593 need_wr = 1;
1594 wr_len = n;
1595 wr_k = k;
1596 }
1597 if (need_tr) {
1598 if (! done_sigs_delay) {
1599 done_sigs_delay = 1;
1600 signals_process_delay(op, DELAY_WRITE);
1601 }
1602 res = pt_write_same16(op, b2p, obs, tr_len / obs,
1603 op->seek + (tr_k / obs));
1604 if (res)
1605 ++op->trim_errs;
1606 /* continue past trim errors */
1607 need_tr = 0;
1608 }
1609 }
1610 }
1611 if (need_wr) {
1612 if (FT_DEV_NULL & out_type)
1613 ;
1614 else if (FT_PT & out_type) {
1615 if (! done_sigs_delay) {
1616 done_sigs_delay = 1;
1617 signals_process_delay(op, DELAY_WRITE);
1618 }
1619 if ((res = cp_write_pt(op, csp, wr_k / obs, wr_len / obs,
1620 b1p + wr_k)))
1621 return res;
1622 } else {
1623 if (! done_sigs_delay) {
1624 done_sigs_delay = 1;
1625 signals_process_delay(op, DELAY_WRITE);
1626 }
1627 if ((res = cp_write_block_reg(op, csp, wr_k / obs, wr_len / obs,
1628 b1p + wr_k)))
1629 return res;
1630 }
1631 }
1632 if (need_tr) {
1633 if (! done_sigs_delay)
1634 signals_process_delay(op, DELAY_WRITE);
1635 res = pt_write_same16(op, b2p, obs, tr_len / obs,
1636 op->seek + (tr_k / obs));
1637 if (res)
1638 ++op->trim_errs;
1639 /* continue past trim errors */
1640 }
1641 return 0;
1642 }
1643
1644 static int
cp_construct_pt_zero_buff(struct opts_t * op,int obpt)1645 cp_construct_pt_zero_buff(struct opts_t * op, int obpt)
1646 {
1647 if ((FT_PT & op->idip->d_type) && (NULL == op->idip->ptvp)) {
1648 op->idip->ptvp = (struct sg_pt_base *)pt_construct_obj();
1649 if (NULL == op->idip->ptvp)
1650 return -1;
1651 }
1652 if ((FT_PT & op->odip->d_type) && (NULL == op->odip->ptvp)) {
1653 op->odip->ptvp = (struct sg_pt_base *)pt_construct_obj();
1654 if (NULL == op->odip->ptvp)
1655 return -1;
1656 }
1657 if ((op->oflagp->sparse) && (NULL == op->zeros_buff)) {
1658 op->zeros_buff = (unsigned char *)calloc(obpt * op->obs, 1);
1659 if (NULL == op->zeros_buff) {
1660 pr2serr("zeros_buff calloc failed\n");
1661 return -1;
1662 }
1663 }
1664 return 0;
1665 }
1666
1667 /* Look at IFILE and OFILE lengths and blocks sizes. If dd_count
1668 * not given, try to deduce a value for it. If oflag=resume do skip,
1669 * seek, dd_count adjustments. Returns 0 to start copy, otherwise
1670 * bypass copy and exit */
1671 static int
count_calculate(struct opts_t * op)1672 count_calculate(struct opts_t * op)
1673 {
1674 int64_t in_num_blks = -1;
1675 int64_t out_num_blks = -1;
1676 int64_t ibytes, obytes, ibk;
1677 int valid_resume = 0;
1678 int res;
1679
1680 if ((res = calc_count(op, &in_num_blks, &out_num_blks)))
1681 return res;
1682 if ((0 == op->oflagp->resume) && (op->dd_count > 0))
1683 return 0;
1684 if (op->verbose > 1)
1685 pr2serr("calc_count: in_num_blks=%" PRId64 ", out_num_blks"
1686 "=%" PRId64 "\n", in_num_blks, out_num_blks);
1687 if (op->skip && (FT_REG == op->idip->d_type) &&
1688 (op->skip > in_num_blks)) {
1689 pr2serr("cannot skip to specified offset on %s\n", op->idip->fn);
1690 op->dd_count = 0;
1691 return -1;
1692 }
1693 if (op->oflagp->resume) {
1694 if (FT_REG == op->odip->d_type) {
1695 if (out_num_blks < 0)
1696 pr2serr("resume cannot determine size of OFILE, ignore\n");
1697 else
1698 valid_resume = 1;
1699 } else
1700 pr2serr("resume expects OFILE to be regular, ignore\n");
1701 }
1702 if ((op->dd_count < 0) && (! valid_resume)) {
1703 /* Scale back in_num_blks by value of skip */
1704 if (op->skip && (in_num_blks > op->skip))
1705 in_num_blks -= op->skip;
1706 /* Scale back out_num_blks by value of seek */
1707 if (op->seek && (out_num_blks > op->seek))
1708 out_num_blks -= op->seek;
1709
1710 if ((out_num_blks < 0) && (in_num_blks > 0))
1711 op->dd_count = in_num_blks;
1712 else if ((op->reading_fifo) && (out_num_blks < 0))
1713 ;
1714 else if ((out_num_blks < 0) && (in_num_blks <= 0))
1715 ;
1716 else {
1717 ibytes = (in_num_blks > 0) ? (op->ibs * in_num_blks) : 0;
1718 obytes = op->obs * out_num_blks;
1719 if (0 == ibytes)
1720 op->dd_count = obytes / op->ibs;
1721 else if ((ibytes > obytes) && (FT_REG != op->odip->d_type)) {
1722 op->dd_count = obytes / op->ibs;
1723 } else
1724 op->dd_count = in_num_blks;
1725 }
1726 }
1727 if (valid_resume) {
1728 if (op->dd_count < 0)
1729 op->dd_count = in_num_blks - op->skip;
1730 if (out_num_blks <= op->seek)
1731 pr2serr("resume finds no previous copy, restarting\n");
1732 else {
1733 obytes = op->obs * (out_num_blks - op->seek);
1734 ibk = obytes / op->ibs;
1735 if (ibk >= op->dd_count) {
1736 pr2serr("resume finds copy complete, exiting\n");
1737 op->dd_count = 0;
1738 return -1;
1739 }
1740 /* align to bpt multiple */
1741 ibk = (ibk / op->bpt_i) * op->bpt_i;
1742 op->skip += ibk;
1743 op->seek += (ibk * op->ibs) / op->obs;
1744 op->dd_count -= ibk;
1745 pr2serr("resume adjusting skip=%" PRId64 ", seek=%"
1746 PRId64 ", and count=%" PRId64 "\n", op->skip, op->seek,
1747 op->dd_count);
1748 }
1749 }
1750 return 0;
1751 }
1752
1753 /* This is the main copy loop (unless an offloaded copy is requested).
1754 * Attempts to copy 'dd_count' blocks (size given by bs or ibs) in chunks
1755 * of op->bpt_i blocks. Returns 0 if successful. */
1756 static int
do_rw_copy(struct opts_t * op)1757 do_rw_copy(struct opts_t * op)
1758 {
1759 int ibpt, obpt, res, n, sparse_skip, sparing_skip, continual_read;
1760 int ret = 0;
1761 int first_time = 1;
1762 int first_time_ff = 1;
1763 int id_type = op->idip->d_type;
1764 int od_type = op->odip->d_type;
1765 struct cp_state_t cp_st;
1766 struct cp_state_t * csp;
1767 unsigned char * wPos = op->wrkPos;
1768
1769 continual_read = op->reading_fifo && (op->dd_count < 0);
1770 if (op->verbose > 3) {
1771 if (continual_read)
1772 pr2serr("do_rw_copy: reading fifo continually\n");
1773 else
1774 pr2serr("do_rw_copy: dd_count=%" PRId64 "\n", op->dd_count);
1775 }
1776 if ((op->dd_count <= 0) && (! op->reading_fifo))
1777 return 0;
1778 csp = &cp_st;
1779 memset(csp, 0, sizeof(struct cp_state_t));
1780 ibpt = op->bpt_i;
1781 obpt = (op->ibs * op->bpt_i) / op->obs;
1782 if ((ret = cp_construct_pt_zero_buff(op, obpt)))
1783 goto copy_end;
1784 /* Both csp->if_filepos and csp->of_filepos are 0 */
1785
1786 /* <<< main loop that does the copy >>> */
1787 while ((op->dd_count > 0) || continual_read) {
1788 if (first_time)
1789 first_time = 0;
1790 else
1791 signals_process_delay(op, DELAY_COPY_SEGMENT);
1792 csp->bytes_read = 0;
1793 csp->bytes_of = 0;
1794 csp->bytes_of2 = 0;
1795 sparing_skip = 0;
1796 sparse_skip = 0;
1797 if ((op->dd_count >= ibpt) || continual_read) {
1798 csp->icbpt = ibpt;
1799 csp->ocbpt = obpt;
1800 } else {
1801 csp->icbpt = op->dd_count;
1802 res = op->dd_count;
1803 n = res * op->ibs;
1804 csp->ocbpt = n / op->obs;
1805 if (n % op->obs) {
1806 ++csp->ocbpt;
1807 memset(wPos, 0, op->ibs * ibpt);
1808 }
1809 }
1810
1811 /* Start of reading section */
1812 if (FT_PT & id_type) {
1813 if ((ret = cp_read_pt(op, csp, wPos)))
1814 break;
1815 } else if (FT_FIFO & id_type) {
1816 if ((ret = cp_read_fifo(op, csp, wPos)))
1817 break;
1818 } else if (FT_TAPE & id_type) {
1819 #ifdef SG_LIB_LINUX
1820 if ((ret = cp_read_tape(op, csp, wPos)))
1821 break;
1822 #else
1823 pr2serr("reading from tape not supported in this OS\n");
1824 ret = SG_LIB_CAT_OTHER;
1825 break;
1826 #endif
1827 } else if (FT_ALL_FF & id_type) {
1828 if (first_time_ff) {
1829 first_time_ff = 0;
1830 memset(wPos, 0xff, op->ibs * ibpt);
1831 }
1832 op->in_full += csp->icbpt;
1833 } else {
1834 if ((ret = cp_read_block_reg(op, csp, wPos)))
1835 break;
1836 }
1837 if (0 == csp->icbpt)
1838 break; /* nothing read so leave loop */
1839
1840 if ((op->o2dip->fd >= 0) &&
1841 ((ret = cp_write_of2(op, csp, wPos))))
1842 break;
1843
1844 if (op->oflagp->sparse) {
1845 n = (csp->ocbpt * op->obs) + csp->partial_write_bytes;
1846 if (0 == memcmp(wPos, op->zeros_buff, n)) {
1847 sparse_skip = 1;
1848 if (op->oflagp->wsame16 && (FT_PT & od_type)) {
1849 signals_process_delay(op, DELAY_WRITE);
1850 res = pt_write_same16(op, op->zeros_buff, op->obs,
1851 csp->ocbpt, op->seek);
1852 if (res)
1853 ++op->trim_errs;
1854 }
1855 } else if (op->obpch) {
1856 ret = cp_finer_comp_wr(op, csp, wPos, op->zeros_buff);
1857 if (ret)
1858 break;
1859 goto bypass_write;
1860 }
1861 }
1862 if (op->oflagp->sparing && (! sparse_skip)) {
1863 /* In write sparing, we read from the output */
1864 if (FT_PT & od_type)
1865 res = cp_read_of_pt(op, csp, op->wrkPos2);
1866 else
1867 res = cp_read_of_block_reg(op, csp, op->wrkPos2);
1868 if (0 == res) {
1869 n = (csp->ocbpt * op->obs) + csp->partial_write_bytes;
1870 if (0 == memcmp(wPos, op->wrkPos2, n))
1871 sparing_skip = 1;
1872 else if (op->obpch) {
1873 ret = cp_finer_comp_wr(op, csp, wPos, op->wrkPos2);
1874 if (ret)
1875 break;
1876 goto bypass_write;
1877 }
1878 } else {
1879 ret = res;
1880 break;
1881 }
1882 }
1883
1884 /* Start of writing section */
1885 if (sparing_skip || sparse_skip) {
1886 op->out_sparse += csp->ocbpt;
1887 if (csp->partial_write_bytes > 0)
1888 ++op->out_sparse_partial;
1889 } else {
1890 if (FT_DEV_NULL & od_type)
1891 ; /* don't bump out_full (earlier revs did) */
1892 else {
1893 signals_process_delay(op, DELAY_WRITE);
1894 if (FT_PT & od_type) {
1895 if ((ret = cp_write_pt(op, csp, 0, csp->ocbpt, wPos)))
1896 break;
1897 } else if (FT_TAPE & od_type) {
1898 #ifdef SG_LIB_LINUX
1899 int could_be_last;
1900
1901 could_be_last = ((! continual_read) &&
1902 (csp->icbpt >= op->dd_count));
1903 if ((ret = cp_write_tape(op, csp, wPos, could_be_last)))
1904 break;
1905 #else
1906 pr2serr("writing to tape not supported in this OS\n");
1907 ret = SG_LIB_CAT_OTHER;
1908 break;
1909 #endif
1910 } else if ((ret = cp_write_block_reg(op, csp, 0, csp->ocbpt,
1911 wPos))) /* plus fifo */
1912 break;
1913 }
1914 }
1915 bypass_write:
1916 #ifdef HAVE_POSIX_FADVISE
1917 do_fadvise(op, csp->bytes_read, csp->bytes_of, csp->bytes_of2);
1918 #endif
1919 if (op->dd_count > 0)
1920 op->dd_count -= csp->icbpt;
1921 op->skip += csp->icbpt;
1922 op->seek += csp->ocbpt;
1923 if (csp->leave_after_write) {
1924 if (REASON_TAPE_SHORT_READ == csp->leave_reason) {
1925 /* allow multiple partial writes for tape */
1926 csp->partial_write_bytes = 0;
1927 csp->leave_after_write = 0;
1928 } else {
1929 /* other cases: stop copy after partial write */
1930 ret = csp->leave_reason;
1931 break;
1932 }
1933 }
1934 } /* end of main loop that does the copy ... */
1935
1936 /* sparse: clean up ofile length when last block(s) were not written */
1937 if ((FT_REG & od_type) && (0 == op->oflagp->nowrite) &&
1938 op->oflagp->sparse)
1939 cp_sparse_cleanup(op, csp);
1940
1941 #ifdef HAVE_FDATASYNC
1942 else if (op->oflagp->fdatasync) {
1943 if (fdatasync(op->odip->fd) < 0)
1944 perror("fdatasync() error");
1945 if (op->verbose)
1946 pr2serr("Called fdatasync() on %s successfully\n", op->odip->fn);
1947 }
1948 #endif
1949 #ifdef HAVE_FSYNC
1950 else if (op->oflagp->fsync) {
1951 if (fsync(op->odip->fd) < 0)
1952 perror("fsync() error");
1953 if (op->verbose)
1954 pr2serr("Called fsync() on %s successfully\n", op->odip->fn);
1955 }
1956 #endif
1957
1958 copy_end:
1959 if (op->idip->ptvp) {
1960 pt_destruct_obj(op->idip->ptvp);
1961 op->idip->ptvp = NULL;
1962 }
1963 if (op->odip->ptvp) {
1964 pt_destruct_obj(op->odip->ptvp);
1965 op->odip->ptvp = NULL;
1966 }
1967 return ret;
1968 }
1969
1970 static int
prepare_pi(struct opts_t * op)1971 prepare_pi(struct opts_t * op)
1972 {
1973 #define PI_WORK 1 /* Protection Information */
1974 #ifdef PI_WORK
1975 int res;
1976
1977 op->ibs_pi = op->ibs;
1978 op->obs_pi = op->obs;
1979 if (op->rdprotect) {
1980 if ((0 == op->idip->prot_type) || (! (FT_PT & op->idip->d_type))) {
1981 pr2serr("IFILE is not a pt device or doesn't have "
1982 "protection information\n");
1983 return SG_LIB_CAT_OTHER;
1984 }
1985 if (op->ibs != op->obs) {
1986 pr2serr("protect: don't support IFILE and OFILE "
1987 "with different block sizes\n");
1988 return SG_LIB_CAT_OTHER;
1989 }
1990 if (op->wrprotect) {
1991 if (op->idip->p_i_exp != op->odip->p_i_exp) {
1992 pr2serr("Don't support IFILE and OFILE with "
1993 "different P_I_EXP fields\n");
1994 return SG_LIB_CAT_OTHER;
1995 }
1996 }
1997 res = (op->idip->p_i_exp ? (1 << op->idip->p_i_exp) : 1) * 8;
1998 op->ibs_pi += res;
1999 op->obs_pi += res;
2000 }
2001 if (op->wrprotect) {
2002 if ((0 == op->odip->prot_type) || (! (FT_PT & op->odip->d_type))) {
2003 pr2serr("OFILE is not a pt device or doesn't have "
2004 "protection information\n");
2005 return SG_LIB_CAT_OTHER;
2006 }
2007 if (op->ibs != op->obs) {
2008 pr2serr("protect: don't support IFILE and OFILE "
2009 "with different block sizes\n");
2010 return SG_LIB_CAT_OTHER;
2011 }
2012 res = (op->odip->p_i_exp ? (1 << op->odip->p_i_exp) : 1) * 8;
2013 op->ibs_pi += res;
2014 op->obs_pi += res;
2015 }
2016 #else
2017 if (op) { ; } /* suppress warning */
2018 #endif /* PI_WORK */
2019 return 0;
2020 }
2021
2022 static int
open_files_devices(struct opts_t * op)2023 open_files_devices(struct opts_t * op)
2024 {
2025 int fd, ret;
2026 struct dev_info_t * idip = op->idip;
2027 struct dev_info_t * odip = op->odip;
2028 struct dev_info_t * o2dip = op->o2dip;
2029
2030 #ifdef SG_LIB_WIN32
2031 win32_adjust_fns_pt(op);
2032 #endif
2033 if (idip->fn[0]) {
2034 if (('-' == idip->fn[0]) && ('\0' == idip->fn[1])) {
2035 fd = STDIN_FILENO;
2036 idip->d_type = FT_FIFO;
2037 ++op->reading_fifo;
2038 if (op->verbose)
2039 pr2serr(" >> Input file type: fifo [stdin, stdout, named "
2040 "pipe]\n");
2041 } else {
2042 fd = open_if(op);
2043 if (fd < 0)
2044 return -fd;
2045 }
2046 idip->fd = fd;
2047 } else if (op->iflagp->ff) {
2048 idip->d_type = FT_ALL_FF;
2049 idip->fd = 9999; /* unlikely file descriptor */
2050 } else {
2051 pr2serr("'if=IFILE' option must be given. For stdin as input use "
2052 "'if=-'\n");
2053 pr2serr("For more information use '--help'\n");
2054 return SG_LIB_SYNTAX_ERROR;
2055 }
2056
2057 if ('\0' == odip->fn[0])
2058 strcpy(odip->fn, "."); /* treat no 'of=OFILE' option as /dev/null */
2059 if (('-' == odip->fn[0]) && ('\0' == odip->fn[1])) {
2060 fd = STDOUT_FILENO;
2061 odip->d_type = FT_FIFO;
2062 odip->d_type_hold = odip->d_type;
2063 if (op->verbose)
2064 pr2serr(" >> Output file type: fifo [stdin, stdout, named "
2065 "pipe]\n");
2066 } else {
2067 fd = open_of(op);
2068 if (fd < -1)
2069 return -fd;
2070 }
2071 odip->fd = fd;
2072
2073 if (o2dip->fn[0]) {
2074 if (('-' == o2dip->fn[0]) && ('\0' == o2dip->fn[1])) {
2075 fd = STDOUT_FILENO;
2076 o2dip->d_type = FT_FIFO;
2077 if (op->verbose)
2078 pr2serr(" >> Output 2 file type: fifo [stdin, stdout, "
2079 "named pipe]\n");
2080 } else {
2081 o2dip->d_type = dd_filetype(o2dip->fn, op->verbose);
2082 if (FT_DEV_NULL & o2dip->d_type)
2083 fd = -1;
2084 else if (! ((FT_REG | FT_FIFO) & o2dip->d_type)) {
2085 pr2serr("Error: output 2 file type must be regular "
2086 "file or fifo\n");
2087 return SG_LIB_FILE_ERROR;
2088 } else {
2089 if ((fd = open(o2dip->fn, O_WRONLY | O_CREAT, 0666)) < 0) {
2090 ret = errno;
2091 pr2serr("could not open %s for writing: %s\n", o2dip->fn,
2092 safe_strerror(errno));
2093 return ret;
2094 }
2095 if (sg_set_binary_mode(fd) < 0)
2096 perror("sg_set_binary_mode");
2097 if (op->verbose)
2098 pr2serr(" >> Output 2 file type: regular\n");
2099 }
2100 }
2101 } else
2102 fd = -1;
2103 o2dip->fd = fd;
2104 return 0;
2105 }
2106
2107 static void
block_size_bpt_check(struct opts_t * op)2108 block_size_bpt_check(struct opts_t * op)
2109 {
2110 if (0 == op->bpt_given) {
2111 /* If reading from or writing to tape, use default bpt 1 if user did not
2112 * specify. Avoids inadvertent/accidental use of wrong tape block size. */
2113 if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type)) {
2114 op->bpt_i = 1;
2115 }
2116 #ifdef SG_LIB_FREEBSD
2117 else {
2118 /* FreeBSD (7+8 [DFLTPHYS]) doesn't like buffers larger than 64 KB being
2119 * sent to its pt interface (CAM), so take that into account when choosing
2120 * the default bpt value. There is overhead in the pt interface so reduce
2121 * default bpt value so bpt*ibs <= 32 KB .*/
2122 if (((FT_PT & op->idip->d_type) || (FT_PT & op->odip->d_type)) &&
2123 ((op->ibs <= 32768) && (op->bpt_i * op->ibs) > 32768))
2124 op->bpt_i = 32768 / op->ibs;
2125 }
2126 #endif
2127 }
2128 }
2129
2130 static void
sparse_sparing_check(struct opts_t * op)2131 sparse_sparing_check(struct opts_t * op)
2132 {
2133 if (op->iflagp->sparse && (! op->oflagp->sparse)) {
2134 if (FT_DEV_NULL & op->odip->d_type) {
2135 pr2serr("sparse flag usually ignored on input; set it "
2136 "on output in this case\n");
2137 ++op->oflagp->sparse;
2138 } else
2139 pr2serr("sparse flag ignored on input\n");
2140 }
2141 if (op->oflagp->sparse) {
2142 if ((FT_FIFO | FT_TAPE) & op->odip->d_type) {
2143 pr2serr("oflag=sparse needs seekable output file, ignore\n");
2144 op->oflagp->sparse = 0;
2145 } else {
2146 op->out_sparse_active = 1;
2147 if (op->oflagp->wsame16)
2148 op->out_trim_active = 1;
2149 }
2150 }
2151 if (op->oflagp->sparing) {
2152 if ((FT_DEV_NULL | FT_FIFO | FT_TAPE) & op->odip->d_type) {
2153 pr2serr("oflag=sparing needs a readable and seekable "
2154 "output file, ignore\n");
2155 op->oflagp->sparing = 0;
2156 } else
2157 op->out_sparing_active = 1;
2158 }
2159 }
2160
2161 static void
cdb_size_prealloc(struct opts_t * op)2162 cdb_size_prealloc(struct opts_t * op)
2163 {
2164 if (op->oflagp->prealloc) {
2165 if ((FT_DEV_NULL | FT_FIFO | FT_TAPE | FT_PT) & op->odip->d_type) {
2166 pr2serr("oflag=pre-alloc needs a normal output file, ignore\n");
2167 op->oflagp->prealloc = 0;
2168 }
2169 }
2170 if (! op->cdbsz_given) {
2171 if ((FT_PT & op->idip->d_type) && (op->iflagp->cdbsz < 16) &&
2172 (((op->dd_count + op->skip) > UINT_MAX) ||
2173 (op->bpt_i > USHRT_MAX))) {
2174 if (op->verbose > 0)
2175 pr2serr("SCSI command size increased from 10 to 16 "
2176 "bytes on %s\n", op->idip->fn);
2177 op->iflagp->cdbsz = 16;
2178 }
2179 if ((FT_PT & op->odip->d_type) && (op->oflagp->cdbsz < 16) &&
2180 (((op->dd_count + op->seek) > UINT_MAX) ||
2181 (((op->ibs * op->bpt_i) / op->obs) > USHRT_MAX))) {
2182 if (op->verbose)
2183 pr2serr("SCSI command size increased from 10 to 16 "
2184 "bytes on %s\n", op->odip->fn);
2185 op->oflagp->cdbsz = 16;
2186 }
2187 }
2188 }
2189
2190 #ifdef SG_LIB_LINUX
2191
2192 static void
tape_cleanup_of(struct opts_t * op)2193 tape_cleanup_of(struct opts_t * op)
2194 {
2195 /* Before closing OFILE, if writing to tape handle suppressing the
2196 * writing of a filemark and/or flushing the drive buffer which the
2197 * Linux st driver normally does when tape file is closed after writing.
2198 * Possibilities depend on oflag arguments:
2199 * nofm: MTWEOFI 0 if possible (kernel 2.6.37+), else MTBSR 0
2200 * nofm & fsync: MTWEOF 0
2201 * fsync: Do nothing; st writes filemark & flushes buffer on close.
2202 * neither: MTWEOFI 1 if possible (2.6.37+), else nothing (drive
2203 * buffer will be flushed if MTWEOFI not possible). */
2204 struct mtop mt_cmd;
2205 int res;
2206
2207 if (op->oflagp->nofm || !op->oflagp->fsync) {
2208 mt_cmd.mt_op = (op->oflagp->fsync) ? MTWEOF : MTWEOFI;
2209 mt_cmd.mt_count = (op->oflagp->nofm) ? 0 : 1;
2210 res = ioctl(op->odip->fd, MTIOCTOP, &mt_cmd);
2211 if (res != 0) {
2212 if (op->verbose > 0)
2213 pr2serr("MTWEOF%s %d failed: %s\n",
2214 (op->oflagp->fsync) ? "" : "I", mt_cmd.mt_count,
2215 safe_strerror(errno));
2216 if (op->oflagp->nofm && !op->oflagp->fsync) {
2217 if (op->verbose > 0)
2218 pr2serr("Trying MTBSR 0 instead\n");
2219 mt_cmd.mt_op = MTBSR; /* mt_cmd.mt_count = 0 from above */
2220 res = ioctl(op->odip->fd, MTIOCTOP, &mt_cmd);
2221 if (res != 0)
2222 pr2serr("MTBSR 0 failed: %s\n(Filemark will be written "
2223 "when tape file is closed)\n",
2224 safe_strerror(errno));
2225 }
2226 }
2227 }
2228 }
2229
2230 #endif /* SG_LIB_LINUX */
2231
2232 static int
do_falloc(struct opts_t * op)2233 do_falloc(struct opts_t * op)
2234 {
2235 #ifdef SG_LIB_LINUX
2236 #ifdef HAVE_FALLOCATE
2237 /* Try to pre-allocate space in the output file.
2238 *
2239 * If fallocate() does not succeed, exit with an error message. The user
2240 * can then either free up some disk space or invoke ddpt without
2241 * oflag=pre-alloc (at the risk of running out of disk space).
2242 *
2243 * TODO/DISCUSSION: Some filesystems (e.g. FAT32) don't support
2244 * fallocate(). In that case we should probably have a way to continue if
2245 * fallocate() fails, rather than exiting; useful for use in scripts
2246 * where the user would like to pre-allocate space when possible.
2247 *
2248 * On Linux, try fallocate() with the FALLOC_FL_KEEP_SIZE flag, which
2249 * allocates space but doesn't change the apparent file size (useful
2250 * since oflag=resume can be used).
2251 *
2252 * If fallocate() with FALLOC_FL_KEEP_SIZE returns ENOTTY, EINVAL or
2253 * EOPNOTSUPP, retry without that flag (since the flag is only supported
2254 * in recent Linux kernels). */
2255 int res;
2256
2257 #ifdef PREALLOC_DEBUG
2258 pr2serr("About to call fallocate() with FALLOC_FL_KEEP_SIZE\n");
2259 #endif
2260 res = fallocate(op->odip->fd, FALLOC_FL_KEEP_SIZE, op->obs*op->seek,
2261 op->obs*op->dd_count);
2262 #ifdef PREALLOC_DEBUG
2263 pr2serr("fallocate() returned %d\n", res);
2264 #endif
2265 /* fallocate() fails if the kernel does not support
2266 * FALLOC_FL_KEEP_SIZE, so retry without that flag. */
2267 if (-1 == res) {
2268 if ((ENOTTY == errno) || (EINVAL == errno)
2269 || (EOPNOTSUPP == errno)) {
2270 if (op->verbose)
2271 pr2serr("Could not pre-allocate with "
2272 "FALLOC_FL_KEEP_SIZE (%s), retrying without "
2273 "...\n", safe_strerror(errno));
2274 res = fallocate(op->odip->fd, 0, op->obs*op->seek,
2275 op->obs*op->dd_count);
2276 #ifdef PREALLOC_DEBUG
2277 pr2serr("fallocate() without FALLOC_FL_KEEP_SIZE "
2278 " returned %d\n", res);
2279 #endif
2280 }
2281 } else {
2282 /* fallocate() with FALLOC_FL_KEEP_SIZE succeeded. Set
2283 * op->oflagp->prealloc to 0 so the possible message about using
2284 * oflag=resume is not suppressed later. */
2285 op->oflagp->prealloc = 0;
2286 }
2287 if (-1 == res) {
2288 pr2serr("Unable to pre-allocate space: %s\n",
2289 safe_strerror(errno));
2290 return SG_LIB_CAT_OTHER;
2291 }
2292 if (op->verbose > 1)
2293 pr2serr("Pre-allocated %" PRId64 " bytes at offset %"
2294 PRId64 "\n", op->obs*op->dd_count, op->obs*op->seek);
2295
2296 #endif /* HAVE_FALLOCATE */
2297 #else /* other than SG_LIB_LINUX */
2298 #ifdef HAVE_POSIX_FALLOCATE
2299 int res;
2300
2301 /* If not on Linux, use posix_fallocate(). (That sets the file size to its
2302 * full length, so re-invoking ddpt with oflag=resume will do nothing.) */
2303 res = posix_fallocate(op->odip->fd, op->obs*op->seek,
2304 op->obs*op->dd_count);
2305 if (-1 == res) {
2306 pr2serr("Unable to pre-allocate space: %s\n",
2307 safe_strerror(errno));
2308 return SG_LIB_CAT_OTHER;
2309 }
2310 if (op->verbose > 1)
2311 pr2serr("Pre-allocated %" PRId64 " bytes at offset %" PRId64 "\n",
2312 op->obs*op->dd_count, op->obs*op->seek);
2313 #else /* do not HAVE_POSIX_FALLOCATE */
2314 if (op) { ; }
2315 #endif /* HAVE_POSIX_FALLOCATE else */
2316 #endif /* SG_LIB_LINUX else */
2317 return 0;
2318 }
2319
2320 static void
details_pre_copy_print(struct opts_t * op)2321 details_pre_copy_print(struct opts_t * op)
2322 {
2323 pr2serr("skip=%" PRId64 " (blocks on input), seek=%" PRId64
2324 " (blocks on output)\n", op->skip, op->seek);
2325 if (op->verbose > 1) {
2326 pr2serr(" ibs=%d bytes, obs=%d bytes, OBPC=%d\n",
2327 op->ibs, op->obs, op->obpch);
2328 if (op->ibs != op->ibs_pi)
2329 pr2serr(" due to protect ibs_pi=%d bytes, "
2330 "obs_pi=%d bytes\n", op->ibs_pi, op->obs_pi);
2331 }
2332 if (op->reading_fifo && (op->dd_count < 0))
2333 pr2serr(" reading fifo, blocks_per_transfer=%d\n", op->bpt_i);
2334 else
2335 pr2serr(" initial count=%" PRId64 " (blocks of input), "
2336 "blocks_per_transfer=%d\n", op->dd_count, op->bpt_i);
2337 if ((op->delay > 0) || (op->wdelay > 0))
2338 pr2serr(" delay=%d ms, wdelay=%d ms\n", op->delay, op->wdelay);
2339 }
2340
2341 static int
wrk_buffers_init(struct opts_t * op)2342 wrk_buffers_init(struct opts_t * op)
2343 {
2344 int len = op->ibs_pi * op->bpt_i;
2345
2346 if (op->has_xcopy)
2347 return 0;
2348 if (op->iflagp->direct || op->oflagp->direct) {
2349 size_t psz;
2350
2351 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
2352 psz = sysconf(_SC_PAGESIZE); /* POSIX.1 (was getpagesize()) */
2353 #elif defined(SG_LIB_WIN32)
2354 psz = win32_pagesize();
2355 #else
2356 psz = 4096; /* give up, pick likely figure */
2357 #endif
2358
2359 #ifdef HAVE_POSIX_MEMALIGN
2360 {
2361 int err;
2362 void * wp;
2363
2364 wp = op->wrkBuff;
2365 err = posix_memalign(&wp, psz, len);
2366 if (err) {
2367 pr2serr("posix_memalign: error [%d] out of memory?\n", err);
2368 return SG_LIB_CAT_OTHER;
2369 }
2370 op->wrkBuff = (unsigned char *)wp;
2371 memset(op->wrkBuff, 0, len);
2372 op->wrkPos = op->wrkBuff;
2373 if (op->oflagp->sparing) {
2374 wp = op->wrkBuff2;
2375 err = posix_memalign(&wp, psz, len);
2376 if (err) {
2377 pr2serr("posix_memalign(2): error [%d] out of memory?\n",
2378 err);
2379 return SG_LIB_CAT_OTHER;
2380 }
2381 op->wrkBuff2 = (unsigned char *)wp;
2382 memset(op->wrkBuff2, 0, len);
2383 op->wrkPos2 = op->wrkBuff2;
2384 }
2385 }
2386 #else /* do not HAVE_POSIX_MEMALIGN */
2387 op->wrkBuff = (unsigned char*)calloc(len + psz, 1);
2388 if (0 == op->wrkBuff) {
2389 pr2serr("Not enough user memory for aligned usage\n");
2390 return SG_LIB_CAT_OTHER;
2391 }
2392 op->wrkPos = (unsigned char *)(((uintptr_t)op->wrkBuff + psz - 1) &
2393 (~((uintptr_t)psz - 1)));
2394 if (op->oflagp->sparing) {
2395 op->wrkBuff2 = (unsigned char*)calloc(len + psz, 1);
2396 if (0 == op->wrkBuff2) {
2397 pr2serr("Not enough user memory for aligned usage(2)\n");
2398 return SG_LIB_CAT_OTHER;
2399 }
2400 op->wrkPos2 = (unsigned char *)
2401 (((uintptr_t)op->wrkBuff2 + psz - 1) &
2402 (~((uintptr_t)psz - 1)));
2403 }
2404 #endif /* HAVE_POSIX_MEMALIGN */
2405 } else {
2406 op->wrkBuff = (unsigned char*)calloc(op->ibs_pi * op->bpt_i, 1);
2407 if (0 == op->wrkBuff) {
2408 pr2serr("Not enough user memory\n");
2409 return SG_LIB_CAT_OTHER;
2410 }
2411 op->wrkPos = op->wrkBuff;
2412 if (op->oflagp->sparing) {
2413 op->wrkBuff2 = (unsigned char*)calloc(op->ibs_pi * op->bpt_i, 1);
2414 if (0 == op->wrkBuff2) {
2415 pr2serr("Not enough user memory(2)\n");
2416 return SG_LIB_CAT_OTHER;
2417 }
2418 op->wrkPos2 = op->wrkBuff2;
2419 }
2420 }
2421 return 0;
2422 }
2423
2424 static void
cleanup_resources(struct opts_t * op)2425 cleanup_resources(struct opts_t * op)
2426 {
2427 #ifdef SG_LIB_LINUX
2428 if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type)) {
2429 /* For writing, the st driver writes a filemark on closing the file
2430 * (unless user specified oflag=nofm), so make clear that the
2431 * position shown is prior to closing. */
2432 print_tape_pos("Final ", " (before closing file)", op);
2433 if ((FT_TAPE & op->odip->d_type) && (op->verbose > 1) &&
2434 op->oflagp->nofm)
2435 pr2serr("(suppressing writing of filemark on close)\n");
2436 }
2437 #endif
2438
2439 if (op->iflagp->errblk)
2440 errblk_close(op);
2441
2442 if (op->wrkBuff)
2443 free(op->wrkBuff);
2444 if (op->wrkBuff2)
2445 free(op->wrkBuff2);
2446 if (op->zeros_buff)
2447 free(op->zeros_buff);
2448 if (FT_PT & op->idip->d_type)
2449 pt_close(op->idip->fd);
2450 else if ((op->idip->fd >= 0) && (STDIN_FILENO != op->idip->fd))
2451 close(op->idip->fd);
2452 if (FT_PT & op->odip->d_type)
2453 pt_close(op->odip->fd);
2454 if ((op->odip->fd >= 0) && (STDOUT_FILENO != op->odip->fd) &&
2455 !(FT_DEV_NULL & op->odip->d_type)) {
2456 #ifdef SG_LIB_LINUX
2457 if (FT_TAPE & op->odip->d_type)
2458 tape_cleanup_of(op);
2459 #endif
2460 close(op->odip->fd);
2461 }
2462 if ((op->o2dip->fd >= 0) && (STDOUT_FILENO != op->o2dip->fd))
2463 close(op->o2dip->fd);
2464 }
2465
2466 static int
chk_sgl_for_non_offload(struct opts_t * op)2467 chk_sgl_for_non_offload(struct opts_t * op)
2468 {
2469 if (op->in_sgl) {
2470 if (op->in_sgl_elems > 1) {
2471 pr2serr("Only accept a multiple element skip= (gather) list for "
2472 "%s with odx\n", op->idip->fn[0] ? op->idip->fn : "?");
2473 return SG_LIB_SYNTAX_ERROR;
2474 }
2475 if ((op->dd_count >= 0) && (op->dd_count != op->in_sgl[0].num)) {
2476 pr2serr("dd_count [%" PRIu64 "] and skip (sgl num) [%" PRIu32 "] "
2477 "contradict\n", op->dd_count, op->in_sgl[0].num);
2478 return SG_LIB_SYNTAX_ERROR;
2479 }
2480 op->skip = op->in_sgl[0].lba;
2481 op->dd_count = op->in_sgl[0].num;
2482 }
2483 if (op->out_sgl) {
2484 if (op->out_sgl_elems > 1) {
2485 pr2serr("Only accept a multiple element seek= (scatter) list for "
2486 "%s with odx\n", op->odip->fn[0] ? op->odip->fn : "?");
2487 return SG_LIB_SYNTAX_ERROR;
2488 }
2489 /* assuming ibs==obs, revisit xxxxxxx */
2490 if ((op->dd_count >= 0) && (op->dd_count != op->out_sgl[0].num)) {
2491 pr2serr("dd_count [%" PRIu64 "] and seek (sgl num) [%" PRIu32 "] "
2492 "too confusing\n", op->dd_count, op->out_sgl[0].num);
2493 return SG_LIB_SYNTAX_ERROR;
2494 }
2495 op->seek = op->out_sgl[0].lba;
2496 op->dd_count = op->out_sgl[0].num;
2497 }
2498 return 0;
2499 }
2500
2501
2502 /* The main() function: much of the its complex logic is spawned off to
2503 * helper functions shown directly above. */
2504 int
main(int argc,char * argv[])2505 main(int argc, char * argv[])
2506 {
2507 int ret = 0;
2508 int started_copy = 0;
2509 int jf_depth = 0;
2510 struct opts_t ops;
2511 struct flags_t iflag, oflag;
2512 struct dev_info_t ids, ods, o2ds;
2513 struct opts_t * op;
2514
2515 op = &ops;
2516 state_init(op, &iflag, &oflag, &ids, &ods, &o2ds);
2517 ret = cl_process(op, argc, argv, ddpt_version_str, jf_depth);
2518 if (op->do_help > 0) {
2519 ddpt_usage(op->do_help);
2520 return 0;
2521 } else if (ret)
2522 return (ret < 0) ? 0 : ret;
2523
2524 if (op->quiet) {
2525 if (NULL == freopen("/dev/null", "w", stderr))
2526 pr2serr("freopen: failed to redirect stderr to /dev/null : %s\n",
2527 safe_strerror(errno));
2528 }
2529
2530 #ifdef SG_LIB_WIN32
2531 if (op->wscan)
2532 return sg_do_wscan('\0', op->wscan, op->verbose);
2533 #endif
2534
2535 install_signal_handlers(op);
2536
2537 if (op->has_odx) {
2538 started_copy = 1;
2539 ret = do_odx(op);
2540 goto cleanup;
2541 }
2542
2543 /* may allow scatter gather lists for non-odx copies in future */
2544 ret = chk_sgl_for_non_offload(op);
2545 if (ret)
2546 return ret;
2547
2548 if ((ret = open_files_devices(op)))
2549 return ret;
2550
2551 block_size_bpt_check(op);
2552 sparse_sparing_check(op);
2553
2554 if ((ret = count_calculate(op))) {
2555 if (op->verbose)
2556 pr2serr("count_calculate() returned %d, exit\n", ret);
2557 goto cleanup;
2558 }
2559
2560 if ((ret = prepare_pi(op)))
2561 goto cleanup;
2562
2563 if ((op->dd_count < 0) && (! op->reading_fifo)) {
2564 pr2serr("Couldn't calculate count, please give one\n");
2565 ret = SG_LIB_CAT_OTHER;
2566 goto cleanup;
2567 }
2568
2569 cdb_size_prealloc(op);
2570
2571 if ((ret = wrk_buffers_init(op)))
2572 goto cleanup;
2573
2574 if (op->verbose)
2575 details_pre_copy_print(op);
2576
2577 op->read1_or_transfer = !! (FT_DEV_NULL & op->odip->d_type);
2578 op->dd_count_start = op->dd_count;
2579 if (op->read1_or_transfer && (! op->outf_given) &&
2580 ((op->dd_count > 0) || op->reading_fifo))
2581 pr2serr("Output file not specified so no copy, just reading input\n");
2582
2583 if (op->do_time)
2584 calc_duration_init(op);
2585
2586 if (op->iflagp->errblk)
2587 errblk_open(op);
2588
2589 #ifdef SG_LIB_LINUX
2590 if ((FT_TAPE & op->idip->d_type) || (FT_TAPE & op->odip->d_type))
2591 print_tape_pos("Initial ", "", op);
2592 #endif
2593
2594 if (op->oflagp->prealloc) {
2595 if ((ret = do_falloc(op)))
2596 goto cleanup;
2597 }
2598
2599 ++started_copy;
2600 if (op->has_xcopy)
2601 ret = do_xcopy_lid1(op);
2602 else
2603 ret = do_rw_copy(op);
2604
2605 if (0 == op->status_none)
2606 print_stats("", op, 0);
2607
2608 if ((op->oflagp->ssync) && (FT_PT & op->odip->d_type)) {
2609 if (0 == op->status_none)
2610 pr2serr(">> SCSI synchronizing cache on %s\n", op->odip->fn);
2611 pt_sync_cache(op->odip->fd);
2612 }
2613 if (op->do_time)
2614 calc_duration_throughput("", 0, op);
2615
2616 if (op->sum_of_resids)
2617 pr2serr(">> Non-zero sum of residual counts=%d\n", op->sum_of_resids);
2618
2619 cleanup:
2620 cleanup_resources(op);
2621 if ((0 == ret) && op->err_to_report)
2622 ret = op->err_to_report;
2623 if (started_copy && (0 != op->dd_count) && (! op->reading_fifo)) {
2624 if (0 == ret)
2625 pr2serr("Early termination, EOF on input?\n");
2626 else if (ret > 0)
2627 print_exit_status_msg("Early termination", ret, 1);
2628 else {
2629 if (op->verbose < 2)
2630 pr2serr("Early termination: some error occurred; try again "
2631 "with '-vv'\n");
2632 else
2633 pr2serr("Early termination: some error occurred\n");
2634 }
2635 }
2636 return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
2637 }
2638