Blame gfs2/edit/hexedit.c

Packit 6ef888
#include "clusterautoconfig.h"
Packit 6ef888
Packit 6ef888
#include <stdio.h>
Packit 6ef888
#include <stdlib.h>
Packit 6ef888
#include <ctype.h>
Packit 6ef888
#include <string.h>
Packit 6ef888
#include <inttypes.h>
Packit 6ef888
#include <sys/types.h>
Packit 6ef888
#include <linux/types.h>
Packit 6ef888
#include <sys/stat.h>
Packit 6ef888
#include <fcntl.h>
Packit 6ef888
#include <unistd.h>
Packit 6ef888
#include <errno.h>
Packit 6ef888
#include <curses.h>
Packit 6ef888
#include <term.h>
Packit 6ef888
#include <time.h>
Packit 6ef888
#include <signal.h>
Packit 6ef888
#include <sys/ioctl.h>
Packit 6ef888
#include <sys/mount.h>
Packit 6ef888
#include <dirent.h>
Packit 6ef888
Packit 6ef888
#include <linux/gfs2_ondisk.h>
Packit 6ef888
#include "copyright.cf"
Packit 6ef888
Packit 6ef888
#include "hexedit.h"
Packit 6ef888
#include "libgfs2.h"
Packit 6ef888
#include "gfs2hex.h"
Packit 6ef888
#include "extended.h"
Packit 6ef888
#include "journal.h"
Packit 6ef888
Packit 6ef888
const char *mtypes[] = {"none", "sb", "rg", "rb", "di", "in", "lf", "jd",
Packit 6ef888
			"lh", "ld", "ea", "ed", "lb", "13", "qc"};
Packit 6ef888
const char *allocdesc[2][5] = {
Packit 6ef888
	{"Free ", "Data ", "Unlnk", "Meta ", "Resrv"},
Packit 6ef888
	{"Free ", "Data ", "FreeM", "Meta ", "Resrv"},};
