]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/dir2.c
b8b440cc50d020c82e4a5a436022db7bc5224a97
[thirdparty/xfsprogs-dev.git] / db / dir2.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include "bit.h"
35 #include "type.h"
36 #include "faddr.h"
37 #include "fprint.h"
38 #include "field.h"
39 #include "dir.h"
40 #include "dir2.h"
41 #include "mount.h"
42 #include "data.h"
43
44 static int dir2_block_hdr_count(void *obj, int startoff);
45 static int dir2_block_leaf_count(void *obj, int startoff);
46 static int dir2_block_leaf_offset(void *obj, int startoff, int idx);
47 static int dir2_block_tail_count(void *obj, int startoff);
48 static int dir2_block_tail_offset(void *obj, int startoff, int idx);
49 static int dir2_block_u_count(void *obj, int startoff);
50 static int dir2_block_u_offset(void *obj, int startoff, int idx);
51 static int dir2_data_union_freetag_count(void *obj, int startoff);
52 static int dir2_data_union_inumber_count(void *obj, int startoff);
53 static int dir2_data_union_length_count(void *obj, int startoff);
54 static int dir2_data_union_name_count(void *obj, int startoff);
55 static int dir2_data_union_namelen_count(void *obj, int startoff);
56 static int dir2_data_union_tag_count(void *obj, int startoff);
57 static int dir2_data_union_tag_offset(void *obj, int startoff, int idx);
58 static int dir2_data_hdr_count(void *obj, int startoff);
59 static int dir2_data_u_count(void *obj, int startoff);
60 static int dir2_data_u_offset(void *obj, int startoff, int idx);
61 static int dir2_free_bests_count(void *obj, int startoff);
62 static int dir2_free_hdr_count(void *obj, int startoff);
63 static int dir2_leaf_bests_count(void *obj, int startoff);
64 static int dir2_leaf_bests_offset(void *obj, int startoff, int idx);
65 static int dir2_leaf_ents_count(void *obj, int startoff);
66 static int dir2_leaf_hdr_count(void *obj, int startoff);
67 static int dir2_leaf_tail_count(void *obj, int startoff);
68 static int dir2_leaf_tail_offset(void *obj, int startoff, int idx);
69 static int dir2_node_btree_count(void *obj, int startoff);
70 static int dir2_node_hdr_count(void *obj, int startoff);
71
72 const field_t dir2_hfld[] = {
73 { "", FLDT_DIR2, OI(0), C1, 0, TYP_NONE },
74 { NULL }
75 };
76
77 #define BOFF(f) bitize(offsetof(xfs_dir2_block_t, f))
78 #define DOFF(f) bitize(offsetof(xfs_dir2_data_t, f))
79 #define FOFF(f) bitize(offsetof(xfs_dir2_free_t, f))
80 #define LOFF(f) bitize(offsetof(xfs_dir2_leaf_t, f))
81 #define NOFF(f) bitize(offsetof(xfs_da_intnode_t, f))
82 const field_t dir2_flds[] = {
83 { "bhdr", FLDT_DIR2_DATA_HDR, OI(BOFF(hdr)), dir2_block_hdr_count,
84 FLD_COUNT, TYP_NONE },
85 { "bu", FLDT_DIR2_DATA_UNION, dir2_block_u_offset, dir2_block_u_count,
86 FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE },
87 { "bleaf", FLDT_DIR2_LEAF_ENTRY, dir2_block_leaf_offset,
88 dir2_block_leaf_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE },
89 { "btail", FLDT_DIR2_BLOCK_TAIL, dir2_block_tail_offset,
90 dir2_block_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
91 { "dhdr", FLDT_DIR2_DATA_HDR, OI(DOFF(hdr)), dir2_data_hdr_count,
92 FLD_COUNT, TYP_NONE },
93 { "du", FLDT_DIR2_DATA_UNION, dir2_data_u_offset, dir2_data_u_count,
94 FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE },
95 { "lhdr", FLDT_DIR2_LEAF_HDR, OI(LOFF(hdr)), dir2_leaf_hdr_count,
96 FLD_COUNT, TYP_NONE },
97 { "lbests", FLDT_DIR2_DATA_OFF, dir2_leaf_bests_offset,
98 dir2_leaf_bests_count, FLD_ARRAY|FLD_OFFSET|FLD_COUNT, TYP_NONE },
99 { "lents", FLDT_DIR2_LEAF_ENTRY, OI(LOFF(ents)), dir2_leaf_ents_count,
100 FLD_ARRAY|FLD_COUNT, TYP_NONE },
101 { "ltail", FLDT_DIR2_LEAF_TAIL, dir2_leaf_tail_offset,
102 dir2_leaf_tail_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
103 { "nhdr", FLDT_DIR_NODE_HDR, OI(NOFF(hdr)), dir2_node_hdr_count,
104 FLD_COUNT, TYP_NONE },
105 { "nbtree", FLDT_DIR_NODE_ENTRY, OI(NOFF(btree)), dir2_node_btree_count,
106 FLD_ARRAY|FLD_COUNT, TYP_NONE },
107 { "fhdr", FLDT_DIR2_FREE_HDR, OI(FOFF(hdr)), dir2_free_hdr_count,
108 FLD_COUNT, TYP_NONE },
109 { "fbests", FLDT_DIR2_DATA_OFFNZ, OI(FOFF(bests)),
110 dir2_free_bests_count, FLD_ARRAY|FLD_COUNT, TYP_NONE },
111 { NULL }
112 };
113
114 #define BTOFF(f) bitize(offsetof(xfs_dir2_block_tail_t, f))
115 const field_t dir2_block_tail_flds[] = {
116 { "count", FLDT_UINT32D, OI(BTOFF(count)), C1, 0, TYP_NONE },
117 { "stale", FLDT_UINT32D, OI(BTOFF(stale)), C1, 0, TYP_NONE },
118 { NULL }
119 };
120
121 #define DFOFF(f) bitize(offsetof(xfs_dir2_data_free_t, f))
122 const field_t dir2_data_free_flds[] = {
123 { "offset", FLDT_DIR2_DATA_OFF, OI(DFOFF(offset)), C1, 0, TYP_NONE },
124 { "length", FLDT_DIR2_DATA_OFF, OI(DFOFF(length)), C1, 0, TYP_NONE },
125 { NULL }
126 };
127
128 #define DHOFF(f) bitize(offsetof(xfs_dir2_data_hdr_t, f))
129 const field_t dir2_data_hdr_flds[] = {
130 { "magic", FLDT_UINT32X, OI(DHOFF(magic)), C1, 0, TYP_NONE },
131 { "bestfree", FLDT_DIR2_DATA_FREE, OI(DHOFF(bestfree)),
132 CI(XFS_DIR2_DATA_FD_COUNT), FLD_ARRAY, TYP_NONE },
133 { NULL }
134 };
135
136 #define DEOFF(f) bitize(offsetof(xfs_dir2_data_entry_t, f))
137 #define DUOFF(f) bitize(offsetof(xfs_dir2_data_unused_t, f))
138 const field_t dir2_data_union_flds[] = {
139 { "freetag", FLDT_UINT16X, OI(DUOFF(freetag)),
140 dir2_data_union_freetag_count, FLD_COUNT, TYP_NONE },
141 { "inumber", FLDT_INO, OI(DEOFF(inumber)),
142 dir2_data_union_inumber_count, FLD_COUNT, TYP_INODE },
143 { "length", FLDT_DIR2_DATA_OFF, OI(DUOFF(length)),
144 dir2_data_union_length_count, FLD_COUNT, TYP_NONE },
145 { "namelen", FLDT_UINT8D, OI(DEOFF(namelen)),
146 dir2_data_union_namelen_count, FLD_COUNT, TYP_NONE },
147 { "name", FLDT_CHARNS, OI(DEOFF(name)), dir2_data_union_name_count,
148 FLD_COUNT, TYP_NONE },
149 { "tag", FLDT_DIR2_DATA_OFF, dir2_data_union_tag_offset,
150 dir2_data_union_tag_count, FLD_OFFSET|FLD_COUNT, TYP_NONE },
151 { NULL }
152 };
153
154 #define LEOFF(f) bitize(offsetof(xfs_dir2_leaf_entry_t, f))
155 const field_t dir2_leaf_entry_flds[] = {
156 { "hashval", FLDT_UINT32X, OI(LEOFF(hashval)), C1, 0, TYP_NONE },
157 { "address", FLDT_UINT32X, OI(LEOFF(address)), C1, 0, TYP_NONE },
158 { NULL }
159 };
160
161 #define LHOFF(f) bitize(offsetof(xfs_dir2_leaf_hdr_t, f))
162 const field_t dir2_leaf_hdr_flds[] = {
163 { "info", FLDT_DIR_BLKINFO, OI(LHOFF(info)), C1, 0, TYP_NONE },
164 { "count", FLDT_UINT16D, OI(LHOFF(count)), C1, 0, TYP_NONE },
165 { "stale", FLDT_UINT16D, OI(LHOFF(stale)), C1, 0, TYP_NONE },
166 { NULL }
167 };
168
169 #define LTOFF(f) bitize(offsetof(xfs_dir2_leaf_tail_t, f))
170 const field_t dir2_leaf_tail_flds[] = {
171 { "bestcount", FLDT_UINT32D, OI(LTOFF(bestcount)), C1, 0, TYP_NONE },
172 { NULL }
173 };
174
175 #define FHOFF(f) bitize(offsetof(xfs_dir2_free_hdr_t, f))
176 const field_t dir2_free_hdr_flds[] = {
177 { "magic", FLDT_UINT32X, OI(FHOFF(magic)), C1, 0, TYP_NONE },
178 { "firstdb", FLDT_INT32D, OI(FHOFF(firstdb)), C1, 0, TYP_NONE },
179 { "nvalid", FLDT_INT32D, OI(FHOFF(nvalid)), C1, 0, TYP_NONE },
180 { "nused", FLDT_INT32D, OI(FHOFF(nused)), C1, 0, TYP_NONE },
181 { NULL }
182 };
183
184 /*ARGSUSED*/
185 static int
186 dir2_block_hdr_count(
187 void *obj,
188 int startoff)
189 {
190 xfs_dir2_block_t *block;
191
192 ASSERT(startoff == 0);
193 block = obj;
194 return INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC;
195 }
196
197 /*ARGSUSED*/
198 static int
199 dir2_block_leaf_count(
200 void *obj,
201 int startoff)
202 {
203 xfs_dir2_block_t *block;
204 xfs_dir2_block_tail_t *btp;
205
206 ASSERT(startoff == 0);
207 block = obj;
208 if (INT_GET(block->hdr.magic, ARCH_CONVERT) != XFS_DIR2_BLOCK_MAGIC)
209 return 0;
210 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
211 return INT_GET(btp->count, ARCH_CONVERT);
212 }
213
214 /*ARGSUSED*/
215 static int
216 dir2_block_leaf_offset(
217 void *obj,
218 int startoff,
219 int idx)
220 {
221 xfs_dir2_block_t *block;
222 xfs_dir2_block_tail_t *btp;
223 xfs_dir2_leaf_entry_t *lep;
224
225 ASSERT(startoff == 0);
226 block = obj;
227 ASSERT(INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC);
228 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
229 lep = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT) + idx;
230 return bitize((int)((char *)lep - (char *)block));
231 }
232
233 /*ARGSUSED*/
234 static int
235 dir2_block_tail_count(
236 void *obj,
237 int startoff)
238 {
239 xfs_dir2_block_t *block;
240
241 ASSERT(startoff == 0);
242 block = obj;
243 return INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC;
244 }
245
246 /*ARGSUSED*/
247 static int
248 dir2_block_tail_offset(
249 void *obj,
250 int startoff,
251 int idx)
252 {
253 xfs_dir2_block_t *block;
254 xfs_dir2_block_tail_t *btp;
255
256 ASSERT(startoff == 0);
257 ASSERT(idx == 0);
258 block = obj;
259 ASSERT(INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC);
260 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
261 return bitize((int)((char *)btp - (char *)block));
262 }
263
264 /*ARGSUSED*/
265 static int
266 dir2_block_u_count(
267 void *obj,
268 int startoff)
269 {
270 xfs_dir2_block_t *block;
271 xfs_dir2_block_tail_t *btp;
272 xfs_dir2_data_entry_t *dep;
273 xfs_dir2_data_unused_t *dup;
274 char *endptr;
275 int i;
276 char *ptr;
277
278 ASSERT(startoff == 0);
279 block = obj;
280 if (INT_GET(block->hdr.magic, ARCH_CONVERT) != XFS_DIR2_BLOCK_MAGIC)
281 return 0;
282 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
283 ptr = (char *)block->u;
284 endptr = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
285 for (i = 0; ptr < endptr; i++) {
286 dup = (xfs_dir2_data_unused_t *)ptr;
287 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
288 ptr += INT_GET(dup->length, ARCH_CONVERT);
289 else {
290 dep = (xfs_dir2_data_entry_t *)ptr;
291 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
292 }
293 }
294 return i;
295 }
296
297 /*ARGSUSED*/
298 static int
299 dir2_block_u_offset(
300 void *obj,
301 int startoff,
302 int idx)
303 {
304 xfs_dir2_block_t *block;
305 xfs_dir2_block_tail_t *btp;
306 xfs_dir2_data_entry_t *dep;
307 xfs_dir2_data_unused_t *dup;
308 /*REFERENCED*/
309 char *endptr;
310 int i;
311 char *ptr;
312
313 ASSERT(startoff == 0);
314 block = obj;
315 ASSERT(INT_GET(block->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC);
316 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
317 ptr = (char *)block->u;
318 endptr = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
319 for (i = 0; i < idx; i++) {
320 ASSERT(ptr < endptr);
321 dup = (xfs_dir2_data_unused_t *)ptr;
322 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
323 ptr += INT_GET(dup->length, ARCH_CONVERT);
324 else {
325 dep = (xfs_dir2_data_entry_t *)ptr;
326 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
327 }
328 }
329 return bitize((int)(ptr - (char *)block));
330 }
331
332 static int
333 dir2_data_union_freetag_count(
334 void *obj,
335 int startoff)
336 {
337 xfs_dir2_data_unused_t *dup;
338 char *end;
339
340 ASSERT(bitoffs(startoff) == 0);
341 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
342 end = (char *)&dup->freetag + sizeof(dup->freetag);
343 return end <= (char *)obj + mp->m_dirblksize &&
344 INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG;
345 }
346
347 static int
348 dir2_data_union_inumber_count(
349 void *obj,
350 int startoff)
351 {
352 xfs_dir2_data_entry_t *dep;
353 xfs_dir2_data_unused_t *dup;
354 char *end;
355
356 ASSERT(bitoffs(startoff) == 0);
357 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
358 dep = (xfs_dir2_data_entry_t *)dup;
359 end = (char *)&dep->inumber + sizeof(dep->inumber);
360 return end <= (char *)obj + mp->m_dirblksize &&
361 INT_GET(dup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG;
362 }
363
364 static int
365 dir2_data_union_length_count(
366 void *obj,
367 int startoff)
368 {
369 xfs_dir2_data_unused_t *dup;
370 char *end;
371
372 ASSERT(bitoffs(startoff) == 0);
373 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
374 end = (char *)&dup->length + sizeof(dup->length);
375 return end <= (char *)obj + mp->m_dirblksize &&
376 INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG;
377 }
378
379 static int
380 dir2_data_union_name_count(
381 void *obj,
382 int startoff)
383 {
384 xfs_dir2_data_entry_t *dep;
385 xfs_dir2_data_unused_t *dup;
386 char *end;
387
388 ASSERT(bitoffs(startoff) == 0);
389 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
390 dep = (xfs_dir2_data_entry_t *)dup;
391 end = (char *)&dep->namelen + sizeof(dep->namelen);
392 if (end >= (char *)obj + mp->m_dirblksize ||
393 INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
394 return 0;
395 end = (char *)&dep->name[0] + dep->namelen;
396 return end <= (char *)obj + mp->m_dirblksize ? dep->namelen : 0;
397 }
398
399 static int
400 dir2_data_union_namelen_count(
401 void *obj,
402 int startoff)
403 {
404 xfs_dir2_data_entry_t *dep;
405 xfs_dir2_data_unused_t *dup;
406 char *end;
407
408 ASSERT(bitoffs(startoff) == 0);
409 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
410 dep = (xfs_dir2_data_entry_t *)dup;
411 end = (char *)&dep->namelen + sizeof(dep->namelen);
412 return end <= (char *)obj + mp->m_dirblksize &&
413 INT_GET(dup->freetag, ARCH_CONVERT) != XFS_DIR2_DATA_FREE_TAG;
414 }
415
416 static int
417 dir2_data_union_tag_count(
418 void *obj,
419 int startoff)
420 {
421 xfs_dir2_data_entry_t *dep;
422 xfs_dir2_data_unused_t *dup;
423 char *end;
424 xfs_dir2_data_off_t *tagp;
425
426 ASSERT(bitoffs(startoff) == 0);
427 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
428 dep = (xfs_dir2_data_entry_t *)dup;
429 end = (char *)&dup->freetag + sizeof(dup->freetag);
430 if (end > (char *)obj + mp->m_dirblksize)
431 return 0;
432 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
433 end = (char *)&dup->length + sizeof(dup->length);
434 if (end > (char *)obj + mp->m_dirblksize)
435 return 0;
436 tagp = XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT);
437 } else {
438 end = (char *)&dep->namelen + sizeof(dep->namelen);
439 if (end > (char *)obj + mp->m_dirblksize)
440 return 0;
441 tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
442 }
443 end = (char *)tagp + sizeof(*tagp);
444 return end <= (char *)obj + mp->m_dirblksize;
445 }
446
447 /*ARGSUSED*/
448 static int
449 dir2_data_union_tag_offset(
450 void *obj,
451 int startoff,
452 int idx)
453 {
454 xfs_dir2_data_entry_t *dep;
455 xfs_dir2_data_unused_t *dup;
456
457 ASSERT(bitoffs(startoff) == 0);
458 ASSERT(idx == 0);
459 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
460 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
461 return bitize((int)((char *)XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT) -
462 (char *)dup));
463 dep = (xfs_dir2_data_entry_t *)dup;
464 return bitize((int)((char *)XFS_DIR2_DATA_ENTRY_TAG_P(dep) -
465 (char *)dep));
466 }
467
468 /*ARGSUSED*/
469 static int
470 dir2_data_hdr_count(
471 void *obj,
472 int startoff)
473 {
474 xfs_dir2_data_t *data;
475
476 ASSERT(startoff == 0);
477 data = obj;
478 return INT_GET(data->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC;
479 }
480
481 /*ARGSUSED*/
482 static int
483 dir2_data_u_count(
484 void *obj,
485 int startoff)
486 {
487 xfs_dir2_data_t *data;
488 xfs_dir2_data_entry_t *dep;
489 xfs_dir2_data_unused_t *dup;
490 char *endptr;
491 int i;
492 char *ptr;
493
494 ASSERT(startoff == 0);
495 data = obj;
496 if (INT_GET(data->hdr.magic, ARCH_CONVERT) != XFS_DIR2_DATA_MAGIC)
497 return 0;
498 ptr = (char *)data->u;
499 endptr = (char *)data + mp->m_dirblksize;
500 for (i = 0; ptr < endptr; i++) {
501 dup = (xfs_dir2_data_unused_t *)ptr;
502 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
503 ptr += INT_GET(dup->length, ARCH_CONVERT);
504 else {
505 dep = (xfs_dir2_data_entry_t *)ptr;
506 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
507 }
508 }
509 return i;
510 }
511
512 /*ARGSUSED*/
513 static int
514 dir2_data_u_offset(
515 void *obj,
516 int startoff,
517 int idx)
518 {
519 xfs_dir2_data_t *data;
520 xfs_dir2_data_entry_t *dep;
521 xfs_dir2_data_unused_t *dup;
522 /*REFERENCED*/
523 char *endptr;
524 int i;
525 char *ptr;
526
527 ASSERT(startoff == 0);
528 data = obj;
529 ASSERT(INT_GET(data->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC);
530 ptr = (char *)data->u;
531 endptr = (char *)data + mp->m_dirblksize;
532 for (i = 0; i < idx; i++) {
533 ASSERT(ptr < endptr);
534 dup = (xfs_dir2_data_unused_t *)ptr;
535 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
536 ptr += INT_GET(dup->length, ARCH_CONVERT);
537 else {
538 dep = (xfs_dir2_data_entry_t *)ptr;
539 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
540 }
541 }
542 return bitize((int)(ptr - (char *)data));
543 }
544
545 /*ARGSUSED*/
546 int
547 dir2_data_union_size(
548 void *obj,
549 int startoff,
550 int idx)
551 {
552 xfs_dir2_data_entry_t *dep;
553 xfs_dir2_data_unused_t *dup;
554
555 ASSERT(bitoffs(startoff) == 0);
556 ASSERT(idx == 0);
557 dup = (xfs_dir2_data_unused_t *)((char *)obj + byteize(startoff));
558 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG)
559 return bitize(INT_GET(dup->length, ARCH_CONVERT));
560 else {
561 dep = (xfs_dir2_data_entry_t *)dup;
562 return bitize(XFS_DIR2_DATA_ENTSIZE(dep->namelen));
563 }
564 }
565
566 /*ARGSUSED*/
567 static int
568 dir2_free_bests_count(
569 void *obj,
570 int startoff)
571 {
572 xfs_dir2_free_t *free;
573
574 ASSERT(startoff == 0);
575 free = obj;
576 if (INT_GET(free->hdr.magic, ARCH_CONVERT) != XFS_DIR2_FREE_MAGIC)
577 return 0;
578 return INT_GET(free->hdr.nvalid, ARCH_CONVERT);
579 }
580
581 /*ARGSUSED*/
582 static int
583 dir2_free_hdr_count(
584 void *obj,
585 int startoff)
586 {
587 xfs_dir2_free_t *free;
588
589 ASSERT(startoff == 0);
590 free = obj;
591 return INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC;
592 }
593
594 /*ARGSUSED*/
595 static int
596 dir2_leaf_bests_count(
597 void *obj,
598 int startoff)
599 {
600 xfs_dir2_leaf_t *leaf;
601 xfs_dir2_leaf_tail_t *ltp;
602
603 ASSERT(startoff == 0);
604 leaf = obj;
605 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR2_LEAF1_MAGIC)
606 return 0;
607 ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
608 return INT_GET(ltp->bestcount, ARCH_CONVERT);
609 }
610
611 /*ARGSUSED*/
612 static int
613 dir2_leaf_bests_offset(
614 void *obj,
615 int startoff,
616 int idx)
617 {
618 xfs_dir2_data_off_t *lbp;
619 xfs_dir2_leaf_t *leaf;
620 xfs_dir2_leaf_tail_t *ltp;
621
622 ASSERT(startoff == 0);
623 leaf = obj;
624 ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC);
625 ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
626 lbp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT) + idx;
627 return bitize((int)((char *)lbp - (char *)leaf));
628 }
629
630 /*ARGSUSED*/
631 static int
632 dir2_leaf_ents_count(
633 void *obj,
634 int startoff)
635 {
636 xfs_dir2_leaf_t *leaf;
637
638 ASSERT(startoff == 0);
639 leaf = obj;
640 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR2_LEAF1_MAGIC &&
641 INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR2_LEAFN_MAGIC)
642 return 0;
643 return INT_GET(leaf->hdr.count, ARCH_CONVERT);
644 }
645
646 /*ARGSUSED*/
647 static int
648 dir2_leaf_hdr_count(
649 void *obj,
650 int startoff)
651 {
652 xfs_dir2_leaf_t *leaf;
653
654 ASSERT(startoff == 0);
655 leaf = obj;
656 return INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC ||
657 INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC;
658 }
659
660 /*ARGSUSED*/
661 static int
662 dir2_leaf_tail_count(
663 void *obj,
664 int startoff)
665 {
666 xfs_dir2_leaf_t *leaf;
667
668 ASSERT(startoff == 0);
669 leaf = obj;
670 return INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC;
671 }
672
673 /*ARGSUSED*/
674 static int
675 dir2_leaf_tail_offset(
676 void *obj,
677 int startoff,
678 int idx)
679 {
680 xfs_dir2_leaf_t *leaf;
681 xfs_dir2_leaf_tail_t *ltp;
682
683 ASSERT(startoff == 0);
684 ASSERT(idx == 0);
685 leaf = obj;
686 ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC);
687 ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
688 return bitize((int)((char *)ltp - (char *)leaf));
689 }
690
691 /*ARGSUSED*/
692 static int
693 dir2_node_btree_count(
694 void *obj,
695 int startoff)
696 {
697 xfs_da_intnode_t *node;
698
699 ASSERT(startoff == 0);
700 node = obj;
701 if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC)
702 return 0;
703 return INT_GET(node->hdr.count, ARCH_CONVERT);
704 }
705
706 /*ARGSUSED*/
707 static int
708 dir2_node_hdr_count(
709 void *obj,
710 int startoff)
711 {
712 xfs_da_intnode_t *node;
713
714 ASSERT(startoff == 0);
715 node = obj;
716 return INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC;
717 }
718
719 /*ARGSUSED*/
720 int
721 dir2_size(
722 void *obj,
723 int startoff,
724 int idx)
725 {
726 return bitize(mp->m_dirblksize);
727 }