All of lore.kernel.org
 help / color / mirror / Atom feed
From: rpeterso@sourceware.org <rpeterso@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/gfs2 edit/Makefile edit/gfs2hex.c edit ...
Date: 26 Jun 2007 01:40:44 -0000	[thread overview]
Message-ID: <20070626014044.897.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	cluster
Branch: 	RHEL5
Changes by:	rpeterso at sourceware.org	2007-06-26 01:40:43

Modified files:
	gfs2/edit      : Makefile gfs2hex.c hexedit.c hexedit.h 
	gfs2/libgfs2   : super.c 

Log message:
	Resolves: bz 245635: Bring gfs2_edit up to date

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4&r2=1.4.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/gfs2hex.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.5.2.2&r2=1.5.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.6.2.2&r2=1.6.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/edit/hexedit.h.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.4.2.2&r2=1.4.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/super.c.diff?cvsroot=cluster&only_with_tag=RHEL5&r1=1.3.2.1&r2=1.3.2.2

--- cluster/gfs2/edit/Makefile	2006/08/11 15:18:12	1.4
+++ cluster/gfs2/edit/Makefile	2007/06/26 01:40:43	1.4.2.1
@@ -15,6 +15,7 @@
 
 SOURCE=	\
 	gfs2hex.c \
+	savemeta.c \
 	hexedit.c
 
 top_srcdir=..
--- cluster/gfs2/edit/gfs2hex.c	2006/11/14 20:13:36	1.5.2.2
+++ cluster/gfs2/edit/gfs2hex.c	2007/06/26 01:40:43	1.5.2.3
@@ -41,12 +41,12 @@
 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[DISPLAY_MODES], edit_col[DISPLAY_MODES];
-extern int edit_size[DISPLAY_MODES], edit_last[DISPLAY_MODES];
-extern char edit_string[1024], edit_fmt[80];
-extern enum dsp_mode display_mode INIT(HEX_MODE);
+extern int edit_row[DMODES], edit_col[DMODES];
+extern int edit_size[DMODES], last_entry_onscreen[DMODES];
+extern char edit_fmt[80];
+extern enum dsp_mode dmode INIT(HEX_MODE); /* display mode */
 
 void eol(int col) /* end of line */
 {
@@ -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[display_mode] + 4)
-				COLORS_HIGHLIGHT;
 			move(line,0);
 			printw("%s", label);
-			if (line == edit_row[display_mode] + 4)
-				COLORS_NORMAL;
 			move(line,24);
 		}
 		else {
@@ -102,28 +126,21 @@
 		}
 		vsprintf(tmp_string, fmt, args);
 
-		if (termlines) {
-			if (line == edit_row[display_mode] + 4)
-				COLORS_HIGHLIGHT;
+		if (termlines)
 			printw(tmp_string);
-			if (line == edit_row[display_mode] + 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[display_mode] + 4)
-					COLORS_HIGHLIGHT;
 				printw("%s", tmp_string);
-				if (line == edit_row[display_mode] + 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[display_mode] + 4) {
-				strcpy(edit_string, tmp_string);
+			if (line == (edit_row[dmode] * lines_per_row[dmode]) + 4) {
+				strcpy(estring, tmp_string);
 				strcpy(edit_fmt, fmt);
-				edit_size[display_mode] = strlen(edit_string);
+				edit_size[dmode] = strlen(estring);
 				COLORS_NORMAL;
 			}
-			if (line - 3 > edit_last[display_mode])
-				edit_last[display_mode] = line - 4;
+			last_entry_onscreen[dmode] = (line / lines_per_row[dmode]) - 4;
 		}
 		eol(0);
 		va_end(args);
@@ -293,7 +310,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));
@@ -326,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) {
@@ -360,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)
@@ -374,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	2006/11/14 20:13:36	1.6.2.2
+++ cluster/gfs2/edit/hexedit.c	2007/06/26 01:40:43	1.6.2.3
@@ -42,9 +42,13 @@
 
 #include <syslog.h>
 
-int display(enum dsp_mode display_mode, int identify_only);
+#define RGLIST_DUMMY_BLOCK -2
+
+int display(int identify_only);
 extern void eol(int col);
 extern void do_indirect_extended(char *buf);
+extern void savemeta(const char *in_fn, const char *out_fn, int slow);
+extern void restoremeta(const char *in_fn, const char *out_device);
 
 /* ------------------------------------------------------------------------ */
 /* UpdateSize - screen size changed, so update it                           */
