busybox/coreutils/od.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * od implementation for busybox
   4 * Based on code from util-linux v 2.11l
   5 *
   6 * Copyright (c) 1990
   7 * The Regents of the University of California.  All rights reserved.
   8 *
   9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  10 *
  11 * Original copyright notice is retained at the end of this file.
  12 */
  13//config:config OD
  14//config:       bool "od (11 kb)"
  15//config:       default y
  16//config:       help
  17//config:       od is used to dump binary files in octal and other formats.
  18
  19//applet:IF_OD(APPLET(od, BB_DIR_USR_BIN, BB_SUID_DROP))
  20
  21//kbuild:lib-$(CONFIG_OD) += od.o
  22
  23//usage:#if !ENABLE_DESKTOP
  24//usage:#define od_trivial_usage
  25//usage:       "[-aBbcDdeFfHhIiLlOovXx] [FILE]"
  26//usage:#define od_full_usage "\n\n"
  27//usage:       "Print FILE (or stdin) unambiguously, as octal bytes by default"
  28//usage:#endif
  29
  30#include "libbb.h"
  31#if ENABLE_DESKTOP
  32/* This one provides -t (busybox's own build script needs it) */
  33#include "od_bloaty.c"
  34#else
  35
  36#include "dump.h"
  37
  38static void
  39odoffset(dumper_t *dumper, int argc, char ***argvp)
  40{
  41        char *num, *p;
  42        int base;
  43        char *end;
  44
  45        /*
  46         * The offset syntax of od(1) was genuinely bizarre.  First, if
  47         * it started with a plus it had to be an offset.  Otherwise, if
  48         * there were at least two arguments, a number or lower-case 'x'
  49         * followed by a number makes it an offset.  By default it was
  50         * octal; if it started with 'x' or '0x' it was hex.  If it ended
  51         * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
  52         * multiplied the number by 512 or 1024 byte units.  There was
  53         * no way to assign a block count to a hex offset.
  54         *
  55         * We assumes it's a file if the offset is bad.
  56         */
  57        p = **argvp;
  58
  59        if (!p) {
  60                /* hey someone is probably piping to us ... */
  61                return;
  62        }
  63
  64        if ((*p != '+')
  65                && (argc < 2
  66                        || (!isdigit(p[0])
  67                                && ((p[0] != 'x') || !isxdigit(p[1])))))
  68                return;
  69
  70        base = 0;
  71        /*
  72         * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
  73         * set base.
  74         */
  75        if (p[0] == '+')
  76                ++p;
  77        if (p[0] == 'x' && isxdigit(p[1])) {
  78                ++p;
  79                base = 16;
  80        } else if (p[0] == '0' && p[1] == 'x') {
  81                p += 2;
  82                base = 16;
  83        }
  84
  85        /* skip over the number */
  86        if (base == 16)
  87                for (num = p; isxdigit(*p); ++p)
  88                        continue;
  89        else
  90                for (num = p; isdigit(*p); ++p)
  91                        continue;
  92
  93        /* check for no number */
  94        if (num == p)
  95                return;
  96
  97        /* if terminates with a '.', base is decimal */
  98        if (*p == '.') {
  99                if (base)
 100                        return;
 101                base = 10;
 102        }
 103
 104        dumper->dump_skip = strtol(num, &end, base ? base : 8);
 105
 106        /* if end isn't the same as p, we got a non-octal digit */
 107        if (end != p)
 108                dumper->dump_skip = 0;
 109        else {
 110                if (*p) {
 111                        if (*p == 'b') {
 112                                dumper->dump_skip *= 512;
 113                                ++p;
 114                        } else if (*p == 'B') {
 115                                dumper->dump_skip *= 1024;
 116                                ++p;
 117                        }
 118                }
 119                if (*p)
 120                        dumper->dump_skip = 0;
 121                else {
 122                        ++*argvp;
 123                        /*
 124                         * If the offset uses a non-octal base, the base of
 125                         * the offset is changed as well.  This isn't pretty,
 126                         * but it's easy.
 127                         */
 128#define TYPE_OFFSET 7
 129                        {
 130                                char x_or_d;
 131                                if (base == 16) {
 132                                        x_or_d = 'x';
 133                                        goto DO_X_OR_D;
 134                                }
 135                                if (base == 10) {
 136                                        x_or_d = 'd';
 137 DO_X_OR_D:
 138                                        dumper->fshead->nextfu->fmt[TYPE_OFFSET]
 139                                                = dumper->fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
 140                                                = x_or_d;
 141                                }
 142                        }
 143                }
 144        }
 145}
 146
 147static const char *const add_strings[] = {
 148        "16/1 \"%3_u \" \"\\n\"",              /* a */
 149        "8/2 \" %06o \" \"\\n\"",              /* B, o */
 150        "16/1 \"%03o \" \"\\n\"",              /* b */
 151        "16/1 \"%3_c \" \"\\n\"",              /* c */
 152        "8/2 \"  %05u \" \"\\n\"",             /* d */
 153        "4/4 \"     %010u \" \"\\n\"",         /* D */
 154        "2/8 \"          %21.14e \" \"\\n\"",  /* e (undocumented in od), F */
 155        "4/4 \" %14.7e \" \"\\n\"",            /* f */
 156        "4/4 \"       %08x \" \"\\n\"",        /* H, X */
 157        "8/2 \"   %04x \" \"\\n\"",            /* h, x */
 158        "4/4 \"    %11d \" \"\\n\"",           /* I, L, l */
 159        "8/2 \" %6d \" \"\\n\"",               /* i */
 160        "4/4 \"    %011o \" \"\\n\"",          /* O */
 161};
 162
 163static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
 164
 165static const char od_o2si[] ALIGN1 = {
 166        0, 1, 2, 3, 5,
 167        4, 6, 6, 7, 8,
 168        9, 0xa, 0xb, 0xa, 0xa,
 169        0xb, 1, 8, 9,
 170};
 171
 172int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 173int od_main(int argc, char **argv)
 174{
 175        int ch;
 176        int first = 1;
 177        char *p;
 178        dumper_t *dumper = alloc_dumper();
 179
 180        while ((ch = getopt(argc, argv, od_opts)) > 0) {
 181                if (ch == 'v') {
 182                        dumper->dump_vflag = ALL;
 183                } else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
 184                        if (first) {
 185                                first = 0;
 186                                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 187                                bb_dump_add(dumper, "\"%07.7_ao  \"");
 188                        } else {
 189                                bb_dump_add(dumper, "\"         \"");
 190                        }
 191                        bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]);
 192                } else {  /* P, p, s, w, or other unhandled */
 193                        bb_show_usage();
 194                }
 195        }
 196        if (!dumper->fshead) {
 197                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 198                bb_dump_add(dumper, "\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
 199        }
 200
 201        argc -= optind;
 202        argv += optind;
 203
 204        odoffset(dumper, argc, &argv);
 205
 206        return bb_dump_dump(dumper, argv);
 207}
 208#endif /* ENABLE_DESKTOP */
 209
 210/*-
 211 * Copyright (c) 1990 The Regents of the University of California.
 212 * All rights reserved.
 213 *
 214 * Redistribution and use in source and binary forms, with or without
 215 * modification, are permitted provided that the following conditions
 216 * are met:
 217 * 1. Redistributions of source code must retain the above copyright
 218 *    notice, this list of conditions and the following disclaimer.
 219 * 2. Redistributions in binary form must reproduce the above copyright
 220 *    notice, this list of conditions and the following disclaimer in the
 221 *    documentation and/or other materials provided with the distribution.
 222 * 3. Neither the name of the University nor the names of its contributors
 223 *    may be used to endorse or promote products derived from this software
 224 *    without specific prior written permission.
 225 *
 226 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
 227 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 228 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 229 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 230 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 231 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 232 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 233 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 234 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 235 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 236 * SUCH DAMAGE.
 237 */
 238