// // hex -- File hex dump tool. // // 30-Mar-2009 tvb www.LeapSecond.com/tools // #include #include #include #include #define SAFE(c) ( (c >= ' ' && c <= '~') ? c : '.' ) int WIDE = 16; int FULL = 0; time_t Mtime; // Dump given array in hex. void hex_dump (unsigned char *buf, long size) { long i; // current buffer index long n; // bytes left in buffer int j; for (i = 0; i < size; i += WIDE) { n = size - i; // (1) Display address on left. if (FULL) { printf("%.8lX:", i); // display all lines in "full" mode } else { char *pl = &buf[i - WIDE]; // previous line char *cl = &buf[i]; // current line char *nl = &buf[i + WIDE]; // next line // If current line is the same as previous line then skip it. if (n >= WIDE && i >= WIDE && memcmp(cl, pl, WIDE) == 0) { continue; } // If current line is the same as next line then mark it. if (n >= 2 * WIDE && memcmp(cl, nl, WIDE) == 0) { printf("%.8lX*", i); // Otherwise display current line as usual. } else { printf("%.8lX:", i); } } // (2) Display bytes in hexadecimal format. for (j = 0; j < WIDE; j += 1) { if (j < n) { printf(" %.2X", buf[i + j]); } else { printf(" --"); // file not mod-16; partial last line } } // (3) Display bytes as ascii characters on right. printf(" "); for (j = 0; j < WIDE; j += 1) { if (j < n) { printf("%c", SAFE(buf[i + j])); } } printf("\n"); } printf("%.8lX: end (%ld bytes) mtime %ld\n", size, size, Mtime); } // Read entire binary file into array. char *read_file (char *path, long *size) { char *buf; FILE *f; struct _stat st; f = fopen(path, "rb"); if (NULL == f) { fprintf(stderr, "%s: open failed\n", path); exit(1); } if (_fstat(_fileno(f), &st) != 0) { fprintf(stderr, "%s: fstat failed\n", path); exit(1); } Mtime = st.st_mtime; if (st.st_size == 0) { buf = NULL; } else { buf = malloc(st.st_size); if (NULL == buf) { fprintf(stderr, "%s: malloc failed (%ld bytes).\n", path, st.st_size); exit(1); } if (fread(buf, st.st_size, 1, f) != 1) { fprintf(stderr, "%s: read error (size=%ld)\n", path, st.st_size); exit(1); } } *size = st.st_size; fclose(f); return buf; } void main (int argc, char *argv[]) { char *buf; long size; if (argc < 2) { fprintf(stderr, "Usage: hexdump [file]\n"); exit(1); } if (argc > 2) { WIDE = atoi(argv[2]); if (WIDE < 0) { WIDE = -WIDE; FULL = 1; } if (WIDE <= 1) { WIDE = 1; } } buf = read_file(argv[1], &size); hex_dump(buf, size); if (buf != NULL) { free(buf); } }