]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - db/io.c
xfsprogs: Release v6.15.0
[thirdparty/xfsprogs-dev.git] / db / io.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18 8#include "command.h"
2bd0ea18
NS
9#include "type.h"
10#include "faddr.h"
11#include "fprint.h"
12#include "field.h"
1e9c13c5 13#include "dquot.h"
2bd0ea18
NS
14#include "inode.h"
15#include "io.h"
16#include "output.h"
4ca431fc 17#include "init.h"
2bd0ea18 18#include "malloc.h"
b64af2c4 19#include "crc.h"
55f224ba 20#include "bit.h"
2bd0ea18
NS
21
22static int pop_f(int argc, char **argv);
23static void pop_help(void);
24static int push_f(int argc, char **argv);
25static void push_help(void);
26static int stack_f(int argc, char **argv);
27static void stack_help(void);
28static int forward_f(int argc, char **argv);
29static void forward_help(void);
30static int back_f(int argc, char **argv);
31static void back_help(void);
32static int ring_f(int argc, char **argv);
33static void ring_help(void);
34
35static const cmdinfo_t pop_cmd =
36 { "pop", NULL, pop_f, 0, 0, 0, NULL,
9ee7055c 37 N_("pop location from the stack"), pop_help };
2bd0ea18 38static const cmdinfo_t push_cmd =
9ee7055c
AM
39 { "push", NULL, push_f, 0, 2, 0, N_("[command]"),
40 N_("push location to the stack"), push_help };
2bd0ea18
NS
41static const cmdinfo_t stack_cmd =
42 { "stack", NULL, stack_f, 0, 0, 0, NULL,
9ee7055c 43 N_("view the location stack"), stack_help };
dfc130f3 44static const cmdinfo_t forward_cmd =
2bd0ea18 45 { "forward", "f", forward_f, 0, 0, 0, NULL,
9ee7055c 46 N_("move forward to next entry in the position ring"), forward_help };
dfc130f3 47static const cmdinfo_t back_cmd =
2bd0ea18 48 { "back", "b", back_f, 0, 0, 0, NULL,
9ee7055c 49 N_("move to the previous location in the position ring"), back_help };
dfc130f3 50static const cmdinfo_t ring_cmd =
2bd0ea18 51 { "ring", NULL, ring_f, 0, 1, 0, NULL,
9ee7055c 52 N_("show position ring or move to a specific entry"), ring_help };
2bd0ea18
NS
53
54iocur_t *iocur_base;
55iocur_t *iocur_top;
56int iocur_sp = -1;
57int iocur_len;
58
59#define RING_ENTRIES 20
60static iocur_t iocur_ring[RING_ENTRIES];
61static int ring_head = -1;
62static int ring_tail = -1;
63static int ring_current = -1;
64
65void
66io_init(void)
67{
68 add_command(&pop_cmd);
69 add_command(&push_cmd);
70 add_command(&stack_cmd);
71 add_command(&forward_cmd);
72 add_command(&back_cmd);
73 add_command(&ring_cmd);
74}
75
0d376f6c
AA
76static inline void set_cur_boff(int off)
77{
78 iocur_top->boff = off;
79 iocur_top->off = ((xfs_off_t)iocur_top->bb << BBSHIFT) + off;
80 iocur_top->data = (void *)((char *)iocur_top->buf + off);
81}
82
2bd0ea18
NS
83void
84off_cur(
85 int off,
86 int len)
87{
88 if (iocur_top == NULL || off + len > BBTOB(iocur_top->blen))
9ee7055c 89 dbprintf(_("can't set block offset to %d\n"), off);
2bd0ea18 90 else {
0d376f6c 91 set_cur_boff(off);
2bd0ea18 92 iocur_top->len = len;
2bd0ea18
NS
93 }
94}
95
96void
97pop_cur(void)
98{
99 if (iocur_sp < 0) {
9ee7055c 100 dbprintf(_("can't pop anything from I/O stack\n"));
2bd0ea18
NS
101 return;
102 }
72298d16 103 if (iocur_top->bp) {
e02ba985 104 libxfs_buf_relse(iocur_top->bp);
72298d16
DC
105 iocur_top->bp = NULL;
106 }
107 if (iocur_top->bbmap) {
108 free(iocur_top->bbmap);
109 iocur_top->bbmap = NULL;
110 }
2bd0ea18
NS
111 if (--iocur_sp >= 0) {
112 iocur_top = iocur_base + iocur_sp;
113 cur_typ = iocur_top->typ;
114 } else {
115 iocur_top = iocur_base;
116 iocur_sp = 0;
117 }
118}
119
120/*ARGSUSED*/
121static int
122pop_f(
123 int argc,
124 char **argv)
125{
126 pop_cur();
127 return 0;
128}
129
130static void
131pop_help(void)
132{
9ee7055c 133 dbprintf(_(
2bd0ea18
NS
134"\n"
135" Changes the address and data type to the first entry on the stack.\n"
136"\n"
9ee7055c 137 ));
2bd0ea18
NS
138}
139
1665923a
DW
140bool
141iocur_is_ddev(const struct iocur *ioc)
142{
143 if (!ioc->bp)
144 return false;
145
146 return ioc->bp->b_target == ioc->bp->b_mount->m_ddev_targp;
147}
148
149bool
150iocur_is_extlogdev(const struct iocur *ioc)
151{
152 struct xfs_buf *bp = ioc->bp;
153
154 if (!bp)
155 return false;
156 if (bp->b_mount->m_logdev_targp == bp->b_mount->m_ddev_targp)
157 return false;
158
159 return bp->b_target == bp->b_mount->m_logdev_targp;
160}
161
49844913
DW
162bool
163iocur_is_rtdev(const struct iocur *ioc)
164{
165 if (!ioc->bp)
166 return false;
167
168 return ioc->bp->b_target == ioc->bp->b_mount->m_rtdev_targp;
169}
170
2bd0ea18
NS
171void
172print_iocur(
173 char *tag,
174 iocur_t *ioc)
175{
1665923a 176 const char *block_unit = "fsbno?";
2bd0ea18
NS
177 int i;
178
1665923a
DW
179 if (iocur_is_ddev(ioc))
180 block_unit = "fsbno";
181 else if (iocur_is_extlogdev(ioc))
182 block_unit = "logbno";
49844913
DW
183 else if (iocur_is_rtdev(ioc))
184 block_unit = "rtbno";
1665923a 185
2bd0ea18 186 dbprintf("%s\n", tag);
9ee7055c 187 dbprintf(_("\tbyte offset %lld, length %d\n"), ioc->off, ioc->len);
1665923a
DW
188 dbprintf(_("\tbuffer block %lld (%s %lld), %d bb%s\n"), ioc->bb,
189 block_unit,
190 (xfs_fsblock_t)XFS_DADDR_TO_FSB(mp, ioc->bb),
191 ioc->blen, ioc->blen == 1 ? "" : "s");
72298d16 192 if (ioc->bbmap) {
9ee7055c 193 dbprintf(_("\tblock map"));
72298d16
DC
194 for (i = 0; i < ioc->bbmap->nmaps; i++)
195 dbprintf(" %lld:%d", ioc->bbmap->b[i].bm_bn,
196 ioc->bbmap->b[i].bm_len);
2bd0ea18
NS
197 dbprintf("\n");
198 }
9ee7055c
AM
199 dbprintf(_("\tinode %lld, dir inode %lld, type %s\n"), ioc->ino,
200 ioc->dirino, ioc->typ == NULL ? _("none") : ioc->typ->name);
2bd0ea18
NS
201}
202
00ff2b10 203static void
2bd0ea18
NS
204print_ring(void)
205{
206 int i;
207 iocur_t *ioc;
208
209 if (ring_current == -1) {
9ee7055c 210 dbprintf(_("no entries in location ring.\n"));
2bd0ea18
NS
211 return;
212 }
213
9ee7055c 214 dbprintf(_(" type bblock bblen fsbno inode\n"));
2bd0ea18
NS
215
216 i = ring_head;
217 for (;;) {
218 ioc = &iocur_ring[i];
219 if (i == ring_current)
220 printf("*%2d: ", i);
221 else
222 printf(" %2d: ", i);
223
224 dbprintf("%-7.7s %8lld %5d %8lld %9lld\n",
225 ioc->typ == NULL ? "none" : ioc->typ->name,
226 ioc->bb,
227 ioc->blen,
5a35bf2c 228 (xfs_fsblock_t)XFS_DADDR_TO_FSB(mp, ioc->bb),
2bd0ea18
NS
229 ioc->ino
230 );
231
232 if (i == ring_tail)
233 break;
234
235 i = (i+(RING_ENTRIES-1))%RING_ENTRIES;
236 }
237}
238
239
240void
241push_cur(void)
242{
243 if (iocur_sp + 1 >= iocur_len) {
244 iocur_base = xrealloc(iocur_base,
245 sizeof(*iocur_base) * (iocur_len + 1));
246 iocur_len++;
247 }
248 iocur_sp++;
249 iocur_top = iocur_base + iocur_sp;
250 memset(iocur_top, 0, sizeof(*iocur_base));
251 iocur_top->ino = iocur_sp > 0 ? iocur_top[-1].ino : NULLFSINO;
252 iocur_top->dirino = iocur_sp > 0 ? iocur_top[-1].dirino : NULLFSINO;
253 iocur_top->mode = iocur_sp > 0 ? iocur_top[-1].mode : 0;
254 cur_typ = NULL;
255}
256
3540b418
DW
257void
258push_cur_and_set_type(void)
259{
260 /* save current state */
261 push_cur();
262 if (iocur_top[-1].typ && iocur_top[-1].typ->typnm == TYP_INODE)
263 set_cur_inode(iocur_top[-1].ino);
264 else
265 set_cur(iocur_top[-1].typ, iocur_top[-1].bb,
266 iocur_top[-1].blen, DB_RING_IGN,
267 iocur_top[-1].bbmap);
268}
269
2bd0ea18
NS
270static int
271push_f(
272 int argc,
273 char **argv)
274{
275 const cmdinfo_t *ct;
276
277 if (argc > 1) {
dfc130f3
RC
278 /* check we can execute command */
279 ct = find_command(argv[1]);
280 if (ct == NULL) {
9ee7055c 281 dbprintf(_("no such command %s\n"), argv[1]);
dfc130f3
RC
282 return 0;
283 }
284 if (!ct->canpush) {
9ee7055c 285 dbprintf(_("no push form allowed for %s\n"), argv[1]);
dfc130f3
RC
286 return 0;
287 }
288 }
289
3540b418 290 push_cur_and_set_type();
2bd0ea18 291
dfc130f3
RC
292 /* run requested command */
293 if (argc>1)
294 (void)command(argc-1, argv+1);
2bd0ea18
NS
295 return 0;
296}
297
298static void
299push_help(void)
300{
9ee7055c 301 dbprintf(_(
2bd0ea18
NS
302"\n"
303" Allows you to push the current address and data type on the stack for\n"
304" later return. 'push' also accepts an additional command to execute after\n"
305" storing the current address (ex: 'push a rootino' from the superblock).\n"
306"\n"
9ee7055c 307 ));
2bd0ea18
NS
308}
309
310/* move forward through the ring */
311/* ARGSUSED */
312static int
313forward_f(
314 int argc,
315 char **argv)
316{
317 if (ring_current == -1) {
9ee7055c 318 dbprintf(_("ring is empty\n"));
2bd0ea18
NS
319 return 0;
320 }
321 if (ring_current == ring_head) {
9ee7055c 322 dbprintf(_("no further entries\n"));
2bd0ea18
NS
323 return 0;
324 }
325
326 ring_current = (ring_current+1)%RING_ENTRIES;
327
328 set_cur(iocur_ring[ring_current].typ,
329 iocur_ring[ring_current].bb,
330 iocur_ring[ring_current].blen,
331 DB_RING_IGN,
72298d16 332 iocur_ring[ring_current].bbmap);
2bd0ea18
NS
333
334 return 0;
335}
336
337static void
338forward_help(void)
339{
9ee7055c 340 dbprintf(_(
2bd0ea18
NS
341"\n"
342" The 'forward' ('f') command moves to the next location in the position\n"
343" ring, updating the current position and data type. If the current location\n"
344" is the top entry in the ring, then the 'forward' command will have\n"
345" no effect.\n"
346"\n"
9ee7055c 347 ));
2bd0ea18
NS
348}
349
350/* move backwards through the ring */
351/* ARGSUSED */
352static int
353back_f(
354 int argc,
355 char **argv)
356{
357 if (ring_current == -1) {
9ee7055c 358 dbprintf(_("ring is empty\n"));
2bd0ea18
NS
359 return 0;
360 }
361 if (ring_current == ring_tail) {
9ee7055c 362 dbprintf(_("no previous entries\n"));
2bd0ea18
NS
363 return 0;
364 }
365
366 ring_current = (ring_current+(RING_ENTRIES-1))%RING_ENTRIES;
367
368 set_cur(iocur_ring[ring_current].typ,
369 iocur_ring[ring_current].bb,
370 iocur_ring[ring_current].blen,
371 DB_RING_IGN,
72298d16 372 iocur_ring[ring_current].bbmap);
2bd0ea18
NS
373
374 return 0;
375}
376
377static void
378back_help(void)
379{
9ee7055c 380 dbprintf(_(
2bd0ea18
NS
381"\n"
382" The 'back' ('b') command moves to the previous location in the position\n"
383" ring, updating the current position and data type. If the current location\n"
384" is the last entry in the ring, then the 'back' command will have no effect.\n"
385"\n"
9ee7055c 386 ));
2bd0ea18
NS
387}
388
389/* show or go to specific point in ring */
390static int
391ring_f(
392 int argc,
393 char **argv)
394{
395 int index;
396
397 if (argc == 1) {
398 print_ring();
399 return 0;
400 }
401
b3d6b800 402 index = (int)strtoul(argv[1], NULL, 0);
d15f7cfb 403 if (index < 0 || index >= RING_ENTRIES) {
9ee7055c 404 dbprintf(_("invalid entry: %d\n"), index);
d15f7cfb
ES
405 return 0;
406 }
2bd0ea18
NS
407
408 ring_current = index;
409
410 set_cur(iocur_ring[index].typ,
411 iocur_ring[index].bb,
412 iocur_ring[index].blen,
413 DB_RING_IGN,
72298d16 414 iocur_ring[index].bbmap);
2bd0ea18
NS
415
416 return 0;
417}
418
419static void
420ring_help(void)
421{
9ee7055c 422 dbprintf(_(
2bd0ea18
NS
423"\n"
424" The position ring automatically keeps track of each disk location and\n"
425" structure type for each change of position you make during your xfs_db\n"
426" session. The last %d most recent entries are kept in the ring.\n"
427"\n"
428" To display the current list of ring entries type 'ring' by itself on\n"
429" the command line. The entry highlighted by an asterisk ('*') is the\n"
430" current entry.\n"
431"\n"
432" To move to another entry in the ring type 'ring <num>' where <num> is\n"
433" your desired entry from the ring position list.\n"
434"\n"
435" You may also use the 'forward' ('f') or 'back' ('b') commands to move\n"
436" to the previous or next entry in the ring, respectively.\n"
437"\n"
438" Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n"
439" location implicitly. Use the 'push' and 'pop' commands if you wish to\n"
440" store a specific location explicitly for later return.\n"
9ee7055c 441"\n"),
2bd0ea18
NS
442 RING_ENTRIES);
443}
444
445
446void
447ring_add(void)
448{
449 if (ring_head == -1) {
450 /* only get here right after startup */
451 ring_head = 0;
452 ring_tail = 0;
453 ring_current = 0;
454 iocur_ring[0] = *iocur_top;
455 } else {
456 if (ring_current == ring_head) {
457 ring_head = (ring_head+1)%RING_ENTRIES;
458 iocur_ring[ring_head] = *iocur_top;
459 if (ring_head == ring_tail)
460 ring_tail = (ring_tail+1)%RING_ENTRIES;
461 ring_current = ring_head;
462 } else {
463 ring_current = (ring_current+1)%RING_ENTRIES;
464 iocur_ring[ring_current] = *iocur_top;
465 }
466 }
467}
468
2a8b3fdf
DC
469static void
470write_cur_buf(void)
471{
e84718ec 472 struct xfs_buftarg *btp = iocur_top->bp->b_target;
2a8b3fdf
DC
473 int ret;
474
331d5956 475 ret = -libxfs_bwrite(iocur_top->bp);
72298d16 476 if (ret != 0)
2a8b3fdf
DC
477 dbprintf(_("write error: %s\n"), strerror(ret));
478
479 /* re-read buffer from disk */
e84718ec 480 ret = -libxfs_readbufr(btp, iocur_top->bb, iocur_top->bp,
72298d16
DC
481 iocur_top->blen, 0);
482 if (ret != 0)
2a8b3fdf
DC
483 dbprintf(_("read error: %s\n"), strerror(ret));
484}
485
2a8b3fdf
DC
486static void
487write_cur_bbs(void)
2bd0ea18 488{
e84718ec 489 struct xfs_buftarg *btp = iocur_top->bp->b_target;
2bd0ea18
NS
490 int ret;
491
331d5956 492 ret = -libxfs_bwrite(iocur_top->bp);
72298d16 493 if (ret != 0)
9ee7055c 494 dbprintf(_("write error: %s\n"), strerror(ret));
2a8b3fdf 495
72298d16 496
2bd0ea18 497 /* re-read buffer from disk */
e84718ec 498 ret = -libxfs_readbufr_map(btp, iocur_top->bp, 0);
72298d16 499 if (ret != 0)
9ee7055c 500 dbprintf(_("read error: %s\n"), strerror(ret));
2bd0ea18
NS
501}
502
c9f5e3db
ES
503void
504xfs_dummy_verify(
505 struct xfs_buf *bp)
506{
507 return;
508}
509
86769b32
DC
510void
511xfs_verify_recalc_crc(
512 struct xfs_buf *bp)
513{
514 xfs_buf_update_cksum(bp, iocur_top->typ->crc_off);
515}
516
2a8b3fdf
DC
517void
518write_cur(void)
519{
b64af2c4
ES
520 bool skip_crc = false;
521
2a8b3fdf
DC
522 if (iocur_sp < 0) {
523 dbprintf(_("nothing to write\n"));
524 return;
525 }
526
2660e653 527 if (!xfs_has_crc(mp) ||
b64af2c4
ES
528 !iocur_top->bp->b_ops ||
529 iocur_top->bp->b_ops->verify_write == xfs_dummy_verify)
530 skip_crc = true;
531
532 if (!skip_crc) {
1e9c13c5
ES
533 if (iocur_top->ino_buf)
534 xfs_inode_set_crc(iocur_top->bp);
535 else if (iocur_top->dquot_buf)
536 xfs_dquot_set_crc(iocur_top->bp);
b335ecb5 537 }
72298d16 538 if (iocur_top->bbmap)
2a8b3fdf
DC
539 write_cur_bbs();
540 else
541 write_cur_buf();
b64af2c4
ES
542
543 /* If we didn't write the crc automatically, re-check inode validity */
2660e653 544 if (xfs_has_crc(mp) &&
b64af2c4 545 skip_crc && iocur_top->ino_buf) {
3c73a9a1 546 iocur_top->ino_crc_ok = libxfs_verify_cksum(iocur_top->data,
b64af2c4
ES
547 mp->m_sb.sb_inodesize,
548 XFS_DINODE_CRC_OFF);
549 }
550
2a8b3fdf
DC
551}
552
0323bbf6
CB
553static void
554__set_cur(
555 struct xfs_buftarg *btargp,
556 const typ_t *type,
e84718ec
DW
557 xfs_daddr_t blknum,
558 int len,
559 int ring_flag,
0323bbf6 560 bbmap_t *bbmap)
2bd0ea18 561{
0323bbf6
CB
562 struct xfs_buf *bp;
563 xfs_ino_t dirino;
564 xfs_ino_t ino;
565 uint16_t mode;
db23e0f4 566 const struct xfs_buf_ops *ops = type ? type->bops : NULL;
f4afdcb0 567 int error;
2bd0ea18
NS
568
569 if (iocur_sp < 0) {
9ee7055c 570 dbprintf(_("set_cur no stack element to set\n"));
2bd0ea18
NS
571 return;
572 }
573
2bd0ea18
NS
574 ino = iocur_top->ino;
575 dirino = iocur_top->dirino;
576 mode = iocur_top->mode;
577 pop_cur();
578 push_cur();
2a8b3fdf
DC
579
580 if (bbmap) {
857592d2 581#ifdef DEBUG_BBMAP
72298d16 582 int i;
db23e0f4 583 printf(_("xfs_db got a bbmap for %lld\n"), (long long)blknum);
72298d16
DC
584 printf(_("\tblock map"));
585 for (i = 0; i < bbmap->nmaps; i++)
586 printf(" %lld:%d", (long long)bbmap->b[i].bm_bn,
587 bbmap->b[i].bm_len);
588 printf("\n");
2a8b3fdf 589#endif
72298d16
DC
590 iocur_top->bbmap = malloc(sizeof(struct bbmap));
591 if (!iocur_top->bbmap)
2a8b3fdf 592 return;
72298d16 593 memcpy(iocur_top->bbmap, bbmap, sizeof(struct bbmap));
0323bbf6 594 error = -libxfs_buf_read_map(btargp, bbmap->b,
f4afdcb0
DW
595 bbmap->nmaps, LIBXFS_READBUF_SALVAGE, &bp,
596 ops);
2a8b3fdf 597 } else {
0323bbf6 598 error = -libxfs_buf_read(btargp, blknum, len,
31079e67 599 LIBXFS_READBUF_SALVAGE, &bp, ops);
72298d16 600 iocur_top->bbmap = NULL;
2a8b3fdf 601 }
6fea8f83
DC
602
603 /*
f4afdcb0
DW
604 * Salvage mode means that we still get a buffer even if the verifier
605 * says the metadata is corrupt. Therefore, the only errors we should
606 * get are for IO errors or runtime errors.
6fea8f83 607 */
f4afdcb0 608 if (error)
72298d16
DC
609 return;
610 iocur_top->buf = bp->b_addr;
611 iocur_top->bp = bp;
2cf166bc
ES
612 if (!ops) {
613 bp->b_ops = NULL;
b511ff41 614 bp->b_flags |= LIBXFS_B_UNCHECKED;
2cf166bc 615 }
2a8b3fdf 616
db23e0f4
BD
617 iocur_top->bb = blknum;
618 iocur_top->blen = len;
2bd0ea18
NS
619 iocur_top->boff = 0;
620 iocur_top->data = iocur_top->buf;
db23e0f4
BD
621 iocur_top->len = BBTOB(len);
622 iocur_top->off = blknum << BBSHIFT;
623 iocur_top->typ = cur_typ = type;
2bd0ea18
NS
624 iocur_top->ino = ino;
625 iocur_top->dirino = dirino;
626 iocur_top->mode = mode;
a73b88f2 627 iocur_top->ino_buf = 0;
66a40d02 628 iocur_top->dquot_buf = 0;
2bd0ea18
NS
629
630 /* store location in ring */
631 if (ring_flag)
632 ring_add();
633}
634
0323bbf6
CB
635void
636set_cur(
637 const typ_t *type,
638 xfs_daddr_t blknum,
639 int len,
640 int ring_flag,
641 bbmap_t *bbmap)
642{
643 __set_cur(mp->m_ddev_targp, type, blknum, len, ring_flag, bbmap);
644}
645
646void
647set_log_cur(
648 const typ_t *type,
649 xfs_daddr_t blknum,
650 int len,
651 int ring_flag,
652 bbmap_t *bbmap)
653{
654 if (mp->m_logdev_targp->bt_bdev == mp->m_ddev_targp->bt_bdev) {
655 fprintf(stderr, "no external log specified\n");
656 exitcode = 1;
657 return;
658 }
659
660 __set_cur(mp->m_logdev_targp, type, blknum, len, ring_flag, bbmap);
661}
662
e84718ec
DW
663int
664set_rt_cur(
665 const typ_t *type,
666 xfs_daddr_t blknum,
667 int len,
668 int ring_flag,
669 bbmap_t *bbmap)
670{
671 if (!mp->m_rtdev_targp->bt_bdev) {
672 printf(_("realtime device not loaded, use -R.\n"));
673 return ENODEV;
674 }
675
676 __set_cur(mp->m_rtdev_targp, type, blknum, len, ring_flag, bbmap);
677 return 0;
678}
0323bbf6 679
9ba69ce2
DC
680void
681set_iocur_type(
db23e0f4 682 const typ_t *type)
9ba69ce2 683{
127b66a4
DW
684 /* type's size in basic blocks */
685 int bb_count = BTOBB(mp->m_sb.sb_sectsize);
0d376f6c 686 int boff = iocur_top->boff;
9ba69ce2 687
b1a48c4f
ZL
688 /*
689 * Inodes are special; verifier checks all inodes in the chunk, the
690 * set_cur_inode() will help that
691 */
533d1d22
ES
692 if (type->typnm == TYP_INODE) {
693 xfs_daddr_t b = iocur_top->bb;
b1a48c4f
ZL
694 xfs_agblock_t agbno;
695 xfs_agino_t agino;
533d1d22
ES
696 xfs_ino_t ino;
697
b1a48c4f
ZL
698 agbno = xfs_daddr_to_agbno(mp, b);
699 agino = XFS_OFFBNO_TO_AGINO(mp, agbno,
700 iocur_top->boff / mp->m_sb.sb_inodesize);
701 ino = XFS_AGINO_TO_INO(mp, xfs_daddr_to_agno(mp, b), agino);
533d1d22
ES
702 set_cur_inode(ino);
703 return;
704 }
705
55f224ba 706 /* adjust buffer size for types with fields & hence fsize() */
cdabe556 707 if (type->fields)
db23e0f4 708 bb_count = BTOBB(byteize(fsize(type->fields,
cdabe556
ES
709 iocur_top->data, 0, 0)));
710 set_cur(type, iocur_top->bb, bb_count, DB_RING_IGN, NULL);
0d376f6c 711 set_cur_boff(boff);
9ba69ce2
DC
712}
713
2bd0ea18
NS
714static void
715stack_help(void)
716{
9ee7055c 717 dbprintf(_(
2bd0ea18
NS
718"\n"
719" The stack is used to explicitly store your location and data type\n"
720" for later return. The 'push' operation stores the current address\n"
721" and type on the stack, the 'pop' operation returns you to the\n"
722" position and datatype of the top entry on the stack.\n"
723"\n"
724" The 'stack' allows explicit location saves, see 'ring' for implicit\n"
725" position tracking.\n"
726"\n"
9ee7055c 727 ));
2bd0ea18
NS
728}
729
730/*ARGSUSED*/
731static int
732stack_f(
733 int argc,
734 char **argv)
735{
736 int i;
75ff9c67 737 char tagbuf[14];
2bd0ea18 738
2d9475a4
NS
739 for (i = iocur_sp; i > 0; i--) {
740 snprintf(tagbuf, sizeof(tagbuf), "%d: ", i);
2bd0ea18
NS
741 print_iocur(tagbuf, &iocur_base[i]);
742 }
743 return 0;
744}