@@ -70,7 +74,7 @@
 	else
 		perror("Error: tgetent failed.");
 	termlines--; /* last line is number of lines -1 */
-	display(display_mode, FALSE);
+	display(FALSE);
 	signal(SIGWINCH, UpdateSize);
 }
 
@@ -112,9 +116,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 +131,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 +167,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 +239,7 @@
 				break;
 			default:
 				move(0,70);
-				printw("%08X",ch);
+				printw("%08X",*ch);
 				// ignore all other characters
 				break;
 			} // end switch on non-printable character
@@ -323,12 +342,15 @@
 	}
 	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 (block == RGLIST_DUMMY_BLOCK)
+		print_gfs2("RG List       ");
+	else
+		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);
 	}
@@ -340,9 +362,14 @@
 	else
 		printf(" ");
 
-	if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 && *(lpBuffer+2)==0x19 &&
-		*(lpBuffer+3)==0x70 && *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
-		*(lpBuffer+6)==0x00) { /* If magic number appears at the start */
+	if (block == RGLIST_DUMMY_BLOCK) {
+		ret_type = GFS2_METATYPE_RG;
+		struct_len = sizeof(struct gfs2_rgrp);
+	}
+	else if (*(lpBuffer+0)==0x01 && *(lpBuffer+1)==0x16 &&
+	    *(lpBuffer+2)==0x19 && *(lpBuffer+3)==0x70 &&
+	    *(lpBuffer+4)==0x00 && *(lpBuffer+5)==0x00 &&
+	    *(lpBuffer+6)==0x00) { /* If magic number appears at the start */
 		ret_type = *(lpBuffer+7);
 		switch (*(lpBuffer+7)) {
 		case GFS2_METATYPE_SB:   /* 1 */
@@ -401,7 +428,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,9 +440,11 @@
 		/*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 if (!gfs1 && block == RGLIST_DUMMY_BLOCK)
+		print_gfs2("----------------------- RG List ----------------------");
 	else {
 		if (gfs1) {
 			if (block == sbd1->sb_rindex_di.no_addr)
@@ -465,6 +494,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)) ||
@@ -499,15 +529,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);
+				memset(estring,0,3);
+				sprintf(estring,"%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,10 +554,11 @@
 			ptr2++;
 		}
 		print_gfs2("] ");
-		if (line - 3 > edit_last[display_mode])
-			edit_last[display_mode] = 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;
@@ -552,28 +583,125 @@
 }
 
 /* ------------------------------------------------------------------------ */
-/* print_rindex - print the rgindex file.                                   */
+/* parse_rindex - print the rgindex file.                                   */
 /* ------------------------------------------------------------------------ */
-int print_rindex(struct gfs2_inode *di)
+int parse_rindex(struct gfs2_inode *di, int print_rindex)
 {
-	int rgs, error;
+	int error, start_line;
 	struct gfs2_rindex ri;
 	char buf[sizeof(struct gfs2_rindex)];
+	char highlighted_addr[32];
 
+	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),
-						   sizeof(struct gfs2_rindex));
+	lines_per_row[dmode] = 6;
+	memset(highlighted_addr, 0, sizeof(highlighted_addr));
+	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(highlighted_addr, "%llx", (unsigned long long)ri.ri_addr);
+			}
+			print_gfs2("RG #%d", print_entry_ndx);
+			if (!print_rindex)
+				print_gfs2(" located at: %llu (0x%llx)",
+					   ri.ri_addr, ri.ri_addr);
+			eol(0);
+			if (edit_row[dmode] == print_entry_ndx)
+				COLORS_NORMAL;
+			if(print_rindex)
+				gfs2_rindex_print(&ri);
+			else {
+				struct gfs2_rgrp rg;
+				struct gfs2_buffer_head *tmp_bh;
+
+				tmp_bh = bread(&sbd, ri.ri_addr);
+				gfs2_rgrp_in(&rg, tmp_bh->b_data);
+				gfs2_rgrp_print(&rg);
+				brelse(tmp_bh, not_updated);
+			}
+			last_entry_onscreen[dmode] = print_entry_ndx;
+		}
+	}
+	strcpy(estring, highlighted_addr);
+	end_row[dmode] = print_entry_ndx;
+	return error;
+}
+
+/* ------------------------------------------------------------------------ */
+/* 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;
 }
 
@@ -644,168 +772,358 @@
 }
 
 /* ------------------------------------------------------------------------ */
