1*cf5a6c84SAndroid Build Coastguard Worker /* dd.c - convert/copy a file
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Ashwini Kumar <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker *
6*cf5a6c84SAndroid Build Coastguard Worker * See http://opengroup.org/onlinepubs/9699919799/utilities/dd.html
7*cf5a6c84SAndroid Build Coastguard Worker *
8*cf5a6c84SAndroid Build Coastguard Worker * Deviations from posix: no conversions, no cbs=
9*cf5a6c84SAndroid Build Coastguard Worker * TODO: seek=n with unseekable output? (Read output and... write it back?)
10*cf5a6c84SAndroid Build Coastguard Worker
11*cf5a6c84SAndroid Build Coastguard Worker USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
12*cf5a6c84SAndroid Build Coastguard Worker
13*cf5a6c84SAndroid Build Coastguard Worker config DD
14*cf5a6c84SAndroid Build Coastguard Worker bool "dd"
15*cf5a6c84SAndroid Build Coastguard Worker default y
16*cf5a6c84SAndroid Build Coastguard Worker help
17*cf5a6c84SAndroid Build Coastguard Worker usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker Copy/convert blocks of data from input to output, with the following
20*cf5a6c84SAndroid Build Coastguard Worker keyword=value modifiers (and their default values):
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker if=FILE Read FILE (stdin) of=FILE Write to FILE (stdout)
23*cf5a6c84SAndroid Build Coastguard Worker bs=N Block size in bytes (512) count=N Stop after copying N blocks (all)
24*cf5a6c84SAndroid Build Coastguard Worker ibs=N Input block size (bs=) obs=N Output block size (bs=)
25*cf5a6c84SAndroid Build Coastguard Worker skip=N Skip N input blocks (0) seek=N Skip N output blocks (0)
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker Each =N value accepts the normal unit suffixes (see toybox --help).
28*cf5a6c84SAndroid Build Coastguard Worker
29*cf5a6c84SAndroid Build Coastguard Worker These modifiers take a comma separated list of potential options:
30*cf5a6c84SAndroid Build Coastguard Worker
31*cf5a6c84SAndroid Build Coastguard Worker iflag=count_bytes,skip_bytes count=N or skip=N is in bytes not blocks
32*cf5a6c84SAndroid Build Coastguard Worker oflag=seek_bytes,append seek=N is in bytes, append output to file
33*cf5a6c84SAndroid Build Coastguard Worker status=noxfer,none don't show transfer rate, no summary info
34*cf5a6c84SAndroid Build Coastguard Worker conv=
35*cf5a6c84SAndroid Build Coastguard Worker notrunc Don't truncate output noerror Continue after read errors
36*cf5a6c84SAndroid Build Coastguard Worker sync Zero pad short reads fsync Flush output to disk at end
37*cf5a6c84SAndroid Build Coastguard Worker sparse Seek past zeroed output excl Fail if output file exists
38*cf5a6c84SAndroid Build Coastguard Worker nocreat Fail if of=FILE missing
39*cf5a6c84SAndroid Build Coastguard Worker */
40*cf5a6c84SAndroid Build Coastguard Worker
41*cf5a6c84SAndroid Build Coastguard Worker #define FOR_dd
42*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
43*cf5a6c84SAndroid Build Coastguard Worker
44*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
45*cf5a6c84SAndroid Build Coastguard Worker // Display fields
46*cf5a6c84SAndroid Build Coastguard Worker int show_xfer, show_records;
47*cf5a6c84SAndroid Build Coastguard Worker unsigned long long bytes, in_full, in_part, out_full, out_part, start;
48*cf5a6c84SAndroid Build Coastguard Worker )
49*cf5a6c84SAndroid Build Coastguard Worker
50*cf5a6c84SAndroid Build Coastguard Worker struct dd_flag {
51*cf5a6c84SAndroid Build Coastguard Worker char *name;
52*cf5a6c84SAndroid Build Coastguard Worker };
53*cf5a6c84SAndroid Build Coastguard Worker
54*cf5a6c84SAndroid Build Coastguard Worker static const struct dd_flag dd_conv[] = TAGGED_ARRAY(DD_conv,
55*cf5a6c84SAndroid Build Coastguard Worker {"fsync"}, {"noerror"}, {"notrunc"}, {"sync"}, // TODO sparse excl nocreat
56*cf5a6c84SAndroid Build Coastguard Worker );
57*cf5a6c84SAndroid Build Coastguard Worker
58*cf5a6c84SAndroid Build Coastguard Worker static const struct dd_flag dd_iflag[] = TAGGED_ARRAY(DD_iflag,
59*cf5a6c84SAndroid Build Coastguard Worker {"count_bytes"}, {"skip_bytes"},
60*cf5a6c84SAndroid Build Coastguard Worker );
61*cf5a6c84SAndroid Build Coastguard Worker
62*cf5a6c84SAndroid Build Coastguard Worker static const struct dd_flag dd_oflag[] = TAGGED_ARRAY(DD_oflag,
63*cf5a6c84SAndroid Build Coastguard Worker {"seek_bytes"},
64*cf5a6c84SAndroid Build Coastguard Worker );
65*cf5a6c84SAndroid Build Coastguard Worker
status()66*cf5a6c84SAndroid Build Coastguard Worker static void status()
67*cf5a6c84SAndroid Build Coastguard Worker {
68*cf5a6c84SAndroid Build Coastguard Worker unsigned long long now = millitime()-TT.start ? : 1, bytes = TT.bytes*1000;
69*cf5a6c84SAndroid Build Coastguard Worker
70*cf5a6c84SAndroid Build Coastguard Worker if (TT.show_records)
71*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "%llu+%llu records in\n%llu+%llu records out\n",
72*cf5a6c84SAndroid Build Coastguard Worker TT.in_full, TT.in_part, TT.out_full, TT.out_part);
73*cf5a6c84SAndroid Build Coastguard Worker
74*cf5a6c84SAndroid Build Coastguard Worker if (TT.show_xfer) {
75*cf5a6c84SAndroid Build Coastguard Worker human_readable(toybuf, TT.bytes, HR_SPACE|HR_B);
76*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "%llu bytes (%s) copied, ", TT.bytes, toybuf);
77*cf5a6c84SAndroid Build Coastguard Worker bytes = (bytes>TT.bytes) ? bytes/now : TT.bytes/((now+999)/1000);
78*cf5a6c84SAndroid Build Coastguard Worker human_readable(toybuf, bytes, HR_SPACE|HR_B);
79*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "%llu.%03u s, %s/s\n", now/1000, (int)(now%1000), toybuf);
80*cf5a6c84SAndroid Build Coastguard Worker }
81*cf5a6c84SAndroid Build Coastguard Worker }
82*cf5a6c84SAndroid Build Coastguard Worker
parse_flags(char * what,char * arg,const struct dd_flag * flags,int flag_count,unsigned * result)83*cf5a6c84SAndroid Build Coastguard Worker static void parse_flags(char *what, char *arg,
84*cf5a6c84SAndroid Build Coastguard Worker const struct dd_flag* flags, int flag_count, unsigned *result)
85*cf5a6c84SAndroid Build Coastguard Worker {
86*cf5a6c84SAndroid Build Coastguard Worker char *pre = xstrdup(arg);
87*cf5a6c84SAndroid Build Coastguard Worker int i;
88*cf5a6c84SAndroid Build Coastguard Worker
89*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<flag_count; ++i)
90*cf5a6c84SAndroid Build Coastguard Worker while (comma_remove(pre, flags[i].name)) *result |= 1<<i;
91*cf5a6c84SAndroid Build Coastguard Worker if (*pre) error_exit("bad %s=%s", what, pre);
92*cf5a6c84SAndroid Build Coastguard Worker free(pre);
93*cf5a6c84SAndroid Build Coastguard Worker }
94*cf5a6c84SAndroid Build Coastguard Worker
95*cf5a6c84SAndroid Build Coastguard Worker // Multiply detecting overflow.
overmul(unsigned long long x,unsigned long long y)96*cf5a6c84SAndroid Build Coastguard Worker static unsigned long long overmul(unsigned long long x, unsigned long long y)
97*cf5a6c84SAndroid Build Coastguard Worker {
98*cf5a6c84SAndroid Build Coastguard Worker unsigned long long ll = x*y;
99*cf5a6c84SAndroid Build Coastguard Worker
100*cf5a6c84SAndroid Build Coastguard Worker if (x && y && (ll<x || ll<y)) error_exit("overflow");
101*cf5a6c84SAndroid Build Coastguard Worker
102*cf5a6c84SAndroid Build Coastguard Worker return ll;
103*cf5a6c84SAndroid Build Coastguard Worker }
104*cf5a6c84SAndroid Build Coastguard Worker
105*cf5a6c84SAndroid Build Coastguard Worker // Handle funky posix 1x2x3 syntax.
argxarg(char * arg,int cap)106*cf5a6c84SAndroid Build Coastguard Worker static unsigned long long argxarg(char *arg, int cap)
107*cf5a6c84SAndroid Build Coastguard Worker {
108*cf5a6c84SAndroid Build Coastguard Worker long long ll = 1;
109*cf5a6c84SAndroid Build Coastguard Worker char x QUIET, *s, *new;
110*cf5a6c84SAndroid Build Coastguard Worker
111*cf5a6c84SAndroid Build Coastguard Worker arg = xstrdup(arg);
112*cf5a6c84SAndroid Build Coastguard Worker for (new = s = arg;; new = s+1) {
113*cf5a6c84SAndroid Build Coastguard Worker // atolx() handles 0x hex prefixes, so skip past those looking for separator
114*cf5a6c84SAndroid Build Coastguard Worker if ((s = strchr(new+2*!strncmp(new, "0x", 2), 'x'))) {
115*cf5a6c84SAndroid Build Coastguard Worker if (s==new) break;
116*cf5a6c84SAndroid Build Coastguard Worker x = *s;
117*cf5a6c84SAndroid Build Coastguard Worker *s = 0;
118*cf5a6c84SAndroid Build Coastguard Worker }
119*cf5a6c84SAndroid Build Coastguard Worker ll = overmul(ll, atolx(new));
120*cf5a6c84SAndroid Build Coastguard Worker if (s) *s = x;
121*cf5a6c84SAndroid Build Coastguard Worker else break;
122*cf5a6c84SAndroid Build Coastguard Worker }
123*cf5a6c84SAndroid Build Coastguard Worker if (s || ll<cap || ll>(cap ? LONG_MAX : LLONG_MAX)) error_exit("bad %s", arg);
124*cf5a6c84SAndroid Build Coastguard Worker free(arg);
125*cf5a6c84SAndroid Build Coastguard Worker
126*cf5a6c84SAndroid Build Coastguard Worker return ll;
127*cf5a6c84SAndroid Build Coastguard Worker }
128*cf5a6c84SAndroid Build Coastguard Worker
129*cf5a6c84SAndroid Build Coastguard Worker
130*cf5a6c84SAndroid Build Coastguard Worker // Point 1 or 2 iovec at len bytes at buf, starting at "start" and wrapping
131*cf5a6c84SAndroid Build Coastguard Worker // around at buflen.
iovwrap(char * buf,unsigned long long buflen,unsigned long long start,unsigned long long len,struct iovec * iov)132*cf5a6c84SAndroid Build Coastguard Worker int iovwrap(char *buf, unsigned long long buflen, unsigned long long start,
133*cf5a6c84SAndroid Build Coastguard Worker unsigned long long len, struct iovec *iov)
134*cf5a6c84SAndroid Build Coastguard Worker {
135*cf5a6c84SAndroid Build Coastguard Worker iov[0].iov_base = buf + start;
136*cf5a6c84SAndroid Build Coastguard Worker iov[0].iov_len = len;
137*cf5a6c84SAndroid Build Coastguard Worker if (start+len<=buflen) return 1;
138*cf5a6c84SAndroid Build Coastguard Worker
139*cf5a6c84SAndroid Build Coastguard Worker iov[1].iov_len = len-(iov[0].iov_len = buflen-start);
140*cf5a6c84SAndroid Build Coastguard Worker iov[1].iov_base = buf;
141*cf5a6c84SAndroid Build Coastguard Worker
142*cf5a6c84SAndroid Build Coastguard Worker return 2;
143*cf5a6c84SAndroid Build Coastguard Worker }
144*cf5a6c84SAndroid Build Coastguard Worker
dd_main()145*cf5a6c84SAndroid Build Coastguard Worker void dd_main()
146*cf5a6c84SAndroid Build Coastguard Worker {
147*cf5a6c84SAndroid Build Coastguard Worker char **args, *arg, *iname = 0, *oname = 0, *buf;
148*cf5a6c84SAndroid Build Coastguard Worker unsigned long long bs = 0, seek = 0, skip = 0, ibs = 512, obs = 512,
149*cf5a6c84SAndroid Build Coastguard Worker count = ULLONG_MAX, buflen;
150*cf5a6c84SAndroid Build Coastguard Worker long long len;
151*cf5a6c84SAndroid Build Coastguard Worker struct iovec iov[2];
152*cf5a6c84SAndroid Build Coastguard Worker int opos, olen, ifd = 0, ofd = 1, trunc = O_TRUNC, ii;
153*cf5a6c84SAndroid Build Coastguard Worker unsigned conv = 0, iflag = 0, oflag = 0;
154*cf5a6c84SAndroid Build Coastguard Worker
155*cf5a6c84SAndroid Build Coastguard Worker TT.show_xfer = TT.show_records = 1;
156*cf5a6c84SAndroid Build Coastguard Worker
157*cf5a6c84SAndroid Build Coastguard Worker for (args = toys.optargs; (arg = *args); args++) {
158*cf5a6c84SAndroid Build Coastguard Worker if (strstart(&arg, "bs=")) bs = argxarg(arg, 1);
159*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "ibs=")) ibs = argxarg(arg, 1);
160*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "obs=")) obs = argxarg(arg, 1);
161*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "count=")) count = argxarg(arg, 0);
162*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "if=")) iname = arg;
163*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "of=")) oname = arg;
164*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "seek=")) seek = argxarg(arg, 0);
165*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "skip=")) skip = argxarg(arg, 0);
166*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "status=")) {
167*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(arg, "noxfer")) TT.show_xfer = 0;
168*cf5a6c84SAndroid Build Coastguard Worker else if (!strcmp(arg, "none")) TT.show_xfer = TT.show_records = 0;
169*cf5a6c84SAndroid Build Coastguard Worker else error_exit("unknown status '%s'", arg);
170*cf5a6c84SAndroid Build Coastguard Worker } else if (strstart(&arg, "conv="))
171*cf5a6c84SAndroid Build Coastguard Worker parse_flags("conv", arg, dd_conv, ARRAY_LEN(dd_conv), &conv);
172*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "iflag="))
173*cf5a6c84SAndroid Build Coastguard Worker parse_flags("iflag", arg, dd_iflag, ARRAY_LEN(dd_iflag), &iflag);
174*cf5a6c84SAndroid Build Coastguard Worker else if (strstart(&arg, "oflag="))
175*cf5a6c84SAndroid Build Coastguard Worker parse_flags("oflag", arg, dd_oflag, ARRAY_LEN(dd_oflag), &oflag);
176*cf5a6c84SAndroid Build Coastguard Worker else error_exit("bad arg %s", arg);
177*cf5a6c84SAndroid Build Coastguard Worker }
178*cf5a6c84SAndroid Build Coastguard Worker if (bs) ibs = obs = bs; // bs overrides ibs and obs regardless of position
179*cf5a6c84SAndroid Build Coastguard Worker
180*cf5a6c84SAndroid Build Coastguard Worker TT.start = millitime();
181*cf5a6c84SAndroid Build Coastguard Worker sigatexit(status);
182*cf5a6c84SAndroid Build Coastguard Worker xsignal(SIGUSR1, status);
183*cf5a6c84SAndroid Build Coastguard Worker
184*cf5a6c84SAndroid Build Coastguard Worker // If bs set, output blocks match input blocks (passing along short reads).
185*cf5a6c84SAndroid Build Coastguard Worker // Else read ibs blocks and write obs, which worst case requires ibs+obs-1.
186*cf5a6c84SAndroid Build Coastguard Worker buf = xmalloc(buflen = ibs+obs*!bs);
187*cf5a6c84SAndroid Build Coastguard Worker if (buflen<ibs || buflen<obs) error_exit("tilt");
188*cf5a6c84SAndroid Build Coastguard Worker
189*cf5a6c84SAndroid Build Coastguard Worker if (conv & _DD_conv_notrunc) trunc = 0;
190*cf5a6c84SAndroid Build Coastguard Worker if (iname) ifd = xopenro(iname);
191*cf5a6c84SAndroid Build Coastguard Worker else iname = "stdin";
192*cf5a6c84SAndroid Build Coastguard Worker if (oname) ofd = xcreate(oname, O_WRONLY|O_CREAT|(trunc*!seek),0666);
193*cf5a6c84SAndroid Build Coastguard Worker else oname = "stdout";
194*cf5a6c84SAndroid Build Coastguard Worker
195*cf5a6c84SAndroid Build Coastguard Worker // Implement skip=
196*cf5a6c84SAndroid Build Coastguard Worker if (skip) {
197*cf5a6c84SAndroid Build Coastguard Worker if (!(iflag & _DD_iflag_skip_bytes)) skip *= ibs;
198*cf5a6c84SAndroid Build Coastguard Worker if (lseek(ifd, skip, SEEK_CUR) < 0) {
199*cf5a6c84SAndroid Build Coastguard Worker for (; skip > 0; skip -= len) {
200*cf5a6c84SAndroid Build Coastguard Worker len = read(ifd, buf, minof(skip, ibs));
201*cf5a6c84SAndroid Build Coastguard Worker if (len < 0) {
202*cf5a6c84SAndroid Build Coastguard Worker perror_msg_raw(iname);
203*cf5a6c84SAndroid Build Coastguard Worker if (conv & _DD_conv_noerror) status();
204*cf5a6c84SAndroid Build Coastguard Worker else return;
205*cf5a6c84SAndroid Build Coastguard Worker } else if (!len) return xprintf("%s: Can't skip\n", iname);
206*cf5a6c84SAndroid Build Coastguard Worker }
207*cf5a6c84SAndroid Build Coastguard Worker }
208*cf5a6c84SAndroid Build Coastguard Worker }
209*cf5a6c84SAndroid Build Coastguard Worker
210*cf5a6c84SAndroid Build Coastguard Worker // Implement seek= and truncate as necessary. We handled position zero
211*cf5a6c84SAndroid Build Coastguard Worker // truncate with O_TRUNC on open, so output to /dev/null etc doesn't error.
212*cf5a6c84SAndroid Build Coastguard Worker if (!(oflag & _DD_oflag_seek_bytes)) seek *= obs;
213*cf5a6c84SAndroid Build Coastguard Worker if (seek) {
214*cf5a6c84SAndroid Build Coastguard Worker struct stat st;
215*cf5a6c84SAndroid Build Coastguard Worker
216*cf5a6c84SAndroid Build Coastguard Worker xlseek(ofd, seek, SEEK_CUR);
217*cf5a6c84SAndroid Build Coastguard Worker if (trunc && !fstat(ofd, &st) && S_ISREG(st.st_mode) && ftruncate(ofd,seek))
218*cf5a6c84SAndroid Build Coastguard Worker perror_exit("truncate");
219*cf5a6c84SAndroid Build Coastguard Worker }
220*cf5a6c84SAndroid Build Coastguard Worker
221*cf5a6c84SAndroid Build Coastguard Worker if (count!=ULLONG_MAX && !(iflag & _DD_iflag_count_bytes))
222*cf5a6c84SAndroid Build Coastguard Worker count = overmul(count, ibs);
223*cf5a6c84SAndroid Build Coastguard Worker
224*cf5a6c84SAndroid Build Coastguard Worker // output start position, output bytes available
225*cf5a6c84SAndroid Build Coastguard Worker opos = olen = 0;
226*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
227*cf5a6c84SAndroid Build Coastguard Worker // Write as many output blocks as we can. Using writev() avoids memmove()
228*cf5a6c84SAndroid Build Coastguard Worker // to realign data but is still a single atomic write.
229*cf5a6c84SAndroid Build Coastguard Worker while (olen>=obs || (olen && (bs || !count))) {
230*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
231*cf5a6c84SAndroid Build Coastguard Worker len = writev(ofd, iov, iovwrap(buf, buflen, opos, minof(obs, olen), iov));
232*cf5a6c84SAndroid Build Coastguard Worker if (len<1) {
233*cf5a6c84SAndroid Build Coastguard Worker if (errno==EINTR) continue;
234*cf5a6c84SAndroid Build Coastguard Worker perror_exit("%s: write error", oname);
235*cf5a6c84SAndroid Build Coastguard Worker }
236*cf5a6c84SAndroid Build Coastguard Worker TT.bytes += len;
237*cf5a6c84SAndroid Build Coastguard Worker olen -= len;
238*cf5a6c84SAndroid Build Coastguard Worker if ((opos += len)>=buflen) opos -= buflen;
239*cf5a6c84SAndroid Build Coastguard Worker if (len == obs) TT.out_full++;
240*cf5a6c84SAndroid Build Coastguard Worker else TT.out_part++;
241*cf5a6c84SAndroid Build Coastguard Worker }
242*cf5a6c84SAndroid Build Coastguard Worker if (!count) break;
243*cf5a6c84SAndroid Build Coastguard Worker
244*cf5a6c84SAndroid Build Coastguard Worker // Read next block of input. (There MUST be enough space, we sized buf.)
245*cf5a6c84SAndroid Build Coastguard Worker len = opos+olen;
246*cf5a6c84SAndroid Build Coastguard Worker if (len>buflen) len -= buflen;
247*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
248*cf5a6c84SAndroid Build Coastguard Worker if (2 == (ii = iovwrap(buf, buflen, len, minof(count, ibs), iov)))
249*cf5a6c84SAndroid Build Coastguard Worker memset(iov[1].iov_base, 0, iov[1].iov_len);
250*cf5a6c84SAndroid Build Coastguard Worker memset(iov[0].iov_base, 0, iov[0].iov_len);
251*cf5a6c84SAndroid Build Coastguard Worker len = readv(ifd, iov, ii);
252*cf5a6c84SAndroid Build Coastguard Worker if (len<1) {
253*cf5a6c84SAndroid Build Coastguard Worker if (errno==EINTR) continue;
254*cf5a6c84SAndroid Build Coastguard Worker if (!len) count = 0;
255*cf5a6c84SAndroid Build Coastguard Worker else {
256*cf5a6c84SAndroid Build Coastguard Worker //read error case.
257*cf5a6c84SAndroid Build Coastguard Worker perror_msg("%s: read error", iname);
258*cf5a6c84SAndroid Build Coastguard Worker if (!(conv & _DD_conv_noerror)) xexit();
259*cf5a6c84SAndroid Build Coastguard Worker
260*cf5a6c84SAndroid Build Coastguard Worker // Complain and try to seek past it
261*cf5a6c84SAndroid Build Coastguard Worker status();
262*cf5a6c84SAndroid Build Coastguard Worker lseek(ifd, ibs, SEEK_CUR);
263*cf5a6c84SAndroid Build Coastguard Worker if (conv & _DD_conv_sync) olen += ibs;
264*cf5a6c84SAndroid Build Coastguard Worker }
265*cf5a6c84SAndroid Build Coastguard Worker
266*cf5a6c84SAndroid Build Coastguard Worker continue;
267*cf5a6c84SAndroid Build Coastguard Worker }
268*cf5a6c84SAndroid Build Coastguard Worker if (len == ibs) TT.in_full++;
269*cf5a6c84SAndroid Build Coastguard Worker else TT.in_part++;
270*cf5a6c84SAndroid Build Coastguard Worker if (conv & _DD_conv_sync) len = ibs;
271*cf5a6c84SAndroid Build Coastguard Worker olen += len;
272*cf5a6c84SAndroid Build Coastguard Worker count -= minof(len, count);
273*cf5a6c84SAndroid Build Coastguard Worker }
274*cf5a6c84SAndroid Build Coastguard Worker if ((conv & _DD_conv_fsync) && fsync(ofd)) perror_exit("%s: fsync", oname);
275*cf5a6c84SAndroid Build Coastguard Worker
276*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) {
277*cf5a6c84SAndroid Build Coastguard Worker close(ifd);
278*cf5a6c84SAndroid Build Coastguard Worker close(ofd);
279*cf5a6c84SAndroid Build Coastguard Worker free(buf);
280*cf5a6c84SAndroid Build Coastguard Worker }
281*cf5a6c84SAndroid Build Coastguard Worker }
282