position.c revision 1.12 1 /* $NetBSD: position.c,v 1.12 2001/11/26 00:56:33 enami Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Keith Muller of the University of California, San Diego and Lance
9 * Visser of Convex Computer Corporation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
44 #else
45 __RCSID("$NetBSD: position.c,v 1.12 2001/11/26 00:56:33 enami Exp $");
46 #endif
47 #endif /* not lint */
48
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/ioctl.h>
52 #include <sys/mtio.h>
53 #include <sys/time.h>
54
55 #include <err.h>
56 #include <errno.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 #include "dd.h"
61 #include "extern.h"
62
63 /*
64 * Position input/output data streams before starting the copy. Device type
65 * dependent. Seekable devices use lseek, and the rest position by reading.
66 * Seeking past the end of file can cause null blocks to be written to the
67 * output.
68 */
69 void
70 pos_in(void)
71 {
72 int bcnt, cnt, nr, warned;
73
74 /* If not a pipe or tape device, try to seek on it. */
75 if (!(in.flags & (ISPIPE|ISTAPE))) {
76 if (lseek(in.fd,
77 (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1)
78 err(1, "%s", in.name);
79 return;
80 }
81
82 /*
83 * Read the data. If a pipe, read until satisfy the number of bytes
84 * being skipped. No differentiation for reading complete and partial
85 * blocks for other devices.
86 */
87 for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
88 if ((nr = read(in.fd, in.db, bcnt)) > 0) {
89 if (in.flags & ISPIPE) {
90 if (!(bcnt -= nr)) {
91 bcnt = in.dbsz;
92 --cnt;
93 }
94 } else
95 --cnt;
96 continue;
97 }
98
99 if (nr == 0) {
100 if (files_cnt > 1) {
101 --files_cnt;
102 continue;
103 }
104 errx(1, "skip reached end of input");
105 }
106
107 /*
108 * Input error -- either EOF with no more files, or I/O error.
109 * If noerror not set die. POSIX requires that the warning
110 * message be followed by an I/O display.
111 */
112 if (ddflags & C_NOERROR) {
113 if (!warned) {
114 warn("%s", in.name);
115 warned = 1;
116 summary();
117 }
118 continue;
119 }
120 err(1, "%s", in.name);
121 }
122 }
123
124 void
125 pos_out(void)
126 {
127 struct mtop t_op;
128 int cnt, n;
129
130 /*
131 * If not a tape, try seeking on the file. Seeking on a pipe is
132 * going to fail, but don't protect the user -- they shouldn't
133 * have specified the seek operand.
134 */
135 if (!(out.flags & ISTAPE)) {
136 if (lseek(out.fd,
137 (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
138 err(1, "%s", out.name);
139 return;
140 }
141
142 /* If no read access, try using mtio. */
143 if (out.flags & NOREAD) {
144 t_op.mt_op = MTFSR;
145 t_op.mt_count = out.offset;
146
147 if (ioctl(out.fd, MTIOCTOP, &t_op) < 0)
148 err(1, "%s", out.name);
149 return;
150 }
151
152 /* Read it. */
153 for (cnt = 0; cnt < out.offset; ++cnt) {
154 if ((n = read(out.fd, out.db, out.dbsz)) > 0)
155 continue;
156
157 if (n < 0)
158 err(1, "%s", out.name);
159
160 /*
161 * If reach EOF, fill with NUL characters; first, back up over
162 * the EOF mark. Note, cnt has not yet been incremented, so
163 * the EOF read does not count as a seek'd block.
164 */
165 t_op.mt_op = MTBSR;
166 t_op.mt_count = 1;
167 if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
168 err(1, "%s", out.name);
169
170 while (cnt++ < out.offset)
171 if ((n = bwrite(out.fd, out.db, out.dbsz)) != out.dbsz)
172 err(1, "%s", out.name);
173 break;
174 }
175 }
176