-/* 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[display_mode] = 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]={0,0,0,0,0};
+	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)))) {
-		indir_blocks = indirect_blocks;
-		if (!indirect_blocks) {
+	if (!has_indirect_blocks())
+		return -1;
+
+	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);
-			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))
+		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);
-			eol(0);
-			print_gfs2("Indirect blocks for this inode:");
-			eol(0);
 		}
-		total_dirents = 0;
-		for (e = 0; (!termlines || e < termlines - start_line - 2) &&
-				 e < indir_blocks; e++) {
+		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;
+			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) {
+			int diptrs, inptrs;
+
+			if (gfs1) {
+				diptrs = 483;
+				inptrs = 501;
+			} else {
+				diptrs = (bufsize - sizeof(sizeof(struct gfs2_dinode))) / sizeof(uint64_t);
+				inptrs = (bufsize - sizeof(sizeof(struct gfs2_meta_header))) /
+					sizeof(uint64_t);
+			}
+			/* 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] * inptrs;
+		}
+		print_gfs2("  (at height=%d)", cur_height);
+	}
+	if (indirect_blocks) {
+		eol(0);
+		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[display_mode] >= 0 &&
-					line - start_line - 2 == edit_row[display_mode])
-					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);
-				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;
-					}
+				if (edit_row[dmode] >= 0 &&
+					line - start_line - 2 == edit_row[dmode] -
+					start_row[dmode]) { 
+					sprintf(estring, "%"PRIx64,
+							indirect[print_entry_ndx].block);
+					strcpy(edit_fmt, "%"PRIx64);
+					edit_size[dmode] = strlen(estring);
+					COLORS_NORMAL;
 				}
 			}
-			if (indir_blocks == indirect_blocks)
+			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[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[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,
-								   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 (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[display_mode] >= 0 &&
-							line - start_line - 2 == edit_row[display_mode])
-							COLORS_NORMAL;
+						if (edit_row[dmode] >=0 &&
+							line - start_line - 2 == 
+							edit_row[dmode] -
+							start_row[dmode]) {
+							COLORS_HIGHLIGHT;
+							sprintf(estring, "%"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);
 				}
-			} /* 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;
-	} /* if (indirect_blocks) */
-	else
-		print_gfs2("This block does not have indirect blocks.");
+				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])
+						COLORS_NORMAL;
+				}
+			}
+		} /* 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;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_rindex                                                          */
+/* ------------------------------------------------------------------------ */
+int block_is_rindex(void)
+{
 	if ((gfs1 && block == sbd1->sb_rindex_di.no_addr) ||
-		(block == masterblock("rindex"))) {
-		struct gfs2_buffer_head *tmp_bh;
+	    (block == masterblock("rindex")))
+		return TRUE;
+	return FALSE;
+}
+
+/* ------------------------------------------------------------------------ */
+/* block_is_rglist - there's no such block as the rglist.  This is a        */
+/*                   special case meant to parse the rindex and follow the  */
+/*                   blocks to the real rgs.                                */
+/* ------------------------------------------------------------------------ */
+int block_is_rglist(void)
+{
+	if (block == RGLIST_DUMMY_BLOCK)
+		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_rglist() ||
+	    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)
+{
+	struct gfs2_inode *tmp_inode;
+	struct gfs2_buffer_head *tmp_bh;
+
+	/* Display any indirect pointers that we have. */
+	if (display_indirect() == 0)
+		return -1;
+	else if (block_is_rindex()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
-		print_rindex(tmp_inode);
+		parse_rindex(tmp_inode, TRUE);
 		brelse(tmp_bh, not_updated);
 	}
-	else if (!gfs1 && block == masterblock("inum")) {
-		struct gfs2_buffer_head *tmp_bh;
-
+	else if (block_is_rglist()) {
+		tmp_bh = bread(&sbd, masterblock("rindex"));
+		tmp_inode = inode_get(&sbd, tmp_bh);
+		parse_rindex(tmp_inode, FALSE);
+		brelse(tmp_bh, not_updated);
+	}
+	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")) {
-		struct gfs2_buffer_head *tmp_bh;
-
+	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"))) {
-		struct gfs2_buffer_head *tmp_bh;
-
+	else if (block_is_quota_file()) {
 		tmp_bh = bread(&sbd, block);
 		tmp_inode = inode_get(&sbd, tmp_bh);
 		print_quota(tmp_inode);
@@ -823,7 +1141,7 @@
 
 	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
 	ioctl(fd, BLKFLSBUF, 0);
-	do_lseek(fd, 0x10 * bufsize);
+	do_lseek(fd, 0x10 * 4096);
 	do_read(fd, buf, bufsize); /* read in the desired block */
 	memset(&sbd, 0, sizeof(struct gfs2_sbd));
 	sbd.device_fd = fd;
@@ -853,6 +1171,8 @@
 	}
 	else
 		gfs1 = FALSE;
+	bufsize = sbd.sd_sb.sb_bsize;
+	block = 0x10 * (4096 / bufsize);
 }
 
 /* ------------------------------------------------------------------------ */
@@ -871,26 +1191,54 @@
 /* ------------------------------------------------------------------------ */
 /* display                                                                  */
 /* ------------------------------------------------------------------------ */
-int display(enum dsp_mode display_mode, int identify_only)
+int display(int identify_only)
 {
+	uint64_t blk;
+
+	if (block == RGLIST_DUMMY_BLOCK)
+		blk = masterblock("rindex");
+	else
+		blk = block;
 	if (termlines) {
 		display_title_lines();
 		move(2,0);
 	}
-	if (block_in_mem != block) { /* If we changed blocks from the last read */
-		dev_offset = block * bufsize;
+	if (block_in_mem != blk) { /* If we changed blocks from the last read */
+		dev_offset = blk * bufsize;
 		ioctl(fd, BLKFLSBUF, 0);
 		do_lseek(fd, dev_offset);
 		do_read(fd, buf, bufsize); /* read in the desired block */
-		block_in_mem = block; /* remember which block is in memory */
+		block_in_mem = blk; /* remember which block is in memory */
 	}
 	line = 1;
 	gfs2_struct_type = display_block_type(buf);
 	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 || blk == 0x10 * (4096 / bufsize)) {
 		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 */
@@ -905,7 +1253,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;
@@ -917,16 +1266,31 @@
 				indirect[indirect_blocks].is_dir = TRUE;
 				indirect[indirect_blocks].dirents++;
 			}
+			if (de.de_rec_len <= sizeof(struct gfs2_dirent))
+				break;
 		}
 	}
