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