//---------------------------------------------------------------- // fileview.cpp // // This program displays the contents of a specified file // in hexadecimal and ascii formats (including any device // special files representing storage media). A user may // navigate the file's contents using arrow-key commands, // or may adjust the format of the hexadecimal display to // select from among four data-sizes: byte (B), word (W), // doubleword (D) or quadword (Q). // // compile using: // root# g++ -o fileview fileview.cpp -lncurses // root# chmod a+s fileview // // execute using: // user$ fileview // e.g., user$ fileview /dev/hda // // programmer: ALLAN CRUSE // written on: 26 OCT 2002 // revised on: 01 NOV 2004 -- to remove 'syscall5()' macro // revised on: 31 JAN 2005 -- for revised keypad key-codes // revised on: 14 AUG 2005 -- exits on failure to find EOF // bug repair: 27 AUG 2005 -- disallowed: posmax < posmin //---------------------------------------------------------------- #include // for initscr(), endwin() #include // for strncpy() #include // for read(), close() #include // for exit() #include // for open(), O_RDONLY #define MAXNAME 79 #define BUFHIGH 16 #define BUFWIDE 16 #define BUFSIZE BUFHIGH*BUFWIDE #define ROW 5 #define COL 2 #define KB_ESC 0x0000001B #define KB_RETN 0x0000000D #define KB_HOME 0x7E315B1B #define KB_LNUP 0x00415B1B #define KB_PGUP 0x7E355B1B #define KB_LEFT 0x00445B1B #define KB_RGHT 0x00435B1B #define KB_END 0x7E345B1B #define KB_LNDN 0x00425B1B #define KB_PGDN 0x7E365B1B char progname[ ] = "FILEVIEW"; char filename[ 1+MAXNAME ] = "/proc/kcore"; char buffer[ BUFSIZE ]; char outline[ 80 ]; int main( int argc, char **argv ) { if ( argc > 1 ) strncpy( filename, argv[1], MAXNAME ); int fd = open( filename, O_RDONLY ); if ( fd < 0 ) { perror( filename ); exit(1); } loff_t filesize = lseek64( fd, 0LL, SEEK_END ); if ( filesize == 0LL ) { fprintf( stderr, "cannot locate \'end-of-file\'\n" ); exit(1); } loff_t incmin = ( 1LL << 8 ); loff_t incmax = ( 1LL << 36 ); loff_t posmin = lseek64( fd, 0LL, SEEK_SET ); loff_t posmax = lseek64( fd, -241LL, SEEK_END )&~0xF; if ( posmax < posmin ) posmax = posmin; initscr(); noecho(); clear(); int i, j, k; k = ( 77 - strlen( progname ) )/2; mvprintw( 0, 35, "%s", progname ); k = ( 77 - strlen( filename ) )/2; mvprintw( 2, k, "\'%s\'", filename ); char infomsg[ 80 ]; sprintf( infomsg,"filesize: %lld (=0x%08llX)", filesize, filesize ); k = ( 78 - strlen( infomsg ) ); mvprintw( 23, k, "%s", infomsg ); refresh(); loff_t pageincr = incmin; loff_t lineincr = 16; loff_t format = 1; loff_t position = 0LL; while( 1 ) { for (j = 0; j < BUFSIZE; j++) buffer[ j ] = ~0; if ( pageincr == 0 ) pageincr = incmax; else if ( pageincr < incmin ) pageincr = incmin; else if ( pageincr > incmax ) pageincr = incmax; loff_t location = lseek64( fd, position, SEEK_SET ); char *where = buffer; int to_read = BUFSIZE; while ( to_read > 0 ) { int nbytes = read( fd, where, to_read ); if ( nbytes <= 0 ) break; where += nbytes; to_read -= nbytes; } int len; for (i = 0; i < BUFHIGH; i++) { len = 0; location = position + i*BUFWIDE; len += sprintf( outline+len, "%010llX ", location ); unsigned char *bp; unsigned short *wp; unsigned long *lp; unsigned long long *qp; len += sprintf( outline+len, " " ); switch( format ) { case 1: bp = (unsigned char *)&buffer[ i*BUFWIDE ]; for (j = 0; j < BUFWIDE; j++) len += sprintf(outline+len,"%02X ", bp[j] ); break; case 2: wp = (unsigned short *)&buffer[ i*BUFWIDE ]; for (j = 0; j < BUFWIDE/2; j++) len += sprintf(outline+len," %04X ", wp[j] ); break; case 4: lp = (unsigned long *)&buffer[ i*BUFWIDE ]; for (j = 0; j < BUFWIDE/4; j++) len += sprintf(outline+len," %08X ",lp[j] ); break; case 8: lp = (unsigned long *)&buffer[ i*BUFWIDE ]; for (j = 0; j < BUFWIDE/4; j+=2) len += sprintf(outline+len," %08X%08X ", lp[j+1], lp[j] ); break; } len += sprintf( outline+len, " " ); for (j = 0; j < BUFWIDE; j++) { char ch = buffer[ i*BUFWIDE + j ]; if (( ch < 0x20 )||( ch > 0x7E )) ch = '.'; len += sprintf( outline+len, "%c", ch ); } mvprintw( ROW+i, COL, "%s", outline ); } move( 23, COL ); refresh(); long long inch = 0LL; read( STDIN_FILENO, &inch, sizeof( inch ) ); if (( inch == 'x' )||( inch == KB_ESC )) break; mvprintw( 22, COL, "%75s", " " ); refresh(); switch( inch ) { case KB_RGHT: pageincr /= 0x10; break; case KB_LEFT: pageincr *= 0x10; break; case KB_LNUP: position -= BUFWIDE; break; case KB_LNDN: position += BUFWIDE; break; case KB_PGDN: position += pageincr; break; //PGDN case KB_PGUP: position -= pageincr; break; //PGUP case KB_HOME: position = posmin; break; //HOME case KB_END: position = posmax; break; //END case 'H': case 'h': position = posmin; break; case 'E': case 'e': position = posmax; break; case 'B': case 'b': format = 1; break; case 'W': case 'w': format = 2; break; case 'D': case 'd': format = 4; break; case 'Q': case 'q': format = 8; break; case KB_RETN: { char inbuf[40]; mvprintw( 22, COL, "Address: " ); refresh(); echo(); getstr( inbuf ); noecho(); sscanf( inbuf, "%x", &position ); position &= ~0xFLL; } break; } if ( position < posmin ) position = posmin; if ( position > posmax ) position = posmax; } mvprintw( 24, 0, "%-79s", " " ); refresh(); endwin(); close( fd ); }