-	edit_last[display_mode] = 0;
-	if (display_mode == 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          */
-		display_gfs2();                    /* display the gfs2 structure    */
-	else                                   /* otherwise                     */
-		display_extended();                /* display extended blocks       */
+	last_entry_onscreen[dmode] = 0;
+	if (dmode == EXTENDED_MODE && !block_has_extended_info())
+		dmode = HEX_MODE;
+	if (termlines) {
+		move(termlines, 63);
+		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);
+	else if (dmode == GFS2_MODE)    /* if structure display          */
+		display_gfs2();            /* display the gfs2 structure    */
+	else
+		display_extended();        /* display extended blocks       */
+	/* No else here because display_extended can switch back to hex mode */
 	if (termlines)
 		refresh();
 	return(0);
@@ -937,14 +1301,19 @@
 /* ------------------------------------------------------------------------ */
 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].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++;
 		blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
 	}
@@ -955,17 +1324,22 @@
 /* ------------------------------------------------------------------------ */
 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];
+		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];
 	}
-	return blockstack[blockhist % BLOCK_STACK_SIZE].block;
+	gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
+	return blockstack[bhst].block;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -973,16 +1347,20 @@
 /* ------------------------------------------------------------------------ */
 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 (!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"))
@@ -992,15 +1370,19 @@
 				else if (!strcmp(string, "quota"))
 					temp_blk = gfs1_quota_di.no_addr;
 			}
-			else
-				temp_blk = masterblock(string);
+			else {
+				if (!strcmp(string, "rgs"))
+					temp_blk = RGLIST_DUMMY_BLOCK;
+				else
+					temp_blk = masterblock(string);
+			}
 		}
 		else if (string[0] == '0' && string[1] == 'x')
 			sscanf(string, "%"SCNx64, &temp_blk); /* retrieve in hex */
 		else
 			sscanf(string, "%" PRIu64, &temp_blk); /* retrieve decimal */
 
