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

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 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.