1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Keith Muller of the University of California, San Diego and Lance 7 * Visser of Convex Computer Corporation. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 #ifndef lint 13 static char sccsid[] = "@(#)position.c 5.3 (Berkeley) 08/05/91"; 14 #endif /* not lint */ 15 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 #include <sys/ioctl.h> 19 #include <sys/mtio.h> 20 #include <errno.h> 21 #include <unistd.h> 22 #include <string.h> 23 #include "dd.h" 24 #include "extern.h" 25 26 /* 27 * Position input/output data streams before starting the copy. Device type 28 * dependent. Seekable devices use lseek, and the rest position by reading. 29 * Seeking past the end of file can cause null blocks to be written to the 30 * output. 31 */ 32 void 33 pos_in() 34 { 35 register int bcnt, cnt, nr, warned; 36 37 /* If not a character, pipe or tape device, try to seek on it. */ 38 if (!(in.flags & (ISCHR|ISPIPE|ISTAPE))) { 39 if (lseek(in.fd, (off_t)(in.offset * in.dbsz), SEEK_CUR) == -1) 40 err("%s: %s", in.name, strerror(errno)); 41 return; 42 } 43 44 /* 45 * Read the data. If a pipe, read until satisfy the number of bytes 46 * being skipped. No differentiation for reading complete and partial 47 * blocks for other devices. 48 */ 49 for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { 50 if ((nr = read(in.fd, in.db, bcnt)) > 0) { 51 if (in.flags & ISPIPE) { 52 if (!(bcnt -= nr)) { 53 bcnt = in.dbsz; 54 --cnt; 55 } 56 } else 57 --cnt; 58 continue; 59 } 60 61 if (nr == 0) { 62 if (files_cnt > 1) { 63 --files_cnt; 64 continue; 65 } 66 err("skip reached end of input"); 67 } 68 69 /* 70 * Input error -- either EOF with no more files, or I/O error. 71 * If noerror not set die. POSIX requires that the warning 72 * message be followed by an I/O display. 73 */ 74 if (ddflags & C_NOERROR) { 75 if (!warned) { 76 warn("%s: %s", in.name, strerror(errno)); 77 warned = 1; 78 summary(0); 79 } 80 continue; 81 } 82 err("%s: %s", in.name, strerror(errno)); 83 } 84 } 85 86 void 87 pos_out() 88 { 89 register int cnt, n; 90 struct mtop t_op; 91 92 /* 93 * If not a tape, try seeking on the file. Seeking on a pipe is 94 * going to fail, but don't protect the user -- they shouldn't 95 * have specified the seek operand. 96 */ 97 if (!(out.flags & ISTAPE)) { 98 if (lseek(out.fd, 99 (off_t)out.offset * out.dbsz, SEEK_SET) == -1) 100 err("%s: %s", out.name, strerror(errno)); 101 return; 102 } 103 104 /* If no read access, try using mtio. */ 105 if (out.flags & NOREAD) { 106 t_op.mt_op = MTFSR; 107 t_op.mt_count = out.offset; 108 109 if (ioctl(out.fd, MTIOCTOP, &t_op) < 0) 110 err("%s: %s", out.name, strerror(errno)); 111 return; 112 } 113 114 /* Read it. */ 115 for (cnt = 0; cnt < out.offset; ++cnt) { 116 if ((n = read(out.fd, out.db, out.dbsz)) > 0) 117 continue; 118 119 if (n < 0) 120 err("%s: %s", out.name, strerror(errno)); 121 122 /* 123 * If reach EOF, fill with NUL characters; first, back up over 124 * the EOF mark. Note, cnt has not yet been incremented, so 125 * the EOF read does not count as a seek'd block. 126 */ 127 t_op.mt_op = MTBSR; 128 t_op.mt_count = 1; 129 if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 130 err("%s: %s", out.name, strerror(errno)); 131 132 while (cnt++ < out.offset) 133 if ((n = write(out.fd, out.db, out.dbsz)) != out.dbsz) 134 err("%s: %s", out.name, strerror(errno)); 135 break; 136 } 137 } 138