1 /* od -- dump files in octal and other formats
2 Copyright (C) 92, 1995-2004 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 /* Written by Jim Meyering. */
19 /* Busyboxed by Denys Vlasenko, based on od.c from coreutils-5.2.1 */
22 /* #include "libbb.h" - done in od.c */
23 #define assert(a) ((void)0)
26 //usage:#if ENABLE_DESKTOP
27 //usage:#define od_trivial_usage
28 //usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE]..."
30 // ... [FILE] [[+]OFFSET[.][b]]
31 // Support is buggy for:
32 // od --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]
34 //usage:#define od_full_usage "\n\n"
35 //usage: "Print FILEs (or stdin) unambiguously, as octal bytes by default"
52 /* When zero and two or more consecutive blocks are equal, format
53 only the first block and output an asterisk alone on the following
54 line to indicate that identical blocks have been elided: */
60 OPT_traditional = (1 << 18) * ENABLE_LONG_OPTS,
63 #define OD_GETOPT32() getopt32(argv, \
64 "A:N:abcdfhij:lot:vxsS:w::", \
65 /* -w with optional param */ \
66 /* -S was -s and also had optional parameter */ \
67 /* but in coreutils 6.3 it was renamed and now has */ \
68 /* _mandatory_ parameter */ \
69 &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block)
72 /* Check for 0x7f is a coreutils 6.3 addition */
73 #define ISPRINT(c) (((c) >= ' ') && (c) < 0x7f)
75 typedef long double longdouble_t;
76 typedef unsigned long long ulonglong_t;
77 typedef long long llong;
80 # define xstrtooff_sfx xstrtoull_sfx
82 # define xstrtooff_sfx xstrtoul_sfx
85 /* The default number of input bytes per output line. */
86 #define DEFAULT_BYTES_PER_BLOCK 16
88 /* The number of decimal digits of precision in a float. */
93 /* The number of decimal digits of precision in a double. */
98 /* The number of decimal digits of precision in a long double. */
100 # define LDBL_DIG DBL_DIG
126 /* Each output format specification (from '-t spec' or from
127 old-style options) is represented by one of these structures. */
129 enum output_format fmt;
131 void (*print_function) (size_t, const char *, const char *);
133 int hexl_mode_trailer;
137 /* Convert the number of 8-bit bytes of a binary representation to
138 the number of characters (digits + sign if the type is signed)
139 required to represent the same quantity in the specified base/type.
140 For example, a 32-bit (4-byte) quantity may require a field width
141 as wide as the following for these types:
145 8 unsigned hexadecimal */
147 static const uint8_t bytes_to_oct_digits[] ALIGN1 =
148 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
150 static const uint8_t bytes_to_signed_dec_digits[] ALIGN1 =
151 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
153 static const uint8_t bytes_to_unsigned_dec_digits[] ALIGN1 =
154 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
156 static const uint8_t bytes_to_hex_digits[] ALIGN1 =
157 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
159 /* Convert enum size_spec to the size of the named type. */
160 static const signed char width_bytes[] ALIGN1 = {
171 /* Ensure that for each member of 'enum size_spec' there is an
172 initializer in the width_bytes array. */
173 struct ERR_width_bytes_has_bad_size {
174 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
177 static smallint exit_code;
179 static unsigned string_min;
181 /* An array of specs describing how to format each input block. */
182 static size_t n_specs;
183 static struct tspec *spec;
185 /* Function that accepts an address and an optional following char,
186 and prints the address and char to stdout. */
187 static void (*format_address)(off_t, char);
188 /* The difference between the old-style pseudo starting address and
189 the number of bytes to skip. */
191 static off_t pseudo_offset;
193 enum { pseudo_offset = 0 };
195 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
196 input is formatted. */
198 /* The number of input bytes formatted per output line. It must be
199 a multiple of the least common multiple of the sizes associated with
200 the specified output types. It should be as large as possible, but
201 no larger than 16 -- unless specified with the -w option. */
202 static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
204 /* A NULL-terminated list of the file-arguments from the command line. */
205 static const char *const *file_list;
207 /* The input stream associated with the current file. */
208 static FILE *in_stream;
210 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
211 static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
212 [sizeof(char)] = CHAR,
213 #if USHRT_MAX != UCHAR_MAX
214 [sizeof(short)] = SHORT,
216 #if UINT_MAX != USHRT_MAX
219 #if ULONG_MAX != UINT_MAX
220 [sizeof(long)] = LONG,
222 #if ULLONG_MAX != ULONG_MAX
223 [sizeof(ulonglong_t)] = LONG_LONG,
227 #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
228 static const unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
229 /* gcc seems to allow repeated indexes. Last one wins */
230 [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
231 [sizeof(double)] = FLOAT_DOUBLE,
232 [sizeof(float)] = FLOAT_SINGLE
237 gcd(unsigned u, unsigned v)
248 /* Compute the least common multiple of U and V. */
250 lcm(unsigned u, unsigned v) {
251 unsigned t = gcd(u, v);
258 print_s_char(size_t n_bytes, const char *block, const char *fmt_string)
261 int tmp = *(signed char *) block;
262 printf(fmt_string, tmp);
263 block += sizeof(unsigned char);
268 print_char(size_t n_bytes, const char *block, const char *fmt_string)
271 unsigned tmp = *(unsigned char *) block;
272 printf(fmt_string, tmp);
273 block += sizeof(unsigned char);
278 print_s_short(size_t n_bytes, const char *block, const char *fmt_string)
280 n_bytes /= sizeof(signed short);
282 int tmp = *(signed short *) block;
283 printf(fmt_string, tmp);
284 block += sizeof(unsigned short);
289 print_short(size_t n_bytes, const char *block, const char *fmt_string)
291 n_bytes /= sizeof(unsigned short);
293 unsigned tmp = *(unsigned short *) block;
294 printf(fmt_string, tmp);
295 block += sizeof(unsigned short);
300 print_int(size_t n_bytes, const char *block, const char *fmt_string)
302 n_bytes /= sizeof(unsigned);
304 unsigned tmp = *(unsigned *) block;
305 printf(fmt_string, tmp);
306 block += sizeof(unsigned);
310 #if UINT_MAX == ULONG_MAX
311 # define print_long print_int
314 print_long(size_t n_bytes, const char *block, const char *fmt_string)
316 n_bytes /= sizeof(unsigned long);
318 unsigned long tmp = *(unsigned long *) block;
319 printf(fmt_string, tmp);
320 block += sizeof(unsigned long);
325 #if ULONG_MAX == ULLONG_MAX
326 # define print_long_long print_long
329 print_long_long(size_t n_bytes, const char *block, const char *fmt_string)
331 n_bytes /= sizeof(ulonglong_t);
333 ulonglong_t tmp = *(ulonglong_t *) block;
334 printf(fmt_string, tmp);
335 block += sizeof(ulonglong_t);
341 print_float(size_t n_bytes, const char *block, const char *fmt_string)
343 n_bytes /= sizeof(float);
345 float tmp = *(float *) block;
346 printf(fmt_string, tmp);
347 block += sizeof(float);
352 print_double(size_t n_bytes, const char *block, const char *fmt_string)
354 n_bytes /= sizeof(double);
356 double tmp = *(double *) block;
357 printf(fmt_string, tmp);
358 block += sizeof(double);
363 print_long_double(size_t n_bytes, const char *block, const char *fmt_string)
365 n_bytes /= sizeof(longdouble_t);
367 longdouble_t tmp = *(longdouble_t *) block;
368 printf(fmt_string, tmp);
369 block += sizeof(longdouble_t);
373 /* print_[named]_ascii are optimized for speed.
374 * Remember, someday you may want to pump gigabytes through this thing.
375 * Saving a dozen of .text bytes here is counter-productive */
378 print_named_ascii(size_t n_bytes, const char *block,
379 const char *unused_fmt_string UNUSED_PARAM)
381 /* Names for some non-printing characters. */
382 static const char charname[33][3] ALIGN1 = {
383 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
384 " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
385 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
386 "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
389 // buf[N] pos: 01234 56789
390 char buf[12] = " x\0 0xx\0";
391 // actually " x\0 xxx\0", but want to share string with print_ascii.
392 // [12] because we take three 32bit stack slots anyway, and
393 // gcc is too dumb to initialize with constant stores,
394 // it copies initializer from rodata. Oh well.
397 unsigned masked_c = *(unsigned char *) block++;
400 if (masked_c == 0x7f) {
401 fputs(" del", stdout);
404 if (masked_c > ' ') {
409 /* Why? Because printf(" %3.3s") is much slower... */
410 buf[6] = charname[masked_c][0];
411 buf[7] = charname[masked_c][1];
412 buf[8] = charname[masked_c][2];
413 fputs(buf+5, stdout);
418 print_ascii(size_t n_bytes, const char *block,
419 const char *unused_fmt_string UNUSED_PARAM)
421 // buf[N] pos: 01234 56789
422 char buf[12] = " x\0 0xx\0";
426 unsigned c = *(unsigned char *) block++;
461 default: /* c is never larger than 040 */
462 buf[7] = (c >> 3) + '0';
463 buf[8] = (c & 7) + '0';
470 /* Given a list of one or more input filenames FILE_LIST, set the global
471 file pointer IN_STREAM and the global string INPUT_FILENAME to the
472 first one that can be successfully opened. Modify FILE_LIST to
473 reference the next filename in the list. A file name of "-" is
474 interpreted as standard input. If any file open fails, give an error
475 message and return nonzero. */
483 in_stream = fopen_or_warn_stdin(*file_list++);
490 if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N)
491 setbuf(in_stream, NULL);
494 /* Test whether there have been errors on in_stream, and close it if
495 it is not standard input. Return nonzero if there has been an error
496 on in_stream or stdout; return zero otherwise. This function will
497 report more than one error only if both a read and a write error
498 have occurred. IN_ERRNO, if nonzero, is the error number
499 corresponding to the most recent action for IN_STREAM. */
502 check_and_close(void)
505 if (ferror(in_stream)) {
506 bb_error_msg("%s: read error", (in_stream == stdin)
507 ? bb_msg_standard_input
512 fclose_if_not_stdin(in_stream);
516 if (ferror(stdout)) {
517 bb_error_msg_and_die(bb_msg_write_error);
521 /* If S points to a single valid modern od format string, put
522 a description of that format in *TSPEC, return pointer to
523 character following the just-decoded format.
524 For example, if S were "d4afL", we will return a rtp to "afL"
527 fmt = SIGNED_DECIMAL;
528 size = INT or LONG; (whichever integral_type_size[4] resolves to)
529 print_function = print_int; (assuming size == INT)
530 fmt_string = "%011d%c";
532 S_ORIG is solely for reporting errors. It should be the full format
535 static NOINLINE const char *
536 decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
538 enum size_spec size_spec;
540 enum output_format fmt;
543 char *fmt_string = NULL;
544 void (*print_function) (size_t, const char *, const char *);
546 unsigned field_width = 0;
554 static const char CSIL[] ALIGN1 = "CSIL";
557 p = strchr(CSIL, *s);
558 /* if *s == NUL, p != NULL! Testcase: "od -tx" */
559 if (!p || *p == '\0') {
562 size = bb_strtou(s, &end, 0);
564 || MAX_INTEGRAL_TYPE_SIZE < size
565 || integral_type_size[size] == NO_SIZE
567 bb_error_msg_and_die("invalid type string '%s'; "
568 "%u-byte %s type is not supported",
569 s_orig, size, "integral");
574 static const uint8_t CSIL_sizeof[4] = {
580 size = CSIL_sizeof[p - CSIL];
581 s++; /* skip C/S/I/L */
584 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
585 ((Spec) == LONG_LONG ? (Max_format) \
586 : ((Spec) == LONG ? (Long_format) : (Min_format)))
588 #define FMT_BYTES_ALLOCATED 9
589 size_spec = integral_type_size[size];
592 static const char doux[] ALIGN1 = "doux";
593 static const char doux_fmt_letter[][4] = {
594 "lld", "llo", "llu", "llx"
596 static const enum output_format doux_fmt[] = {
602 static const uint8_t *const doux_bytes_to_XXX[] = {
603 bytes_to_signed_dec_digits,
605 bytes_to_unsigned_dec_digits,
608 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
615 pos = strchr(doux, c) - doux;
617 field_width = doux_bytes_to_XXX[pos][size];
618 p = doux_fmt_letter[pos] + 2;
619 if (size_spec == LONG) p--;
620 if (size_spec == LONG_LONG) p -= 2;
621 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
626 print_function = (fmt == SIGNED_DECIMAL
631 print_function = (fmt == SIGNED_DECIMAL
636 print_function = print_int;
639 print_function = print_long;
641 default: /* case LONG_LONG: */
642 print_function = print_long_long;
649 static const char FDL[] ALIGN1 = "FDL";
651 fmt = FLOATING_POINT;
655 size = sizeof(double);
657 size = bb_strtou(s, &end, 0);
658 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
659 || fp_type_size[size] == NO_SIZE
661 bb_error_msg_and_die("invalid type string '%s'; "
662 "%u-byte %s type is not supported",
663 s_orig, size, "floating point");
668 static const uint8_t FDL_sizeof[] = {
671 sizeof(longdouble_t),
674 size = FDL_sizeof[p - FDL];
677 size_spec = fp_type_size[size];
681 print_function = print_float;
682 field_width = FLT_DIG + 8;
683 /* Don't use %#e; not all systems support it. */
684 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
687 print_function = print_double;
688 field_width = DBL_DIG + 8;
689 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
691 default: /* case FLOAT_LONG_DOUBLE: */
692 print_function = print_long_double;
693 field_width = LDBL_DIG + 8;
694 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
702 fmt = NAMED_CHARACTER;
704 print_function = print_named_ascii;
711 print_function = print_ascii;
715 bb_error_msg_and_die("invalid character '%c' "
716 "in type string '%s'", *s, s_orig);
719 tspec->size = size_spec;
721 tspec->print_function = print_function;
722 tspec->fmt_string = fmt_string;
724 tspec->field_width = field_width;
725 tspec->hexl_mode_trailer = (*s == 'z');
726 if (tspec->hexl_mode_trailer)
732 /* Decode the modern od format string S. Append the decoded
733 representation to the global array SPEC, reallocating SPEC if
737 decode_format_string(const char *s)
739 const char *s_orig = s;
745 next = decode_one_format(s_orig, s, &tspec);
749 spec = xrealloc_vector(spec, 4, n_specs);
750 memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
755 /* Given a list of one or more input filenames FILE_LIST, set the global
756 file pointer IN_STREAM to position N_SKIP in the concatenation of
757 those files. If any file operation fails or if there are fewer than
758 N_SKIP bytes in the combined input, give an error message and return
759 nonzero. When possible, use seek rather than read operations to
760 advance IN_STREAM. */
768 while (in_stream) { /* !EOF */
769 struct stat file_stats;
771 /* First try seeking. For large offsets, this extra work is
772 worthwhile. If the offset is below some threshold it may be
773 more efficient to move the pointer by reading. There are two
774 issues when trying to seek:
775 - the file must be seekable.
776 - before seeking to the specified position, make sure
777 that the new position is in the current file.
778 Try to do that by getting file's size using fstat.
779 But that will work only for regular files. */
781 /* The st_size field is valid only for regular files
782 (and for symbolic links, which cannot occur here).
783 If the number of bytes left to skip is at least
784 as large as the size of the current file, we can
785 decrement n_skip and go on to the next file. */
786 if (fstat(fileno(in_stream), &file_stats) == 0
787 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
789 if (file_stats.st_size < n_skip) {
790 n_skip -= file_stats.st_size;
791 /* take "check & close / open_next" route */
793 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
798 /* If it's not a regular file with positive size,
799 position the file pointer by reading. */
801 size_t n_bytes_to_read = 1024;
805 if (n_skip < n_bytes_to_read)
806 n_bytes_to_read = n_skip;
807 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
808 n_skip -= n_bytes_read;
809 if (n_bytes_read != n_bytes_to_read)
810 break; /* EOF on this file or error */
821 bb_error_msg_and_die("can't skip past end of combined input");
825 typedef void FN_format_address(off_t address, char c);
828 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
832 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
833 /* Corresponds to 'x' above */
834 #define address_base_char address_fmt[sizeof(address_fmt)-3]
835 /* Corresponds to 'n' above */
836 #define address_pad_len_char address_fmt[2]
839 format_address_std(off_t address, char c)
841 /* Corresponds to 'c' */
842 address_fmt[sizeof(address_fmt)-2] = c;
843 printf(address_fmt, address);
847 /* only used with --traditional */
849 format_address_paren(off_t address, char c)
852 format_address_std(address, ')');
857 format_address_label(off_t address, char c)
859 format_address_std(address, ' ');
860 format_address_paren(address + pseudo_offset, c);
865 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
869 unsigned c = *(unsigned char *) block++;
870 c = (ISPRINT(c) ? c : '.');
876 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
877 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
878 CURR_BLOCK in the concatenation of input files, and it is printed
879 (optionally) only before the output line associated with the first
880 format spec. When duplicate blocks are being abbreviated, the output
881 for a sequence of identical input blocks is the output for the first
882 block followed by an asterisk alone on a line. It is valid to compare
883 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
884 That condition may be false only for the last input block -- and then
885 only when it has not been padded to length BYTES_PER_BLOCK. */
888 write_block(off_t current_offset, size_t n_bytes,
889 const char *prev_block, const char *curr_block)
891 static char first = 1;
892 static char prev_pair_equal = 0;
895 if (!(option_mask32 & OPT_v)
897 && n_bytes == bytes_per_block
898 && memcmp(prev_block, curr_block, bytes_per_block) == 0
900 if (prev_pair_equal) {
901 /* The two preceding blocks were equal, and the current
902 block is the same as the last one, so print nothing. */
910 for (i = 0; i < n_specs; i++) {
912 format_address(current_offset, '\0');
914 printf("%*s", address_pad_len_char - '0', "");
915 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
916 if (spec[i].hexl_mode_trailer) {
917 /* space-pad out to full line width, then dump the trailer */
918 unsigned datum_width = width_bytes[spec[i].size];
919 unsigned blank_fields = (bytes_per_block - n_bytes) / datum_width;
920 unsigned field_width = spec[i].field_width + 1;
921 printf("%*s", blank_fields * field_width, "");
922 dump_hexl_mode_trailer(n_bytes, curr_block);
930 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
932 assert(0 < n && n <= bytes_per_block);
934 *n_bytes_in_buffer = 0;
939 while (in_stream != NULL) { /* EOF. */
943 n_needed = n - *n_bytes_in_buffer;
944 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
945 *n_bytes_in_buffer += n_read;
946 if (n_read == n_needed)
948 /* error check is done in check_and_close */
954 /* Return the least common multiple of the sizes associated
955 with the format specs. */
963 for (i = 0; i < n_specs; i++)
964 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
968 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
969 formatted block to standard output, and repeat until the specified
970 maximum number of bytes has been read or until all input has been
971 processed. If the last block read is smaller than BYTES_PER_BLOCK
972 and its size is not a multiple of the size associated with a format
973 spec, extend the input block with zero bytes until its length is a
974 multiple of all format spec sizes. Write the final block. Finally,
975 write on a line by itself the offset of the byte after the last byte
979 dump(off_t current_offset, off_t end_offset)
985 block[0] = xmalloc(2 * bytes_per_block);
986 block[1] = block[0] + bytes_per_block;
989 if (option_mask32 & OPT_N) {
992 if (current_offset >= end_offset) {
996 n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block);
997 read_block(n_needed, block[idx], &n_bytes_read);
998 if (n_bytes_read < bytes_per_block)
1000 assert(n_bytes_read == bytes_per_block);
1001 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1002 current_offset += n_bytes_read;
1007 read_block(bytes_per_block, block[idx], &n_bytes_read);
1008 if (n_bytes_read < bytes_per_block)
1010 assert(n_bytes_read == bytes_per_block);
1011 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1012 current_offset += n_bytes_read;
1017 if (n_bytes_read > 0) {
1019 size_t bytes_to_write;
1023 /* Make bytes_to_write the smallest multiple of l_c_m that
1024 is at least as large as n_bytes_read. */
1025 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1027 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1028 write_block(current_offset, bytes_to_write,
1029 block[idx ^ 1], block[idx]);
1030 current_offset += n_bytes_read;
1033 format_address(current_offset, '\n');
1035 if ((option_mask32 & OPT_N) && current_offset >= end_offset)
1041 /* Read N bytes into BLOCK from the concatenation of the input files
1042 named in the global array FILE_LIST. On the first call to this
1043 function, the global variable IN_STREAM is expected to be an open
1044 stream associated with the input file INPUT_FILENAME. If all N
1045 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1046 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1047 read the remaining bytes from the newly opened file. Repeat if
1048 necessary until EOF is reached for the last file in FILE_LIST.
1049 On subsequent calls, don't modify BLOCK and return zero. Set
1050 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1051 it will be detected through ferror when the stream is about to be
1052 closed. If there is an error, give a message but continue reading
1053 as usual and return nonzero. Otherwise return zero. */
1055 /* STRINGS mode. Find each "string constant" in the input.
1056 A string constant is a run of at least 'string_min' ASCII
1057 graphic (or formatting) characters terminated by a null.
1058 Based on a function written by Richard Stallman for a
1059 traditional version of od. */
1062 dump_strings(off_t address, off_t end_offset)
1064 unsigned bufsize = MAX(100, string_min);
1065 unsigned char *buf = xmalloc(bufsize);
1071 /* See if the next 'string_min' chars are all printing chars. */
1073 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
1076 while (!(option_mask32 & OPT_N) || address < end_offset) {
1078 bufsize += bufsize/8;
1079 buf = xrealloc(buf, bufsize);
1082 while (in_stream) { /* !EOF */
1083 c = fgetc(in_stream);
1096 goto tryline; /* It isn't; give up on this string. */
1097 buf[i++] = c; /* String continues; store it all. */
1100 if (i < string_min) /* Too short! */
1103 /* If we get here, the string is all printable and NUL-terminated */
1105 format_address(address - i - 1, ' ');
1107 for (i = 0; (c = buf[i]); i++) {
1109 case '\007': fputs("\\a", stdout); break;
1110 case '\b': fputs("\\b", stdout); break;
1111 case '\f': fputs("\\f", stdout); break;
1112 case '\n': fputs("\\n", stdout); break;
1113 case '\r': fputs("\\r", stdout); break;
1114 case '\t': fputs("\\t", stdout); break;
1115 case '\v': fputs("\\v", stdout); break;
1116 default: putchar(c);
1122 /* We reach this point only if we search through
1123 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1129 #if ENABLE_LONG_OPTS
1130 /* If S is a valid traditional offset specification with an optional
1131 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
1134 parse_old_offset(const char *s, off_t *offset)
1136 static const struct suffix_mult Bb[] = {
1144 /* Skip over any leading '+'. */
1145 if (s[0] == '+') ++s;
1146 if (!isdigit(s[0])) return 0; /* not a number */
1148 /* Determine the radix we'll use to interpret S. If there is a '.',
1149 * it's decimal, otherwise, if the string begins with '0X'or '0x',
1150 * it's hexadecimal, else octal. */
1154 p[0] = '\0'; /* cheating */
1156 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1159 *offset = xstrtooff_sfx(s, radix, Bb);
1162 return (*offset >= 0);
1166 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1167 int od_main(int argc UNUSED_PARAM, char **argv)
1169 static const struct suffix_mult bkm[] = {
1175 #if ENABLE_LONG_OPTS
1176 static const char od_longopts[] ALIGN1 =
1177 "skip-bytes\0" Required_argument "j"
1178 "address-radix\0" Required_argument "A"
1179 "read-bytes\0" Required_argument "N"
1180 "format\0" Required_argument "t"
1181 "output-duplicates\0" No_argument "v"
1182 /* Yes, it's true: -S NUM, but --strings[=NUM]!
1183 * that is, NUM is mandatory for -S but optional for --strings!
1185 "strings\0" Optional_argument "S"
1186 "width\0" Optional_argument "w"
1187 "traditional\0" No_argument "\xff"
1190 const char *str_A, *str_N, *str_j, *str_S = "3";
1191 llist_t *lst_t = NULL;
1194 /* The number of input bytes to skip before formatting and writing. */
1195 off_t n_bytes_to_skip = 0;
1196 /* The offset of the first byte after the last byte to be formatted. */
1197 off_t end_offset = 0;
1198 /* The maximum number of bytes that will be formatted. */
1199 off_t max_bytes_to_format = 0;
1202 format_address = format_address_std;
1203 address_base_char = 'o';
1204 address_pad_len_char = '7';
1206 /* Parse command line */
1207 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1208 #if ENABLE_LONG_OPTS
1209 applet_long_options = od_longopts;
1211 opt = OD_GETOPT32();
1214 static const char doxn[] ALIGN1 = "doxn";
1215 static const char doxn_address_base_char[] ALIGN1 = {
1216 'u', 'o', 'x', /* '?' fourth one is not important */
1218 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1219 '7', '7', '6', /* '?' */
1223 p = strchr(doxn, str_A[0]);
1225 bb_error_msg_and_die("bad output address radix "
1226 "'%c' (must be [doxn])", str_A[0]);
1228 if (pos == 3) format_address = format_address_none;
1229 address_base_char = doxn_address_base_char[pos];
1230 address_pad_len_char = doxn_address_pad_len_char[pos];
1233 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1235 if (opt & OPT_a) decode_format_string("a");
1236 if (opt & OPT_b) decode_format_string("oC");
1237 if (opt & OPT_c) decode_format_string("c");
1238 if (opt & OPT_d) decode_format_string("u2");
1239 if (opt & OPT_f) decode_format_string("fF");
1240 if (opt & OPT_h) decode_format_string("x2");
1241 if (opt & OPT_i) decode_format_string("d2");
1242 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1243 if (opt & OPT_l) decode_format_string("d4");
1244 if (opt & OPT_o) decode_format_string("o2");
1246 decode_format_string(llist_pop(&lst_t));
1248 if (opt & OPT_x) decode_format_string("x2");
1249 if (opt & OPT_s) decode_format_string("d2");
1251 string_min = xstrtou_sfx(str_S, 0, bkm);
1255 //if ((option_mask32 & OPT_S) && n_specs > 0)
1256 // bb_error_msg_and_die("no type may be specified when dumping strings");
1258 /* If the --traditional option is used, there may be from
1259 * 0 to 3 remaining command line arguments; handle each case
1261 * od [FILE] [[+]OFFSET[.][b] [[+]LABEL[.][b]]]
1262 * The offset and pseudo_start have the same syntax.
1264 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1265 * traditional syntax even if --traditional is not given. */
1267 #if ENABLE_LONG_OPTS
1268 if (opt & OPT_traditional) {
1270 off_t pseudo_start = -1;
1273 if (!argv[1]) { /* one arg */
1274 if (parse_old_offset(argv[0], &o1)) {
1275 /* od --traditional OFFSET */
1276 n_bytes_to_skip = o1;
1279 /* od --traditional FILE */
1280 } else if (!argv[2]) { /* two args */
1281 if (parse_old_offset(argv[0], &o1)
1282 && parse_old_offset(argv[1], &o2)
1284 /* od --traditional OFFSET LABEL */
1285 n_bytes_to_skip = o1;
1288 } else if (parse_old_offset(argv[1], &o2)) {
1289 /* od --traditional FILE OFFSET */
1290 n_bytes_to_skip = o2;
1293 bb_error_msg_and_die("invalid second argument '%s'", argv[1]);
1295 } else if (!argv[3]) { /* three args */
1296 if (parse_old_offset(argv[1], &o1)
1297 && parse_old_offset(argv[2], &o2)
1299 /* od --traditional FILE OFFSET LABEL */
1300 n_bytes_to_skip = o1;
1304 bb_error_msg_and_die("the last two arguments must be offsets");
1306 } else { /* >3 args */
1307 bb_error_msg_and_die("too many arguments");
1310 if (pseudo_start >= 0) {
1311 if (format_address == format_address_none) {
1312 address_base_char = 'o';
1313 address_pad_len_char = '7';
1314 format_address = format_address_paren;
1316 format_address = format_address_label;
1318 pseudo_offset = pseudo_start - n_bytes_to_skip;
1321 /* else: od --traditional (without args) */
1325 if (option_mask32 & OPT_N) {
1326 end_offset = n_bytes_to_skip + max_bytes_to_format;
1327 if (end_offset < n_bytes_to_skip)
1328 bb_error_msg_and_die("SKIP + SIZE is too large");
1332 decode_format_string("o2");
1333 /*n_specs = 1; - done by decode_format_string */
1336 /* If no files were listed on the command line,
1337 set the global pointer FILE_LIST so that it
1338 references the null-terminated list of one name: "-". */
1339 file_list = bb_argv_dash;
1341 /* Set the global pointer FILE_LIST so that it
1342 references the first file-argument on the command-line. */
1343 file_list = (char const *const *) argv;
1346 /* Open the first input file */
1348 /* Skip over any unwanted header bytes */
1349 skip(n_bytes_to_skip);
1351 return EXIT_FAILURE;
1353 /* Compute output block length */
1356 if (opt & OPT_w) { /* -w: width */
1357 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1358 bb_error_msg("warning: invalid width %u; using %d instead",
1359 (unsigned)bytes_per_block, l_c_m);
1360 bytes_per_block = l_c_m;
1363 bytes_per_block = l_c_m;
1364 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1365 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1369 for (i = 0; i < n_specs; i++) {
1370 printf("%d: fmt=\"%s\" width=%d\n",
1371 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1375 if (option_mask32 & OPT_S)
1376 dump_strings(n_bytes_to_skip, end_offset);
1378 dump(n_bytes_to_skip, end_offset);
1381 bb_perror_msg_and_die(bb_msg_standard_input);