1 /* od -- dump files in octal and other formats
2 Copyright (C) 92, 1995-2004 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Jim Meyering. */
20 /* Busyboxed by Denis Vlasenko
22 Based on od.c from coreutils-5.2.1
25 00000073 t parse_old_offset
27 00000090 r long_options
28 00000092 t print_named_ascii
29 000000bf t print_ascii
30 00000168 t write_block
31 00000366 t decode_format_string
34 Tested for compat with coreutils 6.3
35 using this script. Minor differences fixed.
39 time /path/to/coreutils/od \
48 diff -u -a std bbox >bbox.diff || { echo Different!; sleep 1; }
55 #define assert(a) ((void)0)
57 /* Check for 0x7f is a coreutils 6.3 addition */
58 #define ISPRINT(c) (((c)>=' ') && (c) != 0x7f)
60 typedef long double longdouble_t;
61 typedef unsigned long long ulonglong_t;
62 typedef long long llong;
65 # define xstrtooff_sfx xstrtoull_sfx
67 # define xstrtooff_sfx xstrtoul_sfx
70 /* The default number of input bytes per output line. */
71 #define DEFAULT_BYTES_PER_BLOCK 16
73 /* The number of decimal digits of precision in a float. */
78 /* The number of decimal digits of precision in a double. */
83 /* The number of decimal digits of precision in a long double. */
85 # define LDBL_DIG DBL_DIG
111 /* Each output format specification (from '-t spec' or from
112 old-style options) is represented by one of these structures. */
114 enum output_format fmt;
116 void (*print_function) (size_t, const char *, const char *);
118 int hexl_mode_trailer;
122 /* Convert the number of 8-bit bytes of a binary representation to
123 the number of characters (digits + sign if the type is signed)
124 required to represent the same quantity in the specified base/type.
125 For example, a 32-bit (4-byte) quantity may require a field width
126 as wide as the following for these types:
130 8 unsigned hexadecimal */
132 static const uint8_t bytes_to_oct_digits[] ALIGN1 =
133 {0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43};
135 static const uint8_t bytes_to_signed_dec_digits[] ALIGN1 =
136 {1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40};
138 static const uint8_t bytes_to_unsigned_dec_digits[] ALIGN1 =
139 {0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39};
141 static const uint8_t bytes_to_hex_digits[] ALIGN1 =
142 {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32};
144 /* Convert enum size_spec to the size of the named type. */
145 static const signed char width_bytes[] ALIGN1 = {
156 /* Ensure that for each member of 'enum size_spec' there is an
157 initializer in the width_bytes array. */
159 int assert_width_bytes_matches_size_spec_decl
160 [ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
163 static smallint flag_dump_strings;
164 /* Non-zero if an old-style 'pseudo-address' was specified. */
165 static smallint flag_pseudo_start;
166 static smallint limit_bytes_to_format;
167 /* When zero and two or more consecutive blocks are equal, format
168 only the first block and output an asterisk alone on the following
169 line to indicate that identical blocks have been elided. */
170 static smallint verbose;
171 static smallint ioerror;
173 static size_t string_min;
175 /* An array of specs describing how to format each input block. */
176 static size_t n_specs;
177 static struct tspec *spec;
179 /* Function that accepts an address and an optional following char,
180 and prints the address and char to stdout. */
181 static void (*format_address)(off_t, char);
182 /* The difference between the old-style pseudo starting address and
183 the number of bytes to skip. */
184 static off_t pseudo_offset;
185 /* The number of input bytes to skip before formatting and writing. */
186 static off_t n_bytes_to_skip;
187 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
188 input is formatted. */
189 /* The maximum number of bytes that will be formatted. */
190 static off_t max_bytes_to_format;
191 /* The offset of the first byte after the last byte to be formatted. */
192 static off_t end_offset;
194 /* The number of input bytes formatted per output line. It must be
195 a multiple of the least common multiple of the sizes associated with
196 the specified output types. It should be as large as possible, but
197 no larger than 16 -- unless specified with the -w option. */
198 static size_t bytes_per_block;
200 /* Human-readable representation of *file_list (for error messages).
201 It differs from *file_list only when *file_list is "-". */
202 static char const *input_filename;
204 /* A NULL-terminated list of the file-arguments from the command line. */
205 static char const *const *file_list;
207 /* Initializer for file_list if no file-arguments
208 were specified on the command line. */
209 static char const *const default_file_list[] = { "-", NULL };
211 /* The input stream associated with the current file. */
212 static FILE *in_stream;
214 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t)
215 static unsigned char integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1] ALIGN1 = {
216 [sizeof(char)] = CHAR,
217 #if USHRT_MAX != UCHAR_MAX
218 [sizeof(short)] = SHORT,
220 #if UINT_MAX != USHRT_MAX
223 #if ULONG_MAX != UINT_MAX
224 [sizeof(long)] = LONG,
226 #if ULLONG_MAX != ULONG_MAX
227 [sizeof(ulonglong_t)] = LONG_LONG,
231 #define MAX_FP_TYPE_SIZE sizeof(longdouble_t)
232 static unsigned char fp_type_size[MAX_FP_TYPE_SIZE + 1] ALIGN1 = {
233 /* gcc seems to allow repeated indexes. Last one stays */
234 [sizeof(longdouble_t)] = FLOAT_LONG_DOUBLE,
235 [sizeof(double)] = FLOAT_DOUBLE,
236 [sizeof(float)] = FLOAT_SINGLE
241 gcd(unsigned u, unsigned v)
252 /* Compute the least common multiple of U and V. */
254 lcm(unsigned u, unsigned v) {
255 unsigned t = gcd(u, v);
262 print_s_char(size_t n_bytes, const char *block, const char *fmt_string)
265 int tmp = *(signed char *) block;
266 printf(fmt_string, tmp);
267 block += sizeof(unsigned char);
272 print_char(size_t n_bytes, const char *block, const char *fmt_string)
275 unsigned tmp = *(unsigned char *) block;
276 printf(fmt_string, tmp);
277 block += sizeof(unsigned char);
282 print_s_short(size_t n_bytes, const char *block, const char *fmt_string)
284 n_bytes /= sizeof(signed short);
286 int tmp = *(signed short *) block;
287 printf(fmt_string, tmp);
288 block += sizeof(unsigned short);
293 print_short(size_t n_bytes, const char *block, const char *fmt_string)
295 n_bytes /= sizeof(unsigned short);
297 unsigned tmp = *(unsigned short *) block;
298 printf(fmt_string, tmp);
299 block += sizeof(unsigned short);
304 print_int(size_t n_bytes, const char *block, const char *fmt_string)
306 n_bytes /= sizeof(unsigned);
308 unsigned tmp = *(unsigned *) block;
309 printf(fmt_string, tmp);
310 block += sizeof(unsigned);
314 #if UINT_MAX == ULONG_MAX
315 # define print_long print_int
318 print_long(size_t n_bytes, const char *block, const char *fmt_string)
320 n_bytes /= sizeof(unsigned long);
322 unsigned long tmp = *(unsigned long *) block;
323 printf(fmt_string, tmp);
324 block += sizeof(unsigned long);
329 #if ULONG_MAX == ULLONG_MAX
330 # define print_long_long print_long
333 print_long_long(size_t n_bytes, const char *block, const char *fmt_string)
335 n_bytes /= sizeof(ulonglong_t);
337 ulonglong_t tmp = *(ulonglong_t *) block;
338 printf(fmt_string, tmp);
339 block += sizeof(ulonglong_t);
345 print_float(size_t n_bytes, const char *block, const char *fmt_string)
347 n_bytes /= sizeof(float);
349 float tmp = *(float *) block;
350 printf(fmt_string, tmp);
351 block += sizeof(float);
356 print_double(size_t n_bytes, const char *block, const char *fmt_string)
358 n_bytes /= sizeof(double);
360 double tmp = *(double *) block;
361 printf(fmt_string, tmp);
362 block += sizeof(double);
367 print_long_double(size_t n_bytes, const char *block, const char *fmt_string)
369 n_bytes /= sizeof(longdouble_t);
371 longdouble_t tmp = *(longdouble_t *) block;
372 printf(fmt_string, tmp);
373 block += sizeof(longdouble_t);
377 /* print_[named]_ascii are optimized for speed.
378 * Remember, someday you may want to pump gigabytes thru this thing.
379 * Saving a dozen of .text bytes here is counter-productive */
382 print_named_ascii(size_t n_bytes, const char *block,
383 const char *unused_fmt_string ATTRIBUTE_UNUSED)
385 /* Names for some non-printing characters. */
386 static const char charname[33][3] ALIGN1 = {
387 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
388 " bs", " ht", " nl", " vt", " ff", " cr", " so", " si",
389 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
390 "can", " em", "sub", "esc", " fs", " gs", " rs", " us",
393 // buf[N] pos: 01234 56789
394 char buf[12] = " x\0 0xx\0";
395 // actually " x\0 xxx\0", but I want to share the string with below.
396 // [12] because we take three 32bit stack slots anyway, and
397 // gcc is too dumb to initialize with constant stores,
398 // it copies initializer from rodata. Oh well.
401 unsigned masked_c = *(unsigned char *) block++;
404 if (masked_c == 0x7f) {
405 fputs(" del", stdout);
408 if (masked_c > ' ') {
413 /* Why? Because printf(" %3.3s") is much slower... */
414 buf[6] = charname[masked_c][0];
415 buf[7] = charname[masked_c][1];
416 buf[8] = charname[masked_c][2];
417 fputs(buf+5, stdout);
422 print_ascii(size_t n_bytes, const char *block,
423 const char *unused_fmt_string ATTRIBUTE_UNUSED)
425 // buf[N] pos: 01234 56789
426 char buf[12] = " x\0 0xx\0";
430 unsigned c = *(unsigned char *) block++;
465 default: /* c is never larger than 040 */
466 buf[7] = (c >> 3) + '0';
467 buf[8] = (c & 7) + '0';
474 /* Given a list of one or more input filenames FILE_LIST, set the global
475 file pointer IN_STREAM and the global string INPUT_FILENAME to the
476 first one that can be successfully opened. Modify FILE_LIST to
477 reference the next filename in the list. A file name of "-" is
478 interpreted as standard input. If any file open fails, give an error
479 message and return nonzero. */
485 input_filename = *file_list;
489 in_stream = fopen_or_warn_stdin(input_filename);
491 if (in_stream == stdin)
492 input_filename = bb_msg_standard_input;
498 if (limit_bytes_to_format && !flag_dump_strings)
499 setbuf(in_stream, NULL);
502 /* Test whether there have been errors on in_stream, and close it if
503 it is not standard input. Return nonzero if there has been an error
504 on in_stream or stdout; return zero otherwise. This function will
505 report more than one error only if both a read and a write error
506 have occurred. IN_ERRNO, if nonzero, is the error number
507 corresponding to the most recent action for IN_STREAM. */
510 check_and_close(void)
513 if (ferror(in_stream)) {
514 bb_error_msg("%s: read error", input_filename);
517 fclose_if_not_stdin(in_stream);
521 if (ferror(stdout)) {
522 bb_error_msg("write error");
527 /* If S points to a single valid modern od format string, put
528 a description of that format in *TSPEC, make *NEXT point at the
529 character following the just-decoded format (if *NEXT is non-NULL),
530 and return zero. For example, if S were "d4afL"
531 *NEXT would be set to "afL" and *TSPEC would be
533 fmt = SIGNED_DECIMAL;
534 size = INT or LONG; (whichever integral_type_size[4] resolves to)
535 print_function = print_int; (assuming size == INT)
536 fmt_string = "%011d%c";
538 S_ORIG is solely for reporting errors. It should be the full format
542 decode_one_format(const char *s_orig, const char *s, const char **next,
545 enum size_spec size_spec;
547 enum output_format fmt;
550 char *fmt_string = NULL;
551 void (*print_function) (size_t, const char *, const char *);
553 unsigned field_width = 0;
556 assert(tspec != NULL);
563 static const char CSIL[] ALIGN1 = "CSIL";
566 p = strchr(CSIL, *s);
570 size = bb_strtou(s, &end, 0);
572 || MAX_INTEGRAL_TYPE_SIZE < size
573 || integral_type_size[size] == NO_SIZE
575 bb_error_msg_and_die("invalid type string '%s'; "
576 "%u-byte %s type is not supported",
577 s_orig, size, "integral");
582 static const uint8_t CSIL_sizeof[] = {
588 size = CSIL_sizeof[p - CSIL];
591 #define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \
592 ((Spec) == LONG_LONG ? (Max_format) \
593 : ((Spec) == LONG ? (Long_format) : (Min_format)))
595 #define FMT_BYTES_ALLOCATED 9
596 size_spec = integral_type_size[size];
599 static const char doux[] ALIGN1 = "doux";
600 static const char doux_fmt_letter[][4] = {
601 "lld", "llo", "llu", "llx"
603 static const enum output_format doux_fmt[] = {
609 static const uint8_t *const doux_bytes_to_XXX[] = {
610 bytes_to_signed_dec_digits,
612 bytes_to_unsigned_dec_digits,
615 static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
622 pos = strchr(doux, c) - doux;
624 field_width = doux_bytes_to_XXX[pos][size];
625 p = doux_fmt_letter[pos] + 2;
626 if (size_spec == LONG) p--;
627 if (size_spec == LONG_LONG) p -= 2;
628 fmt_string = xasprintf(doux_fmtstring[pos], field_width, p);
633 print_function = (fmt == SIGNED_DECIMAL
638 print_function = (fmt == SIGNED_DECIMAL
643 print_function = print_int;
646 print_function = print_long;
648 default: /* case LONG_LONG: */
649 print_function = print_long_long;
656 static const char FDL[] ALIGN1 = "FDL";
658 fmt = FLOATING_POINT;
662 size = sizeof(double);
664 size = bb_strtou(s, &end, 0);
665 if (errno == ERANGE || size > MAX_FP_TYPE_SIZE
666 || fp_type_size[size] == NO_SIZE
668 bb_error_msg_and_die("invalid type string '%s'; "
669 "%u-byte %s type is not supported",
670 s_orig, size, "floating point");
675 static const uint8_t FDL_sizeof[] = {
678 sizeof(longdouble_t),
681 size = FDL_sizeof[p - FDL];
684 size_spec = fp_type_size[size];
688 print_function = print_float;
689 field_width = FLT_DIG + 8;
690 /* Don't use %#e; not all systems support it. */
691 fmt_string = xasprintf(" %%%d.%de", field_width, FLT_DIG);
694 print_function = print_double;
695 field_width = DBL_DIG + 8;
696 fmt_string = xasprintf(" %%%d.%de", field_width, DBL_DIG);
698 default: /* case FLOAT_LONG_DOUBLE: */
699 print_function = print_long_double;
700 field_width = LDBL_DIG + 8;
701 fmt_string = xasprintf(" %%%d.%dLe", field_width, LDBL_DIG);
709 fmt = NAMED_CHARACTER;
711 print_function = print_named_ascii;
718 print_function = print_ascii;
722 bb_error_msg_and_die("invalid character '%c' "
723 "in type string '%s'", *s, s_orig);
726 tspec->size = size_spec;
728 tspec->print_function = print_function;
729 tspec->fmt_string = fmt_string;
731 tspec->field_width = field_width;
732 tspec->hexl_mode_trailer = (*s == 'z');
733 if (tspec->hexl_mode_trailer)
740 /* Decode the modern od format string S. Append the decoded
741 representation to the global array SPEC, reallocating SPEC if
742 necessary. Return zero if S is valid, nonzero otherwise. */
745 decode_format_string(const char *s)
747 const char *s_orig = s;
753 decode_one_format(s_orig, s, &next, &tspec);
758 spec = xrealloc(spec, n_specs * sizeof(*spec));
759 memcpy(&spec[n_specs-1], &tspec, sizeof *spec);
763 /* Given a list of one or more input filenames FILE_LIST, set the global
764 file pointer IN_STREAM to position N_SKIP in the concatenation of
765 those files. If any file operation fails or if there are fewer than
766 N_SKIP bytes in the combined input, give an error message and return
767 nonzero. When possible, use seek rather than read operations to
768 advance IN_STREAM. */
776 while (in_stream) { /* !EOF */
777 struct stat file_stats;
779 /* First try seeking. For large offsets, this extra work is
780 worthwhile. If the offset is below some threshold it may be
781 more efficient to move the pointer by reading. There are two
782 issues when trying to seek:
783 - the file must be seekable.
784 - before seeking to the specified position, make sure
785 that the new position is in the current file.
786 Try to do that by getting file's size using fstat.
787 But that will work only for regular files. */
789 /* The st_size field is valid only for regular files
790 (and for symbolic links, which cannot occur here).
791 If the number of bytes left to skip is at least
792 as large as the size of the current file, we can
793 decrement n_skip and go on to the next file. */
794 if (fstat(fileno(in_stream), &file_stats) == 0
795 && S_ISREG(file_stats.st_mode) && file_stats.st_size >= 0
797 if (file_stats.st_size < n_skip) {
798 n_skip -= file_stats.st_size;
799 /* take check&close / open_next route */
801 if (fseeko(in_stream, n_skip, SEEK_CUR) != 0)
806 /* If it's not a regular file with nonnegative size,
807 position the file pointer by reading. */
809 size_t n_bytes_read, n_bytes_to_read = BUFSIZ;
812 if (n_skip < n_bytes_to_read)
813 n_bytes_to_read = n_skip;
814 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);
815 n_skip -= n_bytes_read;
816 if (n_bytes_read != n_bytes_to_read)
817 break; /* EOF on this file or error */
828 bb_error_msg_and_die("cannot skip past end of combined input");
832 typedef void FN_format_address(off_t address, char c);
835 format_address_none(off_t address ATTRIBUTE_UNUSED, char c ATTRIBUTE_UNUSED)
839 static char address_fmt[] ALIGN1 = "%0n"OFF_FMT"xc";
840 /* Corresponds to 'x' above */
841 #define address_base_char address_fmt[sizeof(address_fmt)-3]
842 /* Corresponds to 'n' above */
843 #define address_pad_len_char address_fmt[2]
846 format_address_std(off_t address, char c)
848 /* Corresponds to 'c' */
849 address_fmt[sizeof(address_fmt)-2] = c;
850 printf(address_fmt, address);
853 #if ENABLE_GETOPT_LONG
854 /* only used with --traditional */
856 format_address_paren(off_t address, char c)
859 format_address_std(address, ')');
864 format_address_label(off_t address, char c)
866 format_address_std(address, ' ');
867 format_address_paren(address + pseudo_offset, c);
872 dump_hexl_mode_trailer(size_t n_bytes, const char *block)
876 unsigned c = *(unsigned char *) block++;
877 c = (ISPRINT(c) ? c : '.');
883 /* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
884 of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
885 CURR_BLOCK in the concatenation of input files, and it is printed
886 (optionally) only before the output line associated with the first
887 format spec. When duplicate blocks are being abbreviated, the output
888 for a sequence of identical input blocks is the output for the first
889 block followed by an asterisk alone on a line. It is valid to compare
890 the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
891 That condition may be false only for the last input block -- and then
892 only when it has not been padded to length BYTES_PER_BLOCK. */
895 write_block(off_t current_offset, size_t n_bytes,
896 const char *prev_block, const char *curr_block)
898 static char first = 1;
899 static char prev_pair_equal = 0;
902 if (!verbose && !first
903 && n_bytes == bytes_per_block
904 && memcmp(prev_block, curr_block, bytes_per_block) == 0
906 if (prev_pair_equal) {
907 /* The two preceding blocks were equal, and the current
908 block is the same as the last one, so print nothing. */
916 for (i = 0; i < n_specs; i++) {
918 format_address(current_offset, '\0');
920 printf("%*s", address_pad_len_char - '0', "");
921 (*spec[i].print_function) (n_bytes, curr_block, spec[i].fmt_string);
922 if (spec[i].hexl_mode_trailer) {
923 /* space-pad out to full line width, then dump the trailer */
924 int datum_width = width_bytes[spec[i].size];
925 int blank_fields = (bytes_per_block - n_bytes) / datum_width;
926 int field_width = spec[i].field_width + 1;
927 printf("%*s", blank_fields * field_width, "");
928 dump_hexl_mode_trailer(n_bytes, curr_block);
936 read_block(size_t n, char *block, size_t *n_bytes_in_buffer)
938 assert(0 < n && n <= bytes_per_block);
940 *n_bytes_in_buffer = 0;
945 while (in_stream != NULL) { /* EOF. */
949 n_needed = n - *n_bytes_in_buffer;
950 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);
951 *n_bytes_in_buffer += n_read;
952 if (n_read == n_needed)
954 /* error check is done in check_and_close */
960 /* Return the least common multiple of the sizes associated
961 with the format specs. */
969 for (i = 0; i < n_specs; i++)
970 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);
974 #if ENABLE_GETOPT_LONG
975 /* If S is a valid traditional offset specification with an optional
976 leading '+' return nonzero and set *OFFSET to the offset it denotes. */
979 parse_old_offset(const char *s, off_t *offset)
981 static const struct suffix_mult Bb[] = {
989 /* Skip over any leading '+'. */
990 if (s[0] == '+') ++s;
992 /* Determine the radix we'll use to interpret S. If there is a '.',
993 * it's decimal, otherwise, if the string begins with '0X'or '0x',
994 * it's hexadecimal, else octal. */
998 p[0] = '\0'; /* cheating */
1000 } else if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
1003 *offset = xstrtooff_sfx(s, radix, Bb);
1006 return (*offset >= 0);
1010 /* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
1011 formatted block to standard output, and repeat until the specified
1012 maximum number of bytes has been read or until all input has been
1013 processed. If the last block read is smaller than BYTES_PER_BLOCK
1014 and its size is not a multiple of the size associated with a format
1015 spec, extend the input block with zero bytes until its length is a
1016 multiple of all format spec sizes. Write the final block. Finally,
1017 write on a line by itself the offset of the byte after the last byte
1018 read. Accumulate return values from calls to read_block and
1019 check_and_close, and if any was nonzero, return nonzero.
1020 Otherwise, return zero. */
1026 off_t current_offset;
1028 size_t n_bytes_read;
1030 block[0] = xmalloc(2*bytes_per_block);
1031 block[1] = block[0] + bytes_per_block;
1033 current_offset = n_bytes_to_skip;
1036 if (limit_bytes_to_format) {
1039 if (current_offset >= end_offset) {
1043 n_needed = MIN(end_offset - current_offset,
1044 (off_t) bytes_per_block);
1045 read_block(n_needed, block[idx], &n_bytes_read);
1046 if (n_bytes_read < bytes_per_block)
1048 assert(n_bytes_read == bytes_per_block);
1049 write_block(current_offset, n_bytes_read,
1050 block[!idx], block[idx]);
1051 current_offset += n_bytes_read;
1056 read_block(bytes_per_block, block[idx], &n_bytes_read);
1057 if (n_bytes_read < bytes_per_block)
1059 assert(n_bytes_read == bytes_per_block);
1060 write_block(current_offset, n_bytes_read,
1061 block[!idx], block[idx]);
1062 current_offset += n_bytes_read;
1067 if (n_bytes_read > 0) {
1069 size_t bytes_to_write;
1073 /* Make bytes_to_write the smallest multiple of l_c_m that
1074 is at least as large as n_bytes_read. */
1075 bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m);
1077 memset(block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read);
1078 write_block(current_offset, bytes_to_write,
1079 block[!idx], block[idx]);
1080 current_offset += n_bytes_read;
1083 format_address(current_offset, '\n');
1085 if (limit_bytes_to_format && current_offset >= end_offset)
1091 /* Read a single byte into *C from the concatenation of the input files
1092 named in the global array FILE_LIST. On the first call to this
1093 function, the global variable IN_STREAM is expected to be an open
1094 stream associated with the input file INPUT_FILENAME. If IN_STREAM
1095 is at end-of-file, close it and update the global variables IN_STREAM
1096 and INPUT_FILENAME so they correspond to the next file in the list.
1097 Then try to read a byte from the newly opened file. Repeat if
1098 necessary until EOF is reached for the last file in FILE_LIST, then
1099 set *C to EOF and return. Subsequent calls do likewise. The return
1100 value is nonzero if any errors occured, zero otherwise. */
1105 while (in_stream) { /* !EOF */
1106 *c = fgetc(in_stream);
1115 /* Read N bytes into BLOCK from the concatenation of the input files
1116 named in the global array FILE_LIST. On the first call to this
1117 function, the global variable IN_STREAM is expected to be an open
1118 stream associated with the input file INPUT_FILENAME. If all N
1119 bytes cannot be read from IN_STREAM, close IN_STREAM and update
1120 the global variables IN_STREAM and INPUT_FILENAME. Then try to
1121 read the remaining bytes from the newly opened file. Repeat if
1122 necessary until EOF is reached for the last file in FILE_LIST.
1123 On subsequent calls, don't modify BLOCK and return zero. Set
1124 *N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
1125 it will be detected through ferror when the stream is about to be
1126 closed. If there is an error, give a message but continue reading
1127 as usual and return nonzero. Otherwise return zero. */
1129 /* STRINGS mode. Find each "string constant" in the input.
1130 A string constant is a run of at least 'string_min' ASCII
1131 graphic (or formatting) characters terminated by a null.
1132 Based on a function written by Richard Stallman for a
1133 traditional version of od. Return nonzero if an error
1134 occurs. Otherwise, return zero. */
1139 size_t bufsize = MAX(100, string_min);
1140 char *buf = xmalloc(bufsize);
1141 off_t address = n_bytes_to_skip;
1147 /* See if the next 'string_min' chars are all printing chars. */
1149 if (limit_bytes_to_format && (end_offset - string_min <= address))
1152 while (!limit_bytes_to_format || address < end_offset) {
1154 bufsize += bufsize/8;
1155 buf = xrealloc(buf, bufsize);
1158 if (c < 0) { /* EOF */
1166 goto tryline; /* It isn't; give up on this string. */
1167 buf[i++] = c; /* String continues; store it all. */
1170 if (i < string_min) /* Too short! */
1173 /* If we get here, the string is all printable and null-terminated,
1174 * so print it. It is all in 'buf' and 'i' is its length. */
1176 format_address(address - i - 1, ' ');
1178 for (i = 0; (c = buf[i]); i++) {
1180 case '\007': fputs("\\a", stdout); break;
1181 case '\b': fputs("\\b", stdout); break;
1182 case '\f': fputs("\\f", stdout); break;
1183 case '\n': fputs("\\n", stdout); break;
1184 case '\r': fputs("\\r", stdout); break;
1185 case '\t': fputs("\\t", stdout); break;
1186 case '\v': fputs("\\v", stdout); break;
1187 default: putc(c, stdout);
1193 /* We reach this point only if we search through
1194 (max_bytes_to_format - string_min) bytes before reaching EOF. */
1200 int od_main(int argc, char **argv);
1201 int od_main(int argc, char **argv)
1203 static const struct suffix_mult bkm[] = {
1211 /* The old-style 'pseudo starting address' to be printed in parentheses
1212 after any true address. */
1213 off_t pseudo_start = 0; // only for gcc
1233 OPT_traditional = (1 << 18) * ENABLE_GETOPT_LONG,
1235 #if ENABLE_GETOPT_LONG
1236 static const char od_longopts[] ALIGN1 =
1237 "skip-bytes\0" Required_argument "j"
1238 "address-radix\0" Required_argument "A"
1239 "read-bytes\0" Required_argument "N"
1240 "format\0" Required_argument "t"
1241 "output-duplicates\0" No_argument "v"
1242 "strings\0" Optional_argument "S"
1243 "width\0" Optional_argument "w"
1244 "traditional\0" No_argument "\xff"
1247 char *str_A, *str_N, *str_j, *str_S;
1249 llist_t *lst_t = NULL;
1252 format_address = format_address_std;
1253 address_base_char = 'o';
1254 address_pad_len_char = '7';
1255 /* flag_dump_strings = 0; - already is */
1257 /* Parse command line */
1258 opt_complementary = "t::"; // list
1259 #if ENABLE_GETOPT_LONG
1260 applet_long_options = od_longopts;
1262 opt = getopt32(argv, "A:N:abcdfhij:lot:vxsS:"
1263 "w::", // -w with optional param
1264 // -S was -s and also had optional parameter
1265 // but in coreutils 6.3 it was renamed and now has
1266 // _mandatory_ parameter
1267 &str_A, &str_N, &str_j, &lst_t, &str_S, &str_w);
1271 static const char doxn[] ALIGN1 = "doxn";
1272 static const char doxn_address_base_char[] ALIGN1 = {
1273 'u', 'o', 'x', /* '?' fourth one is not important */
1275 static const uint8_t doxn_address_pad_len_char[] ALIGN1 = {
1276 '7', '7', '6', /* '?' */
1280 p = strchr(doxn, str_A[0]);
1282 bb_error_msg_and_die("bad output address radix "
1283 "'%c' (must be [doxn])", str_A[0]);
1285 if (pos == 3) format_address = format_address_none;
1286 address_base_char = doxn_address_base_char[pos];
1287 address_pad_len_char = doxn_address_pad_len_char[pos];
1290 limit_bytes_to_format = 1;
1291 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm);
1293 if (opt & OPT_a) decode_format_string("a");
1294 if (opt & OPT_b) decode_format_string("oC");
1295 if (opt & OPT_c) decode_format_string("c");
1296 if (opt & OPT_d) decode_format_string("u2");
1297 if (opt & OPT_f) decode_format_string("fF");
1298 if (opt & OPT_h) decode_format_string("x2");
1299 if (opt & OPT_i) decode_format_string("d2");
1300 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm);
1301 if (opt & OPT_l) decode_format_string("d4");
1302 if (opt & OPT_o) decode_format_string("o2");
1303 //if (opt & OPT_t)...
1305 decode_format_string(lst_t->data);
1306 lst_t = lst_t->link;
1308 if (opt & OPT_v) verbose = 1;
1309 if (opt & OPT_x) decode_format_string("x2");
1310 if (opt & OPT_s) decode_format_string("d2");
1313 string_min = xstrtou_sfx(str_S, 0, bkm);
1314 flag_dump_strings = 1;
1316 //if (opt & OPT_w)...
1317 //if (opt & OPT_traditional)...
1319 if (flag_dump_strings && n_specs > 0)
1320 bb_error_msg_and_die("no type may be specified when dumping strings");
1322 /* If the --traditional option is used, there may be from
1323 * 0 to 3 remaining command line arguments; handle each case
1325 * od [file] [[+]offset[.][b] [[+]label[.][b]]]
1326 * The offset and pseudo_start have the same syntax.
1328 * FIXME: POSIX 1003.1-2001 with XSI requires support for the
1329 * traditional syntax even if --traditional is not given. */
1331 #if ENABLE_GETOPT_LONG
1332 if (opt & OPT_traditional) {
1336 if (parse_old_offset(argv[0], &o1)) {
1337 n_bytes_to_skip = o1;
1341 } else if (argc == 2) {
1342 if (parse_old_offset(argv[0], &o1)
1343 && parse_old_offset(argv[1], &o2)
1345 n_bytes_to_skip = o1;
1346 flag_pseudo_start = 1;
1350 } else if (parse_old_offset(argv[1], &o2)) {
1351 n_bytes_to_skip = o2;
1356 bb_error_msg_and_die("invalid second operand "
1357 "in compatibility mode '%s'", argv[1]);
1359 } else if (argc == 3) {
1360 if (parse_old_offset(argv[1], &o1)
1361 && parse_old_offset(argv[2], &o2)
1363 n_bytes_to_skip = o1;
1364 flag_pseudo_start = 1;
1370 bb_error_msg_and_die("in compatibility mode "
1371 "the last two arguments must be offsets");
1373 } else if (argc > 3) {
1374 bb_error_msg_and_die("compatibility mode supports "
1375 "at most three arguments");
1378 if (flag_pseudo_start) {
1379 if (format_address == format_address_none) {
1380 address_base_char = 'o';
1381 address_pad_len_char = '7';
1382 format_address = format_address_paren;
1384 format_address = format_address_label;
1389 if (limit_bytes_to_format) {
1390 end_offset = n_bytes_to_skip + max_bytes_to_format;
1391 if (end_offset < n_bytes_to_skip)
1392 bb_error_msg_and_die("skip-bytes + read-bytes is too large");
1396 decode_format_string("o2");
1400 /* If no files were listed on the command line,
1401 set the global pointer FILE_LIST so that it
1402 references the null-terminated list of one name: "-". */
1403 file_list = default_file_list;
1405 /* Set the global pointer FILE_LIST so that it
1406 references the first file-argument on the command-line. */
1407 file_list = (char const *const *) argv;
1410 /* open the first input file */
1412 /* skip over any unwanted header bytes */
1413 skip(n_bytes_to_skip);
1417 pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0);
1419 /* Compute output block length. */
1422 if (opt & OPT_w) { /* -w: width */
1423 bytes_per_block = 32;
1425 bytes_per_block = xatou(str_w);
1426 if (!bytes_per_block || bytes_per_block % l_c_m != 0) {
1427 bb_error_msg("warning: invalid width %zu; using %d instead",
1428 bytes_per_block, l_c_m);
1429 bytes_per_block = l_c_m;
1432 bytes_per_block = l_c_m;
1433 if (l_c_m < DEFAULT_BYTES_PER_BLOCK)
1434 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;
1438 for (i = 0; i < n_specs; i++) {
1439 printf("%d: fmt=\"%s\" width=%d\n",
1440 i, spec[i].fmt_string, width_bytes[spec[i].size]);
1444 if (flag_dump_strings)
1449 if (fclose(stdin) == EOF)
1450 bb_perror_msg_and_die(bb_msg_standard_input);