prettyness police
[unix-history] / usr / src / bin / dd / position.c
CommitLineData
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 13static 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 */
35void
36pos_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
89void
90pos_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}