-		if (temp_blk < max_block) {
+		if (temp_blk == RGLIST_DUMMY_BLOCK || temp_blk < max_block) {
 			offset = 0;
 			block = temp_blk;
 			push_block(block);
@@ -1016,22 +1398,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);  /* 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_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 {
+		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;
+		}
 	}
 }
 
@@ -1041,8 +1560,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.");
@@ -1062,240 +1579,223 @@
 	init_colors();
 	/* Accept keystrokes and act on them accordingly */
 	Quit = FALSE;
+	editing = FALSE;
 	while (!Quit) {
-		display(display_mode, FALSE);
-		while ((ch=getch()) == 0); // wait for input
+		display(FALSE);
+		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:
-			block = 0x10;
-			push_block(block);
-			offset = 0;
+			if (dmode == EXTENDED_MODE) {
+				start_row[dmode] = end_row[dmode] = 0;
+				edit_row[dmode] = 0;
+			}
+			else {
+				block = 0x10 * (4096 / bufsize);
+				push_block(block);
+				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 (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 < end_row[dmode]) {
+					if (edit_row[dmode] >= last_entry_onscreen[dmode])
+						start_row[dmode]++;
+					edit_row[dmode]++;
+				}
+			}
+			else {
+				if (edit_row[dmode] < last_entry_onscreen[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) {
-				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];
-				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 < DISPLAY_MODES; 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':
-			edit_row[display_mode] = 0;
-			if (block > 0) {
+			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.
-			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;
+			pageup();
+			break;
+		/* --------------------------------------------------------- */
+		/* end - Jump to the end of the list */
+		/* --------------------------------------------------------- */
+		case 0x168:
+			if (dmode == EXTENDED_MODE) {
+				int dsplines = termlines - 6;
+				int ents_per_screen = dsplines /
+					lines_per_row[dmode];
+
+				edit_row[dmode] = end_row[dmode] - 1;
+				if ((edit_row[dmode] - ents_per_screen)+1 > 0)
+					start_row[dmode] = edit_row[dmode] - 
+						ents_per_screen + 1;
 				else
-					offset = 0;
+					start_row[dmode] = 0;
 			}
-			else
-				offset -= screen_chunk_size;
+			/* 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]=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.
-			edit_row[display_mode] = 0;
-			if (display_mode == 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[display_mode] == -1)
-				block = goto_block();
-			else {
-				if (display_mode == HEX_MODE) {
-					left_off = ((block * bufsize) < 0xffffffff) ? 9 : 17;
-					/* 8 and 16 char addresses on screen */
-					       
-					if (bobgets(edit_string, edit_row[display_mode] + 3,
-								(edit_col[display_mode] * 2) + 
-								(edit_col[display_mode] / 4) + left_off, 2)) {
-						if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
-							int hexoffset;
-							unsigned char ch;
-							
-							hexoffset = (edit_row[display_mode] * 16) +
-								edit_col[display_mode];
-							ch = 0x00;
-							if (isdigit(edit_string[0]))
-								ch = (edit_string[0] - '0') * 0x10;
-							else if (edit_string[0] >= 'a' &&
-									 edit_string[0] <= 'f')
-								ch = (edit_string[0] - 'a' + 0x0a) * 0x10;
-							else if (edit_string[0] >= 'A' &&
-									 edit_string[0] <= 'F')
-								ch = (edit_string[0] - 'A' + 0x0a) * 0x10;
-							if (isdigit(edit_string[1]))
-								ch += (edit_string[1] - '0');
-							else if (edit_string[1] >= 'a' &&
-									 edit_string[1] <= 'f')
-								ch += (edit_string[1] - 'a' + 0x0a);
-							else if (edit_string[1] >= 'A' &&
-									 edit_string[1] <= 'F')
-								ch += (edit_string[1] - 'A' + 0x0a);
-							buf[offset + hexoffset] = ch;
-							do_lseek(fd, dev_offset);
-							do_write(fd, buf, bufsize);
-							fsync(fd);
-						}
-					}
-				}
-				else if (display_mode == GFS2_MODE)
-					bobgets(edit_string, edit_row[display_mode] + 4, 24,
-							edit_size[display_mode]);
-				else
-					bobgets(edit_string, edit_row[display_mode] + 6, 14,
-							edit_size[display_mode]);
-			}
+			editing = !editing;
 			break;
 		default:
 			move(termlines - 1, 0);
-			printw("Keystroke not understood: %02X",ch);
+			printw("Keystroke not understood: 0x%03X",ch);
 			refresh();
 			sleep(1);
 			break;
@@ -1315,6 +1815,9 @@
 	fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-p structures|blocks] /dev/device\n\n");
 	fprintf(stderr,"If only the device is specified, it enters into hexedit mode.\n");
 	fprintf(stderr,"identify - prints out only the block type, not the details.\n");
+	fprintf(stderr,"savemeta - save off your metadata for analysis and debugging.  The intelligent way (assume bitmap is correct).\n");
+	fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging.  The SLOW way (block by block).\n");
+	fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
 	fprintf(stderr,"-V   prints version number.\n");
 	fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
 	fprintf(stderr,"-p   prints GFS2 structures or blocks to stdout.\n");
@@ -1327,6 +1830,7 @@
 	fprintf(stderr,"     inum - prints the inum file.\n");
 	fprintf(stderr,"     statfs - prints the statfs file.\n");
 	fprintf(stderr,"     rindex - prints the rindex file.\n");
+	fprintf(stderr,"     rgs - prints all the resource groups (rgs).\n");
 	fprintf(stderr,"     quota - prints the quota file.\n");
 	fprintf(stderr,"-x   print in hexmode.\n");
 	fprintf(stderr,"-h   prints this help.\n\n");
@@ -1376,17 +1880,21 @@
 			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 (!strcasecmp(argv[i], "savemeta"))
+				savemeta(argv[i+1], argv[i+2], FALSE);
+			else if (!strcasecmp(argv[i], "savemetaslow"))
+				savemeta(argv[i+1], argv[i+2], TRUE);
+			else if (!strcasecmp(argv[i], "restoremeta"))
+				restoremeta(argv[i+1], argv[i+2]);
 			else if (strchr(argv[i],'/'))
 				strcpy(device, argv[i]);
 		}
 		else { /* second pass */
 			if (!termlines && !strchr(argv[i],'/')) { /* if print, no slash */
-				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"))
@@ -1396,12 +1904,16 @@
 						   max_block, max_block);
 				else if (!strcmp(argv[i], "sb") ||
 						 !strcmp(argv[i], "superblock"))
-					push_block(0x10); /* superblock */
+					push_block(0x10 * (4096 / bufsize)); /* superblock */
 				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);
