Commit | Line | Data |
---|---|---|
5e002034 KB |
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 | |
a08a4cd0 KB |
6 | * Keith Muller of the University of California, San Diego and Lance |
7 | * Visser of Convex Computer Corporation. | |
5e002034 KB |
8 | * |
9 | * %sccs.include.redist.c% | |
10 | */ | |
11 | ||
12 | #ifndef lint | |
a08a4cd0 | 13 | static char sccsid[] = "@(#)position.c 5.2 (Berkeley) %G%"; |
5e002034 KB |
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 | continue; | |
57 | } else | |
58 | --cnt; | |
59 | ||
60 | if (nr == 0) { | |
61 | if (files_cnt > 1) { | |
62 | --files_cnt; | |
63 | continue; | |
64 | } | |
65 | err("skip reached end of input"); | |
66 | } | |
67 | ||
68 | /* | |
69 | * Input error -- either EOF with no more files, or I/O error. | |
70 | * If noerror not set die. POSIX requires that the warning | |
71 | * message be followed by an I/O display. | |
72 | */ | |
73 | if (ddflags & C_NOERROR) { | |
74 | if (!warned) { | |
75 | warn("%s: %s", in.name, strerror(errno)); | |
76 | warned = 1; | |
77 | summary(0); | |
78 | } | |
79 | continue; | |
80 | } | |
81 | err("%s: %s", in.name, strerror(errno)); | |
82 | } | |
83 | } | |
84 | ||
85 | void | |
86 | pos_out() | |
87 | { | |
88 | register int cnt, n; | |
89 | struct mtop t_op; | |
90 | ||
91 | /* | |
92 | * If not a tape, try seeking on the file. Seeking on a pipe is | |
93 | * going to fail, but don't protect the user -- they shouldn't | |
94 | * have specified the seek operand. | |
95 | */ | |
96 | if (!(out.flags & ISTAPE)) { | |
97 | if (lseek(out.fd, | |
98 | (off_t)out.offset * out.dbsz, SEEK_SET) == -1) | |
99 | err("%s: %s", out.name, strerror(errno)); | |
100 | return; | |
101 | } | |
102 | ||
103 | /* If no read access, try using mtio. */ | |
104 | if (out.flags & NOREAD) { | |
105 | t_op.mt_op = MTFSR; | |
106 | t_op.mt_count = out.offset; | |
107 | ||
108 | if (ioctl(out.fd, MTIOCTOP, &t_op) < 0) | |
109 | err("%s: %s", out.name, strerror(errno)); | |
110 | return; | |
111 | } | |
112 | ||
113 | /* Read it. */ | |
114 | for (cnt = 0; cnt < out.offset; ++cnt) { | |
115 | if ((n = read(out.fd, out.db, out.dbsz)) > 0) | |
116 | continue; | |
117 | ||
118 | if (n < 0) | |
119 | err("%s: %s", out.name, strerror(errno)); | |
120 | ||
121 | /* | |
122 | * If reach EOF, fill with NUL characters; first, back up over | |
123 | * the EOF mark. Note, cnt has not yet been incremented, so | |
124 | * the EOF read does not count as a seek'd block. | |
125 | */ | |
126 | t_op.mt_op = MTBSR; | |
127 | t_op.mt_count = 1; | |
128 | if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) | |
129 | err("%s: %s", out.name, strerror(errno)); | |
130 | ||
131 | while (cnt++ < out.offset) | |
132 | if ((n = write(out.fd, out.db, out.dbsz)) != out.dbsz) | |
133 | err("%s: %s", out.name, strerror(errno)); | |
134 | break; | |
135 | } | |
136 | } |