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