Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/coreutils/dd.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/coreutils/dd.c

    r1765 r2725  
    66 * Copyright (C) 2000,2001  Matt Kraai
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
    11 #include <signal.h>  /* For FEATURE_DD_SIGNAL_HANDLING */
    1211#include "libbb.h"
    1312
    1413/* This is a NOEXEC applet. Be very careful! */
    1514
     15
     16enum {
     17    ifd = STDIN_FILENO,
     18    ofd = STDOUT_FILENO,
     19};
    1620
    1721static const struct suffix_mult dd_suffixes[] = {
     
    2125    { "kD", 1000 },
    2226    { "k", 1024 },
    23     { "K", 1024 },  /* compat with coreutils dd */
     27    { "K", 1024 },  /* compat with coreutils dd */
    2428    { "MD", 1000000 },
    2529    { "M", 1048576 },
    2630    { "GD", 1000000000 },
    2731    { "G", 1073741824 },
    28     { }
     32    { "", 0 }
    2933};
    3034
    3135struct globals {
    3236    off_t out_full, out_part, in_full, in_part;
    33 };
     37#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     38    unsigned long long total_bytes;
     39    unsigned long long begin_time_us;
     40#endif
     41} FIX_ALIASING;
    3442#define G (*(struct globals*)&bb_common_bufsiz1)
    35 /* We have to zero it out because of NOEXEC */
    36 #define INIT_G() memset(&G, 0, sizeof(G))
    37 
    38 
    39 static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
     43#define INIT_G() do { \
     44    /* we have to zero it out because of NOEXEC */ \
     45    memset(&G, 0, sizeof(G)); \
     46} while (0)
     47
     48
     49static void dd_output_status(int UNUSED_PARAM cur_signal)
    4050{
     51#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     52    double seconds;
     53    unsigned long long bytes_sec;
     54    unsigned long long now_us = monotonic_us(); /* before fprintf */
     55#endif
     56
    4157    /* Deliberately using %u, not %d */
    4258    fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n"
     
    4460            G.in_full, G.in_part,
    4561            G.out_full, G.out_part);
     62
     63#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     64    fprintf(stderr, "%llu bytes (%sB) copied, ",
     65            G.total_bytes,
     66            /* show fractional digit, use suffixes */
     67            make_human_readable_str(G.total_bytes, 1, 0)
     68    );
     69    /* Corner cases:
     70     * ./busybox dd </dev/null >/dev/null
     71     * ./busybox dd bs=1M count=2000 </dev/zero >/dev/null
     72     * (echo DONE) | ./busybox dd >/dev/null
     73     * (sleep 1; echo DONE) | ./busybox dd >/dev/null
     74     */
     75    seconds = (now_us - G.begin_time_us) / 1000000.0;
     76    bytes_sec = G.total_bytes / seconds;
     77    fprintf(stderr, "%f seconds, %sB/s\n",
     78            seconds,
     79            /* show fractional digit, use suffixes */
     80            make_human_readable_str(bytes_sec, 1, 0)
     81    );
     82#endif
    4683}
    4784
    48 static ssize_t full_write_or_warn(int fd, const void *buf, size_t len,
     85static ssize_t full_write_or_warn(const void *buf, size_t len,
    4986    const char *const filename)
    5087{
    51     ssize_t n = full_write(fd, buf, len);
     88    ssize_t n = full_write(ofd, buf, len);
    5289    if (n < 0)
    5390        bb_perror_msg("writing '%s'", filename);
     
    5592}
    5693
    57 static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs,
     94static bool write_and_stats(const void *buf, size_t len, size_t obs,
    5895    const char *filename)
    5996{
    60     ssize_t n = full_write_or_warn(fd, buf, len, filename);
     97    ssize_t n = full_write_or_warn(buf, len, filename);
    6198    if (n < 0)
    6299        return 1;
    63     if (n == obs)
     100    if ((size_t)n == obs)
    64101        G.out_full++;
    65102    else if (n) /* > 0 */
    66103        G.out_part++;
     104#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     105    G.total_bytes += n;
     106#endif
    67107    return 0;
    68108}
    69109
    70110#if ENABLE_LFS
    71 #define XATOU_SFX xatoull_sfx
     111# define XATOU_SFX xatoull_sfx
    72112#else
    73 #define XATOU_SFX xatoul_sfx
    74 #endif
    75 
    76 int dd_main(int argc, char **argv);
    77 int dd_main(int argc, char **argv)
     113# define XATOU_SFX xatoul_sfx
     114#endif
     115
     116int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     117int dd_main(int argc UNUSED_PARAM, char **argv)
    78118{
    79119    enum {
    80         FLAG_SYNC    = 1 << 0,
    81         FLAG_NOERROR = 1 << 1,
    82         FLAG_NOTRUNC = 1 << 2,
    83         FLAG_TWOBUFS = 1 << 3,
    84         FLAG_COUNT   = 1 << 4,
     120        /* Must be in the same order as OP_conv_XXX! */
     121        /* (see "flags |= (1 << what)" below) */
     122        FLAG_NOTRUNC = 1 << 0,
     123        FLAG_SYNC    = 1 << 1,
     124        FLAG_NOERROR = 1 << 2,
     125        FLAG_FSYNC   = 1 << 3,
     126        /* end of conv flags */
     127        FLAG_TWOBUFS = 1 << 4,
     128        FLAG_COUNT   = 1 << 5,
    85129    };
    86130    static const char keywords[] ALIGN1 =
    87         "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0"
     131        "bs\0""count\0""seek\0""skip\0""if\0""of\0"
    88132#if ENABLE_FEATURE_DD_IBS_OBS
    89         "ibs=\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0"
     133        "ibs\0""obs\0""conv\0"
    90134#endif
    91135        ;
     136#if ENABLE_FEATURE_DD_IBS_OBS
     137    static const char conv_words[] ALIGN1 =
     138        "notrunc\0""sync\0""noerror\0""fsync\0";
     139#endif
    92140    enum {
    93         OP_bs = 1,
     141        OP_bs = 0,
    94142        OP_count,
    95143        OP_seek,
     
    101149        OP_obs,
    102150        OP_conv,
    103         OP_conv_notrunc,
     151        /* Must be in the same order as FLAG_XXX! */
     152        OP_conv_notrunc = 0,
    104153        OP_conv_sync,
    105154        OP_conv_noerror,
     155        OP_conv_fsync,
     156    /* Unimplemented conv=XXX: */
     157    //nocreat       do not create the output file
     158    //excl          fail if the output file already exists
     159    //fdatasync     physically write output file data before finishing
     160    //swab          swap every pair of input bytes
     161    //lcase         change upper case to lower case
     162    //ucase         change lower case to upper case
     163    //block         pad newline-terminated records with spaces to cbs-size
     164    //unblock       replace trailing spaces in cbs-size records with newline
     165    //ascii         from EBCDIC to ASCII
     166    //ebcdic        from ASCII to EBCDIC
     167    //ibm           from ASCII to alternate EBCDIC
    106168#endif
    107169    };
     170    int exitcode = EXIT_FAILURE;
    108171    size_t ibs = 512, obs = 512;
    109172    ssize_t n, w;
     
    112175    struct {
    113176        int flags;
    114         int ifd, ofd;
    115177        size_t oc;
    116178        off_t count;
    117179        off_t seek, skip;
    118180        const char *infile, *outfile;
    119 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING
    120         struct sigaction sigact;
    121 #endif
    122181    } Z;
    123182#define flags   (Z.flags  )
    124 #define ifd     (Z.ifd    )
    125 #define ofd     (Z.ofd    )
    126183#define oc      (Z.oc     )
    127184#define count   (Z.count  )
     
    130187#define infile  (Z.infile )
    131188#define outfile (Z.outfile)
    132 #define sigact  (Z.sigact )
    133189
    134190    memset(&Z, 0, sizeof(Z));
    135191    INIT_G();
    136 
    137 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING
    138     sigact.sa_handler = dd_output_status;
    139     sigact.sa_flags = SA_RESTART;
    140     sigemptyset(&sigact.sa_mask);
    141     sigaction(SIGUSR1, &sigact, NULL);
    142 #endif
    143 
    144     for (n = 1; n < argc; n++) {
    145         smalluint key_len;
    146         smalluint what;
    147         char *key;
     192    //fflush_all(); - is this needed because of NOEXEC?
     193
     194    for (n = 1; argv[n]; n++) {
     195        int what;
     196        char *val;
    148197        char *arg = argv[n];
    149198
    150 //XXX:FIXME: we reject plain "dd --" This would cost ~20 bytes, so..
    151 //if (*arg == '-' && *++arg == '-' && !*++arg) continue;
    152         key = strstr(arg, "=");
    153         if (key == NULL)
     199#if ENABLE_DESKTOP
     200        /* "dd --". NB: coreutils 6.9 will complain if they see
     201         * more than one of them. We wouldn't. */
     202        if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0')
     203            continue;
     204#endif
     205        val = strchr(arg, '=');
     206        if (val == NULL)
    154207            bb_show_usage();
    155         key_len = key - arg + 1;
    156         key = xstrndup(arg, key_len);
    157         what = index_in_strings(keywords, key) + 1;
    158         if (ENABLE_FEATURE_CLEAN_UP)
    159             free(key);
    160         if (what == 0)
     208        *val = '\0';
     209        what = index_in_strings(keywords, arg);
     210        if (what < 0)
    161211            bb_show_usage();
    162         arg += key_len;
    163         /* Must fit into positive ssize_t */
     212        /* *val = '='; - to preserve ps listing? */
     213        val++;
    164214#if ENABLE_FEATURE_DD_IBS_OBS
    165             if (what == OP_ibs) {
    166                 ibs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    167                 continue;
     215        if (what == OP_ibs) {
     216            /* Must fit into positive ssize_t */
     217            ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     218            /*continue;*/
     219        }
     220        if (what == OP_obs) {
     221            obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     222            /*continue;*/
     223        }
     224        if (what == OP_conv) {
     225            while (1) {
     226                /* find ',', replace them with NUL so we can use val for
     227                 * index_in_strings() without copying.
     228                 * We rely on val being non-null, else strchr would fault.
     229                 */
     230                arg = strchr(val, ',');
     231                if (arg)
     232                    *arg = '\0';
     233                what = index_in_strings(conv_words, val);
     234                if (what < 0)
     235                    bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv");
     236                flags |= (1 << what);
     237                if (!arg) /* no ',' left, so this was the last specifier */
     238                    break;
     239                /* *arg = ','; - to preserve ps listing? */
     240                val = arg + 1; /* skip this keyword and ',' */
    168241            }
    169             if (what == OP_obs) {
    170                 obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    171                 continue;
    172             }
    173             if (what == OP_conv) {
    174                 while (1) {
    175                     /* find ',', replace them with nil so we can use arg for
    176                      * index_in_strings() without copying.
    177                      * We rely on arg being non-null, else strchr would fault.
    178                      */
    179                     key = strchr(arg, ',');
    180                     if (key)
    181                         *key = '\0';
    182                     what = index_in_strings(keywords, arg) + 1;
    183                     if (what < OP_conv_notrunc)
    184                         bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv");
    185                     if (what == OP_conv_notrunc)
    186                         flags |= FLAG_NOTRUNC;
    187                     if (what == OP_conv_sync)
    188                         flags |= FLAG_SYNC;
    189                     if (what == OP_conv_noerror)
    190                         flags |= FLAG_NOERROR;
    191                     if (!key) /* no ',' left, so this was the last specifier */
    192                         break;
    193                     arg = key + 1; /* skip this keyword and ',' */
    194                 }
    195                 continue;
    196             }
     242            continue; /* we trashed 'what', can't fall through */
     243        }
    197244#endif
    198245        if (what == OP_bs) {
    199             ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
    200             continue;
     246            ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
     247            /*continue;*/
    201248        }
    202249        /* These can be large: */
    203250        if (what == OP_count) {
    204251            flags |= FLAG_COUNT;
    205             count = XATOU_SFX(arg, dd_suffixes);
    206             continue;
     252            count = XATOU_SFX(val, dd_suffixes);
     253            /*continue;*/
    207254        }
    208255        if (what == OP_seek) {
    209             seek = XATOU_SFX(arg, dd_suffixes);
    210             continue;
     256            seek = XATOU_SFX(val, dd_suffixes);
     257            /*continue;*/
    211258        }
    212259        if (what == OP_skip) {
    213             skip = XATOU_SFX(arg, dd_suffixes);
    214             continue;
     260            skip = XATOU_SFX(val, dd_suffixes);
     261            /*continue;*/
    215262        }
    216263        if (what == OP_if) {
    217             infile = arg;
    218             continue;
    219         }
    220         if (what == OP_of)
    221             outfile = arg;
    222     }
     264            infile = val;
     265            /*continue;*/
     266        }
     267        if (what == OP_of) {
     268            outfile = val;
     269            /*continue;*/
     270        }
     271    } /* end of "for (argv[n])" */
     272
    223273//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
    224274    ibuf = obuf = xmalloc(ibs);
     
    227277        obuf = xmalloc(obs);
    228278    }
     279
     280#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
     281    signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
     282#endif
     283#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
     284    G.begin_time_us = monotonic_us();
     285#endif
     286
    229287    if (infile != NULL)
    230         ifd = xopen(infile, O_RDONLY);
     288        xmove_fd(xopen(infile, O_RDONLY), ifd);
    231289    else {
    232         /* ifd = STDIN_FILENO; - it's zero and it's already there */
    233290        infile = bb_msg_standard_input;
    234291    }
     
    239296            oflag |= O_TRUNC;
    240297
    241         ofd = xopen(outfile, oflag);
     298        xmove_fd(xopen(outfile, oflag), ofd);
    242299
    243300        if (seek && !(flags & FLAG_NOTRUNC)) {
     
    245302                struct stat st;
    246303
    247                 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
    248                         S_ISDIR(st.st_mode))
     304                if (fstat(ofd, &st) < 0
     305                 || S_ISREG(st.st_mode)
     306                 || S_ISDIR(st.st_mode)
     307                ) {
    249308                    goto die_outfile;
     309                }
    250310            }
    251311        }
    252312    } else {
    253         ofd = STDOUT_FILENO;
    254313        outfile = bb_msg_standard_output;
    255314    }
     
    271330
    272331    while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
    273         if (flags & FLAG_NOERROR) /* Pre-zero the buffer if conv=noerror */
    274             memset(ibuf, 0, ibs);
    275332        n = safe_read(ifd, ibuf, ibs);
    276333        if (n == 0)
    277334            break;
    278335        if (n < 0) {
    279             if (flags & FLAG_NOERROR) {
    280                 n = ibs;
    281                 bb_perror_msg("%s", infile);
    282             } else
     336            /* "Bad block" */
     337            if (!(flags & FLAG_NOERROR))
    283338                goto die_infile;
     339            bb_simple_perror_msg(infile);
     340            /* GNU dd with conv=noerror skips over bad blocks */
     341            xlseek(ifd, ibs, SEEK_CUR);
     342            /* conv=noerror,sync writes NULs,
     343             * conv=noerror just ignores input bad blocks */
     344            n = 0;
    284345        }
    285346        if ((size_t)n == ibs)
     
    288349            G.in_part++;
    289350            if (flags & FLAG_SYNC) {
    290                 memset(ibuf + n, '\0', ibs - n);
     351                memset(ibuf + n, 0, ibs - n);
    291352                n = ibs;
    292353            }
     
    297358                size_t d = obs - oc;
    298359
    299                 if (d > n)
     360                if (d > (size_t)n)
    300361                    d = n;
    301362                memcpy(obuf + oc, tmp, d);
     
    304365                oc += d;
    305366                if (oc == obs) {
    306                     if (write_and_stats(ofd, obuf, obs, obs, outfile))
     367                    if (write_and_stats(obuf, obs, obs, outfile))
    307368                        goto out_status;
    308369                    oc = 0;
    309370                }
    310371            }
    311         } else if (write_and_stats(ofd, ibuf, n, obs, outfile))
     372        } else if (write_and_stats(ibuf, n, obs, outfile))
    312373            goto out_status;
     374
     375        if (flags & FLAG_FSYNC) {
     376            if (fsync(ofd) < 0)
     377                goto die_outfile;
     378        }
    313379    }
    314380
    315381    if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
    316         w = full_write_or_warn(ofd, obuf, oc, outfile);
     382        w = full_write_or_warn(obuf, oc, outfile);
    317383        if (w < 0) goto out_status;
    318         if (w > 0)
    319             G.out_part++;
     384        if (w > 0) G.out_part++;
    320385    }
    321386    if (close(ifd) < 0) {
    322387 die_infile:
    323         bb_perror_msg_and_die("%s", infile);
     388        bb_simple_perror_msg_and_die(infile);
    324389    }
    325390
    326391    if (close(ofd) < 0) {
    327392 die_outfile:
    328         bb_perror_msg_and_die("%s", outfile);
    329     }
     393        bb_simple_perror_msg_and_die(outfile);
     394    }
     395
     396    exitcode = EXIT_SUCCESS;
    330397 out_status:
    331398    dd_output_status(0);
    332399
    333     return EXIT_SUCCESS;
     400    return exitcode;
    334401}
Note: See TracChangeset for help on using the changeset viewer.