All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2007-02-08  5:41 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2007-02-08  5:41 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2007-02-08 05:41:16

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Fixed some bugs and made some improvements.
	When displaying indirect blocks, it now gives the data offset.
	Also added page-up/page-down/home/end navigation to block list display.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.8&r2=1.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.6&r2=1.7

--- cluster/gfs2/edit/gfs2hex.c	2006/11/14 20:11:10	1.7
+++ cluster/gfs2/edit/gfs2hex.c	2007/02/08 05:41:16	1.8
@@ -43,10 +43,10 @@
 extern char edit_fmt[80];
 extern char edit_string[1024];
 extern int edit_mode INIT(0);
-extern int edit_row[DISPLAY_MODES], edit_col[DISPLAY_MODES];
-extern int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES];
+extern int edit_row[DMODES], edit_col[DMODES];
+extern int edit_size[DMODES], edit_last[DMODES];
 extern char edit_string[1024], edit_fmt[80];
-extern enum dsp_mode display_mode INIT(HEX_MODE);
+extern enum dsp_mode dmode INIT(HEX_MODE); /* display mode */
 
 void eol(int col) /* end of line */
 {
@@ -86,11 +86,11 @@
 	if (!termlines || line < termlines) {
 		va_start(args, fmt2);
 		if (termlines) {
-			if (line == edit_row[display_mode] + 4)
+			if (line == edit_row[dmode] + 4)
 				COLORS_HIGHLIGHT;
 			move(line,0);
 			printw("%s", label);
-			if (line == edit_row[display_mode] + 4)
+			if (line == edit_row[dmode] + 4)
 				COLORS_NORMAL;
 			move(line,24);
 		}
@@ -103,10 +103,10 @@
 		vsprintf(tmp_string, fmt, args);
 
 		if (termlines) {
-			if (line == edit_row[display_mode] + 4)
+			if (line == edit_row[dmode] + 4)
 				COLORS_HIGHLIGHT;
 			printw(tmp_string);
-			if (line == edit_row[display_mode] + 4)
+			if (line == edit_row[dmode] + 4)
 				COLORS_NORMAL;
 		}
 		else
@@ -119,10 +119,10 @@
 			vsprintf(tmp_string, fmt2, args);
 			if (termlines) {
 				move(line, 50);
-				if (line == edit_row[display_mode] + 4)
+				if (line == edit_row[dmode] + 4)
 					COLORS_HIGHLIGHT;
 				printw("%s", tmp_string);
-				if (line == edit_row[display_mode] + 4)
+				if (line == edit_row[dmode] + 4)
 					COLORS_NORMAL;
 			}
 			else {
@@ -148,14 +148,14 @@
 		}
 		if (termlines) {
 			refresh();
-			if (line == edit_row[display_mode] + 4) {
+			if (line == edit_row[dmode] + 4) {
 				strcpy(edit_string, tmp_string);
 				strcpy(edit_fmt, fmt);
-				edit_size[display_mode] = strlen(edit_string);
+				edit_size[dmode] = strlen(edit_string);
 				COLORS_NORMAL;
 			}
-			if (line - 3 > edit_last[display_mode])
-				edit_last[display_mode] = line - 4;
+			if (line - 3 > edit_last[dmode])
+				edit_last[dmode] = line - 4;
 		}
 		eol(0);
 		va_end(args);
@@ -293,7 +293,8 @@
 
 	indirect_blocks = 0;
 	memset(&indirect, 0, sizeof(indirect));
-	for (x = sizeof(struct gfs_indirect), y = 0;
+	for (x = (gfs1 ? sizeof(struct gfs_indirect):
+			  sizeof(struct gfs2_meta_header)), y = 0;
 		 x < bufsize;
 		 x += sizeof(uint64_t), y++) {
 		p = be64_to_cpu(*(uint64_t *)(buf + x));
--- cluster/gfs2/edit/hexedit.c	2006/11/14 20:11:10	1.8
+++ cluster/gfs2/edit/hexedit.c	2007/02/08 05:41:16	1.9
@@ -42,7 +42,7 @@
 
 #include <syslog.h>
 
-int display(enum dsp_mode display_mode, int identify_only);
+int display(enum dsp_mode dmode, int identify_only);
 extern void eol(int col);
 extern void do_indirect_extended(char *buf);
 
@@ -70,7 +70,7 @@
 	else
 		perror("Error: tgetent failed.");
 	termlines--; /* last line is number of lines -1 */
-	display(display_mode, FALSE);
+	display(dmode, FALSE);
 	signal(SIGWINCH, UpdateSize);
 }
 
@@ -323,12 +323,12 @@
 	}
 	print_gfs2("Block #");
 	if (termlines) {
-		if (edit_row[display_mode] == -1)
+		if (edit_row[dmode] == -1)
 			COLORS_HIGHLIGHT;
 	}
 	print_gfs2("%lld    (0x%"PRIx64")", block, block);
 	if (termlines) {
-		if (edit_row[display_mode] == -1)
+		if (edit_row[dmode] == -1)
 			COLORS_NORMAL;
 		move(line,30);
 	}
@@ -401,7 +401,7 @@
 	else
 		struct_len = 512;
 	eol(0);
-	if (termlines && display_mode == HEX_MODE) {
+	if (termlines && dmode == 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)
@@ -413,7 +413,7 @@
 		/*eol(9);*/
 	}
 	if (block == sbd.sd_sb.sb_root_dir.no_addr)
-		print_gfs2("-------------------- Root direcory -------------------");
+		print_gfs2("-------------------- Root directory ------------------");
 	else if (!gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr)
 		print_gfs2("------------------- Master directory -----------------");
 	else {
@@ -499,15 +499,15 @@
 			}
 			if (i%4 == 0)
 				print_gfs2(" ");
-			if (termlines && line == edit_row[display_mode] + 3 &&
-				i == edit_col[display_mode]) {
+			if (termlines && line == edit_row[dmode] + 3 &&
+				i == edit_col[dmode]) {
 				COLORS_HIGHLIGHT; /* normal part of the structure */
 				memset(edit_string,0,3);
 				sprintf(edit_string,"%02X",*pointer);
 			}
 			print_gfs2("%02X",*pointer);
-			if (termlines && line == edit_row[display_mode] + 3 &&
-				i == edit_col[display_mode]) {
+			if (termlines && line == edit_row[dmode] + 3 &&
+				i == edit_col[dmode]) {
 				if (l < struct_len + offset)
 					COLORS_NORMAL; /* normal part of the structure */
 				else
@@ -524,8 +524,8 @@
 			ptr2++;
 		}
 		print_gfs2("] ");
-		if (line - 3 > edit_last[display_mode])
-			edit_last[display_mode] = line - 3;
+		if (line - 3 > edit_last[dmode])
+			edit_last[dmode] = line - 3;
 		eol(0);
 		l+=16;
 	} /* while */
@@ -651,36 +651,73 @@
 	int e, start_line, total_dirents, indir_blocks;
 	struct gfs2_inode *tmp_inode;
 
-	edit_last[display_mode] = 0;
+	edit_last[dmode] = 0;
 	eol(0);
 	start_line = line;
 	if (indirect_blocks ||
 		(gfs2_struct_type == GFS2_METATYPE_DI &&
 		 (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR)))) {
+		int i, cur_height = -1;
+		uint64_t factor[5];
+		int offsets[5];
+
 		indir_blocks = indirect_blocks;
 		if (!indirect_blocks) {
 			print_gfs2("This directory contains %d directory entries.",
 					   indirect[0].dirents);
-			eol(0);
 			indir_blocks = 1; /* not really an indirect block, but treat it as one */
 		}
 		else {
-			if (gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode))
-				print_gfs2("This directory contains %d indirect blocks",
-						   indirect_blocks);
+			if (gfs2_struct_type == GFS2_METATYPE_DI) {
+				if (S_ISDIR(di.di_mode))
+					print_gfs2("This directory contains %d indirect blocks",
+							   indirect_blocks);
+				else
+					print_gfs2("This inode contains %d indirect blocks",
+							   indirect_blocks);
+			}
 			else
-				print_gfs2("This inode contains %d indirect blocks",
+				print_gfs2("This indirect block contains %d indirect blocks",
 						   indirect_blocks);
+		}
+		total_dirents = 0;
+		/* Figure out multiplication factors for indirect pointers. */
+		if ((indir_blocks == indirect_blocks) && !S_ISDIR(di.di_mode)) {
+			memset(&offsets, 0, sizeof(offsets));
+			/* See if we are on an inode or have one in history. */
+			cur_height = 0;
+			if (gfs2_struct_type != GFS2_METATYPE_DI) {
+				cur_height = 0;
+				for (i = 0; i <= blockhist && i < 5; i++) {
+					offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode];
+					if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI)
+						break;
+					cur_height++;
+				}
+			}
+			if (cur_height >= 0) {
+				/* Multiply out the max factor based on inode height.*/
+				/* This is how much data is represented by each      */
+				/* indirect pointer at each height.                  */
+				factor[0] = 1ull;
+				for (i = 0; i < di.di_height; i++)
+					factor[i + 1] = factor[i] * 509;
+			}
+			print_gfs2("  (at height=%d)", cur_height);
+		}
+		if (indirect_blocks) {
 			eol(0);
 			print_gfs2("Indirect blocks for this inode:");
-			eol(0);
 		}
-		total_dirents = 0;
-		for (e = 0; (!termlines || e < termlines - start_line - 2) &&
+		eol(0);
+		for (e = start_row[dmode];
+			 (!termlines ||
+			  e < termlines - start_line - 2 + start_row[dmode]) &&
 				 e < indir_blocks; e++) {
 			if (termlines) {
-				if (edit_row[display_mode] >= 0 &&
-					line - start_line - 2 == edit_row[display_mode])
+				if (edit_row[dmode] >= 0 &&
+					line - start_line - 2 == edit_row[dmode] -
+					start_row[dmode])
 					COLORS_HIGHLIGHT;
 				move(line, 1);
 			}
@@ -691,17 +728,33 @@
 				print_gfs2("0x%llx / %lld", indirect[e].block,
 						   indirect[e].block);
 				if (termlines) {
-					if (edit_row[display_mode] >= 0 &&
-						line - start_line - 2 == edit_row[display_mode]) { 
+					if (edit_row[dmode] >= 0 &&
+						line - start_line - 2 == edit_row[dmode] -
+						start_row[dmode]) { 
 						sprintf(edit_string, "%"PRIx64, indirect[e].block);
 						strcpy(edit_fmt, "%"PRIx64);
-						edit_size[display_mode] = strlen(edit_string);
+						edit_size[dmode] = strlen(edit_string);
 						COLORS_NORMAL;
 					}
 				}
+				if (!S_ISDIR(di.di_mode)) {
+					int hgt;
+					uint64_t file_offset = 0ull;
+
+					/* Now divide by how deep we are at the moment.      */
+					/* This is how much data is represented by each      */
+					/* indirect pointer for each height we've traversed. */
+					offsets[0] = e;
+					for (hgt = cur_height; hgt >= 0; hgt--)
+						file_offset += offsets[cur_height - hgt] *
+							factor[di.di_height - hgt - 1] *
+							(bufsize - sizeof(struct gfs2_meta_header));
+					print_gfs2("     ");
+					print_gfs2("(data offset 0x%llx / %lld)", file_offset,
+							   file_offset);
+					print_gfs2("   ");
+				}
 			}
-			if (indir_blocks == indirect_blocks)
-				print_gfs2("   ");
 			if (indirect[e].is_dir) {
 				int d;
 
@@ -713,8 +766,10 @@
 					if (indirect[e].dirents > 1) {
 						eol(5);
 						if (termlines) {
-							if (edit_row[display_mode] >=0 &&
-								line - start_line - 2 == edit_row[display_mode]) {
+							if (edit_row[dmode] >=0 &&
+								line - start_line - 2 == 
+								edit_row[dmode] -
+								start_row[dmode]) {
 								COLORS_HIGHLIGHT;
 								sprintf(edit_string, "%"PRIx64,
 										indirect[e].dirent[d].block);
@@ -761,18 +816,17 @@
 
 					print_gfs2(" %s", indirect[e].dirent[d].filename);
 					if (termlines) {
-						if (edit_row[display_mode] >= 0 &&
-							line - start_line - 2 == edit_row[display_mode])
+						if (edit_row[dmode] >= 0 &&
+							line - start_line - 2 == edit_row[dmode] -
+							start_row[dmode])
 							COLORS_NORMAL;
 					}
 				}
 			} /* if isdir */
-			else
-				print_gfs2("indirect block");
 			eol(0);
 		} /* for termlines */
 		if (line >= 7) /* 7 because it was bumped at the end */
-			edit_last[display_mode] = line - 7;
+			edit_last[dmode] = line - 7;
 	} /* if (indirect_blocks) */
 	else
 		print_gfs2("This block does not have indirect blocks.");
@@ -871,7 +925,7 @@
 /* ------------------------------------------------------------------------ */
 /* display                                                                  */
 /* ------------------------------------------------------------------------ */
-int display(enum dsp_mode display_mode, int identify_only)
+int display(enum dsp_mode dmode, int identify_only)
 {
 	if (termlines) {
 		display_title_lines();
@@ -919,11 +973,11 @@
 			}
 		}
 	}
-	edit_last[display_mode] = 0;
-	if (display_mode == HEX_MODE)          /* if hex display mode           */
+	edit_last[dmode] = 0;
+	if (dmode == HEX_MODE)          /* if hex display mode           */
 		hexdump(dev_offset, buf, (gfs2_struct_type == GFS2_METATYPE_DI)?
 				struct_len + di.di_size:bufsize); /* show block in hex */
-	else if (display_mode == GFS2_MODE)    /* if structure display          */
+	else if (dmode == GFS2_MODE)    /* if structure display          */
 		display_gfs2();                    /* display the gfs2 structure    */
 	else                                   /* otherwise                     */
 		display_extended();                /* display extended blocks       */
@@ -937,14 +991,17 @@
 /* ------------------------------------------------------------------------ */
 void push_block(uint64_t blk)
 {
-	int i;
+	int i, bhst;
 
+	bhst = blockhist % BLOCK_STACK_SIZE;
 	if (blk) {
-		blockstack[blockhist % BLOCK_STACK_SIZE].display_mode = display_mode;
-		for (i = 0; i < DISPLAY_MODES; i++) {
-			blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i] = edit_row[i];
-			blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i] = edit_col[i];
+		blockstack[bhst].dmode = dmode;
+		for (i = 0; i < DMODES; i++) {
+			blockstack[bhst].start_row[i] = start_row[i];
+			blockstack[bhst].edit_row[i] = edit_row[i];
+			blockstack[bhst].edit_col[i] = edit_col[i];
 		}
+		blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
 		blockhist++;
 		blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
 	}
@@ -955,17 +1012,20 @@
 /* ------------------------------------------------------------------------ */
 uint64_t pop_block(void)
 {
-	int i;
+	int i, bhst;
 
 	if (!blockhist)
 		return block;
 	blockhist--;
-	display_mode = blockstack[blockhist % BLOCK_STACK_SIZE].display_mode;
-	for (i = 0; i < DISPLAY_MODES; i++) {
-		edit_row[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i];
-		edit_col[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i];
+	bhst = blockhist % BLOCK_STACK_SIZE;
+	dmode = blockstack[bhst].dmode;
+	for (i = 0; i < DMODES; i++) {
+		start_row[i] = blockstack[bhst].start_row[i];
+		edit_row[i] = blockstack[bhst].edit_row[i];
+		edit_col[i] = blockstack[bhst].edit_col[i];
 	}
-	return blockstack[blockhist % BLOCK_STACK_SIZE].block;
+	gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
+	return blockstack[bhst].block;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -981,8 +1041,12 @@
 	if (bobgets(string, 1, 7, 16)) {
 		if (!strcmp(string,"root"))
 			temp_blk = sbd.sd_sb.sb_root_dir.no_addr;
-		else if (!gfs1 && !strcmp(string,"master"))
-			temp_blk = sbd.sd_sb.sb_master_dir.no_addr;
+		else if (!strcmp(string,"master")) {
+			if (!gfs1)
+				temp_blk = sbd.sd_sb.sb_master_dir.no_addr;
+			else
+				; /* maybe put out an error message@some point */
+		}
 		else if (isalpha(string[0])) {
 			if (gfs1) {
 				if (!strcmp(string, "jindex"))
@@ -1063,7 +1127,7 @@
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
 	while (!Quit) {
-		display(display_mode, FALSE);
+		display(dmode, FALSE);
 		while ((ch=getch()) == 0); // wait for input
 		switch (ch)
 		{
@@ -1079,9 +1143,15 @@
 		/* home - return to the superblock                                */
 		/* -------------------------------------------------------------- */
 		case KEY_HOME:
-			block = 0x10;
-			push_block(block);
-			offset = 0;
+			if (dmode == EXTENDED_MODE) {
+				start_row[dmode] = 0;
+				edit_row[dmode] = 0;
+			}
+			else {
+				block = 0x10;
+				push_block(block);
+				offset = 0;
+			}
 			break;
 		/* -------------------------------------------------------------- */
 		/* backspace - return to the previous block on the stack          */
@@ -1103,54 +1173,73 @@
 		/* arrow up */
 		/* -------------------------------------------------------------- */
 		case KEY_UP:
-			if (edit_row[display_mode] >= 0) /* -1 means change block number */
-				edit_row[display_mode]--;
+			if (dmode == EXTENDED_MODE) {
+				if (edit_row[dmode] > 0)
+					edit_row[dmode]--;
+				if (edit_row[dmode] < start_row[dmode])
+					start_row[dmode] = edit_row[dmode];
+			}
+			else {
+				if (edit_row[dmode] >= 0)
+					edit_row[dmode]--;
+			}
 			break;
 		/* -------------------------------------------------------------- */
 		/* arrow down */
 		/* -------------------------------------------------------------- */
 		case KEY_DOWN:
-			if (edit_row[display_mode] < edit_last[display_mode])
-				edit_row[display_mode]++;
+			if (dmode == EXTENDED_MODE) {
+				if (edit_row[dmode] + 1 <
+					(indirect_blocks ? indirect_blocks:indirect[0].dirents)) {
+					if (edit_row[dmode] >= edit_last[dmode] +
+						start_row[dmode])
+						start_row[dmode]++;
+					edit_row[dmode]++;
+				}
+			}
+			else {
+				if (edit_row[dmode] < edit_last[dmode])
+					edit_row[dmode]++;
+			}
 			break;
 		/* -------------------------------------------------------------- */
 		/* arrow left */
 		/* -------------------------------------------------------------- */
 		case KEY_LEFT:
-			if (display_mode == HEX_MODE) {
-				if (edit_col[display_mode] > 0)
-					edit_col[display_mode]--;
+			if (dmode == HEX_MODE) {
+				if (edit_col[dmode] > 0)
+					edit_col[dmode]--;
 				else
-					edit_col[display_mode] = 15;
+					edit_col[dmode] = 15;
 			}
 			break;
 		/* -------------------------------------------------------------- */
 		/* arrow right */
 		/* -------------------------------------------------------------- */
 		case KEY_RIGHT:
-			if (display_mode == HEX_MODE) {
-				if (edit_col[display_mode] < 15)
-					edit_col[display_mode]++;
+			if (dmode == HEX_MODE) {
+				if (edit_col[dmode] < 15)
+					edit_col[dmode]++;
 				else
-					edit_col[display_mode] = 0;
+					edit_col[dmode] = 0;
 			}
 			break;
 		/* -------------------------------------------------------------- */
 		/* m - change display mode key */
 		/* -------------------------------------------------------------- */
 		case 'm':
-			display_mode = ((display_mode + 1) % DISPLAY_MODES);
+			dmode = ((dmode + 1) % DMODES);
 			break;
 		/* -------------------------------------------------------------- */
 		/* J - Jump to highlighted block number */
 		/* -------------------------------------------------------------- */
 		case 'j':
-			if (display_mode == HEX_MODE) {
+			if (dmode == HEX_MODE) {
 				unsigned int col2;
 				uint64_t *b;
 
-				col2 = edit_col[display_mode] & 0x08;/* thus 0-7->0, 8-15->8 */
-				b = (uint64_t *)&buf[edit_row[display_mode]*16 + offset + col2];
+				col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
+				b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2];
 				temp_blk=be64_to_cpu(*b);
 			}
 			else
@@ -1161,8 +1250,8 @@
 				offset = 0;
 				block = temp_blk;
 				push_block(block);
-				for (i = 0; i < DISPLAY_MODES; i++) {
-					edit_row[i] = 0;
+				for (i = 0; i < DMODES; i++) {
+					start_row[i] = edit_row[i] = 0;
 					edit_col[i] = 0;
 				}
 			}
@@ -1183,10 +1272,9 @@
 		/* b - Back one 4K block */
 		/* -------------------------------------------------------------- */
 		case 'b':
-			edit_row[display_mode] = 0;
-			if (block > 0) {
+			start_row[dmode] = edit_row[dmode] = 0;
+			if (block > 0)
 				block--;
-			}
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
@@ -1203,24 +1291,49 @@
 		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 == GFS2_MODE || offset==0) {
-				block--;
-				if (display_mode == HEX_MODE)
-					offset = (bufsize % screen_chunk_size) > 0 ? 
-						screen_chunk_size * (bufsize / screen_chunk_size) :
-						bufsize - screen_chunk_size;
+			if (dmode == EXTENDED_MODE) {
+				int lines_of_display = termlines - 6;
+
+				if (edit_row[dmode] - lines_of_display > 0) {
+					start_row[dmode] -= lines_of_display;
+					edit_row[dmode] -= lines_of_display;
+				}
+				else {
+					start_row[dmode] = 0;
+					edit_row[dmode] = 0;
+				}
+			}
+			else {
+				start_row[dmode] = edit_row[dmode] = 0;
+				if (dmode == GFS2_MODE || offset==0) {
+					block--;
+					if (dmode == HEX_MODE)
+						offset = (bufsize % screen_chunk_size) > 0 ? 
+							screen_chunk_size * (bufsize / screen_chunk_size) :
+							bufsize - screen_chunk_size;
+					else
+						offset = 0;
+				}
 				else
-					offset = 0;
+					offset -= screen_chunk_size;
 			}
-			else
-				offset -= screen_chunk_size;
+			break;
+		/* -------------------------------------------------------------- */
+		/* end - Jump to the end of the list */
+		/* -------------------------------------------------------------- */
+		case 0x168:
+			if (dmode == EXTENDED_MODE) {
+				edit_row[dmode] =
+					(indirect_blocks? indirect_blocks - 1:indirect[0].dirents - 1);
+				start_row[dmode] = edit_row[dmode] - (termlines - 7);
+			}
+			/* TODO: Make "end" key work for other display modes. */
 			break;
 		/* -------------------------------------------------------------- */
 		/* f - Forward one 4K block */
 		/* -------------------------------------------------------------- */
 		case 'f':
-			edit_row[display_mode] = 0;
+			start_row[dmode] = edit_row[dmode] = 0;
 			block++;
 			offset = 0;
 			break;
@@ -1230,14 +1343,29 @@
 		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 == GFS2_MODE ||
-				offset + screen_chunk_size >= bufsize) {
-				block++;
-				offset = 0;
+			if (dmode == EXTENDED_MODE) {
+				int lines_of_display = termlines - 6;
+
+				if (edit_row[dmode] + lines_of_display + 1 <
+					(indirect_blocks ? indirect_blocks:indirect[0].dirents)) {
+					start_row[dmode] += lines_of_display;
+					edit_row[dmode] += lines_of_display;
+				}
+				else {
+					edit_row[dmode] =
+						(indirect_blocks ? indirect_blocks - 1:indirect[0].dirents - 1);
+				}
+			}
+			else {
+				start_row[dmode] = edit_row[dmode] = 0;
+				if (dmode == GFS2_MODE ||
+					offset + screen_chunk_size >= bufsize) {
+					block++;
+					offset = 0;
+				}
+				else
+					offset += screen_chunk_size;
 			}
-			else
-				offset += screen_chunk_size;
 			break;
 		/* -------------------------------------------------------------- */
 		/* enter key - change a value */
@@ -1245,22 +1373,22 @@
 		case(KEY_ENTER):
 		case('\n'):
 		case('\r'):
-			if (edit_row[display_mode] == -1)
+			if (edit_row[dmode] == -1)
 				block = goto_block();
 			else {
-				if (display_mode == HEX_MODE) {
+				if (dmode == 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 (bobgets(edit_string, edit_row[dmode] + 3,
+								(edit_col[dmode] * 2) + 
+								(edit_col[dmode] / 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];
+							hexoffset = (edit_row[dmode] * 16) +
+								edit_col[dmode];
 							ch = 0x00;
 							if (isdigit(edit_string[0]))
 								ch = (edit_string[0] - '0') * 0x10;
@@ -1285,17 +1413,17 @@
 						}
 					}
 				}
-				else if (display_mode == GFS2_MODE)
-					bobgets(edit_string, edit_row[display_mode] + 4, 24,
-							edit_size[display_mode]);
+				else if (dmode == GFS2_MODE)
+					bobgets(edit_string, edit_row[dmode] + 4, 24,
+							edit_size[dmode]);
 				else
-					bobgets(edit_string, edit_row[display_mode] + 6, 14,
-							edit_size[display_mode]);
+					bobgets(edit_string, edit_row[dmode] + 6, 14,
+							edit_size[dmode]);
 			}
 			break;
 		default:
 			move(termlines - 1, 0);
-			printw("Keystroke not understood: %02X",ch);
+			printw("Keystroke not understood: 0x%03X",ch);
 			refresh();
 			sleep(1);
 			break;
@@ -1376,7 +1504,7 @@
 			else if (!strcasecmp(argv[i], "-p") ||
 					 !strcasecmp(argv[i], "-print")) {
 				termlines = 0; /* initial value--we'll figure it out later */
-				display_mode = GFS2_MODE;
+				dmode = GFS2_MODE;
 			}
 			else if (strchr(argv[i],'/'))
 				strcpy(device, argv[i]);
@@ -1386,7 +1514,7 @@
 				uint64_t temp_blk;
 
 				if (!strcasecmp(argv[i], "-x"))
-					display_mode = HEX_MODE;
+					dmode = HEX_MODE;
 				else if (argv[i][0] == '-') /* if it starts with a dash */
 					; /* ignore it--meant for pass == 0 */
 				else if (!strcmp(argv[i], "identify"))
@@ -1400,8 +1528,12 @@
 				else if (!strcmp(argv[i], "root") ||
 						 !strcmp(argv[i], "rootdir"))
 					push_block(sbd.sd_sb.sb_root_dir.no_addr);
-				else if (!gfs1 && !strcmp(argv[i], "master"))
-					push_block(sbd.sd_sb.sb_master_dir.no_addr);
+				else if (!strcmp(argv[i], "master")) {
+					if (!gfs1)
+						push_block(sbd.sd_sb.sb_master_dir.no_addr);
+					else
+						fprintf(stderr, "This is GFS1; there's no master directory.\n");
+				}
 				else if (!strcmp(argv[i], "jindex")) {
 					if (gfs1)
 						push_block(sbd1->sb_jindex_di.no_addr);
@@ -1461,17 +1593,19 @@
 
 	prog_name = argv[0];
 
+	memset(start_row, 0, sizeof(start_row));
 	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;
+	dmode = HEX_MODE;
 	type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */
 	block = 0x10;
 	for (i = 0; i < BLOCK_STACK_SIZE; i++) {
-		blockstack[i].display_mode = display_mode;
+		blockstack[i].dmode = dmode;
 		blockstack[i].block = block;
-		for (j = 0; j < DISPLAY_MODES; j++) {
+		for (j = 0; j < DMODES; j++) {
+			blockstack[i].start_row[j] = 0;
 			blockstack[i].edit_row[j] = 0;
 			blockstack[i].edit_col[j] = 0;
 		}
@@ -1498,7 +1632,7 @@
 	else { /* print all the structures requested */
 		for (i = 0; i <= blockhist; i++) {
 			block = blockstack[i + 1].block;
-			display(display_mode, identify);
+			display(dmode, identify);
 			if (!identify) {
 				display_extended();
 				printf("-------------------------------------" \
--- cluster/gfs2/edit/hexedit.h	2006/11/14 20:11:10	1.6
+++ cluster/gfs2/edit/hexedit.h	2007/02/08 05:41:16	1.7
@@ -39,7 +39,7 @@
 #define INIT(X) =X 
 #endif
 
-#define DISPLAY_MODES 3
+#define DMODES 3
 enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2 };
 #define BLOCK_STACK_SIZE 256
 
@@ -76,8 +76,9 @@
 EXTERN int line INIT(1);
 EXTERN int struct_len INIT(0);
 EXTERN unsigned int offset;
-EXTERN int edit_row[DISPLAY_MODES], edit_col[DISPLAY_MODES];
-EXTERN int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES];
+EXTERN int edit_row[DMODES], edit_col[DMODES];
+EXTERN int start_row[DMODES];
+EXTERN int edit_size[DMODES], edit_last[DMODES];
 EXTERN char edit_string[1024], edit_fmt[80];
 EXTERN struct gfs2_sbd sbd;
 EXTERN struct gfs_sb *sbd1;
@@ -114,9 +115,15 @@
 
 struct blkstack_info {
 	uint64_t block;
-	int edit_row[DISPLAY_MODES];
-	int edit_col[DISPLAY_MODES];
-	enum dsp_mode display_mode;
+	int start_row[DMODES];
+	int edit_row[DMODES];
+	int edit_col[DMODES];
+	enum dsp_mode dmode;
+	int gfs2_struct_type;
+};
+
+struct metapath {
+	uint64_t mp_list[GFS2_MAX_META_HEIGHT];
 };
 
 struct gfs_sb {
@@ -154,7 +161,7 @@
 											  4K block */
 EXTERN struct indirect_info masterdir; /* Master directory info */
 EXTERN int indirect_blocks INIT(0);  /* count of indirect blocks */
-EXTERN enum dsp_mode display_mode INIT(HEX_MODE);
+EXTERN enum dsp_mode dmode INIT(HEX_MODE);
 
 #define SCREEN_HEIGHT   (16)
 #define SCREEN_WIDTH    (16)



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2007-11-13 17:22 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2007-11-13 17:22 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2007-11-13 17:22:06

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Fixed printing of gfs1 journals.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.12&r2=1.13
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.24&r2=1.25
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.13&r2=1.14

--- cluster/gfs2/edit/gfs2hex.c	2007/07/30 15:31:23	1.12
+++ cluster/gfs2/edit/gfs2hex.c	2007/11/13 17:22:06	1.13
@@ -463,6 +463,7 @@
 	struct gfs2_meta_header mh;
 	struct gfs2_rgrp rg;
 	struct gfs2_leaf lf;
+	struct gfs_log_header lh1;
 	struct gfs2_log_header lh;
 	struct gfs2_log_descriptor ld;
 
@@ -525,8 +526,13 @@
 		case GFS2_METATYPE_LH:
 			print_gfs2("Log Header:");
 			eol(0);
-			gfs2_log_header_in(&lh, buf);
-			gfs2_log_header_print(&lh);
+			if (gfs1) {
+				gfs_log_header_in(&lh1, buf);
+				gfs_log_header_print(&lh1);
+			} else {
+				gfs2_log_header_in(&lh, buf);
+				gfs2_log_header_print(&lh);
+			}
 			break;
 			
 		case GFS2_METATYPE_LD:
--- cluster/gfs2/edit/hexedit.c	2007/11/08 18:10:09	1.24
+++ cluster/gfs2/edit/hexedit.c	2007/11/13 17:22:06	1.25
@@ -1247,6 +1247,8 @@
 		parse_rindex(tmp_inode, TRUE);
 		brelse(tmp_bh, not_updated);
 	}
+	else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
+		return -1;
 	else if (block_is_rglist()) {
 		tmp_bh = bread(&sbd, masterblock("rindex"));
 		tmp_inode = inode_get(&sbd, tmp_bh);
@@ -1277,8 +1279,6 @@
 		print_quota(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
-		return -1;
 	return 0;
 }
 
@@ -1977,6 +1977,42 @@
 }/* interactive_mode */
 
 /* ------------------------------------------------------------------------ */
+/* gfs_log_header_in - read in a gfs1-style log header                      */
+/* ------------------------------------------------------------------------ */
+void gfs_log_header_in(struct gfs_log_header *head, char *buf)
+{
+	struct gfs_log_header *str = (struct gfs_log_header *) buf;
+
+	gfs2_meta_header_in(&head->lh_header, buf);
+
+	head->lh_flags = be32_to_cpu(str->lh_flags);
+	head->lh_pad = be32_to_cpu(str->lh_pad);
+
+	head->lh_first = be64_to_cpu(str->lh_first);
+	head->lh_sequence = be64_to_cpu(str->lh_sequence);
+
+	head->lh_tail = be64_to_cpu(str->lh_tail);
+	head->lh_last_dump = be64_to_cpu(str->lh_last_dump);
+
+	memcpy(head->lh_reserved, str->lh_reserved, 64);
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* gfs_log_header_print - print a gfs1-style log header                     */
+/* ------------------------------------------------------------------------ */
+void gfs_log_header_print(struct gfs_log_header *lh)
+{
+	gfs2_meta_header_print(&lh->lh_header);
+	pv(lh, lh_flags, "%u", "0x%.8X");
+	pv(lh, lh_pad, "%u", "%x");
+	pv(lh, lh_first, "%llu", "%llx");
+	pv(lh, lh_sequence, "%llu", "%llx");
+	pv(lh, lh_tail, "%llu", "%llx");
+	pv(lh, lh_last_dump, "%llu", "%llx");
+}
+
+/* ------------------------------------------------------------------------ */
 /* dump_journal - dump a journal file's contents.                           */
 /* ------------------------------------------------------------------------ */
 void dump_journal(const char *journal)
@@ -2045,19 +2081,34 @@
 			uint64_t *b;
 			struct gfs2_log_descriptor ld;
 			int i = 0, ltndx;
-			const char *logtypestr[4] = {
-				"Metadata", "Revoke", "Jdata", "Unknown"};
+			uint32_t logtypes[2][6] = {
+				{GFS2_LOG_DESC_METADATA,
+				 GFS2_LOG_DESC_REVOKE,
+				 GFS2_LOG_DESC_JDATA,
+				 0, 0, 0},
+				{GFS_LOG_DESC_METADATA,
+				 GFS_LOG_DESC_IUL,
+				 GFS_LOG_DESC_IDA,
+				 GFS_LOG_DESC_Q,
+				 GFS_LOG_DESC_LAST,
+				 0}};
+			const char *logtypestr[2][6] = {
+				{"Metadata", "Revoke", "Jdata",
+				 "Unknown", "Unknown", "Unknown"},
+				{"Metadata", "Unlinked inode", "Dealloc inode",
+				 "Quota", "Final Entry", "Unknown"}};
 
 			print_gfs2("Block #%4llx: Log descriptor, ",
 				   jb / (gfs1 ? 1 : bufsize));
 			gfs2_log_descriptor_in(&ld, jbuf);
 			print_gfs2("type %d ", ld.ld_type);
-			if (ld.ld_type >= GFS2_LOG_DESC_METADATA &&
-			    ld.ld_type <= GFS2_LOG_DESC_JDATA)
-				ltndx = ld.ld_type - GFS2_LOG_DESC_METADATA;
-			else
-				ltndx = 3;
-			print_gfs2("(%s) ", logtypestr[ltndx]);
+
+			for (ltndx = 0;; ltndx++) {
+				if (ld.ld_type == logtypes[gfs1][ltndx] ||
+				    logtypes[gfs1][ltndx] == 0)
+					break;
+			}
+			print_gfs2("(%s) ", logtypestr[gfs1][ltndx]);
 			print_gfs2("len:%u, data1: %u",
 				   ld.ld_length, ld.ld_data1);
 			eol(0);
@@ -2085,11 +2136,22 @@
 			eol(0);
 		} else if (get_block_type(jbuf) == GFS2_METATYPE_LH) {
 			struct gfs2_log_header lh;
+			struct gfs_log_header lh1;
 
-			gfs2_log_header_in(&lh, jbuf);
-			print_gfs2("Block #%4llx: Log header: Seq = 0x%x, tail = 0x%x, blk = 0x%x",
-				   jb / (gfs1 ? 1 : bufsize),
-				   lh.lh_sequence, lh.lh_tail, lh.lh_blkno);
+			if (gfs1) {
+				gfs_log_header_in(&lh1, jbuf);
+				print_gfs2("Block #%4llx: Log header: Seq"
+					   "= 0x%x, first = 0x%x tail = "
+					   "0x%x, last = 0x%x",
+					   jb, lh1.lh_sequence, lh1.lh_first,
+					   lh1.lh_tail, lh1.lh_last_dump);
+			} else {
+				gfs2_log_header_in(&lh, jbuf);
+				print_gfs2("Block #%4llx: Log header: Seq"
+					   "= 0x%x, tail = 0x%x, blk = 0x%x",
+					   jb / bufsize, lh.lh_sequence,
+					   lh.lh_tail, lh.lh_blkno);
+			}
 			eol(0);
 		}
 	}
--- cluster/gfs2/edit/hexedit.h	2007/11/13 17:03:39	1.13
+++ cluster/gfs2/edit/hexedit.h	2007/11/13 17:22:06	1.14
@@ -57,6 +57,13 @@
 #define GFS_FILE_FIFO           (101)  /* fifo/pipe */
 #define GFS_FILE_SOCK           (102)  /* socket */
 
+/* GFS 1 journal block types: */
+#define GFS_LOG_DESC_METADATA   (300)    /* metadata */
+#define GFS_LOG_DESC_IUL        (400)    /* unlinked inode */
+#define GFS_LOG_DESC_IDA        (401)    /* de-allocated inode */
+#define GFS_LOG_DESC_Q          (402)    /* quota */
+#define GFS_LOG_DESC_LAST       (500)    /* final in a logged transaction */
+
 EXTERN char *prog_name;
 EXTERN uint64_t block INIT(0);
 EXTERN int blockhist INIT(0);
@@ -103,12 +110,39 @@
         char ji_reserved[64];
 };
 
+struct gfs_log_descriptor {
+	struct gfs2_meta_header ld_header;
+
+	uint32_t ld_type;       /* GFS_LOG_DESC_... Type of this log chunk */
+	uint32_t ld_length;     /* Number of buffers in this chunk */
+	uint32_t ld_data1;      /* descriptor-specific field */
+	uint32_t ld_data2;      /* descriptor-specific field */
+	char ld_reserved[64];
+};
+
+struct gfs_log_header {
+	struct gfs2_meta_header lh_header;
+
+	uint32_t lh_flags;      /* GFS_LOG_HEAD_... */
+	uint32_t lh_pad;
+
+	uint64_t lh_first;     /* Block number of first header in this trans */
+	uint64_t lh_sequence;   /* Sequence number of this transaction */
+
+	uint64_t lh_tail;       /* Block number of log tail */
+	uint64_t lh_last_dump;  /* Block number of last dump */
+
+	char lh_reserved[64];
+};
+
 EXTERN int block_is_jindex(void);
 EXTERN int block_is_inum_file(void);
 EXTERN int block_is_statfs_file(void);
 EXTERN int block_is_quota_file(void);
 EXTERN int display_block_type(const char *lpBuffer, int from_restore);
 EXTERN void gfs_jindex_in(struct gfs_jindex *jindex, char *buf);
+EXTERN void gfs_log_header_in(struct gfs_log_header *head, char *buf);
+EXTERN void gfs_log_header_print(struct gfs_log_header *lh);
 
 struct gfs2_dirents {
 	uint64_t block;
@@ -177,16 +211,6 @@
 	char sb_reserved[96];
 };
 
-struct gfs_log_descriptor {
-	struct gfs2_meta_header ld_header;
-
-	uint32_t ld_type;       /* GFS_LOG_DESC_... Type of this log chunk */
-	uint32_t ld_length;     /* Number of buffers in this chunk */
-	uint32_t ld_data1;      /* descriptor-specific field */
-	uint32_t ld_data2;      /* descriptor-specific field */
-	char ld_reserved[64];
-};
-
 EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
 EXTERN struct iinfo *indirect; /* more than the most indirect
 			       pointers possible for any given 4K block */



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2007-02-28 21:58 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2007-02-28 21:58 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2007-02-28 21:58:46

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Made hex editing a lot easier (for bz 229484).  Fixed several bugs
	regarding printing.  Added ability to print/view gfs1 journal index.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.9&r2=1.10
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.10&r2=1.11
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.8&r2=1.9

--- cluster/gfs2/edit/gfs2hex.c	2007/02/13 01:07:35	1.9
+++ cluster/gfs2/edit/gfs2hex.c	2007/02/28 21:58:46	1.10
@@ -41,11 +41,11 @@
 extern uint64_t bufsize;
 extern int line, termlines;
 extern char edit_fmt[80];
-extern char edit_string[1024];
+extern char estring[1024];
 extern int edit_mode INIT(0);
 extern int edit_row[DMODES], edit_col[DMODES];
 extern int edit_size[DMODES], last_entry_onscreen[DMODES];
-extern char edit_string[1024], edit_fmt[80];
+extern char edit_fmt[80];
 extern enum dsp_mode dmode INIT(HEX_MODE); /* display mode */
 
 void eol(int col) /* end of line */
@@ -167,9 +167,9 @@
 		if (termlines) {
 			refresh();
 			if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
-				strcpy(edit_string, tmp_string);
+				strcpy(estring, tmp_string);
 				strcpy(edit_fmt, fmt);
-				edit_size[dmode] = strlen(edit_string);
+				edit_size[dmode] = strlen(estring);
 				COLORS_NORMAL;
 			}
 			last_entry_onscreen[dmode] = (line / lines_per_row[dmode]) - 4;
--- cluster/gfs2/edit/hexedit.c	2007/02/13 01:07:35	1.10
+++ cluster/gfs2/edit/hexedit.c	2007/02/28 21:58:46	1.11
@@ -112,9 +112,9 @@
 /* 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 bobgets(char string[],int x,int y,int sz,int *ch)
 {
-	int done,ch,runningy,rc;
+	int done,runningy,rc;
 
 	move(x,y);
 	done=FALSE;
@@ -127,23 +127,29 @@
 	runningy=y;
 	rc=0;
 	while (!done) {
-		ch=getch();
+		*ch = getch();
 		
-		if(ch < 0x0100 && isprint(ch)) {
+		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;
+			string[runningy-y]=*ch;
 			runningy++;
 			move(x,y);
 			addstr(string);
+			if (runningy-y >= sz) {
+				rc=1;
+				*ch = KEY_RIGHT;
+				done = TRUE;
+			}
 		}
 		else {
 			// special character, is it one we recognize?
-			switch(ch)
+			switch(*ch)
 			{
 			case(KEY_ENTER):
 			case('\n'):
@@ -157,11 +163,20 @@
 				done=TRUE;
 				break;
 			case(KEY_LEFT):
-				if (runningy>y)
+				if (dmode == HEX_MODE) {
+					done = TRUE;
+					rc = 1;
+				}
+				else
 					runningy--;
 				break;
 			case(KEY_RIGHT):
-				runningy++;
+				if (dmode == HEX_MODE) {
+					done = TRUE;
+					rc = 1;
+				}
+				else
+					runningy++;
 				break;
 			case(KEY_DC):
 			case(0x07F):
@@ -220,7 +235,7 @@
 				break;
 			default:
 				move(0,70);
-				printw("%08X",ch);
+				printw("%08X",*ch);
 				// ignore all other characters
 				break;
 			} // end switch on non-printable character
@@ -503,8 +518,8 @@
 			if (termlines && line == edit_row[dmode] + 3 &&
 				i == edit_col[dmode]) {
 				COLORS_HIGHLIGHT; /* normal part of the structure */
-				memset(edit_string,0,3);
-				sprintf(edit_string,"%02X",*pointer);
+				memset(estring,0,3);
+				sprintf(estring,"%02X",*pointer);
 			}
 			print_gfs2("%02X",*pointer);
 			if (termlines && line == edit_row[dmode] + 3 &&
@@ -581,7 +596,7 @@
 			 termlines - start_line - 2)) {
 			if (edit_row[dmode] == print_entry_ndx) {
 				COLORS_HIGHLIGHT;
-				sprintf(edit_string, "%" PRIx64, ri.ri_addr);
+				sprintf(estring, "%" PRIx64, ri.ri_addr);
 			}
 			print_gfs2("RG #%d", print_entry_ndx);
 			eol(0);
@@ -596,6 +611,71 @@
 }
 
 /* ------------------------------------------------------------------------ */
+/* gfs_jindex_in - read in a gfs1 jindex structure.                         */
+/* ------------------------------------------------------------------------ */
+void gfs_jindex_in(struct gfs_jindex *jindex, char *buf)
+{
+        struct gfs_jindex *str = (struct gfs_jindex *) buf;
+
+        jindex->ji_addr = be64_to_cpu(str->ji_addr);
+        jindex->ji_nsegment = be32_to_cpu(str->ji_nsegment);
+        jindex->ji_pad = be32_to_cpu(str->ji_pad);
+        memcpy(jindex->ji_reserved, str->ji_reserved, 64);
+}
+
+/* ------------------------------------------------------------------------ */
+/* gfs_jindex_print - print an jindex entry.                                */
+/* ------------------------------------------------------------------------ */
+void gfs_jindex_print(struct gfs_jindex *ji)
+{
+        pv(ji, ji_addr, "%llu", "0x%llx");
+        pv(ji, ji_nsegment, "%u", "0x%x");
+        pv(ji, ji_pad, "%u", "0x%x");
+}
+
+/* ------------------------------------------------------------------------ */
+/* print_jindex - print the jindex file.                                    */
+/* ------------------------------------------------------------------------ */
+int print_jindex(struct gfs2_inode *di)
+{
+	int error, start_line;
+	struct gfs_jindex ji;
+	char buf[sizeof(struct gfs_jindex)];
+
+	start_line = line;
+	error = 0;
+	print_gfs2("Journal index entries found: %d.",
+		   di->i_di.di_size / sizeof(struct gfs_jindex));
+	eol(0);
+	lines_per_row[dmode] = 6;
+	for (print_entry_ndx=0; ; print_entry_ndx++) {
+		error = gfs2_readi(di, (void *)&buf,
+				   print_entry_ndx*sizeof(struct gfs_jindex),
+				   sizeof(struct gfs_jindex));
+		gfs_jindex_in(&ji, buf);
+		if (!error) /* end of file */
+			break;
+		if (!termlines ||
+		    (print_entry_ndx >= start_row[dmode] &&
+		     ((print_entry_ndx - start_row[dmode])+1) *
+		     lines_per_row[dmode] <= termlines - start_line - 2)) {
+			if (edit_row[dmode] == print_entry_ndx) {
+				COLORS_HIGHLIGHT;
+				sprintf(estring, "%" PRIx64, ji.ji_addr);
+			}
+			print_gfs2("Journal #%d", print_entry_ndx);
+			eol(0);
+			if (edit_row[dmode] == print_entry_ndx)
+				COLORS_NORMAL;
+			gfs_jindex_print(&ji);
+			last_entry_onscreen[dmode] = print_entry_ndx;
+		}
+	}
+	end_row[dmode] = print_entry_ndx;
+	return error;
+}
+
+/* ------------------------------------------------------------------------ */
 /* print_inum - print the inum file.                                        */
 /* ------------------------------------------------------------------------ */
 int print_inum(struct gfs2_inode *di)
@@ -723,7 +803,7 @@
 	eol(0);
 	start_line = line;
 	if (!has_indirect_blocks())
-		return -01;
+		return -1;
 
 	indir_blocks = indirect_blocks;
 	if (!indirect_blocks) {
@@ -798,10 +878,10 @@
 				if (edit_row[dmode] >= 0 &&
 					line - start_line - 2 == edit_row[dmode] -
 					start_row[dmode]) { 
-					sprintf(edit_string, "%"PRIx64,
+					sprintf(estring, "%"PRIx64,
 							indirect[print_entry_ndx].block);
 					strcpy(edit_fmt, "%"PRIx64);
-					edit_size[dmode] = strlen(edit_string);
+					edit_size[dmode] = strlen(estring);
 					COLORS_NORMAL;
 				}
 			}
@@ -848,7 +928,7 @@
 							edit_row[dmode] -
 							start_row[dmode]) {
 							COLORS_HIGHLIGHT;
-							sprintf(edit_string, "%"PRIx64,
+							sprintf(estring, "%"PRIx64,
 									indirect[print_entry_ndx].dirent[d].block);
 							strcpy(edit_fmt, "%"PRIx64);
 						}
@@ -883,6 +963,73 @@
 }
 
 /* ------------------------------------------------------------------------ */
+/* block_is_rindex                                                          */
+/* ------------------------------------------------------------------------ */
+int block_is_rindex(void)
+{
+	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
+	    (block == masterblock("rindex")))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_jindex                                                          */
+/* ------------------------------------------------------------------------ */
+int block_is_jindex(void)
+{
+	if ((gfs1 && block == sbd1->sb_jindex_di.no_addr))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_inum_file                                                       */
+/* ------------------------------------------------------------------------ */
+int block_is_inum_file(void)
+{
+	if (!gfs1 && block == masterblock("inum"))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_statfs_file                                                     */
+/* ------------------------------------------------------------------------ */
+int block_is_statfs_file(void)
+{
+	if (!gfs1 && block == masterblock("statfs"))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_quota_file                                                      */
+/* ------------------------------------------------------------------------ */
+int block_is_quota_file(void)
+{
+	if ((gfs1 && block == gfs1_quota_di.no_addr) ||
+	    (block == masterblock("quota")))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_has_extended_info                                                  */
+/* ------------------------------------------------------------------------ */
+int block_has_extended_info(void)
+{
+	if (has_indirect_blocks() ||
+	    block_is_rindex() ||
+	    block_is_jindex() ||
+	    block_is_inum_file() ||
+	    block_is_statfs_file() ||
+	    block_is_quota_file())
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
 /* display_extended                                                         */
 /* ------------------------------------------------------------------------ */
 int display_extended(void)
@@ -891,29 +1038,33 @@
 	struct gfs2_buffer_head *tmp_bh;
 
 	/* Display any indirect pointers that we have. */
-	if (display_indirect() < 0)
+	if (display_indirect() == 0)
 		return -1;
-	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
-		(block == masterblock("rindex"))) {
+	else if (block_is_rindex()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_rindex(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (!gfs1 && block == masterblock("inum")) {
+	else if (block_is_jindex()) {
+		tmp_bh = bread(&sbd, block);
+		tmp_inode = inode_get(&sbd, tmp_bh);
+		print_jindex(tmp_inode);
+		brelse(tmp_bh, not_updated);
+	}
+	else if (block_is_inum_file()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_inum(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (!gfs1 && block == masterblock("statfs")) {
+	else if (block_is_statfs_file()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_statfs(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if ((gfs1 && block == gfs1_quota_di.no_addr) ||
-			 (block == masterblock("quota"))) {
+	else if (block_is_quota_file()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_quota(tmp_inode);
@@ -1035,7 +1186,8 @@
 		indirect_blocks = 1;
 		memset(&indirect, 0, sizeof(indirect));
 		/* Directory Entries: */
-		for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) {
+		for (x = sizeof(struct gfs2_leaf); x < bufsize;
+		     x += de.de_rec_len) {
 			gfs2_dirent_in(&de, buf + x);
 			if (de.de_inum.no_addr) {
 				indirect[indirect_blocks].block = de.de_inum.no_addr;
@@ -1047,24 +1199,31 @@
 				indirect[indirect_blocks].is_dir = TRUE;
 				indirect[indirect_blocks].dirents++;
 			}
+			if (de.de_rec_len <= sizeof(struct gfs2_dirent))
+				break;
 		}
 	}
 	last_entry_onscreen[dmode] = 0;
-	if (dmode == EXTENDED_MODE && !has_indirect_blocks())
+	if (dmode == EXTENDED_MODE && !block_has_extended_info())
 		dmode = HEX_MODE;
 	if (termlines) {
 		move(termlines, 63);
-		printw("Mode: %s", (dmode==HEX_MODE?"Hex edit ":(dmode==GFS2_MODE?"Structure":"Pointers ")));
+		if (dmode==HEX_MODE)
+			printw("Mode: Hex %s", (editing?"edit ":"view "));
+		else
+			printw("Mode: %s", (dmode==GFS2_MODE?"Structure":
+					    "Pointers "));
 		move(line, 0);
 	}
 	if (dmode == HEX_MODE)          /* if hex display mode           */
-		hexdump(dev_offset, buf, (gfs2_struct_type == GFS2_METATYPE_DI)?
-				struct_len + di.di_size:bufsize); /* show block in hex */
+		hexdump(dev_offset, buf,
+			(gfs2_struct_type == GFS2_METATYPE_DI)?
+			struct_len + di.di_size:bufsize);
 	else if (dmode == GFS2_MODE)    /* if structure display          */
-		display_gfs2();                    /* display the gfs2 structure    */
+		display_gfs2();            /* display the gfs2 structure    */
 	else
-		display_extended();                /* display extended blocks       */
-	/* No else here, because display_extended can switch back to hex mode */
+		display_extended();        /* display extended blocks       */
+	/* No else here because display_extended can switch back to hex mode */
 	if (termlines)
 		refresh();
 	return(0);
@@ -1121,12 +1280,12 @@
 /* ------------------------------------------------------------------------ */
 uint64_t goto_block(void)
 {
-	uint64_t temp_blk;
 	char string[256];
+	int ch;
 
 	memset(string, 0, sizeof(string));
 	sprintf(string,"%"PRId64, block);
-	if (bobgets(string, 1, 7, 16)) {
+	if (bobgets(string, 1, 7, 16, &ch)) {
 		if (!strcmp(string,"root"))
 			temp_blk = sbd.sd_sb.sb_root_dir.no_addr;
 		else if (!strcmp(string,"master")) {
@@ -1168,22 +1327,159 @@
 {
 
 	if (color_scheme) {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
+		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK);
+		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE);
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK);
+		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK);
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK);
+		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK);
+	}
+	else {
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
+		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE);
+		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK);
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE);
+		init_pair(COLOR_HIGHLIGHT, COLOR_MAGENTA, COLOR_WHITE);
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE);
+		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE);
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+/* hex_edit - Allow the user to edit the page by entering hex digits        */
+/* ------------------------------------------------------------------------ */
+void hex_edit(int *exitch)
+{
+	int left_off;
+	int ch;
+
+	left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17;
+	/* 8 and 16 char addresses on screen */
+	
+	if (bobgets(estring, edit_row[dmode] + 3,
+		    (edit_col[dmode] * 2) + (edit_col[dmode] / 4) + left_off,
+		    2, exitch)) {
+		if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
+			int hexoffset;
+			int i, sl = strlen(estring);
+			
+			for (i = 0; i < sl; i+=2) {
+				hexoffset = (edit_row[dmode] * 16) +
+					edit_col[dmode] + (i / 2);
+				ch = 0x00;
+				if (isdigit(estring[i]))
+					ch = (estring[i] - '0') * 0x10;
+				else if (estring[i] >= 'a' &&
+					 estring[i] <= 'f')
+					ch = (estring[i]-'a' + 0x0a)*0x10;
+				else if (estring[i] >= 'A' &&
+					 estring[i] <= 'F')
+					ch = (estring[i] - 'A' + 0x0a) * 0x10;
+				if (isdigit(estring[i+1]))
+					ch += (estring[i+1] - '0');
+				else if (estring[i+1] >= 'a' &&
+					 estring[i+1] <= 'f')
+					ch += (estring[i+1] - 'a' + 0x0a);
+				else if (estring[i+1] >= 'A' &&
+					 estring[i+1] <= 'F')
+					ch += (estring[i+1] - 'A' + 0x0a);
+				buf[offset + hexoffset] = ch;
+			}
+			do_lseek(fd, dev_offset);
+			do_write(fd, buf, bufsize);
+			fsync(fd);
+		}
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+/* page up                                                                  */
+/* ------------------------------------------------------------------------ */
+void pageup(void)
+{
+	if (dmode == EXTENDED_MODE) {
+		int dsplines = termlines - 6;
+		
+		if (edit_row[dmode] - (dsplines / lines_per_row[dmode]) > 0) {
+			start_row[dmode] -= (dsplines / lines_per_row[dmode]);
+			edit_row[dmode] -= (dsplines / lines_per_row[dmode]);
+		}
+		else {
+			start_row[dmode] = 0;
+			edit_row[dmode] = 0;
+		}
+	}
+	else {
+		start_row[dmode] = edit_row[dmode] = 0;
+		if (dmode == GFS2_MODE || offset==0) {
+			block--;
+			if (dmode == 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;
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+/* page down                                                                */
+/* ------------------------------------------------------------------------ */
+void pagedn(void)
+{
+	if (dmode == EXTENDED_MODE) {
+		int dsplines = termlines - 6;
+
+		if ((edit_row[dmode] + dsplines) / lines_per_row[dmode] + 1 <
+		    end_row[dmode]) {
+			start_row[dmode] += dsplines / lines_per_row[dmode];
+			edit_row[dmode] += dsplines / lines_per_row[dmode];
+		}
+		else
+			edit_row[dmode] = end_row[dmode] - 1;
 	}
 	else {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_MAGENTA, COLOR_WHITE); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
+		start_row[dmode] = edit_row[dmode] = 0;
+		if (dmode == GFS2_MODE ||
+		    offset + screen_chunk_size >= bufsize) {
+			block++;
+			offset = 0;
+		}
+		else
+			offset += screen_chunk_size;
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+/* jump - jump to the address the cursor is on                              */
+/* ------------------------------------------------------------------------ */
+void jump(void)
+{
+	if (dmode == HEX_MODE) {
+		unsigned int col2;
+		uint64_t *b;
+		
+		col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
+		b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2];
+		temp_blk=be64_to_cpu(*b);
+	}
+	else
+		sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */
+	if (temp_blk < max_block) { /* if the block number is valid */
+		int i;
+		
+		offset = 0;
+		block = temp_blk;
+		push_block(block);
+		for (i = 0; i < DMODES; i++) {
+			start_row[i] = end_row[i] = edit_row[i] = 0;
+			edit_col[i] = 0;
+		}
 	}
 }
 
@@ -1193,8 +1489,6 @@
 void interactive_mode(void)
 {
 	int ch, Quit;
-	int64_t temp_blk;
-	int left_off;
 
 	if ((wind = initscr()) == NULL) {
 		fprintf(stderr, "Error: unable to initialize screen.");
@@ -1214,22 +1508,42 @@
 	init_colors();
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
+	editing = FALSE;
 	while (!Quit) {
 		display(FALSE);
-		while ((ch=getch()) == 0); // wait for input
+		if (editing) {
+			if (edit_row[dmode] == -1)
+				block = goto_block();
+			else {
+				if (dmode == HEX_MODE)
+					hex_edit(&ch);
+				else if (dmode == GFS2_MODE)
+					bobgets(estring, edit_row[dmode]+4, 24,
+						edit_size[dmode], &ch);
+				else
+					bobgets(estring, edit_row[dmode]+6, 14,
+						edit_size[dmode], &ch);
+			}
+		}
+		else
+			while ((ch=getch()) == 0); // wait for input
+
 		switch (ch)
 		{
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* escape or 'q' */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 0x1b:
 		case 0x03:
 		case 'q':
-			Quit=TRUE;
+			if (editing)
+				editing = FALSE;
+			else
+				Quit=TRUE;
 			break;
-		/* -------------------------------------------------------------- */
-		/* home - return to the superblock                                */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
+		/* home - return to the superblock                           */
+		/* --------------------------------------------------------- */
 		case KEY_HOME:
 			if (dmode == EXTENDED_MODE) {
 				start_row[dmode] = end_row[dmode] = 0;
@@ -1241,25 +1555,25 @@
 				offset = 0;
 			}
 			break;
-		/* -------------------------------------------------------------- */
-		/* backspace - return to the previous block on the stack          */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
+		/* backspace - return to the previous block on the stack     */
+		/* --------------------------------------------------------- */
 		case KEY_BACKSPACE:
 		case 0x7f:
 			block = pop_block();
 			offset = 0;
 			break;
-		/* -------------------------------------------------------------- */
-		/* space - go down the block stack (opposite of backspace)        */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
+		/* space - go down the block stack (opposite of backspace)   */
+		/* --------------------------------------------------------- */
 		case ' ':
 			blockhist++;
 			block = blockstack[blockhist % BLOCK_STACK_SIZE].block;
 			offset = 0;
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* arrow up */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case KEY_UP:
 			if (dmode == EXTENDED_MODE) {
 				if (edit_row[dmode] > 0)
@@ -1272,9 +1586,9 @@
 					edit_row[dmode]--;
 			}
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* arrow down */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case KEY_DOWN:
 			if (dmode == EXTENDED_MODE) {
 				if (edit_row[dmode] + 1 < end_row[dmode]) {
@@ -1288,9 +1602,9 @@
 					edit_row[dmode]++;
 			}
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* arrow left */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case KEY_LEFT:
 			if (dmode == HEX_MODE) {
 				if (edit_col[dmode] > 0)
@@ -1299,9 +1613,9 @@
 					edit_col[dmode] = 15;
 			}
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* arrow right */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case KEY_RIGHT:
 			if (dmode == HEX_MODE) {
 				if (edit_col[dmode] < 15)
@@ -1310,217 +1624,103 @@
 					edit_col[dmode] = 0;
 			}
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* m - change display mode key */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'm':
 			dmode = ((dmode + 1) % DMODES);
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* J - Jump to highlighted block number */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'j':
-			if (dmode == HEX_MODE) {
-				unsigned int col2;
-				uint64_t *b;
-
-				col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
-				b = (uint64_t *)&buf[edit_row[dmode]*16 + offset + col2];
-				temp_blk=be64_to_cpu(*b);
-			}
-			else
-				sscanf(edit_string, "%"SCNx64, &temp_blk);/* retrieve in hex */
-			if (temp_blk < max_block) { /* if the block number is valid */
-				int i;
-
-				offset = 0;
-				block = temp_blk;
-				push_block(block);
-				for (i = 0; i < DMODES; i++) {
-					start_row[i] = end_row[i] = edit_row[i] = 0;
-					edit_col[i] = 0;
-				}
-			}
+			jump();
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* g - goto block */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'g':
 			block = goto_block();
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* h - help key */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'h':
 			print_usage();
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* e - change to extended mode */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'e':
 			dmode = EXTENDED_MODE;
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* b - Back one 4K block */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'b':
 			start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
 			if (block > 0)
 				block--;
 			offset = 0;
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* c - Change color scheme */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'c':
 			color_scheme = !color_scheme;
 			init_colors();
 			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.
-			if (dmode == EXTENDED_MODE) {
-				int lines_of_display = termlines - 6;
-
-				if (edit_row[dmode] - (lines_of_display / lines_per_row[dmode]) > 0) {
-					start_row[dmode] -= (lines_of_display / lines_per_row[dmode]);
-					edit_row[dmode] -= (lines_of_display / lines_per_row[dmode]);
-				}
-				else {
-					start_row[dmode] = 0;
-					edit_row[dmode] = 0;
-				}
-			}
-			else {
-				start_row[dmode] = edit_row[dmode] = 0;
-				if (dmode == GFS2_MODE || offset==0) {
-					block--;
-					if (dmode == 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;
-			}
+			pageup();
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* end - Jump to the end of the list */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 0x168:
 			if (dmode == EXTENDED_MODE) {
-				int lines_of_display = termlines - 6;
-				int entries_per_screen = lines_of_display /
+				int dsplines = termlines - 6;
+				int ents_per_screen = dsplines /
 					lines_per_row[dmode];
 
 				edit_row[dmode] = end_row[dmode] - 1;
-				if ((edit_row[dmode] - entries_per_screen) + 1 > 0)
-					start_row[dmode] = edit_row[dmode] - entries_per_screen + 1;
-				/*
-				  if (edit_row[dmode] * lines_per_row[dmode] > (termlines - 7))
-				  start_row[dmode] = (edit_row[dmode] - (termlines - 7)) /
-				  lines_per_row[dmode];
-				*/
+				if ((edit_row[dmode] - ents_per_screen)+1 > 0)
+					start_row[dmode] = edit_row[dmode] - 
+						ents_per_screen + 1;
 				else
 					start_row[dmode] = 0;
 			}
-			/* TODO: Make "end" key work for other display modes. */
+			/* TODO: Make end key work for other display modes. */
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* f - Forward one 4K block */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 'f':
-			start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
+			start_row[dmode]=end_row[dmode]=edit_row[dmode] = 0;
 			lines_per_row[dmode] = 1;
 			block++;
 			offset = 0;
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* page down key */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case 0x16:                    // ctrl-v for vt100
 		case KEY_NPAGE:		      // PgDown
 		case 0x04:                    // ctrl-d for vi compat.
-			if (dmode == EXTENDED_MODE) {
-				int lines_of_display = termlines - 6;
-
-				if ((edit_row[dmode] + lines_of_display) / lines_per_row[dmode] + 1 < end_row[dmode]) {
-					start_row[dmode] += lines_of_display / lines_per_row[dmode];
-					edit_row[dmode] += lines_of_display / lines_per_row[dmode];
-				}
-				else
-					edit_row[dmode] = end_row[dmode] - 1;
-			}
-			else {
-				start_row[dmode] = edit_row[dmode] = 0;
-				if (dmode == GFS2_MODE ||
-					offset + screen_chunk_size >= bufsize) {
-					block++;
-					offset = 0;
-				}
-				else
-					offset += screen_chunk_size;
-			}
+			pagedn();
 			break;
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		/* enter key - change a value */
-		/* -------------------------------------------------------------- */
+		/* --------------------------------------------------------- */
 		case(KEY_ENTER):
 		case('\n'):
 		case('\r'):
-			if (edit_row[dmode] == -1)
-				block = goto_block();
-			else {
-				if (dmode == HEX_MODE) {
-					left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17;
-					/* 8 and 16 char addresses on screen */
-					       
-					if (bobgets(edit_string, edit_row[dmode] + 3,
-								(edit_col[dmode] * 2) + 
-								(edit_col[dmode] / 4) + left_off, 2)) {
-						if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
-							int hexoffset;
-							unsigned char ch;
-							
-							hexoffset = (edit_row[dmode] * 16) +
-								edit_col[dmode];
-							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 (dmode == GFS2_MODE)
-					bobgets(edit_string, edit_row[dmode] + 4, 24,
-							edit_size[dmode]);
-				else
-					bobgets(edit_string, edit_row[dmode] + 6, 14,
-							edit_size[dmode]);
-			}
+			editing = !editing;
 			break;
 		default:
 			move(termlines - 1, 0);
@@ -1612,8 +1812,6 @@
 		}
 		else { /* second pass */
 			if (!termlines && !strchr(argv[i],'/')) { /* if print, no slash */
-				uint64_t temp_blk;
-
 				if (!strcasecmp(argv[i], "-x"))
 					dmode = HEX_MODE;
 				else if (argv[i][0] == '-') /* if it starts with a dash */
--- cluster/gfs2/edit/hexedit.h	2007/02/13 01:07:35	1.8
+++ cluster/gfs2/edit/hexedit.h	2007/02/28 21:58:46	1.9
@@ -64,7 +64,7 @@
 EXTERN int edit_mode INIT(0);
 EXTERN int line;
 EXTERN char edit_fmt[80];
-EXTERN char edit_string[1024];
+EXTERN char estring[1024]; /* edit string */
 EXTERN uint64_t dev_offset INIT(0);
 EXTERN uint64_t max_block INIT(0);
 EXTERN char *buf INIT(NULL);
@@ -79,7 +79,7 @@
 EXTERN int edit_row[DMODES], edit_col[DMODES], print_entry_ndx;
 EXTERN int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES];
 EXTERN int edit_size[DMODES], last_entry_onscreen[DMODES];
-EXTERN char edit_string[1024], edit_fmt[80];
+EXTERN char edit_fmt[80];
 EXTERN struct gfs2_sbd sbd;
 EXTERN struct gfs_sb *sbd1;
 EXTERN struct gfs2_inum gfs1_quota_di;   /* kludge because gfs2 sb too small */
@@ -93,6 +93,8 @@
 EXTERN int color_scheme INIT(0);
 EXTERN WINDOW *wind;
 EXTERN int gfs1 INIT(0);
+EXTERN int editing INIT(0);
+EXTERN uint64_t temp_blk;
 
 struct gfs2_dirents {
 	uint64_t block;
@@ -157,6 +159,14 @@
 	char sb_reserved[96];
 };
 
+struct gfs_jindex {
+        uint64_t ji_addr;       /* starting block of the journal */
+        uint32_t ji_nsegment;   /* number (quantity) of segments in journal */
+        uint32_t ji_pad;
+
+        char ji_reserved[64];
+};
+
 EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
 EXTERN struct indirect_info indirect[512]; /* more than the most indirect
 											  pointers possible for any given
@@ -230,12 +240,54 @@
 #define COLOR_OFFSETS   6
 #define COLOR_CONTENTS  7
 
-#define COLORS_TITLE     do { attrset(COLOR_PAIR(COLOR_TITLE));attron(A_BOLD); } while (0)
-#define COLORS_NORMAL    do { attrset(COLOR_PAIR(COLOR_NORMAL));attron(A_BOLD); } while (0)
-#define COLORS_INVERSE   do { attrset(COLOR_PAIR(COLOR_INVERSE));attron(A_BOLD); } while (0)
-#define COLORS_SPECIAL   do { attrset(COLOR_PAIR(COLOR_SPECIAL));attron(A_BOLD); } while (0)
-#define COLORS_HIGHLIGHT do { attrset(COLOR_PAIR(COLOR_HIGHLIGHT));attron(A_BOLD); } while (0)
-#define COLORS_OFFSETS   do { attrset(COLOR_PAIR(COLOR_OFFSETS));attron(A_BOLD); } while (0)
-#define COLORS_CONTENTS  do { attrset(COLOR_PAIR(COLOR_CONTENTS));attron(A_BOLD); } while (0)
+#define COLORS_TITLE     \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_TITLE)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_NORMAL    \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_NORMAL)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_INVERSE   \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_INVERSE)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_SPECIAL   \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_SPECIAL)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_HIGHLIGHT \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_HIGHLIGHT)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_OFFSETS   \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_OFFSETS)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
+#define COLORS_CONTENTS  \
+	do { \
+		if (termlines) { \
+			attrset(COLOR_PAIR(COLOR_CONTENTS)); \
+			attron(A_BOLD); \
+		} \
+	} while (0)
 
 #endif /* __HEXVIEW_DOT_H__ */



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2007-02-13  1:07 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2007-02-13  1:07 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2007-02-13 01:07:35

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Misc improvements.  Better scrolling.  You can now scroll through
	the rindex.  The superblock now has a pseudo-extended display.
	Fixed the file offset calculations for indirect pointers.
	It still has some bugs but it's better than it was.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.8&r2=1.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.9&r2=1.10
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.7&r2=1.8

--- cluster/gfs2/edit/gfs2hex.c	2007/02/08 05:41:16	1.8
+++ cluster/gfs2/edit/gfs2hex.c	2007/02/13 01:07:35	1.9
@@ -44,7 +44,7 @@
 extern char edit_string[1024];
 extern int edit_mode INIT(0);
 extern int edit_row[DMODES], edit_col[DMODES];
-extern int edit_size[DMODES], edit_last[DMODES];
+extern int edit_size[DMODES], last_entry_onscreen[DMODES];
 extern char edit_string[1024], edit_fmt[80];
 extern enum dsp_mode dmode INIT(HEX_MODE); /* display mode */
 
@@ -76,6 +76,33 @@
 	va_end(args);
 }
 
+void check_highlight(int highlight)
+{
+	if (!termlines || line >= termlines) /* If printing or out of bounds */
+		return;
+	if (dmode == HEX_MODE) {
+		if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
+			if (highlight) {
+				COLORS_HIGHLIGHT;
+				last_entry_onscreen[dmode] = print_entry_ndx;
+			}
+			else
+				COLORS_NORMAL;
+		}
+	}
+	else {
+		if ((line * lines_per_row[dmode]) - 4 == 
+			(edit_row[dmode] - start_row[dmode]) * lines_per_row[dmode]) {
+			if (highlight) {
+				COLORS_HIGHLIGHT;
+				last_entry_onscreen[dmode] = print_entry_ndx;
+			}
+			else
+				COLORS_NORMAL;
+		}
+	}
+}
+
 void print_it(const char *label, const char *fmt, const char *fmt2, ...)
 {
 	va_list args;
@@ -85,13 +112,10 @@
 
 	if (!termlines || line < termlines) {
 		va_start(args, fmt2);
+		check_highlight(TRUE);
 		if (termlines) {
-			if (line == edit_row[dmode] + 4)
-				COLORS_HIGHLIGHT;
 			move(line,0);
 			printw("%s", label);
-			if (line == edit_row[dmode] + 4)
-				COLORS_NORMAL;
 			move(line,24);
 		}
 		else {
@@ -102,28 +126,21 @@
 		}
 		vsprintf(tmp_string, fmt, args);
 
-		if (termlines) {
-			if (line == edit_row[dmode] + 4)
-				COLORS_HIGHLIGHT;
+		if (termlines)
 			printw(tmp_string);
-			if (line == edit_row[dmode] + 4)
-				COLORS_NORMAL;
-		}
 		else
 			printf(tmp_string);
+		check_highlight(FALSE);
 
 		if (fmt2) {
 			decimalsize = strlen(tmp_string);
 			va_end(args);
 			va_start(args, fmt2);
 			vsprintf(tmp_string, fmt2, args);
+			check_highlight(TRUE);
 			if (termlines) {
 				move(line, 50);
-				if (line == edit_row[dmode] + 4)
-					COLORS_HIGHLIGHT;
 				printw("%s", tmp_string);
-				if (line == edit_row[dmode] + 4)
-					COLORS_NORMAL;
 			}
 			else {
 				int i;
@@ -131,6 +148,7 @@
 					printf(" ");
 				printf("%s", tmp_string);
 			}
+			check_highlight(FALSE);
 		}
 		else {
 			if (strstr(fmt,"X") || strstr(fmt,"x"))
@@ -148,14 +166,13 @@
 		}
 		if (termlines) {
 			refresh();
-			if (line == edit_row[dmode] + 4) {
+			if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
 				strcpy(edit_string, tmp_string);
 				strcpy(edit_fmt, fmt);
 				edit_size[dmode] = strlen(edit_string);
 				COLORS_NORMAL;
 			}
-			if (line - 3 > edit_last[dmode])
-				edit_last[dmode] = line - 4;
+			last_entry_onscreen[dmode] = (line / lines_per_row[dmode]) - 4;
 		}
 		eol(0);
 		va_end(args);
@@ -327,7 +344,7 @@
 	unsigned int x;
 
 	eol(0);
-	printf("Directory Entries:");
+	print_gfs2("Directory Entries:");
 	eol(0);
 
 	for (x = sizeof(struct gfs2_leaf); x < bufsize; x += de.de_rec_len) {
@@ -361,7 +378,7 @@
 	unsigned int x;
 
 	eol(0);
-	printf("Eattr Entries:");
+	print_gfs2("Eattr Entries:");
 	eol(0);
 
 	for (x = sizeof(struct gfs2_meta_header); x < bufsize; x += ea.ea_rec_len)
@@ -375,8 +392,10 @@
 void gfs2_inum_print2(const char *title,struct gfs2_inum *no)
 {
 	if (termlines) {
+		check_highlight(TRUE);
 		move(line,2);
 		printw(title);
+		check_highlight(FALSE);
 	}
 	else
 		printf("  %s:",title);
--- cluster/gfs2/edit/hexedit.c	2007/02/08 05:41:16	1.9
+++ cluster/gfs2/edit/hexedit.c	2007/02/13 01:07:35	1.10
@@ -42,7 +42,7 @@
 
 #include <syslog.h>
 
-int display(enum dsp_mode dmode, int identify_only);
+int display(int identify_only);
 extern void eol(int col);
 extern void do_indirect_extended(char *buf);
 
@@ -70,7 +70,7 @@
 	else
 		perror("Error: tgetent failed.");
 	termlines--; /* last line is number of lines -1 */
-	display(dmode, FALSE);
+	display(FALSE);
 	signal(SIGWINCH, UpdateSize);
 }
 
@@ -465,6 +465,7 @@
 	pointer = (unsigned char *)lpBuffer + offset;
 	ptr2 = (unsigned char *)lpBuffer + offset;
 	l = offset;
+	print_entry_ndx = 0;
 	while (((termlines &&
 			line < termlines &&
 			line <= ((screen_chunk_size / 16) + 2)) ||
@@ -524,10 +525,11 @@
 			ptr2++;
 		}
 		print_gfs2("] ");
-		if (line - 3 > edit_last[dmode])
-			edit_last[dmode] = line - 3;
+		if (line - 3 > last_entry_onscreen[dmode])
+			last_entry_onscreen[dmode] = line - 3;
 		eol(0);
 		l+=16;
+		print_entry_ndx++;
 	} /* while */
 	if (gfs1) {
 		COLORS_NORMAL;
@@ -556,24 +558,40 @@
 /* ------------------------------------------------------------------------ */
 int print_rindex(struct gfs2_inode *di)
 {
-	int rgs, error;
+	int error, start_line;
 	struct gfs2_rindex ri;
 	char buf[sizeof(struct gfs2_rindex)];
 
+	start_line = line;
 	error = 0;
 	print_gfs2("RG index entries found: %d.",
 			   di->i_di.di_size / sizeof(struct gfs2_rindex));
 	eol(0);
-	for (rgs=0; ; rgs++) {
-		error = gfs2_readi(di, (void *)&buf, rgs * sizeof(struct gfs2_rindex),
+	lines_per_row[dmode] = 6;
+	for (print_entry_ndx=0; ; print_entry_ndx++) {
+		error = gfs2_readi(di, (void *)&buf,
+						   print_entry_ndx * sizeof(struct gfs2_rindex),
 						   sizeof(struct gfs2_rindex));
 		gfs2_rindex_in(&ri, buf);
 		if (!error) /* end of file */
 			break;
-		print_gfs2("RG #%d", rgs + 1);
-		eol(0);
-		gfs2_rindex_print(&ri);
+		if (!termlines ||
+			(print_entry_ndx >= start_row[dmode] &&
+			 ((print_entry_ndx - start_row[dmode])+1) * lines_per_row[dmode] <=
+			 termlines - start_line - 2)) {
+			if (edit_row[dmode] == print_entry_ndx) {
+				COLORS_HIGHLIGHT;
+				sprintf(edit_string, "%" PRIx64, ri.ri_addr);
+			}
+			print_gfs2("RG #%d", print_entry_ndx);
+			eol(0);
+			if (edit_row[dmode] == print_entry_ndx)
+				COLORS_NORMAL;
+			gfs2_rindex_print(&ri);
+			last_entry_onscreen[dmode] = print_entry_ndx;
+		}
 	}
+	end_row[dmode] = print_entry_ndx;
 	return error;
 }
 
@@ -644,213 +662,251 @@
 }
 
 /* ------------------------------------------------------------------------ */
-/* display_extended                                                         */
+/* has_indirect_blocks                                                      */
 /* ------------------------------------------------------------------------ */
-int display_extended(void)
+int has_indirect_blocks(void)
 {
-	int e, start_line, total_dirents, indir_blocks;
-	struct gfs2_inode *tmp_inode;
+	if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB ||
+		(gfs2_struct_type == GFS2_METATYPE_DI &&
+		 (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR))))
+		return TRUE;
+	return FALSE;
+}
 
-	edit_last[dmode] = 0;
+/* ------------------------------------------------------------------------ */
+/* print_inode_type                                                         */
+/* ------------------------------------------------------------------------ */
+void print_inode_type(__be16 de_type)
+{
+	switch(de_type) {
+	case DT_UNKNOWN:
+		print_gfs2("Unknown");
+		break;
+	case DT_REG:
+		print_gfs2("File   ");
+		break;
+	case DT_DIR:
+		print_gfs2("Dir    ");
+		break;
+	case DT_LNK:
+		print_gfs2("Symlink");
+		break;
+	case DT_BLK:
+		print_gfs2("BlkDev ");
+		break;
+	case DT_CHR:
+		print_gfs2("ChrDev ");
+		break;
+	case DT_FIFO:
+		print_gfs2("Fifo   ");
+		break;
+	case DT_SOCK:
+		print_gfs2("Socket ");
+		break;
+	default:
+		print_gfs2("%04x   ", de_type);
+		break;
+	}
+}
+
+/* ------------------------------------------------------------------------ */
+/* display_indirect                                                         */
+/* ------------------------------------------------------------------------ */
+int display_indirect(void)
+{
+	int start_line, total_dirents, indir_blocks;
+	int i, cur_height = -1;
+	uint64_t factor[5];
+	int offsets[5];
+
+	last_entry_onscreen[dmode] = 0;
 	eol(0);
 	start_line = line;
-	if (indirect_blocks ||
-		(gfs2_struct_type == GFS2_METATYPE_DI &&
-		 (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR)))) {
-		int i, cur_height = -1;
-		uint64_t factor[5];
-		int offsets[5];
+	if (!has_indirect_blocks())
+		return -01;
 
-		indir_blocks = indirect_blocks;
-		if (!indirect_blocks) {
+	indir_blocks = indirect_blocks;
+	if (!indirect_blocks) {
+		if (gfs2_struct_type == GFS2_METATYPE_SB)
+			print_gfs2("The superblock has 2 directories");
+		else
 			print_gfs2("This directory contains %d directory entries.",
 					   indirect[0].dirents);
-			indir_blocks = 1; /* not really an indirect block, but treat it as one */
-		}
-		else {
-			if (gfs2_struct_type == GFS2_METATYPE_DI) {
-				if (S_ISDIR(di.di_mode))
-					print_gfs2("This directory contains %d indirect blocks",
-							   indirect_blocks);
-				else
-					print_gfs2("This inode contains %d indirect blocks",
-							   indirect_blocks);
-			}
+		indir_blocks = 1; /* not really an indirect block, but treat it as one */
+	}
+	else {
+		if (gfs2_struct_type == GFS2_METATYPE_DI) {
+			if (S_ISDIR(di.di_mode))
+				print_gfs2("This directory contains %d indirect blocks",
+						   indirect_blocks);
 			else
-				print_gfs2("This indirect block contains %d indirect blocks",
+				print_gfs2("This inode contains %d indirect blocks",
 						   indirect_blocks);
 		}
-		total_dirents = 0;
-		/* Figure out multiplication factors for indirect pointers. */
-		if ((indir_blocks == indirect_blocks) && !S_ISDIR(di.di_mode)) {
-			memset(&offsets, 0, sizeof(offsets));
-			/* See if we are on an inode or have one in history. */
+		else
+			print_gfs2("This indirect block contains %d indirect blocks",
+					   indirect_blocks);
+	}
+	total_dirents = 0;
+	/* Figure out multiplication factors for indirect pointers. */
+	if ((indir_blocks == indirect_blocks) && !S_ISDIR(di.di_mode)) {
+		memset(&offsets, 0, sizeof(offsets));
+		/* See if we are on an inode or have one in history. */
+		cur_height = 0;
+		if (gfs2_struct_type != GFS2_METATYPE_DI) {
 			cur_height = 0;
-			if (gfs2_struct_type != GFS2_METATYPE_DI) {
-				cur_height = 0;
-				for (i = 0; i <= blockhist && i < 5; i++) {
-					offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode];
-					if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI)
-						break;
-					cur_height++;
-				}
-			}
-			if (cur_height >= 0) {
-				/* Multiply out the max factor based on inode height.*/
-				/* This is how much data is represented by each      */
-				/* indirect pointer at each height.                  */
-				factor[0] = 1ull;
-				for (i = 0; i < di.di_height; i++)
-					factor[i + 1] = factor[i] * 509;
-			}
-			print_gfs2("  (at height=%d)", cur_height);
-		}
-		if (indirect_blocks) {
-			eol(0);
-			print_gfs2("Indirect blocks for this inode:");
+			for (i = 0; i <= blockhist && i < 5; i++) {
+				offsets[i] = blockstack[(blockhist - i) % BLOCK_STACK_SIZE].edit_row[dmode];
+				if (blockstack[(blockhist - i) % BLOCK_STACK_SIZE].gfs2_struct_type == GFS2_METATYPE_DI)
+					break;
+				cur_height++;
+			}
+		}
+		if (cur_height >= 0) {
+			/* Multiply out the max factor based on inode height.*/
+			/* This is how much data is represented by each      */
+			/* indirect pointer at each height.                  */
+			factor[0] = 1ull;
+			for (i = 0; i < di.di_height; i++)
+				factor[i + 1] = factor[i] * (gfs1 ? 501 : 509);
 		}
+		print_gfs2("  (at height=%d)", cur_height);
+	}
+	if (indirect_blocks) {
 		eol(0);
-		for (e = start_row[dmode];
-			 (!termlines ||
-			  e < termlines - start_line - 2 + start_row[dmode]) &&
-				 e < indir_blocks; e++) {
+		print_gfs2("Indirect blocks:");
+	}
+	eol(0);
+	for (print_entry_ndx = start_row[dmode];
+		 (!termlines || print_entry_ndx < termlines - start_line - 2
+		  + start_row[dmode]) && print_entry_ndx < indir_blocks;
+		 print_entry_ndx++) {
+		if (termlines) {
+			if (edit_row[dmode] >= 0 &&
+				line - start_line - 2 == edit_row[dmode] -
+				start_row[dmode])
+				COLORS_HIGHLIGHT;
+			move(line, 1);
+		}
+		if (indir_blocks == indirect_blocks) {
+			print_gfs2("%d => ", print_entry_ndx);
+			if (termlines)
+				move(line,9);
+			print_gfs2("0x%llx / %lld", indirect[print_entry_ndx].block,
+					   indirect[print_entry_ndx].block);
 			if (termlines) {
 				if (edit_row[dmode] >= 0 &&
 					line - start_line - 2 == edit_row[dmode] -
-					start_row[dmode])
-					COLORS_HIGHLIGHT;
-				move(line, 1);
-			}
-			if (indir_blocks == indirect_blocks) {
-				print_gfs2("%d => ", e);
-				if (termlines)
-					move(line,9);
-				print_gfs2("0x%llx / %lld", indirect[e].block,
-						   indirect[e].block);
+					start_row[dmode]) { 
+					sprintf(edit_string, "%"PRIx64,
+							indirect[print_entry_ndx].block);
+					strcpy(edit_fmt, "%"PRIx64);
+					edit_size[dmode] = strlen(edit_string);
+					COLORS_NORMAL;
+				}
+			}
+			if (!S_ISDIR(di.di_mode)) {
+				int hgt;
+				uint64_t file_offset = 0ull;
+				float human_off;
+				char h;
+				
+				/* Now divide by how deep we are at the moment.      */
+				/* This is how much data is represented by each      */
+				/* indirect pointer for each height we've traversed. */
+				offsets[0] = print_entry_ndx;
+				for (hgt = cur_height; hgt >= 0; hgt--)
+					file_offset += offsets[cur_height - hgt] *
+						factor[di.di_height - hgt - 1] * bufsize;
+				print_gfs2("     ");
+				h = 'K';
+				human_off = (file_offset / 1024.0);
+				if (human_off > 1024.0) { h = 'M'; human_off /= 1024.0; }
+				if (human_off > 1024.0) { h = 'G'; human_off /= 1024.0; }
+				if (human_off > 1024.0) { h = 'T'; human_off /= 1024.0; }
+				if (human_off > 1024.0) { h = 'P'; human_off /= 1024.0; }
+				if (human_off > 1024.0) { h = 'E'; human_off /= 1024.0; }
+				print_gfs2("(data offset 0x%llx / %lld / %6.2f%c)",
+						   file_offset, file_offset, human_off, h);
+				print_gfs2("   ");
+			}
+		}
+		if (indirect[print_entry_ndx].is_dir) {
+			int d;
+			
+			if (indirect[print_entry_ndx].dirents > 1 &&
+				indir_blocks == indirect_blocks)
+				print_gfs2("(directory leaf with %d entries)",
+						   indirect[print_entry_ndx].dirents);
+			for (d = 0; d < indirect[print_entry_ndx].dirents; d++) {
+				total_dirents++;
+				if (indirect[print_entry_ndx].dirents > 1) {
+					eol(5);
+					if (termlines) {
+						if (edit_row[dmode] >=0 &&
+							line - start_line - 2 == 
+							edit_row[dmode] -
+							start_row[dmode]) {
+							COLORS_HIGHLIGHT;
+							sprintf(edit_string, "%"PRIx64,
+									indirect[print_entry_ndx].dirent[d].block);
+							strcpy(edit_fmt, "%"PRIx64);
+						}
+					}
+					print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ",
+							   total_dirents, d + 1,
+							   indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino,
+							   indirect[print_entry_ndx].dirent[d].dirent.de_inum.no_formal_ino,
+							   indirect[print_entry_ndx].dirent[d].block,
+							   indirect[print_entry_ndx].dirent[d].block);
+				}
+				print_inode_type(indirect[print_entry_ndx].dirent[d].dirent.de_type);
+				print_gfs2(" %s", indirect[print_entry_ndx].dirent[d].filename);
 				if (termlines) {
 					if (edit_row[dmode] >= 0 &&
 						line - start_line - 2 == edit_row[dmode] -
-						start_row[dmode]) { 
-						sprintf(edit_string, "%"PRIx64, indirect[e].block);
-						strcpy(edit_fmt, "%"PRIx64);
-						edit_size[dmode] = strlen(edit_string);
+						start_row[dmode])
 						COLORS_NORMAL;
-					}
-				}
-				if (!S_ISDIR(di.di_mode)) {
-					int hgt;
-					uint64_t file_offset = 0ull;
-
-					/* Now divide by how deep we are at the moment.      */
-					/* This is how much data is represented by each      */
-					/* indirect pointer for each height we've traversed. */
-					offsets[0] = e;
-					for (hgt = cur_height; hgt >= 0; hgt--)
-						file_offset += offsets[cur_height - hgt] *
-							factor[di.di_height - hgt - 1] *
-							(bufsize - sizeof(struct gfs2_meta_header));
-					print_gfs2("     ");
-					print_gfs2("(data offset 0x%llx / %lld)", file_offset,
-							   file_offset);
-					print_gfs2("   ");
-				}
-			}
-			if (indirect[e].is_dir) {
-				int d;
-
-				if (indirect[e].dirents > 1 && indir_blocks == indirect_blocks)
-					print_gfs2("(directory leaf with %d entries)",
-							   indirect[e].dirents);
-				for (d = 0; d < indirect[e].dirents; d++) {
-					total_dirents++;
-					if (indirect[e].dirents > 1) {
-						eol(5);
-						if (termlines) {
-							if (edit_row[dmode] >=0 &&
-								line - start_line - 2 == 
-								edit_row[dmode] -
-								start_row[dmode]) {
-								COLORS_HIGHLIGHT;
-								sprintf(edit_string, "%"PRIx64,
-										indirect[e].dirent[d].block);
-								strcpy(edit_fmt, "%"PRIx64);
-							}
-						}
-						print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ",
-								   total_dirents, d + 1,
-								   indirect[e].dirent[d].dirent.de_inum.no_formal_ino,
-								   indirect[e].dirent[d].dirent.de_inum.no_formal_ino,
-								   indirect[e].dirent[d].block,
-								   indirect[e].dirent[d].block);
-					}
-					switch(indirect[e].dirent[d].dirent.de_type) {
-					case DT_UNKNOWN:
-						print_gfs2("Unknown");
-						break;
-					case DT_REG:
-						print_gfs2("File   ");
-						break;
-					case DT_DIR:
-						print_gfs2("Dir    ");
-						break;
-					case DT_LNK:
-						print_gfs2("Symlink");
-						break;
-					case DT_BLK:
-						print_gfs2("BlkDev ");
-						break;
-					case DT_CHR:
-						print_gfs2("ChrDev ");
-						break;
-					case DT_FIFO:
-						print_gfs2("Fifo   ");
-						break;
-					case DT_SOCK:
-						print_gfs2("Socket ");
-						break;
-					default:
-						print_gfs2("%04x   ",
-								   indirect[e].dirent[d].dirent.de_type);
-						break;
-					}
-
-					print_gfs2(" %s", indirect[e].dirent[d].filename);
-					if (termlines) {
-						if (edit_row[dmode] >= 0 &&
-							line - start_line - 2 == edit_row[dmode] -
-							start_row[dmode])
-							COLORS_NORMAL;
-					}
 				}
-			} /* if isdir */
-			eol(0);
-		} /* for termlines */
-		if (line >= 7) /* 7 because it was bumped at the end */
-			edit_last[dmode] = line - 7;
-	} /* if (indirect_blocks) */
-	else
-		print_gfs2("This block does not have indirect blocks.");
+			}
+		} /* if isdir */
+		eol(0);
+	} /* for each display row */
+	if (line >= 7) /* 7 because it was bumped at the end */
+		last_entry_onscreen[dmode] = line - 7;
 	eol(0);
+	end_row[dmode] = (indirect_blocks ? indirect_blocks:indirect[0].dirents);
+	if (end_row[dmode] < last_entry_onscreen[dmode])
+		end_row[dmode] = last_entry_onscreen[dmode];
+	lines_per_row[dmode] = 1;
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* display_extended                                                         */
+/* ------------------------------------------------------------------------ */
+int display_extended(void)
+{
+	struct gfs2_inode *tmp_inode;
+	struct gfs2_buffer_head *tmp_bh;
+
+	/* Display any indirect pointers that we have. */
+	if (display_indirect() < 0)
+		return -1;
 	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
 		(block == masterblock("rindex"))) {
-		struct gfs2_buffer_head *tmp_bh;
-
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_rindex(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
 	else if (!gfs1 && block == masterblock("inum")) {
-		struct gfs2_buffer_head *tmp_bh;
-
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_inum(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
 	else if (!gfs1 && block == masterblock("statfs")) {
-		struct gfs2_buffer_head *tmp_bh;
-
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_statfs(tmp_inode);
@@ -858,8 +914,6 @@
 	}
 	else if ((gfs1 && block == gfs1_quota_di.no_addr) ||
 			 (block == masterblock("quota"))) {
-		struct gfs2_buffer_head *tmp_bh;
-
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_quota(tmp_inode);
@@ -925,7 +979,7 @@
 /* ------------------------------------------------------------------------ */
 /* display                                                                  */
 /* ------------------------------------------------------------------------ */
-int display(enum dsp_mode dmode, int identify_only)
+int display(int identify_only)
 {
 	if (termlines) {
 		display_title_lines();
@@ -943,8 +997,30 @@
 	if (identify_only)
 		return 0;
 	indirect_blocks = 0;
-	if (gfs2_struct_type == GFS2_METATYPE_SB || block == 0x10)
+	lines_per_row[dmode] = 1;
+	if (gfs2_struct_type == GFS2_METATYPE_SB || block == 0x10) {
 		gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */
+		memset(&indirect, 0, sizeof(indirect));
+		indirect[0].block = sbd.sd_sb.sb_master_dir.no_addr;
+		indirect[0].is_dir = TRUE;
+		indirect[0].dirents = 2;
+
+		memcpy(&indirect[0].dirent[0].filename, "root", 4);
+		indirect[0].dirent[0].dirent.de_inum.no_formal_ino =
+			sbd.sd_sb.sb_root_dir.no_formal_ino;
+		indirect[0].dirent[0].dirent.de_inum.no_addr =
+			sbd.sd_sb.sb_root_dir.no_addr;
+		indirect[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr;
+		indirect[0].dirent[0].dirent.de_type = DT_DIR;
+
+		memcpy(&indirect[0].dirent[1].filename, "master", 7);
+		indirect[0].dirent[1].dirent.de_inum.no_formal_ino = 
+			sbd.sd_sb.sb_master_dir.no_formal_ino;
+		indirect[0].dirent[1].dirent.de_inum.no_addr =
+			sbd.sd_sb.sb_master_dir.no_addr;
+		indirect[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr;
+		indirect[0].dirent[1].dirent.de_type = DT_DIR;
+	}
 	else if (gfs2_struct_type == GFS2_METATYPE_DI) {
 		gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
 		do_dinode_extended(&di, buf); /* get extended data, if any */
@@ -973,14 +1049,22 @@
 			}
 		}
 	}
-	edit_last[dmode] = 0;
+	last_entry_onscreen[dmode] = 0;
+	if (dmode == EXTENDED_MODE && !has_indirect_blocks())
+		dmode = HEX_MODE;
+	if (termlines) {
+		move(termlines, 63);
+		printw("Mode: %s", (dmode==HEX_MODE?"Hex edit ":(dmode==GFS2_MODE?"Structure":"Pointers ")));
+		move(line, 0);
+	}
 	if (dmode == HEX_MODE)          /* if hex display mode           */
 		hexdump(dev_offset, buf, (gfs2_struct_type == GFS2_METATYPE_DI)?
 				struct_len + di.di_size:bufsize); /* show block in hex */
 	else if (dmode == GFS2_MODE)    /* if structure display          */
 		display_gfs2();                    /* display the gfs2 structure    */
-	else                                   /* otherwise                     */
+	else
 		display_extended();                /* display extended blocks       */
+	/* No else here, because display_extended can switch back to hex mode */
 	if (termlines)
 		refresh();
 	return(0);
@@ -998,8 +1082,10 @@
 		blockstack[bhst].dmode = dmode;
 		for (i = 0; i < DMODES; i++) {
 			blockstack[bhst].start_row[i] = start_row[i];
+			blockstack[bhst].end_row[i] = end_row[i];
 			blockstack[bhst].edit_row[i] = edit_row[i];
 			blockstack[bhst].edit_col[i] = edit_col[i];
+			blockstack[bhst].lines_per_row[i] = lines_per_row[i];
 		}
 		blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
 		blockhist++;
@@ -1021,8 +1107,10 @@
 	dmode = blockstack[bhst].dmode;
 	for (i = 0; i < DMODES; i++) {
 		start_row[i] = blockstack[bhst].start_row[i];
+		end_row[i] = blockstack[bhst].end_row[i];
 		edit_row[i] = blockstack[bhst].edit_row[i];
 		edit_col[i] = blockstack[bhst].edit_col[i];
+		lines_per_row[i] = blockstack[bhst].lines_per_row[i];
 	}
 	gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
 	return blockstack[bhst].block;
@@ -1093,7 +1181,7 @@
 		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
 		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
 		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */
+		init_pair(COLOR_HIGHLIGHT, COLOR_MAGENTA, COLOR_WHITE); /* highlighted */
 		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
 		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
 	}
@@ -1127,7 +1215,7 @@
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
 	while (!Quit) {
-		display(dmode, FALSE);
+		display(FALSE);
 		while ((ch=getch()) == 0); // wait for input
 		switch (ch)
 		{
@@ -1144,7 +1232,7 @@
 		/* -------------------------------------------------------------- */
 		case KEY_HOME:
 			if (dmode == EXTENDED_MODE) {
-				start_row[dmode] = 0;
+				start_row[dmode] = end_row[dmode] = 0;
 				edit_row[dmode] = 0;
 			}
 			else {
@@ -1189,16 +1277,14 @@
 		/* -------------------------------------------------------------- */
 		case KEY_DOWN:
 			if (dmode == EXTENDED_MODE) {
-				if (edit_row[dmode] + 1 <
-					(indirect_blocks ? indirect_blocks:indirect[0].dirents)) {
-					if (edit_row[dmode] >= edit_last[dmode] +
-						start_row[dmode])
+				if (edit_row[dmode] + 1 < end_row[dmode]) {
+					if (edit_row[dmode] >= last_entry_onscreen[dmode])
 						start_row[dmode]++;
 					edit_row[dmode]++;
 				}
 			}
 			else {
-				if (edit_row[dmode] < edit_last[dmode])
+				if (edit_row[dmode] < last_entry_onscreen[dmode])
 					edit_row[dmode]++;
 			}
 			break;
@@ -1251,7 +1337,7 @@
 				block = temp_blk;
 				push_block(block);
 				for (i = 0; i < DMODES; i++) {
-					start_row[i] = edit_row[i] = 0;
+					start_row[i] = end_row[i] = edit_row[i] = 0;
 					edit_col[i] = 0;
 				}
 			}
@@ -1269,10 +1355,16 @@
 			print_usage();
 			break;
 		/* -------------------------------------------------------------- */
+		/* e - change to extended mode */
+		/* -------------------------------------------------------------- */
+		case 'e':
+			dmode = EXTENDED_MODE;
+			break;
+		/* -------------------------------------------------------------- */
 		/* b - Back one 4K block */
 		/* -------------------------------------------------------------- */
 		case 'b':
-			start_row[dmode] = edit_row[dmode] = 0;
+			start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
 			if (block > 0)
 				block--;
 			offset = 0;
@@ -1294,9 +1386,9 @@
 			if (dmode == EXTENDED_MODE) {
 				int lines_of_display = termlines - 6;
 
-				if (edit_row[dmode] - lines_of_display > 0) {
-					start_row[dmode] -= lines_of_display;
-					edit_row[dmode] -= lines_of_display;
+				if (edit_row[dmode] - (lines_of_display / lines_per_row[dmode]) > 0) {
+					start_row[dmode] -= (lines_of_display / lines_per_row[dmode]);
+					edit_row[dmode] -= (lines_of_display / lines_per_row[dmode]);
 				}
 				else {
 					start_row[dmode] = 0;
@@ -1323,9 +1415,20 @@
 		/* -------------------------------------------------------------- */
 		case 0x168:
 			if (dmode == EXTENDED_MODE) {
-				edit_row[dmode] =
-					(indirect_blocks? indirect_blocks - 1:indirect[0].dirents - 1);
-				start_row[dmode] = edit_row[dmode] - (termlines - 7);
+				int lines_of_display = termlines - 6;
+				int entries_per_screen = lines_of_display /
+					lines_per_row[dmode];
+
+				edit_row[dmode] = end_row[dmode] - 1;
+				if ((edit_row[dmode] - entries_per_screen) + 1 > 0)
+					start_row[dmode] = edit_row[dmode] - entries_per_screen + 1;
+				/*
+				  if (edit_row[dmode] * lines_per_row[dmode] > (termlines - 7))
+				  start_row[dmode] = (edit_row[dmode] - (termlines - 7)) /
+				  lines_per_row[dmode];
+				*/
+				else
+					start_row[dmode] = 0;
 			}
 			/* TODO: Make "end" key work for other display modes. */
 			break;
@@ -1333,7 +1436,8 @@
 		/* f - Forward one 4K block */
 		/* -------------------------------------------------------------- */
 		case 'f':
-			start_row[dmode] = edit_row[dmode] = 0;
+			start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
+			lines_per_row[dmode] = 1;
 			block++;
 			offset = 0;
 			break;
@@ -1346,15 +1450,12 @@
 			if (dmode == EXTENDED_MODE) {
 				int lines_of_display = termlines - 6;
 
-				if (edit_row[dmode] + lines_of_display + 1 <
-					(indirect_blocks ? indirect_blocks:indirect[0].dirents)) {
-					start_row[dmode] += lines_of_display;
-					edit_row[dmode] += lines_of_display;
-				}
-				else {
-					edit_row[dmode] =
-						(indirect_blocks ? indirect_blocks - 1:indirect[0].dirents - 1);
+				if ((edit_row[dmode] + lines_of_display) / lines_per_row[dmode] + 1 < end_row[dmode]) {
+					start_row[dmode] += lines_of_display / lines_per_row[dmode];
+					edit_row[dmode] += lines_of_display / lines_per_row[dmode];
 				}
+				else
+					edit_row[dmode] = end_row[dmode] - 1;
 			}
 			else {
 				start_row[dmode] = edit_row[dmode] = 0;
@@ -1594,10 +1695,12 @@
 	prog_name = argv[0];
 
 	memset(start_row, 0, sizeof(start_row));
+	memset(lines_per_row, 0, sizeof(lines_per_row));
+	memset(end_row, 0, sizeof(end_row));
 	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));
+	memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
 	dmode = HEX_MODE;
 	type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */
 	block = 0x10;
@@ -1606,8 +1709,10 @@
 		blockstack[i].block = block;
 		for (j = 0; j < DMODES; j++) {
 			blockstack[i].start_row[j] = 0;
+			blockstack[i].end_row[j] = 0;
 			blockstack[i].edit_row[j] = 0;
 			blockstack[i].edit_col[j] = 0;
+			blockstack[i].lines_per_row[j] = 0;
 		}
 	}
 
@@ -1632,7 +1737,7 @@
 	else { /* print all the structures requested */
 		for (i = 0; i <= blockhist; i++) {
 			block = blockstack[i + 1].block;
-			display(dmode, identify);
+			display(identify);
 			if (!identify) {
 				display_extended();
 				printf("-------------------------------------" \
--- cluster/gfs2/edit/hexedit.h	2007/02/08 05:41:16	1.7
+++ cluster/gfs2/edit/hexedit.h	2007/02/13 01:07:35	1.8
@@ -76,9 +76,9 @@
 EXTERN int line INIT(1);
 EXTERN int struct_len INIT(0);
 EXTERN unsigned int offset;
-EXTERN int edit_row[DMODES], edit_col[DMODES];
-EXTERN int start_row[DMODES];
-EXTERN int edit_size[DMODES], edit_last[DMODES];
+EXTERN int edit_row[DMODES], edit_col[DMODES], print_entry_ndx;
+EXTERN int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES];
+EXTERN int edit_size[DMODES], last_entry_onscreen[DMODES];
 EXTERN char edit_string[1024], edit_fmt[80];
 EXTERN struct gfs2_sbd sbd;
 EXTERN struct gfs_sb *sbd1;
@@ -116,6 +116,8 @@
 struct blkstack_info {
 	uint64_t block;
 	int start_row[DMODES];
+	int end_row[DMODES];
+	int lines_per_row[DMODES];
 	int edit_row[DMODES];
 	int edit_col[DMODES];
 	enum dsp_mode dmode;



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2006-11-14 20:13 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2006-11-14 20:13 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	rpeterso at sourceware.org	2006-11-14 20:13:36

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Ability for gfs2_edit to handle gfs1 indirect metapointers.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.1&r2=1.5.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.1&r2=1.6.2.2
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.1&r2=1.4.2.2

--- cluster/gfs2/edit/gfs2hex.c	2006/11/09 15:31:01	1.5.2.1
+++ cluster/gfs2/edit/gfs2hex.c	2006/11/14 20:13:36	1.5.2.2
@@ -291,23 +291,20 @@
 	unsigned int x, y;
 	uint64_t p;
 
-	eol(0);
-	printf("Pointers");
-	eol(0);
-	eol(0);
-
-	for (x = sizeof(struct gfs2_meta_header), y = 0; x < bufsize; x += 8, y++)
-	{
+	indirect_blocks = 0;
+	memset(&indirect, 0, sizeof(indirect));
+	for (x = sizeof(struct gfs_indirect), y = 0;
+		 x < bufsize;
+		 x += sizeof(uint64_t), y++) {
 		p = be64_to_cpu(*(uint64_t *)(buf + x));
-		
 		if (p) {
-			printf("  %u -> %" PRIu64, y, p);
-			eol(0);
+			indirect[indirect_blocks].block = p;
+			indirect[indirect_blocks].is_dir = FALSE;
+			indirect_blocks++;
 		}
 	}
 }
 
-
 /******************************************************************************
 *******************************************************************************
 **
--- cluster/gfs2/edit/hexedit.c	2006/11/09 15:31:01	1.6.2.1
+++ cluster/gfs2/edit/hexedit.c	2006/11/14 20:13:36	1.6.2.2
@@ -44,6 +44,7 @@
 
 int display(enum dsp_mode display_mode, int identify_only);
 extern void eol(int col);
+extern void do_indirect_extended(char *buf);
 
 /* ------------------------------------------------------------------------ */
 /* UpdateSize - screen size changed, so update it                           */
@@ -684,10 +685,11 @@
 				move(line, 1);
 			}
 			if (indir_blocks == indirect_blocks) {
-				print_gfs2("%d => ", e + 1);
+				print_gfs2("%d => ", e);
 				if (termlines)
 					move(line,9);
-				print_gfs2("0x%llx", indirect[e].block);
+				print_gfs2("0x%llx / %lld", indirect[e].block,
+						   indirect[e].block);
 				if (termlines) {
 					if (edit_row[display_mode] >= 0 &&
 						line - start_line - 2 == edit_row[display_mode]) { 
@@ -893,6 +895,9 @@
 		gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
 		do_dinode_extended(&di, buf); /* get extended data, if any */
 	}
+	else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
+		do_indirect_extended(buf);
+	}
 	else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
 		int x;
 		struct gfs2_dirent de;
--- cluster/gfs2/edit/hexedit.h	2006/11/09 15:31:01	1.4.2.1
+++ cluster/gfs2/edit/hexedit.h	2006/11/14 20:13:36	1.4.2.2
@@ -106,6 +106,12 @@
 	struct gfs2_dirents dirent[64];
 };
 
+struct gfs_indirect {
+	struct gfs2_meta_header in_header;
+
+	char in_reserved[64];
+};
+
 struct blkstack_info {
 	uint64_t block;
 	int edit_row[DISPLAY_MODES];



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2006-11-14 20:11 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2006-11-14 20:11 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2006-11-14 20:11:10

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Ability for gfs2_edit to handle gfs1 indirect metapointers.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.6&r2=1.7
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.5&r2=1.6

--- cluster/gfs2/edit/gfs2hex.c	2006/11/09 15:29:45	1.6
+++ cluster/gfs2/edit/gfs2hex.c	2006/11/14 20:11:10	1.7
@@ -291,23 +291,20 @@
 	unsigned int x, y;
 	uint64_t p;
 
-	eol(0);
-	printf("Pointers");
-	eol(0);
-	eol(0);
-
-	for (x = sizeof(struct gfs2_meta_header), y = 0; x < bufsize; x += 8, y++)
-	{
+	indirect_blocks = 0;
+	memset(&indirect, 0, sizeof(indirect));
+	for (x = sizeof(struct gfs_indirect), y = 0;
+		 x < bufsize;
+		 x += sizeof(uint64_t), y++) {
 		p = be64_to_cpu(*(uint64_t *)(buf + x));
-		
 		if (p) {
-			printf("  %u -> %" PRIu64, y, p);
-			eol(0);
+			indirect[indirect_blocks].block = p;
+			indirect[indirect_blocks].is_dir = FALSE;
+			indirect_blocks++;
 		}
 	}
 }
 
-
 /******************************************************************************
 *******************************************************************************
 **
--- cluster/gfs2/edit/hexedit.c	2006/11/09 15:29:45	1.7
+++ cluster/gfs2/edit/hexedit.c	2006/11/14 20:11:10	1.8
@@ -44,6 +44,7 @@
 
 int display(enum dsp_mode display_mode, int identify_only);
 extern void eol(int col);
+extern void do_indirect_extended(char *buf);
 
 /* ------------------------------------------------------------------------ */
 /* UpdateSize - screen size changed, so update it                           */
@@ -684,10 +685,11 @@
 				move(line, 1);
 			}
 			if (indir_blocks == indirect_blocks) {
-				print_gfs2("%d => ", e + 1);
+				print_gfs2("%d => ", e);
 				if (termlines)
 					move(line,9);
-				print_gfs2("0x%llx", indirect[e].block);
+				print_gfs2("0x%llx / %lld", indirect[e].block,
+						   indirect[e].block);
 				if (termlines) {
 					if (edit_row[display_mode] >= 0 &&
 						line - start_line - 2 == edit_row[display_mode]) { 
@@ -893,6 +895,9 @@
 		gfs2_dinode_in(&di, buf); /* parse disk inode into structure */
 		do_dinode_extended(&di, buf); /* get extended data, if any */
 	}
+	else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
+		do_indirect_extended(buf);
+	}
 	else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
 		int x;
 		struct gfs2_dirent de;
--- cluster/gfs2/edit/hexedit.h	2006/11/09 15:29:45	1.5
+++ cluster/gfs2/edit/hexedit.h	2006/11/14 20:11:10	1.6
@@ -106,6 +106,12 @@
 	struct gfs2_dirents dirent[64];
 };
 
+struct gfs_indirect {
+	struct gfs2_meta_header in_header;
+
+	char in_reserved[64];
+};
+
 struct blkstack_info {
 	uint64_t block;
 	int edit_row[DISPLAY_MODES];



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2006-11-09 15:31 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2006-11-09 15:31 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	rpeterso at sourceware.org	2006-11-09 15:31:01

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	This is the fix for Bugzilla Bug 214621: Allow gfs2_edit to view,
	print and edit gfs(1) file systems.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5&r2=1.5.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6&r2=1.6.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1

--- cluster/gfs2/edit/gfs2hex.c	2006/08/09 20:21:59	1.5
+++ cluster/gfs2/edit/gfs2hex.c	2006/11/09 15:31:01	1.5.2.1
@@ -201,7 +201,8 @@
 {
 	unsigned int x, y;
 	uint64_t p, last;
-	int isdir = !!(S_ISDIR(di->di_mode));
+	int isdir = !!(S_ISDIR(di->di_mode)) || 
+		(gfs1 && di->__pad1 == GFS_FILE_DIR);
 
 	indirect_blocks = 0;
 	memset(&indirect, 0, sizeof(indirect));
@@ -400,11 +401,20 @@
 
 	pv(sb, sb_bsize, "%u", "0x%x");
 	pv(sb, sb_bsize_shift, "%u", "0x%x");
-	gfs2_inum_print2("master dir", &sb->sb_master_dir);
+	if (gfs1) {
+		gfs2_inum_print2("jindex ino", &sbd1->sb_jindex_di);
+		gfs2_inum_print2("rindex ino", &sbd1->sb_rindex_di);
+	}
+	else
+		gfs2_inum_print2("master dir", &sb->sb_master_dir);
 	gfs2_inum_print2("root dir  ", &sb->sb_root_dir);
 
 	pv(sb, sb_lockproto, "%s", NULL);
 	pv(sb, sb_locktable, "%s", NULL);
+	if (gfs1) {
+		gfs2_inum_print2("quota ino ", &gfs1_quota_di);
+		gfs2_inum_print2("license   ", &gfs1_license_di);
+	}
 }
 
 /******************************************************************************
--- cluster/gfs2/edit/hexedit.c	2006/08/09 20:21:59	1.6
+++ cluster/gfs2/edit/hexedit.c	2006/11/09 15:31:01	1.6.2.1
@@ -36,7 +36,6 @@
 
 #define EXTERN
 #include "hexedit.h"
-#include "linux/gfs2_ondisk.h"
 #include "linux_endian.h"
 #include "libgfs2.h"
 #include "gfs2hex.h"
@@ -286,6 +285,7 @@
 	move(line++, 0);
 	printw("Other commands:");
 	gfs2instr("   h","This Help display");
+	gfs2instr("   c","Toggle the color scheme");
 	gfs2instr("   m","Switch display mode: hex -> GFS2 structure -> Extended");
 	gfs2instr("   q","Quit (same as hitting <escape> key)");
 	gfs2instr("<enter>","Edit a value (enter to save, esc to discard)");
@@ -346,7 +346,10 @@
 		switch (*(lpBuffer+7)) {
 		case GFS2_METATYPE_SB:   /* 1 */
 			print_gfs2("(superblock)");
-			struct_len = sizeof(struct gfs2_sb);
+			if (gfs1)
+				struct_len = sizeof(struct gfs_sb);
+			else
+				struct_len = sizeof(struct gfs2_sb);
 			break;
 		case GFS2_METATYPE_RG:   /* 2 */
 			print_gfs2("(rsrc grp hdr)");
@@ -410,25 +413,37 @@
 	}
 	if (block == sbd.sd_sb.sb_root_dir.no_addr)
 		print_gfs2("-------------------- Root direcory -------------------");
-	else if (block == sbd.sd_sb.sb_master_dir.no_addr)
+	else if (!gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr)
 		print_gfs2("------------------- Master directory -----------------");
 	else {
-		int d;
+		if (gfs1) {
+			if (block == sbd1->sb_rindex_di.no_addr)
+				print_gfs2("--------------------- rindex file -------------------");
+			else if (block == gfs1_quota_di.no_addr)
+				print_gfs2("--------------------- Quota file --------------------");
+			else if (block == sbd1->sb_jindex_di.no_addr)
+				print_gfs2("-------------------- Journal Index ------------------");
+			else if (block == gfs1_license_di.no_addr)
+				print_gfs2("-------------------- License file -------------------");
+		}
+		else {
+			int d;
 
-		for (d = 2; d < 8; d++) {
-			if (block == masterdir.dirent[d].block) {
-				if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
-					print_gfs2("-------------------- Journal Index ------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
-					print_gfs2("-------------------- Per-node Dir -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
-					print_gfs2("--------------------- Inum file ---------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
-					print_gfs2("--------------------- statfs file -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
-					print_gfs2("--------------------- rindex file -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
-					print_gfs2("--------------------- Quota file --------------------");
+			for (d = 2; d < 8; d++) {
+				if (block == masterdir.dirent[d].block) {
+					if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
+						print_gfs2("-------------------- Journal Index ------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
+						print_gfs2("-------------------- Per-node Dir -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
+						print_gfs2("--------------------- Inum file ---------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
+						print_gfs2("--------------------- statfs file -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
+						print_gfs2("--------------------- rindex file -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
+						print_gfs2("--------------------- Quota file --------------------");
+				}
 			}
 		}
 	}
@@ -513,6 +528,11 @@
 		eol(0);
 		l+=16;
 	} /* while */
+	if (gfs1) {
+		COLORS_NORMAL;
+		print_gfs2("         *** This seems to be a GFS-1 file system ***");
+		eol(0);
+	}
 	return (offset+len);
 }/* hexdump */
 
@@ -634,7 +654,8 @@
 	eol(0);
 	start_line = line;
 	if (indirect_blocks ||
-		(gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode))) {
+		(gfs2_struct_type == GFS2_METATYPE_DI &&
+		 (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR)))) {
 		indir_blocks = indirect_blocks;
 		if (!indirect_blocks) {
 			print_gfs2("This directory contains %d directory entries.",
@@ -754,7 +775,8 @@
 	else
 		print_gfs2("This block does not have indirect blocks.");
 	eol(0);
-	if (block == masterblock("rindex")) {
+	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
+		(block == masterblock("rindex"))) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -762,7 +784,7 @@
 		print_rindex(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("inum")) {
+	else if (!gfs1 && block == masterblock("inum")) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -770,7 +792,7 @@
 		print_inum(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("statfs")) {
+	else if (!gfs1 && block == masterblock("statfs")) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -778,7 +800,8 @@
 		print_statfs(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("quota")) {
+	else if ((gfs1 && block == gfs1_quota_di.no_addr) ||
+			 (block == masterblock("quota"))) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -796,6 +819,7 @@
 {
 	int x;
 
+	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
 	do_lseek(fd, 0x10 * bufsize);
 	do_read(fd, buf, bufsize); /* read in the desired block */
@@ -813,6 +837,20 @@
 		osi_list_init(&sbd.buf_hash[x]);
 	compute_constants(&sbd);
 	gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */
+	/* Check to see if this is really gfs1 */
+	if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
+		sbd1->sb_header.mh_type == GFS_METATYPE_SB &&
+		sbd1->sb_header.mh_format == GFS_FORMAT_SB &&
+		sbd1->sb_multihost_format == GFS_FORMAT_MULTI) {
+		struct gfs_sb *sbbuf = (struct gfs_sb *)buf;
+
+		gfs1 = TRUE;
+		gfs2_inum_in(&sbd1->sb_rindex_di, (void *)&sbbuf->sb_rindex_di);
+		gfs2_inum_in(&gfs1_quota_di, (void *)&sbbuf->sb_quota_di);
+		gfs2_inum_in(&gfs1_license_di, (void *)&sbbuf->sb_license_di);
+	}
+	else
+		gfs1 = FALSE;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -938,10 +976,20 @@
 	if (bobgets(string, 1, 7, 16)) {
 		if (!strcmp(string,"root"))
 			temp_blk = sbd.sd_sb.sb_root_dir.no_addr;
-		else if (!strcmp(string,"master"))
+		else if (!gfs1 && !strcmp(string,"master"))
 			temp_blk = sbd.sd_sb.sb_master_dir.no_addr;
-		else if (isalpha(string[0]))
-			temp_blk = masterblock(string);
+		else if (isalpha(string[0])) {
+			if (gfs1) {
+				if (!strcmp(string, "jindex"))
+					temp_blk = sbd1->sb_jindex_di.no_addr;
+				else if (!strcmp(string, "rindex"))
+					temp_blk = sbd1->sb_rindex_di.no_addr;
+				else if (!strcmp(string, "quota"))
+					temp_blk = gfs1_quota_di.no_addr;
+			}
+			else
+				temp_blk = masterblock(string);
+		}
 		else if (string[0] == '0' && string[1] == 'x')
 			sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
 		else
@@ -957,6 +1005,32 @@
 }
 
 /* ------------------------------------------------------------------------ */
+/* init_colors                                                              */
+/* ------------------------------------------------------------------------ */
+void init_colors()
+{
+
+	if (color_scheme) {
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
+		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK); /* normal text */
+		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE); /* inverse text */
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK); /* special text */
+		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK); /* offsets */
+		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */
+	}
+	else {
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
+		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
+		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
+		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
+		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
+	}
+}
+
+/* ------------------------------------------------------------------------ */
 /* interactive_mode - accept keystrokes from user and display structures    */
 /* ------------------------------------------------------------------------ */
 void interactive_mode(void)
@@ -980,24 +1054,7 @@
 	keypad(stdscr, TRUE);
 	raw();
 	curs_set(0);
-	if (color_scheme) {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */
-	}
-	else {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
-	}
+	init_colors();
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
 	while (!Quit) {
@@ -1128,6 +1185,13 @@
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
+		/* c - Change color scheme */
+		/* -------------------------------------------------------------- */
+		case 'c':
+			color_scheme = !color_scheme;
+			init_colors();
+			break;
+		/* -------------------------------------------------------------- */
 		/* page up key */
 		/* -------------------------------------------------------------- */
 		case 0x19:                    // ctrl-y for vt100
@@ -1295,6 +1359,7 @@
 				exit(0);
 			}
 			else if (!strcasecmp(argv[i], "-h") ||
+					 !strcasecmp(argv[i], "-help") ||
 					 !strcasecmp(argv[i], "-usage")) {
 				usage();
 				exit(0);
@@ -1303,7 +1368,8 @@
 				i++;
 				color_scheme = atoi(argv[i]);
 			}
-			else if (!strcasecmp(argv[i], "-p")) {
+			else if (!strcasecmp(argv[i], "-p") ||
+					 !strcasecmp(argv[i], "-print")) {
 				termlines = 0; /* initial value--we'll figure it out later */
 				display_mode = GFS2_MODE;
 			}
@@ -1323,24 +1389,39 @@
 				else if (!strcmp(argv[i], "size"))
 					printf("Device size: %" PRIu64 " (0x%" PRIx64 ")\n",
 						   max_block, max_block);
-				else if (!strcmp(argv[i], "sb"))
+				else if (!strcmp(argv[i], "sb") ||
+						 !strcmp(argv[i], "superblock"))
 					push_block(0x10); /* superblock */
-				else if (!strcmp(argv[i], "root"))
+				else if (!strcmp(argv[i], "root") ||
+						 !strcmp(argv[i], "rootdir"))
 					push_block(sbd.sd_sb.sb_root_dir.no_addr);
-				else if (!strcmp(argv[i], "master"))
+				else if (!gfs1 && !strcmp(argv[i], "master"))
 					push_block(sbd.sd_sb.sb_master_dir.no_addr);
-				else if (!strcmp(argv[i], "jindex"))
-					push_block(masterblock("jindex"));/* journal index */
-				else if (!strcmp(argv[i], "per_node"))
+				else if (!strcmp(argv[i], "jindex")) {
+					if (gfs1)
+						push_block(sbd1->sb_jindex_di.no_addr);
+					else
+						push_block(masterblock("jindex"));/* journal index */
+				}
+				else if (!gfs1 && !strcmp(argv[i], "per_node"))
 					push_block(masterblock("per_node"));
-				else if (!strcmp(argv[i], "inum"))
+				else if (!gfs1 && !strcmp(argv[i], "inum"))
 					push_block(masterblock("inum"));
-				else if (!strcmp(argv[i], "statfs"))
+				else if (!gfs1 && !strcmp(argv[i], "statfs"))
 					push_block(masterblock("statfs"));
-				else if (!strcmp(argv[i], "rindex"))
-					push_block(masterblock("rindex"));
-				else if (!strcmp(argv[i], "quota"))
-					push_block(masterblock("quota"));
+				else if (!strcmp(argv[i], "rindex") ||
+						 !strcmp(argv[i], "rgindex")) {
+					if (gfs1)
+						push_block(sbd1->sb_rindex_di.no_addr);
+					else
+						push_block(masterblock("rindex"));
+				}
+				else if (!strcmp(argv[i], "quota")) {
+					if (gfs1)
+						push_block(gfs1_quota_di.no_addr);
+					else
+						push_block(masterblock("quota"));
+				}
 				else if (argv[i][0]=='0' && argv[i][1]=='x') { /* hex addr */
 					sscanf(argv[i], "%"SCNx64, &temp_blk);/* retrieve in hex */
 					push_block(temp_blk);
@@ -1401,7 +1482,8 @@
 	max_block = lseek(fd, 0, SEEK_END) / bufsize;
 
 	read_superblock();
-	read_master_dir();
+	if (!gfs1)
+		read_master_dir();
 	block_in_mem = -1;
 	if (!termlines)    /* if printing to stdout */
 		process_parameters(argc, argv, 1); /* get what to print from cmdline */
--- cluster/gfs2/edit/hexedit.h	2006/06/19 20:49:25	1.4
+++ cluster/gfs2/edit/hexedit.h	2006/11/09 15:31:01	1.4.2.1
@@ -43,6 +43,20 @@
 enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2 };
 #define BLOCK_STACK_SIZE 256
 
+#define GFS_FORMAT_SB           (100)  /* Super-Block */
+#define GFS_METATYPE_SB         (1)    /* Super-Block */
+#define GFS_FORMAT_FS           (1309) /* Filesystem (all-encompassing) */
+#define GFS_FORMAT_MULTI        (1401) /* Multi-Host */
+/* GFS1 Dinode types  */
+#define GFS_FILE_NON            (0)
+#define GFS_FILE_REG            (1)    /* regular file */
+#define GFS_FILE_DIR            (2)    /* directory */
+#define GFS_FILE_LNK            (5)    /* link */
+#define GFS_FILE_BLK            (7)    /* block device node */
+#define GFS_FILE_CHR            (8)    /* character device node */
+#define GFS_FILE_FIFO           (101)  /* fifo/pipe */
+#define GFS_FILE_SOCK           (102)  /* socket */
+
 EXTERN char *prog_name;
 EXTERN int fd;
 EXTERN uint64_t block INIT(0);
@@ -66,6 +80,9 @@
 EXTERN int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES];
 EXTERN char edit_string[1024], edit_fmt[80];
 EXTERN struct gfs2_sbd sbd;
+EXTERN struct gfs_sb *sbd1;
+EXTERN struct gfs2_inum gfs1_quota_di;   /* kludge because gfs2 sb too small */
+EXTERN struct gfs2_inum gfs1_license_di; /* kludge because gfs2 sb too small */
 EXTERN struct gfs2_dinode di;
 EXTERN int screen_chunk_size INIT(512); /* how much of the 4K can fit on screen */
 EXTERN int gfs2_struct_type;
@@ -74,6 +91,7 @@
 EXTERN int identify INIT(FALSE);
 EXTERN int color_scheme INIT(0);
 EXTERN WINDOW *wind;
+EXTERN int gfs1 INIT(0);
 
 struct gfs2_dirents {
 	uint64_t block;
@@ -95,6 +113,35 @@
 	enum dsp_mode display_mode;
 };
 
+struct gfs_sb {
+	/*  Order is important; need to be able to read old superblocks
+	    in order to support on-disk version upgrades */
+	struct gfs2_meta_header sb_header;
+
+	uint32_t sb_fs_format;         /* GFS_FORMAT_FS (on-disk version) */
+	uint32_t sb_multihost_format;  /* GFS_FORMAT_MULTI */
+	uint32_t sb_flags;             /* ?? */
+
+	uint32_t sb_bsize;             /* fundamental FS block size in bytes */
+	uint32_t sb_bsize_shift;       /* log2(sb_bsize) */
+	uint32_t sb_seg_size;          /* Journal segment size in FS blocks */
+
+	/* These special inodes do not appear in any on-disk directory. */
+	struct gfs2_inum sb_jindex_di;  /* journal index inode */
+	struct gfs2_inum sb_rindex_di;  /* resource group index inode */
+	struct gfs2_inum sb_root_di;    /* root directory inode */
+
+	/* Default inter-node locking protocol (lock module) and namespace */
+	char sb_lockproto[GFS2_LOCKNAME_LEN]; /* lock protocol name */
+	char sb_locktable[GFS2_LOCKNAME_LEN]; /* unique name for this FS */
+
+	/* More special inodes */
+	struct gfs2_inum sb_quota_di;   /* quota inode */
+	struct gfs2_inum sb_license_di; /* license inode */
+
+	char sb_reserved[96];
+};
+
 EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
 EXTERN struct indirect_info indirect[512]; /* more than the most indirect
 											  pointers possible for any given



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2006-11-09 15:29 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2006-11-09 15:29 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2006-11-09 15:29:45

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	This is the fix for Bugzilla Bug 214621: Allow gfs2_edit to view,
	print and edit gfs(1) file systems.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.5&r2=1.6
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.6&r2=1.7
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.4&r2=1.5

--- cluster/gfs2/edit/gfs2hex.c	2006/08/09 20:21:59	1.5
+++ cluster/gfs2/edit/gfs2hex.c	2006/11/09 15:29:45	1.6
@@ -201,7 +201,8 @@
 {
 	unsigned int x, y;
 	uint64_t p, last;
-	int isdir = !!(S_ISDIR(di->di_mode));
+	int isdir = !!(S_ISDIR(di->di_mode)) || 
+		(gfs1 && di->__pad1 == GFS_FILE_DIR);
 
 	indirect_blocks = 0;
 	memset(&indirect, 0, sizeof(indirect));
@@ -400,11 +401,20 @@
 
 	pv(sb, sb_bsize, "%u", "0x%x");
 	pv(sb, sb_bsize_shift, "%u", "0x%x");
-	gfs2_inum_print2("master dir", &sb->sb_master_dir);
+	if (gfs1) {
+		gfs2_inum_print2("jindex ino", &sbd1->sb_jindex_di);
+		gfs2_inum_print2("rindex ino", &sbd1->sb_rindex_di);
+	}
+	else
+		gfs2_inum_print2("master dir", &sb->sb_master_dir);
 	gfs2_inum_print2("root dir  ", &sb->sb_root_dir);
 
 	pv(sb, sb_lockproto, "%s", NULL);
 	pv(sb, sb_locktable, "%s", NULL);
+	if (gfs1) {
+		gfs2_inum_print2("quota ino ", &gfs1_quota_di);
+		gfs2_inum_print2("license   ", &gfs1_license_di);
+	}
 }
 
 /******************************************************************************
--- cluster/gfs2/edit/hexedit.c	2006/08/09 20:21:59	1.6
+++ cluster/gfs2/edit/hexedit.c	2006/11/09 15:29:45	1.7
@@ -36,7 +36,6 @@
 
 #define EXTERN
 #include "hexedit.h"
-#include "linux/gfs2_ondisk.h"
 #include "linux_endian.h"
 #include "libgfs2.h"
 #include "gfs2hex.h"
@@ -286,6 +285,7 @@
 	move(line++, 0);
 	printw("Other commands:");
 	gfs2instr("   h","This Help display");
+	gfs2instr("   c","Toggle the color scheme");
 	gfs2instr("   m","Switch display mode: hex -> GFS2 structure -> Extended");
 	gfs2instr("   q","Quit (same as hitting <escape> key)");
 	gfs2instr("<enter>","Edit a value (enter to save, esc to discard)");
@@ -346,7 +346,10 @@
 		switch (*(lpBuffer+7)) {
 		case GFS2_METATYPE_SB:   /* 1 */
 			print_gfs2("(superblock)");
-			struct_len = sizeof(struct gfs2_sb);
+			if (gfs1)
+				struct_len = sizeof(struct gfs_sb);
+			else
+				struct_len = sizeof(struct gfs2_sb);
 			break;
 		case GFS2_METATYPE_RG:   /* 2 */
 			print_gfs2("(rsrc grp hdr)");
@@ -410,25 +413,37 @@
 	}
 	if (block == sbd.sd_sb.sb_root_dir.no_addr)
 		print_gfs2("-------------------- Root direcory -------------------");
-	else if (block == sbd.sd_sb.sb_master_dir.no_addr)
+	else if (!gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr)
 		print_gfs2("------------------- Master directory -----------------");
 	else {
-		int d;
+		if (gfs1) {
+			if (block == sbd1->sb_rindex_di.no_addr)
+				print_gfs2("--------------------- rindex file -------------------");
+			else if (block == gfs1_quota_di.no_addr)
+				print_gfs2("--------------------- Quota file --------------------");
+			else if (block == sbd1->sb_jindex_di.no_addr)
+				print_gfs2("-------------------- Journal Index ------------------");
+			else if (block == gfs1_license_di.no_addr)
+				print_gfs2("-------------------- License file -------------------");
+		}
+		else {
+			int d;
 
-		for (d = 2; d < 8; d++) {
-			if (block == masterdir.dirent[d].block) {
-				if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
-					print_gfs2("-------------------- Journal Index ------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
-					print_gfs2("-------------------- Per-node Dir -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
-					print_gfs2("--------------------- Inum file ---------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
-					print_gfs2("--------------------- statfs file -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
-					print_gfs2("--------------------- rindex file -------------------");
-				else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
-					print_gfs2("--------------------- Quota file --------------------");
+			for (d = 2; d < 8; d++) {
+				if (block == masterdir.dirent[d].block) {
+					if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
+						print_gfs2("-------------------- Journal Index ------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
+						print_gfs2("-------------------- Per-node Dir -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
+						print_gfs2("--------------------- Inum file ---------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
+						print_gfs2("--------------------- statfs file -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
+						print_gfs2("--------------------- rindex file -------------------");
+					else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
+						print_gfs2("--------------------- Quota file --------------------");
+				}
 			}
 		}
 	}
@@ -513,6 +528,11 @@
 		eol(0);
 		l+=16;
 	} /* while */
+	if (gfs1) {
+		COLORS_NORMAL;
+		print_gfs2("         *** This seems to be a GFS-1 file system ***");
+		eol(0);
+	}
 	return (offset+len);
 }/* hexdump */
 
@@ -634,7 +654,8 @@
 	eol(0);
 	start_line = line;
 	if (indirect_blocks ||
-		(gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode))) {
+		(gfs2_struct_type == GFS2_METATYPE_DI &&
+		 (S_ISDIR(di.di_mode) || (gfs1 && di.__pad1 == GFS_FILE_DIR)))) {
 		indir_blocks = indirect_blocks;
 		if (!indirect_blocks) {
 			print_gfs2("This directory contains %d directory entries.",
@@ -754,7 +775,8 @@
 	else
 		print_gfs2("This block does not have indirect blocks.");
 	eol(0);
-	if (block == masterblock("rindex")) {
+	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
+		(block == masterblock("rindex"))) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -762,7 +784,7 @@
 		print_rindex(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("inum")) {
+	else if (!gfs1 && block == masterblock("inum")) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -770,7 +792,7 @@
 		print_inum(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("statfs")) {
+	else if (!gfs1 && block == masterblock("statfs")) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -778,7 +800,8 @@
 		print_statfs(tmp_inode);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (block == masterblock("quota")) {
+	else if ((gfs1 && block == gfs1_quota_di.no_addr) ||
+			 (block == masterblock("quota"))) {
 		struct gfs2_buffer_head *tmp_bh;
 
 		tmp_bh = bread(&sbd, block);
@@ -796,6 +819,7 @@
 {
 	int x;
 
+	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
 	do_lseek(fd, 0x10 * bufsize);
 	do_read(fd, buf, bufsize); /* read in the desired block */
@@ -813,6 +837,20 @@
 		osi_list_init(&sbd.buf_hash[x]);
 	compute_constants(&sbd);
 	gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */
+	/* Check to see if this is really gfs1 */
+	if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
+		sbd1->sb_header.mh_type == GFS_METATYPE_SB &&
+		sbd1->sb_header.mh_format == GFS_FORMAT_SB &&
+		sbd1->sb_multihost_format == GFS_FORMAT_MULTI) {
+		struct gfs_sb *sbbuf = (struct gfs_sb *)buf;
+
+		gfs1 = TRUE;
+		gfs2_inum_in(&sbd1->sb_rindex_di, (void *)&sbbuf->sb_rindex_di);
+		gfs2_inum_in(&gfs1_quota_di, (void *)&sbbuf->sb_quota_di);
+		gfs2_inum_in(&gfs1_license_di, (void *)&sbbuf->sb_license_di);
+	}
+	else
+		gfs1 = FALSE;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -938,10 +976,20 @@
 	if (bobgets(string, 1, 7, 16)) {
 		if (!strcmp(string,"root"))
 			temp_blk = sbd.sd_sb.sb_root_dir.no_addr;
-		else if (!strcmp(string,"master"))
+		else if (!gfs1 && !strcmp(string,"master"))
 			temp_blk = sbd.sd_sb.sb_master_dir.no_addr;
-		else if (isalpha(string[0]))
-			temp_blk = masterblock(string);
+		else if (isalpha(string[0])) {
+			if (gfs1) {
+				if (!strcmp(string, "jindex"))
+					temp_blk = sbd1->sb_jindex_di.no_addr;
+				else if (!strcmp(string, "rindex"))
+					temp_blk = sbd1->sb_rindex_di.no_addr;
+				else if (!strcmp(string, "quota"))
+					temp_blk = gfs1_quota_di.no_addr;
+			}
+			else
+				temp_blk = masterblock(string);
+		}
 		else if (string[0] == '0' && string[1] == 'x')
 			sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
 		else
@@ -957,6 +1005,32 @@
 }
 
 /* ------------------------------------------------------------------------ */
+/* init_colors                                                              */
+/* ------------------------------------------------------------------------ */
+void init_colors()
+{
+
+	if (color_scheme) {
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
+		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK); /* normal text */
+		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE); /* inverse text */
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK); /* special text */
+		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK); /* offsets */
+		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */
+	}
+	else {
+		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
+		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
+		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
+		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
+		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */
+		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
+		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
+	}
+}
+
+/* ------------------------------------------------------------------------ */
 /* interactive_mode - accept keystrokes from user and display structures    */
 /* ------------------------------------------------------------------------ */
 void interactive_mode(void)
@@ -980,24 +1054,7 @@
 	keypad(stdscr, TRUE);
 	raw();
 	curs_set(0);
-	if (color_scheme) {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK); /* file data */
-	}
-	else {
-		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);  /* title lines */
-		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE); /* normal text */
-		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK); /* inverse text */
-		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_WHITE); /* special text */
-		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_WHITE); /* highlighted */
-		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE); /* offsets */
-		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE); /* file data */
-	}
+	init_colors();
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
 	while (!Quit) {
@@ -1128,6 +1185,13 @@
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
+		/* c - Change color scheme */
+		/* -------------------------------------------------------------- */
+		case 'c':
+			color_scheme = !color_scheme;
+			init_colors();
+			break;
+		/* -------------------------------------------------------------- */
 		/* page up key */
 		/* -------------------------------------------------------------- */
 		case 0x19:                    // ctrl-y for vt100
@@ -1295,6 +1359,7 @@
 				exit(0);
 			}
 			else if (!strcasecmp(argv[i], "-h") ||
+					 !strcasecmp(argv[i], "-help") ||
 					 !strcasecmp(argv[i], "-usage")) {
 				usage();
 				exit(0);
@@ -1303,7 +1368,8 @@
 				i++;
 				color_scheme = atoi(argv[i]);
 			}
-			else if (!strcasecmp(argv[i], "-p")) {
+			else if (!strcasecmp(argv[i], "-p") ||
+					 !strcasecmp(argv[i], "-print")) {
 				termlines = 0; /* initial value--we'll figure it out later */
 				display_mode = GFS2_MODE;
 			}
@@ -1323,24 +1389,39 @@
 				else if (!strcmp(argv[i], "size"))
 					printf("Device size: %" PRIu64 " (0x%" PRIx64 ")\n",
 						   max_block, max_block);
-				else if (!strcmp(argv[i], "sb"))
+				else if (!strcmp(argv[i], "sb") ||
+						 !strcmp(argv[i], "superblock"))
 					push_block(0x10); /* superblock */
-				else if (!strcmp(argv[i], "root"))
+				else if (!strcmp(argv[i], "root") ||
+						 !strcmp(argv[i], "rootdir"))
 					push_block(sbd.sd_sb.sb_root_dir.no_addr);
-				else if (!strcmp(argv[i], "master"))
+				else if (!gfs1 && !strcmp(argv[i], "master"))
 					push_block(sbd.sd_sb.sb_master_dir.no_addr);
-				else if (!strcmp(argv[i], "jindex"))
-					push_block(masterblock("jindex"));/* journal index */
-				else if (!strcmp(argv[i], "per_node"))
+				else if (!strcmp(argv[i], "jindex")) {
+					if (gfs1)
+						push_block(sbd1->sb_jindex_di.no_addr);
+					else
+						push_block(masterblock("jindex"));/* journal index */
+				}
+				else if (!gfs1 && !strcmp(argv[i], "per_node"))
 					push_block(masterblock("per_node"));
-				else if (!strcmp(argv[i], "inum"))
+				else if (!gfs1 && !strcmp(argv[i], "inum"))
 					push_block(masterblock("inum"));
-				else if (!strcmp(argv[i], "statfs"))
+				else if (!gfs1 && !strcmp(argv[i], "statfs"))
 					push_block(masterblock("statfs"));
-				else if (!strcmp(argv[i], "rindex"))
-					push_block(masterblock("rindex"));
-				else if (!strcmp(argv[i], "quota"))
-					push_block(masterblock("quota"));
+				else if (!strcmp(argv[i], "rindex") ||
+						 !strcmp(argv[i], "rgindex")) {
+					if (gfs1)
+						push_block(sbd1->sb_rindex_di.no_addr);
+					else
+						push_block(masterblock("rindex"));
+				}
+				else if (!strcmp(argv[i], "quota")) {
+					if (gfs1)
+						push_block(gfs1_quota_di.no_addr);
+					else
+						push_block(masterblock("quota"));
+				}
 				else if (argv[i][0]=='0' && argv[i][1]=='x') { /* hex addr */
 					sscanf(argv[i], "%"SCNx64, &temp_blk);/* retrieve in hex */
 					push_block(temp_blk);
@@ -1401,7 +1482,8 @@
 	max_block = lseek(fd, 0, SEEK_END) / bufsize;
 
 	read_superblock();
-	read_master_dir();
+	if (!gfs1)
+		read_master_dir();
 	block_in_mem = -1;
 	if (!termlines)    /* if printing to stdout */
 		process_parameters(argc, argv, 1); /* get what to print from cmdline */
--- cluster/gfs2/edit/hexedit.h	2006/06/19 20:49:25	1.4
+++ cluster/gfs2/edit/hexedit.h	2006/11/09 15:29:45	1.5
@@ -43,6 +43,20 @@
 enum dsp_mode { HEX_MODE = 0, GFS2_MODE = 1, EXTENDED_MODE = 2 };
 #define BLOCK_STACK_SIZE 256
 
+#define GFS_FORMAT_SB           (100)  /* Super-Block */
+#define GFS_METATYPE_SB         (1)    /* Super-Block */
+#define GFS_FORMAT_FS           (1309) /* Filesystem (all-encompassing) */
+#define GFS_FORMAT_MULTI        (1401) /* Multi-Host */
+/* GFS1 Dinode types  */
+#define GFS_FILE_NON            (0)
+#define GFS_FILE_REG            (1)    /* regular file */
+#define GFS_FILE_DIR            (2)    /* directory */
+#define GFS_FILE_LNK            (5)    /* link */
+#define GFS_FILE_BLK            (7)    /* block device node */
+#define GFS_FILE_CHR            (8)    /* character device node */
+#define GFS_FILE_FIFO           (101)  /* fifo/pipe */
+#define GFS_FILE_SOCK           (102)  /* socket */
+
 EXTERN char *prog_name;
 EXTERN int fd;
 EXTERN uint64_t block INIT(0);
@@ -66,6 +80,9 @@
 EXTERN int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES];
 EXTERN char edit_string[1024], edit_fmt[80];
 EXTERN struct gfs2_sbd sbd;
+EXTERN struct gfs_sb *sbd1;
+EXTERN struct gfs2_inum gfs1_quota_di;   /* kludge because gfs2 sb too small */
+EXTERN struct gfs2_inum gfs1_license_di; /* kludge because gfs2 sb too small */
 EXTERN struct gfs2_dinode di;
 EXTERN int screen_chunk_size INIT(512); /* how much of the 4K can fit on screen */
 EXTERN int gfs2_struct_type;
@@ -74,6 +91,7 @@
 EXTERN int identify INIT(FALSE);
 EXTERN int color_scheme INIT(0);
 EXTERN WINDOW *wind;
+EXTERN int gfs1 INIT(0);
 
 struct gfs2_dirents {
 	uint64_t block;
@@ -95,6 +113,35 @@
 	enum dsp_mode display_mode;
 };
 
+struct gfs_sb {
+	/*  Order is important; need to be able to read old superblocks
+	    in order to support on-disk version upgrades */
+	struct gfs2_meta_header sb_header;
+
+	uint32_t sb_fs_format;         /* GFS_FORMAT_FS (on-disk version) */
+	uint32_t sb_multihost_format;  /* GFS_FORMAT_MULTI */
+	uint32_t sb_flags;             /* ?? */
+
+	uint32_t sb_bsize;             /* fundamental FS block size in bytes */
+	uint32_t sb_bsize_shift;       /* log2(sb_bsize) */
+	uint32_t sb_seg_size;          /* Journal segment size in FS blocks */
+
+	/* These special inodes do not appear in any on-disk directory. */
+	struct gfs2_inum sb_jindex_di;  /* journal index inode */
+	struct gfs2_inum sb_rindex_di;  /* resource group index inode */
+	struct gfs2_inum sb_root_di;    /* root directory inode */
+
+	/* Default inter-node locking protocol (lock module) and namespace */
+	char sb_lockproto[GFS2_LOCKNAME_LEN]; /* lock protocol name */
+	char sb_locktable[GFS2_LOCKNAME_LEN]; /* unique name for this FS */
+
+	/* More special inodes */
+	struct gfs2_inum sb_quota_di;   /* quota inode */
+	struct gfs2_inum sb_license_di; /* license inode */
+
+	char sb_reserved[96];
+};
+
 EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
 EXTERN struct indirect_info indirect[512]; /* more than the most indirect
 											  pointers possible for any given



^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h
@ 2006-06-19 20:49 rpeterso
  0 siblings, 0 replies; 9+ messages in thread
From: rpeterso @ 2006-06-19 20:49 UTC (permalink / raw)
  To: cluster-devel.redhat.com

CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2006-06-19 20:49:25

Modified files:
	gfs2/edit      : gfs2hex.c hexedit.c hexedit.h 

Log message:
	Fixed problems printing stuffed directories like master and jindex.
	Also enhanced the jump 'j' command capabilities to jump based on
	highlighted directory entries.  Also made it remember display mode
	and highlighted entry when jumping from structure to structure.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&r1=1.3&r2=1.4

--- cluster/gfs2/edit/gfs2hex.c	2006/06/12 20:43:33	1.3
+++ cluster/gfs2/edit/gfs2hex.c	2006/06/19 20:49:25	1.4
@@ -221,6 +221,8 @@
 		int skip = 0;
 		/* Directory Entries: */
 		indirect[0].dirents = 0;
+		indirect[0].block = block;
+		indirect[0].is_dir = TRUE;
 		for (x = sizeof(struct gfs2_dinode); x < bufsize; x += skip) {
 			skip = indirect_dirent(&indirect[0], buf + x, indirect[0].dirents);
 			if (skip <= 0)
--- cluster/gfs2/edit/hexedit.c	2006/06/12 20:43:33	1.4
+++ cluster/gfs2/edit/hexedit.c	2006/06/19 20:49:25	1.5
@@ -627,48 +627,77 @@
 /* ------------------------------------------------------------------------ */
 int display_extended(void)
 {
-	int e, start_line, total_dirents;
+	int e, start_line, total_dirents, indir_blocks;
 	struct gfs2_inode *tmp_inode;
 
 	edit_last[display_mode] = 0;
 	eol(0);
 	start_line = line;
-	if (indirect_blocks) {
-		print_gfs2("This inode contains %d indirect blocks", indirect_blocks);
-		eol(0);
-		print_gfs2("Indirect blocks for this inode:");
-		eol(0);
+	if (indirect_blocks ||
+		(gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode))) {
+		indir_blocks = indirect_blocks;
+		if (!indirect_blocks) {
+			print_gfs2("This directory contains %d directory entries.",
+					   indirect[0].dirents);
+			eol(0);
+			indir_blocks = 1; /* not really an indirect block, but treat it as one */
+		}
+		else {
+			if (gfs2_struct_type == GFS2_METATYPE_DI && S_ISDIR(di.di_mode))
+				print_gfs2("This directory contains %d indirect blocks",
+						   indirect_blocks);
+			else
+				print_gfs2("This inode contains %d indirect blocks",
+						   indirect_blocks);
+			eol(0);
+			print_gfs2("Indirect blocks for this inode:");
+			eol(0);
+		}
 		total_dirents = 0;
 		for (e = 0; (!termlines || e < termlines - start_line - 2) &&
-				 e < indirect_blocks; e++) {
+				 e < indir_blocks; e++) {
 			if (termlines) {
-				if (line - 6 == edit_row[display_mode])
+				if (edit_row[display_mode] >= 0 &&
+					line - start_line - 2 == edit_row[display_mode])
 					COLORS_HIGHLIGHT;
-				move(line, 5);
+				move(line, 1);
 			}
-			print_gfs2("%d => ", e + 1);
-			if (termlines)
-				move(line,14);
-			print_gfs2("0x%llx", indirect[e].block);
-			if (termlines) {
-				if (line - 6 == edit_row[display_mode]) { 
-					sprintf(edit_string, "%"PRIx64, indirect[e].block);
-					strcpy(edit_fmt, "%"PRIx64);
-					edit_size[display_mode] = strlen(edit_string);
-					COLORS_NORMAL;
+			if (indir_blocks == indirect_blocks) {
+				print_gfs2("%d => ", e + 1);
+				if (termlines)
+					move(line,9);
+				print_gfs2("0x%llx", indirect[e].block);
+				if (termlines) {
+					if (edit_row[display_mode] >= 0 &&
+						line - start_line - 2 == edit_row[display_mode]) { 
+						sprintf(edit_string, "%"PRIx64, indirect[e].block);
+						strcpy(edit_fmt, "%"PRIx64);
+						edit_size[display_mode] = strlen(edit_string);
+						COLORS_NORMAL;
+					}
 				}
 			}
-			print_gfs2("   ");
+			if (indir_blocks == indirect_blocks)
+				print_gfs2("   ");
 			if (indirect[e].is_dir) {
 				int d;
 
-				if (indirect[e].dirents > 1)
+				if (indirect[e].dirents > 1 && indir_blocks == indirect_blocks)
 					print_gfs2("(directory leaf with %d entries)",
 							   indirect[e].dirents);
 				for (d = 0; d < indirect[e].dirents; d++) {
 					total_dirents++;
 					if (indirect[e].dirents > 1) {
 						eol(5);
+						if (termlines) {
+							if (edit_row[display_mode] >=0 &&
+								line - start_line - 2 == edit_row[display_mode]) {
+								COLORS_HIGHLIGHT;
+								sprintf(edit_string, "%"PRIx64,
+										indirect[e].dirent[d].block);
+								strcpy(edit_fmt, "%"PRIx64);
+							}
+						}
 						print_gfs2("%d. (%d). %lld (0x%llx) / %lld (0x%llx): ",
 								   total_dirents, d + 1,
 								   indirect[e].dirent[d].dirent.de_inum.no_formal_ino,
@@ -708,6 +737,11 @@
 					}
 
 					print_gfs2(" %s", indirect[e].dirent[d].filename);
+					if (termlines) {
+						if (edit_row[display_mode] >= 0 &&
+							line - start_line - 2 == edit_row[display_mode])
+							COLORS_NORMAL;
+					}
 				}
 			} /* if isdir */
 			else
@@ -860,9 +894,16 @@
 /* ------------------------------------------------------------------------ */
 void push_block(uint64_t blk)
 {
+	int i;
+
 	if (blk) {
+		blockstack[blockhist % BLOCK_STACK_SIZE].display_mode = display_mode;
+		for (i = 0; i < DISPLAY_MODES; i++) {
+			blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i] = edit_row[i];
+			blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i] = edit_col[i];
+		}
 		blockhist++;
-		blockstack[blockhist % BLOCK_STACK_SIZE] = blk;
+		blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
 	}
 }
 
@@ -871,10 +912,17 @@
 /* ------------------------------------------------------------------------ */
 uint64_t pop_block(void)
 {
+	int i;
+
 	if (!blockhist)
 		return block;
 	blockhist--;
-	return blockstack[blockhist % BLOCK_STACK_SIZE];
+	display_mode = blockstack[blockhist % BLOCK_STACK_SIZE].display_mode;
+	for (i = 0; i < DISPLAY_MODES; i++) {
+		edit_row[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_row[i];
+		edit_col[i] = blockstack[blockhist % BLOCK_STACK_SIZE].edit_col[i];
+	}
+	return blockstack[blockhist % BLOCK_STACK_SIZE].block;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -966,7 +1014,7 @@
 			Quit=TRUE;
 			break;
 		/* -------------------------------------------------------------- */
-		/* home - return to the superblock */
+		/* home - return to the superblock                                */
 		/* -------------------------------------------------------------- */
 		case KEY_HOME:
 			block = 0x10;
@@ -974,7 +1022,7 @@
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
-		/* backspace - return to the previous block */
+		/* backspace - return to the previous block on the stack          */
 		/* -------------------------------------------------------------- */
 		case KEY_BACKSPACE:
 		case 0x7f:
@@ -982,11 +1030,11 @@
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
-		/* space */
+		/* space - go down the block stack (opposite of backspace)        */
 		/* -------------------------------------------------------------- */
 		case ' ':
 			blockhist++;
-			block = blockstack[blockhist % BLOCK_STACK_SIZE];
+			block = blockstack[blockhist % BLOCK_STACK_SIZE].block;
 			offset = 0;
 			break;
 		/* -------------------------------------------------------------- */
@@ -1046,10 +1094,15 @@
 			else
 				sscanf(edit_string, "%"SCNx64, &temp_blk);/* retrieve in hex */
 			if (temp_blk < max_block) { /* if the block number is valid */
+				int i;
+
 				offset = 0;
-				display_mode = HEX_MODE;
 				block = temp_blk;
 				push_block(block);
+				for (i = 0; i < DISPLAY_MODES; i++) {
+					edit_row[i] = 0;
+					edit_col[i] = 0;
+				}
 			}
 			break;
 		/* -------------------------------------------------------------- */
@@ -1318,7 +1371,7 @@
 ******************************************************************************/
 int main(int argc, char *argv[])
 {
-	int i;
+	int i, j;
 
 	prog_name = argv[0];
 
@@ -1329,8 +1382,14 @@
 	display_mode = HEX_MODE;
 	type_alloc(buf, char, bufsize); /* allocate/malloc a new 4K buffer */
 	block = 0x10;
-	for (i = 0; i < BLOCK_STACK_SIZE; i++)
-		blockstack[i] = block;
+	for (i = 0; i < BLOCK_STACK_SIZE; i++) {
+		blockstack[i].display_mode = display_mode;
+		blockstack[i].block = block;
+		for (j = 0; j < DISPLAY_MODES; j++) {
+			blockstack[i].edit_row[j] = 0;
+			blockstack[i].edit_col[j] = 0;
+		}
+	}
 
 	memset(device, 0, sizeof(device));
 	termlines = 30;  /* assume interactive mode until we find -p */
@@ -1351,7 +1410,7 @@
 		interactive_mode();
 	else { /* print all the structures requested */
 		for (i = 0; i <= blockhist; i++) {
-			block = blockstack[i + 1];
+			block = blockstack[i + 1].block;
 			display(display_mode, identify);
 			if (!identify) {
 				display_extended();
--- cluster/gfs2/edit/hexedit.h	2006/06/06 14:35:32	1.3
+++ cluster/gfs2/edit/hexedit.h	2006/06/19 20:49:25	1.4
@@ -47,7 +47,6 @@
 EXTERN int fd;
 EXTERN uint64_t block INIT(0);
 EXTERN int blockhist INIT(0);
-EXTERN uint64_t blockstack[BLOCK_STACK_SIZE];
 EXTERN int edit_mode INIT(0);
 EXTERN int line;
 EXTERN char edit_fmt[80];
@@ -89,6 +88,14 @@
 	struct gfs2_dirents dirent[64];
 };
 
+struct blkstack_info {
+	uint64_t block;
+	int edit_row[DISPLAY_MODES];
+	int edit_col[DISPLAY_MODES];
+	enum dsp_mode display_mode;
+};
+
+EXTERN struct blkstack_info blockstack[BLOCK_STACK_SIZE];
 EXTERN struct indirect_info indirect[512]; /* more than the most indirect
 											  pointers possible for any given
 											  4K block */



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-11-13 17:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-08  5:41 [Cluster-devel] cluster/gfs2/edit gfs2hex.c hexedit.c hexedit.h rpeterso
  -- strict thread matches above, loose matches on Subject: below --
2007-11-13 17:22 rpeterso
2007-02-28 21:58 rpeterso
2007-02-13  1:07 rpeterso
2006-11-14 20:13 rpeterso
2006-11-14 20:11 rpeterso
2006-11-09 15:31 rpeterso
2006-11-09 15:29 rpeterso
2006-06-19 20:49 rpeterso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.