@@ -1421,6 +1933,10 @@
 					else
 						push_block(masterblock("rindex"));
 				}
+				else if (!strcmp(argv[i], "rgs")) {
+					if (!gfs1)
+						push_block(RGLIST_DUMMY_BLOCK);
+				}
 				else if (!strcmp(argv[i], "quota")) {
 					if (gfs1)
 						push_block(gfs1_quota_di.no_addr);
@@ -1461,19 +1977,25 @@
 
 	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));
-	display_mode = HEX_MODE;
+	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;
 	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].end_row[j] = 0;
 			blockstack[i].edit_row[j] = 0;
 			blockstack[i].edit_col[j] = 0;
+			blockstack[i].lines_per_row[j] = 0;
 		}
 	}
 
@@ -1498,7 +2020,7 @@
 	else { /* print all the structures requested */
 		for (i = 0; i <= blockhist; i++) {
 			block = blockstack[i + 1].block;
-			display(display_mode, identify);
+			display(identify);
 			if (!identify) {
 				display_extended();
 				printf("-------------------------------------" \
--- cluster/gfs2/edit/hexedit.h	2006/11/14 20:13:36	1.4.2.2
+++ cluster/gfs2/edit/hexedit.h	2007/06/26 01:40:43	1.4.2.3
@@ -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
 
@@ -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);
@@ -76,9 +76,10 @@
 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 char edit_string[1024], edit_fmt[80];
+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_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 */
@@ -92,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;
@@ -114,9 +117,17 @@
 
 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 end_row[DMODES];
+	int lines_per_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 {
@@ -148,13 +159,21 @@
 	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
 											  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)
@@ -221,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__ */
--- cluster/gfs2/libgfs2/super.c	2007/05/01 18:20:50	1.3.2.1
+++ cluster/gfs2/libgfs2/super.c	2007/06/26 01:40:43	1.3.2.2
@@ -33,7 +33,7 @@
  *
  * Returns: 0 on success, -1 on failure
  */
-static int check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb)
+int check_sb(struct gfs2_sb *sb)
 {
 	if (sb->sb_header.mh_magic != GFS2_MAGIC ||
 	    sb->sb_header.mh_type != GFS2_METATYPE_SB) {
@@ -75,7 +75,7 @@
 	gfs2_sb_in(&sdp->sd_sb, bh->b_data);
 	brelse(bh, not_updated);
 
-	error = check_sb(sdp, &sdp->sd_sb);
+	error = check_sb(&sdp->sd_sb);
 	if (error)
 		goto out;
 



                 reply	other threads:[~2007-06-26  1:40 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070626014044.897.qmail@sourceware.org \
    --to=rpeterso@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.