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;
555 static const char CSIL[] ALIGN1 = "CSIL";
558 p = strchr(CSIL, *s);
559 /* if *s == NUL, p != NULL! Testcase: "od -tx" */
560 if (!p || *p == '\0') {
563 size = bb_strtou(s, &end, 0);
565 || MAX_INTEGRAL_TYPE_SIZE < size
566 || integral_type_size[size] == NO_SIZE
568 bb_error_msg_and_die("invalid type string '%s'; "
569 "%u-byte %s type is not supported",
570 s_orig, size, "integral");
575 static const uint8_t CSIL_sizeof[4] = {
581 size = CSIL_sizeof[p - CSIL];
582 s++; /* skip C/S/I/L */
585 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
586 ((Spec) == LONG_LONG ? (Max_format) \
587 : ((Spec) == LONG ? (Long_format) : (Min_format)))
589 #define FMT_BYTES_ALLOCATED 9
590 size_spec = integral_type_size[size];
593 static const char doux[] ALIGN1 = "doux";
594 static const char doux_fmt_letter[][4] = {
595 "lld", "llo", "llu", "llx"
597 static const enum output_format doux_fmt[] = {
603 static const uint8_t *const doux_bytes_to_XXX[] = {
604 bytes_to_signed_dec_digits,
606 bytes_to_unsigned_dec_digits,
609 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
616 pos = strchr(doux, c) - doux;
618 field_width = doux_bytes_to_XXX[pos][size];
619 p = doux_fmt_letter[pos] + 2;
620 if (size_spec == LONG) p--;
621 if (size_spec == LONG_LONG) p -= 2;
622 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
627 print_function = (fmt == SIGNED_DECIMAL
632 print_function = (fmt == SIGNED_DECIMAL
637 print_function = print_int;
640 print_function = print_long;
642 default: /* case LONG_LONG: */
643 print_function = print_long_long;
650 static const char FDL[] ALIGN1 = "FDL";
652 fmt = FLOATING_POINT;
656 size = sizeof(double);
658 size = bb_strtou(s, &end, 0);
659 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
660 || fp_type_size[size] == NO_SIZE
662 bb_error_msg_and_die("invalid type string '%s'; "
663 "%u-byte %s type is not supported",
664 s_orig, size, "floating point");
669 static const uint8_t FDL_sizeof[] = {
672 sizeof(longdouble_t),
675 size = FDL_sizeof[p - FDL];
678 size_spec = fp_type_size[size];
682 print_function = print_float;
683 field_width = FLT_DIG + 8;
684 /* Don't use %#e; not all systems support it. */
685 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
688 print_function = print_double;
689 field_width = DBL_DIG + 8;
690 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
692 default: /* case FLOAT_LONG_DOUBLE: */
693 print_function = print_long_double;
694 field_width = LDBL_DIG + 8;
695 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
703 fmt = NAMED_CHARACTER;
705 print_function = print_named_ascii;
712 print_function = print_ascii;
716 bb_error_msg_and_die("invalid character '%c' "
717 "in type string '%s'", *s, s_orig);
720 tspec->size = size_spec;
722 tspec->print_function = print_function;
723 tspec->fmt_string = fmt_string;
725 tspec->field_width = field_width;
726 tspec->hexl_mode_trailer = (*s == 'z');
727 if (tspec->hexl_mode_trailer)
733 /* Decode the modern od format string S. Append the decoded
734 representation to the global array SPEC, reallocating SPEC if
738 decode_format_string(const char *s)
740 const char *s_orig = s;
746 next = decode_one_format(s_orig, s, &tspec);
750 spec = xrealloc_vector(spec, 4, n_specs);
751 memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
756 /* Given a list of one or more input filenames FILE_LIST, set the global
757 file pointer IN_STREAM to position N_SKIP in the concatenation of
758 those files. If any file operation fails or if there are fewer than
759 N_SKIP bytes in the combined input, give an error message and return
760 nonzero. When possible, use seek rather than read operations to
761 advance IN_STREAM. */
769 while (in_stream) { /* !EOF */
770 struct stat file_stats;
772 /* First try seeking. For large offsets, this extra work is
773 worthwhile. If the offset is below some threshold it may be
774 more efficient to move the pointer by reading. There are two
775 issues when trying to seek:
776 - the file must be seekable.
777 - before seeking to the specified position, make sure
778 that the new position is in the current file.
779 Try to do that by getting file's size using fstat.
780 But that will work only for regular files. */
782 /* The st_size field is valid only for regular files
783 (and for symbolic links, which cannot occur here).
784 If the number of bytes left to skip is at least
785 as large as the size of the current file, we can
786 decrement n_skip and go on to the next file. */
787 if (fstat(fileno(in_stream), &file_stats) == 0
788 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
790 if (file_stats.st_size < n_skip) {
791 n_skip -= file_stats.st_size;
792 /* take "check & close / open_next" route */
794 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
799 /* If it's not a regular file with positive size,
800 position the file pointer by reading. */
802 size_t n_bytes_to_read = 1024;
806 if (n_skip < n_bytes_to_read)
807 n_bytes_to_read = n_skip;
808 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
809 n_skip -= n_bytes_read;
810 if (n_bytes_read != n_bytes_to_read)
811 break; /* EOF on this file or error */
822 bb_error_msg_and_die("can't skip past end of combined input");
826 typedef void FN_format_address(off_t address, char c);
829 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
833 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
834 /* Corresponds to 'x' above */
835 #define address_base_char address_fmt[sizeof(address_fmt)-3]
836 /* Corresponds to 'n' above */
837 #define address_pad_len_char address_fmt[2]
840 format_address_std(off_t address, char c)
842 /* Corresponds to 'c' */
843 address_fmt[sizeof(address_fmt)-2] = c;
844 printf(address_fmt, address);
848 /* only used with --traditional */
850 format_address_paren(off_t address, char c)
853 format_address_std(address, ')');
858 format_address_label(off_t address, char c)
860 format_address_std(address, ' ');
861 format_address_paren(address + pseudo_offset, c);
866 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
870 unsigned c = *(unsigned char *) block++;
871 c = (ISPRINT(c) ? c : '.');
877 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
878 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
879 CURR_BLOCK in the concatenation of input files, and it is printed
880 (optionally) only before the output line associated with the first
881 format spec. When duplicate blocks are being abbreviated, the output
882 for a sequence of identical input blocks is the output for the first
883 block followed by an asterisk alone on a line. It is valid to compare
884 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
885 That condition may be false only for the last input block -- and then
886 only when it has not been padded to length BYTES_PER_BLOCK. */
889 write_block(off_t current_offset, size_t n_bytes,
890 const char *prev_block, const char *curr_block)
892 static char first = 1;
893 static char prev_pair_equal = 0;
896 if (!(option_mask32 & OPT_v)
898 && n_bytes == bytes_per_block
899 && memcmp(prev_block, curr_block, bytes_per_block) == 0
901 if (prev_pair_equal) {
902 /* The two preceding blocks were equal, and the current
903 block is the same as the last one, so print nothing. */
911 for (i = 0; i < n_specs; i++) {
913 format_address(current_offset, '\0');
915 printf("%*s", address_pad_len_char - '0', "");
916 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
917 if (spec[i].hexl_mode_trailer) {
918 /* space-pad out to full line width, then dump the trailer */
919 int datum_width = width_bytes[spec[i].size];
920 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
921 int field_width = spec[i].field_width + 1;
922 printf("%*s", blank_fields * field_width, "");
923 dump_hexl_mode_trailer(n_bytes, curr_block);
931 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
933 assert(0 < n && n <= bytes_per_block);
935 *n_bytes_in_buffer = 0;
940 while (in_stream != NULL) { /* EOF. */
944 n_needed = n - *n_bytes_in_buffer;
945 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
946 *n_bytes_in_buffer += n_read;
947 if (n_read == n_needed)
949 /* error check is done in check_and_close */
955 /* Return the least common multiple of the sizes associated
956 with the format specs. */
964 for (i = 0; i < n_specs; i++)
965 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
969 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
970 formatted block to standard output, and repeat until the specified
971 maximum number of bytes has been read or until all input has been
972 processed. If the last block read is smaller than BYTES_PER_BLOCK
973 and its size is not a multiple of the size associated with a format
974 spec, extend the input block with zero bytes until its length is a
975 multiple of all format spec sizes. Write the final block. Finally,
976 write on a line by itself the offset of the byte after the last byte
980 dump(off_t current_offset, off_t end_offset)
986 block[0] = xmalloc(2*bytes_per_block);
987 block[1] = block[0] + bytes_per_block;
990 if (option_mask32 & OPT_N) {
993 if (current_offset >= end_offset) {
997 n_needed = MIN(end_offset - current_offset,
998 (off_t) bytes_per_block);
999 read_block(n_needed, block[idx], &n_bytes_read);
1000 if (n_bytes_read < bytes_per_block)
1002 assert(n_bytes_read == bytes_per_block);
1003 write_block(current_offset, n_bytes_read,
1004 block[!idx], block[idx]);
1005 current_offset += n_bytes_read;
1010 read_block(bytes_per_block, block[idx], &n_bytes_read);
1011 if (n_bytes_read < bytes_per_block)
1013 assert(n_bytes_read == bytes_per_block);
1014 write_block(current_offset, n_bytes_read,
1015 block[!idx], block[idx]);
1016 current_offset += n_bytes_read;
1021 if (n_bytes_read > 0) {
1023 size_t bytes_to_write;
1027 /* Make bytes_to_write the smallest multiple of l_c_m that
1028 is at least as large as n_bytes_read. */
1029 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1031 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1032 write_block(current_offset, bytes_to_write,
1033 block[!idx], block[idx]);
1034 current_offset += n_bytes_read;
1037 format_address(current_offset, '\n');
1039 if ((option_mask32 & OPT_N) && current_offset >= end_offset)
1045 /* Read N bytes into BLOCK from the concatenation of the input files
1046 named in the global array FILE_LIST. On the first call to this
1047 function, the global variable IN_STREAM is expected to be an open
1048 stream associated with the input file INPUT_FILENAME. If all N
1049 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1050 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1051 read the remaining bytes from the newly opened file. Repeat if
1052 necessary until EOF is reached for the last file in FILE_LIST.
1053 On subsequent calls, don't modify BLOCK and return zero. Set
1054 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1055 it will be detected through ferror when the stream is about to be
1056 closed. If there is an error, give a message but continue reading
1057 as usual and return nonzero. Otherwise return zero. */
1059 /* STRINGS mode. Find each "string constant" in the input.
1060 A string constant is a run of at least 'string_min' ASCII
1061 graphic (or formatting) characters terminated by a null.
1062 Based on a function written by Richard Stallman for a
1063 traditional version of od. */
1066 dump_strings(off_t address, off_t end_offset)
1068 unsigned bufsize = MAX(100, string_min);
1069 unsigned char *buf = xmalloc(bufsize);
1075 /* See if the next 'string_min' chars are all printing chars. */
1077 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
1080 while (!(option_mask32 & OPT_N) || address < end_offset) {
1082 bufsize += bufsize/8;
1083 buf = xrealloc(buf, bufsize);
1086 while (in_stream) { /* !EOF */
1087 c = fgetc(in_stream);
1100 goto tryline; /* It isn't; give up on this string. */
1101 buf[i++] = c; /* String continues; store it all. */
1104 if (i < string_min) /* Too short! */
1107 /* If we get here, the string is all printable and NUL-terminated */
1109 format_address(address - i - 1, ' ');
1111 for (i = 0; (c = buf[i]); i++) {
1113 case '\007': fputs("\\a", stdout); break;
1114 case '\b': fputs("\\b", stdout); break;
1115 case '\f': fputs("\\f", stdout); break;
1116 case '\n': fputs("\\n", stdout); break;
1117 case '\r': fputs("\\r", stdout); break;
1118 case '\t': fputs("\\t", stdout); break;
1119 case '\v': fputs("\\v", stdout); break;
1120 default: putchar(c);
1126 /* We reach this point only if we search through
1127 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1133 #if ENABLE_LONG_OPTS
1134 /* If S is a valid traditional offset specification with an optional
1135 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
1138 parse_old_offset(const char *s, off_t *offset)
1140 static const struct suffix_mult Bb[] = {
1148 /* Skip over any leading '+'. */
1149 if (s[0] == '+') ++s;
1150 if (!isdigit(s[0])) return 0; /* not a number */
1152 /* Determine the radix we'll use to interpret S. If there is a '.',
1153 * it's decimal, otherwise, if the string begins with '0X'or '0x',
1154 * it's hexadecimal, else octal. */
1158 p[0] = '\0'; /* cheating */
1160 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1163 *offset = xstrtooff_sfx(s, radix, Bb);
1166 return (*offset >= 0);
1170 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1171 int od_main(int argc UNUSED_PARAM, char **argv)
1173 static const struct suffix_mult bkm[] = {
1179 #if ENABLE_LONG_OPTS
1180 static const char od_longopts[] ALIGN1 =
1181 "skip-bytes\0" Required_argument "j"
1182 "address-radix\0" Required_argument "A"
1183 "read-bytes\0" Required_argument "N"
1184 "format\0" Required_argument "t"
1185 "output-duplicates\0" No_argument "v"
1186 "strings\0" Optional_argument "S"
1187 "width\0" Optional_argument "w"
1188 "traditional\0" No_argument "\xff"
1191 char *str_A, *str_N, *str_j, *str_S;
1192 llist_t *lst_t = NULL;
1195 /* The number of input bytes to skip before formatting and writing. */
1196 off_t n_bytes_to_skip = 0;
1197 /* The offset of the first byte after the last byte to be formatted. */
1198 off_t end_offset = 0;
1199 /* The maximum number of bytes that will be formatted. */
1200 off_t max_bytes_to_format = 0;
1203 format_address = format_address_std;
1204 address_base_char = 'o';
1205 address_pad_len_char = '7';
1207 /* Parse command line */
1208 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1209 #if ENABLE_LONG_OPTS
1210 applet_long_options = od_longopts;
1212 opt = OD_GETOPT32();
1215 static const char doxn[] ALIGN1 = "doxn";
1216 static const char doxn_address_base_char[] ALIGN1 = {
1217 'u', 'o', 'x', /* '?' fourth one is not important */
1219 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1220 '7', '7', '6', /* '?' */
1224 p = strchr(doxn, str_A[0]);
1226 bb_error_msg_and_die("bad output address radix "
1227 "'%c' (must be [doxn])", str_A[0]);
1229 if (pos == 3) format_address = format_address_none;
1230 address_base_char = doxn_address_base_char[pos];
1231 address_pad_len_char = doxn_address_pad_len_char[pos];
1234 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1236 if (opt & OPT_a) decode_format_string("a");
1237 if (opt & OPT_b) decode_format_string("oC");
1238 if (opt & OPT_c) decode_format_string("c");
1239 if (opt & OPT_d) decode_format_string("u2");
1240 if (opt & OPT_f) decode_format_string("fF");
1241 if (opt & OPT_h) decode_format_string("x2");
1242 if (opt & OPT_i) decode_format_string("d2");
1243 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1244 if (opt & OPT_l) decode_format_string("d4");
1245 if (opt & OPT_o) decode_format_string("o2");
1247 decode_format_string(llist_pop(&lst_t));
1249 if (opt & OPT_x) decode_format_string("x2");
1250 if (opt & OPT_s) decode_format_string("d2");
1252 string_min = xstrtou_sfx(str_S, 0, bkm);
1256 //if ((option_mask32 & OPT_S) && n_specs > 0)
1257 // bb_error_msg_and_die("no type may be specified when dumping strings");
1259 /* If the --traditional option is used, there may be from
1260 * 0 to 3 remaining command line arguments; handle each case
1262 * od [FILE] [[+]OFFSET[.][b] [[+]LABEL[.][b]]]
1263 * The offset and pseudo_start have the same syntax.
1265 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1266 * traditional syntax even if --traditional is not given. */
1268 #if ENABLE_LONG_OPTS
1269 if (opt & OPT_traditional) {
1271 off_t pseudo_start = -1;
1274 if (!argv[1]) { /* one arg */
1275 if (parse_old_offset(argv[0], &o1)) {
1276 /* od --traditional OFFSET */
1277 n_bytes_to_skip = o1;
1280 /* od --traditional FILE */
1281 } else if (!argv[2]) { /* two args */
1282 if (parse_old_offset(argv[0], &o1)
1283 && parse_old_offset(argv[1], &o2)
1285 /* od --traditional OFFSET LABEL */
1286 n_bytes_to_skip = o1;
1289 } else if (parse_old_offset(argv[1], &o2)) {
1290 /* od --traditional FILE OFFSET */
1291 n_bytes_to_skip = o2;
1294 bb_error_msg_and_die("invalid second argument '%s'", argv[1]);
1296 } else if (!argv[3]) { /* three args */
1297 if (parse_old_offset(argv[1], &o1)
1298 && parse_old_offset(argv[2], &o2)
1300 /* od --traditional FILE OFFSET LABEL */
1301 n_bytes_to_skip = o1;
1305 bb_error_msg_and_die("the last two arguments must be offsets");
1307 } else { /* >3 args */
1308 bb_error_msg_and_die("too many arguments");
1311 if (pseudo_start >= 0) {
1312 if (format_address == format_address_none) {
1313 address_base_char = 'o';
1314 address_pad_len_char = '7';
1315 format_address = format_address_paren;
1317 format_address = format_address_label;
1319 pseudo_offset = pseudo_start - n_bytes_to_skip;
1322 /* else: od --traditional (without args) */
1326 if (option_mask32 & OPT_N) {
1327 end_offset = n_bytes_to_skip + max_bytes_to_format;
1328 if (end_offset < n_bytes_to_skip)
1329 bb_error_msg_and_die("SKIP + SIZE is too large");
1333 decode_format_string("o2");
1334 /*n_specs = 1; - done by decode_format_string */
1337 /* If no files were listed on the command line,
1338 set the global pointer FILE_LIST so that it
1339 references the null-terminated list of one name: "-". */
1340 file_list = bb_argv_dash;
1342 /* Set the global pointer FILE_LIST so that it
1343 references the first file-argument on the command-line. */
1344 file_list = (char const *const *) argv;
1347 /* Open the first input file */
1349 /* Skip over any unwanted header bytes */
1350 skip(n_bytes_to_skip);
1352 return EXIT_FAILURE;
1354 /* Compute output block length */
1357 if (opt & OPT_w) { /* -w: width */
1358 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1359 bb_error_msg("warning: invalid width %u; using %d instead",
1360 (unsigned)bytes_per_block, l_c_m);
1361 bytes_per_block = l_c_m;
1364 bytes_per_block = l_c_m;
1365 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1366 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1370 for (i = 0; i < n_specs; i++) {
1371 printf("%d: fmt=\"%s\" width=%d\n",
1372 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1376 if (option_mask32 & OPT_S)
1377 dump_strings(n_bytes_to_skip, end_offset);
1379 dump(n_bytes_to_skip, end_offset);
1382 bb_perror_msg_and_die(bb_msg_standard_input);