Packit 6ef888
Packit 6ef888
struct gfs2_buffer_head *bh;
Packit 6ef888
struct gfs2_rgrp *lrgrp;
Packit 6ef888
struct gfs2_meta_header *lmh;
Packit 6ef888
struct gfs2_dinode *ldi;
Packit 6ef888
struct gfs2_leaf *lleaf;
Packit 6ef888
struct gfs2_log_header *llh;
Packit 6ef888
struct gfs2_log_descriptor *lld;
Packit 6ef888
int pgnum;
Packit 6ef888
int details = 0;
Packit 6ef888
long int gziplevel = 9;
Packit 6ef888
static int termcols;
Packit 6ef888
char *device = NULL;
Packit 6ef888
extern uint64_t block;
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
/* erase - clear the screen */
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
static void Erase(void)
Packit 6ef888
{
Packit 6ef888
	bkgd(A_NORMAL|COLOR_PAIR(COLOR_NORMAL));
Packit 6ef888
	/* clear();*/ /* doesn't set background correctly */
Packit 6ef888
	erase();
Packit 6ef888
	/*bkgd(bg);*/
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
/* display_title_lines */
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
static void display_title_lines(void)
Packit 6ef888
{
Packit 6ef888
	Erase();
Packit 6ef888
	COLORS_TITLE;
Packit 6ef888
	move(0, 0);
Packit 6ef888
	printw("%-80s",TITLE1);
Packit 6ef888
	move(termlines, 0);
Packit 6ef888
	printw("%-79s",TITLE2);
Packit 6ef888
	COLORS_NORMAL;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
/* bobgets - get a string                                                    */
Packit 6ef888
/* returns: 1 if user exited by hitting enter                                */
Packit 6ef888
/*          0 if user exited by hitting escape                               */
Packit 6ef888
/* ------------------------------------------------------------------------- */
Packit 6ef888
static int bobgets(char string[],int x,int y,int sz,int *ch)
Packit 6ef888
{
Packit 6ef888
	int done,runningy,rc;
Packit 6ef888
Packit 6ef888
	move(x,y);
Packit 6ef888
	done=FALSE;
Packit 6ef888
	COLORS_INVERSE;
Packit 6ef888
	move(x,y);
Packit 6ef888
	addstr(string);
Packit 6ef888
	move(x,y);
Packit 6ef888
	curs_set(2);
Packit 6ef888
	refresh();
Packit 6ef888
	runningy=y;
Packit 6ef888
	rc=0;
Packit 6ef888
	while (!done) {
Packit 6ef888
		*ch = getch();
Packit 6ef888
		
Packit 6ef888
		if(*ch < 0x0100 && isprint(*ch)) {
Packit 6ef888
			char *p=string+strlen(string); // end of the string
Packit 6ef888
Packit 6ef888
			*(p+1)='\0';
Packit 6ef888
			while (insert && p > &string[runningy-y]) {
Packit 6ef888
				*p=*(p-1);
Packit 6ef888
				p--;
Packit 6ef888
			}
Packit 6ef888
			string[runningy-y]=*ch;
Packit 6ef888
			runningy++;
Packit 6ef888
			move(x,y);
Packit 6ef888
			addstr(string);
Packit 6ef888
			if (runningy-y >= sz) {
Packit 6ef888
				rc=1;
Packit 6ef888
				*ch = KEY_RIGHT;
Packit 6ef888
				done = TRUE;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		else {
Packit 6ef888
			// special character, is it one we recognize?
Packit 6ef888
			switch(*ch)
Packit 6ef888
			{
Packit 6ef888
			case(KEY_ENTER):
Packit 6ef888
			case('\n'):
Packit 6ef888
			case('\r'):
Packit 6ef888
				rc=1;
Packit 6ef888
				done=TRUE;
Packit 6ef888
				string[runningy-y] = '\0';
Packit 6ef888
				break;
Packit 6ef888
			case(KEY_CANCEL):
Packit 6ef888
			case(0x01B):
Packit 6ef888
				rc=0;
Packit 6ef888
				done=TRUE;
Packit 6ef888
				break;
Packit 6ef888
			case(KEY_LEFT):
Packit 6ef888
				if (dmode == HEX_MODE) {
Packit 6ef888
					done = TRUE;
Packit 6ef888
					rc = 1;
Packit 6ef888
				}
Packit 6ef888
				else
Packit 6ef888
					runningy--;
Packit 6ef888
				break;
Packit 6ef888
			case(KEY_RIGHT):
Packit 6ef888
				if (dmode == HEX_MODE) {
Packit 6ef888
					done = TRUE;
Packit 6ef888
					rc = 1;
Packit 6ef888
				}
Packit 6ef888
				else
Packit 6ef888
					runningy++;
Packit 6ef888
				break;
Packit 6ef888
			case(KEY_DC):
Packit 6ef888
			case(0x07F):
Packit 6ef888
				if (runningy>=y) {
Packit 6ef888
					char *p;
Packit 6ef888
					p = &string[runningy - y];
Packit 6ef888
					while (*p) {
Packit 6ef888
						*p = *(p + 1);
Packit 6ef888
						p++;
Packit 6ef888
					}
Packit 6ef888
					*p = '\0';
Packit 6ef888
					runningy--;
Packit 6ef888
					// remove the character from the string 
Packit 6ef888
					move(x,y);
Packit 6ef888
					addstr(string);
Packit 6ef888
					COLORS_NORMAL;
Packit 6ef888
					addstr(" ");
Packit 6ef888
					COLORS_INVERSE;
Packit 6ef888
					runningy++;
Packit 6ef888
				}
Packit 6ef888
				break;
Packit 6ef888
			case(KEY_BACKSPACE):
Packit 6ef888
				if (runningy>y) {
Packit 6ef888
					char *p;
Packit 6ef888
Packit 6ef888
					p = &string[runningy - y - 1];
Packit 6ef888
					while (*p) {
Packit 6ef888
						*p = *(p + 1);
Packit 6ef888
						p++;
Packit 6ef888
					}
Packit 6ef888
					*p='\0';
Packit 6ef888
					runningy--;
Packit 6ef888
					// remove the character from the string 
Packit 6ef888
					move(x,y);
Packit 6ef888
					addstr(string);
Packit 6ef888
					COLORS_NORMAL;
Packit 6ef888
					addstr(" ");
Packit 6ef888
					COLORS_INVERSE;
Packit 6ef888
				}
Packit 6ef888
				break;
Packit 6ef888
			case KEY_DOWN:	// Down
Packit 6ef888
				rc=0x5000U;
Packit 6ef888
				done=TRUE;
Packit 6ef888
				break;
Packit 6ef888
			case KEY_UP:	// Up
Packit 6ef888
				rc=0x4800U;
Packit 6ef888
				done=TRUE;
Packit 6ef888
				break;
Packit 6ef888
			case 0x014b:
Packit 6ef888
				insert=!insert;
Packit 6ef888
				move(0,68);
Packit 6ef888
				if (insert)
Packit 6ef888
					printw("insert ");
Packit 6ef888
				else
Packit 6ef888
					printw("replace");
Packit 6ef888
				break;
Packit 6ef888
			default:
Packit 6ef888
				move(0,70);
Packit 6ef888
				printw("%08x",*ch);
Packit 6ef888
				// ignore all other characters
Packit 6ef888
				break;
Packit 6ef888
			} // end switch on non-printable character
Packit 6ef888
		} // end non-printable character
Packit 6ef888
		move(x,runningy);
Packit 6ef888
		refresh();
Packit 6ef888
	} // while !done
Packit 6ef888
	if (sz>0)
Packit 6ef888
		string[sz]='\0';
Packit 6ef888
	COLORS_NORMAL;
Packit 6ef888
	return rc;
Packit 6ef888
}/* bobgets */
Packit 6ef888
Packit 6ef888
/******************************************************************************
Packit 6ef888
** instr - instructions
Packit 6ef888
******************************************************************************/
Packit 6ef888
static void gfs2instr(const char *s1, const char *s2)
Packit 6ef888
{
Packit 6ef888
	COLORS_HIGHLIGHT;
Packit 6ef888
	move(line,0);
Packit 6ef888
	printw(s1);
Packit 6ef888
	COLORS_NORMAL;
Packit 6ef888
	move(line,17);
Packit 6ef888
	printw(s2);
Packit 6ef888
	line++;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/******************************************************************************
Packit 6ef888
*******************************************************************************
Packit 6ef888
**
Packit 6ef888
** void print_usage()
Packit 6ef888
**
Packit 6ef888
** Description:
Packit 6ef888
**   This routine prints out the appropriate commands for this application.
Packit 6ef888
**
Packit 6ef888
*******************************************************************************
Packit 6ef888
******************************************************************************/
Packit 6ef888
Packit 6ef888
static void print_usage(void)
Packit 6ef888
{
Packit 6ef888
	int ch;
Packit 6ef888
Packit 6ef888
	line = 2;
Packit 6ef888
	Erase();
Packit 6ef888
	display_title_lines();
Packit 6ef888
	move(line++,0);
Packit 6ef888
	printw("Supported commands: (roughly conforming to the rules of 'less')");
Packit 6ef888
	line++;
Packit 6ef888
	move(line++,0);
Packit 6ef888
	printw("Navigation:");
Packit 6ef888
	gfs2instr("<pg up>/<down>","Move up or down one screen full");
Packit 6ef888
	gfs2instr("<up>/<down>","Move up or down one line");
Packit 6ef888
	gfs2instr("<left>/<right>","Move left or right one byte");
Packit 6ef888
	gfs2instr("<home>","Return to the superblock.");
Packit 6ef888
	gfs2instr("   f","Forward one 4K block");
Packit 6ef888
	gfs2instr("   b","Backward one 4K block");
Packit 6ef888
	gfs2instr("   g","Goto a given block (number, master, root, rindex, jindex, etc)");
Packit 6ef888
	gfs2instr("   j","Jump to the highlighted 64-bit block number.");
Packit 6ef888
	gfs2instr("    ","(You may also arrow up to the block number and hit enter)");
Packit 6ef888
	gfs2instr("<backspace>","Return to a previous block (a block stack is kept)");
Packit 6ef888
	gfs2instr("<space>","Jump forward to block before backspace (opposite of backspace)");
Packit 6ef888
	line++;
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	printw("Other commands:");
Packit 6ef888
	gfs2instr("   h","This Help display");
Packit 6ef888
	gfs2instr("   c","Toggle the color scheme");
Packit 6ef888
	gfs2instr("   m","Switch display mode: hex -> GFS2 structure -> Extended");
Packit 6ef888
	gfs2instr("   q","Quit (same as hitting <escape> key)");
Packit 6ef888
	gfs2instr("<enter>","Edit a value (enter to save, esc to discard)");
Packit 6ef888
	gfs2instr("       ","(Currently only works on the hex display)");
Packit 6ef888
	gfs2instr("<escape>","Quit the program");
Packit 6ef888
	line++;
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	printw("Notes: Areas shown in red are outside the bounds of the struct/file.");
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	printw("       Areas shown in blue are file contents.");
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	printw("       Characters shown in green are selected for edit on <enter>.");
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	move(line++, 0);
Packit 6ef888
	printw("Press any key to return.");
Packit 6ef888
	refresh();
Packit 6ef888
	while ((ch=getch()) == 0); // wait for input
Packit 6ef888
	Erase();
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* get_block_type                                                           */
Packit 6ef888
/* returns: metatype if block is a GFS2 structure block type                */
Packit 6ef888
/*          0 if block is not a GFS2 structure                              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
uint32_t get_block_type(const struct gfs2_buffer_head *lbh, int *structlen)
Packit 6ef888
{
Packit 6ef888
	uint32_t ty = lgfs2_get_block_type(lbh);
Packit 6ef888
Packit 6ef888
	if (ty != 0 && structlen != NULL) {
Packit 6ef888
		unsigned ver = sbd.gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2;
Packit 6ef888
		const struct lgfs2_metadata *mtype = lgfs2_find_mtype(ty, ver);
Packit 6ef888
		if (mtype != NULL)
Packit 6ef888
			*structlen = mtype->size;
Packit 6ef888
		else
Packit 6ef888
			*structlen = sbd.bsize;
Packit 6ef888
	}
Packit 6ef888
	return ty;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* display_block_type                                                       */
Packit 6ef888
/* returns: metatype if block is a GFS2 structure block type                */
Packit 6ef888
/*          0 if block is not a GFS2 structure                              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
int display_block_type(struct gfs2_buffer_head *dbh, int from_restore)
Packit 6ef888
{
Packit 6ef888
	const struct gfs2_meta_header *mh;
Packit 6ef888
	int ret_type = 0; /* return type */
Packit 6ef888
Packit 6ef888
	/* first, print out the kind of GFS2 block this is */
Packit 6ef888
	if (termlines) {
Packit 6ef888
		line = 1;
Packit 6ef888
		move(line, 0);
Packit 6ef888
	}
Packit 6ef888
	print_gfs2("Block #");
Packit 6ef888
	if (termlines) {
Packit 6ef888
		if (edit_row[dmode] == -1)
Packit 6ef888
			COLORS_HIGHLIGHT;
Packit 6ef888
	}
Packit 6ef888
	if (block == RGLIST_DUMMY_BLOCK)
Packit 6ef888
		print_gfs2("RG List       ");
Packit 6ef888
	else if (block == JOURNALS_DUMMY_BLOCK)
Packit 6ef888
		print_gfs2("Journal Status:      ");
Packit 6ef888
	else
Packit 6ef888
		print_gfs2("%"PRIu64"    (0x%"PRIx64")", dbh->b_blocknr, dbh->b_blocknr);
Packit 6ef888
	if (termlines) {
Packit 6ef888
		if (edit_row[dmode] == -1)
Packit 6ef888
			COLORS_NORMAL;
Packit 6ef888
	}
Packit 6ef888
	print_gfs2(" ");
Packit 6ef888
	if (!from_restore)
Packit 6ef888
		print_gfs2("of %"PRIu64" (0x%"PRIx64") ", max_block, max_block);
Packit 6ef888
	if (block == RGLIST_DUMMY_BLOCK) {
Packit 6ef888
		ret_type = GFS2_METATYPE_RG;
Packit 6ef888
		struct_len = sbd.gfs1 ? sizeof(struct gfs_rgrp) :
Packit 6ef888
			sizeof(struct gfs2_rgrp);
Packit 6ef888
	} else if (block == JOURNALS_DUMMY_BLOCK) {
Packit 6ef888
		ret_type = GFS2_METATYPE_DI;
Packit 6ef888
		struct_len = 0;
Packit 6ef888
	} else {
Packit 6ef888
		ret_type = get_block_type(dbh, &struct_len);
Packit 6ef888
		switch (ret_type) {
Packit 6ef888
		case GFS2_METATYPE_SB:   /* 1 */
Packit 6ef888
			print_gfs2("(superblock)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_RG:   /* 2 */
Packit 6ef888
			print_gfs2("(rsrc grp hdr)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_RB:   /* 3 */
Packit 6ef888
			print_gfs2("(rsrc grp bitblk)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_DI:   /* 4 */
Packit 6ef888
			print_gfs2("(disk inode)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_IN:   /* 5 */
Packit 6ef888
			print_gfs2("(indir blklist)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_LF:   /* 6 */
Packit 6ef888
			print_gfs2("(directory leaf)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_JD:
Packit 6ef888
			print_gfs2("(journal data)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_LH:
Packit 6ef888
			print_gfs2("(log header)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_LD:
Packit 6ef888
		 	print_gfs2("(log descriptor)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_EA:
Packit 6ef888
			print_gfs2("(extended attr hdr)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_ED:
Packit 6ef888
			print_gfs2("(extended attr data)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_LB:
Packit 6ef888
			print_gfs2("(log buffer)");
Packit 6ef888
			break;
Packit 6ef888
		case GFS2_METATYPE_QC:
Packit 6ef888
			print_gfs2("(quota change)");
Packit 6ef888
			break;
Packit 6ef888
		case 0:
Packit 6ef888
			struct_len = sbd.bsize;
Packit 6ef888
			break;
Packit 6ef888
		default:
Packit 6ef888
			print_gfs2("(wtf?)");
Packit 6ef888
			break;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	mh = dbh->iov.iov_base;
Packit 6ef888
	eol(0);
Packit 6ef888
	if (from_restore)
Packit 6ef888
		return ret_type;
Packit 6ef888
	if (termlines && dmode == HEX_MODE) {
Packit 6ef888
		int type;
Packit 6ef888
		struct rgrp_tree *rgd;
Packit 6ef888
Packit 6ef888
		rgd = gfs2_blk2rgrpd(&sbd, block);
Packit 6ef888
		if (rgd) {
Packit 6ef888
			gfs2_rgrp_read(&sbd, rgd);
Packit 6ef888
			if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG) ||
Packit 6ef888
			    (be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB))
Packit 6ef888
				type = 4;
Packit 6ef888
			else {
Packit 6ef888
				type = lgfs2_get_bitmap(&sbd, block, rgd);
Packit 6ef888
			}
Packit 6ef888
		} else
Packit 6ef888
			type = 4;
Packit 6ef888
		screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
Packit 6ef888
		if (!screen_chunk_size)
Packit 6ef888
			screen_chunk_size = 256;
Packit 6ef888
		pgnum = (offset / screen_chunk_size);
Packit 6ef888
		if (type >= 0) {
Packit 6ef888
			print_gfs2("(p.%d of %d--%s)", pgnum + 1,
Packit 6ef888
				   (sbd.bsize % screen_chunk_size) > 0 ?
Packit 6ef888
				   sbd.bsize / screen_chunk_size + 1 : sbd.bsize /
Packit 6ef888
				   screen_chunk_size, allocdesc[sbd.gfs1][type]);
Packit 6ef888
		}
Packit 6ef888
		/*eol(9);*/
Packit 6ef888
		if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG)) {
Packit 6ef888
			int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
Packit 6ef888
Packit 6ef888
			if (rgd && (ptroffset >= struct_len || pgnum)) {
Packit 6ef888
				int blknum, b, btype;
Packit 6ef888
Packit 6ef888
				blknum = pgnum * screen_chunk_size;
Packit 6ef888
				blknum += (ptroffset - struct_len);
Packit 6ef888
				blknum *= 4;
Packit 6ef888
				blknum += rgd->ri.ri_data0;
Packit 6ef888
Packit 6ef888
				print_gfs2(" blk ");
Packit 6ef888
				for (b = blknum; b < blknum + 4; b++) {
Packit 6ef888
					btype = lgfs2_get_bitmap(&sbd, b, rgd);
Packit 6ef888
					if (btype >= 0) {
Packit 6ef888
						print_gfs2("0x%x-%s  ", b,
Packit 6ef888
							   allocdesc[sbd.gfs1][btype]);
Packit 6ef888
					}
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
		} else if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB)) {
Packit 6ef888
			int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
Packit 6ef888
Packit 6ef888
			if (rgd && (ptroffset >= struct_len || pgnum)) {
Packit 6ef888
				int blknum, b, btype, rb_number;
Packit 6ef888
Packit 6ef888
				rb_number = block - rgd->ri.ri_addr;
Packit 6ef888
				blknum = 0;
Packit 6ef888
				/* count the number of bytes representing
Packit 6ef888
				   blocks prior to the displayed screen. */
Packit 6ef888
				for (b = 0; b < rb_number; b++) {
Packit 6ef888
					struct_len = (b ?
Packit 6ef888
					      sizeof(struct gfs2_meta_header) :
Packit 6ef888
					      sizeof(struct gfs2_rgrp));
Packit 6ef888
					blknum += (sbd.bsize - struct_len);
Packit 6ef888
				}
Packit 6ef888
				struct_len = sizeof(struct gfs2_meta_header);
Packit 6ef888
				/* add the number of bytes on this screen */
Packit 6ef888
				blknum += (ptroffset - struct_len);
Packit 6ef888
				/* factor in the page number */
Packit 6ef888
				blknum += pgnum * screen_chunk_size;
Packit 6ef888
				/* convert bytes to blocks */
Packit 6ef888
				blknum *= GFS2_NBBY;
Packit 6ef888
				/* add the starting offset for this rgrp */
Packit 6ef888
				blknum += rgd->ri.ri_data0;
Packit 6ef888
				print_gfs2(" blk ");
Packit 6ef888
				for (b = blknum; b < blknum + 4; b++) {
Packit 6ef888
					btype = lgfs2_get_bitmap(&sbd, b, rgd);
Packit 6ef888
					if (btype >= 0) {
Packit 6ef888
						print_gfs2("0x%x-%s  ", b,
Packit 6ef888
							   allocdesc[sbd.gfs1][btype]);
Packit 6ef888
					}
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		if (rgd)
Packit 6ef888
			gfs2_rgrp_relse(rgd);
Packit 6ef888
 	}
Packit 6ef888
	if (block == sbd.sd_sb.sb_root_dir.no_addr)
Packit 6ef888
		print_gfs2("--------------- Root directory ------------------");
Packit 6ef888
	else if (!sbd.gfs1 && block == sbd.sd_sb.sb_master_dir.no_addr)
Packit 6ef888
		print_gfs2("-------------- Master directory -----------------");
Packit 6ef888
	else if (!sbd.gfs1 && block == RGLIST_DUMMY_BLOCK)
Packit 6ef888
		print_gfs2("------------------ RG List ----------------------");
Packit 6ef888
	else if (!sbd.gfs1 && block == JOURNALS_DUMMY_BLOCK)
Packit 6ef888
		print_gfs2("-------------------- Journal List --------------------");
Packit 6ef888
	else {
Packit 6ef888
		if (sbd.gfs1) {
Packit 6ef888
			if (block == sbd1->sb_rindex_di.no_addr)
Packit 6ef888
				print_gfs2("---------------- rindex file -------------------");
Packit 6ef888
			else if (block == gfs1_quota_di.no_addr)
Packit 6ef888
				print_gfs2("---------------- Quota file --------------------");
Packit 6ef888
			else if (block == sbd1->sb_jindex_di.no_addr)
Packit 6ef888
				print_gfs2("--------------- Journal Index ------------------");
Packit 6ef888
			else if (block == gfs1_license_di.no_addr)
Packit 6ef888
				print_gfs2("--------------- License file -------------------");
Packit 6ef888
		}
Packit 6ef888
		else {
Packit 6ef888
			int d;
Packit 6ef888
Packit 6ef888
			for (d = 2; d < 8; d++) {
Packit 6ef888
				if (block == masterdir.dirent[d].block) {
Packit 6ef888
					if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
Packit 6ef888
						print_gfs2("--------------- Journal Index ------------------");
Packit 6ef888
					else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
Packit 6ef888
						print_gfs2("--------------- Per-node Dir -------------------");
Packit 6ef888
					else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
Packit 6ef888
						print_gfs2("---------------- Inum file ---------------------");
Packit 6ef888
					else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
Packit 6ef888
						print_gfs2("---------------- statfs file -------------------");
Packit 6ef888
					else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
Packit 6ef888
						print_gfs2("---------------- rindex file -------------------");
Packit 6ef888
					else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
Packit 6ef888
						print_gfs2("---------------- Quota file --------------------");
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	eol(0);
Packit 6ef888
	return ret_type;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static const struct lgfs2_metadata *find_mtype(uint32_t mtype, const unsigned versions)
Packit 6ef888
{
Packit 6ef888
	const struct lgfs2_metadata *m = lgfs2_metadata;
Packit 6ef888
	unsigned n = 0;
Packit 6ef888
Packit 6ef888
	do {
Packit 6ef888
		if ((m[n].versions & versions) && m[n].mh_type == mtype)
Packit 6ef888
			return &m[n];
Packit 6ef888
		n++;
Packit 6ef888
	} while (n < lgfs2_metadata_size);
Packit 6ef888
Packit 6ef888
	return NULL;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int get_pnum(int ptroffset)
Packit 6ef888
{
Packit 6ef888
	int pnum;
Packit 6ef888
Packit 6ef888
	pnum = pgnum * screen_chunk_size;
Packit 6ef888
	pnum += (ptroffset - struct_len);
Packit 6ef888
	pnum /= sizeof(uint64_t);
Packit 6ef888
Packit 6ef888
	return pnum;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* hexdump - hex dump the filesystem block to the screen                    */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static int hexdump(uint64_t startaddr, int len, int trunc_zeros,
Packit 6ef888
		   uint64_t flagref, uint64_t ref_blk)
Packit 6ef888
{
Packit 6ef888
	const unsigned char *pointer, *ptr2;
Packit 6ef888
	int i;
Packit 6ef888
	uint64_t l;
Packit 6ef888
	const char *lpBuffer = bh->b_data;
Packit 6ef888
	const char *zeros_strt = lpBuffer + sbd.bsize;
Packit 6ef888
	int print_field, cursor_line;
Packit 6ef888
	const uint32_t block_type = get_block_type(bh, NULL);
Packit 6ef888
	uint64_t *ref;
Packit 6ef888
	int ptroffset = 0;
Packit 6ef888
Packit 6ef888
	strcpy(edit_fmt,"%02x");
Packit 6ef888
	pointer = (unsigned char *)lpBuffer + offset;
Packit 6ef888
	ptr2 = (unsigned char *)lpBuffer + offset;
Packit 6ef888
	ref = (uint64_t *)lpBuffer + offset;
Packit 6ef888
	if (trunc_zeros) {
Packit 6ef888
		while (zeros_strt > lpBuffer && (*(zeros_strt - 1) == 0))
Packit 6ef888
			zeros_strt--;
Packit 6ef888
	}
Packit 6ef888
	l = offset;
Packit 6ef888
	print_entry_ndx = 0;
Packit 6ef888
	while (((termlines && line < termlines &&
Packit 6ef888
		 line <= ((screen_chunk_size / 16) + 2)) ||
Packit 6ef888
		(!termlines && l < len)) && l < sbd.bsize) {
Packit 6ef888
		int ptr_not_null = 0;
Packit 6ef888
Packit 6ef888
		if (termlines) {
Packit 6ef888
			move(line, 0);
Packit 6ef888
			COLORS_OFFSETS; /* cyan for offsets */
Packit 6ef888
		}
Packit 6ef888
		if (startaddr < 0xffffffff)
Packit 6ef888
			print_gfs2("%.8"PRIx64, startaddr + l);
Packit 6ef888
		else
Packit 6ef888
			print_gfs2("%.16"PRIx64, startaddr + l);
Packit 6ef888
		if (termlines) {
Packit 6ef888
			if (l < struct_len)
Packit 6ef888
				COLORS_NORMAL; /* normal part of structure */
Packit 6ef888
			else if (gfs2_struct_type == GFS2_METATYPE_DI &&
Packit 6ef888
					 l < struct_len + di.di_size)
Packit 6ef888
				COLORS_CONTENTS; /* after struct but not eof */
Packit 6ef888
			else
Packit 6ef888
				COLORS_SPECIAL; /* beyond end of the struct */
Packit 6ef888
		}
Packit 6ef888
		print_field = -1;
Packit 6ef888
		cursor_line = 0;
Packit 6ef888
		for (i = 0; i < 16; i++) { /* first print it in hex */
Packit 6ef888
			/* Figure out if we have a null pointer--for colors */
Packit 6ef888
			if (((gfs2_struct_type == GFS2_METATYPE_IN) ||
Packit 6ef888
			     (gfs2_struct_type == GFS2_METATYPE_DI &&
Packit 6ef888
			      l < struct_len + di.di_size &&
Packit 6ef888
			      (di.di_height > 0 || !S_ISREG(di.di_mode)))) &&
Packit 6ef888
			    (i==0 || i==8)) {
Packit 6ef888
				int j;
Packit 6ef888
Packit 6ef888
				ptr_not_null = 0;
Packit 6ef888
				for (j = 0; j < 8; j++) {
Packit 6ef888
					if (*(pointer + j)) {
Packit 6ef888
						ptr_not_null = 1;
Packit 6ef888
						break;
Packit 6ef888
					}
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
			if (termlines) {
Packit 6ef888
				if (l + i < struct_len)
Packit 6ef888
					COLORS_NORMAL; /* in the structure */
Packit 6ef888
				else if (gfs2_struct_type == GFS2_METATYPE_DI
Packit 6ef888
					 && l + i < struct_len + di.di_size) {
Packit 6ef888
					if ((!di.di_height &&
Packit 6ef888
					     S_ISREG(di.di_mode)) ||
Packit 6ef888
					    !ptr_not_null)
Packit 6ef888
						COLORS_CONTENTS;/*stuff data */
Packit 6ef888
					else
Packit 6ef888
						COLORS_SPECIAL;/* non-null */
Packit 6ef888
				}
Packit 6ef888
				else if (gfs2_struct_type == GFS2_METATYPE_IN){
Packit 6ef888
					if (ptr_not_null)
Packit 6ef888
						COLORS_SPECIAL;/* non-null */
Packit 6ef888
					else
Packit 6ef888
						COLORS_CONTENTS;/* null */
Packit 6ef888
				} else
Packit 6ef888
					COLORS_SPECIAL; /* past the struct */
Packit 6ef888
			}
Packit 6ef888
			if (i%4 == 0)
Packit 6ef888
				print_gfs2(" ");
Packit 6ef888
			if (termlines && line == edit_row[dmode] + 3 &&
Packit 6ef888
				i == edit_col[dmode]) {
Packit 6ef888
				COLORS_HIGHLIGHT; /* in the structure */
Packit 6ef888
				memset(estring,0,3);
Packit 6ef888
				sprintf(estring,"%02x",*pointer);
Packit 6ef888
				cursor_line = 1;
Packit 6ef888
				print_field = (char *)pointer - bh->b_data;
Packit 6ef888
			}
Packit 6ef888
			print_gfs2("%02x",*pointer);
Packit 6ef888
			if (termlines && line == edit_row[dmode] + 3 &&
Packit 6ef888
				i == edit_col[dmode]) {
Packit 6ef888
				if (l < struct_len + offset)
Packit 6ef888
					COLORS_NORMAL; /* in the structure */
Packit 6ef888
				else
Packit 6ef888
					COLORS_SPECIAL; /* beyond structure */
Packit 6ef888
			}
Packit 6ef888
			pointer++;
Packit 6ef888
		}
Packit 6ef888
		print_gfs2(" [");
Packit 6ef888
		for (i=0; i<16; i++) { /* now print it in character format */
Packit 6ef888
			if ((*ptr2 >=' ') && (*ptr2 <= '~'))
Packit 6ef888
				print_gfs2("%c",*ptr2);
Packit 6ef888
			else
Packit 6ef888
				print_gfs2(".");
Packit 6ef888
			ptr2++;
Packit 6ef888
		}
Packit 6ef888
		print_gfs2("] ");
Packit 6ef888
		if (print_field >= 0) {
Packit 6ef888
			const struct lgfs2_metadata *m = find_mtype(block_type,
Packit 6ef888
			               sbd.gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2);
Packit 6ef888
			if (m) {
Packit 6ef888
				const struct lgfs2_metafield *f;
Packit 6ef888
				unsigned n;
Packit 6ef888
				for (n = 0; n < m->nfields; n++) {
Packit 6ef888
					f = &m->fields[n];
Packit 6ef888
					if (print_field >= f->offset &&
Packit 6ef888
					    print_field < (f->offset + f->length)) {
Packit 6ef888
						print_gfs2("%s", m->fields[n].name);
Packit 6ef888
						break;
Packit 6ef888
					}
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
Packit 6ef888
		}
Packit 6ef888
		if (cursor_line) {
Packit 6ef888
			if (block_type == GFS2_METATYPE_IN ||
Packit 6ef888
			    block_type == GFS2_METATYPE_LD ||
Packit 6ef888
			    ((block_type == GFS2_METATYPE_DI) &&
Packit 6ef888
			     ((struct gfs2_dinode*)bh->b_data)->di_height) ||
Packit 6ef888
			     S_ISDIR(di.di_mode)) {
Packit 6ef888
				ptroffset = edit_row[dmode] * 16 +
Packit 6ef888
					edit_col[dmode];
Packit 6ef888
Packit 6ef888
				if (ptroffset >= struct_len || pgnum) {
Packit 6ef888
					int pnum = get_pnum(ptroffset);
Packit 6ef888
					if (block_type == GFS2_METATYPE_LD)
Packit 6ef888
						print_gfs2("*");
Packit 6ef888
					print_gfs2("pointer 0x%x", pnum);
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		if (line - 3 > last_entry_onscreen[dmode])
Packit 6ef888
			last_entry_onscreen[dmode] = line - 3;
Packit 6ef888
		if (flagref && be64_to_cpu(*ref) == flagref)
Packit 6ef888
			print_gfs2("<------------------------- ref in 0x%"PRIx64" "
Packit 6ef888
				   "to 0x%"PRIx64, ref_blk, flagref);
Packit 6ef888
		ref++;
Packit 6ef888
		if (flagref && be64_to_cpu(*ref) == flagref)
Packit 6ef888
			print_gfs2("<------------------------- ref in 0x%"PRIx64" "
Packit 6ef888
				   "to 0x%"PRIx64, ref_blk, flagref);
Packit 6ef888
		ref++;
Packit 6ef888
		eol(0);
Packit 6ef888
		l += 16;
Packit 6ef888
		print_entry_ndx++;
Packit 6ef888
		/* This should only happen if trunc_zeros is specified: */
Packit 6ef888
		if ((const char *)pointer >= zeros_strt)
Packit 6ef888
			break;
Packit 6ef888
	} /* while */
Packit 6ef888
	if (block_type == GFS2_METATYPE_LD && ptroffset >= struct_len) {
Packit 6ef888
		COLORS_NORMAL;
Packit 6ef888
		eol(0);
Packit 6ef888
		print_gfs2("         * 'j' will jump to the journaled block, "
Packit 6ef888
			   "not the absolute block.");
Packit 6ef888
		eol(0);
Packit 6ef888
	}
Packit 6ef888
	if (sbd.gfs1) {
Packit 6ef888
		COLORS_NORMAL;
Packit 6ef888
		print_gfs2("         *** This seems to be a GFS-1 file system ***");
Packit 6ef888
		eol(0);
Packit 6ef888
	}
Packit 6ef888
	return (offset+len);
Packit 6ef888
}/* hexdump */
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* masterblock - find a file (by name) in the master directory and return   */
Packit 6ef888
/*               its block number.                                          */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
uint64_t masterblock(const char *fn)
Packit 6ef888
{
Packit 6ef888
	int d;
Packit 6ef888
	
Packit 6ef888
	for (d = 2; d < 8; d++)
Packit 6ef888
		if (!strncmp(masterdir.dirent[d].filename, fn, strlen(fn)))
Packit 6ef888
			return (masterdir.dirent[d].block);
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* rgcount - return how many rgrps there are.                               */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void rgcount(void)
Packit 6ef888
{
Packit 6ef888
	printf("%lld RGs in this file system.\n",
Packit 6ef888
	       (unsigned long long)sbd.md.riinode->i_di.di_size /
Packit 6ef888
	       sizeof(struct gfs2_rindex));
Packit 6ef888
	inode_put(&sbd.md.riinode);
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	exit(EXIT_SUCCESS);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* find_rgrp_block - locate the block for a given rgrp number               */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t find_rgrp_block(struct gfs2_inode *dif, int rg)
Packit 6ef888
{
Packit 6ef888
	int amt;
Packit 6ef888
	struct gfs2_rindex fbuf, ri;
Packit 6ef888
	uint64_t foffset, gfs1_adj = 0;
Packit 6ef888
Packit 6ef888
	foffset = rg * sizeof(struct gfs2_rindex);
Packit 6ef888
	if (sbd.gfs1) {
Packit 6ef888
		uint64_t sd_jbsize =
Packit 6ef888
			(sbd.bsize - sizeof(struct gfs2_meta_header));
Packit 6ef888
Packit 6ef888
		gfs1_adj = (foffset / sd_jbsize) *
Packit 6ef888
			sizeof(struct gfs2_meta_header);
Packit 6ef888
		gfs1_adj += sizeof(struct gfs2_meta_header);
Packit 6ef888
	}
Packit 6ef888
	amt = gfs2_readi(dif, (void *)&fbuf, foffset + gfs1_adj,
Packit 6ef888
			 sizeof(struct gfs2_rindex));
Packit 6ef888
	if (!amt) /* end of file */
Packit 6ef888
		return 0;
Packit 6ef888
	gfs2_rindex_in(&ri, (void *)&fbuf);
Packit 6ef888
	return ri.ri_addr;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* gfs_rgrp_print - print a gfs1 resource group                             */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
void gfs_rgrp_print(struct gfs_rgrp *rg)
Packit 6ef888
{
Packit 6ef888
	gfs2_meta_header_print(&rg->rg_header);
Packit 6ef888
	pv(rg, rg_flags, "%u", "0x%x");
Packit 6ef888
	pv(rg, rg_free, "%u", "0x%x");
Packit 6ef888
	pv(rg, rg_useddi, "%u", "0x%x");
Packit 6ef888
	pv(rg, rg_freedi, "%u", "0x%x");
Packit 6ef888
	gfs2_inum_print(&rg->rg_freedi_list);
Packit 6ef888
	pv(rg, rg_usedmeta, "%u", "0x%x");
Packit 6ef888
	pv(rg, rg_freemeta, "%u", "0x%x");
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* get_rg_addr                                                              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t get_rg_addr(int rgnum)
Packit 6ef888
{
Packit 6ef888
	uint64_t rgblk = 0, gblock;
Packit 6ef888
	struct gfs2_inode *riinode;
Packit 6ef888
Packit 6ef888
	if (sbd.gfs1)
Packit 6ef888
		gblock = sbd1->sb_rindex_di.no_addr;
Packit 6ef888
	else
Packit 6ef888
		gblock = masterblock("rindex");
Packit 6ef888
	riinode = lgfs2_inode_read(&sbd, gblock);
Packit 6ef888
	if (riinode == NULL)
Packit 6ef888
		return 0;
Packit 6ef888
	if (rgnum < riinode->i_di.di_size / sizeof(struct gfs2_rindex))
Packit 6ef888
		rgblk = find_rgrp_block(riinode, rgnum);
Packit 6ef888
	else
Packit 6ef888
		fprintf(stderr, "Error: File system only has %lld RGs.\n",
Packit 6ef888
			(unsigned long long)riinode->i_di.di_size /
Packit 6ef888
			sizeof(struct gfs2_rindex));
Packit 6ef888
	inode_put(&riinode);
Packit 6ef888
	return rgblk;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* set_rgrp_flags - Set an rgrp's flags to a given value                    */
Packit 6ef888
/* rgnum: which rg to print or modify flags for (0 - X)                     */
Packit 6ef888
/* new_flags: value to set new rg_flags to (if modify == TRUE)              */
Packit 6ef888
/* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
Packit 6ef888
/* full: TRUE if the full RG should be printed.                             */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
Packit 6ef888
{
Packit 6ef888
	union {
Packit 6ef888
		struct gfs2_rgrp rg2;
Packit 6ef888
		struct gfs_rgrp rg1;
Packit 6ef888
	} rg;
Packit 6ef888
	struct gfs2_buffer_head *rbh;
Packit 6ef888
	uint64_t rgblk;
Packit 6ef888
Packit 6ef888
	rgblk = get_rg_addr(rgnum);
Packit 6ef888
	rbh = bread(&sbd, rgblk);
Packit 6ef888
	if (sbd.gfs1)
Packit 6ef888
		gfs_rgrp_in(&rg.rg1, rbh);
Packit 6ef888
	else
Packit 6ef888
		gfs2_rgrp_in(&rg.rg2, rbh->b_data);
Packit 6ef888
	if (modify) {
Packit 6ef888
		printf("RG #%d (block %llu / 0x%llx) rg_flags changed from 0x%08x to 0x%08x\n",
Packit 6ef888
		       rgnum, (unsigned long long)rgblk,
Packit 6ef888
		       (unsigned long long)rgblk, rg.rg2.rg_flags, new_flags);
Packit 6ef888
		rg.rg2.rg_flags = new_flags;
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			gfs_rgrp_out(&rg.rg1, rbh);
Packit 6ef888
		else
Packit 6ef888
			gfs2_rgrp_out(&rg.rg2, rbh->b_data);
Packit 6ef888
		bmodified(rbh);
Packit 6ef888
		brelse(rbh);
Packit 6ef888
	} else {
Packit 6ef888
		if (full) {
Packit 6ef888
			print_gfs2("RG #%d", rgnum);
Packit 6ef888
			print_gfs2(" located at: %"PRIu64" (0x%"PRIx64")", rgblk, rgblk);
Packit 6ef888
                        eol(0);
Packit 6ef888
			if (sbd.gfs1)
Packit 6ef888
				gfs_rgrp_print(&rg.rg1);
Packit 6ef888
			else
Packit 6ef888
				gfs2_rgrp_print(&rg.rg2);
Packit 6ef888
		}
Packit 6ef888
		else
Packit 6ef888
			printf("RG #%d (block %llu / 0x%llx) rg_flags = 0x%08x\n",
Packit 6ef888
			       rgnum, (unsigned long long)rgblk,
Packit 6ef888
			       (unsigned long long)rgblk, rg.rg2.rg_flags);
Packit 6ef888
		brelse(rbh);
Packit 6ef888
	}
Packit 6ef888
	if (modify)
Packit 6ef888
		fsync(sbd.device_fd);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* has_indirect_blocks                                                      */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
int has_indirect_blocks(void)
Packit 6ef888
{
Packit 6ef888
	if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB ||
Packit 6ef888
	    gfs2_struct_type == GFS2_METATYPE_LF ||
Packit 6ef888
	    (gfs2_struct_type == GFS2_METATYPE_DI &&
Packit 6ef888
	     (S_ISDIR(di.di_mode) || (sbd.gfs1 && di.__pad1 == GFS_FILE_DIR))))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_rindex(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if ((sbd.gfs1 && blk == sbd1->sb_rindex_di.no_addr) ||
Packit 6ef888
	    (blk == masterblock("rindex")))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_jindex(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if ((sbd.gfs1 && blk == sbd1->sb_jindex_di.no_addr))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_inum_file(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if (!sbd.gfs1 && blk == masterblock("inum"))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_statfs_file(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if (sbd.gfs1 && blk == gfs1_license_di.no_addr)
Packit 6ef888
		return TRUE;
Packit 6ef888
	if (!sbd.gfs1 && blk == masterblock("statfs"))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_quota_file(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if (sbd.gfs1 && blk == gfs1_quota_di.no_addr)
Packit 6ef888
		return TRUE;
Packit 6ef888
	if (!sbd.gfs1 && blk == masterblock("quota"))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int block_is_per_node(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	if (!sbd.gfs1 && blk == masterblock("per_node"))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* block_has_extended_info                                                  */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static int block_has_extended_info(void)
Packit 6ef888
{
Packit 6ef888
	if (has_indirect_blocks() ||
Packit 6ef888
	    block_is_rindex(block) ||
Packit 6ef888
	    block_is_rgtree(block) ||
Packit 6ef888
	    block_is_journals(block) ||
Packit 6ef888
	    block_is_jindex(block) ||
Packit 6ef888
	    block_is_inum_file(block) ||
Packit 6ef888
	    block_is_statfs_file(block) ||
Packit 6ef888
	    block_is_quota_file(block))
Packit 6ef888
		return TRUE;
Packit 6ef888
	return FALSE;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void read_superblock(int fd)
Packit 6ef888
{
Packit 6ef888
	sbd1 = (struct gfs_sb *)&sbd.sd_sb;
Packit 6ef888
	ioctl(fd, BLKFLSBUF, 0);
Packit 6ef888
	memset(&sbd, 0, sizeof(struct gfs2_sbd));
Packit 6ef888
	sbd.bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
	sbd.device_fd = fd;
Packit 6ef888
	bh = bread(&sbd, 0x10);
Packit 6ef888
	sbd.jsize = GFS2_DEFAULT_JSIZE;
Packit 6ef888
	sbd.rgsize = GFS2_DEFAULT_RGSIZE;
Packit 6ef888
	sbd.qcsize = GFS2_DEFAULT_QCSIZE;
Packit 6ef888
	sbd.time = time(NULL);
Packit 6ef888
	sbd.rgtree.osi_node = NULL;
Packit 6ef888
	gfs2_sb_in(&sbd.sd_sb, bh->b_data);
Packit 6ef888
	/* Check to see if this is really gfs1 */
Packit 6ef888
	if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
Packit 6ef888
		sbd1->sb_header.mh_type == GFS_METATYPE_SB &&
Packit 6ef888
		sbd1->sb_header.mh_format == GFS_FORMAT_SB &&
Packit 6ef888
		sbd1->sb_multihost_format == GFS_FORMAT_MULTI) {
Packit 6ef888
		struct gfs_sb *sbbuf = (struct gfs_sb *)bh->b_data;
Packit 6ef888
Packit 6ef888
		sbd.gfs1 = TRUE;
Packit 6ef888
		sbd1->sb_flags = be32_to_cpu(sbbuf->sb_flags);
Packit 6ef888
		sbd1->sb_seg_size = be32_to_cpu(sbbuf->sb_seg_size);
Packit 6ef888
		gfs2_inum_in(&sbd1->sb_rindex_di, (void *)&sbbuf->sb_rindex_di);
Packit 6ef888
		gfs2_inum_in(&gfs1_quota_di, (void *)&sbbuf->sb_quota_di);
Packit 6ef888
		gfs2_inum_in(&gfs1_license_di, (void *)&sbbuf->sb_license_di);
Packit 6ef888
	}
Packit 6ef888
	else
Packit 6ef888
		sbd.gfs1 = FALSE;
Packit 6ef888
	sbd.bsize = sbd.sd_sb.sb_bsize;
Packit 6ef888
	if (!sbd.bsize)
Packit 6ef888
		sbd.bsize = GFS2_DEFAULT_BSIZE;
Packit 6ef888
	if (lgfs2_get_dev_info(fd, &sbd.dinfo)) {
Packit 6ef888
		perror(device);
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	if(compute_constants(&sbd)) {
Packit 6ef888
		fprintf(stderr, "Failed to compute constants.\n");
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	if (sbd.gfs1 || (sbd.sd_sb.sb_header.mh_magic == GFS2_MAGIC &&
Packit 6ef888
		     sbd.sd_sb.sb_header.mh_type == GFS2_METATYPE_SB))
Packit 6ef888
		block = 0x10 * (GFS2_DEFAULT_BSIZE / sbd.bsize);
Packit 6ef888
	else {
Packit 6ef888
		block = starting_blk = 0;
Packit 6ef888
	}
Packit 6ef888
	fix_device_geometry(&sbd;;
Packit 6ef888
	if(sbd.gfs1) {
Packit 6ef888
		sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs_indirect)) /
Packit 6ef888
			sizeof(uint64_t);
Packit 6ef888
		sbd.sd_diptrs = (sbd.bsize - sizeof(struct gfs_dinode)) /
Packit 6ef888
			sizeof(uint64_t);
Packit 6ef888
		sbd.md.riinode = lgfs2_inode_read(&sbd, sbd1->sb_rindex_di.no_addr);
Packit 6ef888
	} else {
Packit 6ef888
		sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs2_meta_header)) /
Packit 6ef888
			sizeof(uint64_t);
Packit 6ef888
		sbd.sd_diptrs = (sbd.bsize - sizeof(struct gfs2_dinode)) /
Packit 6ef888
			sizeof(uint64_t);
Packit 6ef888
		sbd.master_dir = lgfs2_inode_read(&sbd,
Packit 6ef888
					    sbd.sd_sb.sb_master_dir.no_addr);
Packit 6ef888
		if (sbd.master_dir == NULL) {
Packit 6ef888
			sbd.md.riinode = NULL;
Packit 6ef888
		} else {
Packit 6ef888
			gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	brelse(bh);
Packit 6ef888
	bh = NULL;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int read_rindex(void)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_rindex *ri;
Packit 6ef888
	uint64_t count;
Packit 6ef888
	int sane;
Packit 6ef888
Packit 6ef888
	sbd.fssize = sbd.device.length;
Packit 6ef888
	if (sbd.md.riinode) /* If we found the rindex */
Packit 6ef888
		rindex_read(&sbd, 0, &count, &sane);
Packit 6ef888
Packit 6ef888
	if (!OSI_EMPTY_ROOT(&sbd.rgtree)) {
Packit 6ef888
		ri = &((struct rgrp_tree *)osi_last(&sbd.rgtree))->ri;
Packit 6ef888
		sbd.fssize = ri->ri_data0 + ri->ri_data;
Packit 6ef888
	}
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int read_master_dir(void)
Packit 6ef888
{
Packit 6ef888
	ioctl(sbd.device_fd, BLKFLSBUF, 0);
Packit 6ef888
Packit 6ef888
	bh = bread(&sbd, sbd.sd_sb.sb_master_dir.no_addr);
Packit 6ef888
	if (bh == NULL)
Packit 6ef888
		return 1;
Packit 6ef888
	gfs2_dinode_in(&di, bh->b_data);
Packit 6ef888
	do_dinode_extended(&di, bh); /* get extended data, if any */
Packit 6ef888
	memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
Packit 6ef888
	return 0;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
int display(int identify_only, int trunc_zeros, uint64_t flagref,
Packit 6ef888
	    uint64_t ref_blk)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk;
Packit 6ef888
Packit 6ef888
	if (block == RGLIST_DUMMY_BLOCK) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = sbd1->sb_rindex_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("rindex");
Packit 6ef888
	} else if (block == JOURNALS_DUMMY_BLOCK) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = sbd1->sb_jindex_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("jindex");
Packit 6ef888
	} else
Packit 6ef888
		blk = block;
Packit 6ef888
	if (termlines) {
Packit 6ef888
		display_title_lines();
Packit 6ef888
		move(2,0);
Packit 6ef888
	}
Packit 6ef888
	if (bh == NULL || bh->b_blocknr != blk) { /* If we changed blocks from the last read */
Packit 6ef888
		if (bh != NULL)
Packit 6ef888
			brelse(bh);
Packit 6ef888
		dev_offset = blk * sbd.bsize;
Packit 6ef888
		ioctl(sbd.device_fd, BLKFLSBUF, 0);
Packit 6ef888
		if (!(bh = bread(&sbd, blk))) {
Packit 6ef888
			fprintf(stderr, "read error: %s from %s:%d: "
Packit 6ef888
				"offset %lld (0x%llx)\n",
Packit 6ef888
				strerror(errno), __FUNCTION__, __LINE__,
Packit 6ef888
				(unsigned long long)dev_offset,
Packit 6ef888
				(unsigned long long)dev_offset);
Packit 6ef888
			exit(-1);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	line = 1;
Packit 6ef888
	gfs2_struct_type = display_block_type(bh, FALSE);
Packit 6ef888
	if (identify_only)
Packit 6ef888
		return 0;
Packit 6ef888
	indirect_blocks = 0;
Packit 6ef888
	lines_per_row[dmode] = 1;
Packit 6ef888
	if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / sbd.bsize)) {
Packit 6ef888
		gfs2_sb_in(&sbd.sd_sb, bh->b_data);
Packit 6ef888
		memset(indirect, 0, sizeof(struct iinfo));
Packit 6ef888
		indirect->ii[0].block = sbd.sd_sb.sb_master_dir.no_addr;
Packit 6ef888
		indirect->ii[0].is_dir = TRUE;
Packit 6ef888
		indirect->ii[0].dirents = 2;
Packit 6ef888
Packit 6ef888
		memcpy(&indirect->ii[0].dirent[0].filename, "root", 4);
Packit 6ef888
		indirect->ii[0].dirent[0].dirent.de_inum.no_formal_ino =
Packit 6ef888
			sbd.sd_sb.sb_root_dir.no_formal_ino;
Packit 6ef888
		indirect->ii[0].dirent[0].dirent.de_inum.no_addr =
Packit 6ef888
			sbd.sd_sb.sb_root_dir.no_addr;
Packit 6ef888
		indirect->ii[0].dirent[0].block = sbd.sd_sb.sb_root_dir.no_addr;
Packit 6ef888
		indirect->ii[0].dirent[0].dirent.de_type = DT_DIR;
Packit 6ef888
Packit 6ef888
		memcpy(&indirect->ii[0].dirent[1].filename, "master", 7);
Packit 6ef888
		indirect->ii[0].dirent[1].dirent.de_inum.no_formal_ino = 
Packit 6ef888
			sbd.sd_sb.sb_master_dir.no_formal_ino;
Packit 6ef888
		indirect->ii[0].dirent[1].dirent.de_inum.no_addr =
Packit 6ef888
			sbd.sd_sb.sb_master_dir.no_addr;
Packit 6ef888
		indirect->ii[0].dirent[1].block = sbd.sd_sb.sb_master_dir.no_addr;
Packit 6ef888
		indirect->ii[0].dirent[1].dirent.de_type = DT_DIR;
Packit 6ef888
	}
Packit 6ef888
	else if (gfs2_struct_type == GFS2_METATYPE_DI) {
Packit 6ef888
		gfs2_dinode_in(&di, bh->b_data);
Packit 6ef888
		do_dinode_extended(&di, bh); /* get extended data, if any */
Packit 6ef888
	}
Packit 6ef888
	else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
Packit 6ef888
		if (blockhist) {
Packit 6ef888
			int i;
Packit 6ef888
Packit 6ef888
			for (i = 0; i < 512; i++)
Packit 6ef888
				memcpy(&indirect->ii[i].mp,
Packit 6ef888
				       &blockstack[blockhist - 1].mp,
Packit 6ef888
				       sizeof(struct metapath));
Packit 6ef888
		}
Packit 6ef888
		indirect_blocks = do_indirect_extended(bh->b_data, indirect);
Packit 6ef888
	}
Packit 6ef888
	else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
Packit 6ef888
		do_leaf_extended(bh->b_data, indirect);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	last_entry_onscreen[dmode] = 0;
Packit 6ef888
	if (dmode == EXTENDED_MODE && !block_has_extended_info())
Packit 6ef888
		dmode = HEX_MODE;
Packit 6ef888
	if (termlines) {
Packit 6ef888
		move(termlines, 63);
Packit 6ef888
		if (dmode==HEX_MODE)
Packit 6ef888
			printw("Mode: Hex %s", (editing?"edit ":"view "));
Packit 6ef888
		else
Packit 6ef888
			printw("Mode: %s", (dmode==GFS2_MODE?"Structure":
Packit 6ef888
					    "Pointers "));
Packit 6ef888
		move(line, 0);
Packit 6ef888
	}
Packit 6ef888
	if (dmode == HEX_MODE)          /* if hex display mode           */
Packit 6ef888
		hexdump(dev_offset, (gfs2_struct_type == GFS2_METATYPE_DI)?
Packit 6ef888
		        struct_len + di.di_size:sbd.bsize, trunc_zeros,
Packit 6ef888
		        flagref, ref_blk);
Packit 6ef888
	else if (dmode == GFS2_MODE) { /* if structure display */
Packit 6ef888
		if (block != JOURNALS_DUMMY_BLOCK)
Packit 6ef888
			display_gfs2(bh);  /* display the gfs2 structure */
Packit 6ef888
	} else
Packit 6ef888
		display_extended();        /* display extended blocks       */
Packit 6ef888
	/* No else here because display_extended can switch back to hex mode */
Packit 6ef888
	if (termlines)
Packit 6ef888
		refresh();
Packit 6ef888
	return(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* push_block - push a block onto the block stack                           */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void push_block(uint64_t blk)
Packit 6ef888
{
Packit 6ef888
	int i, bhst;
Packit 6ef888
Packit 6ef888
	bhst = blockhist % BLOCK_STACK_SIZE;
Packit 6ef888
	if (blk) {
Packit 6ef888
		blockstack[bhst].dmode = dmode;
Packit 6ef888
		for (i = 0; i < DMODES; i++) {
Packit 6ef888
			blockstack[bhst].start_row[i] = start_row[i];
Packit 6ef888
			blockstack[bhst].end_row[i] = end_row[i];
Packit 6ef888
			blockstack[bhst].edit_row[i] = edit_row[i];
Packit 6ef888
			blockstack[bhst].edit_col[i] = edit_col[i];
Packit 6ef888
			blockstack[bhst].lines_per_row[i] = lines_per_row[i];
Packit 6ef888
		}
Packit 6ef888
		blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
Packit 6ef888
		if (edit_row[dmode] >= 0 && !block_is_rindex(block))
Packit 6ef888
			memcpy(&blockstack[bhst].mp,
Packit 6ef888
			       &indirect->ii[edit_row[dmode]].mp,
Packit 6ef888
			       sizeof(struct metapath));
Packit 6ef888
		blockhist++;
Packit 6ef888
		blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* pop_block - pop a block off the block stack                              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t pop_block(void)
Packit 6ef888
{
Packit 6ef888
	int i, bhst;
Packit 6ef888
Packit 6ef888
	if (!blockhist)
Packit 6ef888
		return block;
Packit 6ef888
	blockhist--;
Packit 6ef888
	bhst = blockhist % BLOCK_STACK_SIZE;
Packit 6ef888
	dmode = blockstack[bhst].dmode;
Packit 6ef888
	for (i = 0; i < DMODES; i++) {
Packit 6ef888
		start_row[i] = blockstack[bhst].start_row[i];
Packit 6ef888
		end_row[i] = blockstack[bhst].end_row[i];
Packit 6ef888
		edit_row[i] = blockstack[bhst].edit_row[i];
Packit 6ef888
		edit_col[i] = blockstack[bhst].edit_col[i];
Packit 6ef888
		lines_per_row[i] = blockstack[bhst].lines_per_row[i];
Packit 6ef888
	}
Packit 6ef888
	gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
Packit 6ef888
	return blockstack[bhst].block;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* Find next metadata block of a given type AFTER a given point in the fs   */
Packit 6ef888
/*                                                                          */
Packit 6ef888
/* This is used to find blocks that aren't represented in the bitmaps, such */
Packit 6ef888
/* as the RGs and bitmaps or the superblock.                                */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int print)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk, last_fs_block;
Packit 6ef888
	int found = 0;
Packit 6ef888
	struct gfs2_buffer_head *lbh;
Packit 6ef888
Packit 6ef888
	last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / sbd.bsize;
Packit 6ef888
	for (blk = startblk + 1; blk < last_fs_block; blk++) {
Packit 6ef888
		lbh = bread(&sbd, blk);
Packit 6ef888
		/* Can't use get_block_type here (returns false "none") */
Packit 6ef888
		if (lbh->b_data[0] == 0x01 && lbh->b_data[1] == 0x16 &&
Packit 6ef888
		    lbh->b_data[2] == 0x19 && lbh->b_data[3] == 0x70 &&
Packit 6ef888
		    lbh->b_data[4] == 0x00 && lbh->b_data[5] == 0x00 &&
Packit 6ef888
		    lbh->b_data[6] == 0x00 && lbh->b_data[7] == metatype) {
Packit 6ef888
			found = 1;
Packit 6ef888
			brelse(lbh);
Packit 6ef888
			break;
Packit 6ef888
		}
Packit 6ef888
		brelse(lbh);
Packit 6ef888
	}
Packit 6ef888
	if (!found)
Packit 6ef888
		blk = 0;
Packit 6ef888
	if (print) {
Packit 6ef888
		if (dmode == HEX_MODE)
Packit 6ef888
			printf("0x%llx\n", (unsigned long long)blk);
Packit 6ef888
		else
Packit 6ef888
			printf("%llu\n", (unsigned long long)blk);
Packit 6ef888
	}
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	if (print)
Packit 6ef888
		exit(0);
Packit 6ef888
	return blk;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int find_rg_metatype(struct rgrp_tree *rgd, uint64_t *blk, uint64_t startblk, int mtype)
Packit 6ef888
{
Packit 6ef888
	int found;
Packit 6ef888
	unsigned i, j, m;
Packit 6ef888
	struct gfs2_buffer_head *bhp = NULL;
Packit 6ef888
	uint64_t *ibuf = malloc(sbd.bsize * GFS2_NBBY * sizeof(uint64_t));
Packit 6ef888
Packit 6ef888
	for (i = 0; i < rgd->ri.ri_length; i++) {
Packit 6ef888
		m = lgfs2_bm_scan(rgd, i, ibuf, GFS2_BLKST_DINODE);
Packit 6ef888
Packit 6ef888
		for (j = 0; j < m; j++) {
Packit 6ef888
			*blk = ibuf[j];
Packit 6ef888
			bhp = bread(&sbd, *blk);
Packit 6ef888
			found = (*blk > startblk) && !gfs2_check_meta(bhp, mtype);
Packit 6ef888
			brelse(bhp);
Packit 6ef888
			if (found) {
Packit 6ef888
				free(ibuf);
Packit 6ef888
				return 0;
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	free(ibuf);
Packit 6ef888
	return -1;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* Find next "metadata in use" block AFTER a given point in the fs          */
Packit 6ef888
/*                                                                          */
Packit 6ef888
/* This version does its magic by searching the bitmaps of the RG.  After   */
Packit 6ef888
/* all, if we're searching for a dinode, we want a real allocated inode,    */
Packit 6ef888
/* not just some block that used to be an inode in a previous incarnation.  */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int print)
Packit 6ef888
{
Packit 6ef888
	struct osi_node *next = NULL;
Packit 6ef888
	uint64_t blk, errblk;
Packit 6ef888
	int first = 1, found = 0;
Packit 6ef888
	struct rgrp_tree *rgd = NULL;
Packit 6ef888
	struct gfs2_rindex *ri;
Packit 6ef888
Packit 6ef888
	blk = 0;
Packit 6ef888
	/* Skip the rgs prior to the block we've been given */
Packit 6ef888
	for (next = osi_first(&sbd.rgtree); next; next = osi_next(next)) {
Packit 6ef888
		rgd = (struct rgrp_tree *)next;
Packit 6ef888
		ri = &rgd->ri;
Packit 6ef888
		if (first && startblk <= ri->ri_data0) {
Packit 6ef888
			startblk = ri->ri_data0;
Packit 6ef888
			break;
Packit 6ef888
		} else if (ri->ri_addr <= startblk &&
Packit 6ef888
			 startblk < ri->ri_data0 + ri->ri_data)
Packit 6ef888
			break;
Packit 6ef888
		else
Packit 6ef888
			rgd = NULL;
Packit 6ef888
		first = 0;
Packit 6ef888
	}
Packit 6ef888
	if (!rgd) {
Packit 6ef888
		if (print)
Packit 6ef888
			printf("0\n");
Packit 6ef888
		gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
		if (print)
Packit 6ef888
			exit(-1);
Packit 6ef888
	}
Packit 6ef888
	for (; !found && next; next = osi_next(next)){
Packit 6ef888
		rgd = (struct rgrp_tree *)next;
Packit 6ef888
		errblk = gfs2_rgrp_read(&sbd, rgd);
Packit 6ef888
		if (errblk)
Packit 6ef888
			continue;
Packit 6ef888
Packit 6ef888
		found = !find_rg_metatype(rgd, &blk, startblk, metatype);
Packit 6ef888
		if (found)
Packit 6ef888
			break;
Packit 6ef888
Packit 6ef888
		gfs2_rgrp_relse(rgd);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (!found)
Packit 6ef888
		blk = 0;
Packit 6ef888
	if (print) {
Packit 6ef888
		if (dmode == HEX_MODE)
Packit 6ef888
			printf("0x%llx\n", (unsigned long long)blk);
Packit 6ef888
		else
Packit 6ef888
			printf("%llu\n", (unsigned long long)blk);
Packit 6ef888
	}
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	if (print)
Packit 6ef888
		exit(0);
Packit 6ef888
	return blk;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* Find next metadata block AFTER a given point in the fs                   */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t find_metablockoftype(const char *strtype, int print)
Packit 6ef888
{
Packit 6ef888
	int mtype = 0;
Packit 6ef888
	uint64_t startblk, blk = 0;
Packit 6ef888
Packit 6ef888
	if (print)
Packit 6ef888
		startblk = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
	else
Packit 6ef888
		startblk = block;
Packit 6ef888
Packit 6ef888
	for (mtype = GFS2_METATYPE_NONE;
Packit 6ef888
	     mtype <= GFS2_METATYPE_QC; mtype++)
Packit 6ef888
		if (!strcasecmp(strtype, mtypes[mtype]))
Packit 6ef888
			break;
Packit 6ef888
	if (!strcmp(strtype, "dinode"))
Packit 6ef888
		mtype = GFS2_METATYPE_DI;
Packit 6ef888
	if (mtype >= GFS2_METATYPE_NONE && mtype <= GFS2_METATYPE_RB)
Packit 6ef888
		blk = find_metablockoftype_slow(startblk, mtype, print);
Packit 6ef888
	else if (mtype >= GFS2_METATYPE_DI && mtype <= GFS2_METATYPE_QC)
Packit 6ef888
		blk = find_metablockoftype_rg(startblk, mtype, print);
Packit 6ef888
	else if (print) {
Packit 6ef888
		fprintf(stderr, "Error: metadata type not "
Packit 6ef888
			"specified: must be one of:\n");
Packit 6ef888
		fprintf(stderr, "sb rg rb di in lf jd lh ld"
Packit 6ef888
			" ea ed lb 13 qc\n");
Packit 6ef888
		gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	return blk;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* Check if the word is a keyword such as "sb" or "rindex"                  */
Packit 6ef888
/* Returns: block number if it is, else 0                                   */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
uint64_t check_keywords(const char *kword)
Packit 6ef888
{
Packit 6ef888
	unsigned long long blk = 0;
Packit 6ef888
Packit 6ef888
	if (!strcmp(kword, "sb") ||!strcmp(kword, "superblock"))
Packit 6ef888
		blk = 0x10 * (4096 / sbd.bsize); /* superblock */
Packit 6ef888
	else if (!strcmp(kword, "root") || !strcmp(kword, "rootdir"))
Packit 6ef888
		blk = sbd.sd_sb.sb_root_dir.no_addr;
Packit 6ef888
	else if (!strcmp(kword, "master")) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			fprintf(stderr, "This is GFS1; there's no master directory.\n");
Packit 6ef888
		else if (!sbd.sd_sb.sb_master_dir.no_addr) {
Packit 6ef888
			fprintf(stderr, "GFS2 master directory not found on %s\n", device);
Packit 6ef888
			exit(-1);
Packit 6ef888
		} else
Packit 6ef888
			blk = sbd.sd_sb.sb_master_dir.no_addr;
Packit 6ef888
	}
Packit 6ef888
	else if (!strcmp(kword, "jindex")) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = sbd1->sb_jindex_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("jindex"); /* journal index */
Packit 6ef888
	}
Packit 6ef888
	else if (!sbd.gfs1 && !strcmp(kword, "per_node"))
Packit 6ef888
		blk = masterblock("per_node");
Packit 6ef888
	else if (!sbd.gfs1 && !strcmp(kword, "inum"))
Packit 6ef888
		blk = masterblock("inum");
Packit 6ef888
	else if (!strcmp(kword, "statfs")) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = gfs1_license_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("statfs");
Packit 6ef888
	}
Packit 6ef888
	else if (!strcmp(kword, "rindex") || !strcmp(kword, "rgindex")) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = sbd1->sb_rindex_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("rindex");
Packit 6ef888
	} else if (!strcmp(kword, "rgs")) {
Packit 6ef888
		blk = RGLIST_DUMMY_BLOCK;
Packit 6ef888
	} else if (!strcmp(kword, "quota")) {
Packit 6ef888
		if (sbd.gfs1)
Packit 6ef888
			blk = gfs1_quota_di.no_addr;
Packit 6ef888
		else
Packit 6ef888
			blk = masterblock("quota");
Packit 6ef888
	} else if (!strncmp(kword, "rg ", 3)) {
Packit 6ef888
		int rgnum = 0;
Packit 6ef888
Packit 6ef888
		rgnum = atoi(kword + 3);
Packit 6ef888
		blk = get_rg_addr(rgnum);
Packit 6ef888
	} else if (!strncmp(kword, "journals", 8)) {
Packit 6ef888
		blk = JOURNALS_DUMMY_BLOCK;
Packit 6ef888
	} else if (strlen(kword) > 7 && !strncmp(kword, "journal", 7) && isdigit(kword[7])) {
Packit 6ef888
		uint64_t j_size;
Packit 6ef888
Packit 6ef888
		blk = find_journal_block(kword, &j_size);
Packit 6ef888
	} else if (kword[0]=='/') /* search */
Packit 6ef888
		blk = find_metablockoftype(&kword[1], 0);
Packit 6ef888
	else if (kword[0]=='0' && kword[1]=='x') /* hex addr */
Packit 6ef888
		sscanf(kword, "%llx", &blk);/* retrieve in hex */
Packit 6ef888
	else
Packit 6ef888
		sscanf(kword, "%llu", &blk); /* retrieve decimal */
Packit 6ef888
Packit 6ef888
	return blk;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* goto_block - go to a desired block entered by the user                   */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static uint64_t goto_block(void)
Packit 6ef888
{
Packit 6ef888
	char string[256];
Packit 6ef888
	int ch, delta;
Packit 6ef888
Packit 6ef888
	memset(string, 0, sizeof(string));
Packit 6ef888
	sprintf(string,"%lld", (long long)block);
Packit 6ef888
	if (bobgets(string, 1, 7, 16, &ch)) {
Packit 6ef888
		if (isalnum(string[0]) || string[0] == '/')
Packit 6ef888
			temp_blk = check_keywords(string);
Packit 6ef888
		else if (string[0] == '+' || string[0] == '-') {
Packit 6ef888
			if (string[1] == '0' && string[2] == 'x')
Packit 6ef888
				sscanf(string, "%x", &delta);
Packit 6ef888
			else
Packit 6ef888
				sscanf(string, "%d", &delta);
Packit 6ef888
			temp_blk = block + delta;
Packit 6ef888
		}
Packit 6ef888
Packit 6ef888
		if (temp_blk == RGLIST_DUMMY_BLOCK ||
Packit 6ef888
		    temp_blk == JOURNALS_DUMMY_BLOCK || temp_blk < max_block) {
Packit 6ef888
			offset = 0;
Packit 6ef888
			block = temp_blk;
Packit 6ef888
			push_block(block);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	return block;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* init_colors                                                              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void init_colors(void)
Packit 6ef888
{
Packit 6ef888
Packit 6ef888
	if (color_scheme) {
Packit 6ef888
		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
Packit 6ef888
		init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK);
Packit 6ef888
		init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE);
Packit 6ef888
		init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK);
Packit 6ef888
		init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK);
Packit 6ef888
		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK);
Packit 6ef888
		init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK);
Packit 6ef888
	}
Packit 6ef888
	else {
Packit 6ef888
		init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
Packit 6ef888
		init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE);
Packit 6ef888
		init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK);
Packit 6ef888
		init_pair(COLOR_SPECIAL, COLOR_MAGENTA, COLOR_WHITE);
Packit 6ef888
		init_pair(COLOR_HIGHLIGHT, COLOR_RED, COLOR_WHITE); /*cursor*/
Packit 6ef888
		init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE);
Packit 6ef888
		init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE);
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* hex_edit - Allow the user to edit the page by entering hex digits        */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void hex_edit(int *exitch)
Packit 6ef888
{
Packit 6ef888
	int left_off;
Packit 6ef888
	int ch;
Packit 6ef888
Packit 6ef888
	left_off = ((block * sbd.bsize) < 0xffffffff) ? 9 : 17;
Packit 6ef888
	/* 8 and 16 char addresses on screen */
Packit 6ef888
	
Packit 6ef888
	if (bobgets(estring, edit_row[HEX_MODE] + 3,
Packit 6ef888
		    (edit_col[HEX_MODE] * 2) + (edit_col[HEX_MODE] / 4) +
Packit 6ef888
		    left_off, 2, exitch)) {
Packit 6ef888
		if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
Packit 6ef888
			int hexoffset;
Packit 6ef888
			int i, sl = strlen(estring);
Packit 6ef888
			
Packit 6ef888
			for (i = 0; i < sl; i+=2) {
Packit 6ef888
				hexoffset = (edit_row[HEX_MODE] * 16) +
Packit 6ef888
					edit_col[HEX_MODE] + (i / 2);
Packit 6ef888
				ch = 0x00;
Packit 6ef888
				if (isdigit(estring[i]))
Packit 6ef888
					ch = (estring[i] - '0') * 0x10;
Packit 6ef888
				else if (estring[i] >= 'a' &&
Packit 6ef888
					 estring[i] <= 'f')
Packit 6ef888
					ch = (estring[i]-'a' + 0x0a)*0x10;
Packit 6ef888
				else if (estring[i] >= 'A' &&
Packit 6ef888
					 estring[i] <= 'F')
Packit 6ef888
					ch = (estring[i] - 'A' + 0x0a) * 0x10;
Packit 6ef888
				if (isdigit(estring[i+1]))
Packit 6ef888
					ch += (estring[i+1] - '0');
Packit 6ef888
				else if (estring[i+1] >= 'a' &&
Packit 6ef888
					 estring[i+1] <= 'f')
Packit 6ef888
					ch += (estring[i+1] - 'a' + 0x0a);
Packit 6ef888
				else if (estring[i+1] >= 'A' &&
Packit 6ef888
					 estring[i+1] <= 'F')
Packit 6ef888
					ch += (estring[i+1] - 'A' + 0x0a);
Packit 6ef888
				bh->b_data[offset + hexoffset] = ch;
Packit 6ef888
			}
Packit 6ef888
			if (pwrite(sbd.device_fd, bh->b_data, sbd.bsize, dev_offset) !=
Packit 6ef888
			    sbd.bsize) {
Packit 6ef888
				fprintf(stderr, "write error: %s from %s:%d: "
Packit 6ef888
					"offset %lld (0x%llx)\n",
Packit 6ef888
					strerror(errno),
Packit 6ef888
					__FUNCTION__, __LINE__,
Packit 6ef888
					(unsigned long long)dev_offset,
Packit 6ef888
					(unsigned long long)dev_offset);
Packit 6ef888
				exit(-1);
Packit 6ef888
			}
Packit 6ef888
			fsync(sbd.device_fd);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* page up                                                                  */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void pageup(void)
Packit 6ef888
{
Packit 6ef888
	if (dmode == EXTENDED_MODE) {
Packit 6ef888
		if (edit_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
Packit 6ef888
			edit_row[dmode] -= (dsplines / lines_per_row[dmode]);
Packit 6ef888
		else
Packit 6ef888
			edit_row[dmode] = 0;
Packit 6ef888
		if (start_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
Packit 6ef888
			start_row[dmode] -= (dsplines / lines_per_row[dmode]);
Packit 6ef888
		else
Packit 6ef888
			start_row[dmode] = 0;
Packit 6ef888
	}
Packit 6ef888
	else {
Packit 6ef888
		start_row[dmode] = edit_row[dmode] = 0;
Packit 6ef888
		if (dmode == GFS2_MODE || offset==0) {
Packit 6ef888
			block--;
Packit 6ef888
			if (dmode == HEX_MODE)
Packit 6ef888
				offset = (sbd.bsize % screen_chunk_size) > 0 ?
Packit 6ef888
					screen_chunk_size *
Packit 6ef888
					(sbd.bsize / screen_chunk_size) :
Packit 6ef888
					sbd.bsize - screen_chunk_size;
Packit 6ef888
			else
Packit 6ef888
				offset = 0;
Packit 6ef888
		} else
Packit 6ef888
			offset -= screen_chunk_size;
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* page down                                                                */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void pagedn(void)
Packit 6ef888
{
Packit 6ef888
	if (dmode == EXTENDED_MODE) {
Packit 6ef888
		if ((edit_row[dmode] + dsplines) / lines_per_row[dmode] + 1 <=
Packit 6ef888
		    end_row[dmode]) {
Packit 6ef888
			start_row[dmode] += dsplines / lines_per_row[dmode];
Packit 6ef888
			edit_row[dmode] += dsplines / lines_per_row[dmode];
Packit 6ef888
		} else {
Packit 6ef888
			edit_row[dmode] = end_row[dmode] - 1;
Packit 6ef888
			while (edit_row[dmode] - start_row[dmode]
Packit 6ef888
			       + 1 > last_entry_onscreen[dmode])
Packit 6ef888
				start_row[dmode]++;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	else {
Packit 6ef888
		start_row[dmode] = edit_row[dmode] = 0;
Packit 6ef888
		if (dmode == GFS2_MODE ||
Packit 6ef888
		    offset + screen_chunk_size >= sbd.bsize) {
Packit 6ef888
			block++;
Packit 6ef888
			offset = 0;
Packit 6ef888
		} else
Packit 6ef888
			offset += screen_chunk_size;
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* jump - jump to the address the cursor is on                              */
Packit 6ef888
/*                                                                          */
Packit 6ef888
/* If the cursor is in a log descriptor, jump to the log-descriptor version */
Packit 6ef888
/* of the block instead of the "real" block.                                */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void jump(void)
Packit 6ef888
{
Packit 6ef888
	if (dmode == HEX_MODE) {
Packit 6ef888
		unsigned int col2;
Packit 6ef888
		uint64_t *b;
Packit 6ef888
		const uint32_t block_type = get_block_type(bh, NULL);
Packit 6ef888
		
Packit 6ef888
		/* special exception for log descriptors: jump the journaled
Packit 6ef888
		   version of the block, not the "real" block */
Packit 6ef888
		if (block_type == GFS2_METATYPE_LD) {
Packit 6ef888
			int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
Packit 6ef888
			int pnum = get_pnum(ptroffset);
Packit 6ef888
			temp_blk = bh->b_blocknr + pnum + 1;
Packit 6ef888
		} else if (edit_row[dmode] >= 0) {
Packit 6ef888
			col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
Packit 6ef888
			b = (uint64_t *)&bh->b_data[edit_row[dmode]*16 +
Packit 6ef888
						    offset + col2];
Packit 6ef888
			temp_blk = be64_to_cpu(*b);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	else
Packit 6ef888
		sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */
Packit 6ef888
	if (temp_blk < max_block) { /* if the block number is valid */
Packit 6ef888
		int i;
Packit 6ef888
		
Packit 6ef888
		offset = 0;
Packit 6ef888
		push_block(temp_blk);
Packit 6ef888
		block = temp_blk;
Packit 6ef888
		for (i = 0; i < DMODES; i++) {
Packit 6ef888
			start_row[i] = end_row[i] = edit_row[i] = 0;
Packit 6ef888
			edit_col[i] = 0;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* print block type                                                         */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void print_block_type(uint64_t tblock, int type, const char *additional)
Packit 6ef888
{
Packit 6ef888
	if (type <= GFS2_METATYPE_QC)
Packit 6ef888
		printf("%d (Block %lld is type %d: %s%s)\n", type,
Packit 6ef888
		       (unsigned long long)tblock, type, block_type_str[type],
Packit 6ef888
		       additional);
Packit 6ef888
	else
Packit 6ef888
		printf("%d (Block %lld is type %d: unknown%s)\n", type,
Packit 6ef888
		       (unsigned long long)tblock, type, additional);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* find_print block type                                                    */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void find_print_block_type(void)
Packit 6ef888
{
Packit 6ef888
	uint64_t tblock;
Packit 6ef888
	struct gfs2_buffer_head *lbh;
Packit 6ef888
	int type;
Packit 6ef888
Packit 6ef888
	tblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
	lbh = bread(&sbd, tblock);
Packit 6ef888
	type = get_block_type(lbh, NULL);
Packit 6ef888
	print_block_type(tblock, type, "");
Packit 6ef888
	brelse(lbh);
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	exit(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* Find and print the resource group associated with a given block          */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void find_print_block_rg(int bitmap)
Packit 6ef888
{
Packit 6ef888
	uint64_t rblock, rgblock;
Packit 6ef888
	int i;
Packit 6ef888
	struct rgrp_tree *rgd;
Packit 6ef888
Packit 6ef888
	rblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
	if (rblock == LGFS2_SB_ADDR(&sbd))
Packit 6ef888
		printf("0 (the superblock is not in the bitmap)\n");
Packit 6ef888
	else {
Packit 6ef888
		rgd = gfs2_blk2rgrpd(&sbd, rblock);
Packit 6ef888
		if (rgd) {
Packit 6ef888
			rgblock = rgd->ri.ri_addr;
Packit 6ef888
			if (bitmap) {
Packit 6ef888
				struct gfs2_bitmap *bits = NULL;
Packit 6ef888
Packit 6ef888
				for (i = 0; i < rgd->ri.ri_length; i++) {
Packit 6ef888
					bits = &(rgd->bits[i]);
Packit 6ef888
					if (rblock - rgd->ri.ri_data0 <
Packit 6ef888
					    ((bits->bi_start + bits->bi_len) *
Packit 6ef888
					     GFS2_NBBY)) {
Packit 6ef888
						break;
Packit 6ef888
					}
Packit 6ef888
				}
Packit 6ef888
				if (i < rgd->ri.ri_length)
Packit 6ef888
					rgblock += i;
Packit 6ef888
Packit 6ef888
			}
Packit 6ef888
			if (dmode == HEX_MODE)
Packit 6ef888
				printf("0x%llx\n",(unsigned long long)rgblock);
Packit 6ef888
			else
Packit 6ef888
				printf("%llu\n", (unsigned long long)rgblock);
Packit 6ef888
		} else {
Packit 6ef888
			printf("-1 (block invalid or part of an rgrp).\n");
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	exit(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* find/change/print block allocation (what the bitmap says about block)    */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void find_change_block_alloc(int *newval)
Packit 6ef888
{
Packit 6ef888
	uint64_t ablock;
Packit 6ef888
	int type;
Packit 6ef888
	struct rgrp_tree *rgd;
Packit 6ef888
Packit 6ef888
	if (newval &&
Packit 6ef888
	    (*newval < GFS2_BLKST_FREE || *newval > GFS2_BLKST_DINODE)) {
Packit 6ef888
		int i;
Packit 6ef888
Packit 6ef888
		printf("Error: value %d is not valid.\nValid values are:\n",
Packit 6ef888
		       *newval);
Packit 6ef888
		for (i = GFS2_BLKST_FREE; i <= GFS2_BLKST_DINODE; i++)
Packit 6ef888
			printf("%d - %s\n", i, allocdesc[sbd.gfs1][i]);
Packit 6ef888
		gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	ablock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
	if (ablock == LGFS2_SB_ADDR(&sbd))
Packit 6ef888
		printf("3 (the superblock is not in the bitmap)\n");
Packit 6ef888
	else {
Packit 6ef888
		rgd = gfs2_blk2rgrpd(&sbd, ablock);
Packit 6ef888
		if (rgd) {
Packit 6ef888
			gfs2_rgrp_read(&sbd, rgd);
Packit 6ef888
			if (newval) {
Packit 6ef888
				if (gfs2_set_bitmap(rgd, ablock, *newval))
Packit 6ef888
					printf("-1 (block invalid or part of an rgrp).\n");
Packit 6ef888
				else
Packit 6ef888
					printf("%d\n", *newval);
Packit 6ef888
			} else {
Packit 6ef888
				type = lgfs2_get_bitmap(&sbd, ablock, rgd);
Packit 6ef888
				if (type < 0) {
Packit 6ef888
					printf("-1 (block invalid or part of "
Packit 6ef888
					       "an rgrp).\n");
Packit 6ef888
					exit(-1);
Packit 6ef888
				}
Packit 6ef888
				printf("%d (%s)\n", type, allocdesc[sbd.gfs1][type]);
Packit 6ef888
			}
Packit 6ef888
			gfs2_rgrp_relse(rgd);
Packit 6ef888
		} else {
Packit 6ef888
			gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
			printf("-1 (block invalid or part of an rgrp).\n");
Packit 6ef888
			exit(-1);
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
	if (newval)
Packit 6ef888
		fsync(sbd.device_fd);
Packit 6ef888
	exit(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * process request to print a certain field from a previously pushed block
Packit 6ef888
 */
Packit 6ef888
static void process_field(const char *field, const char *nstr)
Packit 6ef888
{
Packit 6ef888
	uint64_t fblock;
Packit 6ef888
	struct gfs2_buffer_head *rbh;
Packit 6ef888
	int type;
Packit 6ef888
	const struct lgfs2_metadata *mtype;
Packit 6ef888
	const struct lgfs2_metafield *mfield;
Packit 6ef888
Packit 6ef888
	fblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
	rbh = bread(&sbd, fblock);
Packit 6ef888
	type = get_block_type(rbh, NULL);
Packit 6ef888
Packit 6ef888
	mtype = lgfs2_find_mtype(type, sbd.gfs1 ? LGFS2_MD_GFS1 : LGFS2_MD_GFS2);
Packit 6ef888
	if (mtype == NULL) {
Packit 6ef888
		fprintf(stderr, "Metadata type '%d' invalid\n", type);
Packit 6ef888
		exit(1);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	mfield = lgfs2_find_mfield_name(field, mtype);
Packit 6ef888
	if (mfield == NULL) {
Packit 6ef888
		fprintf(stderr, "No field '%s' in block type '%s'\n", field, mtype->name);
Packit 6ef888
		exit(1);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (nstr != device) {
Packit 6ef888
		int err = 0;
Packit 6ef888
		if (mfield->flags & (LGFS2_MFF_UUID|LGFS2_MFF_STRING)) {
Packit 6ef888
			err = lgfs2_field_assign(rbh->b_data, mfield, nstr);
Packit 6ef888
		} else {
Packit 6ef888
			uint64_t val = 0;
Packit 6ef888
			err = sscanf(nstr, "%"SCNi64, &val;;
Packit 6ef888
			if (err == 1)
Packit 6ef888
				err = lgfs2_field_assign(rbh->b_data, mfield, &val;;
Packit 6ef888
			else
Packit 6ef888
				err = -1;
Packit 6ef888
		}
Packit 6ef888
		if (err != 0) {
Packit 6ef888
			fprintf(stderr, "Could not set '%s' to '%s': %s\n", field, nstr,
Packit 6ef888
			        strerror(errno));
Packit 6ef888
			exit(1);
Packit 6ef888
		}
Packit 6ef888
		bmodified(rbh);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	if (!termlines) {
Packit 6ef888
		char str[GFS2_LOCKNAME_LEN] = "";
Packit 6ef888
		lgfs2_field_str(str, GFS2_LOCKNAME_LEN, rbh->b_data, mfield, (dmode == HEX_MODE));
Packit 6ef888
		printf("%s\n", str);
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	brelse(rbh);
Packit 6ef888
	fsync(sbd.device_fd);
Packit 6ef888
	exit(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* interactive_mode - accept keystrokes from user and display structures    */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void interactive_mode(void)
Packit 6ef888
{
Packit 6ef888
	int ch = 0, Quit;
Packit 6ef888
Packit 6ef888
	if ((wind = initscr()) == NULL) {
Packit 6ef888
		fprintf(stderr, "Error: unable to initialize screen.");
Packit 6ef888
		eol(0);
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	getmaxyx(stdscr, termlines, termcols);
Packit 6ef888
	termlines--;
Packit 6ef888
	/* Do our initial screen stuff: */
Packit 6ef888
	clear(); /* don't use Erase */
Packit 6ef888
	start_color();
Packit 6ef888
	noecho();
Packit 6ef888
	keypad(stdscr, TRUE);
Packit 6ef888
	raw();
Packit 6ef888
	curs_set(0);
Packit 6ef888
	init_colors();
Packit 6ef888
	/* Accept keystrokes and act on them accordingly */
Packit 6ef888
	Quit = FALSE;
Packit 6ef888
	editing = FALSE;
Packit 6ef888
	while (!Quit) {
Packit 6ef888
		display(FALSE, 0, 0, 0);
Packit 6ef888
		if (editing) {
Packit 6ef888
			if (edit_row[dmode] == -1)
Packit 6ef888
				block = goto_block();
Packit 6ef888
			else {
Packit 6ef888
				if (dmode == HEX_MODE)
Packit 6ef888
					hex_edit(&ch);
Packit 6ef888
				else if (dmode == GFS2_MODE) {
Packit 6ef888
					bobgets(estring, edit_row[dmode]+4, 24,
Packit 6ef888
						10, &ch);
Packit 6ef888
					process_field(efield, estring);
Packit 6ef888
				} else
Packit 6ef888
					bobgets(estring, edit_row[dmode]+6, 14,
Packit 6ef888
						edit_size[dmode], &ch);
Packit 6ef888
			}
Packit 6ef888
		}
Packit 6ef888
		else
Packit 6ef888
			while ((ch=getch()) == 0); // wait for input
Packit 6ef888
Packit 6ef888
		switch (ch)
Packit 6ef888
		{
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* escape or 'q' */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 0x1b:
Packit 6ef888
		case 0x03:
Packit 6ef888
		case 'q':
Packit 6ef888
			if (editing)
Packit 6ef888
				editing = FALSE;
Packit 6ef888
			else
Packit 6ef888
				Quit=TRUE;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* home - return to the superblock                           */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_HOME:
Packit 6ef888
			if (dmode == EXTENDED_MODE) {
Packit 6ef888
				start_row[dmode] = end_row[dmode] = 0;
Packit 6ef888
				edit_row[dmode] = 0;
Packit 6ef888
			}
Packit 6ef888
			else {
Packit 6ef888
				block = 0x10 * (4096 / sbd.bsize);
Packit 6ef888
				push_block(block);
Packit 6ef888
				offset = 0;
Packit 6ef888
			}
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* backspace - return to the previous block on the stack     */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_BACKSPACE:
Packit 6ef888
		case 0x7f:
Packit 6ef888
			block = pop_block();
Packit 6ef888
			offset = 0;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* space - go down the block stack (opposite of backspace)   */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case ' ':
Packit 6ef888
			blockhist++;
Packit 6ef888
			block = blockstack[blockhist % BLOCK_STACK_SIZE].block;
Packit 6ef888
			offset = 0;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* arrow up */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_UP:
Packit 6ef888
		case '-':
Packit 6ef888
			if (dmode == EXTENDED_MODE) {
Packit 6ef888
				if (edit_row[dmode] > 0)
Packit 6ef888
					edit_row[dmode]--;
Packit 6ef888
				if (edit_row[dmode] < start_row[dmode])
Packit 6ef888
					start_row[dmode] = edit_row[dmode];
Packit 6ef888
			}
Packit 6ef888
			else {
Packit 6ef888
				if (edit_row[dmode] >= 0)
Packit 6ef888
					edit_row[dmode]--;
Packit 6ef888
			}
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* arrow down */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_DOWN:
Packit 6ef888
		case '+':
Packit 6ef888
			if (dmode == EXTENDED_MODE) {
Packit 6ef888
				if (edit_row[dmode] + 1 < end_row[dmode]) {
Packit 6ef888
					if (edit_row[dmode] - start_row[dmode]
Packit 6ef888
					    + 1 > last_entry_onscreen[dmode])
Packit 6ef888
						start_row[dmode]++;
Packit 6ef888
					edit_row[dmode]++;
Packit 6ef888
				}
Packit 6ef888
			}
Packit 6ef888
			else {
Packit 6ef888
				if (edit_row[dmode] < last_entry_onscreen[dmode])
Packit 6ef888
					edit_row[dmode]++;
Packit 6ef888
			}
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* arrow left */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_LEFT:
Packit 6ef888
			if (dmode == HEX_MODE) {
Packit 6ef888
				if (edit_col[dmode] > 0)
Packit 6ef888
					edit_col[dmode]--;
Packit 6ef888
				else
Packit 6ef888
					edit_col[dmode] = 15;
Packit 6ef888
			}
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* arrow right */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_RIGHT:
Packit 6ef888
			if (dmode == HEX_MODE) {
Packit 6ef888
				if (edit_col[dmode] < 15)
Packit 6ef888
					edit_col[dmode]++;
Packit 6ef888
				else
Packit 6ef888
					edit_col[dmode] = 0;
Packit 6ef888
			}
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* m - change display mode key */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'm':
Packit 6ef888
			dmode = ((dmode + 1) % DMODES);
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* J - Jump to highlighted block number */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'j':
Packit 6ef888
			jump();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* g - goto block */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'g':
Packit 6ef888
			block = goto_block();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* h - help key */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'h':
Packit 6ef888
			print_usage();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* e - change to extended mode */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'e':
Packit 6ef888
			dmode = EXTENDED_MODE;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* b - Back one 4K block */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'b':
Packit 6ef888
			start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
Packit 6ef888
			if (block > 0)
Packit 6ef888
				block--;
Packit 6ef888
			offset = 0;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* c - Change color scheme */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'c':
Packit 6ef888
			color_scheme = !color_scheme;
Packit 6ef888
			init_colors();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* page up key */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 0x19:                    // ctrl-y for vt100
Packit 6ef888
		case KEY_PPAGE:		      // PgUp
Packit 6ef888
		case 0x15:                    // ctrl-u for vi compat.
Packit 6ef888
		case 0x02:                   // ctrl-b for less compat.
Packit 6ef888
			pageup();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* end - Jump to the end of the list */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 0x168:
Packit 6ef888
			if (dmode == EXTENDED_MODE) {
Packit 6ef888
				int ents_per_screen = dsplines /
Packit 6ef888
					lines_per_row[dmode];
Packit 6ef888
Packit 6ef888
				edit_row[dmode] = end_row[dmode] - 1;
Packit 6ef888
				if ((edit_row[dmode] - ents_per_screen)+1 > 0)
Packit 6ef888
					start_row[dmode] = edit_row[dmode] - 
Packit 6ef888
						ents_per_screen + 1;
Packit 6ef888
				else
Packit 6ef888
					start_row[dmode] = 0;
Packit 6ef888
			}
Packit 6ef888
			/* TODO: Make end key work for other display modes. */
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* f - Forward one 4K block */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 'f':
Packit 6ef888
			start_row[dmode]=end_row[dmode]=edit_row[dmode] = 0;
Packit 6ef888
			lines_per_row[dmode] = 1;
Packit 6ef888
			block++;
Packit 6ef888
			offset = 0;
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* page down key */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case 0x16:                    // ctrl-v for vt100
Packit 6ef888
		case KEY_NPAGE:		      // PgDown
Packit 6ef888
		case 0x04:                    // ctrl-d for vi compat.
Packit 6ef888
			pagedn();
Packit 6ef888
			break;
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		/* enter key - change a value */
Packit 6ef888
		/* --------------------------------------------------------- */
Packit 6ef888
		case KEY_ENTER:
Packit 6ef888
		case('\n'):
Packit 6ef888
		case('\r'):
Packit 6ef888
			editing = !editing;
Packit 6ef888
			break;
Packit 6ef888
		case KEY_RESIZE:
Packit 6ef888
			getmaxyx(stdscr, termlines, termcols);
Packit 6ef888
			termlines--;
Packit 6ef888
			break;
Packit 6ef888
		default:
Packit 6ef888
			move(termlines - 1, 0);
Packit 6ef888
			printw("Keystroke not understood: 0x%03x",ch);
Packit 6ef888
			refresh();
Packit 6ef888
			usleep(50000);
Packit 6ef888
			break;
Packit 6ef888
		} /* switch */
Packit 6ef888
	} /* while !Quit */
Packit 6ef888
Packit 6ef888
    Erase();
Packit 6ef888
    refresh();
Packit 6ef888
    endwin();
Packit 6ef888
}/* interactive_mode */
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* gfs_log_header_in - read in a gfs1-style log header                      */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
void gfs_log_header_in(struct gfs_log_header *head,
Packit 6ef888
		       struct gfs2_buffer_head *lbh)
Packit 6ef888
{
Packit 6ef888
	struct gfs_log_header *str = lbh->iov.iov_base;
Packit 6ef888
Packit 6ef888
	gfs2_meta_header_in(&head->lh_header, lbh->b_data);
Packit 6ef888
Packit 6ef888
	head->lh_flags = be32_to_cpu(str->lh_flags);
Packit 6ef888
	head->lh_pad = be32_to_cpu(str->lh_pad);
Packit 6ef888
Packit 6ef888
	head->lh_first = be64_to_cpu(str->lh_first);
Packit 6ef888
	head->lh_sequence = be64_to_cpu(str->lh_sequence);
Packit 6ef888
Packit 6ef888
	head->lh_tail = be64_to_cpu(str->lh_tail);
Packit 6ef888
	head->lh_last_dump = be64_to_cpu(str->lh_last_dump);
Packit 6ef888
Packit 6ef888
	memcpy(head->lh_reserved, str->lh_reserved, 64);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* gfs_log_header_print - print a gfs1-style log header                     */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
void gfs_log_header_print(struct gfs_log_header *lh)
Packit 6ef888
{
Packit 6ef888
	gfs2_meta_header_print(&lh->lh_header);
Packit 6ef888
	pv(lh, lh_flags, "%u", "0x%.8x");
Packit 6ef888
	pv(lh, lh_pad, "%u", "%x");
Packit 6ef888
	pv((unsigned long long)lh, lh_first, "%llu", "%llx");
Packit 6ef888
	pv((unsigned long long)lh, lh_sequence, "%llu", "%llx");
Packit 6ef888
	pv((unsigned long long)lh, lh_tail, "%llu", "%llx");
Packit 6ef888
	pv((unsigned long long)lh, lh_last_dump, "%llu", "%llx");
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* usage - print command line usage                                         */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void usage(void)
Packit 6ef888
{
Packit 6ef888
	fprintf(stderr,"\nFormat is: gfs2_edit [-c 1] [-V] [-x] [-h] [identify] [-z <0-9>] [-p structures|blocks][blocktype][blockalloc [val]][blockbits][blockrg][rgcount][rgflags][rgbitmaps][find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|13|qc][field <f>[val]] /dev/device\n\n");
Packit 6ef888
	fprintf(stderr,"If only the device is specified, it enters into hexedit mode.\n");
Packit 6ef888
	fprintf(stderr,"identify - prints out only the block type, not the details.\n");
Packit 6ef888
	fprintf(stderr,"printsavedmeta - prints out the saved metadata blocks from a savemeta file.\n");
Packit 6ef888
	fprintf(stderr,"savemeta <file_system> <file.gz> - save off your metadata for analysis and debugging.\n");
Packit 6ef888
	fprintf(stderr,"   (The intelligent way: assume bitmap is correct).\n");
Packit 6ef888
	fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging.  The SLOW way (block by block).\n");
Packit 6ef888
	fprintf(stderr,"savergs - save off only the resource group information (rindex and rgs).\n");
Packit 6ef888
	fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
Packit 6ef888
	fprintf(stderr,"rgcount - print how many RGs in the file system.\n");
Packit 6ef888
	fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
Packit 6ef888
	fprintf(stderr,"rgbitmaps <rgnum> - print out the bitmaps for rgrp "
Packit 6ef888
		"rgnum.\n");
Packit 6ef888
	fprintf(stderr,"rgrepair - find and repair damaged rgrp.\n");
Packit 6ef888
	fprintf(stderr,"-V   prints version number.\n");
Packit 6ef888
	fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
Packit 6ef888
	fprintf(stderr,"-d   prints details (for printing journals)\n");
Packit 6ef888
	fprintf(stderr,"-p   prints GFS2 structures or blocks to stdout.\n");
Packit 6ef888
	fprintf(stderr,"     sb - prints the superblock.\n");
Packit 6ef888
	fprintf(stderr,"     size - prints the filesystem size.\n");
Packit 6ef888
	fprintf(stderr,"     master - prints the master directory.\n");
Packit 6ef888
	fprintf(stderr,"     root - prints the root directory.\n");
Packit 6ef888
	fprintf(stderr,"     jindex - prints the journal index directory.\n");
Packit 6ef888
	fprintf(stderr,"     journals - prints the journal status.\n");
Packit 6ef888
	fprintf(stderr,"     per_node - prints the per_node directory.\n");
Packit 6ef888
	fprintf(stderr,"     inum - prints the inum file.\n");
Packit 6ef888
	fprintf(stderr,"     statfs - prints the statfs file.\n");
Packit 6ef888
	fprintf(stderr,"     rindex - prints the rindex file.\n");
Packit 6ef888
	fprintf(stderr,"     rg X - print resource group X.\n");
Packit 6ef888
	fprintf(stderr,"     rgs - prints all the resource groups (rgs).\n");
Packit 6ef888
	fprintf(stderr,"     quota - prints the quota file.\n");
Packit 6ef888
	fprintf(stderr,"     0x1234 - prints the specified block\n");
Packit 6ef888
	fprintf(stderr,"-p   <block> blocktype - prints the type "
Packit 6ef888
		"of the specified block\n");
Packit 6ef888
	fprintf(stderr,"-p   <block> blockrg - prints the resource group "
Packit 6ef888
		"block corresponding to the specified block\n");
Packit 6ef888
	fprintf(stderr,"-p   <block> blockbits - prints the block with "
Packit 6ef888
		"the bitmap corresponding to the specified block\n");
Packit 6ef888
	fprintf(stderr,"-p   <block> blockalloc [0|1|2|3] - print or change "
Packit 6ef888
		"the allocation type of the specified block\n");
Packit 6ef888
	fprintf(stderr,"-p   <block> field [new_value] - prints or change the "
Packit 6ef888
		"structure field\n");
Packit 6ef888
	fprintf(stderr,"-p    find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|"
Packit 6ef888
		"13|qc - find block of given type after block \n");
Packit 6ef888
	fprintf(stderr,"      specifies the starting block for search\n");
Packit 6ef888
	fprintf(stderr,"-z 1 use gzip compression level 1 for savemeta (default 9)\n");
Packit 6ef888
	fprintf(stderr,"-z 0 do not use compression\n");
Packit 6ef888
	fprintf(stderr,"-s   specifies a starting block such as root, rindex, quota, inum.\n");
Packit 6ef888
	fprintf(stderr,"-x   print in hexmode.\n");
Packit 6ef888
	fprintf(stderr,"-h   prints this help.\n\n");
Packit 6ef888
	fprintf(stderr,"Examples:\n");
Packit 6ef888
	fprintf(stderr,"   To run in interactive mode:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit /dev/bobs_vg/lvol0\n");
Packit 6ef888
	fprintf(stderr,"   To print out the superblock and master directory:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p sb master /dev/bobs_vg/lvol0\n");
Packit 6ef888
	fprintf(stderr,"   To print out the master directory in hex:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -x -p master /dev/bobs_vg/lvol0\n");
Packit 6ef888
	fprintf(stderr,"   To print out the block-type for block 0x27381:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit identify -p 0x27381 /dev/bobs_vg/lvol0\n");
Packit 6ef888
	fprintf(stderr,"   To print out the fourth Resource Group. (the first R is #0)\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p rg 3 /dev/sdb1\n");
Packit 6ef888
	fprintf(stderr,"   To print out the metadata type of block 1234\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p 1234 blocktype /dev/roth_vg/roth_lb\n");
Packit 6ef888
	fprintf(stderr,"   To print out the allocation type of block 2345\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p 2345 blockalloc /dev/vg/lv\n");
Packit 6ef888
	fprintf(stderr,"   To change the allocation type of block 2345 to a 'free block'\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p 2345 blockalloc 0 /dev/vg/lv\n");
Packit 6ef888
	fprintf(stderr,"   To print out the file size of the dinode at block 0x118\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p 0x118 field di_size /dev/roth_vg/roth_lb\n");
Packit 6ef888
	fprintf(stderr,"   To find any dinode higher than the quota file dinode:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit -p quota find di /dev/x/y\n");
Packit 6ef888
	fprintf(stderr,"   To set the Resource Group flags for rg #7 to 3.\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit rgflags 7 3 /dev/sdc2\n");
Packit 6ef888
	fprintf(stderr,"   To save off all metadata for /dev/vg/lv:\n");
Packit 6ef888
	fprintf(stderr,"     gfs2_edit savemeta /dev/vg/lv /tmp/metasave.gz\n");
Packit 6ef888
}/* usage */
Packit 6ef888
Packit 6ef888
/**
Packit 6ef888
 * getgziplevel - Process the -z parameter to savemeta operations
Packit 6ef888
 * argv - argv
Packit 6ef888
 * i    - a pointer to the argv index at which to begin processing
Packit 6ef888
 * The index pointed to by i will be incremented past the -z option if found
Packit 6ef888
 */
Packit 6ef888
static void getgziplevel(char *argv[], int *i)
Packit 6ef888
{
Packit 6ef888
	char *opt, *arg;
Packit 6ef888
	char *endptr;
Packit 6ef888
Packit 6ef888
	arg = argv[1 + *i];
Packit 6ef888
	if (strncmp(arg, "-z", 2)) {
Packit 6ef888
		return;
Packit 6ef888
	} else if (arg[2] != '\0') {
Packit 6ef888
		opt = &arg[2];
Packit 6ef888
	} else {
Packit 6ef888
		(*i)++;
Packit 6ef888
		opt = argv[1 + *i];
Packit 6ef888
	}
Packit 6ef888
	errno = 0;
Packit 6ef888
	gziplevel = strtol(opt, &endptr, 10);
Packit 6ef888
	if (errno || endptr == opt || gziplevel < 0 || gziplevel > 9) {
Packit 6ef888
		fprintf(stderr, "Compression level out of range: %s\n", opt);
Packit 6ef888
		exit(-1);
Packit 6ef888
	}
Packit 6ef888
	(*i)++;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int count_dinode_blks(struct rgrp_tree *rgd, int bitmap,
Packit 6ef888
			     struct gfs2_buffer_head *rbh)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_buffer_head *tbh;
Packit 6ef888
	uint64_t b;
Packit 6ef888
	int dinodes = 0;
Packit 6ef888
	char *byte, cur_state, new_state;
Packit 6ef888
	int bit, off;
Packit 6ef888
Packit 6ef888
	if (bitmap)
Packit 6ef888
		off = sizeof(struct gfs2_meta_header);
Packit 6ef888
	else
Packit 6ef888
		off = sizeof(struct gfs2_rgrp);
Packit 6ef888
Packit 6ef888
	for (b = 0; b < rgd->bits[bitmap].bi_len << GFS2_BIT_SIZE; b++) {
Packit 6ef888
		tbh = bread(&sbd, rgd->ri.ri_data0 +
Packit 6ef888
			    rgd->bits[bitmap].bi_start + b);
Packit 6ef888
		byte = rbh->b_data + off + (b / GFS2_NBBY);
Packit 6ef888
		bit = (b % GFS2_NBBY) * GFS2_BIT_SIZE;
Packit 6ef888
		if (gfs2_check_meta(tbh, GFS2_METATYPE_DI) == 0) {
Packit 6ef888
			dinodes++;
Packit 6ef888
			new_state = GFS2_BLKST_DINODE;
Packit 6ef888
		} else {
Packit 6ef888
			new_state = GFS2_BLKST_USED;
Packit 6ef888
		}
Packit 6ef888
		cur_state = (*byte >> bit) & GFS2_BIT_MASK;
Packit 6ef888
		*byte ^= cur_state << bit;
Packit 6ef888
		*byte |= new_state << bit;
Packit 6ef888
		brelse(tbh);
Packit 6ef888
	}
Packit 6ef888
	bmodified(rbh);
Packit 6ef888
	return dinodes;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static int count_dinode_bits(struct gfs2_buffer_head *rbh)
Packit 6ef888
{
Packit 6ef888
	uint64_t blk;
Packit 6ef888
	struct gfs2_meta_header *mh = (struct gfs2_meta_header *)rbh->b_data;
Packit 6ef888
	char *byte;
Packit 6ef888
	int bit;
Packit 6ef888
	int dinodes = 0;
Packit 6ef888
Packit 6ef888
	if (be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG)
Packit 6ef888
		blk = sizeof(struct gfs2_rgrp);
Packit 6ef888
	else
Packit 6ef888
		blk = sizeof(struct gfs2_meta_header);
Packit 6ef888
Packit 6ef888
	for (; blk < sbd.bsize; blk++) {
Packit 6ef888
		byte = rbh->b_data + (blk / GFS2_NBBY);
Packit 6ef888
		bit = (blk % GFS2_NBBY) * GFS2_BIT_SIZE;
Packit 6ef888
		if (((*byte >> bit) & GFS2_BIT_MASK) == GFS2_BLKST_DINODE)
Packit 6ef888
			dinodes++;
Packit 6ef888
	}
Packit 6ef888
	return dinodes;
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
static void rg_repair(void)
Packit 6ef888
{
Packit 6ef888
	struct gfs2_buffer_head *rbh;
Packit 6ef888
	struct rgrp_tree *rgd;
Packit 6ef888
	struct osi_node *n;
Packit 6ef888
	int b;
Packit 6ef888
	int rgs_fixed = 0;
Packit 6ef888
	int dinodes_found = 0, dinodes_total = 0;
Packit 6ef888
Packit 6ef888
	/* Walk through the resource groups saving everything within */
Packit 6ef888
	for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
Packit 6ef888
		rgd = (struct rgrp_tree *)n;
Packit 6ef888
		if (gfs2_rgrp_read(&sbd, rgd) == 0) { /* was read in okay */
Packit 6ef888
			gfs2_rgrp_relse(rgd);
Packit 6ef888
			continue; /* ignore it */
Packit 6ef888
		}
Packit 6ef888
		/* If we get here, it's because we have an rgrp in the rindex
Packit 6ef888
		   file that can't be read in. So attempt to repair it.
Packit 6ef888
		   If we find a damaged rgrp or bitmap, fix the metadata.
Packit 6ef888
		   Then scan all its blocks: if we find a dinode, set the
Packit 6ef888
		   repaired bitmap to GFS2_BLKST_DINODE. Set all others to
Packit 6ef888
		   GFS2_BLKST_USED so fsck can sort it out. If we set them
Packit 6ef888
		   to FREE, fsck would just nuke it all. */
Packit 6ef888
		printf("Resource group at block %llu (0x%llx) appears to be "
Packit 6ef888
		       "damaged. Attempting to fix it (in reverse order).\n",
Packit 6ef888
		       (unsigned long long)rgd->ri.ri_addr,
Packit 6ef888
		       (unsigned long long)rgd->ri.ri_addr);
Packit 6ef888
Packit 6ef888
		for (b = rgd->ri.ri_length - 1; b >= 0; b--) {
Packit 6ef888
			int mtype = (b ? GFS2_METATYPE_RB : GFS2_METATYPE_RG);
Packit 6ef888
			struct gfs2_meta_header *mh;
Packit 6ef888
Packit 6ef888
			printf("Bitmap #%d:", b);
Packit 6ef888
			rbh = bread(&sbd, rgd->ri.ri_addr + b);
Packit 6ef888
			if (gfs2_check_meta(rbh, mtype)) { /* wrong type */
Packit 6ef888
				printf("Damaged. Repairing...");
Packit 6ef888
				/* Fix the meta header */
Packit 6ef888
				memset(rbh->b_data, 0, sbd.bsize);
Packit 6ef888
				mh = (struct gfs2_meta_header *)rbh->b_data;
Packit 6ef888
				mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
Packit 6ef888
				mh->mh_type = cpu_to_be32(mtype);
Packit 6ef888
				if (b)
Packit 6ef888
					mh->mh_format =
Packit 6ef888
						cpu_to_be32(GFS2_FORMAT_RB);
Packit 6ef888
				else
Packit 6ef888
					mh->mh_format =
Packit 6ef888
						cpu_to_be32(GFS2_FORMAT_RG);
Packit 6ef888
				bmodified(rbh);
Packit 6ef888
				/* Count the dinode blocks */
Packit 6ef888
				dinodes_found = count_dinode_blks(rgd, b, rbh);
Packit 6ef888
			} else { /* bitmap info is okay: tally it. */
Packit 6ef888
				printf("Undamaged. Analyzing...");
Packit 6ef888
				dinodes_found = count_dinode_bits(rbh);
Packit 6ef888
			}
Packit 6ef888
			printf("Dinodes found: %d\n", dinodes_found);
Packit 6ef888
			dinodes_total += dinodes_found;
Packit 6ef888
			if (b == 0) { /* rgrp itself was damaged */
Packit 6ef888
				rgd->rg.rg_dinodes = dinodes_total;
Packit 6ef888
				rgd->rg.rg_free = 0;
Packit 6ef888
			}
Packit 6ef888
			brelse(rbh);
Packit 6ef888
		}
Packit 6ef888
		rgs_fixed++;
Packit 6ef888
	}
Packit 6ef888
	if (rgs_fixed)
Packit 6ef888
		printf("%d resource groups fixed.\n"
Packit 6ef888
		       "You should run fsck.gfs2 to reconcile the bitmaps.\n",
Packit 6ef888
		       rgs_fixed);
Packit 6ef888
	else
Packit 6ef888
		printf("All resource groups are okay. No repairs needed.\n");
Packit 6ef888
	exit(0);
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* parameterpass1 - pre-processing for command-line parameters              */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void parameterpass1(int argc, char *argv[], int i)
Packit 6ef888
{
Packit 6ef888
	if (!strcasecmp(argv[i], "-V")) {
Packit 6ef888
		printf("%s version %s (built %s %s)\n",
Packit 6ef888
		       argv[0], VERSION, __DATE__, __TIME__);
Packit 6ef888
		printf("%s\n", REDHAT_COPYRIGHT);
Packit 6ef888
		exit(0);
Packit 6ef888
	}
Packit 6ef888
	else if (!strcasecmp(argv[i], "-h") ||
Packit 6ef888
		 !strcasecmp(argv[i], "-help") ||
Packit 6ef888
		 !strcasecmp(argv[i], "-usage")) {
Packit 6ef888
		usage();
Packit 6ef888
		exit(0);
Packit 6ef888
	}
Packit 6ef888
	else if (!strcasecmp(argv[i], "-c")) {
Packit 6ef888
		i++;
Packit 6ef888
		color_scheme = atoi(argv[i]);
Packit 6ef888
	}
Packit 6ef888
	else if (!strcasecmp(argv[i], "-p") ||
Packit 6ef888
		 !strcasecmp(argv[i], "-print")) {
Packit 6ef888
		termlines = 0; /* initial value--we'll figure
Packit 6ef888
				  it out later */
Packit 6ef888
		dmode = GFS2_MODE;
Packit 6ef888
	}
Packit 6ef888
	else if (!strcasecmp(argv[i], "-d") ||
Packit 6ef888
		 !strcasecmp(argv[i], "-details"))
Packit 6ef888
		details = 1;
Packit 6ef888
	else if (!strcasecmp(argv[i], "savemeta"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcasecmp(argv[i], "savemetaslow"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcasecmp(argv[i], "savergs"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcasecmp(argv[i], "printsavedmeta")) {
Packit 6ef888
		if (dmode == INIT_MODE)
Packit 6ef888
			dmode = GFS2_MODE;
Packit 6ef888
		restoremeta(argv[i+1], argv[i+2], TRUE);
Packit 6ef888
	} else if (!strcasecmp(argv[i], "restoremeta")) {
Packit 6ef888
		if (dmode == INIT_MODE)
Packit 6ef888
			dmode = HEX_MODE; /* hopefully not used */
Packit 6ef888
		restoremeta(argv[i+1], argv[i+2], FALSE);
Packit 6ef888
	} else if (!strcmp(argv[i], "rgcount"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcmp(argv[i], "rgflags"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcmp(argv[i], "rgrepair"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcmp(argv[i], "rg"))
Packit 6ef888
		termlines = 0;
Packit 6ef888
	else if (!strcasecmp(argv[i], "-x"))
Packit 6ef888
		dmode = HEX_MODE;
Packit 6ef888
	else if (device == NULL && strchr(argv[i],'/')) {
Packit 6ef888
		device = argv[i];
Packit 6ef888
	}
Packit 6ef888
}
Packit 6ef888
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
/* process_parameters - process commandline parameters                      */
Packit 6ef888
/* pass - we make two passes through the parameters; the first pass gathers */
Packit 6ef888
/*        normals parameters, device name, etc.  The second pass is for     */
Packit 6ef888
/*        figuring out what structures to print out.                        */
Packit 6ef888
/* ------------------------------------------------------------------------ */
Packit 6ef888
static void process_parameters(int argc, char *argv[], int pass)
Packit 6ef888
{
Packit 6ef888
	int i;
Packit 6ef888
	uint64_t keyword_blk;
Packit 6ef888
Packit 6ef888
	if (argc < 2) {
Packit 6ef888
		usage();
Packit 6ef888
		die("no device specified\n");
Packit 6ef888
	}
Packit 6ef888
	for (i = 1; i < argc; i++) {
Packit 6ef888
		if (!pass) { /* first pass */
Packit 6ef888
			parameterpass1(argc, argv, i);
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		/* second pass */
Packit 6ef888
		if (!strcasecmp(argv[i], "-s")) {
Packit 6ef888
			i++;
Packit 6ef888
			if (i >= argc - 1) {
Packit 6ef888
				printf("Error: starting block not specified "
Packit 6ef888
				       "with -s.\n");
Packit 6ef888
				printf("%s -s [starting block | keyword] "
Packit 6ef888
				       "<device>\n", argv[0]);
Packit 6ef888
				printf("For example: %s -s \"rg 3\" "
Packit 6ef888
				       "/dev/exxon_vg/exxon_lv\n", argv[0]);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			starting_blk = check_keywords(argv[i]);
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		if (termlines || strchr(argv[i],'/')) /* if print or slash */
Packit 6ef888
			continue;
Packit 6ef888
Packit 6ef888
		if (!strncmp(argv[i], "journal", 7) && isdigit(argv[i][7]) &&
Packit 6ef888
		    strcmp(argv[i+1], "field")) {
Packit 6ef888
			int blk = 0;
Packit 6ef888
Packit 6ef888
			if (i < argc - 1 && isdigit(argv[i + 1][0])) {
Packit 6ef888
				if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
Packit 6ef888
					sscanf(argv[i + 1], "%x", &blk);
Packit 6ef888
				else
Packit 6ef888
					blk = atoi(argv[i + 1]);
Packit 6ef888
			}
Packit 6ef888
			dump_journal(argv[i], blk);
Packit 6ef888
			continue;
Packit 6ef888
		}
Packit 6ef888
		keyword_blk = check_keywords(argv[i]);
Packit 6ef888
		if (keyword_blk)
Packit 6ef888
			push_block(keyword_blk);
Packit 6ef888
		else if (!strcasecmp(argv[i], "-x"))
Packit 6ef888
			dmode = HEX_MODE;
Packit 6ef888
		else if (argv[i][0] == '-') /* if it starts with a dash */
Packit 6ef888
			; /* ignore it--meant for pass == 0 */
Packit 6ef888
		else if (!strcmp(argv[i], "identify"))
Packit 6ef888
			identify = TRUE;
Packit 6ef888
		else if (!strcmp(argv[i], "size")) {
Packit 6ef888
			printf("Device size: %llu (0x%llx)\n",
Packit 6ef888
			       (unsigned long long)max_block,
Packit 6ef888
			       (unsigned long long)max_block);
Packit 6ef888
			exit(EXIT_SUCCESS);
Packit 6ef888
		} else if (!strcmp(argv[i], "rgcount"))
Packit 6ef888
			rgcount();
Packit 6ef888
		else if (!strcmp(argv[i], "field")) {
Packit 6ef888
			i++;
Packit 6ef888
			if (i >= argc - 1) {
Packit 6ef888
				printf("Error: field not specified.\n");
Packit 6ef888
				printf("Format is: %s -p <block> field "
Packit 6ef888
				       "<field> [newvalue]\n", argv[0]);
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			process_field(argv[i], argv[i + 1]);
Packit 6ef888
		} else if (!strcmp(argv[i], "blocktype")) {
Packit 6ef888
			find_print_block_type();
Packit 6ef888
		} else if (!strcmp(argv[i], "blockrg")) {
Packit 6ef888
			find_print_block_rg(0);
Packit 6ef888
		} else if (!strcmp(argv[i], "blockbits")) {
Packit 6ef888
			find_print_block_rg(1);
Packit 6ef888
		} else if (!strcmp(argv[i], "blockalloc")) {
Packit 6ef888
			if (isdigit(argv[i + 1][0])) {
Packit 6ef888
				int newval;
Packit 6ef888
Packit 6ef888
				if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
Packit 6ef888
					sscanf(argv[i + 1], "%x", &newval);
Packit 6ef888
				else
Packit 6ef888
					newval = (uint64_t)atoi(argv[i + 1]);
Packit 6ef888
				find_change_block_alloc(&newval);
Packit 6ef888
			} else {
Packit 6ef888
				find_change_block_alloc(NULL);
Packit 6ef888
			}
Packit 6ef888
		} else if (!strcmp(argv[i], "find")) {
Packit 6ef888
			find_metablockoftype(argv[i + 1], 1);
Packit 6ef888
		} else if (!strcmp(argv[i], "rgflags")) {
Packit 6ef888
			int rg, set = FALSE;
Packit 6ef888
			uint32_t new_flags = 0;
Packit 6ef888
Packit 6ef888
			i++;
Packit 6ef888
			if (i >= argc - 1) {
Packit 6ef888
				printf("Error: rg # not specified.\n");
Packit 6ef888
				printf("Format is: %s rgflags rgnum"
Packit 6ef888
				       "[newvalue]\n", argv[0]);
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			if (argv[i][0]=='0' && argv[i][1]=='x')
Packit 6ef888
				sscanf(argv[i], "%"SCNx32, &rg;;
Packit 6ef888
			else
Packit 6ef888
				rg = atoi(argv[i]);
Packit 6ef888
			i++;
Packit 6ef888
			if (i < argc - 1 &&
Packit 6ef888
			    isdigit(argv[i][0])) {
Packit 6ef888
				set = TRUE;
Packit 6ef888
				if (argv[i][0]=='0' && argv[i][1]=='x')
Packit 6ef888
					sscanf(argv[i], "%"SCNx32, &new_flags);
Packit 6ef888
				else
Packit 6ef888
					new_flags = atoi(argv[i]);
Packit 6ef888
			}
Packit 6ef888
			set_rgrp_flags(rg, new_flags, set, FALSE);
Packit 6ef888
			gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
			exit(EXIT_SUCCESS);
Packit 6ef888
		} else if (!strcmp(argv[i], "rg")) {
Packit 6ef888
			int rg;
Packit 6ef888
				
Packit 6ef888
			i++;
Packit 6ef888
			if (i >= argc - 1) {
Packit 6ef888
				printf("Error: rg # not specified.\n");
Packit 6ef888
				printf("Format is: %s rg rgnum\n", argv[0]);
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			rg = atoi(argv[i]);
Packit 6ef888
			if (!strcasecmp(argv[i + 1], "find")) {
Packit 6ef888
				temp_blk = get_rg_addr(rg);
Packit 6ef888
				push_block(temp_blk);
Packit 6ef888
			} else {
Packit 6ef888
				set_rgrp_flags(rg, 0, FALSE, TRUE);
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_SUCCESS);
Packit 6ef888
			}
Packit 6ef888
		} else if (!strcmp(argv[i], "rgbitmaps")) {
Packit 6ef888
			int rg, bmap;
Packit 6ef888
			uint64_t rgblk;
Packit 6ef888
			struct rgrp_tree *rgd;
Packit 6ef888
Packit 6ef888
			i++;
Packit 6ef888
			if (i >= argc - 1) {
Packit 6ef888
				printf("Error: rg # not specified.\n");
Packit 6ef888
				printf("Format is: %s rgbitmaps rgnum\n",
Packit 6ef888
				       argv[0]);
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			rg = atoi(argv[i]);
Packit 6ef888
			rgblk = get_rg_addr(rg);
Packit 6ef888
			rgd = gfs2_blk2rgrpd(&sbd, rgblk);
Packit 6ef888
			if (rgd == NULL) {
Packit 6ef888
				printf("Error: rg # is invalid.\n");
Packit 6ef888
				gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
				exit(EXIT_FAILURE);
Packit 6ef888
			}
Packit 6ef888
			for (bmap = 0; bmap < rgd->ri.ri_length; bmap++)
Packit 6ef888
				push_block(rgblk + bmap);
Packit 6ef888
		}
Packit 6ef888
		else if (!strcmp(argv[i], "rgrepair"))
Packit 6ef888
			rg_repair();
Packit 6ef888
		else if (!strcasecmp(argv[i], "savemeta")) {
Packit 6ef888
			getgziplevel(argv, &i);
Packit 6ef888
			savemeta(argv[i+2], 0, gziplevel);
Packit 6ef888
		} else if (!strcasecmp(argv[i], "savemetaslow")) {
Packit 6ef888
			getgziplevel(argv, &i);
Packit 6ef888
			savemeta(argv[i+2], 1, gziplevel);
Packit 6ef888
		} else if (!strcasecmp(argv[i], "savergs")) {
Packit 6ef888
			getgziplevel(argv, &i);
Packit 6ef888
			savemeta(argv[i+2], 2, gziplevel);
Packit 6ef888
		} else if (isdigit(argv[i][0])) { /* decimal addr */
Packit 6ef888
			sscanf(argv[i], "%"SCNd64, &temp_blk);
Packit 6ef888
			push_block(temp_blk);
Packit 6ef888
		} else {
Packit 6ef888
			fprintf(stderr,"I don't know what '%s' means.\n",
Packit 6ef888
				argv[i]);
Packit 6ef888
			usage();
Packit 6ef888
			exit(EXIT_FAILURE);
Packit 6ef888
		}
Packit 6ef888
	} /* for */
Packit 6ef888
}/* process_parameters */
Packit 6ef888
Packit 6ef888
int main(int argc, char *argv[])
Packit 6ef888
{
Packit 6ef888
	int i, j, fd;
Packit 6ef888
Packit 6ef888
	indirect = malloc(sizeof(struct iinfo));
Packit 6ef888
	if (!indirect)
Packit 6ef888
		die("Out of memory.");
Packit 6ef888
	memset(indirect, 0, sizeof(struct iinfo));
Packit 6ef888
	memset(start_row, 0, sizeof(start_row));
Packit 6ef888
	memset(lines_per_row, 0, sizeof(lines_per_row));
Packit 6ef888
	memset(end_row, 0, sizeof(end_row));
Packit 6ef888
	memset(edit_row, 0, sizeof(edit_row));
Packit 6ef888
	memset(edit_col, 0, sizeof(edit_col));
Packit 6ef888
	memset(edit_size, 0, sizeof(edit_size));
Packit 6ef888
	memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
Packit 6ef888
	dmode = INIT_MODE;
Packit 6ef888
	sbd.bsize = 4096;
Packit 6ef888
	block = starting_blk = 0x10;
Packit 6ef888
	for (i = 0; i < BLOCK_STACK_SIZE; i++) {
Packit 6ef888
		blockstack[i].dmode = HEX_MODE;
Packit 6ef888
		blockstack[i].block = block;
Packit 6ef888
		for (j = 0; j < DMODES; j++) {
Packit 6ef888
			blockstack[i].start_row[j] = 0;
Packit 6ef888
			blockstack[i].end_row[j] = 0;
Packit 6ef888
			blockstack[i].edit_row[j] = 0;
Packit 6ef888
			blockstack[i].edit_col[j] = 0;
Packit 6ef888
			blockstack[i].lines_per_row[j] = 0;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
Packit 6ef888
	edit_row[GFS2_MODE] = 10; /* Start off at root inode
Packit 6ef888
				     pointer in superblock */
Packit 6ef888
	termlines = 30;  /* assume interactive mode until we find -p */
Packit 6ef888
	process_parameters(argc, argv, 0);
Packit 6ef888
	if (dmode == INIT_MODE)
Packit 6ef888
		dmode = HEX_MODE;
Packit 6ef888
Packit 6ef888
	fd = open(device, O_RDWR);
Packit 6ef888
	if (fd < 0)
Packit 6ef888
		die("can't open %s: %s\n", device, strerror(errno));
Packit 6ef888
	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
Packit 6ef888
Packit 6ef888
	read_superblock(fd);
Packit 6ef888
	if (read_rindex())
Packit 6ef888
		exit(-1);
Packit 6ef888
	max_block = lseek(fd, 0, SEEK_END) / sbd.bsize;
Packit 6ef888
	if (sbd.gfs1)
Packit 6ef888
		edit_row[GFS2_MODE]++;
Packit 6ef888
	else if (read_master_dir() != 0)
Packit 6ef888
		exit(-1);
Packit 6ef888
Packit 6ef888
	process_parameters(argc, argv, 1); /* get what to print from cmdline */
Packit 6ef888
Packit 6ef888
	block = blockstack[0].block = starting_blk * (4096 / sbd.bsize);
Packit 6ef888
Packit 6ef888
	if (termlines)
Packit 6ef888
		interactive_mode();
Packit 6ef888
	else { /* print all the structures requested */
Packit 6ef888
		i = 0;
Packit 6ef888
		while (blockhist > 0) {
Packit 6ef888
			block = blockstack[i + 1].block;
Packit 6ef888
			if (!block)
Packit 6ef888
				break;
Packit 6ef888
			display(identify, 0, 0, 0);
Packit 6ef888
			if (!identify) {
Packit 6ef888
				display_extended();
Packit 6ef888
				printf("-------------------------------------" \
Packit 6ef888
				       "-----------------");
Packit 6ef888
				eol(0);
Packit 6ef888
			}
Packit 6ef888
			block = pop_block();
Packit 6ef888
			i++;
Packit 6ef888
		}
Packit 6ef888
	}
Packit 6ef888
	close(fd);
Packit 6ef888
	if (indirect)
Packit 6ef888
		free(indirect);
Packit 6ef888
	gfs2_rgrp_free(&sbd.rgtree);
Packit 6ef888
 	exit(EXIT_SUCCESS);
Packit 6ef888
}