Patch adding support for ibs= and obs= to dd
[people/mcb30/busybox.git] / patches / dd_ibs_and_obs.diff
1 This patch adds support of ibs= and obs= to dd.
2 ----
3 Hideki IWAMOTO  h-iwamoto@kit.hi-ho.ne.jp
4
5
6 --- a/include/usage.h   29 Mar 2004 08:20:08 -0000      1.198
7 +++ b/include/usage.h   4 Apr 2004 07:15:21 -0000
8 @@ -309,13 +309,15 @@
9         "64\n"
10  
11  #define dd_trivial_usage \
12 -       "[if=FILE] [of=FILE] [bs=N] [count=N] [skip=N]\n" \
13 -       "\t  [seek=N] [conv=notrunc|noerror|sync]"
14 +       "[if=FILE] [of=FILE] [ibs=N] [obs=N] [bs=N] [count=N]\n" \
15 +       "\t  [skip=N] [seek=N] [conv=notrunc|noerror|sync]"
16  #define dd_full_usage \
17         "Copy a file, converting and formatting according to options\n\n" \
18         "\tif=FILE\t\tread from FILE instead of stdin\n" \
19         "\tof=FILE\t\twrite to FILE instead of stdout\n" \
20 -       "\tbs=N\t\tread and write N bytes at a time\n" \
21 +       "\tibs=N\t\tread N bytes at a time\n" \
22 +       "\tobs=N\t\twrite N bytes at a time\n" \
23 +       "\tbs=N\t\tforce ibs=N and obs=N\n" \
24         "\tcount=N\t\tcopy only N input blocks\n" \
25         "\tskip=N\t\tskip N input blocks\n" \
26         "\tseek=N\t\tskip N output blocks\n" \
27 @@ -323,6 +325,8 @@
28         "\tconv=noerror\tcontinue after read errors\n" \
29         "\tconv=sync\tpad blocks with zeros\n" \
30         "\n" \
31 +       "If the bs= expr operand is not specified, the input is processed and collected\n" \
32 +       "into full-sized output blocks until the end of the input is reached.\n" \
33         "Numbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),\n" \
34         "MD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)."
35  #define dd_example_usage \
36 --- a/coreutils/dd.c    30 Jan 2004 22:24:32 -0000      1.55
37 +++ b/coreutils/dd.c    4 Apr 2004 07:15:21 -0000
38 @@ -30,6 +30,10 @@
39  #include <fcntl.h>
40  #include "busybox.h"
41  
42 +#define C_NOERROR      0x0001
43 +#define C_TRUNC                0x0002
44 +#define C_SYNC         0x0004
45 +#define C_TWOBUFS      0x0008
46  
47  static const struct suffix_mult dd_suffixes[] = {
48         { "c", 1 },
49 @@ -51,13 +55,13 @@
50         size_t in_full = 0;
51         size_t in_part = 0;
52         size_t count = -1;
53 -       size_t bs = 512;
54 +       size_t ibs = 512;
55 +       size_t obs = 512;
56 +       size_t oc = 0;
57         ssize_t n;
58         off_t seek = 0;
59         off_t skip = 0;
60 -       int sync_flag = FALSE;
61 -       int noerror = FALSE;
62 -       int trunc_flag = TRUE;
63 +       unsigned int dd_flags = C_TWOBUFS | C_TRUNC;
64         int oflag;
65         int ifd;
66         int ofd;
67 @@ -65,11 +69,18 @@
68         const char *infile = NULL;
69         const char *outfile = NULL;
70         char *buf;
71 +       char *ibuf;
72 +       char *obuf;
73  
74         for (i = 1; i < argc; i++) {
75 -               if (strncmp("bs=", argv[i], 3) == 0)
76 -                       bs = bb_xparse_number(argv[i]+3, dd_suffixes);
77 -               else if (strncmp("count=", argv[i], 6) == 0)
78 +               if (strncmp("ibs=", argv[i], 4) == 0)
79 +                       ibs = bb_xparse_number(argv[i]+4, dd_suffixes);
80 +               else if (strncmp("obs=", argv[i], 4) == 0)
81 +                       obs = bb_xparse_number(argv[i]+4, dd_suffixes);
82 +               else if (strncmp("bs=", argv[i], 3) == 0) {
83 +                       ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes);
84 +                       dd_flags &= ~C_TWOBUFS;
85 +               } else if (strncmp("count=", argv[i], 6) == 0)
86                         count = bb_xparse_number(argv[i]+6, dd_suffixes);
87                 else if (strncmp("seek=", argv[i], 5) == 0)
88                         seek = bb_xparse_number(argv[i]+5, dd_suffixes);
89 @@ -83,13 +94,13 @@
90                         buf = argv[i]+5;
91                         while (1) {
92                                 if (strncmp("notrunc", buf, 7) == 0) {
93 -                                       trunc_flag = FALSE;
94 +                                       dd_flags &= ~C_TRUNC;
95                                         buf += 7;
96                                 } else if (strncmp("sync", buf, 4) == 0) {
97 -                                       sync_flag = TRUE;
98 +                                       dd_flags |= C_SYNC;
99                                         buf += 4;
100                                 } else if (strncmp("noerror", buf, 7) == 0) {
101 -                                       noerror = TRUE;
102 +                                       dd_flags |= C_NOERROR;
103                                         buf += 7;
104                                 } else {
105                                         bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5);
106 @@ -103,7 +114,12 @@
107                         bb_show_usage();
108         }
109  
110 -       buf = xmalloc(bs);
111 +       ibuf = xmalloc(ibs);
112 +
113 +       if (dd_flags & C_TWOBUFS)
114 +               obuf = xmalloc(obs);
115 +       else
116 +               obuf = ibuf;
117  
118         if (infile != NULL) {
119                 ifd = bb_xopen(infile, O_RDONLY);
120 @@ -115,7 +131,7 @@
121         if (outfile != NULL) {
122                 oflag = O_WRONLY | O_CREAT;
123  
124 -               if (!seek && trunc_flag) {
125 +               if (!seek && (dd_flags & C_TRUNC)) {
126                         oflag |= O_TRUNC;
127                 }
128  
129 @@ -123,8 +139,8 @@
130                         bb_perror_msg_and_die("%s", outfile);
131                 }
132  
133 -               if (seek && trunc_flag) {
134 -                       if (ftruncate(ofd, seek * bs) < 0) {
135 +               if (seek && (dd_flags & C_TRUNC)) {
136 +                       if (ftruncate(ofd, seek * obs) < 0) {
137                                 struct stat st;
138  
139                                 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
140 @@ -139,52 +155,88 @@
141         }
142  
143         if (skip) {
144 -               if (lseek(ifd, skip * bs, SEEK_CUR) < 0) {
145 -                       bb_perror_msg_and_die("%s", infile);
146 +               if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
147 +                       while (skip-- > 0) {
148 +                               n = safe_read(ifd, ibuf, ibs);
149 +                               if (n < 0)
150 +                                       bb_perror_msg_and_die("%s", infile);
151 +                               if (n == 0)
152 +                                       break;
153 +                       }
154                 }
155         }
156  
157         if (seek) {
158 -               if (lseek(ofd, seek * bs, SEEK_CUR) < 0) {
159 +               if (lseek(ofd, seek * obs, SEEK_CUR) < 0) {
160                         bb_perror_msg_and_die("%s", outfile);
161                 }
162         }
163  
164         while (in_full + in_part != count) {
165 -               if (noerror) {
166 +               if (dd_flags & C_NOERROR) {
167                         /* Pre-zero the buffer when doing the noerror thing */
168 -                       memset(buf, '\0', bs);
169 +                       memset(ibuf, '\0', ibs);
170 +               }
171 +
172 +               n = safe_read(ifd, ibuf, ibs);
173 +               if (n == 0) {
174 +                       break;
175                 }
176 -               n = safe_read(ifd, buf, bs);
177                 if (n < 0) {
178 -                       if (noerror) {
179 -                               n = bs;
180 +                       if (dd_flags & C_NOERROR) {
181 +                               n = ibs;
182                                 bb_perror_msg("%s", infile);
183                         } else {
184                                 bb_perror_msg_and_die("%s", infile);
185                         }
186                 }
187 -               if (n == 0) {
188 -                       break;
189 -               }
190 -               if (n == bs) {
191 +               if (n == ibs) {
192                         in_full++;
193                 } else {
194                         in_part++;
195 +                       if (dd_flags & C_SYNC) {
196 +                               memset(ibuf + n, '\0', ibs - n);
197 +                               n = ibs;
198 +                       }
199                 }
200 -               if (sync_flag) {
201 -                       memset(buf + n, '\0', bs - n);
202 -                       n = bs;
203 +
204 +               if (dd_flags & C_TWOBUFS) {
205 +                       size_t d;
206 +                       char *tmp = ibuf;
207 +
208 +                       while (n) {
209 +                               d = obs - oc;
210 +                               if (d > n)
211 +                                       d = n;
212 +                               memcpy(obuf + oc, tmp, d);
213 +                               n -= d;
214 +                               tmp += d;
215 +                               oc += d;
216 +                               if (oc == obs) {
217 +                                       if (bb_full_write(ofd, obuf, obs) < 0) {
218 +                                               bb_perror_msg_and_die("%s", outfile);
219 +                                       }
220 +                                       out_full++;
221 +                                       oc = 0;
222 +                               }
223 +                       }
224 +               } else {
225 +                       if (bb_full_write(ofd, ibuf, n) < 0) {
226 +                               bb_perror_msg_and_die("%s", outfile);
227 +                       }
228 +                       if (n == ibs) {
229 +                               out_full++;
230 +                       } else {
231 +                               out_part++;
232 +                       }
233                 }
234 -               n = bb_full_write(ofd, buf, n);
235 -               if (n < 0) {
236 +       }
237 +
238 +       if (oc) {
239 +               if (bb_full_write(ofd, obuf, oc) < 0) {
240                         bb_perror_msg_and_die("%s", outfile);
241                 }
242 -               if (n == bs) {
243 -                       out_full++;
244 -               } else {
245 -                       out_part++;
246 -               }
247 +               out_part++;
248         }
249  
250         if (close (ifd) < 0) {
251
252