LCOV - code coverage report
Current view: top level - edit - gfs2hex.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 59.0 % 166 98
Test Date: 2024-03-07 16:24:06 Functions: 75.0 % 8 6

            Line data    Source code
       1              : #include "clusterautoconfig.h"
       2              : 
       3              : #include <stdio.h>
       4              : #include <stdlib.h>
       5              : #include <string.h>
       6              : #include <inttypes.h>
       7              : #include <sys/types.h>
       8              : #include <sys/stat.h>
       9              : #include <fcntl.h>
      10              : #include <unistd.h>
      11              : #include <errno.h>
      12              : #include <curses.h>
      13              : #include <uuid.h>
      14              : #include <libgfs2.h>
      15              : 
      16              : #include "hexedit.h"
      17              : #include "extended.h"
      18              : #include "gfs2hex.h"
      19              : #include "struct_print.h"
      20              : 
      21              : struct gfs2_dinode *di;
      22              : int line, termlines;
      23              : char edit_fmt[80];
      24              : char estring[1024];
      25              : char efield[64];
      26              : int edit_mode = 0;
      27              : int edit_row[DMODES], edit_col[DMODES];
      28              : int edit_size[DMODES], last_entry_onscreen[DMODES];
      29              : enum dsp_mode dmode = HEX_MODE; /* display mode */
      30              : uint64_t block = 0;
      31              : int blockhist = 0;
      32              : struct iinfo *indirect;
      33              : int indirect_blocks;
      34              : struct lgfs2_sbd sbd;
      35              : uint64_t starting_blk;
      36              : struct blkstack_info blockstack[BLOCK_STACK_SIZE];
      37              : int identify = FALSE;
      38              : uint64_t max_block = 0;
      39              : int start_row[DMODES], end_row[DMODES], lines_per_row[DMODES];
      40              : int gfs2_struct_type;
      41              : unsigned int offset;
      42              : struct indirect_info masterdir;
      43              : int print_entry_ndx;
      44              : int screen_chunk_size = 512;
      45              : uint64_t temp_blk;
      46              : int color_scheme = 0;
      47              : int struct_len;
      48              : uint64_t dev_offset = 0;
      49              : int editing = 0;
      50              : int insert = 0;
      51              : const char *termtype;
      52              : WINDOW *wind;
      53              : int dsplines = 0;
      54              : 
      55              : static const char *block_type_str[15] = {
      56              :         "Clump",
      57              :         "Superblock",
      58              :         "Resource Group Header",
      59              :         "Resource Group Bitmap",
      60              :         "Dinode",
      61              :         "Indirect Block",
      62              :         "Leaf",
      63              :         "Journaled Data",
      64              :         "Log Header",
      65              :         "Log descriptor",
      66              :         "Ext. attrib",
      67              :         "Eattr Data",
      68              :         "Log Buffer",
      69              :         "Metatype 13",
      70              :         "Quota Change",
      71              : };
      72              : 
      73        63680 : void eol(int col) /* end of line */
      74              : {
      75        63680 :         if (termlines) {
      76            0 :                 line++;
      77            0 :                 move(line, col);
      78              :         } else {
      79        63680 :                 printf("\n");
      80        63680 :                 for (; col > 0; col--)
      81            0 :                         printf(" ");
      82              :         }
      83        63680 : }
      84              : 
      85         9896 : void print_gfs2(const char *fmt, ...)
      86              : {
      87              :         va_list args;
      88              :         char string[PATH_MAX];
      89              :         
      90         9896 :         memset(string, 0, sizeof(string));
      91         9896 :         va_start(args, fmt);
      92         9896 :         vsprintf(string, fmt, args);
      93         9896 :         if (termlines)
      94            0 :                 printw("%s", string);
      95              :         else
      96         9896 :                 printf("%s", string);
      97         9896 :         va_end(args);
      98         9896 : }
      99              : 
     100        35792 : void idirent_in(struct idirent *id, void *dep)
     101              : {
     102        35792 :         struct gfs2_dirent *de = dep;
     103              : 
     104        35792 :         lgfs2_inum_in(&id->inum, &de->de_inum);
     105        35792 :         id->hash = be32_to_cpu(de->de_hash);
     106        35792 :         id->rec_len = be16_to_cpu(de->de_rec_len);
     107        35792 :         id->name_len = be16_to_cpu(de->de_name_len);
     108        35792 :         id->type = be16_to_cpu(de->de_type);
     109        35792 :         id->rahead = be16_to_cpu(de->de_rahead);
     110        35792 :         memcpy(id->filename, (char *)de + sizeof(*de), id->name_len);
     111        35792 :         id->filename[id->name_len] = '\0';
     112        35792 : }
     113              : 
     114        35792 : static int indirect_dirent(struct indirect_info *indir, void *ptr, int d)
     115              : {
     116        35792 :         struct gfs2_dirent *de = ptr;
     117        35792 :         int ret = 0;
     118              : 
     119        71584 :         if (be16_to_cpu(de->de_rec_len) < sizeof(struct gfs2_dirent) ||
     120        35792 :             be16_to_cpu(de->de_rec_len) > 4096 - sizeof(struct gfs2_dirent))
     121            0 :                 return -1;
     122        35792 :         if (de->de_inum.no_addr) {
     123        35792 :                 idirent_in(&indir->dirent[d], ptr);
     124        35792 :                 indir->block = be64_to_cpu(de->de_inum.no_addr);
     125        35792 :                 indir->is_dir = TRUE;
     126        35792 :                 indir->dirents++;
     127        35792 :                 ret = indir->dirent[d].rec_len;
     128              :         }
     129        35792 :         return ret;
     130              : }
     131              : 
     132         4483 : void do_dinode_extended(char *buf)
     133              : {
     134         4483 :         struct gfs2_dinode *dip = (void *)buf;
     135         4483 :         unsigned int x, y, ptroff = 0;
     136              :         uint64_t p, last;
     137         4483 :         int isdir = S_ISDIR(be32_to_cpu(dip->di_mode));
     138              : 
     139         4483 :         indirect_blocks = 0;
     140         4483 :         memset(indirect, 0, sizeof(struct iinfo));
     141         4483 :         if (be16_to_cpu(dip->di_height) > 0) {
     142              :                 /* Indirect pointers */
     143         2420 :                 for (x = sizeof(struct gfs2_dinode); x < sbd.sd_bsize;
     144         2415 :                          x += sizeof(uint64_t)) {
     145         2415 :                         p = be64_to_cpu(*(__be64 *)(buf + x));
     146         2415 :                         if (p) {
     147           23 :                                 indirect->ii[indirect_blocks].block = p;
     148           23 :                                 indirect->ii[indirect_blocks].mp.mp_list[0] =
     149              :                                         ptroff;
     150           23 :                                 indirect->ii[indirect_blocks].is_dir = FALSE;
     151           23 :                                 indirect->ii[indirect_blocks].ptroff =
     152           23 :                                               (x - sizeof(*dip)) / sizeof(uint64_t);
     153           23 :                                 indirect_blocks++;
     154              :                         }
     155         2415 :                         ptroff++;
     156              :                 }
     157              :         }
     158         8951 :         else if (isdir && !(be32_to_cpu(dip->di_flags) & GFS2_DIF_EXHASH)) {
     159         4473 :                 int skip = 0;
     160              : 
     161              :                 /* Directory Entries: */
     162         4473 :                 indirect->ii[0].dirents = 0;
     163         4473 :                 indirect->ii[0].block = block;
     164         4473 :                 indirect->ii[0].is_dir = TRUE;
     165        40235 :                 for (x = sizeof(struct gfs2_dinode); x < sbd.sd_bsize; x += skip) {
     166        35762 :                         skip = indirect_dirent(indirect->ii, buf + x,
     167        35762 :                                                indirect->ii[0].dirents);
     168        35762 :                         if (skip <= 0)
     169            0 :                                 break;
     170              :                 }
     171              :         }
     172            5 :         else if (isdir && (be32_to_cpu(dip->di_flags) & GFS2_DIF_EXHASH) &&
     173            3 :                  dip->di_height == 0) {
     174              :                 /* Leaf Pointers: */
     175              : 
     176            3 :                 last = be64_to_cpu(*(__be64 *)(buf + sizeof(struct gfs2_dinode)));
     177              : 
     178            3 :                 for (x = sizeof(struct gfs2_dinode), y = 0;
     179           99 :                          y < (1 << be16_to_cpu(dip->di_depth));
     180           96 :                          x += sizeof(uint64_t), y++) {
     181           96 :                         p = be64_to_cpu(*(__be64 *)(buf + x));
     182              : 
     183           96 :                         if (p != last || ((y + 1) * sizeof(uint64_t) == be64_to_cpu(dip->di_size))) {
     184              :                                 struct lgfs2_buffer_head *tmp_bh;
     185            5 :                                 int skip = 0, direntcount = 0;
     186              :                                 unsigned int bufoffset;
     187              : 
     188            5 :                                 if (last >= max_block)
     189            0 :                                         break;
     190            5 :                                 tmp_bh = lgfs2_bread(&sbd, last);
     191            5 :                                 indirect->ii[indirect_blocks].dirents = 0;
     192            5 :                                 for (direntcount = 0, bufoffset = sizeof(struct gfs2_leaf);
     193           35 :                                          bufoffset < sbd.sd_bsize;
     194           30 :                                          direntcount++, bufoffset += skip) {
     195           30 :                                         skip = indirect_dirent(&indirect->ii[indirect_blocks],
     196           30 :                                                                                    tmp_bh->b_data + bufoffset,
     197              :                                                                                    direntcount);
     198           30 :                                         if (skip <= 0)
     199            0 :                                                 break;
     200              :                                 }
     201            5 :                                 lgfs2_brelse(tmp_bh);
     202            5 :                                 indirect->ii[indirect_blocks].block = last;
     203            5 :                                 indirect_blocks++;
     204            5 :                                 last = p;
     205              :                         } /* if not duplicate pointer */
     206              :                 } /* for indirect pointers found */
     207              :         } /* if exhash */
     208         4483 : }/* do_dinode_extended */
     209              : 
     210              : /**
     211              :  * Returns: next leaf block, if any, in a chain of leaf blocks
     212              :  */
     213            0 : uint64_t do_leaf_extended(char *dlebuf, struct iinfo *indir)
     214              : {
     215              :         int x, i;
     216              :         struct gfs2_dirent *de;
     217              : 
     218            0 :         x = 0;
     219            0 :         memset(indir, 0, sizeof(*indir));
     220            0 :         memcpy(&indir->ii[0].lf, dlebuf, sizeof(struct gfs2_leaf));
     221              :         /* Directory Entries: */
     222            0 :         for (i = sizeof(struct gfs2_leaf); i < sbd.sd_bsize; i += be16_to_cpu(de->de_rec_len)) {
     223            0 :                 de = (struct gfs2_dirent *)(dlebuf + i);
     224            0 :                 if (de->de_inum.no_addr) {
     225            0 :                         idirent_in(&indir->ii[0].dirent[x], de);
     226            0 :                         indir->ii[0].block = be64_to_cpu(de->de_inum.no_addr);
     227            0 :                         indir->ii[0].is_dir = TRUE;
     228            0 :                         indir->ii[0].dirents++;
     229            0 :                         x++;
     230              :                 }
     231            0 :                 if (be16_to_cpu(de->de_rec_len) <= sizeof(struct gfs2_dirent))
     232            0 :                         break;
     233              :         }
     234            0 :         return be64_to_cpu(indir->ii[0].lf.lf_next);
     235              : }
     236              : 
     237            0 : static void do_eattr_extended(char *buf)
     238              : {
     239            0 :         uint64_t x = sizeof(struct gfs2_meta_header);
     240              : 
     241            0 :         eol(0);
     242            0 :         print_gfs2("Eattr Entries:");
     243            0 :         eol(0);
     244              : 
     245            0 :         while (x < sbd.sd_bsize - sizeof(struct gfs2_ea_header)) {
     246              :                 struct gfs2_ea_header *ea;
     247              : 
     248            0 :                 ea = (struct gfs2_ea_header *)(buf + x);
     249            0 :                 print_gfs2("0x%"PRIx64":", x);
     250            0 :                 eol(0);
     251            0 :                 ea_header_print(ea, sbd.sd_bsize - x);
     252            0 :                 if (ea->ea_flags & GFS2_EAFLAG_LAST)
     253            0 :                         break;
     254            0 :                 x += be32_to_cpu(ea->ea_rec_len);
     255              :         }
     256            0 : }
     257              : 
     258            7 : void display_gfs2(void *buf)
     259              : {
     260            7 :         struct gfs2_meta_header *mh = buf;
     261              :         uint32_t magic;
     262              :         uint32_t type;
     263              : 
     264            7 :         magic = be32_to_cpu(mh->mh_magic);
     265            7 :         type = be32_to_cpu(mh->mh_type);
     266              : 
     267            7 :         if (magic != GFS2_MAGIC) {
     268            0 :                 print_gfs2("Unknown block type");
     269            0 :                 eol(0);
     270            0 :                 return;
     271              :         }
     272              : 
     273            7 :         if (type <= GFS2_METATYPE_QC)
     274            7 :                 print_gfs2("%s:", block_type_str[type]);
     275            7 :         eol(0);
     276              : 
     277            7 :         switch (type)
     278              :         {
     279            0 :         case GFS2_METATYPE_SB:
     280            0 :                 sb_print(buf);
     281            0 :                 break;
     282            0 :         case GFS2_METATYPE_RG:
     283            0 :                 rgrp_print(buf);
     284            0 :                 break;
     285            7 :         case GFS2_METATYPE_DI:
     286            7 :                 dinode_print(di);
     287            7 :                 break;
     288            0 :         case GFS2_METATYPE_LF:
     289            0 :                 leaf_print(buf);
     290            0 :                 break;
     291            0 :         case GFS2_METATYPE_LH:
     292            0 :                 log_header_print(buf);
     293            0 :                 break;
     294            0 :         case GFS2_METATYPE_LD:
     295            0 :                 log_descriptor_print(buf);
     296            0 :                 break;
     297            0 :         case GFS2_METATYPE_EA:
     298            0 :                 do_eattr_extended(buf);
     299            0 :                 break;
     300            0 :         case GFS2_METATYPE_QC:
     301            0 :                 quota_change_print(buf);
     302            0 :                 break;
     303            0 :         case GFS2_METATYPE_RB:
     304              :         case GFS2_METATYPE_IN:
     305              :         case GFS2_METATYPE_JD:
     306              :         case GFS2_METATYPE_ED:
     307              :         case GFS2_METATYPE_LB:
     308            0 :                 meta_header_print(mh);
     309            0 :                 break;
     310            0 :         default:
     311            0 :                 print_gfs2("Unknown block type");
     312            0 :                 eol(0);
     313            0 :                 break;
     314              :         }
     315              : }
        

Generated by: LCOV version 2.0-1