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 : }
|