Introduction
Introduction Statistics Contact Development Disclaimer Help
dd.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
dd.c (4895B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <ctype.h>
3 #include <fcntl.h>
4 #include <inttypes.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 #include "util.h"
10
11 static off_t ifull, ofull, ipart, opart;
12
13 static void
14 usage(void)
15 {
16 eprintf("usage: %s [operand...]\n", argv0);
17 }
18
19 static size_t
20 parsesize(char *expr)
21 {
22 char *s = expr;
23 size_t n = 1;
24
25 for (;;) {
26 n *= strtoumax(s, &s, 10);
27 switch (*s) {
28 case 'k': n <<= 10; s++; break;
29 case 'b': n <<= 9; s++; break;
30 }
31 if (*s != 'x' || !s[1])
32 break;
33 s++;
34 }
35 if (*s || n == 0)
36 eprintf("invalid block size expression '%s'\n", expr);
37
38 return n;
39 }
40
41 static void
42 bswap(unsigned char *buf, size_t len)
43 {
44 int c;
45
46 for (len &= ~1; len > 0; buf += 2, len -= 2) {
47 c = buf[0];
48 buf[0] = buf[1];
49 buf[1] = c;
50 }
51 }
52
53 static void
54 lcase(unsigned char *buf, size_t len)
55 {
56 for (; len > 0; buf++, len--)
57 buf[0] = tolower(buf[0]);
58 }
59
60 static void
61 ucase(unsigned char *buf, size_t len)
62 {
63 for (; len > 0; buf++, len--)
64 buf[0] = toupper(buf[0]);
65 }
66
67 static void
68 summary(void)
69 {
70 fprintf(stderr, "%"PRIdMAX"+%"PRIdMAX" records in\n", (intmax_t)…
71 fprintf(stderr, "%"PRIdMAX"+%"PRIdMAX" records out\n", (intmax_t…
72 }
73
74 int
75 main(int argc, char *argv[])
76 {
77 enum {
78 LCASE = 1 << 0,
79 UCASE = 1 << 1,
80 SWAB = 1 << 2,
81 NOERROR = 1 << 3,
82 NOTRUNC = 1 << 4,
83 SYNC = 1 << 5,
84 } conv = 0;
85 char *arg, *val, *end;
86 const char *iname = "-", *oname = "-";
87 int ifd = 0, ofd = 1, eof = 0;
88 size_t len, bs = 0, ibs = 512, obs = 512, ipos = 0, opos = 0;
89 off_t skip = 0, seek = 0, count = -1;
90 ssize_t ret;
91 unsigned char *buf;
92
93 argv0 = argc ? (argc--, *argv++) : "dd";
94 for (; argc > 0; argc--, argv++) {
95 arg = *argv;
96 val = strchr(arg, '=');
97 if (!val)
98 usage();
99 *val++ = '\0';
100 if (strcmp(arg, "if") == 0) {
101 iname = val;
102 } else if (strcmp(arg, "of") == 0) {
103 oname = val;
104 } else if (strcmp(arg, "ibs") == 0) {
105 ibs = parsesize(val);
106 } else if (strcmp(arg, "obs") == 0) {
107 obs = parsesize(val);
108 } else if (strcmp(arg, "bs") == 0) {
109 bs = parsesize(val);
110 } else if (strcmp(arg, "skip") == 0) {
111 skip = estrtonum(val, 0, LLONG_MAX);
112 } else if (strcmp(arg, "seek") == 0) {
113 seek = estrtonum(val, 0, LLONG_MAX);
114 } else if (strcmp(arg, "count") == 0) {
115 count = estrtonum(val, 0, LLONG_MAX);
116 } else if (strcmp(arg, "conv") == 0) {
117 do {
118 end = strchr(val, ',');
119 if (end)
120 *end++ = '\0';
121 if (strcmp(val, "lcase") == 0)
122 conv |= LCASE;
123 else if (strcmp(val, "ucase") == 0)
124 conv |= UCASE;
125 else if (strcmp(val, "swab") == 0)
126 conv |= SWAB;
127 else if (strcmp(val, "noerror") == 0)
128 conv |= NOERROR;
129 else if (strcmp(val, "notrunc") == 0)
130 conv |= NOTRUNC;
131 else if (strcmp(val, "sync") == 0)
132 conv |= SYNC;
133 else
134 eprintf("unknown conv flag '%s'\…
135 val = end;
136 } while (val);
137 } else {
138 weprintf("unknown operand '%s'\n", arg);
139 usage();
140 }
141 }
142
143 if (bs)
144 ibs = obs = bs;
145 if (strcmp(iname, "-") != 0) {
146 ifd = open(iname, O_RDONLY);
147 if (ifd < 0)
148 eprintf("open %s:", iname);
149 }
150 if (strcmp(oname, "-") != 0) {
151 ofd = open(oname, O_WRONLY | O_CREAT | (conv & NOTRUNC |…
152 if (ofd < 0)
153 eprintf("open %s:", oname);
154 }
155
156 len = MAX(ibs, obs) + ibs;
157 buf = emalloc(len);
158 if (skip && lseek(ifd, skip * ibs, SEEK_SET) < 0) {
159 while (skip--) {
160 ret = read(ifd, buf, ibs);
161 if (ret < 0)
162 eprintf("read:");
163 if (ret == 0) {
164 eof = 1;
165 break;
166 }
167 }
168 }
169 if (seek) {
170 if (!(conv & NOTRUNC) && ftruncate(ofd, seek * ibs) != 0)
171 eprintf("ftruncate:");
172 if (lseek(ofd, seek * ibs, SEEK_SET) < 0)
173 eprintf("lseek:");
174 /* XXX: handle non-seekable files */
175 }
176 while (!eof) {
177 while (ipos - opos < obs) {
178 if (ifull + ipart == count) {
179 eof = 1;
180 break;
181 }
182 ret = read(ifd, buf + ipos, ibs);
183 if (ret == 0) {
184 eof = 1;
185 break;
186 }
187 if (ret < 0) {
188 weprintf("read:");
189 if (!(conv & NOERROR))
190 return 1;
191 summary();
192 if (!(conv & SYNC))
193 continue;
194 ret = 0;
195 }
196 if (ret < ibs) {
197 ipart++;
198 if (conv & SYNC) {
199 memset(buf + ipos + ret, 0, ibs …
200 ret = ibs;
201 }
202 } else {
203 ifull++;
204 }
205 if (conv & SWAB)
206 bswap(buf + ipos, ret);
207 if (conv & LCASE)
208 lcase(buf + ipos, ret);
209 if (conv & UCASE)
210 ucase(buf + ipos, ret);
211 ipos += ret;
212 if (bs && !(conv & (SWAB | LCASE | UCASE)))
213 break;
214 }
215 if (ipos == opos)
216 break;
217 do {
218 ret = write(ofd, buf + opos, MIN(obs, ipos - opo…
219 if (ret < 0)
220 eprintf("write:");
221 if (ret == 0)
222 eprintf("write returned 0\n");
223 if (ret < obs)
224 opart++;
225 else
226 ofull++;
227 opos += ret;
228 } while (ipos - opos >= (eof ? 1 : obs));
229 if (opos < ipos)
230 memmove(buf, buf + opos, ipos - opos);
231 ipos -= opos;
232 opos = 0;
233 }
234 summary();
235
236 return 0;
237 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.