]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/inode.c
2 * Copyright (c) 2000-2001 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/
47 static int inode_a_bmbt_count(void *obj
, int startoff
);
48 static int inode_a_bmx_count(void *obj
, int startoff
);
49 static int inode_a_count(void *obj
, int startoff
);
50 static int inode_a_offset(void *obj
, int startoff
, int idx
);
51 static int inode_a_sfattr_count(void *obj
, int startoff
);
52 static int inode_core_nlinkv2_count(void *obj
, int startoff
);
53 static int inode_core_onlink_count(void *obj
, int startoff
);
54 static int inode_core_projid_count(void *obj
, int startoff
);
55 static int inode_core_nlinkv1_count(void *obj
, int startoff
);
56 static int inode_f(int argc
, char **argv
);
57 static int inode_u_bmbt_count(void *obj
, int startoff
);
58 static int inode_u_bmx_count(void *obj
, int startoff
);
59 static int inode_u_c_count(void *obj
, int startoff
);
60 static int inode_u_dev_count(void *obj
, int startoff
);
61 static int inode_u_muuid_count(void *obj
, int startoff
);
62 static int inode_u_sfdir_count(void *obj
, int startoff
);
63 static int inode_u_sfdir2_count(void *obj
, int startoff
);
64 static int inode_u_symlink_count(void *obj
, int startoff
);
66 static const cmdinfo_t inode_cmd
=
67 { "inode", NULL
, inode_f
, 0, 1, 1, "[inode#]",
68 "set current inode", NULL
};
70 const field_t inode_hfld
[] = {
71 { "", FLDT_INODE
, OI(0), C1
, 0, TYP_NONE
},
75 #define OFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f))
76 const field_t inode_flds
[] = {
77 { "core", FLDT_DINODE_CORE
, OI(OFF(core
)), C1
, 0, TYP_NONE
},
78 { "next_unlinked", FLDT_AGINO
, OI(OFF(next_unlinked
)), C1
, 0,
80 { "u", FLDT_DINODE_U
, OI(OFF(u
)), C1
, 0, TYP_NONE
},
81 { "a", FLDT_DINODE_A
, inode_a_offset
, inode_a_count
,
82 FLD_COUNT
|FLD_OFFSET
, TYP_NONE
},
86 #define COFF(f) bitize(offsetof(xfs_dinode_core_t, di_ ## f))
87 const field_t inode_core_flds
[] = {
88 { "magic", FLDT_UINT16X
, OI(COFF(magic
)), C1
, 0, TYP_NONE
},
89 { "mode", FLDT_UINT16O
, OI(COFF(mode
)), C1
, 0, TYP_NONE
},
90 { "version", FLDT_INT8D
, OI(COFF(version
)), C1
, 0, TYP_NONE
},
91 { "format", FLDT_DINODE_FMT
, OI(COFF(format
)), C1
, 0, TYP_NONE
},
92 { "nlinkv1", FLDT_UINT16D
, OI(COFF(onlink
)), inode_core_nlinkv1_count
,
93 FLD_COUNT
, TYP_NONE
},
94 { "nlinkv2", FLDT_UINT32D
, OI(COFF(nlink
)), inode_core_nlinkv2_count
,
95 FLD_COUNT
, TYP_NONE
},
96 { "onlink", FLDT_UINT16D
, OI(COFF(onlink
)), inode_core_onlink_count
,
97 FLD_COUNT
, TYP_NONE
},
98 { "projid", FLDT_UINT16D
, OI(COFF(projid
)), inode_core_projid_count
,
99 FLD_COUNT
, TYP_NONE
},
100 { "uid", FLDT_UINT32D
, OI(COFF(uid
)), C1
, 0, TYP_NONE
},
101 { "gid", FLDT_UINT32D
, OI(COFF(gid
)), C1
, 0, TYP_NONE
},
102 { "atime", FLDT_TIMESTAMP
, OI(COFF(atime
)), C1
, 0, TYP_NONE
},
103 { "mtime", FLDT_TIMESTAMP
, OI(COFF(mtime
)), C1
, 0, TYP_NONE
},
104 { "ctime", FLDT_TIMESTAMP
, OI(COFF(ctime
)), C1
, 0, TYP_NONE
},
105 { "size", FLDT_FSIZE
, OI(COFF(size
)), C1
, 0, TYP_NONE
},
106 { "nblocks", FLDT_DRFSBNO
, OI(COFF(nblocks
)), C1
, 0, TYP_NONE
},
107 { "extsize", FLDT_EXTLEN
, OI(COFF(extsize
)), C1
, 0, TYP_NONE
},
108 { "nextents", FLDT_EXTNUM
, OI(COFF(nextents
)), C1
, 0, TYP_NONE
},
109 { "naextents", FLDT_AEXTNUM
, OI(COFF(anextents
)), C1
, 0, TYP_NONE
},
110 { "forkoff", FLDT_UINT8D
, OI(COFF(forkoff
)), C1
, 0, TYP_NONE
},
111 { "aformat", FLDT_DINODE_FMT
, OI(COFF(aformat
)), C1
, 0, TYP_NONE
},
112 { "dmevmask", FLDT_UINT32X
, OI(COFF(dmevmask
)), C1
, 0, TYP_NONE
},
113 { "dmstate", FLDT_UINT16D
, OI(COFF(dmstate
)), C1
, 0, TYP_NONE
},
114 { "flags", FLDT_UINT16X
, OI(COFF(flags
)), C1
, FLD_SKIPALL
, TYP_NONE
},
115 { "newrtbm", FLDT_UINT1
,
116 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_NEWRTBM_BIT
- 1), C1
,
118 { "prealloc", FLDT_UINT1
,
119 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_PREALLOC_BIT
- 1), C1
,
121 { "realtime", FLDT_UINT1
,
122 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_REALTIME_BIT
- 1), C1
,
124 { "gen", FLDT_UINT32D
, OI(COFF(gen
)), C1
, 0, TYP_NONE
},
128 #define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f))
129 const field_t timestamp_flds
[] = {
130 { "sec", FLDT_TIME
, OI(TOFF(sec
)), C1
, 0, TYP_NONE
},
131 { "nsec", FLDT_NSEC
, OI(TOFF(nsec
)), C1
, 0, TYP_NONE
},
135 const field_t inode_u_flds
[] = {
136 { "bmbt", FLDT_BMROOTD
, 0, inode_u_bmbt_count
, FLD_COUNT
, TYP_NONE
},
137 { "bmx", FLDT_BMAPBTDREC
, 0, inode_u_bmx_count
, FLD_ARRAY
|FLD_COUNT
,
139 { "c", FLDT_CHARNS
, 0, inode_u_c_count
, FLD_COUNT
, TYP_NONE
},
140 { "dev", FLDT_DEV
, 0, inode_u_dev_count
, FLD_COUNT
, TYP_NONE
},
141 { "muuid", FLDT_UUID
, 0, inode_u_muuid_count
, FLD_COUNT
, TYP_NONE
},
142 { "sfdir", FLDT_DIRSHORT
, 0, inode_u_sfdir_count
, FLD_COUNT
, TYP_NONE
},
143 { "sfdir2", FLDT_DIR2SF
, 0, inode_u_sfdir2_count
, FLD_COUNT
, TYP_NONE
},
144 { "symlink", FLDT_CHARNS
, 0, inode_u_symlink_count
, FLD_COUNT
,
149 const field_t inode_a_flds
[] = {
150 { "bmbt", FLDT_BMROOTA
, 0, inode_a_bmbt_count
, FLD_COUNT
, TYP_NONE
},
151 { "bmx", FLDT_BMAPBTAREC
, 0, inode_a_bmx_count
, FLD_ARRAY
|FLD_COUNT
,
153 { "sfattr", FLDT_ATTRSHORT
, 0, inode_a_sfattr_count
, FLD_COUNT
,
158 static const char *dinode_fmt_name
[] =
159 { "dev", "local", "extents", "btree", "uuid" };
160 static const int dinode_fmt_name_size
=
161 sizeof(dinode_fmt_name
) / sizeof(dinode_fmt_name
[0]);
179 for (i
= 0, bitpos
= bit
; i
< count
; i
++, bitpos
+= size
) {
180 f
= (xfs_dinode_fmt_t
)getbitval(obj
, bitpos
, size
, BVSIGNED
);
182 dbprintf("%d:", i
+ base
);
183 if (f
< 0 || f
>= dinode_fmt_name_size
)
184 dbprintf("%d", (int)f
);
186 dbprintf("%d (%s)", (int)f
, dinode_fmt_name
[(int)f
]);
200 ASSERT(bitoffs(startoff
) == 0);
201 ASSERT(obj
== iocur_top
->data
);
203 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
205 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
206 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_BTREE
;
216 ASSERT(bitoffs(startoff
) == 0);
217 ASSERT(obj
== iocur_top
->data
);
219 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
221 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
222 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_EXTENTS
?
223 INT_GET(dip
->di_core
.di_anextents
, ARCH_CONVERT
) : 0;
233 ASSERT(startoff
== 0);
235 return XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
);
246 ASSERT(startoff
== 0);
249 ASSERT(XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
));
250 return bitize((int)((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
));
254 inode_a_sfattr_count(
260 ASSERT(bitoffs(startoff
) == 0);
261 ASSERT(obj
== iocur_top
->data
);
263 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
265 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
266 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
;
275 xfs_attr_shortform_t
*asf
;
278 ASSERT(startoff
== 0);
281 switch (INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
)) {
282 case XFS_DINODE_FMT_LOCAL
:
283 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
);
284 return bitize((int)asf
->hdr
.totsize
);
285 case XFS_DINODE_FMT_EXTENTS
:
286 return (int)(INT_GET(dip
->di_core
.di_anextents
, ARCH_CONVERT
) * bitsz(xfs_bmbt_rec_t
));
287 case XFS_DINODE_FMT_BTREE
:
288 return bitize((int)XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
295 inode_core_nlinkv1_count(
299 xfs_dinode_core_t
*dic
;
301 ASSERT(startoff
== 0);
302 ASSERT(obj
== iocur_top
->data
);
304 return dic
->di_version
== XFS_DINODE_VERSION_1
;
308 inode_core_nlinkv2_count(
312 xfs_dinode_core_t
*dic
;
314 ASSERT(startoff
== 0);
315 ASSERT(obj
== iocur_top
->data
);
317 return dic
->di_version
== XFS_DINODE_VERSION_2
;
321 inode_core_onlink_count(
325 xfs_dinode_core_t
*dic
;
327 ASSERT(startoff
== 0);
328 ASSERT(obj
== iocur_top
->data
);
330 return dic
->di_version
== XFS_DINODE_VERSION_2
;
334 inode_core_projid_count(
338 xfs_dinode_core_t
*dic
;
340 ASSERT(startoff
== 0);
341 ASSERT(obj
== iocur_top
->data
);
343 return dic
->di_version
== XFS_DINODE_VERSION_2
;
355 ino
= strtoull(argv
[1], &p
, 0);
357 dbprintf("bad value for inode number %s\n", argv
[1]);
361 } else if (iocur_top
->ino
== NULLFSINO
)
362 dbprintf("no current inode\n");
364 dbprintf("current inode number is %lld\n", iocur_top
->ino
);
371 add_command(&inode_cmd
);
375 inode_next_type(void)
377 switch (iocur_top
->mode
& IFMT
) {
379 return XFS_DIR_IS_V2(mp
) ? TYP_DIR2
: TYP_DIR
;
383 if (iocur_top
->ino
== mp
->m_sb
.sb_rbmino
)
385 else if (iocur_top
->ino
== mp
->m_sb
.sb_rsumino
)
386 return TYP_RTSUMMARY
;
387 else if (iocur_top
->ino
== mp
->m_sb
.sb_uquotino
||
388 iocur_top
->ino
== mp
->m_sb
.sb_gquotino
)
403 return bitize(mp
->m_sb
.sb_inodesize
);
413 ASSERT(bitoffs(startoff
) == 0);
414 ASSERT(obj
== iocur_top
->data
);
416 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
417 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_BTREE
;
427 ASSERT(bitoffs(startoff
) == 0);
428 ASSERT(obj
== iocur_top
->data
);
430 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
431 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_EXTENTS
?
432 INT_GET(dip
->di_core
.di_nextents
, ARCH_CONVERT
) : 0;
442 ASSERT(bitoffs(startoff
) == 0);
443 ASSERT(obj
== iocur_top
->data
);
445 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
446 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
447 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFREG
?
448 (int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) : 0;
458 ASSERT(bitoffs(startoff
) == 0);
459 ASSERT(obj
== iocur_top
->data
);
461 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
462 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_DEV
;
472 ASSERT(bitoffs(startoff
) == 0);
473 ASSERT(obj
== iocur_top
->data
);
475 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
476 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_UUID
;
486 ASSERT(bitoffs(startoff
) == 0);
487 ASSERT(obj
== iocur_top
->data
);
489 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
490 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
491 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFDIR
492 && XFS_DIR_IS_V1(mp
);
496 inode_u_sfdir2_count(
502 ASSERT(bitoffs(startoff
) == 0);
503 ASSERT(obj
== iocur_top
->data
);
505 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
506 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
507 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFDIR
&&
519 ASSERT(startoff
== 0);
522 switch (INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
)) {
523 case XFS_DINODE_FMT_DEV
:
524 return bitsz(xfs_dev_t
);
525 case XFS_DINODE_FMT_LOCAL
:
526 return bitize((int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
));
527 case XFS_DINODE_FMT_EXTENTS
:
528 return (int)(INT_GET(dip
->di_core
.di_nextents
, ARCH_CONVERT
) * bitsz(xfs_bmbt_rec_t
));
529 case XFS_DINODE_FMT_BTREE
:
530 return bitize((int)XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
531 case XFS_DINODE_FMT_UUID
:
532 return bitsz(uuid_t
);
539 inode_u_symlink_count(
545 ASSERT(bitoffs(startoff
) == 0);
546 ASSERT(obj
== iocur_top
->data
);
548 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
549 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
550 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFLNK
?
551 (int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) : 0;
564 agno
= XFS_INO_TO_AGNO(mp
, ino
);
565 agino
= XFS_INO_TO_AGINO(mp
, ino
);
566 agbno
= XFS_AGINO_TO_AGBNO(mp
, agino
);
567 offset
= XFS_AGINO_TO_OFFSET(mp
, agino
);
568 if (agno
>= mp
->m_sb
.sb_agcount
|| agbno
>= mp
->m_sb
.sb_agblocks
||
569 offset
>= mp
->m_sb
.sb_inopblock
||
570 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
) {
571 dbprintf("bad inode number %lld\n", ino
);
576 * First set_cur to the block with the inode
577 * then use off_cur to get the right part of the buffer.
579 ASSERT(typtab
[TYP_INODE
].typnm
== TYP_INODE
);
581 /* ingore ring update here, do it explicitly below */
582 set_cur(&typtab
[TYP_INODE
], XFS_AGB_TO_DADDR(mp
, agno
, agbno
),
583 blkbb
, DB_RING_IGN
, NULL
);
584 off_cur(offset
<< mp
->m_sb
.sb_inodelog
, mp
->m_sb
.sb_inodesize
);
585 dip
= iocur_top
->data
;
586 iocur_top
->ino
= ino
;
587 iocur_top
->mode
= INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
);
588 if ((iocur_top
->mode
& IFMT
) == IFDIR
)
589 iocur_top
->dirino
= ino
;
591 /* track updated info in ring */