//---------------------------------------------------------------- // 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 content using cursor-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 // // NOTE: Developed and tested using Linux kernel 2.4.19. // // programmer: ALLAN CRUSE // date begun: 25 OCT 2002 // completion: 26 OCT 2002 // revised on: 01 NOV 2002 //---------------------------------------------------------------- #include // for initscr(), endwin() #include // for strncpy() #include // for close() #include // for exit() #include // for open(), O_RDONLY #include // for loff_t #include // for _syscall5 #define MAXNAME 79 #define BUFHIGH 16 #define BUFWIDE 16 #define BUFSIZE BUFHIGH*BUFWIDE #define ROW 5 #define COL 2 #define KEY_RET 10 #define KEY_ESC 27 #define __NR_llseek 140 // documented in "Linux Internals" _syscall5(int,llseek,uint,fd,ulong,hi,ulong,lo,loff_t*,result,uint,wh); loff_t my_llseek( int fd, loff_t where, int whence ) { unsigned long hi = ( where >> 32 ); unsigned long lo = ( where >> 0 ); loff_t result = ~0; llseek( fd, hi, lo, &result, whence ); return result; } 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( "fopen" ); exit(1); } loff_t filesize = my_llseek( fd, 0LL, SEEK_END ); loff_t posmax = my_llseek( fd, -241LL, SEEK_END )&~0xF; loff_t posmin = my_llseek( fd, 0LL, SEEK_SET ); loff_t incmax = ( 1LL << 36 ); loff_t incmin = ( 1LL << 8 ); initscr(); cbreak(); noecho(); keypad( stdscr, TRUE ); 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 = my_llseek( fd, position, SEEK_SET ); read( fd, buffer, BUFSIZE ); 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(); int inch = getch(); if (( inch == 'x' )||( inch == KEY_ESC )) break; mvprintw( 22, COL, "%75s", " " ); refresh(); switch( inch ) { case KEY_RIGHT: pageincr /= 0x10; break; case KEY_LEFT: pageincr *= 0x10; break; case KEY_UP: position -= BUFWIDE; break; case KEY_DOWN: position += BUFWIDE; break; case KEY_NPAGE: position += pageincr; break; case KEY_PPAGE: position -= pageincr; break; case KEY_HOME: position = posmin; break; case KEY_END: position = posmax; break; 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 KEY_RET: { 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 ); }