xref: /aosp_15_r20/external/toybox/toys/posix/dd.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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