Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/coreutils/dd.c


Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

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

    r821 r1765  
    99 */
    1010
    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"
     11#include <signal.h>  /* For FEATURE_DD_SIGNAL_HANDLING */
     12#include "libbb.h"
     13
     14/* This is a NOEXEC applet. Be very careful! */
     15
    2016
    2117static const struct suffix_mult dd_suffixes[] = {
     
    2521    { "kD", 1000 },
    2622    { "k", 1024 },
     23    { "K", 1024 },  /* compat with coreutils dd */
    2724    { "MD", 1000000 },
    2825    { "M", 1048576 },
    2926    { "GD", 1000000000 },
    3027    { "G", 1073741824 },
    31     { NULL, 0 }
     28    { }
    3229};
    3330
    34 static size_t out_full;
    35 static size_t out_part;
    36 static size_t in_full;
    37 static size_t in_part;
    38 
    39 static void dd_output_status(int cur_signal)
     31struct globals {
     32    off_t out_full, out_part, in_full, in_part;
     33};
     34#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
     39static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
    4040{
    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);
     41    /* Deliberately using %u, not %d */
     42    fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n"
     43            "%"OFF_FMT"u+%"OFF_FMT"u records out\n",
     44            G.in_full, G.in_part,
     45            G.out_full, G.out_part);
    4446}
    4547
     48static ssize_t full_write_or_warn(int fd, const void *buf, size_t len,
     49    const char *const filename)
     50{
     51    ssize_t n = full_write(fd, buf, len);
     52    if (n < 0)
     53        bb_perror_msg("writing '%s'", filename);
     54    return n;
     55}
     56
     57static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs,
     58    const char *filename)
     59{
     60    ssize_t n = full_write_or_warn(fd, buf, len, filename);
     61    if (n < 0)
     62        return 1;
     63    if (n == obs)
     64        G.out_full++;
     65    else if (n) /* > 0 */
     66        G.out_part++;
     67    return 0;
     68}
     69
     70#if ENABLE_LFS
     71#define XATOU_SFX xatoull_sfx
     72#else
     73#define XATOU_SFX xatoul_sfx
     74#endif
     75
     76int dd_main(int argc, char **argv);
    4677int dd_main(int argc, char **argv)
    4778{
    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;
     79    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,
     85    };
     86    static const char keywords[] ALIGN1 =
     87        "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0"
     88#if ENABLE_FEATURE_DD_IBS_OBS
     89        "ibs=\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0"
     90#endif
     91        ;
     92    enum {
     93        OP_bs = 1,
     94        OP_count,
     95        OP_seek,
     96        OP_skip,
     97        OP_if,
     98        OP_of,
     99#if ENABLE_FEATURE_DD_IBS_OBS
     100        OP_ibs,
     101        OP_obs,
     102        OP_conv,
     103        OP_conv_notrunc,
     104        OP_conv_sync,
     105        OP_conv_noerror,
     106#endif
     107    };
     108    size_t ibs = 512, obs = 512;
     109    ssize_t n, w;
    54110    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");
     111    /* And these are all zeroed at once! */
     112    struct {
     113        int flags;
     114        int ifd, ofd;
     115        size_t oc;
     116        off_t count;
     117        off_t seek, skip;
     118        const char *infile, *outfile;
     119#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
     120        struct sigaction sigact;
     121#endif
     122    } Z;
     123#define flags   (Z.flags  )
     124#define ifd     (Z.ifd    )
     125#define ofd     (Z.ofd    )
     126#define oc      (Z.oc     )
     127#define count   (Z.count  )
     128#define seek    (Z.seek   )
     129#define skip    (Z.skip   )
     130#define infile  (Z.infile )
     131#define outfile (Z.outfile)
     132#define sigact  (Z.sigact )
     133
     134    memset(&Z, 0, sizeof(Z));
     135    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;
     148        char *arg = argv[n];
     149
     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)
     154            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)
     161            bb_show_usage();
     162        arg += key_len;
     163        /* Must fit into positive ssize_t */
     164#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;
     168            }
     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 ',' */
    100194                }
    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;
     195                continue;
     196            }
     197#endif
     198        if (what == OP_bs) {
     199            ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes);
     200            continue;
     201        }
     202        /* These can be large: */
     203        if (what == OP_count) {
     204            flags |= FLAG_COUNT;
     205            count = XATOU_SFX(arg, dd_suffixes);
     206            continue;
     207        }
     208        if (what == OP_seek) {
     209            seek = XATOU_SFX(arg, dd_suffixes);
     210            continue;
     211        }
     212        if (what == OP_skip) {
     213            skip = XATOU_SFX(arg, dd_suffixes);
     214            continue;
     215        }
     216        if (what == OP_if) {
     217            infile = arg;
     218            continue;
     219        }
     220        if (what == OP_of)
     221            outfile = arg;
     222    }
     223//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
     224    ibuf = obuf = xmalloc(ibs);
     225    if (ibs != obs) {
     226        flags |= FLAG_TWOBUFS;
     227        obuf = xmalloc(obs);
     228    }
     229    if (infile != NULL)
     230        ifd = xopen(infile, O_RDONLY);
     231    else {
     232        /* ifd = STDIN_FILENO; - it's zero and it's already there */
    116233        infile = bb_msg_standard_input;
    117234    }
    118 
    119235    if (outfile != NULL) {
    120         oflag = O_WRONLY | O_CREAT;
    121 
    122         if (!seek && trunc_flag) {
     236        int oflag = O_WRONLY | O_CREAT;
     237
     238        if (!seek && !(flags & FLAG_NOTRUNC))
    123239            oflag |= O_TRUNC;
    124         }
    125 
    126         ofd = bb_xopen3(outfile, oflag, 0666);
    127 
    128         if (seek && trunc_flag) {
     240
     241        ofd = xopen(outfile, oflag);
     242
     243        if (seek && !(flags & FLAG_NOTRUNC)) {
    129244            if (ftruncate(ofd, seek * obs) < 0) {
    130245                struct stat st;
    131246
    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                 }
     247                if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) ||
     248                        S_ISDIR(st.st_mode))
     249                    goto die_outfile;
    136250            }
    137251        }
     
    140254        outfile = bb_msg_standard_output;
    141255    }
    142 
    143256    if (skip) {
    144257        if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
     
    146259                n = safe_read(ifd, ibuf, ibs);
    147260                if (n < 0)
    148                     bb_perror_msg_and_die("%s", infile);
     261                    goto die_infile;
    149262                if (n == 0)
    150263                    break;
     
    152265        }
    153266    }
    154 
    155267    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 
     268        if (lseek(ofd, seek * obs, SEEK_CUR) < 0)
     269            goto die_outfile;
     270    }
     271
     272    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);
    167275        n = safe_read(ifd, ibuf, ibs);
    168         if (n == 0) {
     276        if (n == 0)
    169277            break;
    170         }
    171278        if (n < 0) {
    172             if (noerror) {
     279            if (flags & FLAG_NOERROR) {
    173280                n = ibs;
    174281                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) {
     282            } else
     283                goto die_infile;
     284        }
     285        if ((size_t)n == ibs)
     286            G.in_full++;
     287        else {
     288            G.in_part++;
     289            if (flags & FLAG_SYNC) {
    184290                memset(ibuf + n, '\0', ibs - n);
    185291                n = ibs;
    186292            }
    187293        }
    188         if (twobufs_flag) {
     294        if (flags & FLAG_TWOBUFS) {
    189295            char *tmp = ibuf;
    190296            while (n) {
    191297                size_t d = obs - oc;
    192298
    193                 if (d > n) d = n;
     299                if (d > n)
     300                    d = n;
    194301                memcpy(obuf + oc, tmp, d);
    195302                n -= d;
     
    197304                oc += d;
    198305                if (oc == obs) {
    199                     if (bb_full_write(ofd, obuf, obs) < 0) {
    200                         bb_perror_msg_and_die("%s", outfile);
    201                     }
    202                     out_full++;
     306                    if (write_and_stats(ofd, obuf, obs, obs, outfile))
     307                        goto out_status;
    203308                    oc = 0;
    204309                }
    205310            }
    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    
     311        } else if (write_and_stats(ofd, ibuf, n, obs, outfile))
     312            goto out_status;
     313    }
     314
    215315    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) {
     316        w = full_write_or_warn(ofd, obuf, oc, outfile);
     317        if (w < 0) goto out_status;
     318        if (w > 0)
     319            G.out_part++;
     320    }
     321    if (close(ifd) < 0) {
     322 die_infile:
    222323        bb_perror_msg_and_die("%s", infile);
    223324    }
    224325
    225     if (close (ofd) < 0) {
     326    if (close(ofd) < 0) {
     327 die_outfile:
    226328        bb_perror_msg_and_die("%s", outfile);
    227329    }
    228 
     330 out_status:
    229331    dd_output_status(0);
    230332
Note: See TracChangeset for help on using the changeset viewer.