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