Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3156339
hexedit.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
hexedit.c
View Options
/******************************************************************************
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
** of the GNU General Public License v.2.
**
*******************************************************************************
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <curses.h>
#include <term.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include "global.h"
#include "copyright.cf"
#define EXTERN
#include "hexedit.h"
#include "gfshex.h"
#include "gfs_ondisk.h"
#include "linux_endian.h"
#include <syslog.h>
#define TITLE1 "gfs_edit - Global File System Editor (use with extreme caution)"
#define TITLE2 "Copyright (C) 2006 Red Hat, Inc. - Press H for help"
int display(void);
/* ------------------------------------------------------------------------ */
/* UpdateSize - screen size changed, so update it */
/* ------------------------------------------------------------------------ */
void UpdateSize(int sig)
{
static char term_buffer[2048];
int rc;
termlines=30;
termtype=getenv("TERM");
if (termtype==NULL)
return;
rc=tgetent(term_buffer,termtype);
if (rc>=0) {
termlines=tgetnum("li");
if (termlines<10)
termlines=30;
}
else
perror("Error: tgetent failed.");
termlines--; /* last line is number of lines -1 */
display();
signal(SIGWINCH, UpdateSize);
}
/* ------------------------------------------------------------------------- */
/* display_title_lines */
/* ------------------------------------------------------------------------- */
void display_title_lines(void)
{
clear();
attrset(COLOR_PAIR(1));
move(0, 0);
printw("%-80s",TITLE1);
move(termlines, 0);
printw("%-79s",TITLE2);
attrset(COLOR_PAIR(2));
}
/* ------------------------------------------------------------------------- */
/* bobgets - get a string */
/* returns: 1 if user exited by hitting enter */
/* 0 if user exited by hitting escape */
/* ------------------------------------------------------------------------- */
int bobgets(char string[],int x,int y,int sz)
{
int done,ch,runningy,rc;
move(x,y);
done=FALSE;
attrset(COLOR_PAIR(3));
move(x,y);
addstr(string);
move(x,y);
curs_set(2);
refresh();
runningy=y;
rc=0;
while (!done) {
ch=getch();
if(ch < 0x0100 && isprint(ch)) {
char *p=string+strlen(string); // end of the string
*(p+1)='\0';
while (insert && p > &string[runningy-y]) {
*p=*(p-1);
p--;
}
string[runningy-y]=ch;
runningy++;
move(x,y);
addstr(string);
}
else {
// special character, is it one we recognize?
switch(ch)
{
case(KEY_ENTER):
case('\n'):
case('\r'):
rc=1;
done=TRUE;
break;
case(KEY_CANCEL):
case(0x01B):
rc=0;
done=TRUE;
break;
case(KEY_LEFT):
if (runningy>y)
runningy--;
break;
case(KEY_RIGHT):
runningy++;
break;
case(KEY_DC):
case(0x07F):
if (runningy>=y) {
char *p;
p = &string[runningy-y];
while (*p) {
*p = *(p+1);
p++;
}
*p='\0';
runningy--;
// remove the character from the string
move(x,y);
addstr(string);
attrset(COLOR_PAIR(2));
addstr(" ");
attrset(COLOR_PAIR(3));
runningy++;
}
break;
case(KEY_BACKSPACE):
if (runningy>y) {
char *p;
p = &string[runningy-y-1];
while (*p) {
*p = *(p+1);
p++;
}
*p='\0';
runningy--;
// remove the character from the string
move(x,y);
addstr(string);
attrset(COLOR_PAIR(2));
addstr(" ");
attrset(COLOR_PAIR(3));
}
break;
case KEY_DOWN: // Down
rc=0x5000U;
done=TRUE;
break;
case KEY_UP: // Up
rc=0x4800U;
done=TRUE;
break;
case 0x014b:
insert=!insert;
move(0,68);
if (insert)
printw("insert ");
else
printw("replace");
break;
default:
move(0,70);
printw("%08X",ch);
// ignore all other characters
break;
} // end switch on non-printable character
} // end non-printable character
move(x,runningy);
refresh();
} // while !done
if (sz>0)
string[sz]='\0';
attrset(COLOR_PAIR(2));
return rc;
}/* bobgets */
/******************************************************************************
*******************************************************************************
**
** void print_usage()
**
** Description:
** This routine prints out the appropriate commands for this application.
**
*******************************************************************************
******************************************************************************/
void print_usage(void)
{
int ch;
line = 2;
clear();
display_title_lines();
move(line++,0);
printw("Supported commands: (roughly conforming to the rules of 'less')");
line++;
move(line++,0);
printw(" b - Backward one 4K block");
move(line++,0);
printw(" f - Forward one 4K block");
move(line++,0);
printw(" g - Goto a given block in hex");
move(line++,0);
printw(" h - This Help display");
move(line++,0);
printw(" j - Jump to the highlighted 64-bit block number.");
move(line++,0);
printw(" m - Switch display mode: hex -> GFS structure -> Extended");
move(line++,0);
printw(" q - Quit (same as hitting <escape> key)");
move(line++,0);
printw("<space> - Forward one 4K block (same as 'f')");
move(line++,0);
printw("<pg up>/<down> - move up or down one screen full");
move(line++,0);
printw("<up>/<down> - move up or down one line");
move(line++,0);
printw("<left>/<right> - move left or right one byte");
move(line++,0);
printw("<home> - return to the superblock.");
move(line++,0);
printw("<enter> - edit a value (enter to save, esc to discard)");
move(line++,0);
printw("<backspace> - return to previous block");
move(line++,0);
printw("<escape> - Quit the program");
move(line++,0);
move(line++,0);
printw("Notes: Areas shown in red are outside the bounds of the struct.");
move(line++,0);
printw(" Fields shown in green are selected for edit on <enter>.");
move(line++,0);
move(line++,0);
printw("Press any key to return.");
refresh();
while ((ch=getch()) == 0); // wait for input
clear();
}
/* ------------------------------------------------------------------------ */
/* display_block_type */
/* returns: metatype if block is a GFS structure block type */
/* 0 if block is not a GFS structure */
/* ------------------------------------------------------------------------ */
int display_block_type(const char *lpBuffer)
{
int ret_type = 0; /* return type */
/* first, print out the kind of GFS block this is */
line = 1;
move(line, 0);
printw("Block #");
if (edit_row[display_mode] == -1)
attrset(COLOR_PAIR(5));;
printw("%"PRIX64,block);
if (edit_row[display_mode] == -1)
attrset(COLOR_PAIR(2));
move(line,25);
printw("of %"PRIX64,max_block);
move(line, 45);
if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 && *(lpBuffer+2)==0x19 &&
*(lpBuffer+3)==0x70 && *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
*(lpBuffer+6)==0x00) { /* If magic number appears at the start */
ret_type = *(lpBuffer+7);
switch (*(lpBuffer+7)) {
case GFS_METATYPE_SB: /* 1 */
printw("(superblock)");
struct_len = sizeof(struct gfs_sb);
break;
case GFS_METATYPE_RG: /* 2 */
printw("(rsrc grp hdr)");
struct_len = sizeof(struct gfs_rgrp);
break;
case GFS_METATYPE_RB: /* 3 */
printw("(rsrc grp bitblk)");
struct_len = 512;
break;
case GFS_METATYPE_DI: /* 4 */
printw("(disk inode)");
struct_len = sizeof(struct gfs_dinode);
break;
case GFS_METATYPE_IN: /* 5 */
printw("(indir inode blklst)");
struct_len = sizeof(struct gfs_indirect);
break;
case GFS_METATYPE_LF: /* 6 */
printw("(leaf dinode blklst)");
struct_len = sizeof(struct gfs_leaf);
break;
case GFS_METATYPE_JD:
printw("(journal data)");
struct_len = sizeof(struct gfs_meta_header);
break;
case GFS_METATYPE_LH:
printw("(log header)");
struct_len = sizeof(struct gfs_log_header);
break;
case GFS_METATYPE_LD:
printw("(log descriptor)");
struct_len = sizeof(struct gfs_log_descriptor);
break;
case GFS_METATYPE_EA:
printw("(extended attr hdr)");
struct_len = sizeof(struct gfs_ea_header);
break;
case GFS_METATYPE_ED:
printw("(extended attr data)");
struct_len = 512;
break;
default:
printw("(wtf?)");
struct_len = 512;
break;
}
}
else
struct_len = 512;
line++;
move(line, 0);
if (display_mode == HEX_MODE) {
/* calculate how much of the buffer we can fit on screen */
screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
if (!screen_chunk_size)
screen_chunk_size = 256;
printw("(%d of %d)", (offset / screen_chunk_size) + 1,
(bufsize % screen_chunk_size) > 0 ?
bufsize / screen_chunk_size + 1 : bufsize / screen_chunk_size);
}
move(line, 9);
if (block == sb.sb_jindex_di.no_addr)
printw("----------------- Journal Index file -----------------");
else if (block == sb.sb_rindex_di.no_addr)
printw("-------------- Resource Group Index file -------------");
else if (block == sb.sb_quota_di.no_addr)
printw("---------------------- Quota file --------------------");
else if (block == sb.sb_root_di.no_addr)
printw("-------------------- Root direcory -------------------");
else if (block == sb.sb_license_di.no_addr)
printw("--------------------- License file -------------------");
line++;
return ret_type;
}
/* ------------------------------------------------------------------------ */
/* hexdump - hex dump the filesystem block to the screen */
/* ------------------------------------------------------------------------ */
int hexdump(uint64 startaddr, const char *lpBuffer, int len)
{
const unsigned char *pointer,*ptr2;
int i;
uint64 l;
strcpy(edit_fmt,"%02X");
pointer = (unsigned char *)lpBuffer + offset;
ptr2 = (unsigned char *)lpBuffer + offset;
l = offset;
while (line < termlines &&
line <= ((screen_chunk_size / 16) + 2) &&
l < bufsize) {
move(line, 0);
attrset(COLOR_PAIR(6)); /* yellow for offsets */
if (startaddr < 0xffffffff)
printw("%.8"PRIX64,startaddr + l);
else
printw("%.16"PRIX64,startaddr + l);
if (l < struct_len)
attrset(COLOR_PAIR(2)); /* normal part of the structure */
else
attrset(COLOR_PAIR(4)); /* beyond the end of the structure */
for (i=0; i<16; i++) { /* first print it in hex */
if (l+i < struct_len)
attrset(COLOR_PAIR(2)); /* normal part of the structure */
else
attrset(COLOR_PAIR(4)); /* beyond the end of the structure */
if (i%4 == 0)
printw(" ");
if (line == edit_row[display_mode] + 3 &&
i == edit_col[display_mode]) {
attrset(COLOR_PAIR(5)); /* normal part of the structure */
memset(edit_string,0,3);
sprintf(edit_string,"%02X",*pointer);
}
printw("%02X",*pointer);
if (line == edit_row[display_mode] + 3 &&
i == edit_col[display_mode]) {
if (l < struct_len + offset)
attrset(COLOR_PAIR(2)); /* normal part of the structure */
else
attrset(COLOR_PAIR(4)); /* beyond end of the structure */
}
pointer++;
}
printw(" [");
for (i=0; i<16; i++) { /* now print it in character format */
if ((*ptr2 >=' ') && (*ptr2 <= '~'))
printw("%c",*ptr2);
else
printw(".");
ptr2++;
}
printw("] ");
if (line - 3 > edit_last[display_mode])
edit_last[display_mode] = line - 3;
line++;
l+=16;
}
return (offset+len);
}
/* ------------------------------------------------------------------------ */
/* display_extended */
/* ------------------------------------------------------------------------ */
int display_extended(void)
{
int e;
edit_last[display_mode] = 0;
move(line++, 0);
if (indirect_blocks) {
printw("This inode contains %d indirect blocks", indirect_blocks);
line++;
move(line++, 0);
printw("Indirect blocks for this inode:");
for (e = 0; e < termlines && e < indirect_blocks; e++) {
if (line - 6 == edit_row[display_mode])
attrset(COLOR_PAIR(5));
move(line, 5);
printw("%d => %"PRIX64, e + 1, indirect_block[e]);
if (line - 6 == edit_row[display_mode]) {
sprintf(edit_string, "%"PRIX64, indirect_block[e]);
strcpy(edit_fmt, "%"PRIX64);
edit_size[display_mode] = strlen(edit_string);
attrset(COLOR_PAIR(2));
}
line++;
}
if (line >= 7) /* 7 because it was bumped at the end */
edit_last[display_mode] = line - 7;
}
else
printw("This block does not have indirect blocks.");
return 0;
}
/* ------------------------------------------------------------------------ */
/* display */
/* ------------------------------------------------------------------------ */
int display(void)
{
display_title_lines();
move(2,0);
if (block_in_mem != block) { /* If we changed blocks from the last read */
dev_offset = block * bufsize;
ioctl(fd, BLKFLSBUF, 0);
do_lseek(fd, dev_offset);
do_read(fd, buf, bufsize); /* read in the desired block */
block_in_mem = block; /* remember which block is in memory */
}
line = 1;
gfs_struct_type = display_block_type(buf);
indirect_blocks = 0;
if (gfs_struct_type == GFS_METATYPE_SB || block == 0x10)
gfs_sb_in(&sb, buf); /* parse it out into the sb structure */
else if (gfs_struct_type == GFS_METATYPE_DI) {
gfs_dinode_in(&di, buf); /* parse disk inode into structure */
do_dinode_extended(&di, buf); /* get extended data, if any */
}
edit_last[display_mode] = 0;
if (display_mode == HEX_MODE) /* if hex display mode */
hexdump(dev_offset, buf, 256); /* show the block in hex */
else if (display_mode == GFS_MODE) /* if structure display */
display_gfs(); /* display the gfs structure */
else /* otherwise */
display_extended(); /* display extended blocks */
refresh();
return(0);
}
/******************************************************************************
*******************************************************************************
**
** main()
**
** Description:
** Do everything
**
*******************************************************************************
******************************************************************************/
int main(int argc, char *argv[])
{
char device[STRLEN];
char string[256];
int i,ch, left_off;
int64 temp_blk;
prog_name = argv[0];
if (argc < 2)
die("no device specified\n");
memset(edit_row, 0, sizeof(edit_row));
memset(edit_col, 0, sizeof(edit_col));
memset(edit_size, 0, sizeof(edit_size));
memset(edit_last, 0, sizeof(edit_last));
display_mode = HEX_MODE;
type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */
block = 0x10;
for (i = 1; i < argc; i++) {
if (!strcasecmp(argv[i], "-verbose"))
verbose = TRUE;
else if (!strcasecmp(argv[i], "-V")) {
printf("%s %s (built %s %s)\n", prog_name, GFS_RELEASE_NAME,
__DATE__, __TIME__);
printf("%s\n", REDHAT_COPYRIGHT);
exit(0);
}
else {
strcpy(device,argv[i]);
}
}
fd = open(device, O_RDWR);
if (fd < 0)
die("can't open %s: %s\n", argv[1], strerror(errno));
max_block = lseek(fd, 0, SEEK_END) / bufsize;
if (initscr() == NULL) {
fprintf(stderr, "Error: unable to initialize screen.\n");
exit(-1);
}
signal(SIGWINCH, UpdateSize); /* handle the terminal resize signal */
UpdateSize(0); /* update screen size based on terminal settings */
clear();
start_color();
noecho();
keypad(stdscr, TRUE);
raw();
curs_set(0);
init_pair(1, COLOR_BLACK, COLOR_CYAN); /* title lines */
init_pair(2, COLOR_WHITE, COLOR_BLACK); /* normal text */
init_pair(3, COLOR_BLACK, COLOR_WHITE); /* inverse text */
init_pair(4, COLOR_RED, COLOR_BLACK); /* special text */
init_pair(5, COLOR_GREEN, COLOR_BLACK); /* highlighted text */
init_pair(6, COLOR_CYAN, COLOR_BLACK); /* offsets */
while (!Quit) {
display();
while ((ch=getch()) == 0); // wait for input
switch (ch)
{
/* -------------------------------------------------------------- */
/* escape or 'q' */
/* -------------------------------------------------------------- */
case 0x1b:
case 0x03:
case 'q':
Quit=TRUE;
break;
/* -------------------------------------------------------------- */
/* home - return to the superblock */
/* -------------------------------------------------------------- */
case KEY_HOME:
previous_block = block;
block = 0x10;
offset = 0;
break;
/* -------------------------------------------------------------- */
/* backspace - return to the previous block */
/* -------------------------------------------------------------- */
case KEY_BACKSPACE:
case 0x7f:
temp_blk = block;
block = previous_block;
previous_block = temp_blk;
offset = 0;
break;
/* -------------------------------------------------------------- */
/* arrow up */
/* -------------------------------------------------------------- */
case KEY_UP:
if (edit_row[display_mode] >= 0) /* -1 means change block number */
edit_row[display_mode]--;
break;
/* -------------------------------------------------------------- */
/* arrow down */
/* -------------------------------------------------------------- */
case KEY_DOWN:
if (edit_row[display_mode] < edit_last[display_mode])
edit_row[display_mode]++;
break;
/* -------------------------------------------------------------- */
/* arrow left */
/* -------------------------------------------------------------- */
case KEY_LEFT:
if (display_mode == HEX_MODE) {
if (edit_col[display_mode] > 0)
edit_col[display_mode]--;
else
edit_col[display_mode] = 15;
}
break;
/* -------------------------------------------------------------- */
/* arrow right */
/* -------------------------------------------------------------- */
case KEY_RIGHT:
if (display_mode == HEX_MODE) {
if (edit_col[display_mode] < 15)
edit_col[display_mode]++;
else
edit_col[display_mode] = 0;
}
break;
/* -------------------------------------------------------------- */
/* m - change display mode key */
/* -------------------------------------------------------------- */
case 'm':
display_mode = ((display_mode + 1) % DISPLAY_MODES);
break;
/* -------------------------------------------------------------- */
/* J - Jump to highlighted block number */
/* -------------------------------------------------------------- */
case 'j':
if (display_mode == HEX_MODE) {
unsigned int col2;
uint64 *b;
col2 = edit_col[display_mode] & 0x08;/* thus 0-7->0, 8-15->8 */
b = (uint64 *)&buf[edit_row[display_mode]*16 + offset + col2];
temp_blk=gfs64_to_cpu(*b);
}
else
sscanf(edit_string, "%"SCNx64, &temp_blk);/* retrieve in hex */
if (temp_blk < max_block) { /* if the block number is valid */
offset = 0;
display_mode = HEX_MODE;
previous_block = block;
block = temp_blk;
}
break;
/* -------------------------------------------------------------- */
/* g - goto block */
/* -------------------------------------------------------------- */
case 'g':
memset(string, 0, sizeof(string));
sprintf(string,"%"PRIX64, block);
if (bobgets(string, 1, 7, 16))
sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
if (temp_blk < max_block) {
offset = 0;
previous_block = block;
block = temp_blk;
}
break;
/* -------------------------------------------------------------- */
/* h - help key */
/* -------------------------------------------------------------- */
case 'h':
print_usage();
break;
/* -------------------------------------------------------------- */
/* b - Back one 4K block */
/* -------------------------------------------------------------- */
case 'b':
edit_row[display_mode] = 0;
if (block > 0) {
previous_block = block;
block--;
}
offset = 0;
break;
/* -------------------------------------------------------------- */
/* page up key */
/* -------------------------------------------------------------- */
case 0x19: // ctrl-y for vt100
case KEY_PPAGE: // PgUp
case 0x15: // ctrl-u for vi compat.
case 0x02: // ctrl-b for less compat.
edit_row[display_mode] = 0;
if (display_mode == GFS_MODE || offset==0) {
previous_block = block;
block--;
if (display_mode == HEX_MODE)
offset = (bufsize % screen_chunk_size) > 0 ?
screen_chunk_size * (bufsize / screen_chunk_size) :
bufsize - screen_chunk_size;
else
offset = 0;
}
else
offset -= screen_chunk_size;
break;
/* -------------------------------------------------------------- */
/* f - Forward one 4K block */
/* -------------------------------------------------------------- */
case 'f':
case ' ': /* space for less/more compat. */
previous_block = block;
edit_row[display_mode] = 0;
block++;
offset = 0;
break;
/* -------------------------------------------------------------- */
/* page down key */
/* -------------------------------------------------------------- */
case 0x16: // ctrl-v for vt100
case KEY_NPAGE: // PgDown
case 0x04: // ctrl-d for vi compat.
edit_row[display_mode] = 0;
if (display_mode == GFS_MODE ||
offset + screen_chunk_size >= bufsize) {
previous_block = block;
block++;
offset = 0;
}
else
offset += screen_chunk_size;
break;
/* -------------------------------------------------------------- */
/* enter key - change a value */
/* -------------------------------------------------------------- */
case(KEY_ENTER):
case('\n'):
case('\r'):
if (edit_row[display_mode] == -1) {
memset(string, 0, sizeof(string));
sprintf(string,"%"PRIX64, block);
if (bobgets(string, 1, 7, 16))
sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
if (temp_blk < max_block) {
offset = 0;
previous_block = block;
block = temp_blk;
}
}
else {
if (display_mode == HEX_MODE) {
left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17;
/* 8 and 16 char addresses on screen */
if (bobgets(edit_string, edit_row[display_mode] + 3,
(edit_col[display_mode] * 2) +
(edit_col[display_mode] / 4) + left_off, 2)) {
if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
int hexoffset;
unsigned char ch;
hexoffset = (edit_row[display_mode] * 16) +
edit_col[display_mode];
ch = 0x00;
if (isdigit(edit_string[0]))
ch = (edit_string[0] - '0') * 0x10;
else if (edit_string[0] >= 'a' &&
edit_string[0] <= 'f')
ch = (edit_string[0] - 'a' + 0x0a) * 0x10;
else if (edit_string[0] >= 'A' &&
edit_string[0] <= 'F')
ch = (edit_string[0] - 'A' + 0x0a) * 0x10;
if (isdigit(edit_string[1]))
ch += (edit_string[1] - '0');
else if (edit_string[1] >= 'a' &&
edit_string[1] <= 'f')
ch += (edit_string[1] - 'a' + 0x0a);
else if (edit_string[1] >= 'A' &&
edit_string[1] <= 'F')
ch += (edit_string[1] - 'A' + 0x0a);
buf[offset + hexoffset] = ch;
do_lseek(fd, dev_offset);
do_write(fd, buf, bufsize);
fsync(fd);
}
}
}
else if (display_mode == GFS_MODE)
bobgets(edit_string, edit_row[display_mode] + 3, 24,
edit_size[display_mode]);
else
bobgets(edit_string, edit_row[display_mode] + 6, 24,
edit_size[display_mode]);
}
break;
default:
move(termlines - 1, 0);
printw("Keystroke not understood: %02X",ch);
refresh();
sleep(2);
break;
} /* switch */
} /* while !Quit */
clear();
refresh();
endwin();
close(fd);
if (buf)
free(buf);
exit(EXIT_SUCCESS);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Feb 27, 5:44 AM (1 d, 16 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1466223
Default Alt Text
hexedit.c (24 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment