| /* xxd.c - hexdump. |
| * |
| * Copyright 2015 The Android Open Source Project |
| * |
| * TODO: support for reversing a hexdump back into the original data. |
| * TODO: support > 4GiB files? |
| * TODO: -s seek |
| |
| USE_XXD(NEWTOY(xxd, ">1c#<0=16l#g#<0=2", TOYFLAG_USR|TOYFLAG_BIN)) |
| |
| config XXD |
| bool "xxd" |
| default n |
| help |
| usage: xxd [-c n] [-g n] [-l n] [file] |
| |
| Hexdump a file to stdout. If no file is listed, copy from stdin. |
| Filename "-" is a synonym for stdin. |
| |
| -c n Show n bytes per line (default 16). |
| -g n Group bytes by adding a ' ' every n bytes (default 2). |
| -l n Limit of n bytes before stopping (default is no limit). |
| */ |
| |
| #define FOR_xxd |
| #include "toys.h" |
| |
| static const char* hex_digits = "0123456789abcdef"; |
| |
| GLOBALS( |
| long bytes_per_group; // -g |
| long limit; // -l |
| long bytes_per_line; // -c |
| ) |
| |
| static void xxd_file(FILE *fp) |
| { |
| // "0000000: 4c69 6e75 7820 7665 7273 696f 6e20 332e Linux version 3.". |
| size_t hex_size = 8 + 2 + |
| 2*TT.bytes_per_line + TT.bytes_per_line/TT.bytes_per_group + 1; |
| size_t line_size = hex_size + TT.bytes_per_line + 1; |
| char *line = xmalloc(line_size); |
| int offset = 0, bytes_this_line = 0, index = 0, ch; |
| |
| memset(line, ' ', line_size); |
| line[line_size - 1] = 0; |
| |
| while ((ch = getc(fp)) != EOF) { |
| if (!bytes_this_line) index = sprintf(line, "%08x: ", offset); |
| ++offset; |
| |
| line[index++] = hex_digits[(ch >> 4) & 0xf]; |
| line[index++] = hex_digits[ch & 0xf]; |
| line[hex_size + bytes_this_line] = (ch >= ' ' && ch <= '~') ? ch : '.'; |
| |
| ++bytes_this_line; |
| if (bytes_this_line == TT.bytes_per_line) { |
| puts(line); |
| memset(line, ' ', line_size - 1); |
| bytes_this_line = 0; |
| } else if (!(bytes_this_line % TT.bytes_per_group)) line[index++] = ' '; |
| if ((toys.optflags & FLAG_l) && offset == TT.limit) break; |
| } |
| if (bytes_this_line) { |
| line[hex_size + bytes_this_line] = 0; |
| puts(line); |
| } |
| |
| if (CFG_FREE) free(line); |
| } |
| |
| void xxd_main(void) |
| { |
| FILE *fp; |
| |
| if (!*toys.optargs || !strcmp(*toys.optargs, "-")) fp = stdin; |
| else fp = xfopen(*toys.optargs, "r"); |
| |
| xxd_file(fp); |
| |
| fclose(fp); |
| } |