LCOV - code coverage report
Current view: top level - edit - hexedit.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 376 1554 24.2 %
Date: 2023-10-25 12:04:14 Functions: 24 52 46.2 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <stdlib.h>
       5             : #include <ctype.h>
       6             : #include <string.h>
       7             : #include <inttypes.h>
       8             : #include <sys/types.h>
       9             : #include <sys/stat.h>
      10             : #include <fcntl.h>
      11             : #include <unistd.h>
      12             : #include <errno.h>
      13             : #include <curses.h>
      14             : #include <term.h>
      15             : #include <signal.h>
      16             : #include <sys/ioctl.h>
      17             : #include <sys/mount.h>
      18             : #include <dirent.h>
      19             : 
      20             : #include "copyright.cf"
      21             : 
      22             : #include "hexedit.h"
      23             : #include "libgfs2.h"
      24             : #include "gfs2hex.h"
      25             : #include "extended.h"
      26             : #include "journal.h"
      27             : #include "struct_print.h"
      28             : 
      29             : const char *mtypes[] = {"none", "sb", "rg", "rb", "di", "in", "lf", "jd",
      30             :                         "lh", "ld", "ea", "ed", "lb", "13", "qc"};
      31             : const char *allocdesc[5] = {"Free ", "Data ", "Unlnk", "Meta ", "Resrv"};
      32             : 
      33             : static struct lgfs2_buffer_head *bh;
      34             : static int pgnum;
      35             : static long int gziplevel = 9;
      36             : static int termcols;
      37             : 
      38             : int details = 0;
      39             : char *device = NULL;
      40             : 
      41             : /* ------------------------------------------------------------------------- */
      42             : /* erase - clear the screen */
      43             : /* ------------------------------------------------------------------------- */
      44           0 : static void Erase(void)
      45             : {
      46           0 :         bkgd(A_NORMAL|COLOR_PAIR(COLOR_NORMAL));
      47             :         /* clear();*/ /* doesn't set background correctly */
      48           0 :         erase();
      49             :         /*bkgd(bg);*/
      50           0 : }
      51             : 
      52             : /* ------------------------------------------------------------------------- */
      53             : /* display_title_lines */
      54             : /* ------------------------------------------------------------------------- */
      55           0 : static void display_title_lines(void)
      56             : {
      57           0 :         Erase();
      58           0 :         COLORS_TITLE;
      59           0 :         move(0, 0);
      60           0 :         printw("%-80s",TITLE1);
      61           0 :         move(termlines, 0);
      62           0 :         printw("%-79s",TITLE2);
      63           0 :         COLORS_NORMAL;
      64           0 : }
      65             : 
      66             : /* ------------------------------------------------------------------------- */
      67             : /* bobgets - get a string                                                    */
      68             : /* returns: 1 if user exited by hitting enter                                */
      69             : /*          0 if user exited by hitting escape                               */
      70             : /* ------------------------------------------------------------------------- */
      71           0 : static int bobgets(char string[],int x,int y,int sz,int *ch)
      72             : {
      73             :         int done,runningy,rc;
      74             : 
      75           0 :         move(x,y);
      76           0 :         done=FALSE;
      77           0 :         COLORS_INVERSE;
      78           0 :         move(x,y);
      79           0 :         addstr(string);
      80           0 :         move(x,y);
      81           0 :         curs_set(2);
      82           0 :         refresh();
      83           0 :         runningy=y;
      84           0 :         rc=0;
      85           0 :         while (!done) {
      86           0 :                 *ch = getch();
      87             :                 
      88           0 :                 if(*ch < 0x0100 && isprint(*ch)) {
      89           0 :                         char *p=string+strlen(string); // end of the string
      90             : 
      91           0 :                         *(p+1)='\0';
      92           0 :                         while (insert && p > &string[runningy-y]) {
      93           0 :                                 *p=*(p-1);
      94           0 :                                 p--;
      95             :                         }
      96           0 :                         string[runningy-y]=*ch;
      97           0 :                         runningy++;
      98           0 :                         move(x,y);
      99           0 :                         addstr(string);
     100           0 :                         if (runningy-y >= sz) {
     101           0 :                                 rc=1;
     102           0 :                                 *ch = KEY_RIGHT;
     103           0 :                                 done = TRUE;
     104             :                         }
     105             :                 }
     106             :                 else {
     107             :                         // special character, is it one we recognize?
     108           0 :                         switch(*ch)
     109             :                         {
     110           0 :                         case(KEY_ENTER):
     111             :                         case('\n'):
     112             :                         case('\r'):
     113           0 :                                 rc=1;
     114           0 :                                 done=TRUE;
     115           0 :                                 string[runningy-y] = '\0';
     116           0 :                                 break;
     117           0 :                         case(KEY_CANCEL):
     118             :                         case(0x01B):
     119           0 :                                 rc=0;
     120           0 :                                 done=TRUE;
     121           0 :                                 break;
     122           0 :                         case(KEY_LEFT):
     123           0 :                                 if (dmode == HEX_MODE) {
     124           0 :                                         done = TRUE;
     125           0 :                                         rc = 1;
     126             :                                 }
     127             :                                 else
     128           0 :                                         runningy--;
     129           0 :                                 break;
     130           0 :                         case(KEY_RIGHT):
     131           0 :                                 if (dmode == HEX_MODE) {
     132           0 :                                         done = TRUE;
     133           0 :                                         rc = 1;
     134             :                                 }
     135             :                                 else
     136           0 :                                         runningy++;
     137           0 :                                 break;
     138           0 :                         case(KEY_DC):
     139             :                         case(0x07F):
     140           0 :                                 if (runningy>=y) {
     141             :                                         char *p;
     142           0 :                                         p = &string[runningy - y];
     143           0 :                                         while (*p) {
     144           0 :                                                 *p = *(p + 1);
     145           0 :                                                 p++;
     146             :                                         }
     147           0 :                                         *p = '\0';
     148           0 :                                         runningy--;
     149             :                                         // remove the character from the string 
     150           0 :                                         move(x,y);
     151           0 :                                         addstr(string);
     152           0 :                                         COLORS_NORMAL;
     153           0 :                                         addstr(" ");
     154           0 :                                         COLORS_INVERSE;
     155           0 :                                         runningy++;
     156             :                                 }
     157           0 :                                 break;
     158           0 :                         case(KEY_BACKSPACE):
     159           0 :                                 if (runningy>y) {
     160             :                                         char *p;
     161             : 
     162           0 :                                         p = &string[runningy - y - 1];
     163           0 :                                         while (*p) {
     164           0 :                                                 *p = *(p + 1);
     165           0 :                                                 p++;
     166             :                                         }
     167           0 :                                         *p='\0';
     168           0 :                                         runningy--;
     169             :                                         // remove the character from the string 
     170           0 :                                         move(x,y);
     171           0 :                                         addstr(string);
     172           0 :                                         COLORS_NORMAL;
     173           0 :                                         addstr(" ");
     174           0 :                                         COLORS_INVERSE;
     175             :                                 }
     176           0 :                                 break;
     177           0 :                         case KEY_DOWN:  // Down
     178           0 :                                 rc=0x5000U;
     179           0 :                                 done=TRUE;
     180           0 :                                 break;
     181           0 :                         case KEY_UP:    // Up
     182           0 :                                 rc=0x4800U;
     183           0 :                                 done=TRUE;
     184           0 :                                 break;
     185           0 :                         case 0x014b:
     186           0 :                                 insert=!insert;
     187           0 :                                 move(0,68);
     188           0 :                                 if (insert)
     189           0 :                                         printw("insert ");
     190             :                                 else
     191           0 :                                         printw("replace");
     192           0 :                                 break;
     193           0 :                         default:
     194           0 :                                 move(0,70);
     195           0 :                                 printw("%08x",*ch);
     196             :                                 // ignore all other characters
     197           0 :                                 break;
     198             :                         } // end switch on non-printable character
     199             :                 } // end non-printable character
     200           0 :                 move(x,runningy);
     201           0 :                 refresh();
     202             :         } // while !done
     203           0 :         if (sz>0)
     204           0 :                 string[sz]='\0';
     205           0 :         COLORS_NORMAL;
     206           0 :         return rc;
     207             : }/* bobgets */
     208             : 
     209             : /******************************************************************************
     210             : ** instr - instructions
     211             : ******************************************************************************/
     212           0 : static void gfs2instr(const char *s1, const char *s2)
     213             : {
     214           0 :         COLORS_HIGHLIGHT;
     215           0 :         move(line,0);
     216           0 :         printw("%s", s1);
     217           0 :         COLORS_NORMAL;
     218           0 :         move(line,17);
     219           0 :         printw("%s", s2);
     220           0 :         line++;
     221           0 : }
     222             : 
     223             : /******************************************************************************
     224             : *******************************************************************************
     225             : **
     226             : ** void print_usage()
     227             : **
     228             : ** Description:
     229             : **   This routine prints out the appropriate commands for this application.
     230             : **
     231             : *******************************************************************************
     232             : ******************************************************************************/
     233             : 
     234           0 : static void print_usage(void)
     235             : {
     236           0 :         line = 2;
     237           0 :         Erase();
     238           0 :         display_title_lines();
     239           0 :         move(line++,0);
     240           0 :         printw("Supported commands: (roughly conforming to the rules of 'less')");
     241           0 :         line++;
     242           0 :         move(line++,0);
     243           0 :         printw("Navigation:");
     244           0 :         gfs2instr("<pg up>/<down>","Move up or down one screen full");
     245           0 :         gfs2instr("<up>/<down>","Move up or down one line");
     246           0 :         gfs2instr("<left>/<right>","Move left or right one byte");
     247           0 :         gfs2instr("<home>","Return to the superblock.");
     248           0 :         gfs2instr("   f","Forward one 4K block");
     249           0 :         gfs2instr("   b","Backward one 4K block");
     250           0 :         gfs2instr("   g","Goto a given block (number, master, root, rindex, jindex, etc)");
     251           0 :         gfs2instr("   j","Jump to the highlighted 64-bit block number.");
     252           0 :         gfs2instr("    ","(You may also arrow up to the block number and hit enter)");
     253           0 :         gfs2instr("<backspace>","Return to a previous block (a block stack is kept)");
     254           0 :         gfs2instr("<space>","Jump forward to block before backspace (opposite of backspace)");
     255           0 :         line++;
     256           0 :         move(line++, 0);
     257           0 :         printw("Other commands:");
     258           0 :         gfs2instr("   h","This Help display");
     259           0 :         gfs2instr("   c","Toggle the color scheme");
     260           0 :         gfs2instr("   m","Switch display mode: hex -> GFS2 structure -> Extended");
     261           0 :         gfs2instr("   q","Quit (same as hitting <escape> key)");
     262           0 :         gfs2instr("<enter>","Edit a value (enter to save, esc to discard)");
     263           0 :         gfs2instr("       ","(Currently only works on the hex display)");
     264           0 :         gfs2instr("<escape>","Quit the program");
     265           0 :         line++;
     266           0 :         move(line++, 0);
     267           0 :         printw("Notes: Areas shown in red are outside the bounds of the struct/file.");
     268           0 :         move(line++, 0);
     269           0 :         printw("       Areas shown in blue are file contents.");
     270           0 :         move(line++, 0);
     271           0 :         printw("       Characters shown in green are selected for edit on <enter>.");
     272           0 :         move(line++, 0);
     273           0 :         move(line++, 0);
     274           0 :         printw("Press any key to return.");
     275           0 :         refresh();
     276           0 :         getch(); // wait for input
     277           0 :         Erase();
     278           0 : }
     279             : 
     280          15 : const struct lgfs2_metadata *get_block_type(char *buf)
     281             : {
     282          15 :         uint32_t t = lgfs2_get_block_type(buf);
     283             : 
     284          15 :         if (t != 0)
     285          15 :                 return lgfs2_find_mtype(t);
     286           0 :         return NULL;
     287             : }
     288             : 
     289             : /**
     290             :  * returns: metatype if block is a GFS2 structure block type
     291             :  *          0 if block is not a GFS2 structure
     292             :  */
     293           7 : int display_block_type(char *buf, uint64_t addr, int from_restore)
     294             : {
     295             :         const struct lgfs2_metadata *mtype;
     296             :         const struct gfs2_meta_header *mh;
     297           7 :         int ret_type = 0; /* return type */
     298             : 
     299             :         /* first, print out the kind of GFS2 block this is */
     300           7 :         if (termlines) {
     301           0 :                 line = 1;
     302           0 :                 move(line, 0);
     303             :         }
     304           7 :         print_gfs2("Block #");
     305           7 :         if (termlines) {
     306           0 :                 if (edit_row[dmode] == -1)
     307           0 :                         COLORS_HIGHLIGHT;
     308             :         }
     309           7 :         if (block == RGLIST_DUMMY_BLOCK)
     310           0 :                 print_gfs2("RG List       ");
     311           7 :         else if (block == JOURNALS_DUMMY_BLOCK)
     312           0 :                 print_gfs2("Journal Status:      ");
     313             :         else
     314           7 :                 print_gfs2("%"PRIu64"    (0x%"PRIx64")", addr, addr);
     315           7 :         if (termlines) {
     316           0 :                 if (edit_row[dmode] == -1)
     317           0 :                         COLORS_NORMAL;
     318             :         }
     319           7 :         print_gfs2(" ");
     320           7 :         if (!from_restore)
     321           7 :                 print_gfs2("of %"PRIu64" (0x%"PRIx64") ", max_block, max_block);
     322           7 :         if (block == RGLIST_DUMMY_BLOCK) {
     323           0 :                 ret_type = GFS2_METATYPE_RG;
     324           0 :                 struct_len = sizeof(struct gfs2_rgrp);
     325           7 :         } else if (block == JOURNALS_DUMMY_BLOCK) {
     326           0 :                 ret_type = GFS2_METATYPE_DI;
     327           0 :                 struct_len = 0;
     328             :         } else {
     329           7 :                 mtype = get_block_type(buf);
     330           7 :                 if (mtype != NULL) {
     331           7 :                         print_gfs2("(%s)", mtype->display);
     332           7 :                         struct_len = mtype->size;
     333           7 :                         ret_type = mtype->mh_type;
     334             :                 } else {
     335           0 :                         struct_len = sbd.sd_bsize;
     336           0 :                         ret_type = 0;
     337             :                 }
     338             :         }
     339           7 :         mh = (void *)buf;
     340           7 :         eol(0);
     341           7 :         if (from_restore)
     342           0 :                 return ret_type;
     343           7 :         if (termlines && dmode == HEX_MODE) {
     344             :                 int type;
     345             :                 struct lgfs2_rgrp_tree *rgd;
     346             : 
     347           0 :                 rgd = lgfs2_blk2rgrpd(&sbd, block);
     348           0 :                 if (rgd) {
     349           0 :                         lgfs2_rgrp_read(&sbd, rgd);
     350           0 :                         if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG) ||
     351           0 :                             (be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB))
     352           0 :                                 type = 4;
     353             :                         else {
     354           0 :                                 type = lgfs2_get_bitmap(&sbd, block, rgd);
     355             :                         }
     356             :                 } else
     357           0 :                         type = 4;
     358           0 :                 screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8;
     359           0 :                 if (!screen_chunk_size)
     360           0 :                         screen_chunk_size = 256;
     361           0 :                 pgnum = (offset / screen_chunk_size);
     362           0 :                 if (type >= 0) {
     363           0 :                         print_gfs2("(p.%d of %d--%s)", pgnum + 1,
     364           0 :                                    (sbd.sd_bsize % screen_chunk_size) > 0 ?
     365           0 :                                    sbd.sd_bsize / screen_chunk_size + 1 : sbd.sd_bsize /
     366             :                                    screen_chunk_size, allocdesc[type]);
     367             :                 }
     368             :                 /*eol(9);*/
     369           0 :                 if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG)) {
     370           0 :                         int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
     371             : 
     372           0 :                         if (rgd && (ptroffset >= struct_len || pgnum)) {
     373             :                                 int blknum, b, btype;
     374             : 
     375           0 :                                 blknum = pgnum * screen_chunk_size;
     376           0 :                                 blknum += (ptroffset - struct_len);
     377           0 :                                 blknum *= 4;
     378           0 :                                 blknum += rgd->rt_data0;
     379             : 
     380           0 :                                 print_gfs2(" blk ");
     381           0 :                                 for (b = blknum; b < blknum + 4; b++) {
     382           0 :                                         btype = lgfs2_get_bitmap(&sbd, b, rgd);
     383           0 :                                         if (btype >= 0) {
     384           0 :                                                 print_gfs2("0x%x-%s  ", b,
     385             :                                                            allocdesc[btype]);
     386             :                                         }
     387             :                                 }
     388             :                         }
     389           0 :                 } else if ((be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB)) {
     390           0 :                         int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
     391             : 
     392           0 :                         if (rgd && (ptroffset >= struct_len || pgnum)) {
     393             :                                 int blknum, b, btype, rb_number;
     394             : 
     395           0 :                                 rb_number = block - rgd->rt_addr;
     396           0 :                                 blknum = 0;
     397             :                                 /* count the number of bytes representing
     398             :                                    blocks prior to the displayed screen. */
     399           0 :                                 for (b = 0; b < rb_number; b++) {
     400           0 :                                         struct_len = (b ?
     401             :                                               sizeof(struct gfs2_meta_header) :
     402             :                                               sizeof(struct gfs2_rgrp));
     403           0 :                                         blknum += (sbd.sd_bsize - struct_len);
     404             :                                 }
     405           0 :                                 struct_len = sizeof(struct gfs2_meta_header);
     406             :                                 /* add the number of bytes on this screen */
     407           0 :                                 blknum += (ptroffset - struct_len);
     408             :                                 /* factor in the page number */
     409           0 :                                 blknum += pgnum * screen_chunk_size;
     410             :                                 /* convert bytes to blocks */
     411           0 :                                 blknum *= GFS2_NBBY;
     412             :                                 /* add the starting offset for this rgrp */
     413           0 :                                 blknum += rgd->rt_data0;
     414           0 :                                 print_gfs2(" blk ");
     415           0 :                                 for (b = blknum; b < blknum + 4; b++) {
     416           0 :                                         btype = lgfs2_get_bitmap(&sbd, b, rgd);
     417           0 :                                         if (btype >= 0) {
     418           0 :                                                 print_gfs2("0x%x-%s  ", b,
     419             :                                                            allocdesc[btype]);
     420             :                                         }
     421             :                                 }
     422             :                         }
     423             :                 }
     424           0 :                 if (rgd)
     425           0 :                         lgfs2_rgrp_relse(&sbd, rgd);
     426             :         }
     427           7 :         if (block == sbd.sd_root_dir.in_addr)
     428           0 :                 print_gfs2("--------------- Root directory ------------------");
     429           7 :         else if (block == sbd.sd_meta_dir.in_addr)
     430           0 :                 print_gfs2("-------------- Master directory -----------------");
     431           7 :         else if (block == RGLIST_DUMMY_BLOCK)
     432           0 :                 print_gfs2("------------------ RG List ----------------------");
     433           7 :         else if (block == JOURNALS_DUMMY_BLOCK)
     434           0 :                 print_gfs2("-------------------- Journal List --------------------");
     435             :         else {
     436             :                 int d;
     437             : 
     438          49 :                 for (d = 2; d < 8; d++) {
     439          42 :                         if (block == masterdir.dirent[d].inum.in_addr) {
     440           7 :                                 if (!strncmp(masterdir.dirent[d].filename, "jindex", 6))
     441           0 :                                         print_gfs2("--------------- Journal Index ------------------");
     442           7 :                                 else if (!strncmp(masterdir.dirent[d].filename, "per_node", 8))
     443           0 :                                         print_gfs2("--------------- Per-node Dir -------------------");
     444           7 :                                 else if (!strncmp(masterdir.dirent[d].filename, "inum", 4))
     445           0 :                                         print_gfs2("---------------- Inum file ---------------------");
     446           7 :                                 else if (!strncmp(masterdir.dirent[d].filename, "statfs", 6))
     447           0 :                                         print_gfs2("---------------- statfs file -------------------");
     448           7 :                                 else if (!strncmp(masterdir.dirent[d].filename, "rindex", 6))
     449           7 :                                         print_gfs2("---------------- rindex file -------------------");
     450           0 :                                 else if (!strncmp(masterdir.dirent[d].filename, "quota", 5))
     451           0 :                                         print_gfs2("---------------- Quota file --------------------");
     452             :                         }
     453             :                 }
     454             :         }
     455           7 :         eol(0);
     456           7 :         return ret_type;
     457             : }
     458             : 
     459           0 : static int get_pnum(int ptroffset)
     460             : {
     461             :         int pnum;
     462             : 
     463           0 :         pnum = pgnum * screen_chunk_size;
     464           0 :         pnum += (ptroffset - struct_len);
     465           0 :         pnum /= sizeof(uint64_t);
     466             : 
     467           0 :         return pnum;
     468             : }
     469             : 
     470             : /* ------------------------------------------------------------------------ */
     471             : /* hexdump - hex dump the filesystem block to the screen                    */
     472             : /* ------------------------------------------------------------------------ */
     473           0 : static int hexdump(uint64_t startaddr, uint64_t len, int trunc_zeros,
     474             :                    uint64_t flagref, uint64_t ref_blk)
     475             : {
     476             :         const unsigned char *pointer, *ptr2;
     477             :         int i;
     478             :         uint64_t l;
     479           0 :         const char *lpBuffer = bh->b_data;
     480           0 :         const char *zeros_strt = lpBuffer + sbd.sd_bsize;
     481             :         int print_field, cursor_line;
     482           0 :         const struct lgfs2_metadata *m = get_block_type(bh->b_data);
     483             :         __be64 *ref;
     484           0 :         int ptroffset = 0;
     485             : 
     486           0 :         strcpy(edit_fmt,"%02x");
     487           0 :         pointer = (unsigned char *)lpBuffer + offset;
     488           0 :         ptr2 = (unsigned char *)lpBuffer + offset;
     489           0 :         ref = (__be64 *)lpBuffer + offset;
     490           0 :         if (trunc_zeros) {
     491           0 :                 while (zeros_strt > lpBuffer && (*(zeros_strt - 1) == 0))
     492           0 :                         zeros_strt--;
     493             :         }
     494           0 :         l = offset;
     495           0 :         print_entry_ndx = 0;
     496           0 :         while (((termlines && line < termlines &&
     497           0 :                  line <= ((screen_chunk_size / 16) + 2)) ||
     498           0 :                 (!termlines && l < len)) && l < sbd.sd_bsize) {
     499           0 :                 int ptr_not_null = 0;
     500             : 
     501           0 :                 if (termlines) {
     502           0 :                         move(line, 0);
     503           0 :                         COLORS_OFFSETS; /* cyan for offsets */
     504             :                 }
     505           0 :                 if (startaddr < 0xffffffff)
     506           0 :                         print_gfs2("%.8"PRIx64, startaddr + l);
     507             :                 else
     508           0 :                         print_gfs2("%.16"PRIx64, startaddr + l);
     509           0 :                 if (termlines) {
     510           0 :                         if (l < struct_len)
     511           0 :                                 COLORS_NORMAL; /* normal part of structure */
     512           0 :                         else if (gfs2_struct_type == GFS2_METATYPE_DI &&
     513           0 :                                          l < struct_len + be64_to_cpu(di->di_size))
     514           0 :                                 COLORS_CONTENTS; /* after struct but not eof */
     515             :                         else
     516           0 :                                 COLORS_SPECIAL; /* beyond end of the struct */
     517             :                 }
     518           0 :                 print_field = -1;
     519           0 :                 cursor_line = 0;
     520           0 :                 for (i = 0; i < 16; i++) { /* first print it in hex */
     521             :                         /* Figure out if we have a null pointer--for colors */
     522           0 :                         if (((gfs2_struct_type == GFS2_METATYPE_IN) ||
     523           0 :                              (gfs2_struct_type == GFS2_METATYPE_DI &&
     524           0 :                               l < struct_len + be64_to_cpu(di->di_size) &&
     525           0 :                               (be16_to_cpu(di->di_height) > 0 ||
     526           0 :                               !S_ISREG(be32_to_cpu(di->di_mode))))) &&
     527           0 :                             (i==0 || i==8)) {
     528             :                                 int j;
     529             : 
     530           0 :                                 ptr_not_null = 0;
     531           0 :                                 for (j = 0; j < 8; j++) {
     532           0 :                                         if (*(pointer + j)) {
     533           0 :                                                 ptr_not_null = 1;
     534           0 :                                                 break;
     535             :                                         }
     536             :                                 }
     537             :                         }
     538           0 :                         if (termlines) {
     539           0 :                                 if (l + i < struct_len)
     540           0 :                                         COLORS_NORMAL; /* in the structure */
     541           0 :                                 else if (gfs2_struct_type == GFS2_METATYPE_DI
     542           0 :                                          && l + i < struct_len + be64_to_cpu(di->di_size)) {
     543           0 :                                         if ((!di->di_height &&
     544           0 :                                              S_ISREG(be32_to_cpu(di->di_mode))) ||
     545             :                                             !ptr_not_null)
     546           0 :                                                 COLORS_CONTENTS;/*stuff data */
     547             :                                         else
     548           0 :                                                 COLORS_SPECIAL;/* non-null */
     549             :                                 }
     550           0 :                                 else if (gfs2_struct_type == GFS2_METATYPE_IN){
     551           0 :                                         if (ptr_not_null)
     552           0 :                                                 COLORS_SPECIAL;/* non-null */
     553             :                                         else
     554           0 :                                                 COLORS_CONTENTS;/* null */
     555             :                                 } else
     556           0 :                                         COLORS_SPECIAL; /* past the struct */
     557             :                         }
     558           0 :                         if (i%4 == 0)
     559           0 :                                 print_gfs2(" ");
     560           0 :                         if (termlines && line == edit_row[dmode] + 3 &&
     561           0 :                                 i == edit_col[dmode]) {
     562           0 :                                 COLORS_HIGHLIGHT; /* in the structure */
     563           0 :                                 memset(estring,0,3);
     564           0 :                                 sprintf(estring,"%02x",*pointer);
     565           0 :                                 cursor_line = 1;
     566           0 :                                 print_field = (char *)pointer - bh->b_data;
     567             :                         }
     568           0 :                         print_gfs2("%02x",*pointer);
     569           0 :                         if (termlines && line == edit_row[dmode] + 3 &&
     570           0 :                                 i == edit_col[dmode]) {
     571           0 :                                 if (l < struct_len + offset)
     572           0 :                                         COLORS_NORMAL; /* in the structure */
     573             :                                 else
     574           0 :                                         COLORS_SPECIAL; /* beyond structure */
     575             :                         }
     576           0 :                         pointer++;
     577             :                 }
     578           0 :                 print_gfs2(" [");
     579           0 :                 for (i=0; i<16; i++) { /* now print it in character format */
     580           0 :                         if ((*ptr2 >=' ') && (*ptr2 <= '~'))
     581           0 :                                 print_gfs2("%c",*ptr2);
     582             :                         else
     583           0 :                                 print_gfs2(".");
     584           0 :                         ptr2++;
     585             :                 }
     586           0 :                 print_gfs2("] ");
     587           0 :                 if (print_field >= 0) {
     588           0 :                         if (m) {
     589             :                                 const struct lgfs2_metafield *f;
     590             :                                 unsigned n;
     591           0 :                                 for (n = 0; n < m->nfields; n++) {
     592           0 :                                         f = &m->fields[n];
     593           0 :                                         if (print_field >= f->offset &&
     594           0 :                                             print_field < (f->offset + f->length)) {
     595           0 :                                                 print_gfs2("%s", m->fields[n].name);
     596           0 :                                                 break;
     597             :                                         }
     598             :                                 }
     599             :                         }
     600             : 
     601             :                 }
     602           0 :                 if (m && cursor_line) {
     603           0 :                         const uint32_t block_type = m->mh_type;
     604             :                         int isdir;
     605             : 
     606           0 :                         isdir = ((block_type == GFS2_METATYPE_DI) &&
     607           0 :                                  (((struct gfs2_dinode*)bh->b_data)->di_height ||
     608           0 :                                   S_ISDIR(be32_to_cpu(di->di_mode))));
     609             : 
     610           0 :                         if (block_type == GFS2_METATYPE_IN ||
     611           0 :                             block_type == GFS2_METATYPE_LD || isdir) {
     612             : 
     613           0 :                                 ptroffset = edit_row[dmode] * 16 +
     614           0 :                                         edit_col[dmode];
     615             : 
     616           0 :                                 if (ptroffset >= struct_len || pgnum) {
     617           0 :                                         int pnum = get_pnum(ptroffset);
     618           0 :                                         if (block_type == GFS2_METATYPE_LD)
     619           0 :                                                 print_gfs2("*");
     620           0 :                                         print_gfs2("pointer 0x%x", pnum);
     621             :                                 }
     622             :                         }
     623             :                 }
     624           0 :                 if (line - 3 > last_entry_onscreen[dmode])
     625           0 :                         last_entry_onscreen[dmode] = line - 3;
     626           0 :                 if (flagref && be64_to_cpu(*ref) == flagref)
     627           0 :                         print_gfs2("<------------------------- ref in 0x%"PRIx64" "
     628             :                                    "to 0x%"PRIx64, ref_blk, flagref);
     629           0 :                 ref++;
     630           0 :                 if (flagref && be64_to_cpu(*ref) == flagref)
     631           0 :                         print_gfs2("<------------------------- ref in 0x%"PRIx64" "
     632             :                                    "to 0x%"PRIx64, ref_blk, flagref);
     633           0 :                 ref++;
     634           0 :                 eol(0);
     635           0 :                 l += 16;
     636           0 :                 print_entry_ndx++;
     637             :                 /* This should only happen if trunc_zeros is specified: */
     638           0 :                 if ((const char *)pointer >= zeros_strt)
     639           0 :                         break;
     640             :         } /* while */
     641           0 :         if (m && m->mh_type == GFS2_METATYPE_LD && ptroffset >= struct_len) {
     642           0 :                 COLORS_NORMAL;
     643           0 :                 eol(0);
     644           0 :                 print_gfs2("         * 'j' will jump to the journaled block, "
     645             :                            "not the absolute block.");
     646           0 :                 eol(0);
     647             :         }
     648           0 :         return (offset+len);
     649             : }/* hexdump */
     650             : 
     651             : /* ------------------------------------------------------------------------ */
     652             : /* masterblock - find a file (by name) in the master directory and return   */
     653             : /*               its block number.                                          */
     654             : /* ------------------------------------------------------------------------ */
     655        4807 : uint64_t masterblock(const char *fn)
     656             : {
     657             :         int d;
     658             :         
     659       23747 :         for (d = 2; d < 8; d++)
     660       23747 :                 if (!strncmp(masterdir.dirent[d].filename, fn, strlen(fn)))
     661        4807 :                         return (masterdir.dirent[d].inum.in_addr);
     662           0 :         return 0;
     663             : }
     664             : 
     665             : /* ------------------------------------------------------------------------ */
     666             : /* rgcount - return how many rgrps there are.                               */
     667             : /* ------------------------------------------------------------------------ */
     668           6 : static void rgcount(void)
     669             : {
     670           6 :         printf("%"PRId64" RGs in this file system.\n",
     671           6 :                sbd.md.riinode->i_size / sizeof(struct gfs2_rindex));
     672           6 :         lgfs2_inode_put(&sbd.md.riinode);
     673           6 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
     674           6 :         exit(EXIT_SUCCESS);
     675             : }
     676             : 
     677             : /* ------------------------------------------------------------------------ */
     678             : /* find_rgrp_block - locate the block for a given rgrp number               */
     679             : /* ------------------------------------------------------------------------ */
     680        4437 : static uint64_t find_rgrp_block(struct lgfs2_inode *dif, int rg)
     681             : {
     682             :         int amt;
     683             :         struct gfs2_rindex ri;
     684             :         uint64_t foffset;
     685             : 
     686        4437 :         foffset = rg * sizeof(struct gfs2_rindex);
     687        4437 :         amt = lgfs2_readi(dif, &ri, foffset, sizeof(ri));
     688        4437 :         if (!amt) /* end of file */
     689           0 :                 return 0;
     690        4437 :         return be64_to_cpu(ri.ri_addr);
     691             : }
     692             : 
     693             : /* ------------------------------------------------------------------------ */
     694             : /* get_rg_addr                                                              */
     695             : /* ------------------------------------------------------------------------ */
     696        4437 : static uint64_t get_rg_addr(int rgnum)
     697             : {
     698        4437 :         uint64_t rgblk = 0, gblock;
     699             :         struct lgfs2_inode *riinode;
     700             : 
     701        4437 :         gblock = masterblock("rindex");
     702        4437 :         riinode = lgfs2_inode_read(&sbd, gblock);
     703        4437 :         if (riinode == NULL)
     704           0 :                 return 0;
     705        4437 :         if (rgnum < riinode->i_size / sizeof(struct gfs2_rindex))
     706        4437 :                 rgblk = find_rgrp_block(riinode, rgnum);
     707             :         else
     708           0 :                 fprintf(stderr, "Error: File system only has %"PRId64" RGs.\n",
     709           0 :                         riinode->i_size / sizeof(struct gfs2_rindex));
     710        4437 :         lgfs2_inode_put(&riinode);
     711        4437 :         return rgblk;
     712             : }
     713             : 
     714             : /* ------------------------------------------------------------------------ */
     715             : /* set_rgrp_flags - Set an rgrp's flags to a given value                    */
     716             : /* rgnum: which rg to print or modify flags for (0 - X)                     */
     717             : /* new_flags: value to set new rg_flags to (if modify == TRUE)              */
     718             : /* modify: TRUE if the value is to be modified, FALSE if it's to be printed */
     719             : /* full: TRUE if the full RG should be printed.                             */
     720             : /* ------------------------------------------------------------------------ */
     721        4437 : static void set_rgrp_flags(int rgnum, uint32_t new_flags, int modify, int full)
     722             : {
     723             :         struct lgfs2_buffer_head *rbh;
     724             :         struct gfs2_rgrp *rg;
     725             :         uint64_t rgblk;
     726             : 
     727        4437 :         rgblk = get_rg_addr(rgnum);
     728        4437 :         rbh = lgfs2_bread(&sbd, rgblk);
     729        4437 :         rg = (void *)rbh->b_data;
     730             : 
     731        4437 :         if (modify) {
     732           0 :                 uint32_t flags = be32_to_cpu(rg->rg_flags);
     733             : 
     734           0 :                 printf("RG #%d (block %"PRIu64" / 0x%"PRIx64") rg_flags changed from 0x%08x to 0x%08x\n",
     735             :                        rgnum, rgblk, rgblk, flags, new_flags);
     736           0 :                 rg->rg_flags = cpu_to_be32(new_flags);
     737           0 :                 lgfs2_bmodified(rbh);
     738             :         } else {
     739        4437 :                 if (full) {
     740        4437 :                         print_gfs2("RG #%d", rgnum);
     741        4437 :                         print_gfs2(" located at: %"PRIu64" (0x%"PRIx64")", rgblk, rgblk);
     742        4437 :                         eol(0);
     743        4437 :                         rgrp_print(rg);
     744             :                 }
     745             :                 else
     746           0 :                         printf("RG #%d (block %"PRIu64" / 0x%"PRIx64") rg_flags = 0x%08x\n",
     747           0 :                                rgnum, rgblk, rgblk, be32_to_cpu(rg->rg_flags));
     748             :         }
     749        4437 :         lgfs2_brelse(rbh);
     750        4437 :         if (modify)
     751           0 :                 fsync(sbd.device_fd);
     752        4437 : }
     753             : 
     754           0 : int has_indirect_blocks(void)
     755             : {
     756           0 :         if (indirect_blocks || gfs2_struct_type == GFS2_METATYPE_SB ||
     757           0 :             gfs2_struct_type == GFS2_METATYPE_LF ||
     758           0 :             (gfs2_struct_type == GFS2_METATYPE_DI &&
     759           0 :              (S_ISDIR(be32_to_cpu(di->di_mode)))))
     760           0 :                 return TRUE;
     761           0 :         return FALSE;
     762             : }
     763             : 
     764          88 : int block_is_rindex(uint64_t blk)
     765             : {
     766          88 :         return blk == masterblock("rindex");
     767             : }
     768             : 
     769          87 : int block_is_inum_file(uint64_t blk)
     770             : {
     771          87 :         return blk == masterblock("inum");
     772             : }
     773             : 
     774          80 : int block_is_statfs_file(uint64_t blk)
     775             : {
     776          80 :         return blk == masterblock("statfs");
     777             : }
     778             : 
     779          73 : int block_is_quota_file(uint64_t blk)
     780             : {
     781          73 :         return blk == masterblock("quota");
     782             : }
     783             : 
     784          26 : int block_is_per_node(uint64_t blk)
     785             : {
     786          26 :         return blk == masterblock("per_node");
     787             : }
     788             : 
     789             : /* ------------------------------------------------------------------------ */
     790             : /* block_has_extended_info                                                  */
     791             : /* ------------------------------------------------------------------------ */
     792           0 : static int block_has_extended_info(void)
     793             : {
     794           0 :         if (has_indirect_blocks() ||
     795           0 :             block_is_rindex(block) ||
     796           0 :             block_is_rgtree(block) ||
     797           0 :             block_is_journals(block) ||
     798           0 :             block_is_inum_file(block) ||
     799           0 :             block_is_statfs_file(block) ||
     800           0 :             block_is_quota_file(block))
     801           0 :                 return TRUE;
     802           0 :         return FALSE;
     803             : }
     804             : 
     805        4465 : static void read_superblock(int fd)
     806             : {
     807             :         struct gfs2_meta_header *mh;
     808             : 
     809        4465 :         ioctl(fd, BLKFLSBUF, 0);
     810        4465 :         memset(&sbd, 0, sizeof(struct lgfs2_sbd));
     811        4465 :         sbd.sd_bsize = LGFS2_DEFAULT_BSIZE;
     812        4465 :         sbd.device_fd = fd;
     813        4465 :         bh = lgfs2_bread(&sbd, 0x10);
     814        4465 :         sbd.rgtree.osi_node = NULL;
     815        4465 :         lgfs2_sb_in(&sbd, bh->b_data);
     816        4465 :         mh = (struct gfs2_meta_header *)bh->b_data;
     817        4465 :         if (!sbd.sd_bsize)
     818           0 :                 sbd.sd_bsize = LGFS2_DEFAULT_BSIZE;
     819        4465 :         if (lgfs2_get_dev_info(fd, &sbd.dinfo)) {
     820           0 :                 perror(device);
     821           0 :                 exit(-1);
     822             :         }
     823        4465 :         if (lgfs2_compute_constants(&sbd)) {
     824           0 :                 fprintf(stderr, "Failed to compute constants.\n");
     825           0 :                 exit(-1);
     826             :         }
     827        8930 :         if (be32_to_cpu(mh->mh_magic) == GFS2_MAGIC &&
     828        4465 :             be32_to_cpu(mh->mh_type) == GFS2_METATYPE_SB)
     829        4465 :                 block = 0x10 * (LGFS2_DEFAULT_BSIZE / sbd.sd_bsize);
     830             :         else
     831           0 :                 block = starting_blk = 0;
     832        4465 :         lgfs2_fix_device_geometry(&sbd);
     833        4465 :         sbd.sd_inptrs = (sbd.sd_bsize - sizeof(struct gfs2_meta_header)) /
     834             :                 sizeof(uint64_t);
     835        4465 :         sbd.sd_diptrs = (sbd.sd_bsize - sizeof(struct gfs2_dinode)) /
     836             :                 sizeof(uint64_t);
     837        4465 :         sbd.master_dir = lgfs2_inode_read(&sbd, sbd.sd_meta_dir.in_addr);
     838        4465 :         if (sbd.master_dir == NULL) {
     839           0 :                 sbd.md.riinode = NULL;
     840             :         } else {
     841        4465 :                 sbd.md.riinode = lgfs2_lookupi(sbd.master_dir, "rindex", 6);
     842             :         }
     843        4465 :         lgfs2_brelse(bh);
     844        4465 :         bh = NULL;
     845        4465 : }
     846             : 
     847        4465 : static int read_rindex(void)
     848             : {
     849             :         uint64_t count;
     850             :         int ok;
     851             : 
     852        4465 :         sbd.fssize = sbd.device.length;
     853        4465 :         if (sbd.md.riinode) /* If we found the rindex */
     854        4465 :                 lgfs2_rindex_read(&sbd, &count, &ok);
     855             : 
     856        4465 :         if (!OSI_EMPTY_ROOT(&sbd.rgtree)) {
     857        4465 :                 struct lgfs2_rgrp_tree *rg = (struct lgfs2_rgrp_tree *)osi_last(&sbd.rgtree);
     858        4465 :                 sbd.fssize = rg->rt_data0 + rg->rt_data;
     859             :         }
     860        4465 :         return 0;
     861             : }
     862             : 
     863        4465 : static int read_master_dir(void)
     864             : {
     865        4465 :         ioctl(sbd.device_fd, BLKFLSBUF, 0);
     866             : 
     867        4465 :         bh = lgfs2_bread(&sbd, sbd.sd_meta_dir.in_addr);
     868        4465 :         if (bh == NULL)
     869           0 :                 return 1;
     870        4465 :         di = (struct gfs2_dinode *)bh->b_data;
     871        4465 :         do_dinode_extended(bh->b_data); /* get extended data, if any */
     872        4465 :         memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
     873        4465 :         return 0;
     874             : }
     875             : 
     876           7 : int display(int identify_only, int trunc_zeros, uint64_t flagref,
     877             :             uint64_t ref_blk)
     878             : {
     879             :         uint64_t blk;
     880             : 
     881           7 :         if (block == RGLIST_DUMMY_BLOCK) {
     882           0 :                 blk = masterblock("rindex");
     883           7 :         } else if (block == JOURNALS_DUMMY_BLOCK) {
     884           0 :                 blk = masterblock("jindex");
     885             :         } else
     886           7 :                 blk = block;
     887           7 :         if (termlines) {
     888           0 :                 display_title_lines();
     889           0 :                 move(2,0);
     890             :         }
     891           7 :         if (bh == NULL || bh->b_blocknr != blk) { /* If we changed blocks from the last read */
     892           7 :                 if (bh != NULL)
     893           7 :                         lgfs2_brelse(bh);
     894           7 :                 dev_offset = blk * sbd.sd_bsize;
     895           7 :                 ioctl(sbd.device_fd, BLKFLSBUF, 0);
     896           7 :                 if (!(bh = lgfs2_bread(&sbd, blk))) {
     897           0 :                         fprintf(stderr, "read error: %s from %s:%d: "
     898             :                                 "offset %"PRIu64" (0x%"PRIx64")\n",
     899           0 :                                 strerror(errno), __FUNCTION__, __LINE__,
     900             :                                 dev_offset, dev_offset);
     901           0 :                         exit(-1);
     902             :                 }
     903             :         }
     904           7 :         line = 1;
     905           7 :         gfs2_struct_type = display_block_type(bh->b_data, bh->b_blocknr, FALSE);
     906           7 :         if (identify_only)
     907           0 :                 return 0;
     908           7 :         indirect_blocks = 0;
     909           7 :         lines_per_row[dmode] = 1;
     910           7 :         if (gfs2_struct_type == GFS2_METATYPE_SB || blk == 0x10 * (4096 / sbd.sd_bsize)) {
     911           0 :                 struct indirect_info *ii = &indirect->ii[0];
     912             :                 struct idirent *id;
     913             : 
     914           0 :                 lgfs2_sb_in(&sbd, bh->b_data);
     915           0 :                 memset(indirect, 0, sizeof(struct iinfo));
     916           0 :                 ii->block = sbd.sd_meta_dir.in_addr;
     917           0 :                 ii->is_dir = TRUE;
     918           0 :                 ii->dirents = 2;
     919             : 
     920           0 :                 id = &ii->dirent[0];
     921           0 :                 memcpy(id->filename, "root", 4);
     922           0 :                 id->inum = sbd.sd_root_dir;
     923           0 :                 id->type = DT_DIR;
     924             : 
     925           0 :                 id = &ii->dirent[1];
     926           0 :                 memcpy(id->filename, "master", 7);
     927           0 :                 id->inum = sbd.sd_meta_dir;
     928           0 :                 id->type = DT_DIR;
     929             :         }
     930           7 :         else if (gfs2_struct_type == GFS2_METATYPE_DI) {
     931           7 :                 di = (struct gfs2_dinode *)bh->b_data;
     932           7 :                 do_dinode_extended(bh->b_data); /* get extended data, if any */
     933             :         }
     934           0 :         else if (gfs2_struct_type == GFS2_METATYPE_IN) { /* indirect block list */
     935           0 :                 if (blockhist) {
     936             :                         int i;
     937             : 
     938           0 :                         for (i = 0; i < 512; i++)
     939           0 :                                 memcpy(&indirect->ii[i].mp,
     940           0 :                                        &blockstack[blockhist - 1].mp,
     941             :                                        sizeof(struct lgfs2_metapath));
     942             :                 }
     943           0 :                 indirect_blocks = do_indirect_extended(bh->b_data, indirect);
     944             :         }
     945           0 :         else if (gfs2_struct_type == GFS2_METATYPE_LF) { /* directory leaf */
     946           0 :                 do_leaf_extended(bh->b_data, indirect);
     947             :         }
     948             : 
     949           7 :         last_entry_onscreen[dmode] = 0;
     950           7 :         if (dmode == EXTENDED_MODE && !block_has_extended_info())
     951           0 :                 dmode = HEX_MODE;
     952           7 :         if (termlines) {
     953           0 :                 move(termlines, 63);
     954           0 :                 if (dmode==HEX_MODE)
     955           0 :                         printw("Mode: Hex %s", (editing?"edit ":"view "));
     956             :                 else
     957           0 :                         printw("Mode: %s", (dmode==GFS2_MODE?"Structure":
     958             :                                             "Pointers "));
     959           0 :                 move(line, 0);
     960             :         }
     961           7 :         if (dmode == HEX_MODE) {         /* if hex display mode           */
     962           0 :                 uint64_t len = sbd.sd_bsize;
     963             : 
     964           0 :                 if (gfs2_struct_type == GFS2_METATYPE_DI)
     965           0 :                         len = struct_len + be64_to_cpu(di->di_size);
     966             : 
     967           0 :                 hexdump(dev_offset, len, trunc_zeros, flagref, ref_blk);
     968           7 :         } else if (dmode == GFS2_MODE) { /* if structure display */
     969           7 :                 if (block != JOURNALS_DUMMY_BLOCK)
     970           7 :                         display_gfs2(bh->b_data);
     971             :         } else
     972           0 :                 display_extended();        /* display extended blocks       */
     973             :         /* No else here because display_extended can switch back to hex mode */
     974           7 :         if (termlines)
     975           0 :                 refresh();
     976           7 :         return(0);
     977             : }
     978             : 
     979             : /* ------------------------------------------------------------------------ */
     980             : /* push_block - push a block onto the block stack                           */
     981             : /* ------------------------------------------------------------------------ */
     982          15 : static void push_block(uint64_t blk)
     983             : {
     984             :         int i, bhst;
     985             : 
     986          15 :         bhst = blockhist % BLOCK_STACK_SIZE;
     987          15 :         if (blk) {
     988          15 :                 blockstack[bhst].dmode = dmode;
     989          60 :                 for (i = 0; i < DMODES; i++) {
     990          45 :                         blockstack[bhst].start_row[i] = start_row[i];
     991          45 :                         blockstack[bhst].end_row[i] = end_row[i];
     992          45 :                         blockstack[bhst].edit_row[i] = edit_row[i];
     993          45 :                         blockstack[bhst].edit_col[i] = edit_col[i];
     994          45 :                         blockstack[bhst].lines_per_row[i] = lines_per_row[i];
     995             :                 }
     996          15 :                 blockstack[bhst].gfs2_struct_type = gfs2_struct_type;
     997          15 :                 if (edit_row[dmode] >= 0 && !block_is_rindex(block))
     998          15 :                         memcpy(&blockstack[bhst].mp,
     999          15 :                                &indirect->ii[edit_row[dmode]].mp,
    1000             :                                sizeof(struct lgfs2_metapath));
    1001          15 :                 blockhist++;
    1002          15 :                 blockstack[blockhist % BLOCK_STACK_SIZE].block = blk;
    1003             :         }
    1004          15 : }
    1005             : 
    1006             : /* ------------------------------------------------------------------------ */
    1007             : /* pop_block - pop a block off the block stack                              */
    1008             : /* ------------------------------------------------------------------------ */
    1009           7 : static uint64_t pop_block(void)
    1010             : {
    1011             :         int i, bhst;
    1012             : 
    1013           7 :         if (!blockhist)
    1014           0 :                 return block;
    1015           7 :         blockhist--;
    1016           7 :         bhst = blockhist % BLOCK_STACK_SIZE;
    1017           7 :         dmode = blockstack[bhst].dmode;
    1018          28 :         for (i = 0; i < DMODES; i++) {
    1019          21 :                 start_row[i] = blockstack[bhst].start_row[i];
    1020          21 :                 end_row[i] = blockstack[bhst].end_row[i];
    1021          21 :                 edit_row[i] = blockstack[bhst].edit_row[i];
    1022          21 :                 edit_col[i] = blockstack[bhst].edit_col[i];
    1023          21 :                 lines_per_row[i] = blockstack[bhst].lines_per_row[i];
    1024             :         }
    1025           7 :         gfs2_struct_type = blockstack[bhst].gfs2_struct_type;
    1026           7 :         return blockstack[bhst].block;
    1027             : }
    1028             : 
    1029             : /* ------------------------------------------------------------------------ */
    1030             : /* Find next metadata block of a given type AFTER a given point in the fs   */
    1031             : /*                                                                          */
    1032             : /* This is used to find blocks that aren't represented in the bitmaps, such */
    1033             : /* as the RGs and bitmaps or the superblock.                                */
    1034             : /* ------------------------------------------------------------------------ */
    1035           0 : static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int print)
    1036             : {
    1037             :         uint64_t blk, last_fs_block;
    1038           0 :         int found = 0;
    1039             :         struct lgfs2_buffer_head *lbh;
    1040             : 
    1041           0 :         last_fs_block = lseek(sbd.device_fd, 0, SEEK_END) / sbd.sd_bsize;
    1042           0 :         for (blk = startblk + 1; blk < last_fs_block; blk++) {
    1043           0 :                 lbh = lgfs2_bread(&sbd, blk);
    1044             :                 /* Can't use get_block_type here (returns false "none") */
    1045           0 :                 if (lbh->b_data[0] == 0x01 && lbh->b_data[1] == 0x16 &&
    1046           0 :                     lbh->b_data[2] == 0x19 && lbh->b_data[3] == 0x70 &&
    1047           0 :                     lbh->b_data[4] == 0x00 && lbh->b_data[5] == 0x00 &&
    1048           0 :                     lbh->b_data[6] == 0x00 && lbh->b_data[7] == metatype) {
    1049           0 :                         found = 1;
    1050           0 :                         lgfs2_brelse(lbh);
    1051           0 :                         break;
    1052             :                 }
    1053           0 :                 lgfs2_brelse(lbh);
    1054             :         }
    1055           0 :         if (!found)
    1056           0 :                 blk = 0;
    1057           0 :         if (print) {
    1058           0 :                 if (dmode == HEX_MODE)
    1059           0 :                         printf("0x%"PRIx64"\n", blk);
    1060             :                 else
    1061           0 :                         printf("%"PRIu64"\n", blk);
    1062             :         }
    1063           0 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1064           0 :         if (print)
    1065           0 :                 exit(0);
    1066           0 :         return blk;
    1067             : }
    1068             : 
    1069           0 : static int find_rg_metatype(struct lgfs2_rgrp_tree *rgd, uint64_t *blk, uint64_t startblk, int mtype)
    1070             : {
    1071             :         int found;
    1072             :         unsigned i, j, m;
    1073           0 :         struct lgfs2_buffer_head *bhp = NULL;
    1074           0 :         uint64_t *ibuf = malloc(sbd.sd_bsize * GFS2_NBBY * sizeof(uint64_t));
    1075             : 
    1076           0 :         for (i = 0; i < rgd->rt_length; i++) {
    1077           0 :                 m = lgfs2_bm_scan(rgd, i, ibuf, GFS2_BLKST_DINODE);
    1078             : 
    1079           0 :                 for (j = 0; j < m; j++) {
    1080           0 :                         *blk = ibuf[j];
    1081           0 :                         bhp = lgfs2_bread(&sbd, *blk);
    1082           0 :                         found = (*blk > startblk) && !lgfs2_check_meta(bhp->b_data, mtype);
    1083           0 :                         lgfs2_brelse(bhp);
    1084           0 :                         if (found) {
    1085           0 :                                 free(ibuf);
    1086           0 :                                 return 0;
    1087             :                         }
    1088             :                 }
    1089             :         }
    1090           0 :         free(ibuf);
    1091           0 :         return -1;
    1092             : }
    1093             : 
    1094             : /* ------------------------------------------------------------------------ */
    1095             : /* Find next "metadata in use" block AFTER a given point in the fs          */
    1096             : /*                                                                          */
    1097             : /* This version does its magic by searching the bitmaps of the RG.  After   */
    1098             : /* all, if we're searching for a dinode, we want a real allocated inode,    */
    1099             : /* not just some block that used to be an inode in a previous incarnation.  */
    1100             : /* ------------------------------------------------------------------------ */
    1101           0 : static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int print)
    1102             : {
    1103           0 :         struct osi_node *next = NULL;
    1104             :         uint64_t blk, errblk;
    1105           0 :         int first = 1, found = 0;
    1106           0 :         struct lgfs2_rgrp_tree *rgd = NULL;
    1107             : 
    1108           0 :         blk = 0;
    1109             :         /* Skip the rgs prior to the block we've been given */
    1110           0 :         for (next = osi_first(&sbd.rgtree); next; next = osi_next(next)) {
    1111           0 :                 rgd = (struct lgfs2_rgrp_tree *)next;
    1112           0 :                 if (first && startblk <= rgd->rt_data0) {
    1113           0 :                         startblk = rgd->rt_data0;
    1114           0 :                         break;
    1115           0 :                 } else if (rgd->rt_addr <= startblk &&
    1116           0 :                          startblk < rgd->rt_data0 + rgd->rt_data)
    1117             :                         break;
    1118             :                 else
    1119           0 :                         rgd = NULL;
    1120           0 :                 first = 0;
    1121             :         }
    1122           0 :         if (!rgd) {
    1123           0 :                 if (print)
    1124           0 :                         printf("0\n");
    1125           0 :                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1126           0 :                 if (print)
    1127           0 :                         exit(-1);
    1128             :         }
    1129           0 :         for (; !found && next; next = osi_next(next)){
    1130           0 :                 rgd = (struct lgfs2_rgrp_tree *)next;
    1131           0 :                 errblk = lgfs2_rgrp_read(&sbd, rgd);
    1132           0 :                 if (errblk)
    1133           0 :                         continue;
    1134             : 
    1135           0 :                 found = !find_rg_metatype(rgd, &blk, startblk, metatype);
    1136           0 :                 if (found)
    1137           0 :                         break;
    1138             : 
    1139           0 :                 lgfs2_rgrp_relse(&sbd, rgd);
    1140             :         }
    1141             : 
    1142           0 :         if (!found)
    1143           0 :                 blk = 0;
    1144           0 :         if (print) {
    1145           0 :                 if (dmode == HEX_MODE)
    1146           0 :                         printf("0x%"PRIx64"\n", blk);
    1147             :                 else
    1148           0 :                         printf("%"PRIu64"\n", blk);
    1149             :         }
    1150           0 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1151           0 :         if (print)
    1152           0 :                 exit(0);
    1153           0 :         return blk;
    1154             : }
    1155             : 
    1156             : /* ------------------------------------------------------------------------ */
    1157             : /* Find next metadata block AFTER a given point in the fs                   */
    1158             : /* ------------------------------------------------------------------------ */
    1159           0 : static uint64_t find_metablockoftype(const char *strtype, int print)
    1160             : {
    1161           0 :         int mtype = 0;
    1162           0 :         uint64_t startblk, blk = 0;
    1163             : 
    1164           0 :         if (print)
    1165           0 :                 startblk = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1166             :         else
    1167           0 :                 startblk = block;
    1168             : 
    1169           0 :         for (mtype = GFS2_METATYPE_NONE;
    1170           0 :              mtype <= GFS2_METATYPE_QC; mtype++)
    1171           0 :                 if (!strcasecmp(strtype, mtypes[mtype]))
    1172           0 :                         break;
    1173           0 :         if (!strcmp(strtype, "dinode"))
    1174           0 :                 mtype = GFS2_METATYPE_DI;
    1175           0 :         if (mtype >= GFS2_METATYPE_NONE && mtype <= GFS2_METATYPE_RB)
    1176           0 :                 blk = find_metablockoftype_slow(startblk, mtype, print);
    1177           0 :         else if (mtype >= GFS2_METATYPE_DI && mtype <= GFS2_METATYPE_QC)
    1178           0 :                 blk = find_metablockoftype_rg(startblk, mtype, print);
    1179           0 :         else if (print) {
    1180           0 :                 fprintf(stderr, "Error: metadata type not "
    1181             :                         "specified: must be one of:\n");
    1182           0 :                 fprintf(stderr, "sb rg rb di in lf jd lh ld"
    1183             :                         " ea ed lb 13 qc\n");
    1184           0 :                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1185           0 :                 exit(-1);
    1186             :         }
    1187           0 :         return blk;
    1188             : }
    1189             : 
    1190             : /* ------------------------------------------------------------------------ */
    1191             : /* Check if the word is a keyword such as "sb" or "rindex"                  */
    1192             : /* Returns: block number if it is, else 0                                   */
    1193             : /* ------------------------------------------------------------------------ */
    1194        8935 : uint64_t check_keywords(const char *kword)
    1195             : {
    1196        8935 :         uint64_t blk = 0;
    1197             : 
    1198        8935 :         if (!strcmp(kword, "sb") ||!strcmp(kword, "superblock"))
    1199           2 :                 blk = 0x10 * (4096 / sbd.sd_bsize); /* superblock */
    1200        8933 :         else if (!strcmp(kword, "root") || !strcmp(kword, "rootdir"))
    1201           4 :                 blk = sbd.sd_root_dir.in_addr;
    1202        8929 :         else if (!strcmp(kword, "master")) {
    1203           0 :                 if (!sbd.sd_meta_dir.in_addr) {
    1204           0 :                         fprintf(stderr, "GFS2 master directory not found on %s\n", device);
    1205           0 :                         exit(-1);
    1206             :                 } else
    1207           0 :                         blk = sbd.sd_meta_dir.in_addr;
    1208             :         }
    1209        8929 :         else if (!strcmp(kword, "jindex"))
    1210           0 :                 blk = masterblock("jindex");
    1211        8929 :         else if (!strcmp(kword, "per_node"))
    1212           0 :                 blk = masterblock("per_node");
    1213        8929 :         else if (!strcmp(kword, "inum"))
    1214           0 :                 blk = masterblock("inum");
    1215        8929 :         else if (!strcmp(kword, "statfs"))
    1216           0 :                 blk = masterblock("statfs");
    1217        8929 :         else if (!strcmp(kword, "rindex") || !strcmp(kword, "rgindex")) {
    1218           7 :                 blk = masterblock("rindex");
    1219        8922 :         } else if (!strcmp(kword, "rgs")) {
    1220           0 :                 blk = RGLIST_DUMMY_BLOCK;
    1221        8922 :         } else if (!strcmp(kword, "quota")) {
    1222           0 :                 blk = masterblock("quota");
    1223        8922 :         } else if (!strncmp(kword, "rg ", 3)) {
    1224           0 :                 int rgnum = 0;
    1225             : 
    1226           0 :                 rgnum = atoi(kword + 3);
    1227           0 :                 blk = get_rg_addr(rgnum);
    1228        8922 :         } else if (!strncmp(kword, "journals", 8)) {
    1229           0 :                 blk = JOURNALS_DUMMY_BLOCK;
    1230        8922 :         } else if (strlen(kword) > 7 && !strncmp(kword, "journal", 7) && isdigit(kword[7])) {
    1231             :                 uint64_t j_size;
    1232             : 
    1233           2 :                 blk = find_journal_block(kword, &j_size);
    1234        8920 :         } else if (kword[0]=='/') /* search */
    1235           0 :                 blk = find_metablockoftype(&kword[1], 0);
    1236        8920 :         else if (kword[0]=='0' && kword[1]=='x') /* hex addr */
    1237           0 :                 sscanf(kword, "%"SCNx64, &blk);/* retrieve in hex */
    1238             :         else
    1239        8920 :                 sscanf(kword, "%"SCNu64, &blk); /* retrieve decimal */
    1240             : 
    1241        8935 :         return blk;
    1242             : }
    1243             : 
    1244             : /* ------------------------------------------------------------------------ */
    1245             : /* goto_block - go to a desired block entered by the user                   */
    1246             : /* ------------------------------------------------------------------------ */
    1247           0 : static uint64_t goto_block(void)
    1248             : {
    1249             :         char string[256];
    1250             :         int ch, delta;
    1251             : 
    1252           0 :         memset(string, 0, sizeof(string));
    1253           0 :         sprintf(string,"%lld", (long long)block);
    1254           0 :         if (bobgets(string, 1, 7, 16, &ch)) {
    1255           0 :                 if (isalnum(string[0]) || string[0] == '/')
    1256           0 :                         temp_blk = check_keywords(string);
    1257           0 :                 else if (string[0] == '+' || string[0] == '-') {
    1258           0 :                         if (string[1] == '0' && string[2] == 'x')
    1259           0 :                                 sscanf(string, "%x", &delta);
    1260             :                         else
    1261           0 :                                 sscanf(string, "%d", &delta);
    1262           0 :                         temp_blk = block + delta;
    1263             :                 }
    1264             : 
    1265           0 :                 if (temp_blk == RGLIST_DUMMY_BLOCK ||
    1266           0 :                     temp_blk == JOURNALS_DUMMY_BLOCK || temp_blk < max_block) {
    1267           0 :                         offset = 0;
    1268           0 :                         block = temp_blk;
    1269           0 :                         push_block(block);
    1270             :                 }
    1271             :         }
    1272           0 :         return block;
    1273             : }
    1274             : 
    1275             : /* ------------------------------------------------------------------------ */
    1276             : /* init_colors                                                              */
    1277             : /* ------------------------------------------------------------------------ */
    1278           0 : static void init_colors(void)
    1279             : {
    1280             : 
    1281           0 :         if (color_scheme) {
    1282           0 :                 init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
    1283           0 :                 init_pair(COLOR_NORMAL, COLOR_WHITE,  COLOR_BLACK);
    1284           0 :                 init_pair(COLOR_INVERSE, COLOR_BLACK,  COLOR_WHITE);
    1285           0 :                 init_pair(COLOR_SPECIAL, COLOR_RED,    COLOR_BLACK);
    1286           0 :                 init_pair(COLOR_HIGHLIGHT, COLOR_GREEN, COLOR_BLACK);
    1287           0 :                 init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_BLACK);
    1288           0 :                 init_pair(COLOR_CONTENTS, COLOR_YELLOW, COLOR_BLACK);
    1289             :         }
    1290             :         else {
    1291           0 :                 init_pair(COLOR_TITLE, COLOR_BLACK,  COLOR_CYAN);
    1292           0 :                 init_pair(COLOR_NORMAL, COLOR_BLACK,  COLOR_WHITE);
    1293           0 :                 init_pair(COLOR_INVERSE, COLOR_WHITE,  COLOR_BLACK);
    1294           0 :                 init_pair(COLOR_SPECIAL, COLOR_MAGENTA, COLOR_WHITE);
    1295           0 :                 init_pair(COLOR_HIGHLIGHT, COLOR_RED, COLOR_WHITE); /*cursor*/
    1296           0 :                 init_pair(COLOR_OFFSETS, COLOR_CYAN,   COLOR_WHITE);
    1297           0 :                 init_pair(COLOR_CONTENTS, COLOR_BLUE, COLOR_WHITE);
    1298             :         }
    1299           0 : }
    1300             : 
    1301             : /* ------------------------------------------------------------------------ */
    1302             : /* hex_edit - Allow the user to edit the page by entering hex digits        */
    1303             : /* ------------------------------------------------------------------------ */
    1304           0 : static void hex_edit(int *exitch)
    1305             : {
    1306             :         int left_off;
    1307             :         int ch;
    1308             : 
    1309           0 :         left_off = ((block * sbd.sd_bsize) < 0xffffffff) ? 9 : 17;
    1310             :         /* 8 and 16 char addresses on screen */
    1311             :         
    1312           0 :         if (bobgets(estring, edit_row[HEX_MODE] + 3,
    1313           0 :                     (edit_col[HEX_MODE] * 2) + (edit_col[HEX_MODE] / 4) +
    1314             :                     left_off, 2, exitch)) {
    1315           0 :                 if (strstr(edit_fmt,"X") || strstr(edit_fmt,"x")) {
    1316             :                         int hexoffset;
    1317           0 :                         int i, sl = strlen(estring);
    1318             :                         
    1319           0 :                         for (i = 0; i < sl; i+=2) {
    1320           0 :                                 hexoffset = (edit_row[HEX_MODE] * 16) +
    1321           0 :                                         edit_col[HEX_MODE] + (i / 2);
    1322           0 :                                 ch = 0x00;
    1323           0 :                                 if (isdigit(estring[i]))
    1324           0 :                                         ch = (estring[i] - '0') * 0x10;
    1325           0 :                                 else if (estring[i] >= 'a' &&
    1326           0 :                                          estring[i] <= 'f')
    1327           0 :                                         ch = (estring[i]-'a' + 0x0a)*0x10;
    1328           0 :                                 else if (estring[i] >= 'A' &&
    1329           0 :                                          estring[i] <= 'F')
    1330           0 :                                         ch = (estring[i] - 'A' + 0x0a) * 0x10;
    1331           0 :                                 if (isdigit(estring[i+1]))
    1332           0 :                                         ch += (estring[i+1] - '0');
    1333           0 :                                 else if (estring[i+1] >= 'a' &&
    1334           0 :                                          estring[i+1] <= 'f')
    1335           0 :                                         ch += (estring[i+1] - 'a' + 0x0a);
    1336           0 :                                 else if (estring[i+1] >= 'A' &&
    1337           0 :                                          estring[i+1] <= 'F')
    1338           0 :                                         ch += (estring[i+1] - 'A' + 0x0a);
    1339           0 :                                 bh->b_data[offset + hexoffset] = ch;
    1340             :                         }
    1341           0 :                         if (pwrite(sbd.device_fd, bh->b_data, sbd.sd_bsize, dev_offset) !=
    1342           0 :                             sbd.sd_bsize) {
    1343           0 :                                 fprintf(stderr, "write error: %s from %s:%d: "
    1344             :                                         "offset %"PRIu64" (0x%"PRIx64")\n",
    1345           0 :                                         strerror(errno),
    1346             :                                         __FUNCTION__, __LINE__,
    1347             :                                         dev_offset, dev_offset);
    1348           0 :                                 exit(-1);
    1349             :                         }
    1350           0 :                         fsync(sbd.device_fd);
    1351             :                 }
    1352             :         }
    1353           0 : }
    1354             : 
    1355             : /* ------------------------------------------------------------------------ */
    1356             : /* page up                                                                  */
    1357             : /* ------------------------------------------------------------------------ */
    1358           0 : static void pageup(void)
    1359             : {
    1360           0 :         if (dmode == EXTENDED_MODE) {
    1361           0 :                 if (edit_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
    1362           0 :                         edit_row[dmode] -= (dsplines / lines_per_row[dmode]);
    1363             :                 else
    1364           0 :                         edit_row[dmode] = 0;
    1365           0 :                 if (start_row[dmode] - (dsplines / lines_per_row[dmode]) > 0)
    1366           0 :                         start_row[dmode] -= (dsplines / lines_per_row[dmode]);
    1367             :                 else
    1368           0 :                         start_row[dmode] = 0;
    1369             :         }
    1370             :         else {
    1371           0 :                 start_row[dmode] = edit_row[dmode] = 0;
    1372           0 :                 if (dmode == GFS2_MODE || offset==0) {
    1373           0 :                         block--;
    1374           0 :                         if (dmode == HEX_MODE)
    1375           0 :                                 offset = (sbd.sd_bsize % screen_chunk_size) > 0 ?
    1376           0 :                                         screen_chunk_size *
    1377           0 :                                         (sbd.sd_bsize / screen_chunk_size) :
    1378           0 :                                         sbd.sd_bsize - screen_chunk_size;
    1379             :                         else
    1380           0 :                                 offset = 0;
    1381             :                 } else
    1382           0 :                         offset -= screen_chunk_size;
    1383             :         }
    1384           0 : }
    1385             : 
    1386             : /* ------------------------------------------------------------------------ */
    1387             : /* page down                                                                */
    1388             : /* ------------------------------------------------------------------------ */
    1389           0 : static void pagedn(void)
    1390             : {
    1391           0 :         if (dmode == EXTENDED_MODE) {
    1392           0 :                 if ((edit_row[dmode] + dsplines) / lines_per_row[dmode] + 1 <=
    1393           0 :                     end_row[dmode]) {
    1394           0 :                         start_row[dmode] += dsplines / lines_per_row[dmode];
    1395           0 :                         edit_row[dmode] += dsplines / lines_per_row[dmode];
    1396             :                 } else {
    1397           0 :                         edit_row[dmode] = end_row[dmode] - 1;
    1398           0 :                         while (edit_row[dmode] - start_row[dmode]
    1399           0 :                                + 1 > last_entry_onscreen[dmode])
    1400           0 :                                 start_row[dmode]++;
    1401             :                 }
    1402             :         }
    1403             :         else {
    1404           0 :                 start_row[dmode] = edit_row[dmode] = 0;
    1405           0 :                 if (dmode == GFS2_MODE ||
    1406           0 :                     offset + screen_chunk_size >= sbd.sd_bsize) {
    1407           0 :                         block++;
    1408           0 :                         offset = 0;
    1409             :                 } else
    1410           0 :                         offset += screen_chunk_size;
    1411             :         }
    1412           0 : }
    1413             : 
    1414             : /* ------------------------------------------------------------------------ */
    1415             : /* jump - jump to the address the cursor is on                              */
    1416             : /*                                                                          */
    1417             : /* If the cursor is in a log descriptor, jump to the log-descriptor version */
    1418             : /* of the block instead of the "real" block.                                */
    1419             : /* ------------------------------------------------------------------------ */
    1420           0 : static void jump(void)
    1421             : {
    1422           0 :         if (dmode == HEX_MODE) {
    1423             :                 unsigned int col2;
    1424             :                 __be64 *b;
    1425           0 :                 const struct lgfs2_metadata *mtype = get_block_type(bh->b_data);
    1426           0 :                 uint32_t block_type = 0;
    1427             : 
    1428           0 :                 if (mtype != NULL)
    1429           0 :                         block_type = mtype->mh_type;
    1430             : 
    1431             :                 /* special exception for log descriptors: jump the journaled
    1432             :                    version of the block, not the "real" block */
    1433           0 :                 if (block_type == GFS2_METATYPE_LD) {
    1434           0 :                         int ptroffset = edit_row[dmode] * 16 + edit_col[dmode];
    1435           0 :                         int pnum = get_pnum(ptroffset);
    1436           0 :                         temp_blk = bh->b_blocknr + pnum + 1;
    1437           0 :                 } else if (edit_row[dmode] >= 0) {
    1438           0 :                         col2 = edit_col[dmode] & 0x08;/* thus 0-7->0, 8-15->8 */
    1439           0 :                         b = (__be64 *)&bh->b_data[edit_row[dmode]*16 +
    1440           0 :                                                     offset + col2];
    1441           0 :                         temp_blk = be64_to_cpu(*b);
    1442             :                 }
    1443             :         }
    1444             :         else
    1445           0 :                 sscanf(estring, "%"SCNx64, &temp_blk);/* retrieve in hex */
    1446           0 :         if (temp_blk < max_block) { /* if the block number is valid */
    1447             :                 int i;
    1448             :                 
    1449           0 :                 offset = 0;
    1450           0 :                 push_block(temp_blk);
    1451           0 :                 block = temp_blk;
    1452           0 :                 for (i = 0; i < DMODES; i++) {
    1453           0 :                         start_row[i] = end_row[i] = edit_row[i] = 0;
    1454           0 :                         edit_col[i] = 0;
    1455             :                 }
    1456             :         }
    1457           0 : }
    1458             : 
    1459           0 : static void print_block_type(uint64_t tblock, const struct lgfs2_metadata *type)
    1460             : {
    1461           0 :         if (type == NULL)
    1462           0 :                 return;
    1463           0 :         if (type->nfields > 0)
    1464           0 :                 printf("%d (Block %"PRIu64" is type %d: %s)\n", type->mh_type,
    1465           0 :                        tblock, type->mh_type, type->display);
    1466             :         else
    1467           0 :                 printf("%d (Block %"PRIu64" is type %d: unknown)\n", type->mh_type,
    1468           0 :                        tblock, type->mh_type);
    1469             : }
    1470             : 
    1471           0 : static void find_print_block_type(void)
    1472             : {
    1473             :         uint64_t tblock;
    1474             :         struct lgfs2_buffer_head *lbh;
    1475             :         const struct lgfs2_metadata *type;
    1476             : 
    1477           0 :         tblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1478           0 :         lbh = lgfs2_bread(&sbd, tblock);
    1479           0 :         type = get_block_type(lbh->b_data);
    1480           0 :         print_block_type(tblock, type);
    1481           0 :         lgfs2_brelse(lbh);
    1482           0 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1483           0 :         exit(0);
    1484             : }
    1485             : 
    1486             : /**
    1487             :  * Find and print the resource group associated with a given block
    1488             :  */
    1489           0 : static void find_print_block_rg(int bitmap)
    1490             : {
    1491             :         uint64_t rblock, rgblock;
    1492             :         int i;
    1493             :         struct lgfs2_rgrp_tree *rgd;
    1494             : 
    1495           0 :         rblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1496           0 :         if (rblock == LGFS2_SB_ADDR(&sbd)) {
    1497           0 :                 printf("0 (the superblock is not in the bitmap)\n");
    1498           0 :                 goto out;
    1499             :         }
    1500           0 :         rgd = lgfs2_blk2rgrpd(&sbd, rblock);
    1501           0 :         if (rgd == NULL) {
    1502           0 :                 printf("-1 (block invalid or part of an rgrp).\n");
    1503           0 :                 goto out;
    1504             :         }
    1505           0 :         rgblock = rgd->rt_addr;
    1506           0 :         if (!bitmap)
    1507           0 :                 goto print;
    1508             : 
    1509           0 :         for (i = 0; i < rgd->rt_length; i++) {
    1510           0 :                 struct lgfs2_bitmap *bits = &(rgd->rt_bits[i]);
    1511           0 :                 uint64_t end = ((uint64_t)bits->bi_start + bits->bi_len) * GFS2_NBBY;
    1512             : 
    1513           0 :                 if (rblock - rgd->rt_data0 < end)
    1514           0 :                         break;
    1515             :         }
    1516           0 :         if (i < rgd->rt_length)
    1517           0 :                 rgblock += i;
    1518           0 : print:
    1519           0 :         if (dmode == HEX_MODE)
    1520           0 :                 printf("0x%"PRIx64"\n", rgblock);
    1521             :         else
    1522           0 :                 printf("%"PRIu64"\n", rgblock);
    1523           0 : out:
    1524           0 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1525           0 :         exit(0);
    1526             : }
    1527             : 
    1528             : /* ------------------------------------------------------------------------ */
    1529             : /* find/change/print block allocation (what the bitmap says about block)    */
    1530             : /* ------------------------------------------------------------------------ */
    1531           0 : static void find_change_block_alloc(int *newval)
    1532             : {
    1533             :         uint64_t ablock;
    1534             :         int type;
    1535             :         struct lgfs2_rgrp_tree *rgd;
    1536             : 
    1537           0 :         if (newval &&
    1538           0 :             (*newval < GFS2_BLKST_FREE || *newval > GFS2_BLKST_DINODE)) {
    1539             :                 int i;
    1540             : 
    1541           0 :                 printf("Error: value %d is not valid.\nValid values are:\n",
    1542             :                        *newval);
    1543           0 :                 for (i = GFS2_BLKST_FREE; i <= GFS2_BLKST_DINODE; i++)
    1544           0 :                         printf("%d - %s\n", i, allocdesc[i]);
    1545           0 :                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1546           0 :                 exit(-1);
    1547             :         }
    1548           0 :         ablock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1549           0 :         if (ablock == LGFS2_SB_ADDR(&sbd))
    1550           0 :                 printf("3 (the superblock is not in the bitmap)\n");
    1551             :         else {
    1552           0 :                 rgd = lgfs2_blk2rgrpd(&sbd, ablock);
    1553           0 :                 if (rgd) {
    1554           0 :                         lgfs2_rgrp_read(&sbd, rgd);
    1555           0 :                         if (newval) {
    1556           0 :                                 if (lgfs2_set_bitmap(rgd, ablock, *newval))
    1557           0 :                                         printf("-1 (block invalid or part of an rgrp).\n");
    1558             :                                 else
    1559           0 :                                         printf("%d\n", *newval);
    1560             :                         } else {
    1561           0 :                                 type = lgfs2_get_bitmap(&sbd, ablock, rgd);
    1562           0 :                                 if (type < 0) {
    1563           0 :                                         printf("-1 (block invalid or part of "
    1564             :                                                "an rgrp).\n");
    1565           0 :                                         exit(-1);
    1566             :                                 }
    1567           0 :                                 printf("%d (%s)\n", type, allocdesc[type]);
    1568             :                         }
    1569           0 :                         lgfs2_rgrp_relse(&sbd, rgd);
    1570             :                 } else {
    1571           0 :                         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1572           0 :                         printf("-1 (block invalid or part of an rgrp).\n");
    1573           0 :                         exit(-1);
    1574             :                 }
    1575             :         }
    1576           0 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    1577           0 :         if (newval)
    1578           0 :                 fsync(sbd.device_fd);
    1579           0 :         exit(0);
    1580             : }
    1581             : 
    1582             : /**
    1583             :  * process request to print a certain field from a previously pushed block
    1584             :  */
    1585           8 : static void process_field(const char *field, const char *nstr)
    1586             : {
    1587             :         uint64_t fblock;
    1588             :         struct lgfs2_buffer_head *rbh;
    1589             :         const struct lgfs2_metadata *mtype;
    1590             :         const struct lgfs2_metafield *mfield;
    1591             : 
    1592           8 :         fblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1593           8 :         rbh = lgfs2_bread(&sbd, fblock);
    1594           8 :         mtype = get_block_type(rbh->b_data);
    1595           8 :         if (mtype == NULL) {
    1596           0 :                 fprintf(stderr, "Metadata type of block %"PRIx64" not recognised\n",
    1597             :                         fblock);
    1598           0 :                 exit(1);
    1599             :         }
    1600             : 
    1601           8 :         mfield = lgfs2_find_mfield_name(field, mtype);
    1602           8 :         if (mfield == NULL) {
    1603           0 :                 fprintf(stderr, "No field '%s' in block type '%s'\n", field, mtype->name);
    1604           0 :                 exit(1);
    1605             :         }
    1606             : 
    1607           8 :         if (nstr != device) {
    1608           1 :                 int err = 0;
    1609           1 :                 if (mfield->flags & (LGFS2_MFF_UUID|LGFS2_MFF_STRING)) {
    1610           0 :                         err = lgfs2_field_assign(rbh->b_data, mfield, nstr);
    1611             :                 } else {
    1612           1 :                         uint64_t val = 0;
    1613           1 :                         err = sscanf(nstr, "%"SCNi64, &val);
    1614           1 :                         if (err == 1)
    1615             :                                 /* coverity[overrun-buffer-val:SUPPRESS] False positive */
    1616           1 :                                 err = lgfs2_field_assign(rbh->b_data, mfield, &val);
    1617             :                         else
    1618           0 :                                 err = -1;
    1619             :                 }
    1620           1 :                 if (err != 0) {
    1621           0 :                         fprintf(stderr, "Could not set '%s' to '%s': %s\n", field, nstr,
    1622           0 :                                 strerror(errno));
    1623           0 :                         exit(1);
    1624             :                 }
    1625           1 :                 lgfs2_bmodified(rbh);
    1626             :         }
    1627             : 
    1628           8 :         if (!termlines) {
    1629           8 :                 char str[GFS2_LOCKNAME_LEN] = "";
    1630           8 :                 lgfs2_field_str(str, GFS2_LOCKNAME_LEN, rbh->b_data, mfield, (dmode == HEX_MODE));
    1631           8 :                 printf("%s\n", str);
    1632             :         }
    1633             : 
    1634           8 :         lgfs2_brelse(rbh);
    1635           8 :         fsync(sbd.device_fd);
    1636           8 :         exit(0);
    1637             : }
    1638             : 
    1639             : /* ------------------------------------------------------------------------ */
    1640             : /* interactive_mode - accept keystrokes from user and display structures    */
    1641             : /* ------------------------------------------------------------------------ */
    1642           0 : static void interactive_mode(void)
    1643             : {
    1644           0 :         int ch = 0, Quit;
    1645             : 
    1646           0 :         if ((wind = initscr()) == NULL) {
    1647           0 :                 fprintf(stderr, "Error: unable to initialize screen.");
    1648           0 :                 eol(0);
    1649           0 :                 exit(-1);
    1650             :         }
    1651           0 :         getmaxyx(stdscr, termlines, termcols);
    1652           0 :         termlines--;
    1653             :         /* Do our initial screen stuff: */
    1654           0 :         clear(); /* don't use Erase */
    1655           0 :         start_color();
    1656           0 :         noecho();
    1657           0 :         keypad(stdscr, TRUE);
    1658           0 :         raw();
    1659           0 :         curs_set(0);
    1660           0 :         init_colors();
    1661             :         /* Accept keystrokes and act on them accordingly */
    1662           0 :         Quit = FALSE;
    1663           0 :         editing = FALSE;
    1664           0 :         while (!Quit) {
    1665           0 :                 display(FALSE, 0, 0, 0);
    1666           0 :                 if (editing) {
    1667           0 :                         if (edit_row[dmode] == -1)
    1668           0 :                                 block = goto_block();
    1669             :                         else {
    1670           0 :                                 if (dmode == HEX_MODE)
    1671           0 :                                         hex_edit(&ch);
    1672           0 :                                 else if (dmode == GFS2_MODE) {
    1673           0 :                                         bobgets(estring, edit_row[dmode]+4, 24,
    1674             :                                                 10, &ch);
    1675           0 :                                         process_field(efield, estring);
    1676             :                                 } else
    1677           0 :                                         bobgets(estring, edit_row[dmode]+6, 14,
    1678             :                                                 edit_size[dmode], &ch);
    1679             :                         }
    1680             :                 }
    1681             :                 else
    1682           0 :                         while ((ch=getch()) == 0); // wait for input
    1683             : 
    1684           0 :                 switch (ch)
    1685             :                 {
    1686             :                 /* --------------------------------------------------------- */
    1687             :                 /* escape or 'q' */
    1688             :                 /* --------------------------------------------------------- */
    1689           0 :                 case 0x1b:
    1690             :                 case 0x03:
    1691             :                 case 'q':
    1692           0 :                         if (editing)
    1693           0 :                                 editing = FALSE;
    1694             :                         else
    1695           0 :                                 Quit=TRUE;
    1696           0 :                         break;
    1697             :                 /* --------------------------------------------------------- */
    1698             :                 /* home - return to the superblock                           */
    1699             :                 /* --------------------------------------------------------- */
    1700           0 :                 case KEY_HOME:
    1701           0 :                         if (dmode == EXTENDED_MODE) {
    1702           0 :                                 start_row[dmode] = end_row[dmode] = 0;
    1703           0 :                                 edit_row[dmode] = 0;
    1704             :                         }
    1705             :                         else {
    1706           0 :                                 block = 0x10 * (4096 / sbd.sd_bsize);
    1707           0 :                                 push_block(block);
    1708           0 :                                 offset = 0;
    1709             :                         }
    1710           0 :                         break;
    1711             :                 /* --------------------------------------------------------- */
    1712             :                 /* backspace - return to the previous block on the stack     */
    1713             :                 /* --------------------------------------------------------- */
    1714           0 :                 case KEY_BACKSPACE:
    1715             :                 case 0x7f:
    1716           0 :                         block = pop_block();
    1717           0 :                         offset = 0;
    1718           0 :                         break;
    1719             :                 /* --------------------------------------------------------- */
    1720             :                 /* space - go down the block stack (opposite of backspace)   */
    1721             :                 /* --------------------------------------------------------- */
    1722           0 :                 case ' ':
    1723           0 :                         blockhist++;
    1724           0 :                         block = blockstack[blockhist % BLOCK_STACK_SIZE].block;
    1725           0 :                         offset = 0;
    1726           0 :                         break;
    1727             :                 /* --------------------------------------------------------- */
    1728             :                 /* arrow up */
    1729             :                 /* --------------------------------------------------------- */
    1730           0 :                 case KEY_UP:
    1731             :                 case '-':
    1732           0 :                         if (dmode == EXTENDED_MODE) {
    1733           0 :                                 if (edit_row[dmode] > 0)
    1734           0 :                                         edit_row[dmode]--;
    1735           0 :                                 if (edit_row[dmode] < start_row[dmode])
    1736           0 :                                         start_row[dmode] = edit_row[dmode];
    1737             :                         }
    1738             :                         else {
    1739           0 :                                 if (edit_row[dmode] >= 0)
    1740           0 :                                         edit_row[dmode]--;
    1741             :                         }
    1742           0 :                         break;
    1743             :                 /* --------------------------------------------------------- */
    1744             :                 /* arrow down */
    1745             :                 /* --------------------------------------------------------- */
    1746           0 :                 case KEY_DOWN:
    1747             :                 case '+':
    1748           0 :                         if (dmode == EXTENDED_MODE) {
    1749           0 :                                 if (edit_row[dmode] + 1 < end_row[dmode]) {
    1750           0 :                                         if (edit_row[dmode] - start_row[dmode]
    1751           0 :                                             + 1 > last_entry_onscreen[dmode])
    1752           0 :                                                 start_row[dmode]++;
    1753           0 :                                         edit_row[dmode]++;
    1754             :                                 }
    1755             :                         }
    1756             :                         else {
    1757           0 :                                 if (edit_row[dmode] < last_entry_onscreen[dmode])
    1758           0 :                                         edit_row[dmode]++;
    1759             :                         }
    1760           0 :                         break;
    1761             :                 /* --------------------------------------------------------- */
    1762             :                 /* arrow left */
    1763             :                 /* --------------------------------------------------------- */
    1764           0 :                 case KEY_LEFT:
    1765           0 :                         if (dmode == HEX_MODE) {
    1766           0 :                                 if (edit_col[dmode] > 0)
    1767           0 :                                         edit_col[dmode]--;
    1768             :                                 else
    1769           0 :                                         edit_col[dmode] = 15;
    1770             :                         }
    1771           0 :                         break;
    1772             :                 /* --------------------------------------------------------- */
    1773             :                 /* arrow right */
    1774             :                 /* --------------------------------------------------------- */
    1775           0 :                 case KEY_RIGHT:
    1776           0 :                         if (dmode == HEX_MODE) {
    1777           0 :                                 if (edit_col[dmode] < 15)
    1778           0 :                                         edit_col[dmode]++;
    1779             :                                 else
    1780           0 :                                         edit_col[dmode] = 0;
    1781             :                         }
    1782           0 :                         break;
    1783             :                 /* --------------------------------------------------------- */
    1784             :                 /* m - change display mode key */
    1785             :                 /* --------------------------------------------------------- */
    1786           0 :                 case 'm':
    1787           0 :                         dmode = ((dmode + 1) % DMODES);
    1788           0 :                         break;
    1789             :                 /* --------------------------------------------------------- */
    1790             :                 /* J - Jump to highlighted block number */
    1791             :                 /* --------------------------------------------------------- */
    1792           0 :                 case 'j':
    1793           0 :                         jump();
    1794           0 :                         break;
    1795             :                 /* --------------------------------------------------------- */
    1796             :                 /* g - goto block */
    1797             :                 /* --------------------------------------------------------- */
    1798           0 :                 case 'g':
    1799           0 :                         block = goto_block();
    1800           0 :                         break;
    1801             :                 /* --------------------------------------------------------- */
    1802             :                 /* h - help key */
    1803             :                 /* --------------------------------------------------------- */
    1804           0 :                 case 'h':
    1805           0 :                         print_usage();
    1806           0 :                         break;
    1807             :                 /* --------------------------------------------------------- */
    1808             :                 /* e - change to extended mode */
    1809             :                 /* --------------------------------------------------------- */
    1810           0 :                 case 'e':
    1811           0 :                         dmode = EXTENDED_MODE;
    1812           0 :                         break;
    1813             :                 /* --------------------------------------------------------- */
    1814             :                 /* b - Back one 4K block */
    1815             :                 /* --------------------------------------------------------- */
    1816           0 :                 case 'b':
    1817           0 :                         start_row[dmode] = end_row[dmode] = edit_row[dmode] = 0;
    1818           0 :                         if (block > 0)
    1819           0 :                                 block--;
    1820           0 :                         offset = 0;
    1821           0 :                         break;
    1822             :                 /* --------------------------------------------------------- */
    1823             :                 /* c - Change color scheme */
    1824             :                 /* --------------------------------------------------------- */
    1825           0 :                 case 'c':
    1826           0 :                         color_scheme = !color_scheme;
    1827           0 :                         init_colors();
    1828           0 :                         break;
    1829             :                 /* --------------------------------------------------------- */
    1830             :                 /* page up key */
    1831             :                 /* --------------------------------------------------------- */
    1832           0 :                 case 0x19:                    // ctrl-y for vt100
    1833             :                 case KEY_PPAGE:               // PgUp
    1834             :                 case 0x15:                    // ctrl-u for vi compat.
    1835             :                 case 0x02:                   // ctrl-b for less compat.
    1836           0 :                         pageup();
    1837           0 :                         break;
    1838             :                 /* --------------------------------------------------------- */
    1839             :                 /* end - Jump to the end of the list */
    1840             :                 /* --------------------------------------------------------- */
    1841           0 :                 case 0x168:
    1842           0 :                         if (dmode == EXTENDED_MODE) {
    1843           0 :                                 int ents_per_screen = dsplines /
    1844           0 :                                         lines_per_row[dmode];
    1845             : 
    1846           0 :                                 edit_row[dmode] = end_row[dmode] - 1;
    1847           0 :                                 if ((edit_row[dmode] - ents_per_screen)+1 > 0)
    1848           0 :                                         start_row[dmode] = edit_row[dmode] - 
    1849           0 :                                                 ents_per_screen + 1;
    1850             :                                 else
    1851           0 :                                         start_row[dmode] = 0;
    1852             :                         }
    1853             :                         /* TODO: Make end key work for other display modes. */
    1854           0 :                         break;
    1855             :                 /* --------------------------------------------------------- */
    1856             :                 /* f - Forward one 4K block */
    1857             :                 /* --------------------------------------------------------- */
    1858           0 :                 case 'f':
    1859           0 :                         start_row[dmode]=end_row[dmode]=edit_row[dmode] = 0;
    1860           0 :                         lines_per_row[dmode] = 1;
    1861           0 :                         block++;
    1862           0 :                         offset = 0;
    1863           0 :                         break;
    1864             :                 /* --------------------------------------------------------- */
    1865             :                 /* page down key */
    1866             :                 /* --------------------------------------------------------- */
    1867           0 :                 case 0x16:                    // ctrl-v for vt100
    1868             :                 case KEY_NPAGE:               // PgDown
    1869             :                 case 0x04:                    // ctrl-d for vi compat.
    1870           0 :                         pagedn();
    1871           0 :                         break;
    1872             :                 /* --------------------------------------------------------- */
    1873             :                 /* enter key - change a value */
    1874             :                 /* --------------------------------------------------------- */
    1875           0 :                 case KEY_ENTER:
    1876             :                 case('\n'):
    1877             :                 case('\r'):
    1878           0 :                         editing = !editing;
    1879           0 :                         break;
    1880           0 :                 case KEY_RESIZE:
    1881           0 :                         getmaxyx(stdscr, termlines, termcols);
    1882           0 :                         termlines--;
    1883           0 :                         break;
    1884           0 :                 default:
    1885           0 :                         move(termlines - 1, 0);
    1886           0 :                         printw("Keystroke not understood: 0x%03x",ch);
    1887           0 :                         refresh();
    1888           0 :                         usleep(50000);
    1889           0 :                         break;
    1890             :                 } /* switch */
    1891             :         } /* while !Quit */
    1892             : 
    1893           0 :     Erase();
    1894           0 :     refresh();
    1895           0 :     endwin();
    1896           0 : }/* interactive_mode */
    1897             : 
    1898             : /* ------------------------------------------------------------------------ */
    1899             : /* usage - print command line usage                                         */
    1900             : /* ------------------------------------------------------------------------ */
    1901           0 : static void usage(void)
    1902             : {
    1903           0 :         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");
    1904           0 :         fprintf(stderr,"If only the device is specified, it enters into hexedit mode.\n");
    1905           0 :         fprintf(stderr,"identify - prints out only the block type, not the details.\n");
    1906           0 :         fprintf(stderr,"printsavedmeta - prints out the saved metadata blocks from a savemeta file.\n");
    1907           0 :         fprintf(stderr,"savemeta <file_system> <file.gz> - save off your metadata for analysis and debugging.\n");
    1908           0 :         fprintf(stderr,"   (The intelligent way: assume bitmap is correct).\n");
    1909           0 :         fprintf(stderr,"savemetaslow - save off your metadata for analysis and debugging.  The SLOW way (block by block).\n");
    1910           0 :         fprintf(stderr,"savergs - save off only the resource group information (rindex and rgs).\n");
    1911           0 :         fprintf(stderr,"restoremeta - restore metadata for debugging (DANGEROUS).\n");
    1912           0 :         fprintf(stderr,"rgcount - print how many RGs in the file system.\n");
    1913           0 :         fprintf(stderr,"rgflags rgnum [new flags] - print or modify flags for rg #rgnum (0 - X)\n");
    1914           0 :         fprintf(stderr,"rgbitmaps <rgnum> - print out the bitmaps for rgrp "
    1915             :                 "rgnum.\n");
    1916           0 :         fprintf(stderr,"rgrepair - find and repair damaged rgrp.\n");
    1917           0 :         fprintf(stderr,"-V   prints version number.\n");
    1918           0 :         fprintf(stderr,"-c 1 selects alternate color scheme 1\n");
    1919           0 :         fprintf(stderr,"-d   prints details (for printing journals)\n");
    1920           0 :         fprintf(stderr,"-p   prints GFS2 structures or blocks to stdout.\n");
    1921           0 :         fprintf(stderr,"     sb - prints the superblock.\n");
    1922           0 :         fprintf(stderr,"     size - prints the filesystem size.\n");
    1923           0 :         fprintf(stderr,"     master - prints the master directory.\n");
    1924           0 :         fprintf(stderr,"     root - prints the root directory.\n");
    1925           0 :         fprintf(stderr,"     jindex - prints the journal index directory.\n");
    1926           0 :         fprintf(stderr,"     journals - prints the journal status.\n");
    1927           0 :         fprintf(stderr,"     per_node - prints the per_node directory.\n");
    1928           0 :         fprintf(stderr,"     inum - prints the inum file.\n");
    1929           0 :         fprintf(stderr,"     statfs - prints the statfs file.\n");
    1930           0 :         fprintf(stderr,"     rindex - prints the rindex file.\n");
    1931           0 :         fprintf(stderr,"     rg X - print resource group X.\n");
    1932           0 :         fprintf(stderr,"     rgs - prints all the resource groups (rgs).\n");
    1933           0 :         fprintf(stderr,"     quota - prints the quota file.\n");
    1934           0 :         fprintf(stderr,"     0x1234 - prints the specified block\n");
    1935           0 :         fprintf(stderr,"-p   <block> blocktype - prints the type "
    1936             :                 "of the specified block\n");
    1937           0 :         fprintf(stderr,"-p   <block> blockrg - prints the resource group "
    1938             :                 "block corresponding to the specified block\n");
    1939           0 :         fprintf(stderr,"-p   <block> blockbits - prints the block with "
    1940             :                 "the bitmap corresponding to the specified block\n");
    1941           0 :         fprintf(stderr,"-p   <block> blockalloc [0|1|2|3] - print or change "
    1942             :                 "the allocation type of the specified block\n");
    1943           0 :         fprintf(stderr,"-p   <block> field [new_value] - prints or change the "
    1944             :                 "structure field\n");
    1945           0 :         fprintf(stderr,"-p   <b> find sb|rg|rb|di|in|lf|jd|lh|ld|ea|ed|lb|"
    1946             :                 "13|qc - find block of given type after block <b>\n");
    1947           0 :         fprintf(stderr,"     <b> specifies the starting block for search\n");
    1948           0 :         fprintf(stderr,"-z 1 use gzip compression level 1 for savemeta (default 9)\n");
    1949           0 :         fprintf(stderr,"-z 0 do not use compression\n");
    1950           0 :         fprintf(stderr,"-s   specifies a starting block such as root, rindex, quota, inum.\n");
    1951           0 :         fprintf(stderr,"-x   print in hexmode.\n");
    1952           0 :         fprintf(stderr,"-h   prints this help.\n\n");
    1953           0 :         fprintf(stderr,"Examples:\n");
    1954           0 :         fprintf(stderr,"   To run in interactive mode:\n");
    1955           0 :         fprintf(stderr,"     gfs2_edit /dev/bobs_vg/lvol0\n");
    1956           0 :         fprintf(stderr,"   To print out the superblock and master directory:\n");
    1957           0 :         fprintf(stderr,"     gfs2_edit -p sb master /dev/bobs_vg/lvol0\n");
    1958           0 :         fprintf(stderr,"   To print out the master directory in hex:\n");
    1959           0 :         fprintf(stderr,"     gfs2_edit -x -p master /dev/bobs_vg/lvol0\n");
    1960           0 :         fprintf(stderr,"   To print out the block-type for block 0x27381:\n");
    1961           0 :         fprintf(stderr,"     gfs2_edit identify -p 0x27381 /dev/bobs_vg/lvol0\n");
    1962           0 :         fprintf(stderr,"   To print out the fourth Resource Group. (the first R is #0)\n");
    1963           0 :         fprintf(stderr,"     gfs2_edit -p rg 3 /dev/sdb1\n");
    1964           0 :         fprintf(stderr,"   To print out the metadata type of block 1234\n");
    1965           0 :         fprintf(stderr,"     gfs2_edit -p 1234 blocktype /dev/roth_vg/roth_lb\n");
    1966           0 :         fprintf(stderr,"   To print out the allocation type of block 2345\n");
    1967           0 :         fprintf(stderr,"     gfs2_edit -p 2345 blockalloc /dev/vg/lv\n");
    1968           0 :         fprintf(stderr,"   To change the allocation type of block 2345 to a 'free block'\n");
    1969           0 :         fprintf(stderr,"     gfs2_edit -p 2345 blockalloc 0 /dev/vg/lv\n");
    1970           0 :         fprintf(stderr,"   To print out the file size of the dinode at block 0x118\n");
    1971           0 :         fprintf(stderr,"     gfs2_edit -p 0x118 field di_size /dev/roth_vg/roth_lb\n");
    1972           0 :         fprintf(stderr,"   To find any dinode higher than the quota file dinode:\n");
    1973           0 :         fprintf(stderr,"     gfs2_edit -p quota find di /dev/x/y\n");
    1974           0 :         fprintf(stderr,"   To set the Resource Group flags for rg #7 to 3.\n");
    1975           0 :         fprintf(stderr,"     gfs2_edit rgflags 7 3 /dev/sdc2\n");
    1976           0 :         fprintf(stderr,"   To save off all metadata for /dev/vg/lv:\n");
    1977           0 :         fprintf(stderr,"     gfs2_edit savemeta /dev/vg/lv /tmp/metasave.gz\n");
    1978           0 : }/* usage */
    1979             : 
    1980             : /**
    1981             :  * getgziplevel - Process the -z parameter to savemeta operations
    1982             :  * argv - argv
    1983             :  * i    - a pointer to the argv index at which to begin processing
    1984             :  * The index pointed to by i will be incremented past the -z option if found
    1985             :  */
    1986           7 : static void getgziplevel(char *argv[], int *i)
    1987             : {
    1988             :         char *opt, *arg;
    1989             :         char *endptr;
    1990             : 
    1991           7 :         arg = argv[1 + *i];
    1992           7 :         if (strncmp(arg, "-z", 2)) {
    1993           2 :                 return;
    1994           5 :         } else if (arg[2] != '\0') {
    1995           5 :                 opt = &arg[2];
    1996             :         } else {
    1997           0 :                 (*i)++;
    1998           0 :                 opt = argv[1 + *i];
    1999             :         }
    2000           5 :         errno = 0;
    2001           5 :         gziplevel = strtol(opt, &endptr, 10);
    2002           5 :         if (errno || endptr == opt || gziplevel < 0 || gziplevel > 9) {
    2003           0 :                 fprintf(stderr, "Compression level out of range: %s\n", opt);
    2004           0 :                 exit(-1);
    2005             :         }
    2006           5 :         (*i)++;
    2007             : }
    2008             : 
    2009           0 : static int count_dinode_blks(struct lgfs2_rgrp_tree *rgd, int bitmap,
    2010             :                              struct lgfs2_buffer_head *rbh)
    2011             : {
    2012             :         struct lgfs2_buffer_head *tbh;
    2013             :         uint64_t b;
    2014           0 :         int dinodes = 0;
    2015             :         char *byte, cur_state, new_state;
    2016             :         int bit, off;
    2017             : 
    2018           0 :         if (bitmap)
    2019           0 :                 off = sizeof(struct gfs2_meta_header);
    2020             :         else
    2021           0 :                 off = sizeof(struct gfs2_rgrp);
    2022             : 
    2023           0 :         for (b = 0; b < rgd->rt_bits[bitmap].bi_len << GFS2_BIT_SIZE; b++) {
    2024           0 :                 tbh = lgfs2_bread(&sbd, rgd->rt_data0 +
    2025             :                             rgd->rt_bits[bitmap].bi_start + b);
    2026           0 :                 byte = rbh->b_data + off + (b / GFS2_NBBY);
    2027           0 :                 bit = (b % GFS2_NBBY) * GFS2_BIT_SIZE;
    2028           0 :                 if (lgfs2_check_meta(tbh->b_data, GFS2_METATYPE_DI) == 0) {
    2029           0 :                         dinodes++;
    2030           0 :                         new_state = GFS2_BLKST_DINODE;
    2031             :                 } else {
    2032           0 :                         new_state = GFS2_BLKST_USED;
    2033             :                 }
    2034           0 :                 cur_state = (*byte >> bit) & GFS2_BIT_MASK;
    2035           0 :                 *byte ^= cur_state << bit;
    2036           0 :                 *byte |= new_state << bit;
    2037           0 :                 lgfs2_brelse(tbh);
    2038             :         }
    2039           0 :         lgfs2_bmodified(rbh);
    2040           0 :         return dinodes;
    2041             : }
    2042             : 
    2043           0 : static int count_dinode_bits(struct lgfs2_buffer_head *rbh)
    2044             : {
    2045             :         uint64_t blk;
    2046           0 :         struct gfs2_meta_header *mh = (struct gfs2_meta_header *)rbh->b_data;
    2047             :         char *byte;
    2048             :         int bit;
    2049           0 :         int dinodes = 0;
    2050             : 
    2051           0 :         if (be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RG)
    2052           0 :                 blk = sizeof(struct gfs2_rgrp);
    2053             :         else
    2054           0 :                 blk = sizeof(struct gfs2_meta_header);
    2055             : 
    2056           0 :         for (; blk < sbd.sd_bsize; blk++) {
    2057           0 :                 byte = rbh->b_data + (blk / GFS2_NBBY);
    2058           0 :                 bit = (blk % GFS2_NBBY) * GFS2_BIT_SIZE;
    2059           0 :                 if (((*byte >> bit) & GFS2_BIT_MASK) == GFS2_BLKST_DINODE)
    2060           0 :                         dinodes++;
    2061             :         }
    2062           0 :         return dinodes;
    2063             : }
    2064             : 
    2065           0 : static void rg_repair(void)
    2066             : {
    2067             :         struct lgfs2_buffer_head *rbh;
    2068             :         struct lgfs2_rgrp_tree *rgd;
    2069             :         struct osi_node *n;
    2070             :         int b;
    2071           0 :         int rgs_fixed = 0;
    2072           0 :         int dinodes_found = 0, dinodes_total = 0;
    2073             : 
    2074             :         /* Walk through the resource groups saving everything within */
    2075           0 :         for (n = osi_first(&sbd.rgtree); n; n = osi_next(n)) {
    2076           0 :                 rgd = (struct lgfs2_rgrp_tree *)n;
    2077           0 :                 if (lgfs2_rgrp_read(&sbd, rgd) == 0) { /* was read in okay */
    2078           0 :                         lgfs2_rgrp_relse(&sbd, rgd);
    2079           0 :                         continue; /* ignore it */
    2080             :                 }
    2081             :                 /* If we get here, it's because we have an rgrp in the rindex
    2082             :                    file that can't be read in. So attempt to repair it.
    2083             :                    If we find a damaged rgrp or bitmap, fix the metadata.
    2084             :                    Then scan all its blocks: if we find a dinode, set the
    2085             :                    repaired bitmap to GFS2_BLKST_DINODE. Set all others to
    2086             :                    GFS2_BLKST_USED so fsck can sort it out. If we set them
    2087             :                    to FREE, fsck would just nuke it all. */
    2088           0 :                 printf("Resource group at block %"PRIu64" (0x%"PRIx64") appears to be "
    2089             :                        "damaged. Attempting to fix it (in reverse order).\n",
    2090             :                        rgd->rt_addr, rgd->rt_addr);
    2091             : 
    2092           0 :                 for (b = rgd->rt_length - 1; b >= 0; b--) {
    2093           0 :                         int mtype = (b ? GFS2_METATYPE_RB : GFS2_METATYPE_RG);
    2094             :                         struct gfs2_meta_header *mh;
    2095             : 
    2096           0 :                         printf("Bitmap #%d:", b);
    2097           0 :                         rbh = lgfs2_bread(&sbd, rgd->rt_addr + b);
    2098           0 :                         if (lgfs2_check_meta(rbh->b_data, mtype)) { /* wrong type */
    2099           0 :                                 printf("Damaged. Repairing...");
    2100             :                                 /* Fix the meta header */
    2101           0 :                                 memset(rbh->b_data, 0, sbd.sd_bsize);
    2102           0 :                                 mh = (struct gfs2_meta_header *)rbh->b_data;
    2103           0 :                                 mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
    2104           0 :                                 mh->mh_type = cpu_to_be32(mtype);
    2105           0 :                                 if (b)
    2106           0 :                                         mh->mh_format =
    2107           0 :                                                 cpu_to_be32(GFS2_FORMAT_RB);
    2108             :                                 else
    2109           0 :                                         mh->mh_format =
    2110           0 :                                                 cpu_to_be32(GFS2_FORMAT_RG);
    2111           0 :                                 lgfs2_bmodified(rbh);
    2112             :                                 /* Count the dinode blocks */
    2113           0 :                                 dinodes_found = count_dinode_blks(rgd, b, rbh);
    2114             :                         } else { /* bitmap info is okay: tally it. */
    2115           0 :                                 printf("Undamaged. Analyzing...");
    2116           0 :                                 dinodes_found = count_dinode_bits(rbh);
    2117             :                         }
    2118           0 :                         printf("Dinodes found: %d\n", dinodes_found);
    2119           0 :                         dinodes_total += dinodes_found;
    2120           0 :                         if (b == 0) { /* rgrp itself was damaged */
    2121           0 :                                 rgd->rt_dinodes = dinodes_total;
    2122           0 :                                 rgd->rt_free = 0;
    2123             :                         }
    2124           0 :                         lgfs2_brelse(rbh);
    2125             :                 }
    2126           0 :                 rgs_fixed++;
    2127             :         }
    2128           0 :         if (rgs_fixed)
    2129           0 :                 printf("%d resource groups fixed.\n"
    2130             :                        "You should run fsck.gfs2 to reconcile the bitmaps.\n",
    2131             :                        rgs_fixed);
    2132             :         else
    2133           0 :                 printf("All resource groups are okay. No repairs needed.\n");
    2134           0 :         exit(0);
    2135             : }
    2136             : 
    2137             : /* ------------------------------------------------------------------------ */
    2138             : /* parameterpass1 - pre-processing for command-line parameters              */
    2139             : /* ------------------------------------------------------------------------ */
    2140       17864 : static void parameterpass1(int argc, char *argv[], int i)
    2141             : {
    2142       17864 :         if (!strcasecmp(argv[i], "-V")) {
    2143           0 :                 printf("%s version %s (built %s %s)\n",
    2144             :                        argv[0], VERSION, __DATE__, __TIME__);
    2145           0 :                 printf("%s\n", REDHAT_COPYRIGHT);
    2146           0 :                 exit(0);
    2147             :         }
    2148       17864 :         else if (!strcasecmp(argv[i], "-h") ||
    2149       17864 :                  !strcasecmp(argv[i], "-help") ||
    2150       17864 :                  !strcasecmp(argv[i], "-usage")) {
    2151           0 :                 usage();
    2152           0 :                 exit(0);
    2153             :         }
    2154       17864 :         else if (!strcasecmp(argv[i], "-c")) {
    2155           0 :                 i++;
    2156           0 :                 color_scheme = atoi(argv[i]);
    2157             :         }
    2158       17864 :         else if (!strcasecmp(argv[i], "-p") ||
    2159       13406 :                  !strcasecmp(argv[i], "-print")) {
    2160        4458 :                 termlines = 0; /* initial value--we'll figure
    2161             :                                   it out later */
    2162        4458 :                 dmode = GFS2_MODE;
    2163             :         }
    2164       13406 :         else if (!strcasecmp(argv[i], "-d") ||
    2165       13406 :                  !strcasecmp(argv[i], "-details"))
    2166           0 :                 details = 1;
    2167       13406 :         else if (!strcasecmp(argv[i], "savemeta"))
    2168           7 :                 termlines = 0;
    2169       13399 :         else if (!strcasecmp(argv[i], "savemetaslow"))
    2170           0 :                 termlines = 0;
    2171       13399 :         else if (!strcasecmp(argv[i], "savergs"))
    2172           0 :                 termlines = 0;
    2173       13399 :         else if (!strcasecmp(argv[i], "printsavedmeta")) {
    2174           0 :                 if (dmode == INIT_MODE)
    2175           0 :                         dmode = GFS2_MODE;
    2176           0 :                 restoremeta(argv[i+1], argv[i+2], TRUE);
    2177       13399 :         } else if (!strcasecmp(argv[i], "restoremeta")) {
    2178           5 :                 if (dmode == INIT_MODE)
    2179           5 :                         dmode = HEX_MODE; /* hopefully not used */
    2180           5 :                 restoremeta(argv[i+1], argv[i+2], FALSE);
    2181       13394 :         } else if (!strcmp(argv[i], "rgcount"))
    2182           6 :                 termlines = 0;
    2183       13388 :         else if (!strcmp(argv[i], "rgflags"))
    2184           0 :                 termlines = 0;
    2185       13388 :         else if (!strcmp(argv[i], "rgrepair"))
    2186           0 :                 termlines = 0;
    2187       13388 :         else if (!strcmp(argv[i], "rg"))
    2188        4437 :                 termlines = 0;
    2189        8951 :         else if (!strcasecmp(argv[i], "-x"))
    2190           4 :                 dmode = HEX_MODE;
    2191        8947 :         else if (device == NULL && strchr(argv[i],'/')) {
    2192        4465 :                 device = argv[i];
    2193             :         }
    2194       17859 : }
    2195             : 
    2196             : /* ------------------------------------------------------------------------ */
    2197             : /* process_parameters - process commandline parameters                      */
    2198             : /* pass - we make two passes through the parameters; the first pass gathers */
    2199             : /*        normals parameters, device name, etc.  The second pass is for     */
    2200             : /*        figuring out what structures to print out.                        */
    2201             : /* ------------------------------------------------------------------------ */
    2202        8936 : static void process_parameters(int argc, char *argv[], int pass)
    2203             : {
    2204             :         int i;
    2205             :         uint64_t keyword_blk;
    2206             : 
    2207        8936 :         if (argc < 2) {
    2208           0 :                 fprintf(stderr, "No device specified\n");
    2209           0 :                 exit(1);
    2210             :         }
    2211       31279 :         for (i = 1; i < argc; i++) {
    2212       26806 :                 if (!pass) { /* first pass */
    2213       17864 :                         parameterpass1(argc, argv, i);
    2214       17859 :                         continue;
    2215             :                 }
    2216             :                 /* second pass */
    2217        8942 :                 if (!strcasecmp(argv[i], "-s")) {
    2218           0 :                         i++;
    2219           0 :                         if (i >= argc - 1) {
    2220           0 :                                 printf("Error: starting block not specified "
    2221             :                                        "with -s.\n");
    2222           0 :                                 printf("%s -s [starting block | keyword] "
    2223             :                                        "<device>\n", argv[0]);
    2224           0 :                                 printf("For example: %s -s \"rg 3\" "
    2225             :                                        "/dev/exxon_vg/exxon_lv\n", argv[0]);
    2226           0 :                                 exit(EXIT_FAILURE);
    2227             :                         }
    2228           0 :                         starting_blk = check_keywords(argv[i]);
    2229           0 :                         continue;
    2230             :                 }
    2231        8942 :                 if (termlines || strchr(argv[i],'/')) /* if print or slash */
    2232           7 :                         continue;
    2233             : 
    2234        8935 :                 if (!strncmp(argv[i], "journal", 7) && isdigit(argv[i][7]) &&
    2235           2 :                     strcmp(argv[i+1], "field")) {
    2236           0 :                         uint64_t blk = 0;
    2237             : 
    2238           0 :                         if (i < argc - 1 && isdigit(argv[i + 1][0])) {
    2239           0 :                                 if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
    2240           0 :                                         sscanf(argv[i + 1], "%"SCNx64, &blk);
    2241             :                                 else
    2242           0 :                                         sscanf(argv[i + 1], "%"SCNu64, &blk);
    2243             :                         }
    2244           0 :                         dump_journal(argv[i], blk);
    2245           0 :                         continue;
    2246             :                 }
    2247        8935 :                 keyword_blk = check_keywords(argv[i]);
    2248        8935 :                 if (keyword_blk)
    2249          15 :                         push_block(keyword_blk);
    2250        8920 :                 else if (!strcasecmp(argv[i], "-x"))
    2251           4 :                         dmode = HEX_MODE;
    2252        8916 :                 else if (argv[i][0] == '-') /* if it starts with a dash */
    2253             :                         ; /* ignore it--meant for pass == 0 */
    2254        4458 :                 else if (!strcmp(argv[i], "identify"))
    2255           0 :                         identify = TRUE;
    2256        4458 :                 else if (!strcmp(argv[i], "size")) {
    2257           0 :                         printf("Device size: %"PRIu64" blocks\n", max_block);
    2258           0 :                         exit(EXIT_SUCCESS);
    2259        4458 :                 } else if (!strcmp(argv[i], "rgcount"))
    2260           6 :                         rgcount();
    2261        4452 :                 else if (!strcmp(argv[i], "field")) {
    2262           8 :                         i++;
    2263           8 :                         if (i >= argc - 1) {
    2264           0 :                                 printf("Error: field not specified.\n");
    2265           0 :                                 printf("Format is: %s -p <block> field "
    2266             :                                        "<field> [newvalue]\n", argv[0]);
    2267           0 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2268           0 :                                 exit(EXIT_FAILURE);
    2269             :                         }
    2270           8 :                         process_field(argv[i], argv[i + 1]);
    2271        4444 :                 } else if (!strcmp(argv[i], "blocktype")) {
    2272           0 :                         find_print_block_type();
    2273        4444 :                 } else if (!strcmp(argv[i], "blockrg")) {
    2274           0 :                         find_print_block_rg(0);
    2275        4444 :                 } else if (!strcmp(argv[i], "blockbits")) {
    2276           0 :                         find_print_block_rg(1);
    2277        4444 :                 } else if (!strcmp(argv[i], "blockalloc")) {
    2278           0 :                         if (isdigit(argv[i + 1][0])) {
    2279             :                                 int newval;
    2280             : 
    2281           0 :                                 if (argv[i + 1][0]=='0' && argv[i + 1][1]=='x')
    2282           0 :                                         sscanf(argv[i + 1], "%x", &newval);
    2283             :                                 else
    2284           0 :                                         newval = (uint64_t)atoi(argv[i + 1]);
    2285           0 :                                 find_change_block_alloc(&newval);
    2286             :                         } else {
    2287           0 :                                 find_change_block_alloc(NULL);
    2288             :                         }
    2289        4444 :                 } else if (!strcmp(argv[i], "find")) {
    2290           0 :                         find_metablockoftype(argv[i + 1], 1);
    2291        4444 :                 } else if (!strcmp(argv[i], "rgflags")) {
    2292           0 :                         int rg, set = FALSE;
    2293           0 :                         uint32_t new_flags = 0;
    2294             : 
    2295           0 :                         i++;
    2296           0 :                         if (i >= argc - 1) {
    2297           0 :                                 printf("Error: rg # not specified.\n");
    2298           0 :                                 printf("Format is: %s rgflags rgnum"
    2299             :                                        "[newvalue]\n", argv[0]);
    2300           0 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2301           0 :                                 exit(EXIT_FAILURE);
    2302             :                         }
    2303           0 :                         if (argv[i][0]=='0' && argv[i][1]=='x')
    2304           0 :                                 sscanf(argv[i], "%"SCNx32, &rg);
    2305             :                         else
    2306           0 :                                 rg = atoi(argv[i]);
    2307           0 :                         i++;
    2308           0 :                         if (i < argc - 1 &&
    2309           0 :                             isdigit(argv[i][0])) {
    2310           0 :                                 set = TRUE;
    2311           0 :                                 if (argv[i][0]=='0' && argv[i][1]=='x')
    2312           0 :                                         sscanf(argv[i], "%"SCNx32, &new_flags);
    2313             :                                 else
    2314           0 :                                         new_flags = atoi(argv[i]);
    2315             :                         }
    2316           0 :                         set_rgrp_flags(rg, new_flags, set, FALSE);
    2317           0 :                         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2318           0 :                         exit(EXIT_SUCCESS);
    2319        4444 :                 } else if (!strcmp(argv[i], "rg")) {
    2320             :                         int rg;
    2321             : 
    2322        4437 :                         i++;
    2323        4437 :                         if (i >= argc - 1) {
    2324           0 :                                 printf("Error: rg # not specified.\n");
    2325           0 :                                 printf("Format is: %s rg rgnum\n", argv[0]);
    2326           0 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2327           0 :                                 exit(EXIT_FAILURE);
    2328             :                         }
    2329        4437 :                         rg = atoi(argv[i]);
    2330        4437 :                         if (!strcasecmp(argv[i + 1], "find")) {
    2331           0 :                                 temp_blk = get_rg_addr(rg);
    2332           0 :                                 push_block(temp_blk);
    2333             :                         } else {
    2334        4437 :                                 set_rgrp_flags(rg, 0, FALSE, TRUE);
    2335        4437 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2336        4437 :                                 exit(EXIT_SUCCESS);
    2337             :                         }
    2338           7 :                 } else if (!strcmp(argv[i], "rgbitmaps")) {
    2339             :                         int rg, bmap;
    2340             :                         uint64_t rgblk;
    2341             :                         struct lgfs2_rgrp_tree *rgd;
    2342             : 
    2343           0 :                         i++;
    2344           0 :                         if (i >= argc - 1) {
    2345           0 :                                 printf("Error: rg # not specified.\n");
    2346           0 :                                 printf("Format is: %s rgbitmaps rgnum\n",
    2347             :                                        argv[0]);
    2348           0 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2349           0 :                                 exit(EXIT_FAILURE);
    2350             :                         }
    2351           0 :                         rg = atoi(argv[i]);
    2352           0 :                         rgblk = get_rg_addr(rg);
    2353           0 :                         rgd = lgfs2_blk2rgrpd(&sbd, rgblk);
    2354           0 :                         if (rgd == NULL) {
    2355           0 :                                 printf("Error: rg # is invalid.\n");
    2356           0 :                                 lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2357           0 :                                 exit(EXIT_FAILURE);
    2358             :                         }
    2359           0 :                         for (bmap = 0; bmap < rgd->rt_length; bmap++)
    2360           0 :                                 push_block(rgblk + bmap);
    2361             :                 }
    2362           7 :                 else if (!strcmp(argv[i], "rgrepair"))
    2363           0 :                         rg_repair();
    2364           7 :                 else if (!strcasecmp(argv[i], "savemeta")) {
    2365           7 :                         getgziplevel(argv, &i);
    2366           7 :                         savemeta(argv[i+2], 0, gziplevel);
    2367           0 :                 } else if (!strcasecmp(argv[i], "savemetaslow")) {
    2368           0 :                         getgziplevel(argv, &i);
    2369           0 :                         savemeta(argv[i+2], 1, gziplevel);
    2370           0 :                 } else if (!strcasecmp(argv[i], "savergs")) {
    2371           0 :                         getgziplevel(argv, &i);
    2372           0 :                         savemeta(argv[i+2], 2, gziplevel);
    2373           0 :                 } else if (isdigit(argv[i][0])) { /* decimal addr */
    2374           0 :                         sscanf(argv[i], "%"SCNd64, &temp_blk);
    2375           0 :                         push_block(temp_blk);
    2376             :                 } else {
    2377           0 :                         fprintf(stderr,"I don't know what '%s' means.\n",
    2378           0 :                                 argv[i]);
    2379           0 :                         usage();
    2380           0 :                         exit(EXIT_FAILURE);
    2381             :                 }
    2382             :         } /* for */
    2383        4473 : }/* process_parameters */
    2384             : 
    2385             : #ifndef UNITTESTS
    2386        4471 : int main(int argc, char *argv[])
    2387             : {
    2388             :         int i, j, fd;
    2389             : 
    2390        4471 :         indirect = malloc(sizeof(struct iinfo));
    2391        4471 :         if (indirect == NULL) {
    2392           0 :                 perror("Failed to allocate indirect info");
    2393           0 :                 exit(1);
    2394             :         }
    2395        4471 :         memset(indirect, 0, sizeof(struct iinfo));
    2396        4471 :         memset(start_row, 0, sizeof(start_row));
    2397        4471 :         memset(lines_per_row, 0, sizeof(lines_per_row));
    2398        4471 :         memset(end_row, 0, sizeof(end_row));
    2399        4471 :         memset(edit_row, 0, sizeof(edit_row));
    2400        4471 :         memset(edit_col, 0, sizeof(edit_col));
    2401        4471 :         memset(edit_size, 0, sizeof(edit_size));
    2402        4471 :         memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
    2403        4471 :         dmode = INIT_MODE;
    2404        4471 :         sbd.sd_bsize = 4096;
    2405        4471 :         block = starting_blk = 0x10;
    2406     1149047 :         for (i = 0; i < BLOCK_STACK_SIZE; i++) {
    2407     1144576 :                 blockstack[i].dmode = HEX_MODE;
    2408     1144576 :                 blockstack[i].block = block;
    2409     4578304 :                 for (j = 0; j < DMODES; j++) {
    2410     3433728 :                         blockstack[i].start_row[j] = 0;
    2411     3433728 :                         blockstack[i].end_row[j] = 0;
    2412     3433728 :                         blockstack[i].edit_row[j] = 0;
    2413     3433728 :                         blockstack[i].edit_col[j] = 0;
    2414     3433728 :                         blockstack[i].lines_per_row[j] = 0;
    2415             :                 }
    2416             :         }
    2417             : 
    2418        4471 :         edit_row[GFS2_MODE] = 10; /* Start off at root inode
    2419             :                                      pointer in superblock */
    2420        4471 :         termlines = 30;  /* assume interactive mode until we find -p */
    2421        4471 :         process_parameters(argc, argv, 0);
    2422        4466 :         if (dmode == INIT_MODE)
    2423           8 :                 dmode = HEX_MODE;
    2424             : 
    2425        4466 :         fd = open(device, O_RDWR);
    2426        4466 :         if (fd < 0) {
    2427           1 :                 fprintf(stderr, "Failed to open '%s': %s\n", device, strerror(errno));
    2428           1 :                 exit(1);
    2429             :         }
    2430        4465 :         max_block = lseek(fd, 0, SEEK_END) / sbd.sd_bsize;
    2431             : 
    2432        4465 :         read_superblock(fd);
    2433        4465 :         if (read_rindex())
    2434           0 :                 exit(-1);
    2435        4465 :         max_block = lseek(fd, 0, SEEK_END) / sbd.sd_bsize;
    2436        4465 :         if (read_master_dir() != 0)
    2437           0 :                 exit(-1);
    2438             : 
    2439        4465 :         process_parameters(argc, argv, 1); /* get what to print from cmdline */
    2440             : 
    2441           7 :         block = blockstack[0].block = starting_blk * (4096 / sbd.sd_bsize);
    2442             : 
    2443           7 :         if (termlines)
    2444           0 :                 interactive_mode();
    2445             :         else { /* print all the structures requested */
    2446           7 :                 i = 0;
    2447          14 :                 while (blockhist > 0) {
    2448           7 :                         block = blockstack[i + 1].block;
    2449           7 :                         if (!block)
    2450           0 :                                 break;
    2451           7 :                         display(identify, 0, 0, 0);
    2452           7 :                         if (!identify) {
    2453           7 :                                 display_extended();
    2454           7 :                                 printf("-------------------------------------" \
    2455             :                                        "-----------------");
    2456           7 :                                 eol(0);
    2457             :                         }
    2458           7 :                         block = pop_block();
    2459           7 :                         i++;
    2460             :                 }
    2461             :         }
    2462           7 :         close(fd);
    2463           7 :         if (indirect)
    2464           7 :                 free(indirect);
    2465           7 :         lgfs2_rgrp_free(&sbd, &sbd.rgtree);
    2466           7 :         exit(EXIT_SUCCESS);
    2467             : }
    2468             : #endif /* UNITTESTS */

Generated by: LCOV version 1.14