/************************************************************************** * * Copyright (C) 1996-97 RA Micro Products & Services Ltd. * Author Robert Quince * EMail robq@fiendish.demoncouk * * This code may be reproduced, copied, or redistributed without * prior consent of the copyright owner, as long as no charge is * made for the code and that this copyright message is included * in an unaltered form. * ************************************************************************** * Dump a file hexadecimal and ASCII (32-127) **************************************************************************/ #include #include #include #include #define LINE_SIZE 16 /* The number of bytes per line of input */ #define OLENGTH 72 /* The number of bytes per line of ouput */ static char hex[] = "0123456789ABCDEF"; /**************************************************************************/ void print_line(unsigned char *input, unsigned long offset, int length) { unsigned char output[OLENGTH]; unsigned char ch; unsigned char *hptr = output + 11; unsigned char *aptr = output + 54; int olen = 0; /* Called with 0 read length ? */ if (length <= 0) return; /* Initialize the output string */ sprintf(output, "%08lX: %41s %16s\n", offset, "", ""); /* Process the input line */ while (length--) { /* Is the character printable ? */ if (((ch = *input++) >= ' ') && (ch <= '~')) *aptr++ = ch; else *aptr++ = '.'; /* Convert the character to hexadecimal */ *hptr++ = hex[ch >> 4]; *hptr++ = hex[ch & 0x0f]; /* Output 2 characters so increment count */ olen += 2; /* Add the padding spaces */ if ((olen % 4) == 0) *hptr++ = ' '; if ((olen % 16) == 0) *hptr++ = ' '; } /* Print the output line */ fwrite(output, OLENGTH, 1, stdout); } /**************************************************************************/ int main(int argc, char *argv[]) { unsigned char buf[2][LINE_SIZE]; unsigned char *iptr; unsigned char *optr; int fd; int rlen; int same; unsigned long repeats; unsigned long old_offset; unsigned long offset; /* Assume that the pathname to dump */ /* is passed as the first argument */ if ((fd = open(argv[1], O_RDONLY)) < 0) { perror("Can't open file"); exit(1); } /* To dump the file read a line's worth of */ /* data at a time (or as much as there is) */ /* and compare it to the previous one. The */ /* comparison is to allow for * lines to */ /* indicate repetition of data. The line */ /* is converted to hexadecimal and output */ /* along with the ASCII representation if */ /* printable or a . otherwise. */ offset = 0; repeats = 0; iptr = buf[0]; optr = buf[1]; do { /* Read a line of input */ if ((rlen = read(fd, iptr, LINE_SIZE)) != LINE_SIZE) { /* Did anything get read in ? */ if (rlen < 0) break; /* Is the old line a repeat ? */ if (repeats != 0) { print_line(optr, old_offset, LINE_SIZE); if (repeats > 1) printf("*\n"); } if (offset != 0) print_line(optr, offset - LINE_SIZE, LINE_SIZE); /* Break to last line print */ break; } /* Compare the read data with the */ /* previously read line */ if (offset != 0) same = memcmp(iptr, optr, LINE_SIZE) == 0; else same = 0; if (same) { /* New line was the same as the old */ if (repeats++ == 0) old_offset = offset - LINE_SIZE; } else { /* New and old lines differ */ if (repeats != 0) { /* Repeated old line */ print_line(optr, old_offset, LINE_SIZE); if (repeats > 1) printf("*\n"); } /* Print the old line if not first time */ if (offset != 0) print_line(optr, offset - LINE_SIZE, LINE_SIZE); /* Swap the buffers now */ if (iptr == buf[0]) { iptr = buf[1]; optr = buf[0]; } else { iptr = buf[0]; optr = buf[1]; } repeats = 0; } /* Increment the current offset */ offset += rlen; } while (1); /* Print the last line */ print_line(iptr, offset, rlen); close(fd); return 0; }