source: MondoRescue/branches/stable/mindi-busybox/coreutils/dd.c@ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 18 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 5.0 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini dd implementation for busybox
4 *
5 *
6 * Copyright (C) 2000,2001 Matt Kraai
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */
10
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <string.h>
17#include <fcntl.h>
18#include <signal.h> // For FEATURE_DD_SIGNAL_HANDLING
19#include "busybox.h"
20
21static const struct suffix_mult dd_suffixes[] = {
22 { "c", 1 },
23 { "w", 2 },
24 { "b", 512 },
25 { "kD", 1000 },
26 { "k", 1024 },
27 { "MD", 1000000 },
28 { "M", 1048576 },
29 { "GD", 1000000000 },
30 { "G", 1073741824 },
31 { NULL, 0 }
32};
33
34static size_t out_full;
35static size_t out_part;
36static size_t in_full;
37static size_t in_part;
38
39static void dd_output_status(int cur_signal)
40{
41 fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
42 (long)in_full, (long)in_part,
43 (long)out_full, (long)out_part);
44}
45
46int dd_main(int argc, char **argv)
47{
48 size_t count = -1, oc = 0, ibs = 512, obs = 512;
49 ssize_t n;
50 off_t seek = 0, skip = 0;
51 int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0,
52 oflag, ifd, ofd, i;
53 const char *infile = NULL, *outfile = NULL;
54 char *ibuf, *obuf;
55
56 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING)
57 {
58 struct sigaction sa;
59
60 memset(&sa, 0, sizeof(sa));
61 sa.sa_handler = dd_output_status;
62 sa.sa_flags = SA_RESTART;
63 sigemptyset(&sa.sa_mask);
64 sigaction(SIGUSR1, &sa, 0);
65 }
66
67 for (i = 1; i < argc; i++) {
68 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) {
69 ibs = bb_xparse_number(argv[i]+4, dd_suffixes);
70 twobufs_flag++;
71 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) {
72 obs = bb_xparse_number(argv[i]+4, dd_suffixes);
73 twobufs_flag++;
74 } else if (!strncmp("bs=", argv[i], 3)) {
75 ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes);
76 } else if (!strncmp("count=", argv[i], 6))
77 count = bb_xparse_number(argv[i]+6, dd_suffixes);
78 else if (!strncmp("seek=", argv[i], 5))
79 seek = bb_xparse_number(argv[i]+5, dd_suffixes);
80 else if (!strncmp("skip=", argv[i], 5))
81 skip = bb_xparse_number(argv[i]+5, dd_suffixes);
82 else if (!strncmp("if=", argv[i], 3))
83 infile = argv[i]+3;
84 else if (!strncmp("of=", argv[i], 3))
85 outfile = argv[i]+3;
86 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) {
87 ibuf = argv[i]+5;
88 while (1) {
89 if (!strncmp("notrunc", ibuf, 7)) {
90 trunc_flag = FALSE;
91 ibuf += 7;
92 } else if (!strncmp("sync", ibuf, 4)) {
93 sync_flag = TRUE;
94 ibuf += 4;
95 } else if (!strncmp("noerror", ibuf, 7)) {
96 noerror = TRUE;
97 ibuf += 7;
98 } else {
99 bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv");
100 }
101 if (ibuf[0] == '\0') break;
102 if (ibuf[0] == ',') ibuf++;
103 }
104 } else
105 bb_show_usage();
106 }
107 ibuf = xmalloc(ibs);
108
109 if (twobufs_flag) obuf = xmalloc(obs);
110 else obuf = ibuf;
111
112 if (infile != NULL) {
113 ifd = bb_xopen(infile, O_RDONLY);
114 } else {
115 ifd = STDIN_FILENO;
116 infile = bb_msg_standard_input;
117 }
118
119 if (outfile != NULL) {
120 oflag = O_WRONLY | O_CREAT;
121
122 if (!seek && trunc_flag) {
123 oflag |= O_TRUNC;
124 }
125
126 ofd = bb_xopen3(outfile, oflag, 0666);
127
128 if (seek && trunc_flag) {
129 if (ftruncate(ofd, seek * obs) < 0) {
130 struct stat st;
131
132 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
133 S_ISDIR (st.st_mode)) {
134 bb_perror_msg_and_die("%s", outfile);
135 }
136 }
137 }
138 } else {
139 ofd = STDOUT_FILENO;
140 outfile = bb_msg_standard_output;
141 }
142
143 if (skip) {
144 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
145 while (skip-- > 0) {
146 n = safe_read(ifd, ibuf, ibs);
147 if (n < 0)
148 bb_perror_msg_and_die("%s", infile);
149 if (n == 0)
150 break;
151 }
152 }
153 }
154
155 if (seek) {
156 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) {
157 bb_perror_msg_and_die("%s", outfile);
158 }
159 }
160
161 while (in_full + in_part != count) {
162 if (noerror) {
163 /* Pre-zero the buffer when doing the noerror thing */
164 memset(ibuf, '\0', ibs);
165 }
166
167 n = safe_read(ifd, ibuf, ibs);
168 if (n == 0) {
169 break;
170 }
171 if (n < 0) {
172 if (noerror) {
173 n = ibs;
174 bb_perror_msg("%s", infile);
175 } else {
176 bb_perror_msg_and_die("%s", infile);
177 }
178 }
179 if ((size_t)n == ibs) {
180 in_full++;
181 } else {
182 in_part++;
183 if (sync_flag) {
184 memset(ibuf + n, '\0', ibs - n);
185 n = ibs;
186 }
187 }
188 if (twobufs_flag) {
189 char *tmp = ibuf;
190 while (n) {
191 size_t d = obs - oc;
192
193 if (d > n) d = n;
194 memcpy(obuf + oc, tmp, d);
195 n -= d;
196 tmp += d;
197 oc += d;
198 if (oc == obs) {
199 if (bb_full_write(ofd, obuf, obs) < 0) {
200 bb_perror_msg_and_die("%s", outfile);
201 }
202 out_full++;
203 oc = 0;
204 }
205 }
206 } else {
207 if ((n = bb_full_write(ofd, ibuf, n)) < 0) {
208 bb_perror_msg_and_die("%s", outfile);
209 }
210 if (n == ibs) out_full++;
211 else out_part++;
212 }
213 }
214
215 if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
216 if (bb_full_write(ofd, obuf, oc) < 0) {
217 bb_perror_msg_and_die("%s", outfile);
218 }
219 out_part++;
220 }
221 if (close (ifd) < 0) {
222 bb_perror_msg_and_die("%s", infile);
223 }
224
225 if (close (ofd) < 0) {
226 bb_perror_msg_and_die("%s", outfile);
227 }
228
229 dd_output_status(0);
230
231 return EXIT_SUCCESS;
232}
Note: See TracBrowser for help on using the repository browser.