]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/io.c
99886881ebda9dcd66f638a5bfc76f03fb67d855
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
46 static int pop_f(int argc
, char **argv
);
47 static void pop_help(void);
48 static int push_f(int argc
, char **argv
);
49 static void push_help(void);
50 static int stack_f(int argc
, char **argv
);
51 static void stack_help(void);
52 static int forward_f(int argc
, char **argv
);
53 static void forward_help(void);
54 static int back_f(int argc
, char **argv
);
55 static void back_help(void);
56 static int ring_f(int argc
, char **argv
);
57 static void ring_help(void);
59 static const cmdinfo_t pop_cmd
=
60 { "pop", NULL
, pop_f
, 0, 0, 0, NULL
,
61 "pop location from the stack", pop_help
};
62 static const cmdinfo_t push_cmd
=
63 { "push", NULL
, push_f
, 0, 2, 0, "[command]",
64 "push location to the stack", push_help
};
65 static const cmdinfo_t stack_cmd
=
66 { "stack", NULL
, stack_f
, 0, 0, 0, NULL
,
67 "view the location stack", stack_help
};
68 static const cmdinfo_t forward_cmd
=
69 { "forward", "f", forward_f
, 0, 0, 0, NULL
,
70 "move forward to next entry in the position ring", forward_help
};
71 static const cmdinfo_t back_cmd
=
72 { "back", "b", back_f
, 0, 0, 0, NULL
,
73 "move to the previous location in the position ring", back_help
};
74 static const cmdinfo_t ring_cmd
=
75 { "ring", NULL
, ring_f
, 0, 1, 0, NULL
,
76 "show position ring or move to a specific entry", ring_help
};
83 #define RING_ENTRIES 20
84 static iocur_t iocur_ring
[RING_ENTRIES
];
85 static int ring_head
= -1;
86 static int ring_tail
= -1;
87 static int ring_current
= -1;
92 add_command(&pop_cmd
);
93 add_command(&push_cmd
);
94 add_command(&stack_cmd
);
95 add_command(&forward_cmd
);
96 add_command(&back_cmd
);
97 add_command(&ring_cmd
);
105 if (iocur_top
== NULL
|| off
+ len
> BBTOB(iocur_top
->blen
))
106 dbprintf("can't set block offset to %d\n", off
);
108 iocur_top
->boff
= off
;
109 iocur_top
->off
= ((xfs_off_t
)iocur_top
->bb
<< BBSHIFT
) + off
;
110 iocur_top
->len
= len
;
111 iocur_top
->data
= (void *)((char *)iocur_top
->buf
+ off
);
119 dbprintf("can't pop anything from I/O stack\n");
123 xfree(iocur_top
->buf
);
124 if (--iocur_sp
>= 0) {
125 iocur_top
= iocur_base
+ iocur_sp
;
126 cur_typ
= iocur_top
->typ
;
128 iocur_top
= iocur_base
;
148 " Changes the address and data type to the first entry on the stack.\n"
160 dbprintf("%s\n", tag
);
161 dbprintf("\tbyte offset %lld, length %d\n", ioc
->off
, ioc
->len
);
162 dbprintf("\tbuffer block %lld (fsbno %lld), %d bb%s\n", ioc
->bb
,
163 (xfs_dfsbno_t
)XFS_DADDR_TO_FSB(mp
, ioc
->bb
), ioc
->blen
,
164 ioc
->blen
== 1 ? "" : "s");
165 if (ioc
->use_bbmap
) {
166 dbprintf("\tblock map");
167 for (i
= 0; i
< ioc
->blen
; i
++)
168 dbprintf(" %d:%lld", i
, ioc
->bbmap
.b
[i
]);
171 dbprintf("\tinode %lld, dir inode %lld, type %s\n", ioc
->ino
,
172 ioc
->dirino
, ioc
->typ
== NULL
? "none" : ioc
->typ
->name
);
181 if (ring_current
== -1) {
182 dbprintf("no entries in location ring.\n");
186 dbprintf(" type bblock bblen fsbno inode\n");
190 ioc
= &iocur_ring
[i
];
191 if (i
== ring_current
)
196 dbprintf("%-7.7s %8lld %5d %8lld %9lld\n",
197 ioc
->typ
== NULL
? "none" : ioc
->typ
->name
,
200 (xfs_dfsbno_t
)XFS_DADDR_TO_FSB(mp
, ioc
->bb
),
207 i
= (i
+(RING_ENTRIES
-1))%RING_ENTRIES
;
215 if (iocur_sp
+ 1 >= iocur_len
) {
216 iocur_base
= xrealloc(iocur_base
,
217 sizeof(*iocur_base
) * (iocur_len
+ 1));
221 iocur_top
= iocur_base
+ iocur_sp
;
222 memset(iocur_top
, 0, sizeof(*iocur_base
));
223 iocur_top
->ino
= iocur_sp
> 0 ? iocur_top
[-1].ino
: NULLFSINO
;
224 iocur_top
->dirino
= iocur_sp
> 0 ? iocur_top
[-1].dirino
: NULLFSINO
;
225 iocur_top
->mode
= iocur_sp
> 0 ? iocur_top
[-1].mode
: 0;
237 /* check we can execute command */
238 ct
= find_command(argv
[1]);
240 dbprintf("no such command %s\n", argv
[1]);
244 dbprintf("no push form allowed for %s\n", argv
[1]);
249 /* save current state */
251 if (iocur_top
[-1].typ
&& iocur_top
[-1].typ
->typnm
== TYP_INODE
)
252 set_cur_inode(iocur_top
[-1].ino
);
254 set_cur(iocur_top
[-1].typ
, iocur_top
[-1].bb
,
255 iocur_top
[-1].blen
, DB_RING_IGN
,
256 iocur_top
[-1].use_bbmap
? &iocur_top
[-1].bbmap
: NULL
);
258 /* run requested command */
260 (void)command(argc
-1, argv
+1);
269 " Allows you to push the current address and data type on the stack for\n"
270 " later return. 'push' also accepts an additional command to execute after\n"
271 " storing the current address (ex: 'push a rootino' from the superblock).\n"
276 /* move forward through the ring */
283 if (ring_current
== -1) {
284 dbprintf("ring is empty\n");
287 if (ring_current
== ring_head
) {
288 dbprintf("no further entries\n");
292 ring_current
= (ring_current
+1)%RING_ENTRIES
;
294 set_cur(iocur_ring
[ring_current
].typ
,
295 iocur_ring
[ring_current
].bb
,
296 iocur_ring
[ring_current
].blen
,
298 iocur_ring
[ring_current
].use_bbmap
?
299 &iocur_ring
[ring_current
].bbmap
: NULL
);
309 " The 'forward' ('f') command moves to the next location in the position\n"
310 " ring, updating the current position and data type. If the current location\n"
311 " is the top entry in the ring, then the 'forward' command will have\n"
317 /* move backwards through the ring */
324 if (ring_current
== -1) {
325 dbprintf("ring is empty\n");
328 if (ring_current
== ring_tail
) {
329 dbprintf("no previous entries\n");
333 ring_current
= (ring_current
+(RING_ENTRIES
-1))%RING_ENTRIES
;
335 set_cur(iocur_ring
[ring_current
].typ
,
336 iocur_ring
[ring_current
].bb
,
337 iocur_ring
[ring_current
].blen
,
339 iocur_ring
[ring_current
].use_bbmap
?
340 &iocur_ring
[ring_current
].bbmap
: NULL
);
350 " The 'back' ('b') command moves to the previous location in the position\n"
351 " ring, updating the current position and data type. If the current location\n"
352 " is the last entry in the ring, then the 'back' command will have no effect.\n"
357 /* show or go to specific point in ring */
370 index
= (int)strtoul(argv
[0], NULL
, 0);
371 if (index
< 0 || index
>= RING_ENTRIES
)
372 dbprintf("invalid entry: %d\n", index
);
374 ring_current
= index
;
376 set_cur(iocur_ring
[index
].typ
,
377 iocur_ring
[index
].bb
,
378 iocur_ring
[index
].blen
,
380 iocur_ring
[index
].use_bbmap
? &iocur_ring
[index
].bbmap
: NULL
);
390 " The position ring automatically keeps track of each disk location and\n"
391 " structure type for each change of position you make during your xfs_db\n"
392 " session. The last %d most recent entries are kept in the ring.\n"
394 " To display the current list of ring entries type 'ring' by itself on\n"
395 " the command line. The entry highlighted by an asterisk ('*') is the\n"
398 " To move to another entry in the ring type 'ring <num>' where <num> is\n"
399 " your desired entry from the ring position list.\n"
401 " You may also use the 'forward' ('f') or 'back' ('b') commands to move\n"
402 " to the previous or next entry in the ring, respectively.\n"
404 " Note: Unlike the 'stack', 'push' and 'pop' commands, the ring tracks your\n"
405 " location implicitly. Use the 'push' and 'pop' commands if you wish to\n"
406 " store a specific location explicitly for later return.\n"
415 if (ring_head
== -1) {
416 /* only get here right after startup */
420 iocur_ring
[0] = *iocur_top
;
422 if (ring_current
== ring_head
) {
423 ring_head
= (ring_head
+1)%RING_ENTRIES
;
424 iocur_ring
[ring_head
] = *iocur_top
;
425 if (ring_head
== ring_tail
)
426 ring_tail
= (ring_tail
+1)%RING_ENTRIES
;
427 ring_current
= ring_head
;
429 ring_current
= (ring_current
+1)%RING_ENTRIES
;
430 iocur_ring
[ring_current
] = *iocur_top
;
446 int rval
= EINVAL
; /* initialize for zero `count' case */
448 for (j
= 0; j
< count
; j
+= bbmap
? 1 : count
) {
451 if (lseek64(xfsargs
.dfd
, bbno
<< BBSHIFT
, SEEK_SET
) < 0) {
453 dbprintf("can't seek in filesystem at bb %lld\n", bbno
);
456 c
= BBTOB(bbmap
? 1 : count
);
457 i
= (int)write(xfsargs
.dfd
, (char *)bufp
+ BBTOB(j
), c
);
491 for (j
= 0; j
< count
; j
+= bbmap
? 1 : count
) {
494 if (lseek64(xfsargs
.dfd
, bbno
<< BBSHIFT
, SEEK_SET
) < 0) {
496 dbprintf("can't seek in filesystem at bb %lld\n", bbno
);
501 c
= BBTOB(bbmap
? 1 : count
);
502 i
= (int)read(xfsargs
.dfd
, (char *)buf
+ BBTOB(j
), c
);
530 dbprintf("nothing to write\n");
533 ret
= write_bbs(iocur_top
->bb
, iocur_top
->blen
, iocur_top
->buf
,
534 iocur_top
->use_bbmap
? &iocur_top
->bbmap
: NULL
);
536 dbprintf("incomplete write, block: %lld\n",
537 (iocur_base
+ iocur_sp
)->bb
);
539 dbprintf("write error: %s\n", strerror(ret
));
540 /* re-read buffer from disk */
541 ret
= read_bbs(iocur_top
->bb
, iocur_top
->blen
, &iocur_top
->buf
,
542 iocur_top
->use_bbmap
? &iocur_top
->bbmap
: NULL
);
544 dbprintf("incomplete read, block: %lld\n",
545 (iocur_base
+ iocur_sp
)->bb
);
547 dbprintf("read error: %s\n", strerror(ret
));
563 dbprintf("set_cur no stack element to set\n");
569 printf("xfs_db got a bbmap for %lld\n", (long long)d
);
571 ino
= iocur_top
->ino
;
572 dirino
= iocur_top
->dirino
;
573 mode
= iocur_top
->mode
;
576 if (read_bbs(d
, c
, &iocur_top
->buf
, bbmap
))
581 iocur_top
->data
= iocur_top
->buf
;
582 iocur_top
->len
= BBTOB(c
);
583 iocur_top
->off
= d
<< BBSHIFT
;
584 iocur_top
->typ
= cur_typ
= t
;
585 iocur_top
->ino
= ino
;
586 iocur_top
->dirino
= dirino
;
587 iocur_top
->mode
= mode
;
588 if ((iocur_top
->use_bbmap
= (bbmap
!= NULL
)))
589 iocur_top
->bbmap
= *bbmap
;
591 /* store location in ring */
601 " The stack is used to explicitly store your location and data type\n"
602 " for later return. The 'push' operation stores the current address\n"
603 " and type on the stack, the 'pop' operation returns you to the\n"
604 " position and datatype of the top entry on the stack.\n"
606 " The 'stack' allows explicit location saves, see 'ring' for implicit\n"
607 " position tracking.\n"
621 for (i
= iocur_sp
; i
> 0; i
--) {
622 snprintf(tagbuf
, sizeof(tagbuf
), "%d: ", i
);
623 print_iocur(tagbuf
, &iocur_base
[i
]);