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 */
21 //usage:#if ENABLE_DESKTOP
22 //usage:#define od_trivial_usage
23 //usage: "[-abcdfhilovxs] [-t TYPE] [-A RADIX] [-N SIZE] [-j SKIP] [-S MINSTR] [-w WIDTH] [FILE...]"
25 // ... [FILE] [[+]OFFSET[.][b]]
26 // Support is buggy for:
27 // od --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]
29 //usage:#define od_full_usage "\n\n"
30 //usage: "Print FILEs (or stdin) unambiguously, as octal bytes by default"
33 /* #include "libbb.h" - done in od.c */
35 #define assert(a) ((void)0)
37 /* Check for 0x7f is a coreutils 6.3 addition */
38 #define ISPRINT(c) (((c)>=' ') && (c) != 0x7f)
40 typedef long double longdouble_t;
41 typedef unsigned long long ulonglong_t;
42 typedef long long llong;
45 # define xstrtooff_sfx xstrtoull_sfx
47 # define xstrtooff_sfx xstrtoul_sfx
50 /* The default number of input bytes per output line. */
51 #define DEFAULT_BYTES_PER_BLOCK 16
53 /* The number of decimal digits of precision in a float. */
58 /* The number of decimal digits of precision in a double. */
63 /* The number of decimal digits of precision in a long double. */
65 # define LDBL_DIG DBL_DIG
91 /* Each output format specification (from '-t spec' or from
92 old-style options) is represented by one of these structures. */
94 enum output_format fmt;
96 void (*print_function) (size_t, const char *, const char *);
98 int hexl_mode_trailer;
102 /* Convert the number of 8-bit bytes of a binary representation to
103 the number of characters (digits + sign if the type is signed)
104 required to represent the same quantity in the specified base/type.
105 For example, a 32-bit (4-byte) quantity may require a field width
106 as wide as the following for these types:
110 8 unsigned hexadecimal */
112 static const uint8_t bytes_to_oct_digits[] ALIGN1 =
113 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
115 static const uint8_t bytes_to_signed_dec_digits[] ALIGN1 =
116 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
118 static const uint8_t bytes_to_unsigned_dec_digits[] ALIGN1 =
119 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
121 static const uint8_t bytes_to_hex_digits[] ALIGN1 =
122 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
124 /* Convert enum size_spec to the size of the named type. */
125 static const signed char width_bytes[] ALIGN1 = {
136 /* Ensure that for each member of 'enum size_spec' there is an
137 initializer in the width_bytes array. */
138 struct ERR_width_bytes_has_bad_size {
139 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
142 static smallint flag_dump_strings;
143 /* Non-zero if an old-style 'pseudo-address' was specified. */
144 static smallint flag_pseudo_start;
145 static smallint limit_bytes_to_format;
146 /* When zero and two or more consecutive blocks are equal, format
147 only the first block and output an asterisk alone on the following
148 line to indicate that identical blocks have been elided. */
149 static smallint verbose;
150 static smallint ioerror;
152 static size_t string_min;
154 /* An array of specs describing how to format each input block. */
155 static size_t n_specs;
156 static struct tspec *spec;
158 /* Function that accepts an address and an optional following char,
159 and prints the address and char to stdout. */
160 static void (*format_address)(off_t, char);
161 /* The difference between the old-style pseudo starting address and
162 the number of bytes to skip. */
163 static off_t pseudo_offset;
164 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
165 input is formatted. */
167 /* The number of input bytes formatted per output line. It must be
168 a multiple of the least common multiple of the sizes associated with
169 the specified output types. It should be as large as possible, but
170 no larger than 16 -- unless specified with the -w option. */
171 static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */
173 /* A NULL-terminated list of the file-arguments from the command line. */
174 static const char *const *file_list;
176 /* The input stream associated with the current file. */
177 static FILE *in_stream;
179 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
180 static const unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
181 [sizeof(char)] = CHAR,
182 #if USHRT_MAX != UCHAR_MAX
183 [sizeof(short)] = SHORT,
185 #if UINT_MAX != USHRT_MAX
188 #if ULONG_MAX != UINT_MAX
189 [sizeof(long)] = LONG,
191 #if ULLONG_MAX != ULONG_MAX
192 [sizeof(ulonglong_t)] = LONG_LONG,
196 #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
197 static const unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
198 /* gcc seems to allow repeated indexes. Last one wins */
199 [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
200 [sizeof(double)] = FLOAT_DOUBLE,
201 [sizeof(float)] = FLOAT_SINGLE
206 gcd(unsigned u, unsigned v)
217 /* Compute the least common multiple of U and V. */
219 lcm(unsigned u, unsigned v) {
220 unsigned t = gcd(u, v);
227 print_s_char(size_t n_bytes, const char *block, const char *fmt_string)
230 int tmp = *(signed char *) block;
231 printf(fmt_string, tmp);
232 block += sizeof(unsigned char);
237 print_char(size_t n_bytes, const char *block, const char *fmt_string)
240 unsigned tmp = *(unsigned char *) block;
241 printf(fmt_string, tmp);
242 block += sizeof(unsigned char);
247 print_s_short(size_t n_bytes, const char *block, const char *fmt_string)
249 n_bytes /= sizeof(signed short);
251 int tmp = *(signed short *) block;
252 printf(fmt_string, tmp);
253 block += sizeof(unsigned short);
258 print_short(size_t n_bytes, const char *block, const char *fmt_string)
260 n_bytes /= sizeof(unsigned short);
262 unsigned tmp = *(unsigned short *) block;
263 printf(fmt_string, tmp);
264 block += sizeof(unsigned short);
269 print_int(size_t n_bytes, const char *block, const char *fmt_string)
271 n_bytes /= sizeof(unsigned);
273 unsigned tmp = *(unsigned *) block;
274 printf(fmt_string, tmp);
275 block += sizeof(unsigned);
279 #if UINT_MAX == ULONG_MAX
280 # define print_long print_int
283 print_long(size_t n_bytes, const char *block, const char *fmt_string)
285 n_bytes /= sizeof(unsigned long);
287 unsigned long tmp = *(unsigned long *) block;
288 printf(fmt_string, tmp);
289 block += sizeof(unsigned long);
294 #if ULONG_MAX == ULLONG_MAX
295 # define print_long_long print_long
298 print_long_long(size_t n_bytes, const char *block, const char *fmt_string)
300 n_bytes /= sizeof(ulonglong_t);
302 ulonglong_t tmp = *(ulonglong_t *) block;
303 printf(fmt_string, tmp);
304 block += sizeof(ulonglong_t);
310 print_float(size_t n_bytes, const char *block, const char *fmt_string)
312 n_bytes /= sizeof(float);
314 float tmp = *(float *) block;
315 printf(fmt_string, tmp);
316 block += sizeof(float);
321 print_double(size_t n_bytes, const char *block, const char *fmt_string)
323 n_bytes /= sizeof(double);
325 double tmp = *(double *) block;
326 printf(fmt_string, tmp);
327 block += sizeof(double);
332 print_long_double(size_t n_bytes, const char *block, const char *fmt_string)
334 n_bytes /= sizeof(longdouble_t);
336 longdouble_t tmp = *(longdouble_t *) block;
337 printf(fmt_string, tmp);
338 block += sizeof(longdouble_t);
342 /* print_[named]_ascii are optimized for speed.
343 * Remember, someday you may want to pump gigabytes through this thing.
344 * Saving a dozen of .text bytes here is counter-productive */
347 print_named_ascii(size_t n_bytes, const char *block,
348 const char *unused_fmt_string UNUSED_PARAM)
350 /* Names for some non-printing characters. */
351 static const char charname[33][3] ALIGN1 = {
352 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
353 " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
354 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
355 "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
358 // buf[N] pos: 01234 56789
359 char buf[12] = " x\0 0xx\0";
360 // actually " x\0 xxx\0", but want to share string with print_ascii.
361 // [12] because we take three 32bit stack slots anyway, and
362 // gcc is too dumb to initialize with constant stores,
363 // it copies initializer from rodata. Oh well.
366 unsigned masked_c = *(unsigned char *) block++;
369 if (masked_c == 0x7f) {
370 fputs(" del", stdout);
373 if (masked_c > ' ') {
378 /* Why? Because printf(" %3.3s") is much slower... */
379 buf[6] = charname[masked_c][0];
380 buf[7] = charname[masked_c][1];
381 buf[8] = charname[masked_c][2];
382 fputs(buf+5, stdout);
387 print_ascii(size_t n_bytes, const char *block,
388 const char *unused_fmt_string UNUSED_PARAM)
390 // buf[N] pos: 01234 56789
391 char buf[12] = " x\0 0xx\0";
395 unsigned c = *(unsigned char *) block++;
430 default: /* c is never larger than 040 */
431 buf[7] = (c >> 3) + '0';
432 buf[8] = (c & 7) + '0';
439 /* Given a list of one or more input filenames FILE_LIST, set the global
440 file pointer IN_STREAM and the global string INPUT_FILENAME to the
441 first one that can be successfully opened. Modify FILE_LIST to
442 reference the next filename in the list. A file name of "-" is
443 interpreted as standard input. If any file open fails, give an error
444 message and return nonzero. */
452 in_stream = fopen_or_warn_stdin(*file_list++);
459 if (limit_bytes_to_format && !flag_dump_strings)
460 setbuf(in_stream, NULL);
463 /* Test whether there have been errors on in_stream, and close it if
464 it is not standard input. Return nonzero if there has been an error
465 on in_stream or stdout; return zero otherwise. This function will
466 report more than one error only if both a read and a write error
467 have occurred. IN_ERRNO, if nonzero, is the error number
468 corresponding to the most recent action for IN_STREAM. */
471 check_and_close(void)
474 if (ferror(in_stream)) {
475 bb_error_msg("%s: read error", (in_stream == stdin)
476 ? bb_msg_standard_input
481 fclose_if_not_stdin(in_stream);
485 if (ferror(stdout)) {
486 bb_error_msg(bb_msg_write_error);
491 /* If S points to a single valid modern od format string, put
492 a description of that format in *TSPEC, return pointer to
493 character following the just-decoded format.
494 For example, if S were "d4afL", we will return a rtp to "afL"
497 fmt = SIGNED_DECIMAL;
498 size = INT or LONG; (whichever integral_type_size[4] resolves to)
499 print_function = print_int; (assuming size == INT)
500 fmt_string = "%011d%c";
502 S_ORIG is solely for reporting errors. It should be the full format
505 static NOINLINE const char *
506 decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
508 enum size_spec size_spec;
510 enum output_format fmt;
513 char *fmt_string = NULL;
514 void (*print_function) (size_t, const char *, const char *);
516 unsigned field_width = 0;
525 static const char CSIL[] ALIGN1 = "CSIL";
528 p = strchr(CSIL, *s);
529 /* if *s == NUL, p != NULL! Testcase: "od -tx" */
530 if (!p || *p == '\0') {
533 size = bb_strtou(s, &end, 0);
535 || MAX_INTEGRAL_TYPE_SIZE < size
536 || integral_type_size[size] == NO_SIZE
538 bb_error_msg_and_die("invalid type string '%s'; "
539 "%u-byte %s type is not supported",
540 s_orig, size, "integral");
545 static const uint8_t CSIL_sizeof[4] = {
551 size = CSIL_sizeof[p - CSIL];
552 s++; /* skip C/S/I/L */
555 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
556 ((Spec) == LONG_LONG ? (Max_format) \
557 : ((Spec) == LONG ? (Long_format) : (Min_format)))
559 #define FMT_BYTES_ALLOCATED 9
560 size_spec = integral_type_size[size];
563 static const char doux[] ALIGN1 = "doux";
564 static const char doux_fmt_letter[][4] = {
565 "lld", "llo", "llu", "llx"
567 static const enum output_format doux_fmt[] = {
573 static const uint8_t *const doux_bytes_to_XXX[] = {
574 bytes_to_signed_dec_digits,
576 bytes_to_unsigned_dec_digits,
579 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
586 pos = strchr(doux, c) - doux;
588 field_width = doux_bytes_to_XXX[pos][size];
589 p = doux_fmt_letter[pos] + 2;
590 if (size_spec == LONG) p--;
591 if (size_spec == LONG_LONG) p -= 2;
592 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
597 print_function = (fmt == SIGNED_DECIMAL
602 print_function = (fmt == SIGNED_DECIMAL
607 print_function = print_int;
610 print_function = print_long;
612 default: /* case LONG_LONG: */
613 print_function = print_long_long;
620 static const char FDL[] ALIGN1 = "FDL";
622 fmt = FLOATING_POINT;
626 size = sizeof(double);
628 size = bb_strtou(s, &end, 0);
629 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
630 || fp_type_size[size] == NO_SIZE
632 bb_error_msg_and_die("invalid type string '%s'; "
633 "%u-byte %s type is not supported",
634 s_orig, size, "floating point");
639 static const uint8_t FDL_sizeof[] = {
642 sizeof(longdouble_t),
645 size = FDL_sizeof[p - FDL];
648 size_spec = fp_type_size[size];
652 print_function = print_float;
653 field_width = FLT_DIG + 8;
654 /* Don't use %#e; not all systems support it. */
655 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
658 print_function = print_double;
659 field_width = DBL_DIG + 8;
660 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
662 default: /* case FLOAT_LONG_DOUBLE: */
663 print_function = print_long_double;
664 field_width = LDBL_DIG + 8;
665 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
673 fmt = NAMED_CHARACTER;
675 print_function = print_named_ascii;
682 print_function = print_ascii;
686 bb_error_msg_and_die("invalid character '%c' "
687 "in type string '%s'", *s, s_orig);
690 tspec->size = size_spec;
692 tspec->print_function = print_function;
693 tspec->fmt_string = fmt_string;
695 tspec->field_width = field_width;
696 tspec->hexl_mode_trailer = (*s == 'z');
697 if (tspec->hexl_mode_trailer)
703 /* Decode the modern od format string S. Append the decoded
704 representation to the global array SPEC, reallocating SPEC if
708 decode_format_string(const char *s)
710 const char *s_orig = s;
716 next = decode_one_format(s_orig, s, &tspec);
720 spec = xrealloc_vector(spec, 4, n_specs);
721 memcpy(&spec[n_specs], &tspec, sizeof(spec[0]));
726 /* Given a list of one or more input filenames FILE_LIST, set the global
727 file pointer IN_STREAM to position N_SKIP in the concatenation of
728 those files. If any file operation fails or if there are fewer than
729 N_SKIP bytes in the combined input, give an error message and return
730 nonzero. When possible, use seek rather than read operations to
731 advance IN_STREAM. */
739 while (in_stream) { /* !EOF */
740 struct stat file_stats;
742 /* First try seeking. For large offsets, this extra work is
743 worthwhile. If the offset is below some threshold it may be
744 more efficient to move the pointer by reading. There are two
745 issues when trying to seek:
746 - the file must be seekable.
747 - before seeking to the specified position, make sure
748 that the new position is in the current file.
749 Try to do that by getting file's size using fstat.
750 But that will work only for regular files. */
752 /* The st_size field is valid only for regular files
753 (and for symbolic links, which cannot occur here).
754 If the number of bytes left to skip is at least
755 as large as the size of the current file, we can
756 decrement n_skip and go on to the next file. */
757 if (fstat(fileno(in_stream), &file_stats) == 0
758 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0
760 if (file_stats.st_size < n_skip) {
761 n_skip -= file_stats.st_size;
762 /* take "check & close / open_next" route */
764 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
769 /* If it's not a regular file with positive size,
770 position the file pointer by reading. */
772 size_t n_bytes_to_read = 1024;
776 if (n_skip < n_bytes_to_read)
777 n_bytes_to_read = n_skip;
778 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
779 n_skip -= n_bytes_read;
780 if (n_bytes_read != n_bytes_to_read)
781 break; /* EOF on this file or error */
792 bb_error_msg_and_die("can't skip past end of combined input");
796 typedef void FN_format_address(off_t address, char c);
799 format_address_none(off_t address UNUSED_PARAM, char c UNUSED_PARAM)
803 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
804 /* Corresponds to 'x' above */
805 #define address_base_char address_fmt[sizeof(address_fmt)-3]
806 /* Corresponds to 'n' above */
807 #define address_pad_len_char address_fmt[2]
810 format_address_std(off_t address, char c)
812 /* Corresponds to 'c' */
813 address_fmt[sizeof(address_fmt)-2] = c;
814 printf(address_fmt, address);
818 /* only used with --traditional */
820 format_address_paren(off_t address, char c)
823 format_address_std(address, ')');
828 format_address_label(off_t address, char c)
830 format_address_std(address, ' ');
831 format_address_paren(address + pseudo_offset, c);
836 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
840 unsigned c = *(unsigned char *) block++;
841 c = (ISPRINT(c) ? c : '.');
847 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
848 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
849 CURR_BLOCK in the concatenation of input files, and it is printed
850 (optionally) only before the output line associated with the first
851 format spec. When duplicate blocks are being abbreviated, the output
852 for a sequence of identical input blocks is the output for the first
853 block followed by an asterisk alone on a line. It is valid to compare
854 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
855 That condition may be false only for the last input block -- and then
856 only when it has not been padded to length BYTES_PER_BLOCK. */
859 write_block(off_t current_offset, size_t n_bytes,
860 const char *prev_block, const char *curr_block)
862 static char first = 1;
863 static char prev_pair_equal = 0;
866 if (!verbose && !first
867 && n_bytes == bytes_per_block
868 && memcmp(prev_block, curr_block, bytes_per_block) == 0
870 if (prev_pair_equal) {
871 /* The two preceding blocks were equal, and the current
872 block is the same as the last one, so print nothing. */
880 for (i = 0; i < n_specs; i++) {
882 format_address(current_offset, '\0');
884 printf("%*s", address_pad_len_char - '0', "");
885 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
886 if (spec[i].hexl_mode_trailer) {
887 /* space-pad out to full line width, then dump the trailer */
888 int datum_width = width_bytes[spec[i].size];
889 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
890 int field_width = spec[i].field_width + 1;
891 printf("%*s", blank_fields * field_width, "");
892 dump_hexl_mode_trailer(n_bytes, curr_block);
900 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
902 assert(0 < n && n <= bytes_per_block);
904 *n_bytes_in_buffer = 0;
909 while (in_stream != NULL) { /* EOF. */
913 n_needed = n - *n_bytes_in_buffer;
914 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
915 *n_bytes_in_buffer += n_read;
916 if (n_read == n_needed)
918 /* error check is done in check_and_close */
924 /* Return the least common multiple of the sizes associated
925 with the format specs. */
933 for (i = 0; i < n_specs; i++)
934 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
938 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
939 formatted block to standard output, and repeat until the specified
940 maximum number of bytes has been read or until all input has been
941 processed. If the last block read is smaller than BYTES_PER_BLOCK
942 and its size is not a multiple of the size associated with a format
943 spec, extend the input block with zero bytes until its length is a
944 multiple of all format spec sizes. Write the final block. Finally,
945 write on a line by itself the offset of the byte after the last byte
949 dump(off_t current_offset, off_t end_offset)
955 block[0] = xmalloc(2*bytes_per_block);
956 block[1] = block[0] + bytes_per_block;
959 if (limit_bytes_to_format) {
962 if (current_offset >= end_offset) {
966 n_needed = MIN(end_offset - current_offset,
967 (off_t) bytes_per_block);
968 read_block(n_needed, block[idx], &n_bytes_read);
969 if (n_bytes_read < bytes_per_block)
971 assert(n_bytes_read == bytes_per_block);
972 write_block(current_offset, n_bytes_read,
973 block[!idx], block[idx]);
974 current_offset += n_bytes_read;
979 read_block(bytes_per_block, block[idx], &n_bytes_read);
980 if (n_bytes_read < bytes_per_block)
982 assert(n_bytes_read == bytes_per_block);
983 write_block(current_offset, n_bytes_read,
984 block[!idx], block[idx]);
985 current_offset += n_bytes_read;
990 if (n_bytes_read > 0) {
992 size_t bytes_to_write;
996 /* Make bytes_to_write the smallest multiple of l_c_m that
997 is at least as large as n_bytes_read. */
998 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1000 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1001 write_block(current_offset, bytes_to_write,
1002 block[!idx], block[idx]);
1003 current_offset += n_bytes_read;
1006 format_address(current_offset, '\n');
1008 if (limit_bytes_to_format && current_offset >= end_offset)
1014 /* Read a single byte into *C from the concatenation of the input files
1015 named in the global array FILE_LIST. On the first call to this
1016 function, the global variable IN_STREAM is expected to be an open
1017 stream associated with the input file INPUT_FILENAME. If IN_STREAM
1018 is at end-of-file, close it and update the global variables IN_STREAM
1019 and INPUT_FILENAME so they correspond to the next file in the list.
1020 Then try to read a byte from the newly opened file. Repeat if
1021 necessary until EOF is reached for the last file in FILE_LIST, then
1022 set *C to EOF and return. Subsequent calls do likewise. */
1027 while (in_stream) { /* !EOF */
1028 *c = fgetc(in_stream);
1037 /* Read N bytes into BLOCK from the concatenation of the input files
1038 named in the global array FILE_LIST. On the first call to this
1039 function, the global variable IN_STREAM is expected to be an open
1040 stream associated with the input file INPUT_FILENAME. If all N
1041 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1042 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1043 read the remaining bytes from the newly opened file. Repeat if
1044 necessary until EOF is reached for the last file in FILE_LIST.
1045 On subsequent calls, don't modify BLOCK and return zero. Set
1046 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1047 it will be detected through ferror when the stream is about to be
1048 closed. If there is an error, give a message but continue reading
1049 as usual and return nonzero. Otherwise return zero. */
1051 /* STRINGS mode. Find each "string constant" in the input.
1052 A string constant is a run of at least 'string_min' ASCII
1053 graphic (or formatting) characters terminated by a null.
1054 Based on a function written by Richard Stallman for a
1055 traditional version of od. */
1058 dump_strings(off_t address, off_t end_offset)
1060 size_t bufsize = MAX(100, string_min);
1061 char *buf = xmalloc(bufsize);
1067 /* See if the next 'string_min' chars are all printing chars. */
1069 if (limit_bytes_to_format && (end_offset - string_min <= address))
1072 while (!limit_bytes_to_format || address < end_offset) {
1074 bufsize += bufsize/8;
1075 buf = xrealloc(buf, bufsize);
1078 if (c < 0) { /* EOF */
1086 goto tryline; /* It isn't; give up on this string. */
1087 buf[i++] = c; /* String continues; store it all. */
1090 if (i < string_min) /* Too short! */
1093 /* If we get here, the string is all printable and NUL-terminated,
1094 * so print it. It is all in 'buf' and 'i' is its length. */
1096 format_address(address - i - 1, ' ');
1098 for (i = 0; (c = buf[i]); i++) {
1100 case '\007': fputs("\\a", stdout); break;
1101 case '\b': fputs("\\b", stdout); break;
1102 case '\f': fputs("\\f", stdout); break;
1103 case '\n': fputs("\\n", stdout); break;
1104 case '\r': fputs("\\r", stdout); break;
1105 case '\t': fputs("\\t", stdout); break;
1106 case '\v': fputs("\\v", stdout); break;
1107 default: putchar(c);
1113 /* We reach this point only if we search through
1114 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1120 #if ENABLE_LONG_OPTS
1121 /* If S is a valid traditional offset specification with an optional
1122 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
1125 parse_old_offset(const char *s, off_t *offset)
1127 static const struct suffix_mult Bb[] = {
1135 /* Skip over any leading '+'. */
1136 if (s[0] == '+') ++s;
1137 if (!isdigit(s[0])) return 0; /* not a number */
1139 /* Determine the radix we'll use to interpret S. If there is a '.',
1140 * it's decimal, otherwise, if the string begins with '0X'or '0x',
1141 * it's hexadecimal, else octal. */
1145 p[0] = '\0'; /* cheating */
1147 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1150 *offset = xstrtooff_sfx(s, radix, Bb);
1153 return (*offset >= 0);
1157 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1158 int od_main(int argc UNUSED_PARAM, char **argv)
1160 static const struct suffix_mult bkm[] = {
1185 OPT_traditional = (1 << 18) * ENABLE_LONG_OPTS,
1187 #if ENABLE_LONG_OPTS
1188 static const char od_longopts[] ALIGN1 =
1189 "skip-bytes\0" Required_argument "j"
1190 "address-radix\0" Required_argument "A"
1191 "read-bytes\0" Required_argument "N"
1192 "format\0" Required_argument "t"
1193 "output-duplicates\0" No_argument "v"
1194 "strings\0" Optional_argument "S"
1195 "width\0" Optional_argument "w"
1196 "traditional\0" No_argument "\xff"
1199 char *str_A, *str_N, *str_j, *str_S;
1200 llist_t *lst_t = NULL;
1203 /* The old-style 'pseudo starting address' to be printed in parentheses
1204 after any true address. */
1205 off_t pseudo_start = pseudo_start; // for gcc
1206 /* The number of input bytes to skip before formatting and writing. */
1207 off_t n_bytes_to_skip = 0;
1208 /* The offset of the first byte after the last byte to be formatted. */
1209 off_t end_offset = 0;
1210 /* The maximum number of bytes that will be formatted. */
1211 off_t max_bytes_to_format = 0;
1214 format_address = format_address_std;
1215 address_base_char = 'o';
1216 address_pad_len_char = '7';
1217 /* flag_dump_strings = 0; - already is */
1219 /* Parse command line */
1220 opt_complementary = "w+:t::"; /* -w N, -t is a list */
1221 #if ENABLE_LONG_OPTS
1222 applet_long_options = od_longopts;
1224 opt = getopt32(argv, "A:N:abcdfhij:lot:vxsS:"
1225 "w::", // -w with optional param
1226 // -S was -s and also had optional parameter
1227 // but in coreutils 6.3 it was renamed and now has
1228 // _mandatory_ parameter
1229 &str_A, &str_N, &str_j, &lst_t, &str_S, &bytes_per_block);
1232 static const char doxn[] ALIGN1 = "doxn";
1233 static const char doxn_address_base_char[] ALIGN1 = {
1234 'u', 'o', 'x', /* '?' fourth one is not important */
1236 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1237 '7', '7', '6', /* '?' */
1241 p = strchr(doxn, str_A[0]);
1243 bb_error_msg_and_die("bad output address radix "
1244 "'%c' (must be [doxn])", str_A[0]);
1246 if (pos == 3) format_address = format_address_none;
1247 address_base_char = doxn_address_base_char[pos];
1248 address_pad_len_char = doxn_address_pad_len_char[pos];
1251 limit_bytes_to_format = 1;
1252 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1254 if (opt & OPT_a) decode_format_string("a");
1255 if (opt & OPT_b) decode_format_string("oC");
1256 if (opt & OPT_c) decode_format_string("c");
1257 if (opt & OPT_d) decode_format_string("u2");
1258 if (opt & OPT_f) decode_format_string("fF");
1259 if (opt & OPT_h) decode_format_string("x2");
1260 if (opt & OPT_i) decode_format_string("d2");
1261 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1262 if (opt & OPT_l) decode_format_string("d4");
1263 if (opt & OPT_o) decode_format_string("o2");
1264 //if (opt & OPT_t)...
1266 decode_format_string(llist_pop(&lst_t));
1268 if (opt & OPT_v) verbose = 1;
1269 if (opt & OPT_x) decode_format_string("x2");
1270 if (opt & OPT_s) decode_format_string("d2");
1272 string_min = xstrtou_sfx(str_S, 0, bkm);
1273 flag_dump_strings = 1;
1275 //if (opt & OPT_w)...
1276 //if (opt & OPT_traditional)...
1278 if (flag_dump_strings && n_specs > 0)
1279 bb_error_msg_and_die("no type may be specified when dumping strings");
1281 /* If the --traditional option is used, there may be from
1282 * 0 to 3 remaining command line arguments; handle each case
1284 * od [FILE] [[+]OFFSET[.][b] [[+]LABEL[.][b]]]
1285 * The offset and pseudo_start have the same syntax.
1287 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1288 * traditional syntax even if --traditional is not given. */
1290 #if ENABLE_LONG_OPTS
1291 if (opt & OPT_traditional) {
1295 if (!argv[1]) { /* one arg */
1296 if (parse_old_offset(argv[0], &o1)) {
1297 /* od --traditional OFFSET */
1298 n_bytes_to_skip = o1;
1301 /* od --traditional FILE */
1302 } else if (!argv[2]) { /* two args */
1303 if (parse_old_offset(argv[0], &o1)
1304 && parse_old_offset(argv[1], &o2)
1306 /* od --traditional OFFSET LABEL */
1307 n_bytes_to_skip = o1;
1308 flag_pseudo_start = 1;
1311 } else if (parse_old_offset(argv[1], &o2)) {
1312 /* od --traditional FILE OFFSET */
1313 n_bytes_to_skip = o2;
1316 bb_error_msg_and_die("invalid second argument '%s'", argv[1]);
1318 } else if (!argv[3]) { /* three args */
1319 if (parse_old_offset(argv[1], &o1)
1320 && parse_old_offset(argv[2], &o2)
1322 /* od --traditional FILE OFFSET LABEL */
1323 n_bytes_to_skip = o1;
1324 flag_pseudo_start = 1;
1328 bb_error_msg_and_die("the last two arguments must be offsets");
1330 } else { /* >3 args */
1331 bb_error_msg_and_die("too many arguments");
1334 /* else: od --traditional (without args) */
1336 if (flag_pseudo_start) {
1337 if (format_address == format_address_none) {
1338 address_base_char = 'o';
1339 address_pad_len_char = '7';
1340 format_address = format_address_paren;
1342 format_address = format_address_label;
1347 if (limit_bytes_to_format) {
1348 end_offset = n_bytes_to_skip + max_bytes_to_format;
1349 if (end_offset < n_bytes_to_skip)
1350 bb_error_msg_and_die("SKIP + SIZE is too large");
1354 decode_format_string("o2");
1358 /* If no files were listed on the command line,
1359 set the global pointer FILE_LIST so that it
1360 references the null-terminated list of one name: "-". */
1361 file_list = bb_argv_dash;
1363 /* Set the global pointer FILE_LIST so that it
1364 references the first file-argument on the command-line. */
1365 file_list = (char const *const *) argv;
1368 /* open the first input file */
1370 /* skip over any unwanted header bytes */
1371 skip(n_bytes_to_skip);
1373 return EXIT_FAILURE;
1375 pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1377 /* Compute output block length. */
1380 if (opt & OPT_w) { /* -w: width */
1381 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1382 bb_error_msg("warning: invalid width %u; using %d instead",
1383 (unsigned)bytes_per_block, l_c_m);
1384 bytes_per_block = l_c_m;
1387 bytes_per_block = l_c_m;
1388 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1389 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1393 for (i = 0; i < n_specs; i++) {
1394 printf("%d: fmt=\"%s\" width=%d\n",
1395 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1399 if (flag_dump_strings)
1400 dump_strings(n_bytes_to_skip, end_offset);
1402 dump(n_bytes_to_skip, end_offset);
1404 if (fclose(stdin) == EOF)
1405 bb_perror_msg_and_die(bb_msg_standard_input);