diff --git a/userland/Makefile b/userland/Makefile index 4908d6cf..4af87e6c 100644 --- a/userland/Makefile +++ b/userland/Makefile @@ -18,6 +18,7 @@ BIN_TARGET_NAMES := \ fib \ grep \ halt \ + hexdump \ imgview \ init \ init-test \ diff --git a/userland/hexdump.c b/userland/hexdump.c new file mode 100644 index 00000000..41afa6b9 --- /dev/null +++ b/userland/hexdump.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + +static void dump_file(int fd, bool canonical) { + size_t offset = 0; + for (;;) { + uint8_t buf[16]; + ssize_t nread; + size_t cursor = 0; + for (; cursor < sizeof(buf);) { + nread = read(fd, (char*)buf + cursor, sizeof(buf) - cursor); + if (nread < 0) { + perror("read"); + return; + } + if (nread == 0) + break; + cursor += nread; + } + size_t len = cursor; + if (len == 0) + break; + + printf("%08x", offset); + offset += 0x10; + + if (canonical) { + printf(" "); + for (size_t i = 0; i < sizeof(buf); ++i) { + if (i < len) + printf(" %02x", buf[i]); + else + printf(" "); + if (i == 7) + printf(" "); + } + printf(" |"); + for (size_t i = 0; i < len; ++i) + putchar(isprint(buf[i]) ? buf[i] : '.'); + printf("|\n"); + } else { + for (size_t i = 0; i < len; i += 2) { + if (i + 1 < cursor) + printf(" %04x", (buf[i + 1] << 8) | buf[i]); + else + printf(" 00%02x", buf[i]); + } + puts(""); + } + + if (nread == 0) + break; + } +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + dprintf(STDERR_FILENO, "Usage: hexdump [-C] FILE...\n"); + return EXIT_FAILURE; + } + + bool canonical = false; + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-C")) { + canonical = true; + break; + } + } + + for (int i = 1; i < argc; ++i) { + const char* filename = argv[i]; + if (!strcmp(filename, "-C")) + continue; + int fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("open"); + continue; + } + dump_file(fd, canonical); + close(fd); + } + + return EXIT_SUCCESS; +}