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 size_t 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(bb_msg_write_error);
522 /* If S points to a single valid modern od format string, put
523 a description of that format in *TSPEC, return pointer to
524 character following the just-decoded format.
525 For example, if S were "d4afL", we will return a rtp to "afL"
528 fmt = SIGNED_DECIMAL;
529 size = INT or LONG; (whichever integral_type_size[4] resolves to)
530 print_function = print_int; (assuming size == INT)
531 fmt_string = "%011d%c";
533 S_ORIG is solely for reporting errors. It should be the full format
536 static NOINLINE const char *
537 decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
539 enum size_spec size_spec;
541 enum output_format fmt;
544 char *fmt_string = NULL;
545 void (*print_function) (size_t, const char *, const char *);
547 unsigned field_width = 0;
556 static const char CSIL[] ALIGN1 = "CSIL";
559 p = strchr(CSIL, *s);
560 /* if *s == NUL, p != NULL! Testcase: "od -tx" */
561 if (!p || *p == '\0') {
564 size = bb_strtou(s, &end, 0);
566 || MAX_INTEGRAL_TYPE_SIZE < size
567 || integral_type_size[size] == NO_SIZE
569 bb_error_msg_and_die("invalid type string '%s'; "
570 "%u-byte %s type is not supported",
571 s_orig, size, "integral");
576 static const uint8_t CSIL_sizeof[4] = {
582 size = CSIL_sizeof[p - CSIL];
583 s++; /* skip C/S/I/L */
586 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
587 ((Spec) == LONG_LONG ? (Max_format) \
588 : ((Spec) == LONG ? (Long_format) : (Min_format)))
590 #define FMT_BYTES_ALLOCATED 9
591 size_spec = integral_type_size[size];
594 static const char doux[] ALIGN1 = "doux";
595 static const char doux_fmt_letter[][4] = {
596 "lld", "llo", "llu", "llx"
598 static const enum output_format doux_fmt[] = {
604 static const uint8_t *const doux_bytes_to_XXX[] = {
605 bytes_to_signed_dec_digits,
607 bytes_to_unsigned_dec_digits,
610 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
617 pos = strchr(doux, c) - doux;
619 field_width = doux_bytes_to_XXX[pos][size];
620 p = doux_fmt_letter[pos] + 2;
621 if (size_spec == LONG) p--;
622 if (size_spec == LONG_LONG) p -= 2;
623 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
628 print_function = (fmt == SIGNED_DECIMAL
633 print_function = (fmt == SIGNED_DECIMAL
638 print_function = print_int;
641 print_function = print_long;
643 default: /* case LONG_LONG: */
644 print_function = print_long_long;
651 static const char FDL[] ALIGN1 = "FDL";
653 fmt = FLOATING_POINT;
657 size = sizeof(double);
659 size = bb_strtou(s, &end, 0);
660 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
661 || fp_type_size[size] == NO_SIZE
663 bb_error_msg_and_die("invalid type string '%s'; "
664 "%u-byte %s type is not supported",
665 s_orig, size, "floating point");
670 static const uint8_t FDL_sizeof[] = {
673 sizeof(longdouble_t),
676 size = FDL_sizeof[p - FDL];
679 size_spec = fp_type_size[size];
683 print_function = print_float;
684 field_width = FLT_DIG + 8;
685 /* Don't use %#e; not all systems support it. */
686 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
689 print_function = print_double;
690 field_width = DBL_DIG + 8;
691 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
693 default: /* case FLOAT_LONG_DOUBLE: */
694 print_function = print_long_double;
695 field_width = LDBL_DIG + 8;
696 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
704 fmt = NAMED_CHARACTER;
706 print_function = print_named_ascii;
713 print_function = print_ascii;
717 bb_error_msg_and_die("invalid character '%c' "
718 "in type string '%s'", *s, s_orig);
721 tspec->size = size_spec;
723 tspec->print_function = print_function;
724 tspec->fmt_string = fmt_string;
726 tspec->field_width = field_width;
727 tspec->hexl_mode_trailer = (*s == 'z');
728 if (tspec->hexl_mode_trailer)
734 /* Decode the modern od format string S. Append the decoded
735 representation to the global array SPEC, reallocating SPEC if
739 decode_format_string(const char *s)
741 const char *s_orig = s;
747 next = decode_one_format(s_orig, s, &tspec);
751 spec = xrealloc_vector(spec, 4, n_specs);
752 memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
757 /* Given a list of one or more input filenames FILE_LIST, set the global
758 file pointer IN_STREAM to position N_SKIP in the concatenation of
759 those files. If any file operation fails or if there are fewer than
760 N_SKIP bytes in the combined input, give an error message and return
761 nonzero. When possible, use seek rather than read operations to
762 advance IN_STREAM. */
770 while (in_stream) { /* !EOF */
771 struct stat file_stats;
773 /* First try seeking. For large offsets, this extra work is
774 worthwhile. If the offset is below some threshold it may be
775 more efficient to move the pointer by reading. There are two
776 issues when trying to seek:
777 - the file must be seekable.
778 - before seeking to the specified position, make sure
779 that the new position is in the current file.
780 Try to do that by getting file's size using fstat.
781 But that will work only for regular files. */
783 /* The st_size field is valid only for regular files
784 (and for symbolic links, which cannot occur here).
785 If the number of bytes left to skip is at least
786 as large as the size of the current file, we can
787 decrement n_skip and go on to the next file. */
788 if (fstat(fileno(in_stream), &file_stats) == 0
789 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
791 if (file_stats.st_size < n_skip) {
792 n_skip -= file_stats.st_size;
793 /* take "check & close / open_next" route */
795 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
800 /* If it's not a regular file with positive size,
801 position the file pointer by reading. */
803 size_t n_bytes_to_read = 1024;
807 if (n_skip < n_bytes_to_read)
808 n_bytes_to_read = n_skip;
809 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
810 n_skip -= n_bytes_read;
811 if (n_bytes_read != n_bytes_to_read)
812 break; /* EOF on this file or error */
823 bb_error_msg_and_die("can't skip past end of combined input");
827 typedef void FN_format_address(off_t address, char c);
830 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
834 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
835 /* Corresponds to 'x' above */
836 #define address_base_char address_fmt[sizeof(address_fmt)-3]
837 /* Corresponds to 'n' above */
838 #define address_pad_len_char address_fmt[2]
841 format_address_std(off_t address, char c)
843 /* Corresponds to 'c' */
844 address_fmt[sizeof(address_fmt)-2] = c;
845 printf(address_fmt, address);
849 /* only used with --traditional */
851 format_address_paren(off_t address, char c)
854 format_address_std(address, ')');
859 format_address_label(off_t address, char c)
861 format_address_std(address, ' ');
862 format_address_paren(address + pseudo_offset, c);
867 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
871 unsigned c = *(unsigned char *) block++;
872 c = (ISPRINT(c) ? c : '.');
878 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
879 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
880 CURR_BLOCK in the concatenation of input files, and it is printed
881 (optionally) only before the output line associated with the first
882 format spec. When duplicate blocks are being abbreviated, the output
883 for a sequence of identical input blocks is the output for the first
884 block followed by an asterisk alone on a line. It is valid to compare
885 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
886 That condition may be false only for the last input block -- and then
887 only when it has not been padded to length BYTES_PER_BLOCK. */
890 write_block(off_t current_offset, size_t n_bytes,
891 const char *prev_block, const char *curr_block)
893 static char first = 1;
894 static char prev_pair_equal = 0;
897 if (!(option_mask32 & OPT_v)
899 && n_bytes == bytes_per_block
900 && memcmp(prev_block, curr_block, bytes_per_block) == 0
902 if (prev_pair_equal) {
903 /* The two preceding blocks were equal, and the current
904 block is the same as the last one, so print nothing. */
912 for (i = 0; i < n_specs; i++) {
914 format_address(current_offset, '\0');
916 printf("%*s", address_pad_len_char - '0', "");
917 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
918 if (spec[i].hexl_mode_trailer) {
919 /* space-pad out to full line width, then dump the trailer */
920 int datum_width = width_bytes[spec[i].size];
921 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
922 int field_width = spec[i].field_width + 1;
923 printf("%*s", blank_fields * field_width, "");
924 dump_hexl_mode_trailer(n_bytes, curr_block);
932 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
934 assert(0 < n && n <= bytes_per_block);
936 *n_bytes_in_buffer = 0;
941 while (in_stream != NULL) { /* EOF. */
945 n_needed = n - *n_bytes_in_buffer;
946 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
947 *n_bytes_in_buffer += n_read;
948 if (n_read == n_needed)
950 /* error check is done in check_and_close */
956 /* Return the least common multiple of the sizes associated
957 with the format specs. */
965 for (i = 0; i < n_specs; i++)
966 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
970 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
971 formatted block to standard output, and repeat until the specified
972 maximum number of bytes has been read or until all input has been
973 processed. If the last block read is smaller than BYTES_PER_BLOCK
974 and its size is not a multiple of the size associated with a format
975 spec, extend the input block with zero bytes until its length is a
976 multiple of all format spec sizes. Write the final block. Finally,
977 write on a line by itself the offset of the byte after the last byte
981 dump(off_t current_offset, off_t end_offset)
987 block[0] = xmalloc(2*bytes_per_block);
988 block[1] = block[0] + bytes_per_block;
991 if (option_mask32 & OPT_N) {
994 if (current_offset >= end_offset) {
998 n_needed = MIN(end_offset - current_offset,
999 (off_t) bytes_per_block);
1000 read_block(n_needed, block[idx], &n_bytes_read);
1001 if (n_bytes_read < bytes_per_block)
1003 assert(n_bytes_read == bytes_per_block);
1004 write_block(current_offset, n_bytes_read,
1005 block[!idx], block[idx]);
1006 current_offset += n_bytes_read;
1011 read_block(bytes_per_block, block[idx], &n_bytes_read);
1012 if (n_bytes_read < bytes_per_block)
1014 assert(n_bytes_read == bytes_per_block);
1015 write_block(current_offset, n_bytes_read,
1016 block[!idx], block[idx]);
1017 current_offset += n_bytes_read;
1022 if (n_bytes_read > 0) {
1024 size_t bytes_to_write;
1028 /* Make bytes_to_write the smallest multiple of l_c_m that
1029 is at least as large as n_bytes_read. */
1030 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1032 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1033 write_block(current_offset, bytes_to_write,
1034 block[!idx], block[idx]);
1035 current_offset += n_bytes_read;
1038 format_address(current_offset, '\n');
1040 if ((option_mask32 & OPT_N) && current_offset >= end_offset)
1046 /* Read a single byte into *C from the concatenation of the input files
1047 named in the global array FILE_LIST. On the first call to this
1048 function, the global variable IN_STREAM is expected to be an open
1049 stream associated with the input file INPUT_FILENAME. If IN_STREAM
1050 is at end-of-file, close it and update the global variables IN_STREAM
1051 and INPUT_FILENAME so they correspond to the next file in the list.
1052 Then try to read a byte from the newly opened file. Repeat if
1053 necessary until EOF is reached for the last file in FILE_LIST, then
1054 set *C to EOF and return. Subsequent calls do likewise. */
1059 while (in_stream) { /* !EOF */
1060 *c = fgetc(in_stream);
1069 /* Read N bytes into BLOCK from the concatenation of the input files
1070 named in the global array FILE_LIST. On the first call to this
1071 function, the global variable IN_STREAM is expected to be an open
1072 stream associated with the input file INPUT_FILENAME. If all N
1073 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1074 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1075 read the remaining bytes from the newly opened file. Repeat if
1076 necessary until EOF is reached for the last file in FILE_LIST.
1077 On subsequent calls, don't modify BLOCK and return zero. Set
1078 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1079 it will be detected through ferror when the stream is about to be
1080 closed. If there is an error, give a message but continue reading
1081 as usual and return nonzero. Otherwise return zero. */
1083 /* STRINGS mode. Find each "string constant" in the input.
1084 A string constant is a run of at least 'string_min' ASCII
1085 graphic (or formatting) characters terminated by a null.
1086 Based on a function written by Richard Stallman for a
1087 traditional version of od. */
1090 dump_strings(off_t address, off_t end_offset)
1092 size_t bufsize = MAX(100, string_min);
1093 char *buf = xmalloc(bufsize);
1099 /* See if the next 'string_min' chars are all printing chars. */
1101 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))
1104 while (!(option_mask32 & OPT_N) || address < end_offset) {
1106 bufsize += bufsize/8;
1107 buf = xrealloc(buf, bufsize);
1110 if (c < 0) { /* EOF */
1118 goto tryline; /* It isn't; give up on this string. */
1119 buf[i++] = c; /* String continues; store it all. */
1122 if (i < string_min) /* Too short! */
1125 /* If we get here, the string is all printable and NUL-terminated,
1126 * so print it. It is all in 'buf' and 'i' is its length. */
1128 format_address(address - i - 1, ' ');
1130 for (i = 0; (c = buf[i]); i++) {
1132 case '\007': fputs("\\a", stdout); break;
1133 case '\b': fputs("\\b", stdout); break;
1134 case '\f': fputs("\\f", stdout); break;
1135 case '\n': fputs("\\n", stdout); break;
1136 case '\r': fputs("\\r", stdout); break;
1137 case '\t': fputs("\\t", stdout); break;
1138 case '\v': fputs("\\v", stdout); break;
1139 default: putchar(c);
1145 /* We reach this point only if we search through
1146 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1152 #if ENABLE_LONG_OPTS
1153 /* If S is a valid traditional offset specification with an optional
1154 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
1157 parse_old_offset(const char *s, off_t *offset)
1159 static const struct suffix_mult Bb[] = {
1167 /* Skip over any leading '+'. */
1168 if (s[0] == '+') ++s;
1169 if (!isdigit(s[0])) return 0; /* not a number */
1171 /* Determine the radix we'll use to interpret S. If there is a '.',
1172 * it's decimal, otherwise, if the string begins with '0X'or '0x',
1173 * it's hexadecimal, else octal. */
1177 p[0] = '\0'; /* cheating */
1179 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1182 *offset = xstrtooff_sfx(s, radix, Bb);
1185 return (*offset >= 0);
1189 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1190 int od_main(int argc UNUSED_PARAM, char **argv)
1192 static const struct suffix_mult bkm[] = {
1198 #if ENABLE_LONG_OPTS
1199 static const char od_longopts[] ALIGN1 =
1200 "skip-bytes\0" Required_argument "j"
1201 "address-radix\0" Required_argument "A"
1202 "read-bytes\0" Required_argument "N"
1203 "format\0" Required_argument "t"
1204 "output-duplicates\0" No_argument "v"
1205 "strings\0" Optional_argument "S"
1206 "width\0" Optional_argument "w"
1207 "traditional\0" No_argument "\xff"
1210 char *str_A, *str_N, *str_j, *str_S;
1211 llist_t *lst_t = NULL;
1214 /* The number of input bytes to skip before formatting and writing. */
1215 off_t n_bytes_to_skip = 0;
1216 /* The offset of the first byte after the last byte to be formatted. */
1217 off_t end_offset = 0;
1218 /* The maximum number of bytes that will be formatted. */
1219 off_t max_bytes_to_format = 0;
1222 format_address = format_address_std;
1223 address_base_char = 'o';
1224 address_pad_len_char = '7';
1226 /* Parse command line */
1227 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1228 #if ENABLE_LONG_OPTS
1229 applet_long_options = od_longopts;
1231 opt = OD_GETOPT32();
1234 static const char doxn[] ALIGN1 = "doxn";
1235 static const char doxn_address_base_char[] ALIGN1 = {
1236 'u', 'o', 'x', /* '?' fourth one is not important */
1238 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1239 '7', '7', '6', /* '?' */
1243 p = strchr(doxn, str_A[0]);
1245 bb_error_msg_and_die("bad output address radix "
1246 "'%c' (must be [doxn])", str_A[0]);
1248 if (pos == 3) format_address = format_address_none;
1249 address_base_char = doxn_address_base_char[pos];
1250 address_pad_len_char = doxn_address_pad_len_char[pos];
1253 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1255 if (opt & OPT_a) decode_format_string("a");
1256 if (opt & OPT_b) decode_format_string("oC");
1257 if (opt & OPT_c) decode_format_string("c");
1258 if (opt & OPT_d) decode_format_string("u2");
1259 if (opt & OPT_f) decode_format_string("fF");
1260 if (opt & OPT_h) decode_format_string("x2");
1261 if (opt & OPT_i) decode_format_string("d2");
1262 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1263 if (opt & OPT_l) decode_format_string("d4");
1264 if (opt & OPT_o) decode_format_string("o2");
1266 decode_format_string(llist_pop(&lst_t));
1268 if (opt & OPT_x) decode_format_string("x2");
1269 if (opt & OPT_s) decode_format_string("d2");
1271 string_min = xstrtou_sfx(str_S, 0, bkm);
1275 //if ((option_mask32 & OPT_S) && n_specs > 0)
1276 // bb_error_msg_and_die("no type may be specified when dumping strings");
1278 /* If the --traditional option is used, there may be from
1279 * 0 to 3 remaining command line arguments; handle each case
1281 * od [FILE] [[+]OFFSET[.][b] [[+]LABEL[.][b]]]
1282 * The offset and pseudo_start have the same syntax.
1284 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1285 * traditional syntax even if --traditional is not given. */
1287 #if ENABLE_LONG_OPTS
1288 if (opt & OPT_traditional) {
1290 off_t pseudo_start = -1;
1293 if (!argv[1]) { /* one arg */
1294 if (parse_old_offset(argv[0], &o1)) {
1295 /* od --traditional OFFSET */
1296 n_bytes_to_skip = o1;
1299 /* od --traditional FILE */
1300 } else if (!argv[2]) { /* two args */
1301 if (parse_old_offset(argv[0], &o1)
1302 && parse_old_offset(argv[1], &o2)
1304 /* od --traditional OFFSET LABEL */
1305 n_bytes_to_skip = o1;
1308 } else if (parse_old_offset(argv[1], &o2)) {
1309 /* od --traditional FILE OFFSET */
1310 n_bytes_to_skip = o2;
1313 bb_error_msg_and_die("invalid second argument '%s'", argv[1]);
1315 } else if (!argv[3]) { /* three args */
1316 if (parse_old_offset(argv[1], &o1)
1317 && parse_old_offset(argv[2], &o2)
1319 /* od --traditional FILE OFFSET LABEL */
1320 n_bytes_to_skip = o1;
1324 bb_error_msg_and_die("the last two arguments must be offsets");
1326 } else { /* >3 args */
1327 bb_error_msg_and_die("too many arguments");
1330 if (pseudo_start >= 0) {
1331 if (format_address == format_address_none) {
1332 address_base_char = 'o';
1333 address_pad_len_char = '7';
1334 format_address = format_address_paren;
1336 format_address = format_address_label;
1338 pseudo_offset = pseudo_start - n_bytes_to_skip;
1341 /* else: od --traditional (without args) */
1345 if (option_mask32 & OPT_N) {
1346 end_offset = n_bytes_to_skip + max_bytes_to_format;
1347 if (end_offset < n_bytes_to_skip)
1348 bb_error_msg_and_die("SKIP + SIZE is too large");
1352 decode_format_string("o2");
1353 /*n_specs = 1; - done by decode_format_string */
1356 /* If no files were listed on the command line,
1357 set the global pointer FILE_LIST so that it
1358 references the null-terminated list of one name: "-". */
1359 file_list = bb_argv_dash;
1361 /* Set the global pointer FILE_LIST so that it
1362 references the first file-argument on the command-line. */
1363 file_list = (char const *const *) argv;
1366 /* Open the first input file */
1368 /* Skip over any unwanted header bytes */
1369 skip(n_bytes_to_skip);
1371 return EXIT_FAILURE;
1373 /* Compute output block length */
1376 if (opt & OPT_w) { /* -w: width */
1377 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1378 bb_error_msg("warning: invalid width %u; using %d instead",
1379 (unsigned)bytes_per_block, l_c_m);
1380 bytes_per_block = l_c_m;
1383 bytes_per_block = l_c_m;
1384 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1385 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1389 for (i = 0; i < n_specs; i++) {
1390 printf("%d: fmt=\"%s\" width=%d\n",
1391 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1395 if (option_mask32 & OPT_S)
1396 dump_strings(n_bytes_to_skip, end_offset);
1398 dump(n_bytes_to_skip, end_offset);
1400 if (fclose(stdin) == EOF)
1401 bb_perror_msg_and_die(bb_msg_standard_input);