busybox/util-linux/hexdump.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * hexdump implementation for busybox
   4 * Based on code from util-linux v 2.11l
   5 *
   6 * Copyright (c) 1989
   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//config:config HEXDUMP
  12//config:       bool "hexdump (8.6 kb)"
  13//config:       default y
  14//config:       help
  15//config:       The hexdump utility is used to display binary data in a readable
  16//config:       way that is comparable to the output from most hex editors.
  17//config:
  18//config:config HD
  19//config:       bool "hd (7.8 kb)"
  20//config:       default y
  21//config:       help
  22//config:       hd is an alias to hexdump -C.
  23
  24//applet:IF_HEXDUMP(APPLET_NOEXEC(hexdump, hexdump, BB_DIR_USR_BIN, BB_SUID_DROP, hexdump))
  25//applet:IF_HD(APPLET_NOEXEC(hd, hexdump, BB_DIR_USR_BIN, BB_SUID_DROP, hd))
  26
  27//kbuild:lib-$(CONFIG_HEXDUMP) += hexdump.o
  28//kbuild:lib-$(CONFIG_HD) += hexdump.o
  29
  30//usage:#define hexdump_trivial_usage
  31//usage:       "[-bcdoxCv] [-e FMT] [-f FMT_FILE] [-n LEN] [-s OFS] [FILE]..."
  32//usage:#define hexdump_full_usage "\n\n"
  33//usage:       "Display FILEs (or stdin) in a user specified format\n"
  34//usage:     "\n        -b              1-byte octal display"
  35//usage:     "\n        -c              1-byte character display"
  36//usage:     "\n        -d              2-byte decimal display"
  37//usage:     "\n        -o              2-byte octal display"
  38//usage:     "\n        -x              2-byte hex display"
  39//usage:     "\n        -C              hex+ASCII 16 bytes per line"
  40//usage:     "\n        -v              Show all (no dup folding)"
  41//usage:     "\n        -e FORMAT_STR   Example: '16/1 \"%02x|\"\"\\n\"'"
  42//usage:     "\n        -f FORMAT_FILE"
  43// exactly the same help text lines in hexdump and xxd:
  44//usage:     "\n        -n LENGTH       Show only first LENGTH bytes"
  45//usage:     "\n        -s OFFSET       Skip OFFSET bytes"
  46//usage:
  47//usage:#define hd_trivial_usage
  48//usage:       "FILE..."
  49//usage:#define hd_full_usage "\n\n"
  50//usage:       "hd is an alias for hexdump -C"
  51
  52#include "libbb.h"
  53#include "dump.h"
  54
  55/* This is a NOEXEC applet. Be very careful! */
  56
  57static void bb_dump_addfile(dumper_t *dumper, char *name)
  58{
  59        char *p;
  60        FILE *fp;
  61        char *buf;
  62
  63        fp = xfopen_for_read(name);
  64        while ((buf = xmalloc_fgetline(fp)) != NULL) {
  65                p = skip_whitespace(buf);
  66                if (*p && (*p != '#')) {
  67                        bb_dump_add(dumper, p);
  68                }
  69                free(buf);
  70        }
  71        fclose(fp);
  72}
  73
  74static const char *const add_strings[] = {
  75        "\"%07.7_ax \"16/1 \"%03o \"\"\n\"",   /* b */
  76        "\"%07.7_ax \"16/1 \"%3_c \"\"\n\"",   /* c */
  77        "\"%07.7_ax \"8/2 \"  %05u \"\"\n\"",  /* d */
  78        "\"%07.7_ax \"8/2 \" %06o \"\"\n\"",   /* o */
  79        "\"%07.7_ax \"8/2 \"   %04x \"\"\n\"", /* x */
  80};
  81
  82static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
  83
  84static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v";
  85
  86int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  87int hexdump_main(int argc, char **argv)
  88{
  89        dumper_t *dumper = alloc_dumper();
  90        const char *p;
  91        int ch;
  92
  93        if (ENABLE_HD
  94         && (!ENABLE_HEXDUMP || !applet_name[2])
  95        ) { /* we are "hd" */
  96                ch = 'C';
  97                goto hd_applet;
  98        }
  99
 100        /* We cannot use getopt32: in hexdump options are cumulative.
 101         * E.g. "hexdump -C -C file" should dump each line twice */
 102        while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
 103                p = strchr(hexdump_opts, ch);
 104                if (!p)
 105                        bb_show_usage();
 106                if ((p - hexdump_opts) < 5) {
 107                        bb_dump_add(dumper, add_first);
 108                        bb_dump_add(dumper, add_strings[(int)(p - hexdump_opts)]);
 109                }
 110                /* Save a little bit of space below by omitting the 'else's. */
 111                if (ch == 'C') {
 112 hd_applet:
 113                        bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump
 114                        //------------------- "address  "   8 * "xx "    "  "  8 * "xx "
 115                        bb_dump_add(dumper, "\"%08.8_ax  \"8/1 \"%02x \"\"  \"8/1 \"%02x \"");
 116                        //------------------- "  |ASCII...........|\n"
 117                        bb_dump_add(dumper, "\"  |\"16/1 \"%_p\"\"|\n\"");
 118                }
 119                if (ch == 'e') {
 120                        bb_dump_add(dumper, optarg);
 121                } /* else */
 122                if (ch == 'f') {
 123                        bb_dump_addfile(dumper, optarg);
 124                } /* else */
 125                if (ch == 'n') {
 126                        dumper->dump_length = xatoi_positive(optarg);
 127                } /* else */
 128                if (ch == 's') { /* compat: -s accepts hex numbers too */
 129                        dumper->dump_skip = xstrtoull_range_sfx(
 130                                optarg,
 131                                /*base:*/ 0,
 132                                /*lo:*/ 0, /*hi:*/ OFF_T_MAX,
 133                                bkm_suffixes
 134                        );
 135                } /* else */
 136                if (ch == 'v') {
 137                        dumper->dump_vflag = ALL;
 138                }
 139        }
 140
 141        if (!dumper->fshead) {
 142                bb_dump_add(dumper, add_first);
 143                bb_dump_add(dumper, "\"%07.7_ax \"8/2 \"%04x \"\"\n\"");
 144        }
 145
 146        argv += optind;
 147
 148        return bb_dump_dump(dumper, argv);
 149}
 150