LCOV - code coverage report
Current view: top level - edit - hexedit.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 380 1558 24.4 %
Date: 2023-09-27 13:48:55 Functions: 24 52 46.2 %

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

Generated by: LCOV version 1.14