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 xxx\0";
391 // [12] because we take three 32bit stack slots anyway, and
392 // gcc is too dumb to initialize with constant stores,
393 // it copies initializer from rodata. Oh well.
394 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65410
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 xxx\0";
426 unsigned c = *(unsigned char *) block++;
459 buf[6] = (c >> 6 & 3) + '0';
460 buf[7] = (c >> 3 & 7) + '0';
461 buf[8] = (c & 7) + '0';
468 /* Given a list of one or more input filenames FILE_LIST, set the global
469 file pointer IN_STREAM and the global string INPUT_FILENAME to the
470 first one that can be successfully opened. Modify FILE_LIST to
471 reference the next filename in the list. A file name of "-" is
472 interpreted as standard input. If any file open fails, give an error
473 message and return nonzero. */
481 in_stream = fopen_or_warn_stdin(*file_list++);
488 if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N)
489 setbuf(in_stream, NULL);
492 /* Test whether there have been errors on in_stream, and close it if
493 it is not standard input. Return nonzero if there has been an error
494 on in_stream or stdout; return zero otherwise. This function will
495 report more than one error only if both a read and a write error
496 have occurred. IN_ERRNO, if nonzero, is the error number
497 corresponding to the most recent action for IN_STREAM. */
500 check_and_close(void)
503 if (ferror(in_stream)) {
504 bb_error_msg("%s: read error", (in_stream == stdin)
505 ? bb_msg_standard_input
510 fclose_if_not_stdin(in_stream);
514 if (ferror(stdout)) {
515 bb_error_msg_and_die(bb_msg_write_error);
519 /* If S points to a single valid modern od format string, put
520 a description of that format in *TSPEC, return pointer to
521 character following the just-decoded format.
522 For example, if S were "d4afL", we will return a rtp to "afL"
525 fmt = SIGNED_DECIMAL;
526 size = INT or LONG; (whichever integral_type_size[4] resolves to)
527 print_function = print_int; (assuming size == INT)
528 fmt_string = "%011d%c";
530 S_ORIG is solely for reporting errors. It should be the full format
533 static NOINLINE const char *
534 decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
536 enum size_spec size_spec;
538 enum output_format fmt;
541 char *fmt_string = NULL;
542 void (*print_function) (size_t, const char *, const char *);
544 unsigned field_width = 0;
552 static const char CSIL[] ALIGN1 = "CSIL";
555 p = strchr(CSIL, *s);
556 /* if *s == NUL, p != NULL! Testcase: "od -tx" */
557 if (!p || *p == '\0') {
560 size = bb_strtou(s, &end, 0);
562 || MAX_INTEGRAL_TYPE_SIZE < size
563 || integral_type_size[size] == NO_SIZE
565 bb_error_msg_and_die("invalid type string '%s'; "
566 "%u-byte %s type is not supported",
567 s_orig, size, "integral");
572 static const uint8_t CSIL_sizeof[4] = {
578 size = CSIL_sizeof[p - CSIL];
579 s++; /* skip C/S/I/L */
582 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
583 ((Spec) == LONG_LONG ? (Max_format) \
584 : ((Spec) == LONG ? (Long_format) : (Min_format)))
586 #define FMT_BYTES_ALLOCATED 9
587 size_spec = integral_type_size[size];
590 static const char doux[] ALIGN1 = "doux";
591 static const char doux_fmt_letter[][4] = {
592 "lld", "llo", "llu", "llx"
594 static const enum output_format doux_fmt[] = {
600 static const uint8_t *const doux_bytes_to_XXX[] = {
601 bytes_to_signed_dec_digits,
603 bytes_to_unsigned_dec_digits,
606 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
613 pos = strchr(doux, c) - doux;
615 field_width = doux_bytes_to_XXX[pos][size];
616 p = doux_fmt_letter[pos] + 2;
617 if (size_spec == LONG) p--;
618 if (size_spec == LONG_LONG) p -= 2;
619 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
624 print_function = (fmt == SIGNED_DECIMAL
629 print_function = (fmt == SIGNED_DECIMAL
634 print_function = print_int;
637 print_function = print_long;
639 default: /* case LONG_LONG: */
640 print_function = print_long_long;
647 static const char FDL[] ALIGN1 = "FDL";
649 fmt = FLOATING_POINT;
653 size = sizeof(double);
655 size = bb_strtou(s, &end, 0);
656 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
657 || fp_type_size[size] == NO_SIZE
659 bb_error_msg_and_die("invalid type string '%s'; "
660 "%u-byte %s type is not supported",
661 s_orig, size, "floating point");
666 static const uint8_t FDL_sizeof[] = {
669 sizeof(longdouble_t),
672 size = FDL_sizeof[p - FDL];
675 size_spec = fp_type_size[size];
679 print_function = print_float;
680 field_width = FLT_DIG + 8;
681 /* Don't use %#e; not all systems support it. */
682 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
685 print_function = print_double;
686 field_width = DBL_DIG + 8;
687 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
689 default: /* case FLOAT_LONG_DOUBLE: */
690 print_function = print_long_double;
691 field_width = LDBL_DIG + 8;
692 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
700 fmt = NAMED_CHARACTER;
702 print_function = print_named_ascii;
709 print_function = print_ascii;
713 bb_error_msg_and_die("invalid character '%c' "
714 "in type string '%s'", *s, s_orig);
717 tspec->size = size_spec;
719 tspec->print_function = print_function;
720 tspec->fmt_string = fmt_string;
722 tspec->field_width = field_width;
723 tspec->hexl_mode_trailer = (*s == 'z');
724 if (tspec->hexl_mode_trailer)
730 /* Decode the modern od format string S. Append the decoded
731 representation to the global array SPEC, reallocating SPEC if
735 decode_format_string(const char *s)
737 const char *s_orig = s;
743 next = decode_one_format(s_orig, s, &tspec);
747 spec = xrealloc_vector(spec, 4, n_specs);
748 memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
753 /* Given a list of one or more input filenames FILE_LIST, set the global
754 file pointer IN_STREAM to position N_SKIP in the concatenation of
755 those files. If any file operation fails or if there are fewer than
756 N_SKIP bytes in the combined input, give an error message and return
757 nonzero. When possible, use seek rather than read operations to
758 advance IN_STREAM. */
766 while (in_stream) { /* !EOF */
767 struct stat file_stats;
769 /* First try seeking. For large offsets, this extra work is
770 worthwhile. If the offset is below some threshold it may be
771 more efficient to move the pointer by reading. There are two
772 issues when trying to seek:
773 - the file must be seekable.
774 - before seeking to the specified position, make sure
775 that the new position is in the current file.
776 Try to do that by getting file's size using fstat.
777 But that will work only for regular files. */
779 /* The st_size field is valid only for regular files
780 (and for symbolic links, which cannot occur here).
781 If the number of bytes left to skip is at least
782 as large as the size of the current file, we can
783 decrement n_skip and go on to the next file. */
784 if (fstat(fileno(in_stream), &file_stats) == 0
785 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
787 if (file_stats.st_size < n_skip) {
788 n_skip -= file_stats.st_size;
789 /* take "check & close / open_next" route */
791 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
796 /* If it's not a regular file with positive size,
797 position the file pointer by reading. */
799 size_t n_bytes_to_read = 1024;
803 if (n_skip < n_bytes_to_read)
804 n_bytes_to_read = n_skip;
805 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
806 n_skip -= n_bytes_read;
807 if (n_bytes_read != n_bytes_to_read)
808 break; /* EOF on this file or error */
819 bb_error_msg_and_die("can't skip past end of combined input");
823 typedef void FN_format_address(off_t address, char c);
826 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
830 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
831 /* Corresponds to 'x' above */
832 #define address_base_char address_fmt[sizeof(address_fmt)-3]
833 /* Corresponds to 'n' above */
834 #define address_pad_len_char address_fmt[2]
837 format_address_std(off_t address, char c)
839 /* Corresponds to 'c' */
840 address_fmt[sizeof(address_fmt)-2] = c;
841 printf(address_fmt, address);
845 /* only used with --traditional */
847 format_address_paren(off_t address, char c)
850 format_address_std(address, ')');
855 format_address_label(off_t address, char c)
857 format_address_std(address, ' ');
858 format_address_paren(address + pseudo_offset, c);
863 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
867 unsigned c = *(unsigned char *) block++;
868 c = (ISPRINT(c) ? c : '.');
874 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
875 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
876 CURR_BLOCK in the concatenation of input files, and it is printed
877 (optionally) only before the output line associated with the first
878 format spec. When duplicate blocks are being abbreviated, the output
879 for a sequence of identical input blocks is the output for the first
880 block followed by an asterisk alone on a line. It is valid to compare
881 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
882 That condition may be false only for the last input block -- and then
883 only when it has not been padded to length BYTES_PER_BLOCK. */
886 write_block(off_t current_offset, size_t n_bytes,
887 const char *prev_block, const char *curr_block)
889 static char first = 1;
890 static char prev_pair_equal = 0;
893 if (!(option_mask32 & OPT_v)
895 && n_bytes == bytes_per_block
896 && memcmp(prev_block, curr_block, bytes_per_block) == 0
898 if (prev_pair_equal) {
899 /* The two preceding blocks were equal, and the current
900 block is the same as the last one, so print nothing. */
908 for (i = 0; i < n_specs; i++) {
910 format_address(current_offset, '\0');
912 printf("%*s", address_pad_len_char - '0', "");
913 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
914 if (spec[i].hexl_mode_trailer) {
915 /* space-pad out to full line width, then dump the trailer */
916 unsigned datum_width = width_bytes[spec[i].size];
917 unsigned blank_fields = (bytes_per_block - n_bytes) / datum_width;
918 unsigned field_width = spec[i].field_width + 1;
919 printf("%*s", blank_fields * field_width, "");
920 dump_hexl_mode_trailer(n_bytes, curr_block);
928 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
930 assert(0 < n && n <= bytes_per_block);
932 *n_bytes_in_buffer = 0;
937 while (in_stream != NULL) { /* EOF. */
941 n_needed = n - *n_bytes_in_buffer;
942 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
943 *n_bytes_in_buffer += n_read;
944 if (n_read == n_needed)
946 /* error check is done in check_and_close */
952 /* Return the least common multiple of the sizes associated
953 with the format specs. */
961 for (i = 0; i < n_specs; i++)
962 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
966 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
967 formatted block to standard output, and repeat until the specified
968 maximum number of bytes has been read or until all input has been
969 processed. If the last block read is smaller than BYTES_PER_BLOCK
970 and its size is not a multiple of the size associated with a format
971 spec, extend the input block with zero bytes until its length is a
972 multiple of all format spec sizes. Write the final block. Finally,
973 write on a line by itself the offset of the byte after the last byte
977 dump(off_t current_offset, off_t end_offset)
983 block[0] = xmalloc(2 * bytes_per_block);
984 block[1] = block[0] + bytes_per_block;
987 if (option_mask32 & OPT_N) {
990 if (current_offset >= end_offset) {
994 n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block);
995 read_block(n_needed, block[idx], &n_bytes_read);
996 if (n_bytes_read < bytes_per_block)
998 assert(n_bytes_read == bytes_per_block);
999 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1000 current_offset += n_bytes_read;
1005 read_block(bytes_per_block, block[idx], &n_bytes_read);
1006 if (n_bytes_read < bytes_per_block)
1008 assert(n_bytes_read == bytes_per_block);
1009 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]);
1010 current_offset += n_bytes_read;
1015 if (n_bytes_read > 0) {
1017 size_t bytes_to_write;
1021 /* Make bytes_to_write the smallest multiple of l_c_m that
1022 is at least as large as n_bytes_read. */
1023 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1025 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1026 write_block(current_offset, bytes_to_write,
1027 block[idx ^ 1], block[idx]);
1028 current_offset += n_bytes_read;
1031 format_address(current_offset, '\n');
1033 if ((option_mask32 & OPT_N) && current_offset >= end_offset)
1039 /* Read N bytes into BLOCK from the concatenation of the input files
1040 named in the global array FILE_LIST. On the first call to this
1041 function, the global variable IN_STREAM is expected to be an open
1042 stream associated with the input file INPUT_FILENAME. If all N
1043 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1044 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1045 read the remaining bytes from the newly opened file. Repeat if
1046 necessary until EOF is reached for the last file in FILE_LIST.
1047 On subsequent calls, don't modify BLOCK and return zero. Set
1048 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1049 it will be detected through ferror when the stream is about to be
1050 closed. If there is an error, give a message but continue reading
1051 as usual and return nonzero. Otherwise return zero. */
1053 /* STRINGS mode. Find each "string constant" in the input.
1054 A string constant is a run of at least 'string_min' ASCII
1055 graphic (or formatting) characters terminated by a null.
1056 Based on a function written by Richard Stallman for a
1057 traditional version of od. */
1060 dump_strings(off_t address, off_t end_offset)
1062 unsigned bufsize = MAX(100, string_min);
1063 unsigned char *buf = xmalloc(bufsize);
1069 /* See if the next 'string_min' chars are all printing chars. */
1071 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
1074 while (!(option_mask32 & OPT_N) || address < end_offset) {
1076 bufsize += bufsize/8;
1077 buf = xrealloc(buf, bufsize);
1080 while (in_stream) { /* !EOF */
1081 c = fgetc(in_stream);
1094 goto tryline; /* It isn't; give up on this string. */
1095 buf[i++] = c; /* String continues; store it all. */
1098 if (i < string_min) /* Too short! */
1101 /* If we get here, the string is all printable and NUL-terminated */
1103 format_address(address - i - 1, ' ');
1105 for (i = 0; (c = buf[i]); i++) {
1107 case '\007': fputs("\\a", stdout); break;
1108 case '\b': fputs("\\b", stdout); break;
1109 case '\f': fputs("\\f", stdout); break;
1110 case '\n': fputs("\\n", stdout); break;
1111 case '\r': fputs("\\r", stdout); break;
1112 case '\t': fputs("\\t", stdout); break;
1113 case '\v': fputs("\\v", stdout); break;
1114 default: putchar(c);
1120 /* We reach this point only if we search through
1121 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1127 #if ENABLE_LONG_OPTS
1128 /* If S is a valid traditional offset specification with an optional
1129 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
1132 parse_old_offset(const char *s, off_t *offset)
1134 static const struct suffix_mult Bb[] = {
1142 /* Skip over any leading '+'. */
1143 if (s[0] == '+') ++s;
1144 if (!isdigit(s[0])) return 0; /* not a number */
1146 /* Determine the radix we'll use to interpret S. If there is a '.',
1147 * it's decimal, otherwise, if the string begins with '0X'or '0x',
1148 * it's hexadecimal, else octal. */
1152 p[0] = '\0'; /* cheating */
1154 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1157 *offset = xstrtooff_sfx(s, radix, Bb);
1160 return (*offset >= 0);
1164 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1165 int od_main(int argc UNUSED_PARAM, char **argv)
1167 #if ENABLE_LONG_OPTS
1168 static const char od_longopts[] ALIGN1 =
1169 "skip-bytes\0" Required_argument "j"
1170 "address-radix\0" Required_argument "A"
1171 "read-bytes\0" Required_argument "N"
1172 "format\0" Required_argument "t"
1173 "output-duplicates\0" No_argument "v"
1174 /* Yes, it's true: -S NUM, but --strings[=NUM]!
1175 * that is, NUM is mandatory for -S but optional for --strings!
1177 "strings\0" Optional_argument "S"
1178 "width\0" Optional_argument "w"
1179 "traditional\0" No_argument "\xff"
1182 const char *str_A, *str_N, *str_j, *str_S = "3";
1183 llist_t *lst_t = NULL;
1186 /* The number of input bytes to skip before formatting and writing. */
1187 off_t n_bytes_to_skip = 0;
1188 /* The offset of the first byte after the last byte to be formatted. */
1189 off_t end_offset = 0;
1190 /* The maximum number of bytes that will be formatted. */
1191 off_t max_bytes_to_format = 0;
1194 format_address = format_address_std;
1195 address_base_char = 'o';
1196 address_pad_len_char = '7';
1198 /* Parse command line */
1199 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1200 #if ENABLE_LONG_OPTS
1201 applet_long_options = od_longopts;
1203 opt = OD_GETOPT32();
1206 static const char doxn[] ALIGN1 = "doxn";
1207 static const char doxn_address_base_char[] ALIGN1 = {
1208 'u', 'o', 'x', /* '?' fourth one is not important */
1210 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1211 '7', '7', '6', /* '?' */
1215 p = strchr(doxn, str_A[0]);
1217 bb_error_msg_and_die("bad output address radix "
1218 "'%c' (must be [doxn])", str_A[0]);
1220 if (pos == 3) format_address = format_address_none;
1221 address_base_char = doxn_address_base_char[pos];
1222 address_pad_len_char = doxn_address_pad_len_char[pos];
1225 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm_suffixes);
1227 if (opt & OPT_a) decode_format_string("a");
1228 if (opt & OPT_b) decode_format_string("oC");
1229 if (opt & OPT_c) decode_format_string("c");
1230 if (opt & OPT_d) decode_format_string("u2");
1231 if (opt & OPT_f) decode_format_string("fF");
1232 if (opt & OPT_h) decode_format_string("x2");
1233 if (opt & OPT_i) decode_format_string("d2");
1234 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm_suffixes);
1235 if (opt & OPT_l) decode_format_string("d4");
1236 if (opt & OPT_o) decode_format_string("o2");
1238 decode_format_string(llist_pop(&lst_t));
1240 if (opt & OPT_x) decode_format_string("x2");
1241 if (opt & OPT_s) decode_format_string("d2");
1243 string_min = xstrtou_sfx(str_S, 0, bkm_suffixes);
1247 //if ((option_mask32 & OPT_S) && n_specs > 0)
1248 // bb_error_msg_and_die("no type may be specified when dumping strings");
1250 /* If the --traditional option is used, there may be from
1251 * 0 to 3 remaining command line arguments; handle each case
1253 * od [FILE] [[+]OFFSET[.][b] [[+]LABEL[.][b]]]
1254 * The offset and pseudo_start have the same syntax.
1256 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1257 * traditional syntax even if --traditional is not given. */
1259 #if ENABLE_LONG_OPTS
1260 if (opt & OPT_traditional) {
1262 off_t pseudo_start = -1;
1265 if (!argv[1]) { /* one arg */
1266 if (parse_old_offset(argv[0], &o1)) {
1267 /* od --traditional OFFSET */
1268 n_bytes_to_skip = o1;
1271 /* od --traditional FILE */
1272 } else if (!argv[2]) { /* two args */
1273 if (parse_old_offset(argv[0], &o1)
1274 && parse_old_offset(argv[1], &o2)
1276 /* od --traditional OFFSET LABEL */
1277 n_bytes_to_skip = o1;
1280 } else if (parse_old_offset(argv[1], &o2)) {
1281 /* od --traditional FILE OFFSET */
1282 n_bytes_to_skip = o2;
1285 bb_error_msg_and_die("invalid second argument '%s'", argv[1]);
1287 } else if (!argv[3]) { /* three args */
1288 if (parse_old_offset(argv[1], &o1)
1289 && parse_old_offset(argv[2], &o2)
1291 /* od --traditional FILE OFFSET LABEL */
1292 n_bytes_to_skip = o1;
1296 bb_error_msg_and_die("the last two arguments must be offsets");
1298 } else { /* >3 args */
1299 bb_error_msg_and_die("too many arguments");
1302 if (pseudo_start >= 0) {
1303 if (format_address == format_address_none) {
1304 address_base_char = 'o';
1305 address_pad_len_char = '7';
1306 format_address = format_address_paren;
1308 format_address = format_address_label;
1310 pseudo_offset = pseudo_start - n_bytes_to_skip;
1313 /* else: od --traditional (without args) */
1317 if (option_mask32 & OPT_N) {
1318 end_offset = n_bytes_to_skip + max_bytes_to_format;
1319 if (end_offset < n_bytes_to_skip)
1320 bb_error_msg_and_die("SKIP + SIZE is too large");
1324 decode_format_string("o2");
1325 /*n_specs = 1; - done by decode_format_string */
1328 /* If no files were listed on the command line,
1329 set the global pointer FILE_LIST so that it
1330 references the null-terminated list of one name: "-". */
1331 file_list = bb_argv_dash;
1333 /* Set the global pointer FILE_LIST so that it
1334 references the first file-argument on the command-line. */
1335 file_list = (char const *const *) argv;
1338 /* Open the first input file */
1340 /* Skip over any unwanted header bytes */
1341 skip(n_bytes_to_skip);
1343 return EXIT_FAILURE;
1345 /* Compute output block length */
1348 if (opt & OPT_w) { /* -w: width */
1349 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1350 bb_error_msg("warning: invalid width %u; using %d instead",
1351 (unsigned)bytes_per_block, l_c_m);
1352 bytes_per_block = l_c_m;
1355 bytes_per_block = l_c_m;
1356 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1357 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1361 for (i = 0; i < n_specs; i++) {
1362 printf("%d: fmt=\"%s\" width=%d\n",
1363 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1367 if (option_mask32 & OPT_S)
1368 dump_strings(n_bytes_to_skip, end_offset);
1370 dump(n_bytes_to_skip, end_offset);
1373 bb_perror_msg_and_die(bb_msg_standard_input);