]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/io.c
39a1827cf05d7e32833a38c5a914d1104e7720b2
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <xfs/libxfs.h>
31 static int pop_f(int argc
, char **argv
);
32 static void pop_help(void);
33 static int push_f(int argc
, char **argv
);
34 static void push_help(void);
35 static int stack_f(int argc
, char **argv
);
36 static void stack_help(void);
37 static int forward_f(int argc
, char **argv
);
38 static void forward_help(void);
39 static int back_f(int argc
, char **argv
);
40 static void back_help(void);
41 static int ring_f(int argc
, char **argv
);
42 static void ring_help(void);
44 static const cmdinfo_t pop_cmd
=
45 { "pop", NULL
, pop_f
, 0, 0, 0, NULL
,
46 N_("pop location from the stack"), pop_help
};
47 static const cmdinfo_t push_cmd
=
48 { "push", NULL
, push_f
, 0, 2, 0, N_("[command]"),
49 N_("push location to the stack"), push_help
};
50 static const cmdinfo_t stack_cmd
=
51 { "stack", NULL
, stack_f
, 0, 0, 0, NULL
,
52 N_("view the location stack"), stack_help
};
53 static const cmdinfo_t forward_cmd
=
54 { "forward", "f", forward_f
, 0, 0, 0, NULL
,
55 N_("move forward to next entry in the position ring"), forward_help
};
56 static const cmdinfo_t back_cmd
=
57 { "back", "b", back_f
, 0, 0, 0, NULL
,
58 N_("move to the previous location in the position ring"), back_help
};
59 static const cmdinfo_t ring_cmd
=
60 { "ring", NULL
, ring_f
, 0, 1, 0, NULL
,
61 N_("show position ring or move to a specific entry"), ring_help
};
68 #define RING_ENTRIES 20
69 static iocur_t iocur_ring
[RING_ENTRIES
];
70 static int ring_head
= -1;
71 static int ring_tail
= -1;
72 static int ring_current
= -1;
77 add_command(&pop_cmd
);
78 add_command(&push_cmd
);
79 add_command(&stack_cmd
);
80 add_command(&forward_cmd
);
81 add_command(&back_cmd
);
82 add_command(&ring_cmd
);
90 if (iocur_top
== NULL
|| off
+ len
> BBTOB(iocur_top
->blen
))
91 dbprintf(_("can't set block offset to %d\n"), off
);
93 iocur_top
->boff
= off
;
94 iocur_top
->off
= ((xfs_off_t
)iocur_top
->bb
<< BBSHIFT
) + off
;
96 iocur_top
->data
= (void *)((char *)iocur_top
->buf
+ off
);
104 dbprintf(_("can't pop anything from I/O stack\n"));
108 xfree(iocur_top
->buf
);
109 if (--iocur_sp
>= 0) {
110 iocur_top
= iocur_base
+ iocur_sp
;
111 cur_typ
= iocur_top
->typ
;
113 iocur_top
= iocur_base
;
133 " Changes the address and data type to the first entry on the stack.\n"
145 dbprintf("%s\n", tag
);
146 dbprintf(_("\tbyte offset %lld, length %d\n"), ioc
->off
, ioc
->len
);
147 dbprintf(_("\tbuffer block %lld (fsbno %lld), %d bb%s\n"), ioc
->bb
,
148 (xfs_dfsbno_t
)XFS_DADDR_TO_FSB(mp
, ioc
->bb
), ioc
->blen
,
149 ioc
->blen
== 1 ? "" : "s");
150 if (ioc
->use_bbmap
) {
151 dbprintf(_("\tblock map"));
152 for (i
= 0; i
< ioc
->blen
; i
++)
153 dbprintf(" %d:%lld", i
, ioc
->bbmap
.b
[i
]);
156 dbprintf(_("\tinode %lld, dir inode %lld, type %s\n"), ioc
->ino
,
157 ioc
->dirino
, ioc
->typ
== NULL
? _("none") : ioc
->typ
->name
);
166 if (ring_current
== -1) {
167 dbprintf(_("no entries in location ring.\n"));
171 dbprintf(_(" type bblock bblen fsbno inode\n"));
175 ioc
= &iocur_ring
[i
];
176 if (i
== ring_current
)
181 dbprintf("%-7.7s %8lld %5d %8lld %9lld\n",
182 ioc
->typ
== NULL
? "none" : ioc
->typ
->name
,
185 (xfs_dfsbno_t
)XFS_DADDR_TO_FSB(mp
, ioc
->bb
),
192 i
= (i
+(RING_ENTRIES
-1))%RING_ENTRIES
;
200 if (iocur_sp
+ 1 >= iocur_len
) {
201 iocur_base
= xrealloc(iocur_base
,
202 sizeof(*iocur_base
) * (iocur_len
+ 1));
206 iocur_top
= iocur_base
+ iocur_sp
;
207 memset(iocur_top
, 0, sizeof(*iocur_base
));
208 iocur_top
->ino
= iocur_sp
> 0 ? iocur_top
[-1].ino
: NULLFSINO
;
209 iocur_top
->dirino
= iocur_sp
> 0 ? iocur_top
[-1].dirino
: NULLFSINO
;
210 iocur_top
->mode
= iocur_sp
> 0 ? iocur_top
[-1].mode
: 0;
222 /* check we can execute command */
223 ct
= find_command(argv
[1]);
225 dbprintf(_("no such command %s\n"), argv
[1]);
229 dbprintf(_("no push form allowed for %s\n"), argv
[1]);
234 /* save current state */
236 if (iocur_top
[-1].typ
&& iocur_top
[-1].typ
->typnm
== TYP_INODE
)
237 set_cur_inode(iocur_top
[-1].ino
);
239 set_cur(iocur_top
[-1].typ
, iocur_top
[-1].bb
,
240 iocur_top
[-1].blen
, DB_RING_IGN
,
241 iocur_top
[-1].use_bbmap
? &iocur_top
[-1].bbmap
: NULL
);
243 /* run requested command */
245 (void)command(argc
-1, argv
+1);
254 " Allows you to push the current address and data type on the stack for\n"
255 " later return. 'push' also accepts an additional command to execute after\n"
256 " storing the current address (ex: 'push a rootino' from the superblock).\n"
261 /* move forward through the ring */
268 if (ring_current
== -1) {
269 dbprintf(_("ring is empty\n"));
272 if (ring_current
== ring_head
) {
273 dbprintf(_("no further entries\n"));
277 ring_current
= (ring_current
+1)%RING_ENTRIES
;
279 set_cur(iocur_ring
[ring_current
].typ
,
280 iocur_ring
[ring_current
].bb
,
281 iocur_ring
[ring_current
].blen
,
283 iocur_ring
[ring_current
].use_bbmap
?
284 &iocur_ring
[ring_current
].bbmap
: NULL
);
294 " The 'forward' ('f') command moves to the next location in the position\n"
295 " ring, updating the current position and data type. If the current location\n"
296 " is the top entry in the ring, then the 'forward' command will have\n"
302 /* move backwards through the ring */
309 if (ring_current
== -1) {
310 dbprintf(_("ring is empty\n"));
313 if (ring_current
== ring_tail
) {
314 dbprintf(_("no previous entries\n"));
318 ring_current
= (ring_current
+(RING_ENTRIES
-1))%RING_ENTRIES
;
320 set_cur(iocur_ring
[ring_current
].typ
,
321 iocur_ring
[ring_current
].bb
,
322 iocur_ring
[ring_current
].blen
,
324 iocur_ring
[ring_current
].use_bbmap
?
325 &iocur_ring
[ring_current
].bbmap
: NULL
);
335 " The 'back' ('b') command moves to the previous location in the position\n"
336 " ring, updating the current position and data type. If the current location\n"
337 " is the last entry in the ring, then the 'back' command will have no effect.\n"
342 /* show or go to specific point in ring */
355 index
= (int)strtoul(argv
[1], NULL
, 0);
356 if (index
< 0 || index
>= RING_ENTRIES
)
357 dbprintf(_("invalid entry: %d\n"), index
);
359 ring_current
= index
;
361 set_cur(iocur_ring
[index
].typ
,
362 iocur_ring
[index
].bb
,
363 iocur_ring
[index
].blen
,
365 iocur_ring
[index
].use_bbmap
? &iocur_ring
[index
].bbmap
: NULL
);
375 " The position ring automatically keeps track of each disk location and\n"
376 " structure type for each change of position you make during your xfs_db\n"
377 " session. The last %d most recent entries are kept in the ring.\n"
379 " To display the current list of ring entries type 'ring' by itself on\n"
380 " the command line. The entry highlighted by an asterisk ('*') is the\n"
383 " To move to another entry in the ring type 'ring <num>' where <num> is\n"
384 " your desired entry from the ring position list.\n"
386 " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n"
387 " to the previous or next entry in the ring, respectively.\n"
389 " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n"
390 " location implicitly. Use the 'push' and 'pop' commands if you wish to\n"
391 " store a specific location explicitly for later return.\n"
400 if (ring_head
== -1) {
401 /* only get here right after startup */
405 iocur_ring
[0] = *iocur_top
;
407 if (ring_current
== ring_head
) {
408 ring_head
= (ring_head
+1)%RING_ENTRIES
;
409 iocur_ring
[ring_head
] = *iocur_top
;
410 if (ring_head
== ring_tail
)
411 ring_tail
= (ring_tail
+1)%RING_ENTRIES
;
412 ring_current
= ring_head
;
414 ring_current
= (ring_current
+1)%RING_ENTRIES
;
415 iocur_ring
[ring_current
] = *iocur_top
;
431 int rval
= EINVAL
; /* initialize for zero `count' case */
433 for (j
= 0; j
< count
; j
+= bbmap
? 1 : count
) {
436 if (lseek64(x
.dfd
, bbno
<< BBSHIFT
, SEEK_SET
) < 0) {
438 dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno
);
441 c
= BBTOB(bbmap
? 1 : count
);
442 i
= (int)write(x
.dfd
, (char *)bufp
+ BBTOB(j
), c
);
476 for (j
= 0; j
< count
; j
+= bbmap
? 1 : count
) {
479 if (lseek64(x
.dfd
, bbno
<< BBSHIFT
, SEEK_SET
) < 0) {
481 dbprintf(_("can't seek in filesystem at bb %lld\n"), bbno
);
486 c
= BBTOB(bbmap
? 1 : count
);
487 i
= (int)read(x
.dfd
, (char *)buf
+ BBTOB(j
), c
);
515 dbprintf(_("nothing to write\n"));
518 ret
= write_bbs(iocur_top
->bb
, iocur_top
->blen
, iocur_top
->buf
,
519 iocur_top
->use_bbmap
? &iocur_top
->bbmap
: NULL
);
521 dbprintf(_("incomplete write, block: %lld\n"),
522 (iocur_base
+ iocur_sp
)->bb
);
524 dbprintf(_("write error: %s\n"), strerror(ret
));
525 /* re-read buffer from disk */
526 ret
= read_bbs(iocur_top
->bb
, iocur_top
->blen
, &iocur_top
->buf
,
527 iocur_top
->use_bbmap
? &iocur_top
->bbmap
: NULL
);
529 dbprintf(_("incomplete read, block: %lld\n"),
530 (iocur_base
+ iocur_sp
)->bb
);
532 dbprintf(_("read error: %s\n"), strerror(ret
));
548 dbprintf(_("set_cur no stack element to set\n"));
554 printf(_("xfs_db got a bbmap for %lld\n"), (long long)d
);
556 ino
= iocur_top
->ino
;
557 dirino
= iocur_top
->dirino
;
558 mode
= iocur_top
->mode
;
561 if (read_bbs(d
, c
, &iocur_top
->buf
, bbmap
))
566 iocur_top
->data
= iocur_top
->buf
;
567 iocur_top
->len
= BBTOB(c
);
568 iocur_top
->off
= d
<< BBSHIFT
;
569 iocur_top
->typ
= cur_typ
= t
;
570 iocur_top
->ino
= ino
;
571 iocur_top
->dirino
= dirino
;
572 iocur_top
->mode
= mode
;
573 if ((iocur_top
->use_bbmap
= (bbmap
!= NULL
)))
574 iocur_top
->bbmap
= *bbmap
;
576 /* store location in ring */
586 " The stack is used to explicitly store your location and data type\n"
587 " for later return. The 'push' operation stores the current address\n"
588 " and type on the stack, the 'pop' operation returns you to the\n"
589 " position and datatype of the top entry on the stack.\n"
591 " The 'stack' allows explicit location saves, see 'ring' for implicit\n"
592 " position tracking.\n"
606 for (i
= iocur_sp
; i
> 0; i
--) {
607 snprintf(tagbuf
, sizeof(tagbuf
), "%d: ", i
);
608 print_iocur(tagbuf
, &iocur_base
[i
]);