/**************************************************************************** * * * Copyright (C) 1997-2007 A.J.Dunk. * * * * This program is free software. It may be modified and * * redistributed but must not be sold for profit. * * This notice must be present in all modified versions. * * * ****************************************************************************/ /****************************************************************************/ /* HISTORY */ /****************************************************************************/ /* DATE AUTHOR COMMENT */ /*--------------------------------------------------------------------------*/ /* 1997 Anthony Dunk Initial version */ /* 1998 Anthony Dunk Wrapped up multiple hex tools in one */ /* 19/02/03 Anthony Dunk Updated USAGE info and fixing a few bugs */ /* 9/9/04 Carl Eric Codere Improved -c option */ /* 1/11/04 Anthony Dunk Added -diff option */ /* 12/9/07 Anthony Dunk Added -e option for EBCDIC */ /* */ /****************************************************************************/ /* hd.c 13/2/97 AJD This program reads the given file (or stdin) and outputs it as hexadecimal bytes and ascii strings (un-printable characters are displayed as dots). Usage: hd [-d|-c|-e] [filename] - Dump binary file in ascii hex hd -f string [filename] - Find string in binary file hd -a - Convert ascii hex to Binary (assumes address + 16 bytes per line) hd -x[8|16|32] - Convert 8, 16, or 32 bit ascii hex to Binary (assumes one byte/word per line) hd -diff filename1 filename2 [n] - Compare files for differences. n is the optional number of bytes which must be identical for a difference stretch to end */ #include #include #include #include #include #include #define MAX_LINE_LEN 256 /* EBCDIC to ASCII table */ static unsigned char ebcasc[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x5b,0x2e,0x3c,0x28,0x2b,0x21, 0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x5d,0x24,0x2a,0x29,0x3b,0x5e, 0x2d,0x2f,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x2c,0x25,0x5f,0x3e,0x3f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22, 0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67, 0x68,0x69,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70, 0x71,0x72,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x73,0x74,0x75,0x76,0x77,0x78, 0x79,0x7a,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47, 0x48,0x49,0x00,0x00,0x00,0x00,0x00,0x00, 0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50, 0x51,0x52,0x00,0x00,0x00,0x00,0x00,0x00, 0x5c,0x00,0x53,0x54,0x55,0x56,0x57,0x58, 0x59,0x5a,0x00,0x00,0x00,0x00,0x00,0x00, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, 0x38,0x39,0x00,0x00,0x00,0x00,0x00,0x00 }; /* Binary Find 12/3/98 AJD This program searches the binary stream for the given string (or bytes) and reports the hexadecimal location of each occurrence. String length is limited to MAX_STR_LEN defined below. Usage: hd -f string [filename] */ #define MAX_STR_LEN 64 #define BUFLEN (MAX_STR_LEN+1) char buffer [BUFLEN]; void shift_buffer (int c) { int i; for (i=0; i3) { infile=fopen(argv[3],"rb"); } /* clear buffer */ for (i=0; i1) { if (!strcmp(argv[1]+2,"8")) {bits=8;} else if (!strcmp(argv[1]+2,"16")) {bits=16;} else if (!strcmp(argv[1]+2,"32")) {bits=32;} } while (!feof(stdin)) { if (gets(line)==NULL) break; if (feof(stdin)) break; switch (bits) { case 8: sscanf(line,"%x",&byte); fwrite((char*)(&byte),1,1,stdout); break; case 16: sscanf(line,"%x",&shortword); fwrite((char*)(&shortword),1,2,stdout); break; case 32: sscanf(line,"%x",&word); fwrite((char*)(&word),1,4,stdout); break; } } return 0; } /* AJD 1/11/04 */ int hexdiff(char *filename1, char *filename2, int diff_bytes) { int nOffset = 0; unsigned char byte1; unsigned char byte2; FILE *fin1, *fin2; int bEndOfFile1 = 0; int bEndOfFile2 = 0; int bInDifference = 0; int nIdenticalCount = 0; int nNofDiffs = 0; fin1 = fopen(filename1,"rb"); if (fin1==NULL) {fprintf(stderr,"Could not open %s\n",filename1); return 1;} fin2 = fopen(filename2,"rb"); if (fin2==NULL) {fprintf(stderr,"Could not open %s\n",filename2); return 1;} while(1) { if (!fread(&byte1,1,1,fin1)) {bEndOfFile1=1;} if (!fread(&byte2,1,1,fin2)) {bEndOfFile2=1;} if (bEndOfFile1 || bEndOfFile2) break; if (byte1!=byte2) { /* Difference stretch */ bInDifference = 1; nNofDiffs++; nIdenticalCount = 0; } else { if (bInDifference) { nIdenticalCount++; if (nIdenticalCount>diff_bytes) { bInDifference = 0; nIdenticalCount = 0; printf("...\n"); } } } if (bInDifference) { char c1 = byte1; char c2 = byte2; if (byte1<' ' || byte1>=0x7f) c1='.'; if (byte2<' ' || byte2>=0x7f) c2='.'; printf("%08x:",nOffset); printf(" %02x %02x : '%c' '%c'\n",byte1,byte2, c1,c2); } nOffset++; } if (bEndOfFile1 && !bEndOfFile2) { printf("\n%s is longer than %s.\n",filename2,filename1); } else if (!bEndOfFile1 && bEndOfFile2) { printf("\n%s is longer than %s.\n",filename1,filename2); } else { if (nNofDiffs==0) printf("\nThe files are identical.\n"); else printf("\nFiles differ in %d bytes.\n",nNofDiffs); } fclose(fin1); fclose(fin2); return 0; } #define BYTES_PER_LINE 16 #define UNPRINTABLE "." main (argc,argv) int argc; char* argv[]; { char filename [MAX_LINE_LEN]; FILE *file; char bytes[BYTES_PER_LINE]; int i, j; int filename_provided=0; int filesize; int bytes_read=0; long pos=0L; int data_only=0; int C_style=0; int diff = 0; int nEBCDIC = 0; if (argc>5 || (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"-?")))) { fprintf(stderr,"\n"); fprintf(stderr, "Hex Dump Utility (1997-2004)\n"); fprintf(stderr, "----------------------------\n\n"); fprintf(stderr, "Written by Anthony Dunk\n\n"); fprintf(stderr,"Usage: %s [-d|-c|-e] [filename] // Hex Dump\n", argv[0]); fprintf(stderr," %s -f string [filename] // Binary find\n", argv[0]); fprintf(stderr," %s -a < infile > outfile // Asc to binary\n", argv[0]); fprintf(stderr," %s -x[8|16|32] < infile > outfile // Hex to binary\n", argv[0]); fprintf(stderr," %s -diff filename1 filename2 [n] // Show file differences\n", argv[0]); fprintf(stderr,"\n"); fprintf(stderr," OPTIONS:\n"); fprintf(stderr," -d: Supresses the line addresses.\n"); fprintf(stderr," -c: Outputs the data in a form suitable for C programs.\n"); fprintf(stderr," -e: Convert EBCDIC characters to ASCII.\n"); fprintf(stderr," -f: Searches for all occurrences of the string.\n"); fprintf(stderr," The string can be a quoted or unquoted string of\n"); fprintf(stderr," characters or a sequence of hex bytes of the form\n"); fprintf(stderr," \\x41\\x0D\\x0A\n"); fprintf(stderr," -a: Converts a hex dump back into a binary file. This\n"); fprintf(stderr," allows you to modify binary files using a text editor.\n"); fprintf(stderr," -x: Reads a series of 8, 16, or 32 bit hex numbers in (one per line)\n"); fprintf(stderr," and outputs the numbers as binary data.\n"); fprintf(stderr," -diff: Shows differences between two files. n is optional number of\n"); fprintf(stderr," indentical bytes which indicates end of difference stretch (default is 0).\n"); fprintf(stderr,"\n"); return 1; } // Force binary mode to prevent newline chars being modified in stdin or stdout _setmode(0,_O_BINARY); // stdin _setmode(1,_O_BINARY); // stdout /* Check if -f or -a options */ if (argc>1 && !strcmp(argv[1],"-f")) { return binary_find(argc,argv); } else if (argc>1 && !strcmp(argv[1],"-a")) { return asc2bin(argc,argv); } else if (argc>1 && !strncmp(argv[1],"-x",2)) { return hex2bin(argc,argv); } else if (argc>=4 && !strcmp(argv[1],"-diff")) { char *filename1 = argv[2]; char *filename2 = argv[3]; int diff_bytes = 0; // default diff = 1; if (argc==5) diff_bytes = atoi(argv[4]); return hexdiff(filename1,filename2,diff_bytes); } /* No special options, so do a hex dump */ if (argc==2) { if (!strcmp(argv[1],"-e")) nEBCDIC=1; else if (!strcmp(argv[1],"-d") || !strcmp(argv[1],"-c")) { data_only=1; if (!strcmp(argv[1],"-c")) C_style=1; } else { /* If filename given, store it. */ strcpy(filename,argv[1]); filename_provided=1; } } else if (argc==3) { if (!strcmp(argv[1],"-e")) nEBCDIC=1; if (!strcmp(argv[1],"-d") || !strcmp(argv[1],"-c")) { data_only=1; if (!strcmp(argv[1],"-c")) C_style=1; } /* If filename given, store it. */ strcpy(filename,argv[2]); filename_provided=1; } /* Open the input file */ if (filename_provided) file=fopen(filename,"rb"); else file=stdin; if (file==NULL) { fprintf(stderr,"%s: Could not open input file.\n",argv[0]); return 1; } if (file != stdin) { /* If the input filename is not stdin, then get the size of the file. */ if (fseek(file,0,SEEK_END)!=0) { fprintf(stderr,"%s: Could not seek in input file.\n",argv[0]); return 1; } filesize = ftell(file); fseek(file,0,SEEK_SET); if (C_style) { printf("#define DATA_SIZE %d\n",filesize); printf("const char data[DATA_SIZE] = {\n"); } } while (!feof(file)) { bytes_read=fread(bytes,1,BYTES_PER_LINE,file); if (!data_only) {printf("%07lx: ",pos);} pos+=bytes_read; for (i=0; i=' ' && bytes[j]<0x7F) printf("%c",bytes[j]); else printf(UNPRINTABLE); } } printf("'"); } printf("\n"); } if (filename_provided) fclose(file); return 0; }