LCOV - code coverage report
Current view: top level - edit - gfs2hex.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 98 164 59.8 %
Date: 2023-09-27 13:48:55 Functions: 6 8 75.0 %

          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       35779 : void idirent_in(struct idirent *id, void *dep)
     101             : {
     102       35779 :         struct gfs2_dirent *de = dep;
     103             : 
     104       35779 :         lgfs2_inum_in(&id->inum, &de->de_inum);
     105       35779 :         id->hash = be32_to_cpu(de->de_hash);
     106       35779 :         id->rec_len = be16_to_cpu(de->de_rec_len);
     107       35779 :         id->name_len = be16_to_cpu(de->de_name_len);
     108       35779 :         id->type = be16_to_cpu(de->de_type);
     109       35779 :         id->rahead = be16_to_cpu(de->de_rahead);
     110       35779 :         memcpy(id->filename, (char *)de + sizeof(*de), id->name_len);
     111       35779 :         id->filename[id->name_len] = '\0';
     112       35779 : }
     113             : 
     114       35779 : static int indirect_dirent(struct indirect_info *indir, void *ptr, int d)
     115             : {
     116       35779 :         struct gfs2_dirent *de = ptr;
     117       35779 :         int ret = 0;
     118             : 
     119       71558 :         if (be16_to_cpu(de->de_rec_len) < sizeof(struct gfs2_dirent) ||
     120       35779 :             be16_to_cpu(de->de_rec_len) > 4096 - sizeof(struct gfs2_dirent))
     121           0 :                 return -1;
     122       35779 :         if (de->de_inum.no_addr) {
     123       35779 :                 idirent_in(&indir->dirent[d], ptr);
     124       35779 :                 indir->block = be64_to_cpu(de->de_inum.no_addr);
     125       35779 :                 indir->is_dir = TRUE;
     126       35779 :                 indir->dirents++;
     127       35779 :                 ret = indir->dirent[d].rec_len;
     128             :         }
     129       35779 :         return ret;
     130             : }
     131             : 
     132        4481 : void do_dinode_extended(char *buf)
     133             : {
     134        4481 :         struct gfs2_dinode *dip = (void *)buf;
     135        4481 :         unsigned int x, y, ptroff = 0;
     136             :         uint64_t p, last;
     137        4481 :         int isdir = S_ISDIR(be32_to_cpu(dip->di_mode));
     138             : 
     139        4481 :         indirect_blocks = 0;
     140        4481 :         memset(indirect, 0, sizeof(struct iinfo));
     141        4481 :         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        8947 :         else if (isdir && !(be32_to_cpu(dip->di_flags) & GFS2_DIF_EXHASH)) {
     159        4471 :                 int skip = 0;
     160             : 
     161             :                 /* Directory Entries: */
     162        4471 :                 indirect->ii[0].dirents = 0;
     163        4471 :                 indirect->ii[0].block = block;
     164        4471 :                 indirect->ii[0].is_dir = TRUE;
     165       40220 :                 for (x = sizeof(struct gfs2_dinode); x < sbd.sd_bsize; x += skip) {
     166       35749 :                         skip = indirect_dirent(indirect->ii, buf + x,
     167       35749 :                                                indirect->ii[0].dirents);
     168       35749 :                         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        4481 : }/* 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             :         struct gfs2_ea_header *ea;
     240           0 :         uint32_t rec_len = 0;
     241             :         unsigned int x;
     242             : 
     243           0 :         eol(0);
     244           0 :         print_gfs2("Eattr Entries:");
     245           0 :         eol(0);
     246             : 
     247           0 :         for (x = sizeof(struct gfs2_meta_header); x < sbd.sd_bsize; x += rec_len)
     248             :         {
     249           0 :                 eol(0);
     250           0 :                 buf += x;
     251           0 :                 ea = (struct gfs2_ea_header *)buf;
     252           0 :                 ea_header_print(ea);
     253           0 :                 rec_len = be32_to_cpu(ea->ea_rec_len);
     254             :         }
     255           0 : }
     256             : 
     257           7 : void display_gfs2(void *buf)
     258             : {
     259           7 :         struct gfs2_meta_header *mh = buf;
     260             :         uint32_t magic;
     261             :         uint32_t type;
     262             : 
     263           7 :         magic = be32_to_cpu(mh->mh_magic);
     264           7 :         type = be32_to_cpu(mh->mh_type);
     265             : 
     266           7 :         if (magic != GFS2_MAGIC) {
     267           0 :                 print_gfs2("Unknown block type");
     268           0 :                 eol(0);
     269           0 :                 return;
     270             :         }
     271             : 
     272           7 :         if (type <= GFS2_METATYPE_QC)
     273           7 :                 print_gfs2("%s:", block_type_str[type]);
     274           7 :         eol(0);
     275             : 
     276           7 :         switch (type)
     277             :         {
     278           0 :         case GFS2_METATYPE_SB:
     279           0 :                 sb_print(buf);
     280           0 :                 break;
     281           0 :         case GFS2_METATYPE_RG:
     282           0 :                 rgrp_print(buf);
     283           0 :                 break;
     284           7 :         case GFS2_METATYPE_DI:
     285           7 :                 dinode_print(di);
     286           7 :                 break;
     287           0 :         case GFS2_METATYPE_LF:
     288           0 :                 leaf_print(buf);
     289           0 :                 break;
     290           0 :         case GFS2_METATYPE_LH:
     291           0 :                 log_header_print(buf);
     292           0 :                 break;
     293           0 :         case GFS2_METATYPE_LD:
     294           0 :                 log_descriptor_print(buf);
     295           0 :                 break;
     296           0 :         case GFS2_METATYPE_EA:
     297           0 :                 do_eattr_extended(buf);
     298           0 :                 break;
     299           0 :         case GFS2_METATYPE_QC:
     300           0 :                 quota_change_print(buf);
     301           0 :                 break;
     302           0 :         case GFS2_METATYPE_RB:
     303             :         case GFS2_METATYPE_IN:
     304             :         case GFS2_METATYPE_JD:
     305             :         case GFS2_METATYPE_ED:
     306             :         case GFS2_METATYPE_LB:
     307           0 :                 meta_header_print(mh);
     308           0 :                 break;
     309           0 :         default:
     310           0 :                 print_gfs2("Unknown block type");
     311           0 :                 eol(0);
     312           0 :                 break;
     313             :         }
     314             : }

Generated by: LCOV version 1.14