LCOV - code coverage report
Current view: top level - edit - hexedit.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 24.2 % 1554 376
Test Date: 2024-03-07 16:24:06 Functions: 46.2 % 52 24

            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         4832 : uint64_t masterblock(const char *fn)
     656              : {
     657              :         int d;
     658              :         
     659        23848 :         for (d = 2; d < 8; d++)
     660        23848 :                 if (!strncmp(masterdir.dirent[d].filename, fn, strlen(fn)))
     661         4832 :                         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           92 : int block_is_rindex(uint64_t blk)
     765              : {
     766           92 :         return blk == masterblock("rindex");
     767              : }
     768              : 
     769           94 : int block_is_inum_file(uint64_t blk)
     770              : {
     771           94 :         return blk == masterblock("inum");
     772              : }
     773              : 
     774           86 : int block_is_statfs_file(uint64_t blk)
     775              : {
     776           86 :         return blk == masterblock("statfs");
     777              : }
     778              : 
     779           78 : int block_is_quota_file(uint64_t blk)
     780              : {
     781           78 :         return blk == masterblock("quota");
     782              : }
     783              : 
     784           28 : int block_is_per_node(uint64_t blk)
     785              : {
     786           28 :         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         4466 : static void read_superblock(int fd)
     806              : {
     807              :         struct gfs2_meta_header *mh;
     808              : 
     809         4466 :         ioctl(fd, BLKFLSBUF, 0);
     810         4466 :         memset(&sbd, 0, sizeof(struct lgfs2_sbd));
     811         4466 :         sbd.sd_bsize = LGFS2_DEFAULT_BSIZE;
     812         4466 :         sbd.device_fd = fd;
     813         4466 :         bh = lgfs2_bread(&sbd, 0x10);
     814         4466 :         sbd.rgtree.osi_node = NULL;
     815         4466 :         lgfs2_sb_in(&sbd, bh->b_data);
     816         4466 :         mh = (struct gfs2_meta_header *)bh->b_data;
     817         4466 :         if (!sbd.sd_bsize)
     818            0 :                 sbd.sd_bsize = LGFS2_DEFAULT_BSIZE;
     819         4466 :         if (lgfs2_get_dev_info(fd, &sbd.dinfo)) {
     820            0 :                 perror(device);
     821            0 :                 exit(-1);
     822              :         }
     823         4466 :         if (lgfs2_compute_constants(&sbd)) {
     824            0 :                 fprintf(stderr, "Failed to compute constants.\n");
     825            0 :                 exit(-1);
     826              :         }
     827         8932 :         if (be32_to_cpu(mh->mh_magic) == GFS2_MAGIC &&
     828         4466 :             be32_to_cpu(mh->mh_type) == GFS2_METATYPE_SB)
     829         4466 :                 block = 0x10 * (LGFS2_DEFAULT_BSIZE / sbd.sd_bsize);
     830              :         else
     831            0 :                 block = starting_blk = 0;
     832         4466 :         lgfs2_fix_device_geometry(&sbd);
     833         4466 :         sbd.sd_inptrs = (sbd.sd_bsize - sizeof(struct gfs2_meta_header)) /
     834              :                 sizeof(uint64_t);
     835         4466 :         sbd.sd_diptrs = (sbd.sd_bsize - sizeof(struct gfs2_dinode)) /
     836              :                 sizeof(uint64_t);
     837         4466 :         sbd.master_dir = lgfs2_inode_read(&sbd, sbd.sd_meta_dir.in_addr);
     838         4466 :         if (sbd.master_dir == NULL) {
     839            0 :                 sbd.md.riinode = NULL;
     840              :         } else {
     841         4466 :                 sbd.md.riinode = lgfs2_lookupi(sbd.master_dir, "rindex", 6);
     842              :         }
     843         4466 :         lgfs2_brelse(bh);
     844         4466 :         bh = NULL;
     845         4466 : }
     846              : 
     847         4466 : static int read_rindex(void)
     848              : {
     849              :         uint64_t count;
     850              :         int ok;
     851              : 
     852         4466 :         sbd.fssize = sbd.device.length;
     853         4466 :         if (sbd.md.riinode) /* If we found the rindex */
     854         4466 :                 lgfs2_rindex_read(&sbd, &count, &ok);
     855              : 
     856         4466 :         if (!OSI_EMPTY_ROOT(&sbd.rgtree)) {
     857         4466 :                 struct lgfs2_rgrp_tree *rg = (struct lgfs2_rgrp_tree *)osi_last(&sbd.rgtree);
     858         4466 :                 sbd.fssize = rg->rt_data0 + rg->rt_data;
     859              :         }
     860         4466 :         return 0;
     861              : }
     862              : 
     863         4466 : static int read_master_dir(void)
     864              : {
     865         4466 :         ioctl(sbd.device_fd, BLKFLSBUF, 0);
     866              : 
     867         4466 :         bh = lgfs2_bread(&sbd, sbd.sd_meta_dir.in_addr);
     868         4466 :         if (bh == NULL)
     869            0 :                 return 1;
     870         4466 :         di = (struct gfs2_dinode *)bh->b_data;
     871         4466 :         do_dinode_extended(bh->b_data); /* get extended data, if any */
     872         4466 :         memcpy(&masterdir, &indirect[0], sizeof(struct indirect_info));
     873         4466 :         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         8936 : uint64_t check_keywords(const char *kword)
    1195              : {
    1196         8936 :         uint64_t blk = 0;
    1197              : 
    1198         8936 :         if (!strcmp(kword, "sb") ||!strcmp(kword, "superblock"))
    1199            2 :                 blk = 0x10 * (4096 / sbd.sd_bsize); /* superblock */
    1200         8934 :         else if (!strcmp(kword, "root") || !strcmp(kword, "rootdir"))
    1201            4 :                 blk = sbd.sd_root_dir.in_addr;
    1202         8930 :         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         8930 :         else if (!strcmp(kword, "jindex"))
    1210            0 :                 blk = masterblock("jindex");
    1211         8930 :         else if (!strcmp(kword, "per_node"))
    1212            0 :                 blk = masterblock("per_node");
    1213         8930 :         else if (!strcmp(kword, "inum"))
    1214            0 :                 blk = masterblock("inum");
    1215         8930 :         else if (!strcmp(kword, "statfs"))
    1216            0 :                 blk = masterblock("statfs");
    1217         8930 :         else if (!strcmp(kword, "rindex") || !strcmp(kword, "rgindex")) {
    1218            7 :                 blk = masterblock("rindex");
    1219         8923 :         } else if (!strcmp(kword, "rgs")) {
    1220            0 :                 blk = RGLIST_DUMMY_BLOCK;
    1221         8923 :         } else if (!strcmp(kword, "quota")) {
    1222            0 :                 blk = masterblock("quota");
    1223         8923 :         } 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         8923 :         } else if (!strncmp(kword, "journals", 8)) {
    1229            0 :                 blk = JOURNALS_DUMMY_BLOCK;
    1230         8923 :         } 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         8921 :         } else if (kword[0]=='/') /* search */
    1235            0 :                 blk = find_metablockoftype(&kword[1], 0);
    1236         8921 :         else if (kword[0]=='0' && kword[1]=='x') /* hex addr */
    1237            0 :                 sscanf(kword, "%"SCNx64, &blk);/* retrieve in hex */
    1238              :         else
    1239         8921 :                 sscanf(kword, "%"SCNu64, &blk); /* retrieve decimal */
    1240              : 
    1241         8936 :         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            8 : static void getgziplevel(char *argv[], int *i)
    1987              : {
    1988              :         char *opt, *arg;
    1989              :         char *endptr;
    1990              : 
    1991            8 :         arg = argv[1 + *i];
    1992            8 :         if (strncmp(arg, "-z", 2)) {
    1993            3 :                 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        17868 : static void parameterpass1(int argc, char *argv[], int i)
    2141              : {
    2142        17868 :         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        17868 :         else if (!strcasecmp(argv[i], "-h") ||
    2149        17868 :                  !strcasecmp(argv[i], "-help") ||
    2150        17868 :                  !strcasecmp(argv[i], "-usage")) {
    2151            0 :                 usage();
    2152            0 :                 exit(0);
    2153              :         }
    2154        17868 :         else if (!strcasecmp(argv[i], "-c")) {
    2155            0 :                 i++;
    2156            0 :                 color_scheme = atoi(argv[i]);
    2157              :         }
    2158        17868 :         else if (!strcasecmp(argv[i], "-p") ||
    2159        13410 :                  !strcasecmp(argv[i], "-print")) {
    2160         4458 :                 termlines = 0; /* initial value--we'll figure
    2161              :                                   it out later */
    2162         4458 :                 dmode = GFS2_MODE;
    2163              :         }
    2164        13410 :         else if (!strcasecmp(argv[i], "-d") ||
    2165        13410 :                  !strcasecmp(argv[i], "-details"))
    2166            0 :                 details = 1;
    2167        13410 :         else if (!strcasecmp(argv[i], "savemeta"))
    2168            8 :                 termlines = 0;
    2169        13402 :         else if (!strcasecmp(argv[i], "savemetaslow"))
    2170            0 :                 termlines = 0;
    2171        13402 :         else if (!strcasecmp(argv[i], "savergs"))
    2172            0 :                 termlines = 0;
    2173        13402 :         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        13402 :         } else if (!strcasecmp(argv[i], "restoremeta")) {
    2178            6 :                 if (dmode == INIT_MODE)
    2179            6 :                         dmode = HEX_MODE; /* hopefully not used */
    2180            6 :                 restoremeta(argv[i+1], argv[i+2], FALSE);
    2181        13396 :         } else if (!strcmp(argv[i], "rgcount"))
    2182            6 :                 termlines = 0;
    2183        13390 :         else if (!strcmp(argv[i], "rgflags"))
    2184            0 :                 termlines = 0;
    2185        13390 :         else if (!strcmp(argv[i], "rgrepair"))
    2186            0 :                 termlines = 0;
    2187        13390 :         else if (!strcmp(argv[i], "rg"))
    2188         4437 :                 termlines = 0;
    2189         8953 :         else if (!strcasecmp(argv[i], "-x"))
    2190            4 :                 dmode = HEX_MODE;
    2191         8949 :         else if (device == NULL && strchr(argv[i],'/')) {
    2192         4466 :                 device = argv[i];
    2193              :         }
    2194        17862 : }
    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         8939 : static void process_parameters(int argc, char *argv[], int pass)
    2203              : {
    2204              :         int i;
    2205              :         uint64_t keyword_blk;
    2206              : 
    2207         8939 :         if (argc < 2) {
    2208            0 :                 fprintf(stderr, "No device specified\n");
    2209            0 :                 exit(1);
    2210              :         }
    2211        31285 :         for (i = 1; i < argc; i++) {
    2212        26811 :                 if (!pass) { /* first pass */
    2213        17868 :                         parameterpass1(argc, argv, i);
    2214        17862 :                         continue;
    2215              :                 }
    2216              :                 /* second pass */
    2217         8943 :                 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         8943 :                 if (termlines || strchr(argv[i],'/')) /* if print or slash */
    2232            7 :                         continue;
    2233              : 
    2234         8936 :                 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         8936 :                 keyword_blk = check_keywords(argv[i]);
    2248         8936 :                 if (keyword_blk)
    2249           15 :                         push_block(keyword_blk);
    2250         8921 :                 else if (!strcasecmp(argv[i], "-x"))
    2251            4 :                         dmode = HEX_MODE;
    2252         8917 :                 else if (argv[i][0] == '-') /* if it starts with a dash */
    2253              :                         ; /* ignore it--meant for pass == 0 */
    2254         4459 :                 else if (!strcmp(argv[i], "identify"))
    2255            0 :                         identify = TRUE;
    2256         4459 :                 else if (!strcmp(argv[i], "size")) {
    2257            0 :                         printf("Device size: %"PRIu64" blocks\n", max_block);
    2258            0 :                         exit(EXIT_SUCCESS);
    2259         4459 :                 } else if (!strcmp(argv[i], "rgcount"))
    2260            6 :                         rgcount();
    2261         4453 :                 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         4445 :                 } else if (!strcmp(argv[i], "blocktype")) {
    2272            0 :                         find_print_block_type();
    2273         4445 :                 } else if (!strcmp(argv[i], "blockrg")) {
    2274            0 :                         find_print_block_rg(0);
    2275         4445 :                 } else if (!strcmp(argv[i], "blockbits")) {
    2276            0 :                         find_print_block_rg(1);
    2277         4445 :                 } 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         4445 :                 } else if (!strcmp(argv[i], "find")) {
    2290            0 :                         find_metablockoftype(argv[i + 1], 1);
    2291         4445 :                 } 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         4445 :                 } 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            8 :                 } 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            8 :                 else if (!strcmp(argv[i], "rgrepair"))
    2363            0 :                         rg_repair();
    2364            8 :                 else if (!strcasecmp(argv[i], "savemeta")) {
    2365            8 :                         getgziplevel(argv, &i);
    2366            8 :                         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         4474 : }/* process_parameters */
    2384              : 
    2385              : #ifndef UNITTESTS
    2386         4473 : int main(int argc, char *argv[])
    2387              : {
    2388              :         int i, j, fd;
    2389              : 
    2390         4473 :         indirect = malloc(sizeof(struct iinfo));
    2391         4473 :         if (indirect == NULL) {
    2392            0 :                 perror("Failed to allocate indirect info");
    2393            0 :                 exit(1);
    2394              :         }
    2395         4473 :         memset(indirect, 0, sizeof(struct iinfo));
    2396         4473 :         memset(start_row, 0, sizeof(start_row));
    2397         4473 :         memset(lines_per_row, 0, sizeof(lines_per_row));
    2398         4473 :         memset(end_row, 0, sizeof(end_row));
    2399         4473 :         memset(edit_row, 0, sizeof(edit_row));
    2400         4473 :         memset(edit_col, 0, sizeof(edit_col));
    2401         4473 :         memset(edit_size, 0, sizeof(edit_size));
    2402         4473 :         memset(last_entry_onscreen, 0, sizeof(last_entry_onscreen));
    2403         4473 :         dmode = INIT_MODE;
    2404         4473 :         sbd.sd_bsize = 4096;
    2405         4473 :         block = starting_blk = 0x10;
    2406      1149561 :         for (i = 0; i < BLOCK_STACK_SIZE; i++) {
    2407      1145088 :                 blockstack[i].dmode = HEX_MODE;
    2408      1145088 :                 blockstack[i].block = block;
    2409      4580352 :                 for (j = 0; j < DMODES; j++) {
    2410      3435264 :                         blockstack[i].start_row[j] = 0;
    2411      3435264 :                         blockstack[i].end_row[j] = 0;
    2412      3435264 :                         blockstack[i].edit_row[j] = 0;
    2413      3435264 :                         blockstack[i].edit_col[j] = 0;
    2414      3435264 :                         blockstack[i].lines_per_row[j] = 0;
    2415              :                 }
    2416              :         }
    2417              : 
    2418         4473 :         edit_row[GFS2_MODE] = 10; /* Start off at root inode
    2419              :                                      pointer in superblock */
    2420         4473 :         termlines = 30;  /* assume interactive mode until we find -p */
    2421         4473 :         process_parameters(argc, argv, 0);
    2422         4467 :         if (dmode == INIT_MODE)
    2423            9 :                 dmode = HEX_MODE;
    2424              : 
    2425         4467 :         fd = open(device, O_RDWR);
    2426         4467 :         if (fd < 0) {
    2427            1 :                 fprintf(stderr, "Failed to open '%s': %s\n", device, strerror(errno));
    2428            1 :                 exit(1);
    2429              :         }
    2430         4466 :         max_block = lseek(fd, 0, SEEK_END) / sbd.sd_bsize;
    2431              : 
    2432         4466 :         read_superblock(fd);
    2433         4466 :         if (read_rindex())
    2434            0 :                 exit(-1);
    2435         4466 :         max_block = lseek(fd, 0, SEEK_END) / sbd.sd_bsize;
    2436         4466 :         if (read_master_dir() != 0)
    2437            0 :                 exit(-1);
    2438              : 
    2439         4466 :         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 2.0-1