]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/bmap.c
apply gettext translation to more strings
[thirdparty/xfsprogs-dev.git] / db / bmap.c
1 /*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
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.
8 *
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.
13 *
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
17 */
18
19 #include <xfs/libxfs.h>
20 #include "command.h"
21 #include "type.h"
22 #include "fprint.h"
23 #include "faddr.h"
24 #include "field.h"
25 #include "bmap.h"
26 #include "io.h"
27 #include "inode.h"
28 #include "output.h"
29 #include "init.h"
30
31 static int bmap_f(int argc, char **argv);
32 static int bmap_one_extent(xfs_bmbt_rec_64_t *ep,
33 xfs_dfiloff_t *offp, xfs_dfiloff_t eoff,
34 int *idxp, bmap_ext_t *bep);
35 static xfs_fsblock_t select_child(xfs_dfiloff_t off, xfs_bmbt_key_t *kp,
36 xfs_bmbt_ptr_t *pp, int nrecs);
37
38 static const cmdinfo_t bmap_cmd =
39 { "bmap", NULL, bmap_f, 0, 3, 0, N_("[-ad] [block [len]]"),
40 N_("show block map for current file"), NULL };
41
42 void
43 bmap(
44 xfs_dfiloff_t offset,
45 xfs_dfilblks_t len,
46 int whichfork,
47 int *nexp,
48 bmap_ext_t *bep)
49 {
50 struct xfs_btree_block *block;
51 xfs_fsblock_t bno;
52 xfs_dfiloff_t curoffset;
53 xfs_dinode_t *dip;
54 xfs_dfiloff_t eoffset;
55 xfs_bmbt_rec_64_t *ep;
56 xfs_dinode_fmt_t fmt;
57 int fsize;
58 xfs_bmbt_key_t *kp;
59 int n;
60 int nex;
61 xfs_fsblock_t nextbno;
62 int nextents;
63 xfs_bmbt_ptr_t *pp;
64 xfs_bmdr_block_t *rblock;
65 typnm_t typ;
66 xfs_bmbt_rec_64_t *xp;
67
68 push_cur();
69 set_cur_inode(iocur_top->ino);
70 nex = *nexp;
71 *nexp = 0;
72 ASSERT(nex > 0);
73 dip = iocur_top->data;
74 n = 0;
75 eoffset = offset + len - 1;
76 curoffset = offset;
77 fmt = (xfs_dinode_fmt_t)XFS_DFORK_FORMAT(dip, whichfork);
78 typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA;
79 ASSERT(typtab[typ].typnm == typ);
80 ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS ||
81 fmt == XFS_DINODE_FMT_BTREE);
82 if (fmt == XFS_DINODE_FMT_EXTENTS) {
83 nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
84 xp = (xfs_bmbt_rec_64_t *)XFS_DFORK_PTR(dip, whichfork);
85 for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
86 if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep))
87 break;
88 }
89 } else if (fmt == XFS_DINODE_FMT_BTREE) {
90 push_cur();
91 bno = NULLFSBLOCK;
92 rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
93 fsize = XFS_DFORK_SIZE(dip, mp, whichfork);
94 pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(mp, fsize, 0));
95 kp = XFS_BMDR_KEY_ADDR(rblock, 1);
96 bno = select_child(curoffset, kp, pp,
97 be16_to_cpu(rblock->bb_numrecs));
98 for (;;) {
99 set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno),
100 blkbb, DB_RING_IGN, NULL);
101 block = (struct xfs_btree_block *)iocur_top->data;
102 if (be16_to_cpu(block->bb_level) == 0)
103 break;
104 pp = XFS_BMDR_PTR_ADDR(block, 1,
105 xfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0));
106 kp = XFS_BMDR_KEY_ADDR(block, 1);
107 bno = select_child(curoffset, kp, pp,
108 be16_to_cpu(block->bb_numrecs));
109 }
110 for (;;) {
111 nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);
112 nextents = be16_to_cpu(block->bb_numrecs);
113 xp = (xfs_bmbt_rec_64_t *)
114 XFS_BMBT_REC_ADDR(mp, block, 1);
115 for (ep = xp; ep < &xp[nextents] && n < nex; ep++) {
116 if (!bmap_one_extent(ep, &curoffset, eoffset,
117 &n, bep)) {
118 nextbno = NULLFSBLOCK;
119 break;
120 }
121 }
122 bno = nextbno;
123 if (bno == NULLFSBLOCK)
124 break;
125 set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno),
126 blkbb, DB_RING_IGN, NULL);
127 block = (struct xfs_btree_block *)iocur_top->data;
128 }
129 pop_cur();
130 }
131 pop_cur();
132 *nexp = n;
133 }
134
135 static int
136 bmap_f(
137 int argc,
138 char **argv)
139 {
140 int afork = 0;
141 bmap_ext_t be;
142 int c;
143 xfs_dfiloff_t co, cosave;
144 int dfork = 0;
145 xfs_dinode_t *dip;
146 xfs_dfiloff_t eo;
147 xfs_dfilblks_t len;
148 int nex;
149 char *p;
150 int whichfork;
151
152 if (iocur_top->ino == NULLFSINO) {
153 dbprintf(_("no current inode\n"));
154 return 0;
155 }
156 optind = 0;
157 if (argc) while ((c = getopt(argc, argv, "ad")) != EOF) {
158 switch (c) {
159 case 'a':
160 afork = 1;
161 break;
162 case 'd':
163 dfork = 1;
164 break;
165 default:
166 dbprintf(_("bad option for bmap command\n"));
167 return 0;
168 }
169 }
170 if (afork + dfork == 0) {
171 push_cur();
172 set_cur_inode(iocur_top->ino);
173 dip = iocur_top->data;
174 if (be32_to_cpu(dip->di_core.di_nextents))
175 dfork = 1;
176 if (be16_to_cpu(dip->di_core.di_anextents))
177 afork = 1;
178 pop_cur();
179 }
180 if (optind < argc) {
181 co = (xfs_dfiloff_t)strtoull(argv[optind], &p, 0);
182 if (*p != '\0') {
183 dbprintf(_("bad block number for bmap %s\n"),
184 argv[optind]);
185 return 0;
186 }
187 optind++;
188 if (optind < argc) {
189 len = (xfs_dfilblks_t)strtoull(argv[optind], &p, 0);
190 if (*p != '\0') {
191 dbprintf(_("bad len for bmap %s\n"), argv[optind]);
192 return 0;
193 }
194 eo = co + len - 1;
195 } else
196 eo = co;
197 } else {
198 co = 0;
199 eo = -1;
200 }
201 cosave = co;
202 for (whichfork = XFS_DATA_FORK;
203 whichfork <= XFS_ATTR_FORK;
204 whichfork++) {
205 if (whichfork == XFS_DATA_FORK && !dfork)
206 continue;
207 if (whichfork == XFS_ATTR_FORK && !afork)
208 continue;
209 for (;;) {
210 nex = 1;
211 bmap(co, eo - co + 1, whichfork, &nex, &be);
212 if (nex == 0)
213 break;
214 dbprintf(_("%s offset %lld startblock %llu (%u/%u) count "
215 "%llu flag %u\n"),
216 whichfork == XFS_DATA_FORK ? _("data") : _("attr"),
217 be.startoff, be.startblock,
218 XFS_FSB_TO_AGNO(mp, be.startblock),
219 XFS_FSB_TO_AGBNO(mp, be.startblock),
220 be.blockcount, be.flag);
221 co = be.startoff + be.blockcount;
222 }
223 co = cosave;
224 }
225 return 0;
226 }
227
228 void
229 bmap_init(void)
230 {
231 add_command(&bmap_cmd);
232 }
233
234 static int
235 bmap_one_extent(
236 xfs_bmbt_rec_64_t *ep,
237 xfs_dfiloff_t *offp,
238 xfs_dfiloff_t eoff,
239 int *idxp,
240 bmap_ext_t *bep)
241 {
242 xfs_dfilblks_t c;
243 xfs_dfiloff_t curoffset;
244 int f;
245 int idx;
246 xfs_dfiloff_t o;
247 xfs_dfsbno_t s;
248
249 convert_extent(ep, &o, &s, &c, &f);
250 curoffset = *offp;
251 idx = *idxp;
252 if (o + c <= curoffset)
253 return 1;
254 if (o > eoff)
255 return 0;
256 if (o < curoffset) {
257 c -= curoffset - o;
258 s += curoffset - o;
259 o = curoffset;
260 }
261 if (o + c - 1 > eoff)
262 c -= (o + c - 1) - eoff;
263 bep[idx].startoff = o;
264 bep[idx].startblock = s;
265 bep[idx].blockcount = c;
266 bep[idx].flag = f;
267 *idxp = idx + 1;
268 *offp = o + c;
269 return 1;
270 }
271
272 void
273 convert_extent(
274 xfs_bmbt_rec_64_t *rp,
275 xfs_dfiloff_t *op,
276 xfs_dfsbno_t *sp,
277 xfs_dfilblks_t *cp,
278 int *fp)
279 {
280 xfs_bmbt_irec_t irec;
281
282 libxfs_bmbt_disk_get_all(rp, &irec);
283
284 *fp = irec.br_state == XFS_EXT_UNWRITTEN;
285 *op = irec.br_startoff;
286 *sp = irec.br_startblock;
287 *cp = irec.br_blockcount;
288 }
289
290 void
291 make_bbmap(
292 bbmap_t *bbmap,
293 int nex,
294 bmap_ext_t *bmp)
295 {
296 int d;
297 xfs_dfsbno_t dfsbno;
298 int i;
299 int j;
300 int k;
301
302 for (i = 0, d = 0; i < nex; i++) {
303 dfsbno = bmp[i].startblock;
304 for (j = 0; j < bmp[i].blockcount; j++, dfsbno++) {
305 for (k = 0; k < blkbb; k++)
306 bbmap->b[d++] =
307 XFS_FSB_TO_DADDR(mp, dfsbno) + k;
308 }
309 }
310 }
311
312 static xfs_fsblock_t
313 select_child(
314 xfs_dfiloff_t off,
315 xfs_bmbt_key_t *kp,
316 xfs_bmbt_ptr_t *pp,
317 int nrecs)
318 {
319 int i;
320
321 for (i = 0; i < nrecs; i++) {
322 if (be64_to_cpu(kp[i].br_startoff) == off)
323 return be64_to_cpu(pp[i]);
324 if (be64_to_cpu(kp[i].br_startoff) > off) {
325 if (i == 0)
326 return be64_to_cpu(pp[i]);
327 else
328 return be64_to_cpu(pp[i - 1]);
329 }
330 }
331 return be64_to_cpu(pp[nrecs - 1]);
332 }