]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/inode.c
3b6c3df2ac80d88b3c20bec54c9154684c15355f
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/
48 static int inode_a_bmbt_count(void *obj
, int startoff
);
49 static int inode_a_bmx_count(void *obj
, int startoff
);
50 static int inode_a_count(void *obj
, int startoff
);
51 static int inode_a_offset(void *obj
, int startoff
, int idx
);
52 static int inode_a_sfattr_count(void *obj
, int startoff
);
53 static int inode_core_nlinkv2_count(void *obj
, int startoff
);
54 static int inode_core_onlink_count(void *obj
, int startoff
);
55 static int inode_core_projid_count(void *obj
, int startoff
);
56 static int inode_core_nlinkv1_count(void *obj
, int startoff
);
57 static int inode_f(int argc
, char **argv
);
58 static int inode_u_bmbt_count(void *obj
, int startoff
);
59 static int inode_u_bmx_count(void *obj
, int startoff
);
60 static int inode_u_c_count(void *obj
, int startoff
);
61 static int inode_u_dev_count(void *obj
, int startoff
);
62 static int inode_u_muuid_count(void *obj
, int startoff
);
63 static int inode_u_sfdir_count(void *obj
, int startoff
);
64 static int inode_u_sfdir2_count(void *obj
, int startoff
);
65 static int inode_u_symlink_count(void *obj
, int startoff
);
67 static const cmdinfo_t inode_cmd
=
68 { "inode", NULL
, inode_f
, 0, 1, 1, "[inode#]",
69 "set current inode", NULL
};
71 const field_t inode_hfld
[] = {
72 { "", FLDT_INODE
, OI(0), C1
, 0, TYP_NONE
},
76 #define OFF(f) bitize(offsetof(xfs_dinode_t, di_ ## f))
77 const field_t inode_flds
[] = {
78 { "core", FLDT_DINODE_CORE
, OI(OFF(core
)), C1
, 0, TYP_NONE
},
79 { "next_unlinked", FLDT_AGINO
, OI(OFF(next_unlinked
)), C1
, 0,
81 { "u", FLDT_DINODE_U
, OI(OFF(u
)), C1
, 0, TYP_NONE
},
82 { "a", FLDT_DINODE_A
, inode_a_offset
, inode_a_count
,
83 FLD_COUNT
|FLD_OFFSET
, TYP_NONE
},
87 #define COFF(f) bitize(offsetof(xfs_dinode_core_t, di_ ## f))
88 const field_t inode_core_flds
[] = {
89 { "magic", FLDT_UINT16X
, OI(COFF(magic
)), C1
, 0, TYP_NONE
},
90 { "mode", FLDT_UINT16O
, OI(COFF(mode
)), C1
, 0, TYP_NONE
},
91 { "version", FLDT_INT8D
, OI(COFF(version
)), C1
, 0, TYP_NONE
},
92 { "format", FLDT_DINODE_FMT
, OI(COFF(format
)), C1
, 0, TYP_NONE
},
93 { "nlinkv1", FLDT_UINT16D
, OI(COFF(onlink
)), inode_core_nlinkv1_count
,
94 FLD_COUNT
, TYP_NONE
},
95 { "nlinkv2", FLDT_UINT32D
, OI(COFF(nlink
)), inode_core_nlinkv2_count
,
96 FLD_COUNT
, TYP_NONE
},
97 { "onlink", FLDT_UINT16D
, OI(COFF(onlink
)), inode_core_onlink_count
,
98 FLD_COUNT
, TYP_NONE
},
99 { "projid", FLDT_UINT16D
, OI(COFF(projid
)), inode_core_projid_count
,
100 FLD_COUNT
, TYP_NONE
},
101 { "uid", FLDT_UINT32D
, OI(COFF(uid
)), C1
, 0, TYP_NONE
},
102 { "gid", FLDT_UINT32D
, OI(COFF(gid
)), C1
, 0, TYP_NONE
},
103 { "atime", FLDT_TIMESTAMP
, OI(COFF(atime
)), C1
, 0, TYP_NONE
},
104 { "mtime", FLDT_TIMESTAMP
, OI(COFF(mtime
)), C1
, 0, TYP_NONE
},
105 { "ctime", FLDT_TIMESTAMP
, OI(COFF(ctime
)), C1
, 0, TYP_NONE
},
106 { "size", FLDT_FSIZE
, OI(COFF(size
)), C1
, 0, TYP_NONE
},
107 { "nblocks", FLDT_DRFSBNO
, OI(COFF(nblocks
)), C1
, 0, TYP_NONE
},
108 { "extsize", FLDT_EXTLEN
, OI(COFF(extsize
)), C1
, 0, TYP_NONE
},
109 { "nextents", FLDT_EXTNUM
, OI(COFF(nextents
)), C1
, 0, TYP_NONE
},
110 { "naextents", FLDT_AEXTNUM
, OI(COFF(anextents
)), C1
, 0, TYP_NONE
},
111 { "forkoff", FLDT_UINT8D
, OI(COFF(forkoff
)), C1
, 0, TYP_NONE
},
112 { "aformat", FLDT_DINODE_FMT
, OI(COFF(aformat
)), C1
, 0, TYP_NONE
},
113 { "dmevmask", FLDT_UINT32X
, OI(COFF(dmevmask
)), C1
, 0, TYP_NONE
},
114 { "dmstate", FLDT_UINT16D
, OI(COFF(dmstate
)), C1
, 0, TYP_NONE
},
115 { "flags", FLDT_UINT16X
, OI(COFF(flags
)), C1
, FLD_SKIPALL
, TYP_NONE
},
116 { "newrtbm", FLDT_UINT1
,
117 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_NEWRTBM_BIT
- 1), C1
,
119 { "prealloc", FLDT_UINT1
,
120 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_PREALLOC_BIT
- 1), C1
,
122 { "realtime", FLDT_UINT1
,
123 OI(COFF(flags
) + bitsz(__uint16_t
) - XFS_DIFLAG_REALTIME_BIT
- 1), C1
,
125 { "gen", FLDT_UINT32D
, OI(COFF(gen
)), C1
, 0, TYP_NONE
},
129 #define TOFF(f) bitize(offsetof(xfs_timestamp_t, t_ ## f))
130 const field_t timestamp_flds
[] = {
131 { "sec", FLDT_TIME
, OI(TOFF(sec
)), C1
, 0, TYP_NONE
},
132 { "nsec", FLDT_NSEC
, OI(TOFF(nsec
)), C1
, 0, TYP_NONE
},
136 const field_t inode_u_flds
[] = {
137 { "bmbt", FLDT_BMROOTD
, 0, inode_u_bmbt_count
, FLD_COUNT
, TYP_NONE
},
138 { "bmx", FLDT_BMAPBTDREC
, 0, inode_u_bmx_count
, FLD_ARRAY
|FLD_COUNT
,
140 { "c", FLDT_CHARNS
, 0, inode_u_c_count
, FLD_COUNT
, TYP_NONE
},
141 { "dev", FLDT_DEV
, 0, inode_u_dev_count
, FLD_COUNT
, TYP_NONE
},
142 { "muuid", FLDT_UUID
, 0, inode_u_muuid_count
, FLD_COUNT
, TYP_NONE
},
143 { "sfdir", FLDT_DIRSHORT
, 0, inode_u_sfdir_count
, FLD_COUNT
, TYP_NONE
},
144 { "sfdir2", FLDT_DIR2SF
, 0, inode_u_sfdir2_count
, FLD_COUNT
, TYP_NONE
},
145 { "symlink", FLDT_CHARNS
, 0, inode_u_symlink_count
, FLD_COUNT
,
150 const field_t inode_a_flds
[] = {
151 { "bmbt", FLDT_BMROOTA
, 0, inode_a_bmbt_count
, FLD_COUNT
, TYP_NONE
},
152 { "bmx", FLDT_BMAPBTAREC
, 0, inode_a_bmx_count
, FLD_ARRAY
|FLD_COUNT
,
154 { "sfattr", FLDT_ATTRSHORT
, 0, inode_a_sfattr_count
, FLD_COUNT
,
159 static const char *dinode_fmt_name
[] =
160 { "dev", "local", "extents", "btree", "uuid" };
161 static const int dinode_fmt_name_size
=
162 sizeof(dinode_fmt_name
) / sizeof(dinode_fmt_name
[0]);
180 for (i
= 0, bitpos
= bit
; i
< count
; i
++, bitpos
+= size
) {
181 f
= (xfs_dinode_fmt_t
)getbitval(obj
, bitpos
, size
, BVSIGNED
);
183 dbprintf("%d:", i
+ base
);
184 if (f
< 0 || f
>= dinode_fmt_name_size
)
185 dbprintf("%d", (int)f
);
187 dbprintf("%d (%s)", (int)f
, dinode_fmt_name
[(int)f
]);
201 ASSERT(bitoffs(startoff
) == 0);
202 ASSERT(obj
== iocur_top
->data
);
204 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
206 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
207 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_BTREE
;
217 ASSERT(bitoffs(startoff
) == 0);
218 ASSERT(obj
== iocur_top
->data
);
220 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
222 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
223 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_EXTENTS
?
224 INT_GET(dip
->di_core
.di_anextents
, ARCH_CONVERT
) : 0;
234 ASSERT(startoff
== 0);
236 return XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
);
247 ASSERT(startoff
== 0);
250 ASSERT(XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
));
251 return bitize((int)((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
));
255 inode_a_sfattr_count(
261 ASSERT(bitoffs(startoff
) == 0);
262 ASSERT(obj
== iocur_top
->data
);
264 if (!XFS_DFORK_Q_ARCH(dip
, ARCH_CONVERT
))
266 ASSERT((char *)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
) - (char *)dip
== byteize(startoff
));
267 return INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
;
276 xfs_attr_shortform_t
*asf
;
279 ASSERT(startoff
== 0);
282 switch (INT_GET(dip
->di_core
.di_aformat
, ARCH_CONVERT
)) {
283 case XFS_DINODE_FMT_LOCAL
:
284 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
);
285 return bitize((int)asf
->hdr
.totsize
);
286 case XFS_DINODE_FMT_EXTENTS
:
287 return (int)(INT_GET(dip
->di_core
.di_anextents
, ARCH_CONVERT
) * bitsz(xfs_bmbt_rec_t
));
288 case XFS_DINODE_FMT_BTREE
:
289 return bitize((int)XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
296 inode_core_nlinkv1_count(
300 xfs_dinode_core_t
*dic
;
302 ASSERT(startoff
== 0);
303 ASSERT(obj
== iocur_top
->data
);
305 return dic
->di_version
== XFS_DINODE_VERSION_1
;
309 inode_core_nlinkv2_count(
313 xfs_dinode_core_t
*dic
;
315 ASSERT(startoff
== 0);
316 ASSERT(obj
== iocur_top
->data
);
318 return dic
->di_version
== XFS_DINODE_VERSION_2
;
322 inode_core_onlink_count(
326 xfs_dinode_core_t
*dic
;
328 ASSERT(startoff
== 0);
329 ASSERT(obj
== iocur_top
->data
);
331 return dic
->di_version
== XFS_DINODE_VERSION_2
;
335 inode_core_projid_count(
339 xfs_dinode_core_t
*dic
;
341 ASSERT(startoff
== 0);
342 ASSERT(obj
== iocur_top
->data
);
344 return dic
->di_version
== XFS_DINODE_VERSION_2
;
356 ino
= strtoull(argv
[1], &p
, 0);
358 dbprintf("bad value for inode number %s\n", argv
[1]);
362 } else if (iocur_top
->ino
== NULLFSINO
)
363 dbprintf("no current inode\n");
365 dbprintf("current inode number is %lld\n", iocur_top
->ino
);
372 add_command(&inode_cmd
);
376 inode_next_type(void)
378 switch (iocur_top
->mode
& IFMT
) {
380 return XFS_DIR_IS_V2(mp
) ? TYP_DIR2
: TYP_DIR
;
384 if (iocur_top
->ino
== mp
->m_sb
.sb_rbmino
)
386 else if (iocur_top
->ino
== mp
->m_sb
.sb_rsumino
)
387 return TYP_RTSUMMARY
;
388 else if (iocur_top
->ino
== mp
->m_sb
.sb_uquotino
||
389 iocur_top
->ino
== mp
->m_sb
.sb_gquotino
)
404 return bitize(mp
->m_sb
.sb_inodesize
);
414 ASSERT(bitoffs(startoff
) == 0);
415 ASSERT(obj
== iocur_top
->data
);
417 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
418 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_BTREE
;
428 ASSERT(bitoffs(startoff
) == 0);
429 ASSERT(obj
== iocur_top
->data
);
431 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
432 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_EXTENTS
?
433 INT_GET(dip
->di_core
.di_nextents
, ARCH_CONVERT
) : 0;
443 ASSERT(bitoffs(startoff
) == 0);
444 ASSERT(obj
== iocur_top
->data
);
446 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
447 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
448 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFREG
?
449 (int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) : 0;
459 ASSERT(bitoffs(startoff
) == 0);
460 ASSERT(obj
== iocur_top
->data
);
462 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
463 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_DEV
;
473 ASSERT(bitoffs(startoff
) == 0);
474 ASSERT(obj
== iocur_top
->data
);
476 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
477 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_UUID
;
487 ASSERT(bitoffs(startoff
) == 0);
488 ASSERT(obj
== iocur_top
->data
);
490 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
491 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
492 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFDIR
493 && XFS_DIR_IS_V1(mp
);
497 inode_u_sfdir2_count(
503 ASSERT(bitoffs(startoff
) == 0);
504 ASSERT(obj
== iocur_top
->data
);
506 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
507 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
508 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFDIR
&&
520 ASSERT(startoff
== 0);
523 switch (INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
)) {
524 case XFS_DINODE_FMT_DEV
:
525 return bitsz(xfs_dev_t
);
526 case XFS_DINODE_FMT_LOCAL
:
527 return bitize((int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
));
528 case XFS_DINODE_FMT_EXTENTS
:
529 return (int)(INT_GET(dip
->di_core
.di_nextents
, ARCH_CONVERT
) * bitsz(xfs_bmbt_rec_t
));
530 case XFS_DINODE_FMT_BTREE
:
531 return bitize((int)XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
532 case XFS_DINODE_FMT_UUID
:
533 return bitsz(uuid_t
);
540 inode_u_symlink_count(
546 ASSERT(bitoffs(startoff
) == 0);
547 ASSERT(obj
== iocur_top
->data
);
549 ASSERT((char *)&dip
->di_u
- (char *)dip
== byteize(startoff
));
550 return INT_GET(dip
->di_core
.di_format
, ARCH_CONVERT
) == XFS_DINODE_FMT_LOCAL
&&
551 (INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
) & IFMT
) == IFLNK
?
552 (int)INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) : 0;
565 agno
= XFS_INO_TO_AGNO(mp
, ino
);
566 agino
= XFS_INO_TO_AGINO(mp
, ino
);
567 agbno
= XFS_AGINO_TO_AGBNO(mp
, agino
);
568 offset
= XFS_AGINO_TO_OFFSET(mp
, agino
);
569 if (agno
>= mp
->m_sb
.sb_agcount
|| agbno
>= mp
->m_sb
.sb_agblocks
||
570 offset
>= mp
->m_sb
.sb_inopblock
||
571 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
) {
572 dbprintf("bad inode number %lld\n", ino
);
577 * First set_cur to the block with the inode
578 * then use off_cur to get the right part of the buffer.
580 ASSERT(typtab
[TYP_INODE
].typnm
== TYP_INODE
);
582 /* ingore ring update here, do it explicitly below */
583 set_cur(&typtab
[TYP_INODE
], XFS_AGB_TO_DADDR(mp
, agno
, agbno
),
584 blkbb
, DB_RING_IGN
, NULL
);
585 off_cur(offset
<< mp
->m_sb
.sb_inodelog
, mp
->m_sb
.sb_inodesize
);
586 dip
= iocur_top
->data
;
587 iocur_top
->ino
= ino
;
588 iocur_top
->mode
= INT_GET(dip
->di_core
.di_mode
, ARCH_CONVERT
);
589 if ((iocur_top
->mode
& IFMT
) == IFDIR
)
590 iocur_top
->dirino
= ino
;
592 /* track updated info in ring */