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. */
20 /* Busyboxed by Denys Vlasenko
22 Based on od.c from coreutils-5.2.1
25 00000073 t parse_old_offset
27 00000090 r long_options
28 00000092 t print_named_ascii
29 000000bf t print_ascii
30 00000168 t write_block
31 00000366 t decode_format_string
34 Tested for compat with coreutils 6.3
35 using this script. Minor differences fixed.
39 time /path/to/coreutils/od \
48 diff -u -a std bbox >bbox.diff || { echo Different!; sleep 1; }
55 #define assert(a) ((void)0)
57 /* Check for 0x7f is a coreutils 6.3 addition */
58 #define ISPRINT(c) (((c)>=' ') && (c) != 0x7f)
60 typedef long double longdouble_t;
61 typedef unsigned long long ulonglong_t;
62 typedef long long llong;
65 # define xstrtooff_sfx xstrtoull_sfx
67 # define xstrtooff_sfx xstrtoul_sfx
70 /* The default number of input bytes per output line. */
71 #define DEFAULT_BYTES_PER_BLOCK 16
73 /* The number of decimal digits of precision in a float. */
78 /* The number of decimal digits of precision in a double. */
83 /* The number of decimal digits of precision in a long double. */
85 # define LDBL_DIG DBL_DIG
111 /* Each output format specification (from '-t spec' or from
112 old-style options) is represented by one of these structures. */
114 enum output_format fmt;
116 void (*print_function) (size_t, const char *, const char *);
118 int hexl_mode_trailer;
122 /* Convert the number of 8-bit bytes of a binary representation to
123 the number of characters (digits + sign if the type is signed)
124 required to represent the same quantity in the specified base/type.
125 For example, a 32-bit (4-byte) quantity may require a field width
126 as wide as the following for these types:
130 8 unsigned hexadecimal */
132 static const uint8_t bytes_to_oct_digits[] ALIGN1 =
133 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
135 static const uint8_t bytes_to_signed_dec_digits[] ALIGN1 =
136 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
138 static const uint8_t bytes_to_unsigned_dec_digits[] ALIGN1 =
139 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
141 static const uint8_t bytes_to_hex_digits[] ALIGN1 =
142 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
144 /* Convert enum size_spec to the size of the named type. */
145 static const signed char width_bytes[] ALIGN1 = {
156 /* Ensure that for each member of 'enum size_spec' there is an
157 initializer in the width_bytes array. */
158 struct ERR_width_bytes_has_bad_size {
159 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
162 static smallint flag_dump_strings;
163 /* Non-zero if an old-style 'pseudo-address' was specified. */
164 static smallint flag_pseudo_start;
165 static smallint limit_bytes_to_format;
166 /* When zero and two or more consecutive blocks are equal, format
167 only the first block and output an asterisk alone on the following
168 line to indicate that identical blocks have been elided. */
169 static smallint verbose;
170 static smallint ioerror;
172 static size_t string_min;
174 /* An array of specs describing how to format each input block. */
175 static size_t n_specs;
176 static struct tspec *spec;
178 /* Function that accepts an address and an optional following char,
179 and prints the address and char to stdout. */
180 static void (*format_address)(off_t, char);
181 /* The difference between the old-style pseudo starting address and
182 the number of bytes to skip. */
183 static off_t pseudo_offset;
184 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
185 input is formatted. */
187 /* The number of input bytes formatted per output line. It must be
188 a multiple of the least common multiple of the sizes associated with
189 the specified output types. It should be as large as possible, but
190 no larger than 16 -- unless specified with the -w option. */
191 static size_t bytes_per_block;
193 /* A NULL-terminated list of the file-arguments from the command line. */
194 static const char *const *file_list;
196 /* The input stream associated with the current file. */
197 static FILE *in_stream;
199 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
200 static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
201 [sizeof(char)] = CHAR,
202 #if USHRT_MAX != UCHAR_MAX
203 [sizeof(short)] = SHORT,
205 #if UINT_MAX != USHRT_MAX
208 #if ULONG_MAX != UINT_MAX
209 [sizeof(long)] = LONG,
211 #if ULLONG_MAX != ULONG_MAX
212 [sizeof(ulonglong_t)] = LONG_LONG,
216 #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
217 static const unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
218 /* gcc seems to allow repeated indexes. Last one stays */
219 [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
220 [sizeof(double)] = FLOAT_DOUBLE,
221 [sizeof(float)] = FLOAT_SINGLE
226 gcd(unsigned u, unsigned v)
237 /* Compute the least common multiple of U and V. */
239 lcm(unsigned u, unsigned v) {
240 unsigned t = gcd(u, v);
247 print_s_char(size_t n_bytes, const char *block, const char *fmt_string)
250 int tmp = *(signed char *) block;
251 printf(fmt_string, tmp);
252 block += sizeof(unsigned char);
257 print_char(size_t n_bytes, const char *block, const char *fmt_string)
260 unsigned tmp = *(unsigned char *) block;
261 printf(fmt_string, tmp);
262 block += sizeof(unsigned char);
267 print_s_short(size_t n_bytes, const char *block, const char *fmt_string)
269 n_bytes /= sizeof(signed short);
271 int tmp = *(signed short *) block;
272 printf(fmt_string, tmp);
273 block += sizeof(unsigned short);
278 print_short(size_t n_bytes, const char *block, const char *fmt_string)
280 n_bytes /= sizeof(unsigned short);
282 unsigned tmp = *(unsigned short *) block;
283 printf(fmt_string, tmp);
284 block += sizeof(unsigned short);
289 print_int(size_t n_bytes, const char *block, const char *fmt_string)
291 n_bytes /= sizeof(unsigned);
293 unsigned tmp = *(unsigned *) block;
294 printf(fmt_string, tmp);
295 block += sizeof(unsigned);
299 #if UINT_MAX == ULONG_MAX
300 # define print_long print_int
303 print_long(size_t n_bytes, const char *block, const char *fmt_string)
305 n_bytes /= sizeof(unsigned long);
307 unsigned long tmp = *(unsigned long *) block;
308 printf(fmt_string, tmp);
309 block += sizeof(unsigned long);
314 #if ULONG_MAX == ULLONG_MAX
315 # define print_long_long print_long
318 print_long_long(size_t n_bytes, const char *block, const char *fmt_string)
320 n_bytes /= sizeof(ulonglong_t);
322 ulonglong_t tmp = *(ulonglong_t *) block;
323 printf(fmt_string, tmp);
324 block += sizeof(ulonglong_t);
330 print_float(size_t n_bytes, const char *block, const char *fmt_string)
332 n_bytes /= sizeof(float);
334 float tmp = *(float *) block;
335 printf(fmt_string, tmp);
336 block += sizeof(float);
341 print_double(size_t n_bytes, const char *block, const char *fmt_string)
343 n_bytes /= sizeof(double);
345 double tmp = *(double *) block;
346 printf(fmt_string, tmp);
347 block += sizeof(double);
352 print_long_double(size_t n_bytes, const char *block, const char *fmt_string)
354 n_bytes /= sizeof(longdouble_t);
356 longdouble_t tmp = *(longdouble_t *) block;
357 printf(fmt_string, tmp);
358 block += sizeof(longdouble_t);
362 /* print_[named]_ascii are optimized for speed.
363 * Remember, someday you may want to pump gigabytes through this thing.
364 * Saving a dozen of .text bytes here is counter-productive */
367 print_named_ascii(size_t n_bytes, const char *block,
368 const char *unused_fmt_string ATTRIBUTE_UNUSED)
370 /* Names for some non-printing characters. */
371 static const char charname[33][3] ALIGN1 = {
372 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
373 " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
374 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
375 "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
378 // buf[N] pos: 01234 56789
379 char buf[12] = " x\0 0xx\0";
380 // actually " x\0 xxx\0", but I want to share the string with below.
381 // [12] because we take three 32bit stack slots anyway, and
382 // gcc is too dumb to initialize with constant stores,
383 // it copies initializer from rodata. Oh well.
386 unsigned masked_c = *(unsigned char *) block++;
389 if (masked_c == 0x7f) {
390 fputs(" del", stdout);
393 if (masked_c > ' ') {
398 /* Why? Because printf(" %3.3s") is much slower... */
399 buf[6] = charname[masked_c][0];
400 buf[7] = charname[masked_c][1];
401 buf[8] = charname[masked_c][2];
402 fputs(buf+5, stdout);
407 print_ascii(size_t n_bytes, const char *block,
408 const char *unused_fmt_string ATTRIBUTE_UNUSED)
410 // buf[N] pos: 01234 56789
411 char buf[12] = " x\0 0xx\0";
415 unsigned c = *(unsigned char *) block++;
450 default: /* c is never larger than 040 */
451 buf[7] = (c >> 3) + '0';
452 buf[8] = (c & 7) + '0';
459 /* Given a list of one or more input filenames FILE_LIST, set the global
460 file pointer IN_STREAM and the global string INPUT_FILENAME to the
461 first one that can be successfully opened. Modify FILE_LIST to
462 reference the next filename in the list. A file name of "-" is
463 interpreted as standard input. If any file open fails, give an error
464 message and return nonzero. */
472 in_stream = fopen_or_warn_stdin(*file_list++);
479 if (limit_bytes_to_format && !flag_dump_strings)
480 setbuf(in_stream, NULL);
483 /* Test whether there have been errors on in_stream, and close it if
484 it is not standard input. Return nonzero if there has been an error
485 on in_stream or stdout; return zero otherwise. This function will
486 report more than one error only if both a read and a write error
487 have occurred. IN_ERRNO, if nonzero, is the error number
488 corresponding to the most recent action for IN_STREAM. */
491 check_and_close(void)
494 if (ferror(in_stream)) {
495 bb_error_msg("%s: read error", (in_stream == stdin)
496 ? bb_msg_standard_input
501 fclose_if_not_stdin(in_stream);
505 if (ferror(stdout)) {
506 bb_error_msg("write error");
511 /* If S points to a single valid modern od format string, put
512 a description of that format in *TSPEC, make *NEXT point at the
513 character following the just-decoded format (if *NEXT is non-NULL),
514 and return zero. For example, if S were "d4afL"
515 *NEXT would be set to "afL" and *TSPEC would be
517 fmt = SIGNED_DECIMAL;
518 size = INT or LONG; (whichever integral_type_size[4] resolves to)
519 print_function = print_int; (assuming size == INT)
520 fmt_string = "%011d%c";
522 S_ORIG is solely for reporting errors. It should be the full format
526 decode_one_format(const char *s_orig, const char *s, const char **next,
529 enum size_spec size_spec;
531 enum output_format fmt;
534 char *fmt_string = NULL;
535 void (*print_function) (size_t, const char *, const char *);
537 unsigned field_width = 0;
540 assert(tspec != NULL);
547 static const char CSIL[] ALIGN1 = "CSIL";
550 p = strchr(CSIL, *s);
554 size = bb_strtou(s, &end, 0);
556 || MAX_INTEGRAL_TYPE_SIZE < size
557 || integral_type_size[size] == NO_SIZE
559 bb_error_msg_and_die("invalid type string '%s'; "
560 "%u-byte %s type is not supported",
561 s_orig, size, "integral");
566 static const uint8_t CSIL_sizeof[] = {
572 size = CSIL_sizeof[p - CSIL];
575 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
576 ((Spec) == LONG_LONG ? (Max_format) \
577 : ((Spec) == LONG ? (Long_format) : (Min_format)))
579 #define FMT_BYTES_ALLOCATED 9
580 size_spec = integral_type_size[size];
583 static const char doux[] ALIGN1 = "doux";
584 static const char doux_fmt_letter[][4] = {
585 "lld", "llo", "llu", "llx"
587 static const enum output_format doux_fmt[] = {
593 static const uint8_t *const doux_bytes_to_XXX[] = {
594 bytes_to_signed_dec_digits,
596 bytes_to_unsigned_dec_digits,
599 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
606 pos = strchr(doux, c) - doux;
608 field_width = doux_bytes_to_XXX[pos][size];
609 p = doux_fmt_letter[pos] + 2;
610 if (size_spec == LONG) p--;
611 if (size_spec == LONG_LONG) p -= 2;
612 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
617 print_function = (fmt == SIGNED_DECIMAL
622 print_function = (fmt == SIGNED_DECIMAL
627 print_function = print_int;
630 print_function = print_long;
632 default: /* case LONG_LONG: */
633 print_function = print_long_long;
640 static const char FDL[] ALIGN1 = "FDL";
642 fmt = FLOATING_POINT;
646 size = sizeof(double);
648 size = bb_strtou(s, &end, 0);
649 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
650 || fp_type_size[size] == NO_SIZE
652 bb_error_msg_and_die("invalid type string '%s'; "
653 "%u-byte %s type is not supported",
654 s_orig, size, "floating point");
659 static const uint8_t FDL_sizeof[] = {
662 sizeof(longdouble_t),
665 size = FDL_sizeof[p - FDL];
668 size_spec = fp_type_size[size];
672 print_function = print_float;
673 field_width = FLT_DIG + 8;
674 /* Don't use %#e; not all systems support it. */
675 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
678 print_function = print_double;
679 field_width = DBL_DIG + 8;
680 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
682 default: /* case FLOAT_LONG_DOUBLE: */
683 print_function = print_long_double;
684 field_width = LDBL_DIG + 8;
685 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
693 fmt = NAMED_CHARACTER;
695 print_function = print_named_ascii;
702 print_function = print_ascii;
706 bb_error_msg_and_die("invalid character '%c' "
707 "in type string '%s'", *s, s_orig);
710 tspec->size = size_spec;
712 tspec->print_function = print_function;
713 tspec->fmt_string = fmt_string;
715 tspec->field_width = field_width;
716 tspec->hexl_mode_trailer = (*s == 'z');
717 if (tspec->hexl_mode_trailer)
724 /* Decode the modern od format string S. Append the decoded
725 representation to the global array SPEC, reallocating SPEC if
729 decode_format_string(const char *s)
731 const char *s_orig = s;
737 decode_one_format(s_orig, s, &next, &tspec);
742 spec = xrealloc(spec, n_specs * sizeof(*spec));
743 memcpy(&spec[n_specs-1], &tspec, sizeof *spec);
747 /* Given a list of one or more input filenames FILE_LIST, set the global
748 file pointer IN_STREAM to position N_SKIP in the concatenation of
749 those files. If any file operation fails or if there are fewer than
750 N_SKIP bytes in the combined input, give an error message and return
751 nonzero. When possible, use seek rather than read operations to
752 advance IN_STREAM. */
760 while (in_stream) { /* !EOF */
761 struct stat file_stats;
763 /* First try seeking. For large offsets, this extra work is
764 worthwhile. If the offset is below some threshold it may be
765 more efficient to move the pointer by reading. There are two
766 issues when trying to seek:
767 - the file must be seekable.
768 - before seeking to the specified position, make sure
769 that the new position is in the current file.
770 Try to do that by getting file's size using fstat.
771 But that will work only for regular files. */
773 /* The st_size field is valid only for regular files
774 (and for symbolic links, which cannot occur here).
775 If the number of bytes left to skip is at least
776 as large as the size of the current file, we can
777 decrement n_skip and go on to the next file. */
778 if (fstat(fileno(in_stream), &file_stats) == 0
779 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
781 if (file_stats.st_size < n_skip) {
782 n_skip -= file_stats.st_size;
783 /* take "check & close / open_next" route */
785 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
790 /* If it's not a regular file with positive size,
791 position the file pointer by reading. */
793 size_t n_bytes_to_read = 1024;
797 if (n_skip < n_bytes_to_read)
798 n_bytes_to_read = n_skip;
799 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
800 n_skip -= n_bytes_read;
801 if (n_bytes_read != n_bytes_to_read)
802 break; /* EOF on this file or error */
813 bb_error_msg_and_die("cannot skip past end of combined input");
817 typedef void FN_format_address(off_t address, char c);
820 format_address_none(off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
824 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
825 /* Corresponds to 'x' above */
826 #define address_base_char address_fmt[sizeof(address_fmt)-3]
827 /* Corresponds to 'n' above */
828 #define address_pad_len_char address_fmt[2]
831 format_address_std(off_t address, char c)
833 /* Corresponds to 'c' */
834 address_fmt[sizeof(address_fmt)-2] = c;
835 printf(address_fmt, address);
838 #if ENABLE_GETOPT_LONG
839 /* only used with --traditional */
841 format_address_paren(off_t address, char c)
844 format_address_std(address, ')');
849 format_address_label(off_t address, char c)
851 format_address_std(address, ' ');
852 format_address_paren(address + pseudo_offset, c);
857 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
861 unsigned c = *(unsigned char *) block++;
862 c = (ISPRINT(c) ? c : '.');
868 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
869 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
870 CURR_BLOCK in the concatenation of input files, and it is printed
871 (optionally) only before the output line associated with the first
872 format spec. When duplicate blocks are being abbreviated, the output
873 for a sequence of identical input blocks is the output for the first
874 block followed by an asterisk alone on a line. It is valid to compare
875 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
876 That condition may be false only for the last input block -- and then
877 only when it has not been padded to length BYTES_PER_BLOCK. */
880 write_block(off_t current_offset, size_t n_bytes,
881 const char *prev_block, const char *curr_block)
883 static char first = 1;
884 static char prev_pair_equal = 0;
887 if (!verbose && !first
888 && n_bytes == bytes_per_block
889 && memcmp(prev_block, curr_block, bytes_per_block) == 0
891 if (prev_pair_equal) {
892 /* The two preceding blocks were equal, and the current
893 block is the same as the last one, so print nothing. */
901 for (i = 0; i < n_specs; i++) {
903 format_address(current_offset, '\0');
905 printf("%*s", address_pad_len_char - '0', "");
906 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
907 if (spec[i].hexl_mode_trailer) {
908 /* space-pad out to full line width, then dump the trailer */
909 int datum_width = width_bytes[spec[i].size];
910 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
911 int field_width = spec[i].field_width + 1;
912 printf("%*s", blank_fields * field_width, "");
913 dump_hexl_mode_trailer(n_bytes, curr_block);
921 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
923 assert(0 < n && n <= bytes_per_block);
925 *n_bytes_in_buffer = 0;
930 while (in_stream != NULL) { /* EOF. */
934 n_needed = n - *n_bytes_in_buffer;
935 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
936 *n_bytes_in_buffer += n_read;
937 if (n_read == n_needed)
939 /* error check is done in check_and_close */
945 /* Return the least common multiple of the sizes associated
946 with the format specs. */
954 for (i = 0; i < n_specs; i++)
955 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
959 #if ENABLE_GETOPT_LONG
960 /* If S is a valid traditional offset specification with an optional
961 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
964 parse_old_offset(const char *s, off_t *offset)
966 static const struct suffix_mult Bb[] = {
974 /* Skip over any leading '+'. */
975 if (s[0] == '+') ++s;
977 /* Determine the radix we'll use to interpret S. If there is a '.',
978 * it's decimal, otherwise, if the string begins with '0X'or '0x',
979 * it's hexadecimal, else octal. */
983 p[0] = '\0'; /* cheating */
985 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
988 *offset = xstrtooff_sfx(s, radix, Bb);
991 return (*offset >= 0);
995 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
996 formatted block to standard output, and repeat until the specified
997 maximum number of bytes has been read or until all input has been
998 processed. If the last block read is smaller than BYTES_PER_BLOCK
999 and its size is not a multiple of the size associated with a format
1000 spec, extend the input block with zero bytes until its length is a
1001 multiple of all format spec sizes. Write the final block. Finally,
1002 write on a line by itself the offset of the byte after the last byte
1006 dump(off_t current_offset, off_t end_offset)
1010 size_t n_bytes_read;
1012 block[0] = xmalloc(2*bytes_per_block);
1013 block[1] = block[0] + bytes_per_block;
1016 if (limit_bytes_to_format) {
1019 if (current_offset >= end_offset) {
1023 n_needed = MIN(end_offset - current_offset,
1024 (off_t) bytes_per_block);
1025 read_block(n_needed, block[idx], &n_bytes_read);
1026 if (n_bytes_read < bytes_per_block)
1028 assert(n_bytes_read == bytes_per_block);
1029 write_block(current_offset, n_bytes_read,
1030 block[!idx], block[idx]);
1031 current_offset += n_bytes_read;
1036 read_block(bytes_per_block, block[idx], &n_bytes_read);
1037 if (n_bytes_read < bytes_per_block)
1039 assert(n_bytes_read == bytes_per_block);
1040 write_block(current_offset, n_bytes_read,
1041 block[!idx], block[idx]);
1042 current_offset += n_bytes_read;
1047 if (n_bytes_read > 0) {
1049 size_t bytes_to_write;
1053 /* Make bytes_to_write the smallest multiple of l_c_m that
1054 is at least as large as n_bytes_read. */
1055 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1057 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1058 write_block(current_offset, bytes_to_write,
1059 block[!idx], block[idx]);
1060 current_offset += n_bytes_read;
1063 format_address(current_offset, '\n');
1065 if (limit_bytes_to_format && current_offset >= end_offset)
1071 /* Read a single byte into *C from the concatenation of the input files
1072 named in the global array FILE_LIST. On the first call to this
1073 function, the global variable IN_STREAM is expected to be an open
1074 stream associated with the input file INPUT_FILENAME. If IN_STREAM
1075 is at end-of-file, close it and update the global variables IN_STREAM
1076 and INPUT_FILENAME so they correspond to the next file in the list.
1077 Then try to read a byte from the newly opened file. Repeat if
1078 necessary until EOF is reached for the last file in FILE_LIST, then
1079 set *C to EOF and return. Subsequent calls do likewise. */
1084 while (in_stream) { /* !EOF */
1085 *c = fgetc(in_stream);
1094 /* Read N bytes into BLOCK from the concatenation of the input files
1095 named in the global array FILE_LIST. On the first call to this
1096 function, the global variable IN_STREAM is expected to be an open
1097 stream associated with the input file INPUT_FILENAME. If all N
1098 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1099 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1100 read the remaining bytes from the newly opened file. Repeat if
1101 necessary until EOF is reached for the last file in FILE_LIST.
1102 On subsequent calls, don't modify BLOCK and return zero. Set
1103 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1104 it will be detected through ferror when the stream is about to be
1105 closed. If there is an error, give a message but continue reading
1106 as usual and return nonzero. Otherwise return zero. */
1108 /* STRINGS mode. Find each "string constant" in the input.
1109 A string constant is a run of at least 'string_min' ASCII
1110 graphic (or formatting) characters terminated by a null.
1111 Based on a function written by Richard Stallman for a
1112 traditional version of od. */
1115 dump_strings(off_t address, off_t end_offset)
1117 size_t bufsize = MAX(100, string_min);
1118 char *buf = xmalloc(bufsize);
1124 /* See if the next 'string_min' chars are all printing chars. */
1126 if (limit_bytes_to_format && (end_offset - string_min <= address))
1129 while (!limit_bytes_to_format || address < end_offset) {
1131 bufsize += bufsize/8;
1132 buf = xrealloc(buf, bufsize);
1135 if (c < 0) { /* EOF */
1143 goto tryline; /* It isn't; give up on this string. */
1144 buf[i++] = c; /* String continues; store it all. */
1147 if (i < string_min) /* Too short! */
1150 /* If we get here, the string is all printable and NUL-terminated,
1151 * so print it. It is all in 'buf' and 'i' is its length. */
1153 format_address(address - i - 1, ' ');
1155 for (i = 0; (c = buf[i]); i++) {
1157 case '\007': fputs("\\a", stdout); break;
1158 case '\b': fputs("\\b", stdout); break;
1159 case '\f': fputs("\\f", stdout); break;
1160 case '\n': fputs("\\n", stdout); break;
1161 case '\r': fputs("\\r", stdout); break;
1162 case '\t': fputs("\\t", stdout); break;
1163 case '\v': fputs("\\v", stdout); break;
1164 default: putchar(c);
1170 /* We reach this point only if we search through
1171 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1177 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1178 int od_main(int argc, char **argv)
1180 static char const *const default_file_list[] = { "-", NULL };
1181 static const struct suffix_mult bkm[] = {
1206 OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
1208 #if ENABLE_GETOPT_LONG
1209 static const char od_longopts[] ALIGN1 =
1210 "skip-bytes\0" Required_argument "j"
1211 "address-radix\0" Required_argument "A"
1212 "read-bytes\0" Required_argument "N"
1213 "format\0" Required_argument "t"
1214 "output-duplicates\0" No_argument "v"
1215 "strings\0" Optional_argument "S"
1216 "width\0" Optional_argument "w"
1217 "traditional\0" No_argument "\xff"
1220 char *str_A, *str_N, *str_j, *str_S;
1222 llist_t *lst_t = NULL;
1225 /* The old-style 'pseudo starting address' to be printed in parentheses
1226 after any true address. */
1227 off_t pseudo_start = pseudo_start; // for gcc
1228 /* The number of input bytes to skip before formatting and writing. */
1229 off_t n_bytes_to_skip = 0;
1230 /* The offset of the first byte after the last byte to be formatted. */
1231 off_t end_offset = 0;
1232 /* The maximum number of bytes that will be formatted. */
1233 off_t max_bytes_to_format = 0;
1236 format_address = format_address_std;
1237 address_base_char = 'o';
1238 address_pad_len_char = '7';
1239 /* flag_dump_strings = 0; - already is */
1241 /* Parse command line */
1242 opt_complementary = "t::"; // list
1243 #if ENABLE_GETOPT_LONG
1244 applet_long_options = od_longopts;
1246 opt = getopt32(argv, "A:N:abcdfhij:lot:vxsS:"
1247 "w::", // -w with optional param
1248 // -S was -s and also had optional parameter
1249 // but in coreutils 6.3 it was renamed and now has
1250 // _mandatory_ parameter
1251 &str_A, &str_N, &str_j, &lst_t, &str_S, &str_w);
1255 static const char doxn[] ALIGN1 = "doxn";
1256 static const char doxn_address_base_char[] ALIGN1 = {
1257 'u', 'o', 'x', /* '?' fourth one is not important */
1259 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1260 '7', '7', '6', /* '?' */
1264 p = strchr(doxn, str_A[0]);
1266 bb_error_msg_and_die("bad output address radix "
1267 "'%c' (must be [doxn])", str_A[0]);
1269 if (pos == 3) format_address = format_address_none;
1270 address_base_char = doxn_address_base_char[pos];
1271 address_pad_len_char = doxn_address_pad_len_char[pos];
1274 limit_bytes_to_format = 1;
1275 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1277 if (opt & OPT_a) decode_format_string("a");
1278 if (opt & OPT_b) decode_format_string("oC");
1279 if (opt & OPT_c) decode_format_string("c");
1280 if (opt & OPT_d) decode_format_string("u2");
1281 if (opt & OPT_f) decode_format_string("fF");
1282 if (opt & OPT_h) decode_format_string("x2");
1283 if (opt & OPT_i) decode_format_string("d2");
1284 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1285 if (opt & OPT_l) decode_format_string("d4");
1286 if (opt & OPT_o) decode_format_string("o2");
1287 //if (opt & OPT_t)...
1289 decode_format_string(lst_t->data);
1290 lst_t = lst_t->link;
1292 if (opt & OPT_v) verbose = 1;
1293 if (opt & OPT_x) decode_format_string("x2");
1294 if (opt & OPT_s) decode_format_string("d2");
1297 string_min = xstrtou_sfx(str_S, 0, bkm);
1298 flag_dump_strings = 1;
1300 //if (opt & OPT_w)...
1301 //if (opt & OPT_traditional)...
1303 if (flag_dump_strings && n_specs > 0)
1304 bb_error_msg_and_die("no type may be specified when dumping strings");
1306 /* If the --traditional option is used, there may be from
1307 * 0 to 3 remaining command line arguments; handle each case
1309 * od [file] [[+]offset[.][b] [[+]label[.][b]]]
1310 * The offset and pseudo_start have the same syntax.
1312 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1313 * traditional syntax even if --traditional is not given. */
1315 #if ENABLE_GETOPT_LONG
1316 if (opt & OPT_traditional) {
1320 if (parse_old_offset(argv[0], &o1)) {
1321 n_bytes_to_skip = o1;
1325 } else if (argc == 2) {
1326 if (parse_old_offset(argv[0], &o1)
1327 && parse_old_offset(argv[1], &o2)
1329 n_bytes_to_skip = o1;
1330 flag_pseudo_start = 1;
1334 } else if (parse_old_offset(argv[1], &o2)) {
1335 n_bytes_to_skip = o2;
1340 bb_error_msg_and_die("invalid second operand "
1341 "in compatibility mode '%s'", argv[1]);
1343 } else if (argc == 3) {
1344 if (parse_old_offset(argv[1], &o1)
1345 && parse_old_offset(argv[2], &o2)
1347 n_bytes_to_skip = o1;
1348 flag_pseudo_start = 1;
1354 bb_error_msg_and_die("in compatibility mode "
1355 "the last two arguments must be offsets");
1357 } else if (argc > 3) {
1358 bb_error_msg_and_die("compatibility mode supports "
1359 "at most three arguments");
1362 if (flag_pseudo_start) {
1363 if (format_address == format_address_none) {
1364 address_base_char = 'o';
1365 address_pad_len_char = '7';
1366 format_address = format_address_paren;
1368 format_address = format_address_label;
1373 if (limit_bytes_to_format) {
1374 end_offset = n_bytes_to_skip + max_bytes_to_format;
1375 if (end_offset < n_bytes_to_skip)
1376 bb_error_msg_and_die("skip-bytes + read-bytes is too large");
1380 decode_format_string("o2");
1384 /* If no files were listed on the command line,
1385 set the global pointer FILE_LIST so that it
1386 references the null-terminated list of one name: "-". */
1387 file_list = default_file_list;
1389 /* Set the global pointer FILE_LIST so that it
1390 references the first file-argument on the command-line. */
1391 file_list = (char const *const *) argv;
1394 /* open the first input file */
1396 /* skip over any unwanted header bytes */
1397 skip(n_bytes_to_skip);
1399 return EXIT_FAILURE;
1401 pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1403 /* Compute output block length. */
1406 if (opt & OPT_w) { /* -w: width */
1407 bytes_per_block = 32;
1409 bytes_per_block = xatou(str_w);
1410 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1411 bb_error_msg("warning: invalid width %u; using %d instead",
1412 (unsigned)bytes_per_block, l_c_m);
1413 bytes_per_block = l_c_m;
1416 bytes_per_block = l_c_m;
1417 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1418 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1422 for (i = 0; i < n_specs; i++) {
1423 printf("%d: fmt=\"%s\" width=%d\n",
1424 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1428 if (flag_dump_strings)
1429 dump_strings(n_bytes_to_skip, end_offset);
1431 dump(n_bytes_to_skip, end_offset);
1433 if (fclose(stdin) == EOF)
1434 bb_perror_msg_and_die(bb_msg_standard_input);