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