/src/sleuthkit/tsk/fs/tsk_xfs.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** The Sleuth Kit |
3 | | ** |
4 | | ** Brian Carrier [carrier <at> sleuthkit [dot] org] |
5 | | ** Copyright (c) 2003-2011 Brian Carrier. All rights reserved |
6 | | ** |
7 | | ** ICS Laboratory [515lab.ics <at> gmail [dot] com] |
8 | | ** Copyright (c) 2019 ICS Laboratory. All rights reserved. |
9 | | ** |
10 | | ** This software is distributed under the Common Public License 1.0 |
11 | | */ |
12 | | |
13 | | #ifndef _TSK_XFS_H |
14 | | #define _TSK_XFS_H |
15 | | #endif |
16 | | |
17 | | #include <stdbool.h> |
18 | | #include <stddef.h> |
19 | | |
20 | | #ifdef __cplusplus |
21 | | extern "C" { |
22 | | #endif |
23 | | |
24 | | typedef int64_t xfs_off_t; /* <file offset> type */ |
25 | | typedef uint32_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ |
26 | | typedef uint64_t XFS_AGNUM_T; |
27 | | typedef uint32_t xfs_dir2_data_aoff_t; /* argument form */ |
28 | | typedef uint32_t xfs_dir2_dataptr_t; |
29 | | |
30 | | #ifdef _MSC_VER |
31 | | // For MSVC |
32 | | #define __round_mask(x, y) ((x) < (y) ? 0 : ((y) - 1)) |
33 | | #else |
34 | | // For GCC |
35 | 0 | #define __round_mask(x, y) ((__typeof__(x))((y) - 1)) |
36 | | #endif |
37 | 0 | #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) |
38 | | |
39 | | #define XFS_MIN_AG_BLOCKS 64 |
40 | | // for checking filesystem sanity checking |
41 | | #define XFS_MAX_DBLOCKS(fs, s) ( \ |
42 | | tsk_getu32(&(fs->endian), (s)->sb_agcount) * \ |
43 | | tsk_getu32(&(fs->endian), (s)->sb_agblocks)) |
44 | | |
45 | | #define XFS_MIN_DBLOCKS(fs, s) ( \ |
46 | | (tsk_getu32(&(fs->endian), ((s)->sb_agcount)) - 1) * \ |
47 | | tsk_getu32(&(fs->endian), (s)->sb_agblocks) + XFS_MIN_AG_BLOCKS) |
48 | | |
49 | | |
50 | | /* |
51 | | * masks with n high/low bits set, 64-bit values |
52 | | */ |
53 | | static inline uint64_t xfs_mask64hi(int n) |
54 | 0 | { |
55 | 0 | return (uint64_t)-1 << (64 - (n)); |
56 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_mask64hi(int) Unexecuted instantiation: xfs_dent.cpp:xfs_mask64hi(int) |
57 | | |
58 | | static inline uint32_t xfs_mask32lo(int n) |
59 | 0 | { |
60 | 0 | return ((uint32_t)1 << (n)) - 1; |
61 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_mask32lo(int) Unexecuted instantiation: xfs_dent.cpp:xfs_mask32lo(int) |
62 | | |
63 | | static inline uint64_t xfs_mask64lo(int n) |
64 | 0 | { |
65 | 0 | return ((uint64_t)1 << (n)) - 1; |
66 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_mask64lo(int) Unexecuted instantiation: xfs_dent.cpp:xfs_mask64lo(int) |
67 | | |
68 | | |
69 | | #define XFS_FSB_TO_AGNO(xfs,fsbno) \ |
70 | 0 | ((uint32_t)((fsbno) >> (xfs)->fs->sb_agblklog)) |
71 | | |
72 | | #define XFS_FSB_TO_AGBNO(xfs,fsbno) \ |
73 | 0 | ((uint32_t)((fsbno) & xfs_mask32lo((xfs)->fs->sb_agblklog))) |
74 | | |
75 | | #define XFS_FSB_TO_SECNO(xfs,fsbno) \ |
76 | | ((uint32_t)((fsbno) & xfs_mask32lo((xfs)->fs->sb_agblklog))) |
77 | | |
78 | 0 | #define XFS_MAXNAMELEN 255 |
79 | | |
80 | | #define XFS_INODE_CORE_SIZE_VER4 96 |
81 | 0 | #define XFS_INODE_CORE_SIZE_VER5 176 |
82 | | |
83 | | /* |
84 | | * Bmap btree record and extent descriptor. |
85 | | * l0:63 is an extent flag (value 1 indicates non-normal). |
86 | | * l0:9-62 are startoff. |
87 | | * l0:0-8 and l1:21-63 are startblock. |
88 | | * l1:0-20 are blockcount. |
89 | | */ |
90 | 0 | #define BMBT_EXNTFLAG_BITLEN 1 |
91 | | #define BMBT_STARTOFF_BITLEN 54 |
92 | | #define BMBT_STARTBLOCK_BITLEN 52 |
93 | | #define BMBT_BLOCKCOUNT_BITLEN 21 |
94 | | |
95 | | #define XFS_CONTENT_LEN_V4(xfs) (tsk_getu16((xfs)->fs_info.endian, (xfs)->fs->sb_inodesize) - XFS_INODE_CORE_SIZE_VER4) |
96 | 0 | #define XFS_CONTENT_LEN_V5(xfs) (tsk_getu16((xfs)->fs_info.endian, (xfs)->fs->sb_inodesize) - XFS_INODE_CORE_SIZE_VER5) |
97 | | |
98 | | /* |
99 | | * Minimum and maximum blocksize and sectorsize. |
100 | | * The blocksize upper limit is pretty much arbitrary. |
101 | | * The sectorsize upper limit is due to sizeof(sb_sectsize). |
102 | | * CRC enable filesystems use 512 byte inodes, meaning 512 byte block sizes |
103 | | * cannot be used. |
104 | | */ |
105 | | #define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ |
106 | | #define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ |
107 | | #define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) |
108 | | #define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) |
109 | | #define XFS_MIN_CRC_BLOCKSIZE (1 << (XFS_MIN_BLOCKSIZE_LOG + 1)) |
110 | | #define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ |
111 | | #define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ |
112 | | #define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) |
113 | | #define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) |
114 | | |
115 | | /* |
116 | | * Inode minimum and maximum sizes. |
117 | | */ |
118 | | #define XFS_DINODE_MIN_LOG 8 |
119 | | #define XFS_DINODE_MAX_LOG 11 |
120 | | #define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG) |
121 | | #define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG) |
122 | | |
123 | | // XFS Log (journal) constants |
124 | | #define XLOG_MIN_ICLOGS 2 |
125 | | #define XLOG_MAX_ICLOGS 8 |
126 | | #define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe /* Invalid cycle number */ |
127 | | #define XLOG_VERSION_1 1 |
128 | | #define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */ |
129 | | #define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2) |
130 | | #define XLOG_MIN_RECORD_BSIZE (16*1024) /* eventually 32k */ |
131 | | #define XLOG_BIG_RECORD_BSIZE (32*1024) /* 32k buffers */ |
132 | | #define XLOG_MAX_RECORD_BSIZE (256*1024) |
133 | | #define XLOG_HEADER_CYCLE_SIZE (32*1024) /* cycle data in header */ |
134 | | #define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */ |
135 | | #define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */ |
136 | | #define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */ |
137 | | #define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \ |
138 | | (log)->l_mp->m_sb.sb_logsunit) |
139 | | #define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit) |
140 | | #define XLOG_HEADER_SIZE 512 |
141 | | |
142 | | /* Minimum number of transactions that must fit in the log (defined by mkfs) */ |
143 | | #define XFS_MIN_LOG_FACTOR 3 |
144 | | |
145 | | /* |
146 | | * RealTime Device format definitions |
147 | | */ |
148 | | |
149 | | /* Min and max rt extent sizes, specified in bytes */ |
150 | | #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ |
151 | | #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ |
152 | | #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ |
153 | | |
154 | | // start offset of superblock |
155 | 0 | #define XFS_SBOFF 0 |
156 | | |
157 | | // fs magicnumber |
158 | 0 | #define XFS_FS_MAGIC 0x58465342 |
159 | | |
160 | | // first inode number |
161 | 0 | #define XFS_FIRSTINO 0 // it |
162 | | |
163 | | // superblock related constants & macros |
164 | | // sb version |
165 | | #define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ |
166 | | #define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ |
167 | | #define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ |
168 | | #define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ |
169 | | #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ |
170 | | |
171 | | #define XFS_SB_FEAT_COMPAT_ALL 0 |
172 | | #define XFS_SB_FEAT_COMPAT_UNKNOWN ~XFS_SB_FEAT_COMPAT_ALL |
173 | | // sb version checker |
174 | | |
175 | | |
176 | | // sb version bitmask |
177 | | #define XFS_SB_VERSION_NUMBITS 0x000f |
178 | | #define XFS_SB_VERSION_ALLFBITS 0xfff0 |
179 | | #define XFS_SB_VERSION_ATTRBIT 0x0010 |
180 | | #define XFS_SB_VERSION_NLINKBIT 0x0020 |
181 | | #define XFS_SB_VERSION_QUOTABIT 0x0040 |
182 | | #define XFS_SB_VERSION_ALIGNBIT 0x0080 |
183 | | #define XFS_SB_VERSION_DALIGNBIT 0x0100 |
184 | | #define XFS_SB_VERSION_SHAREDBIT 0x0200 |
185 | | #define XFS_SB_VERSION_LOGV2BIT 0x0400 |
186 | | #define XFS_SB_VERSION_SECTORBIT 0x0800 |
187 | | #define XFS_SB_VERSION_EXTFLGBIT 0x1000 |
188 | | #define XFS_SB_VERSION_DIRV2BIT 0x2000 |
189 | | #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ |
190 | | #define XFS_SB_VERSION_MOREBITSBIT 0x8000 |
191 | | |
192 | | // Checking if sb has compat feature |
193 | | |
194 | | |
195 | | // superblock feature ro compat: for normal blocks |
196 | 0 | #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ |
197 | 0 | #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ |
198 | 0 | #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ |
199 | | #define XFS_SB_FEAT_RO_COMPAT_ALL \ |
200 | | (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ |
201 | | XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ |
202 | | XFS_SB_FEAT_RO_COMPAT_REFLINK) |
203 | | #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL |
204 | | |
205 | | |
206 | | // superblock feature ro compat: for journal |
207 | 0 | #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ |
208 | 0 | #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ |
209 | 0 | #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ |
210 | | #define XFS_SB_FEAT_INCOMPAT_ALL \ |
211 | | (XFS_SB_FEAT_INCOMPAT_FTYPE| \ |
212 | | XFS_SB_FEAT_INCOMPAT_SPINODES| \ |
213 | | XFS_SB_FEAT_INCOMPAT_META_UUID) |
214 | | #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL |
215 | | |
216 | | #define XFS_SB_FEAT_INCOMPAT_LOG_ALL 0 |
217 | | #define XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_LOG_ALL |
218 | | |
219 | | #define XFS_HAS_INCOMPAT_FEATURE(fs, sb, mask)\ |
220 | | ((tsk_fs_guessu32(fs->endian, sb->sb_features_incompat) & mask) != 0) |
221 | | /* |
222 | | static inline bool xfs_sb_has_incompat_feature( |
223 | | struct xfs_sb *sbp, |
224 | | uint32_t feature) |
225 | | { |
226 | | return !tsk_fs_guessu32(sbp->sb_features_incompat & feature, 0); |
227 | | } |
228 | | */ |
229 | | #define XFS_HAS_INCOMPAT_LOG_FEATURE(fs, sb, mask)\ |
230 | | ((tsk_fs_guessu32(fs->endian, sb->sb_features_log_incompat) & mask) != 0) |
231 | | /* |
232 | | static inline bool xfs_sb_has_incompat_log_feature( |
233 | | struct xfs_sb *sbp, |
234 | | uint32_t feature) |
235 | | { |
236 | | return !tsk_fs_guessu32(sbp->sb_features_log_incompat & feature, 0); |
237 | | } |
238 | | */ |
239 | | // Macros |
240 | | // crc offset of sb |
241 | | #define XFS_SB_CRC_OFF offsetof(struct xfs_sb, sb_crc) |
242 | | |
243 | 0 | #define XFS_DIR3_FT_UNKNOWN 0 |
244 | | #define XFS_DIR3_FT_REG_FILE 1 |
245 | | #define XFS_DIR3_FT_DIR 2 |
246 | | #define XFS_DIR3_FT_CHRDEV 3 |
247 | | #define XFS_DIR3_FT_BLKDEV 4 |
248 | | #define XFS_DIR3_FT_FIFO 5 |
249 | | #define XFS_DIR3_FT_SOCK 6 |
250 | | #define XFS_DIR3_FT_SYMLINK 7 |
251 | | #define XFS_DIR3_FT_WHT 8 |
252 | 0 | #define XFS_DIR3_FT_MAX 9 |
253 | | |
254 | | /* |
255 | | * For special situations, the dirent size ends up fixed because we always know |
256 | | * what the size of the entry is. That's true for the "." and "..", and |
257 | | * therefore we know that they are a fixed size and hence their offsets are |
258 | | * constant, as is the first entry. |
259 | | * |
260 | | * Hence, this calculation is written as a macro to be able to be calculated at |
261 | | * compile time and so certain offsets can be calculated directly in the |
262 | | * structure initaliser via the macro. There are two macros - one for dirents |
263 | | * with ftype and without so there are no unresolvable conditionals in the |
264 | | * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power |
265 | | * of 2 and the compiler doesn't reject it (unlike roundup()). |
266 | | */ |
267 | | #define XFS_DIR2_DATA_ENTSIZE(n) \ |
268 | | round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ |
269 | | sizeof(uint16_t)), XFS_DIR2_DATA_ALIGN) |
270 | | |
271 | | #define XFS_DIR3_DATA_ENTSIZE(n) \ |
272 | 0 | round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \ |
273 | 0 | sizeof(uint16_t) + sizeof(uint8_t)), \ |
274 | 0 | XFS_DIR2_DATA_ALIGN) |
275 | | |
276 | | /* |
277 | | Superblock - Must be padded to 64 bit alignment. |
278 | | */ |
279 | | typedef struct xfs_sb { |
280 | | uint8_t sb_magicnum[4]; /* magic number == XFS_SB_MAGIC */ |
281 | | uint8_t sb_blocksize[4]; /* logical block size, bytes */ |
282 | | uint8_t sb_dblocks[8]; /* number of data blocks */ |
283 | | uint8_t sb_rblocks[8]; /* number of realtime blocks */ |
284 | | uint8_t sb_rextents[8]; /* number of realtime extents */ |
285 | | uint8_t sb_uuid[16]; /* user-visible file system unique id */ |
286 | | uint8_t sb_logstart[8]; /* starting block of log if internal */ |
287 | | uint8_t sb_rootino[8]; /* root inode number */ |
288 | | uint8_t sb_rbmino[8]; /* bitmap inode for realtime extents */ |
289 | | uint8_t sb_rsumino[8]; /* summary inode for rt bitmap */ |
290 | | uint8_t sb_rextsize[4]; /* realtime extent size, blocks */ |
291 | | uint8_t sb_agblocks[4]; /* size of an allocation group */ |
292 | | uint8_t sb_agcount[4]; /* number of allocation groups */ |
293 | | uint8_t sb_rbmblocks[4]; /* number of rt bitmap blocks */ |
294 | | uint8_t sb_logblocks[4]; /* number of log blocks */ |
295 | | uint8_t sb_versionnum[2]; /* header version == XFS_SB_VERSION */ |
296 | | uint8_t sb_sectsize[2]; /* volume sector size, bytes */ |
297 | | uint8_t sb_inodesize[2]; /* inode size, bytes */ |
298 | | uint8_t sb_inopblock[2]; /* inodes per block */ |
299 | | char sb_fname[12]; /* file system name */ |
300 | | uint8_t sb_blocklog; /* log2 of sb_blocksize */ |
301 | | uint8_t sb_sectlog; /* log2 of sb_sectsize */ |
302 | | uint8_t sb_inodelog; /* log2 of sb_inodesize */ |
303 | | uint8_t sb_inopblog; /* log2 of sb_inopblock */ |
304 | | uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ |
305 | | uint8_t sb_rextslog; /* log2 of sb_rextents */ |
306 | | uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ |
307 | | uint8_t sb_imax_pct; /* max % of fs for inode space */ |
308 | | /* statistics */ |
309 | | /* |
310 | | * These fields must remain contiguous. If you really |
311 | | * want to change their layout, make sure you fix the |
312 | | * code in xfs_trans_apply_sb_deltas(). |
313 | | */ |
314 | | uint8_t sb_icount[8]; /* allocated inodes */ |
315 | | uint8_t sb_ifree[8]; /* free inodes */ |
316 | | uint8_t sb_fdblocks[8]; /* free data blocks */ |
317 | | uint8_t sb_frextents[8]; /* free realtime extents */ |
318 | | /* |
319 | | * End contiguous fields. |
320 | | */ |
321 | | uint8_t sb_uquotino[8]; /* user quota inode */ |
322 | | uint8_t sb_gquotino[8]; /* group quota inode */ |
323 | | uint8_t sb_qflags[2]; /* quota flags */ |
324 | | uint8_t sb_flags; /* misc. flags */ |
325 | | uint8_t sb_shared_vn; /* shared version number */ |
326 | | uint8_t sb_inoalignmt[4]; /* inode chunk alignment, fsblocks */ |
327 | | uint8_t sb_unit[4]; /* stripe or raid unit */ |
328 | | uint8_t sb_width[4]; /* stripe or raid width */ |
329 | | uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ |
330 | | uint8_t sb_logsectlog; /* log2 of the log sector size */ |
331 | | uint8_t sb_logsectsize[2]; /* sector size for the log, bytes */ |
332 | | uint8_t sb_logsunit[4]; /* stripe unit size for the log */ |
333 | | uint8_t sb_features2[4]; /* additional feature bits */ |
334 | | /* |
335 | | * bad features2 field as a result of failing to pad the sb |
336 | | * structure to 64 bits. Some machines will be using this field |
337 | | * for features2 bits. Easiest just to mark it bad and not use |
338 | | * it for anything else. |
339 | | */ |
340 | | uint8_t sb_bad_features2[4]; |
341 | | |
342 | | /* version 5 superblock fields start here */ |
343 | | |
344 | | /* feature masks */ |
345 | | uint8_t sb_features_compat[4]; |
346 | | uint8_t sb_features_ro_compat[4]; |
347 | | uint8_t sb_features_incompat[4]; |
348 | | uint8_t sb_features_log_incompat[4]; |
349 | | |
350 | | uint8_t sb_crc[4]; /* superblock crc:: ->little endian<- */ |
351 | | uint8_t sb_spino_align[4]; /* sparse inode chunk alignment */ |
352 | | |
353 | | uint8_t sb_pquotino[8]; /* project quota inode */ |
354 | | uint8_t sb_lsn[8]; /* last write sequence */ |
355 | | uint8_t sb_meta_uuid[16]; /* metadata file system unique id */ |
356 | | |
357 | | /* must be padded to 64 bit alignment */ |
358 | | } xfs_sb; |
359 | | |
360 | | /* Journal Info */ |
361 | | typedef struct { |
362 | | |
363 | | TSK_FS_FILE *fs_file; |
364 | | TSK_INUM_T j_inum; |
365 | | |
366 | | uint32_t bsize; |
367 | | TSK_DADDR_T first_block; |
368 | | TSK_DADDR_T last_block; |
369 | | |
370 | | uint32_t start_seq; |
371 | | TSK_DADDR_T start_blk; |
372 | | |
373 | | } XFS_JINFO; |
374 | | |
375 | | /* |
376 | | * Structure of an XFS file system handle. |
377 | | */ |
378 | | typedef struct { |
379 | | TSK_FS_INFO fs_info; /* super class */ |
380 | | xfs_sb *fs; /* super block */ // modified by kyu |
381 | | |
382 | | /* lock protects */ |
383 | | tsk_lock_t lock; |
384 | | |
385 | | // one of the below will be allocated and populated by XFS_group_load depending on the FS type |
386 | | //XFS_agheader *XFS_ag_buf; /* cached AG header for XFS r/w shared - lock */ |
387 | | XFS_AGNUM_T ag_num; /* cached AG number r/w shared - lock */ |
388 | | |
389 | | uint8_t *bmap_buf; /* cached block allocation bitmap r/w shared - lock */ |
390 | | XFS_AGNUM_T bmap_grp_num; /* cached block bitmap nr r/w shared - lock */ |
391 | | |
392 | | uint8_t *imap_buf; /* cached inode allocation bitmap r/w shared - lock */ |
393 | | XFS_AGNUM_T imap_grp_num; /* cached inode bitmap nr r/w shared - lock */ |
394 | | |
395 | | TSK_OFF_T ags_offset; /* offset to first group desc */ |
396 | | XFS_AGNUM_T ags_count; /* nr of descriptor group blocks */ |
397 | | |
398 | | uint16_t inode_size; /* size of each inode */ |
399 | | TSK_DADDR_T first_data_block; |
400 | | |
401 | | XFS_JINFO *jinfo; |
402 | | } XFS_INFO; |
403 | | |
404 | | |
405 | | /* |
406 | | * Byte offset in a directory. |
407 | | */ |
408 | | typedef xfs_off_t xfs_dir2_off_t; |
409 | | |
410 | | #define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ |
411 | | #define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) |
412 | | |
413 | | |
414 | | |
415 | | /* |
416 | | * Convert byte in space to offset in a block |
417 | | */ |
418 | | static inline xfs_dir2_data_aoff_t |
419 | | xfs_dir2_byte_to_off(XFS_INFO *xfs, xfs_dir2_off_t by) |
420 | 0 | { |
421 | 0 | TSK_FS_INFO * fs = (TSK_FS_INFO *) &xfs->fs_info; |
422 | 0 | return (xfs_dir2_data_aoff_t)(by & ( |
423 | 0 | tsk_getu32(fs->endian, xfs->fs->sb_blocksize) - 1)); |
424 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_byte_to_off(XFS_INFO*, long) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_byte_to_off(XFS_INFO*, long) |
425 | | /* |
426 | | * Convert dataptr to byte in file space |
427 | | */ |
428 | | static inline xfs_dir2_off_t |
429 | | xfs_dir2_dataptr_to_byte(xfs_dir2_dataptr_t dp) |
430 | 0 | { |
431 | 0 | return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; |
432 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_dataptr_to_byte(unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_dataptr_to_byte(unsigned int) |
433 | | |
434 | | /* |
435 | | * Convert dataptr to a byte offset in a block |
436 | | */ |
437 | | static inline xfs_dir2_data_aoff_t |
438 | | xfs_dir2_dataptr_to_off(XFS_INFO *xfs, xfs_dir2_dataptr_t dp) |
439 | 0 | { |
440 | 0 | return xfs_dir2_byte_to_off(xfs, xfs_dir2_dataptr_to_byte(dp)); |
441 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_dataptr_to_off(XFS_INFO*, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_dataptr_to_off(XFS_INFO*, unsigned int) |
442 | | |
443 | | |
444 | | // kyu |
445 | | typedef enum { |
446 | | XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, |
447 | | XFS_BTNUM_MAX |
448 | | } xfs_btnum_t; |
449 | | // kyu |
450 | | #define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1) |
451 | | /* |
452 | | AG Free Block Info |
453 | | */ |
454 | | typedef struct xfs_agf { |
455 | | /* |
456 | | * Common allocation group header information |
457 | | */ |
458 | | uint8_t agf_magicnum[4]; /* magic number == XFS_AGF_MAGIC */ |
459 | | uint8_t agf_versionnum[4]; /* header version == XFS_AGF_VERSION */ |
460 | | uint8_t agf_seqno[4]; /* sequence # starting from 0 */ |
461 | | uint8_t agf_length[4]; /* size in blocks of a.g. */ |
462 | | /* |
463 | | * Freespace and rmap information |
464 | | */ |
465 | | uint8_t agf_roots[XFS_BTNUM_AGF * 4]; /* root blocks */ |
466 | | uint8_t agf_levels[XFS_BTNUM_AGF * 4]; /* btree levels */ |
467 | | |
468 | | uint8_t agf_flfirst[4]; /* first freelist block's index */ |
469 | | uint8_t agf_fllast[4]; /* last freelist block's index */ |
470 | | uint8_t agf_flcount[4]; /* count of blocks in freelist */ |
471 | | uint8_t agf_freeblks[4]; /* total free blocks */ |
472 | | |
473 | | uint8_t agf_longest[4]; /* longest free space */ |
474 | | uint8_t agf_btreeblks[4]; /* # of blocks held in AGF btrees */ |
475 | | uint8_t agf_uuid[16]; /* uuid of filesystem */ |
476 | | |
477 | | uint8_t agf_rmap_blocks[4]; /* rmapbt blocks used */ |
478 | | uint8_t agf_refcount_blocks[4]; /* refcountbt blocks used */ |
479 | | |
480 | | uint8_t agf_refcount_root[4]; /* refcount tree root block */ |
481 | | uint8_t agf_refcount_level[4]; /* refcount btree levels */ |
482 | | |
483 | | /* |
484 | | * reserve some contiguous space for future logged fields before we add |
485 | | * the unlogged fields. This makes the range logging via flags and |
486 | | * structure offsets much simpler. |
487 | | */ |
488 | | uint8_t agf_spare64[14*8]; |
489 | | |
490 | | /* unlogged fields, written during buffer writeback. */ |
491 | | uint8_t agf_lsn[8]; /* last write sequence */ |
492 | | uint8_t agf_crc[4]; /* crc of agf sector */ |
493 | | uint8_t agf_spare2[4]; |
494 | | |
495 | | /* structure must be padded to 64 bit alignment */ |
496 | | } xfs_agf_t; |
497 | | |
498 | | #define XFS_AGI_UNLINKED_BUCKETS 64 // kyu |
499 | | |
500 | | /* |
501 | | AG Inode B+ Tree Info |
502 | | */ |
503 | | typedef struct xfs_agi { |
504 | | /* |
505 | | * Common allocation group header information |
506 | | */ |
507 | | uint8_t agi_magicnum[4]; /* magic number == XFS_AGI_MAGIC */ |
508 | | uint8_t agi_versionnum[4]; /* header version == XFS_AGI_VERSION */ |
509 | | uint8_t agi_seqno[4]; /* sequence # starting from 0 */ |
510 | | uint8_t agi_length[4]; /* size in blocks of a.g. */ |
511 | | /* |
512 | | * Inode information |
513 | | * Inodes are mapped by interpreting the inode number, so no |
514 | | * mapping data is needed here. |
515 | | */ |
516 | | uint8_t agi_count[4]; /* count of allocated inodes */ |
517 | | uint8_t agi_root[4]; /* root of inode btree */ |
518 | | uint8_t agi_level[4]; /* levels in inode btree */ |
519 | | uint8_t agi_freecount[4]; /* number of free inodes */ |
520 | | |
521 | | uint8_t agi_newino[4]; /* new inode just allocated */ |
522 | | uint8_t agi_dirino[4]; /* last directory inode chunk */ |
523 | | /* |
524 | | * Hash table of inodes which have been unlinked but are |
525 | | * still being referenced. |
526 | | */ |
527 | | uint8_t agi_unlinked[XFS_AGI_UNLINKED_BUCKETS * 4]; |
528 | | /* |
529 | | * This marks the end of logging region 1 and start of logging region 2. |
530 | | */ |
531 | | uint8_t agi_uuid[16]; /* uuid of filesystem */ |
532 | | uint8_t agi_crc[4]; /* crc of agi sector */ |
533 | | uint8_t agi_pad32[4]; |
534 | | uint8_t agi_lsn[8]; /* last write sequence */ |
535 | | |
536 | | uint8_t agi_free_root[4]; /* root of the free inode btree */ |
537 | | uint8_t agi_free_level[4];/* levels in free inode btree */ |
538 | | |
539 | | /* structure must be padded to 64 bit alignment */ |
540 | | } xfs_agi_t; |
541 | | |
542 | | typedef uint64_t xfs_ino_t; |
543 | | |
544 | | /* |
545 | | AG Free space B+ Tree Info |
546 | | */ |
547 | | |
548 | | //typedef struct xfs_agfl { |
549 | | // uint8_t agfl_magicnum[4]; |
550 | | // uint8_t agfl_seqno[4]; |
551 | | // uint8_t agfl_uuid[16]; |
552 | | // uint8_t agfl_lsn[8]; |
553 | | // uint8_t agfl_crc[4]; |
554 | | // uint8_t agfl_bno[*4]; /* actually XFS_AGFL_SIZE(mp) ->should be defined before compile<- */ |
555 | | //} __attribute__((packed)) xfs_agfl_t; |
556 | | |
557 | | typedef struct xfs_timestamp { |
558 | | uint32_t t_sec; /* timestamp seconds */ |
559 | | uint32_t t_nsec; /* timestamp nanoseconds */ |
560 | | } xfs_timestamp_t; |
561 | | |
562 | | /* |
563 | | Inode |
564 | | */ |
565 | | typedef struct xfs_dinode { |
566 | | uint8_t di_magic[2]; /* inode magic # = XFS_DINODE_MAGIC */ |
567 | | uint8_t di_mode[2]; /* mode and type of file */ |
568 | | uint8_t di_version; /* inode version */ |
569 | | uint8_t di_format; /* format of di_c data */ |
570 | | uint8_t di_onlink[2]; /* old number of links to file */ |
571 | | uint8_t di_uid[4]; /* owner's user id */ |
572 | | uint8_t di_gid[4]; /* owner's group id */ |
573 | | uint8_t di_nlink[4]; /* number of links to file */ |
574 | | uint8_t di_projid_lo[2]; /* lower part of owner's project id */ |
575 | | uint8_t di_projid_hi[2]; /* higher part owner's project id */ |
576 | | uint8_t di_pad[6]; /* unused, zeroed space */ |
577 | | uint8_t di_flushiter[2]; /* incremented on flush */ |
578 | | xfs_timestamp_t di_atime; /* time last accessed */ |
579 | | xfs_timestamp_t di_mtime; /* time last modified */ |
580 | | xfs_timestamp_t di_ctime; /* time created/inode modified */ |
581 | | uint8_t di_size[8]; /* number of bytes in file */ |
582 | | uint8_t di_nblocks[8]; /* # of direct & btree blocks used */ |
583 | | uint8_t di_extsize[4]; /* basic/minimum extent size for file */ |
584 | | uint8_t di_nextents[4]; /* number of extents in data fork */ |
585 | | uint8_t di_anextents[2]; /* number of extents in attribute fork*/ |
586 | | uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ |
587 | | int8_t di_aformat; /* format of attr fork's data */ |
588 | | uint8_t di_dmevmask[4]; /* DMIG event mask */ |
589 | | uint8_t di_dmstate[2]; /* DMIG state info */ |
590 | | uint8_t di_flags[2]; /* random flags, XFS_DIFLAG_... */ |
591 | | uint8_t di_gen[4]; /* generation number */ |
592 | | |
593 | | /* di_next_unlinked is the only non-core field in the old dinode */ |
594 | | uint8_t di_next_unlinked[4];/* agi unlinked list ptr */ |
595 | | |
596 | | /* start of the extended dinode, writable fields */ |
597 | | uint8_t di_crc[4]; /* CRC of the inode -->little endian<-*/ |
598 | | uint8_t di_changecount[8]; /* number of attribute changes */ |
599 | | uint8_t di_lsn[8]; /* flush sequence */ |
600 | | uint8_t di_flags2[8]; /* more random flags */ |
601 | | uint8_t di_cowextsize[4]; /* basic cow extent size for file */ |
602 | | uint8_t di_pad2[12]; /* more padding for future expansion */ |
603 | | |
604 | | /* fields only written to during inode creation */ |
605 | | xfs_timestamp_t di_crtime; /* time created */ |
606 | | uint8_t di_ino[8]; /* inode number */ |
607 | | uint8_t di_uuid[16]; /* UUID of the filesystem */ |
608 | | |
609 | | /* structure must be padded to 64 bit alignment */ |
610 | | } xfs_dinode; |
611 | | |
612 | | /* |
613 | | Internal Inode - Quota Inode |
614 | | */ |
615 | | typedef struct xfs_disk_dquot { |
616 | | uint8_t d_magic[2]; /* dquot magic = XFS_DQUOT_MAGIC */ |
617 | | uint8_t d_version; /* dquot version */ |
618 | | uint8_t d_flags; /* XFS_DQ_USER/PROJ/GROUP */ |
619 | | uint8_t d_id[4]; /* user,project,group id */ |
620 | | uint8_t d_blk_hardlimit[8];/* absolute limit on disk blks */ |
621 | | uint8_t d_blk_softlimit[8];/* preferred limit on disk blks */ |
622 | | uint8_t d_ino_hardlimit[8];/* maximum # allocated inodes */ |
623 | | uint8_t d_ino_softlimit[8];/* preferred inode limit */ |
624 | | uint8_t d_bcount[8]; /* disk blocks owned by the user */ |
625 | | uint8_t d_icount[8]; /* inodes owned by the user */ |
626 | | uint8_t d_itimer[4]; /* zero if within inode limits if not, |
627 | | this is when we refuse service */ |
628 | | uint8_t d_btimer[4]; /* similar to above; for disk blocks */ |
629 | | uint8_t d_iwarns[2]; /* warnings issued wrt num inodes */ |
630 | | uint8_t d_bwarns[2]; /* warnings issued wrt disk blocks */ |
631 | | uint8_t d_pad0[4]; /* 64 bit align */ |
632 | | uint8_t d_rtb_hardlimit[8];/* absolute limit on realtime blks */ |
633 | | uint8_t d_rtb_softlimit[8];/* preferred limit on RT disk blks */ |
634 | | uint8_t d_rtbcount[4]; /* realtime blocks owned */ |
635 | | uint8_t d_rtbtimer[4]; /* similar to above; for RT disk blocks */ |
636 | | uint8_t d_rtbwarns[2]; /* warnings issued wrt RT disk blocks */ |
637 | | uint8_t d_pad[2]; |
638 | | } xfs_disk_dquot_t; |
639 | | |
640 | | /* |
641 | | Internal Inode - Quota block |
642 | | */ |
643 | | typedef struct xfs_dqblk { |
644 | | xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */ |
645 | | char dd_fill[4]; /* filling for posterity */ |
646 | | |
647 | | /* |
648 | | * These two are only present on filesystems with the CRC bits set. |
649 | | */ |
650 | | uint8_t dd_crc[4]; /* checksum ->BIG ENDIAN<-*/ |
651 | | uint8_t dd_lsn[8]; /* last modification in log */ |
652 | | uint8_t dd_uuid[16]; /* location information */ |
653 | | } xfs_dqblk_t; |
654 | | |
655 | | /* |
656 | | Inode record |
657 | | */ |
658 | | typedef struct xfs_inobt_rec { |
659 | | uint8_t ir_startino[4]; /* starting inode number */ |
660 | | union { |
661 | | struct { |
662 | | uint8_t ir_freecount[4]; /* count of free inodes */ |
663 | | } f; |
664 | | struct { |
665 | | uint8_t ir_holemask[2];/* hole mask for sparse chunks */ |
666 | | uint8_t ir_count; /* total inode count */ |
667 | | uint8_t ir_freecount; /* count of free inodes */ |
668 | | } sp; // sparse inode |
669 | | } ir_u; |
670 | | uint8_t ir_free[8]; /* free inode mask */ |
671 | | } xfs_inobt_rec_t; |
672 | | |
673 | | /* |
674 | | Bmap root header |
675 | | */ |
676 | | typedef struct xfs_bmdr_block { |
677 | | uint8_t bb_level[2]; /* 0 is a leaf */ |
678 | | uint8_t bb_numrecs[2]; /* current # of data records */ |
679 | | } xfs_bmdr_block_t; |
680 | | |
681 | | typedef uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ |
682 | | //typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; |
683 | | |
684 | | /* |
685 | | Key structure -> Non-leaf level Tree |
686 | | */ |
687 | | typedef struct xfs_bmbt_key { |
688 | | uint8_t br_startoff[8]; /* starting file offset */ |
689 | | } xfs_bmbt_key_t, xfs_bmdr_key_t; |
690 | | |
691 | | /* |
692 | | Directory:: 1. Shortform directory - header |
693 | | */ |
694 | | |
695 | | typedef struct xfs_dir2_sf_hdr { |
696 | | uint8_t count; /* count of entries */ |
697 | | uint8_t i8count; /* count of 8-byte inode #s */ |
698 | | uint8_t parent[8]; /* parent dir inode number */ |
699 | | } xfs_dir2_sf_hdr_t; |
700 | | |
701 | | /* |
702 | | Directory:: 1. Shortform directory - entry |
703 | | */ |
704 | | typedef struct xfs_dir2_sf_entry { |
705 | | uint8_t namelen; /* actual name length */ |
706 | | uint8_t offset[2]; /* saved offset */ |
707 | | uint8_t name[]; /* name, variable size */ |
708 | | /* |
709 | | * A single byte containing the file type field follows the inode |
710 | | * number for version 3 directory entries. |
711 | | * |
712 | | * A 64-bit or 32-bit inode number follows here, at a variable offset |
713 | | * after the name. |
714 | | */ |
715 | | } xfs_dir2_sf_entry_t; |
716 | | |
717 | | typedef struct xfs_dir2_sf { |
718 | | xfs_dir2_sf_hdr_t *hdr; |
719 | | xfs_dir2_sf_entry_t *entry; |
720 | | } xfs_dir2_sf_t; |
721 | | |
722 | | static inline uint32_t get_unaligned_be32(const uint8_t *p) |
723 | 0 | { |
724 | 0 | return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; |
725 | 0 | } Unexecuted instantiation: xfs.cpp:get_unaligned_be32(unsigned char const*) Unexecuted instantiation: xfs_dent.cpp:get_unaligned_be32(unsigned char const*) |
726 | | |
727 | | static inline uint64_t get_unaligned_be64(const uint8_t *p) |
728 | 0 | { |
729 | 0 | return (uint64_t)get_unaligned_be32(p) << 32 | |
730 | 0 | get_unaligned_be32(p + 4); |
731 | 0 | } Unexecuted instantiation: xfs.cpp:get_unaligned_be64(unsigned char const*) Unexecuted instantiation: xfs_dent.cpp:get_unaligned_be64(unsigned char const*) |
732 | | |
733 | | /* |
734 | | Data block structure:: Free area in data block |
735 | | */ |
736 | | typedef struct xfs_dir2_data_free { |
737 | | uint16_t offset; /* start of freespace */ |
738 | | uint16_t length; /* length of freespace */ |
739 | | } xfs_dir2_data_free_t; |
740 | | |
741 | | /* |
742 | | Data block structure:: Header for the data block |
743 | | */ |
744 | | |
745 | | #define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) |
746 | | #define XFS_DIR2_DATA_FD_COUNT 3 |
747 | | |
748 | | /* |
749 | | * define a structure for all the verification fields we are adding to the |
750 | | * directory block structures. This will be used in several structures. |
751 | | * The magic number must be the first entry to align with all the dir2 |
752 | | * structures so we determine how to decode them just by the magic number. |
753 | | */ |
754 | | struct xfs_dir3_blk_hdr { |
755 | | uint32_t magic; /* magic number */ |
756 | | uint32_t crc; /* CRC of block */ |
757 | | uint64_t blkno; /* first block of the buffer */ |
758 | | uint64_t lsn; /* sequence number of last write */ |
759 | | uint64_t uuid[2]; |
760 | | uint64_t owner; /* inode that owns the block */ |
761 | | }; |
762 | | |
763 | | struct xfs_dir3_data_hdr { |
764 | | struct xfs_dir3_blk_hdr hdr; |
765 | | xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; |
766 | | uint32_t pad; /* 64 bit alignment */ |
767 | | }; |
768 | | |
769 | | typedef struct xfs_dir2_data_hdr { |
770 | | uint32_t magic; /* XFS_DIR2_DATA_MAGIC or */ |
771 | | /* XFS_DIR2_BLOCK_MAGIC */ |
772 | | xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; |
773 | | } xfs_dir2_data_hdr_t; |
774 | | |
775 | | /* |
776 | | Data block structure:: Active entry |
777 | | */ |
778 | | typedef struct xfs_dir2_data_entry { |
779 | | uint8_t inumber[8]; /* inode number */ |
780 | | uint8_t namelen; /* name length */ |
781 | | uint8_t name[]; /* name bytes, no null */ |
782 | | /* uint8_t filetype; */ /* type of inode we point to */ |
783 | | /* uint16_t tag; */ /* starting offset of us */ |
784 | | } xfs_dir2_data_entry_t; |
785 | | |
786 | | /* |
787 | | Data block structure:: empty entry |
788 | | */ |
789 | | typedef struct xfs_dir2_data_unused { |
790 | | uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */ |
791 | | uint16_t length; /* total free length */ |
792 | | /* variable offset */ |
793 | | uint16_t tag; /* starting offset of us */ |
794 | | } xfs_dir2_data_unused_t; |
795 | | |
796 | | /* |
797 | | * Leaf block structures. |
798 | | * |
799 | | * +---------------------------+ |
800 | | * | xfs_dir2_leaf_hdr_t | |
801 | | * +---------------------------+ |
802 | | * | xfs_dir2_leaf_entry_t | |
803 | | * | xfs_dir2_leaf_entry_t | |
804 | | * | xfs_dir2_leaf_entry_t | |
805 | | * | xfs_dir2_leaf_entry_t | |
806 | | * | ... | |
807 | | * +---------------------------+ |
808 | | * | xfs_dir2_data_off_t | |
809 | | * | xfs_dir2_data_off_t | |
810 | | * | xfs_dir2_data_off_t | |
811 | | * | ... | |
812 | | * +---------------------------+ |
813 | | * | xfs_dir2_leaf_tail_t | |
814 | | * +---------------------------+ |
815 | | */ |
816 | | typedef struct xfs_da_blkinfo { |
817 | | uint32_t forw; |
818 | | uint32_t back; |
819 | | uint32_t magic; |
820 | | uint16_t pad; |
821 | | } xfs_da_blkinfo_t; |
822 | | /* |
823 | | Leaf block structure: header |
824 | | */ |
825 | | typedef struct xfs_dir2_leaf_hdr { |
826 | | xfs_da_blkinfo_t info; /* header for da routines */ |
827 | | uint16_t count; /* count of entries */ |
828 | | uint16_t stale; /* count of stale entries */ |
829 | | } xfs_dir2_leaf_hdr_t; |
830 | | |
831 | | /* |
832 | | Leaf block structure: entry |
833 | | */ |
834 | | typedef struct xfs_dir2_leaf_entry { |
835 | | uint32_t hashval; /* hash value of name */ |
836 | | uint32_t address; /* address of data entry */ |
837 | | } xfs_dir2_leaf_entry_t; |
838 | | |
839 | | /* |
840 | | Leaf block structure: tail |
841 | | */ |
842 | | typedef struct xfs_dir2_leaf_tail { |
843 | | uint32_t bestcount; |
844 | | } xfs_dir2_leaf_tail_t; |
845 | | |
846 | | /* |
847 | | Freeindex block:: header |
848 | | */ |
849 | | typedef struct xfs_dir2_free_hdr { |
850 | | uint32_t magic; /* XFS_DIR2_FREE_MAGIC */ |
851 | | uint32_t firstdb; /* db of first entry */ |
852 | | uint32_t nvalid; /* count of valid entries */ |
853 | | uint32_t nused; /* count of used entries */ |
854 | | } xfs_dir2_free_hdr_t; |
855 | | |
856 | | /* |
857 | | Freeindex block:: entry |
858 | | */ |
859 | | typedef struct xfs_dir2_free { |
860 | | xfs_dir2_free_hdr_t hdr; /* block header */ |
861 | | uint16_t bests[]; /* best free counts */ |
862 | | /* unused entries are -1 */ |
863 | | } xfs_dir2_free_t; |
864 | | |
865 | | /* |
866 | | * Single block format. |
867 | | * |
868 | | * The single block format looks like the following drawing on disk: |
869 | | * |
870 | | * +-------------------------------------------------+ |
871 | | * | xfs_dir2_data_hdr_t | |
872 | | * +-------------------------------------------------+ |
873 | | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | |
874 | | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | |
875 | | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : |
876 | | * | ... | |
877 | | * +-------------------------------------------------+ |
878 | | * | unused space | |
879 | | * +-------------------------------------------------+ |
880 | | * | ... | |
881 | | * | xfs_dir2_leaf_entry_t | |
882 | | * | xfs_dir2_leaf_entry_t | |
883 | | * +-------------------------------------------------+ |
884 | | * | xfs_dir2_block_tail_t | |
885 | | * +-------------------------------------------------+ |
886 | | * |
887 | | * As all the entries are variable size structures the accessors below should |
888 | | * be used to iterate over them. |
889 | | */ |
890 | | |
891 | | /* |
892 | | Single block format:: tail |
893 | | */ |
894 | | typedef struct xfs_dir2_block_tail { |
895 | | uint32_t count; /* count of leaf entries */ |
896 | | uint32_t stale; /* count of stale lf entries */ |
897 | | } xfs_dir2_block_tail_t; |
898 | | |
899 | | /* |
900 | | Shortform directory: attributes |
901 | | */ |
902 | | typedef struct xfs_attr_shortform { |
903 | | struct xfs_attr_sf_hdr { /* constant-structure header block */ |
904 | | uint16_t totsize; /* total bytes in shortform list */ |
905 | | uint8_t count; /* count of active entries */ |
906 | | uint8_t padding; |
907 | | } hdr; |
908 | | struct xfs_attr_sf_entry { |
909 | | uint8_t namelen; /* actual length of name (no NULL) */ |
910 | | uint8_t valuelen; /* actual length of value (no NULL) */ |
911 | | uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ |
912 | | uint8_t nameval[1]; /* name & value bytes concatenated */ |
913 | | } list[1]; /* variable sized array */ |
914 | | } xfs_attr_shortform_t; |
915 | | |
916 | | |
917 | | typedef union { |
918 | | uint8_t i8[8]; |
919 | | uint8_t i4[4]; |
920 | | } xfs_dir2_inou_t; |
921 | | |
922 | | // Btree block format |
923 | | struct xfs_btree_block_shdr { |
924 | | uint32_t bb_leftsib; |
925 | | uint32_t bb_rightsib; |
926 | | |
927 | | uint64_t bb_blkno; |
928 | | uint64_t bb_lsn; |
929 | | uint64_t bb_uuid[2]; |
930 | | uint32_t bb_owner; |
931 | | uint32_t bb_crc; |
932 | | //__le32 bb_crc; |
933 | | }; |
934 | | |
935 | | /* long form block header */ |
936 | | struct xfs_btree_block_lhdr { |
937 | | uint64_t bb_leftsib; |
938 | | uint64_t bb_rightsib; |
939 | | |
940 | | uint64_t bb_blkno; |
941 | | uint64_t bb_lsn; |
942 | | uint64_t bb_uuid[2]; |
943 | | uint64_t bb_owner; |
944 | | uint32_t bb_crc; |
945 | | //__le32 bb_crc; |
946 | | uint32_t bb_pad; /* padding for alignment */ |
947 | | }; |
948 | | |
949 | | struct xfs_btree_block { |
950 | | uint32_t bb_magic; /* magic number for block type */ |
951 | | uint16_t bb_level; /* 0 is a leaf */ |
952 | | uint16_t bb_numrecs; /* current # of data records */ |
953 | | union { |
954 | | struct xfs_btree_block_shdr s; |
955 | | struct xfs_btree_block_lhdr l; |
956 | | } bb_u; /* rest */ |
957 | | }; |
958 | | |
959 | | /* MODE */ |
960 | 0 | #define XFS_IN_FMT 0170000 |
961 | 0 | #define XFS_IN_SOCK 0140000 |
962 | 0 | #define XFS_IN_LNK 0120000 |
963 | 0 | #define XFS_IN_REG 0100000 |
964 | 0 | #define XFS_IN_BLK 0060000 |
965 | 0 | #define XFS_IN_DIR 0040000 |
966 | 0 | #define XFS_IN_CHR 0020000 |
967 | 0 | #define XFS_IN_FIFO 0010000 |
968 | | |
969 | 0 | #define XFS_IN_ISUID 0004000 |
970 | 0 | #define XFS_IN_ISGID 0002000 |
971 | 0 | #define XFS_IN_ISVTX 0001000 |
972 | 0 | #define XFS_IN_IRUSR 0000400 |
973 | 0 | #define XFS_IN_IWUSR 0000200 |
974 | 0 | #define XFS_IN_IXUSR 0000100 |
975 | 0 | #define XFS_IN_IRGRP 0000040 |
976 | 0 | #define XFS_IN_IWGRP 0000020 |
977 | 0 | #define XFS_IN_IXGRP 0000010 |
978 | 0 | #define XFS_IN_IROTH 0000004 |
979 | 0 | #define XFS_IN_IWOTH 0000002 |
980 | 0 | #define XFS_IN_IXOTH 0000001 |
981 | | |
982 | | |
983 | | #define XFS_IN_SECDEL 0x00000001 /* Secure deletion */ |
984 | | #define XFS_IN_UNRM 0x00000002 /* Undelete */ |
985 | | #define XFS_IN_COMP 0x00000004 /* Compress file */ |
986 | | #define XFS_IN_SYNC 0x00000008 /* Synchronous updates */ |
987 | | #define XFS_IN_IMM 0x00000010 /* Immutable file */ |
988 | | #define XFS_IN_APPEND 0x00000020 /* writes to file may only append */ |
989 | | #define XFS_IN_NODUMP 0x00000040 /* do not dump file */ |
990 | | #define XFS_IN_NOA 0x00000080 /* do not update atime */ |
991 | | #define XFS_IN_DIRTY 0x00000100 |
992 | | #define XFS_IN_COMPRBLK 0x00000200 /* One or more compressed clusters */ |
993 | | #define XFS_IN_NOCOMPR 0x00000400 /* Don't compress */ |
994 | | #define XFS_IN_ECOMPR 0x00000800 /* Compression error */ |
995 | | #define XFS_IN_INDEX 0x00001000 /* hash-indexed directory */ |
996 | | #define XFS_IN_IMAGIC 0x00002000 /* AFS directory */ |
997 | | #define XFS_IN_JOURNAL_DATA 0x00004000 /* file data should be journaled */ |
998 | | #define XFS_IN_NOTAIL 0x00008000 /* file tail should not be merged */ |
999 | | #define XFS_IN_DIRSYNC 0x00010000 /* dirsync behaviour (directories only) */ |
1000 | | #define XFS_IN_TOPDIR 0x00020000 /* Top of directory hierarchies */ |
1001 | | #define XFS_IN_HUGE_FILE 0x00040000 /* Set to each huge file */ |
1002 | | #define XFS_IN_EXTENTS 0x00080000 /* Inode uses extents */ |
1003 | | #define XFS_IN_EA_INODE 0x00200000 /* Inode used for large EA */ |
1004 | | #define XFS_IN_EOFBLOCKS 0x00400000 /* Blocks allocated beyond EOF */ |
1005 | | #define XFS_IN_RESERVED 0x80000000 /* reserved for XFS lib */ |
1006 | | #define XFS_IN_USER_VISIBLE 0x004BDFFF /* User visible flags */ |
1007 | | #define XFS_IN_USER_MODIFIABLE 0x004B80FF /* User modifiable flags */ |
1008 | | |
1009 | | /* XFS directory file types */ |
1010 | 0 | #define XFS_DE_UNKNOWN 0 |
1011 | 0 | #define XFS_DE_REG 1 |
1012 | 0 | #define XFS_DE_DIR 2 |
1013 | 0 | #define XFS_DE_CHR 3 |
1014 | 0 | #define XFS_DE_BLK 4 |
1015 | 0 | #define XFS_DE_FIFO 5 |
1016 | 0 | #define XFS_DE_SOCK 6 |
1017 | 0 | #define XFS_DE_LNK 7 |
1018 | | #define XFS_DE_MAX 8 |
1019 | | |
1020 | | /* |
1021 | | * Values for di_format |
1022 | | */ |
1023 | | typedef enum xfs_dinode_fmt { |
1024 | | XFS_DINODE_FMT_DEV, /* xfs_dev_t */ |
1025 | | XFS_DINODE_FMT_LOCAL, /* bulk data */ |
1026 | | XFS_DINODE_FMT_EXTENTS, /* struct xfs_bmbt_rec */ |
1027 | | XFS_DINODE_FMT_BTREE, /* struct xfs_bmdr_block */ |
1028 | | XFS_DINODE_FMT_UUID /* added long ago, but never used */ |
1029 | | } xfs_dinode_fmt_t; |
1030 | | |
1031 | | /************** JOURNAL ******************/ |
1032 | | |
1033 | | /* These values are always in big endian */ |
1034 | | |
1035 | | #define XFS_JMAGIC 0xC03b3998 |
1036 | | |
1037 | | /*JBD2 Feature Flags */ |
1038 | | #define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 |
1039 | | |
1040 | | #define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 |
1041 | | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 |
1042 | | #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 |
1043 | | |
1044 | | #define XFS_J_ETYPE_DESC 1 /* descriptor block */ |
1045 | | #define XFS_J_ETYPE_COM 2 /* commit */ |
1046 | | #define XFS_J_ETYPE_SB1 3 /* super block v1 */ |
1047 | | #define XFS_J_ETYPE_SB2 4 /* sb v2 */ |
1048 | | #define XFS_J_ETYPE_REV 5 /* revoke */ |
1049 | | |
1050 | | /* JBD2 Checksum types */ |
1051 | | #define JBD2_CRC32_CHKSUM 1 |
1052 | | #define JBD2_MD5_CHKSUM 2 |
1053 | | #define JBD2_SHA1_CHKSUM 3 |
1054 | | |
1055 | | #define JBD2_CRC32_CHKSUM_SIZE 4 |
1056 | | #define JBD2_CHECKSUM_BYTES (32/ sizeof(unsigned int)) |
1057 | | |
1058 | | #define NSEC_PER_SEC 1000000000L |
1059 | | |
1060 | | /* dentry flags */ |
1061 | | #define XFS_J_DENTRY_ESC 1 /* The orig block starts with magic */ |
1062 | | #define XFS_J_DENTRY_SAMEID 2 /* Entry is for same id, so do not skip 16 ahead */ |
1063 | | #define XFS_J_DENTRY_DEL 4 /* not currently used in src */ |
1064 | | #define XFS_J_DENTRY_LAST 8 /* Last tag */ |
1065 | | |
1066 | | extern TSK_RETVAL_ENUM |
1067 | | xfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, |
1068 | | TSK_INUM_T a_addr, int recursion_depth); |
1069 | | extern uint8_t xfs_jentry_walk(TSK_FS_INFO *, int, |
1070 | | TSK_FS_JENTRY_WALK_CB, void *); |
1071 | | extern uint8_t xfs_jblk_walk(TSK_FS_INFO *, TSK_DADDR_T, |
1072 | | TSK_DADDR_T, int, TSK_FS_JBLK_WALK_CB, void *); |
1073 | | extern uint8_t xfs_jopen(TSK_FS_INFO *, TSK_INUM_T); |
1074 | | |
1075 | | |
1076 | | static inline bool xfs_sb_good_version(TSK_FS_INFO* fs, struct xfs_sb *sbp) |
1077 | 0 | { |
1078 | 0 | if (tsk_fs_guessu16(fs, sbp->sb_versionnum, XFS_SB_VERSION_5)) |
1079 | 0 | return true; |
1080 | 0 | if (tsk_fs_guessu16(fs, sbp->sb_versionnum, XFS_SB_VERSION_4)) |
1081 | 0 | { |
1082 | 0 | tsk_fprintf(stderr, "Found superblock version 4, continuing with version 5 analyzer"); |
1083 | 0 | return true; |
1084 | 0 | } |
1085 | 0 | return false; |
1086 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_sb_good_version(TSK_FS_INFO*, xfs_sb*) Unexecuted instantiation: xfs_dent.cpp:xfs_sb_good_version(TSK_FS_INFO*, xfs_sb*) |
1087 | | |
1088 | | static inline bool |
1089 | | xfs_sb_has_compat_feature( |
1090 | | TSK_FS_INFO * fs, |
1091 | | xfs_sb * sb, |
1092 | | uint32_t feature) |
1093 | 0 | { |
1094 | 0 |
|
1095 | 0 | return (tsk_getu32(fs->endian, sb->sb_features_compat) & feature) != 0; |
1096 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_sb_has_compat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_sb_has_compat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) |
1097 | | |
1098 | | #define XFS_HAS_COMPAT_FEATURE(fs, sb, mask)\ |
1099 | | ((tsk_fs_guessu32(&(fs->endian), sb->sb_features_compat) & mask) != 0) |
1100 | | |
1101 | | // checking if sb has ro compat feature |
1102 | | #define XFS_HAS_RO_COMPAT_FEATURE(fs, sb, mask)\ |
1103 | | ((tsk_fs_guessu32(fs->endian, sb->sb_features_ro_compat) & mask) != 0) |
1104 | | |
1105 | | static inline bool xfs_sb_has_ro_compat_feature( |
1106 | | TSK_FS_INFO * fs, |
1107 | | xfs_sb *sbp, |
1108 | | uint32_t feature) |
1109 | 0 | { |
1110 | 0 | uint32_t oper = tsk_getu32(fs->endian, sbp->sb_features_ro_compat) & feature; |
1111 | 0 | if (oper == 0) |
1112 | 0 | return 1; |
1113 | 0 | else |
1114 | 0 | return 0; |
1115 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_sb_has_ro_compat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_sb_has_ro_compat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) |
1116 | | |
1117 | | static inline bool xfs_sb_has_incompat_feature( |
1118 | | TSK_FS_INFO * fs, |
1119 | | xfs_sb *sbp, |
1120 | | uint32_t feature) |
1121 | 0 | { |
1122 | 0 | uint32_t oper = tsk_getu32(fs->endian, sbp->sb_features_incompat) & feature; |
1123 | 0 | if (oper == 0) |
1124 | 0 | return 1; |
1125 | 0 | else |
1126 | 0 | return 0; |
1127 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_sb_has_incompat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_sb_has_incompat_feature(TSK_FS_INFO*, xfs_sb*, unsigned int) |
1128 | | |
1129 | | |
1130 | | /* |
1131 | | * Directory tail pointer accessor functions. Based on block geometry. |
1132 | | */ |
1133 | | static inline struct xfs_dir2_block_tail * |
1134 | | xfs_dir2_block_tail_p(XFS_INFO *xfs, struct xfs_dir2_data_hdr *hdr) |
1135 | 0 | { |
1136 | 0 | TSK_FS_INFO * fs = (TSK_FS_INFO *) &xfs->fs_info; |
1137 | 0 | return ((struct xfs_dir2_block_tail *) |
1138 | 0 | ((char *)hdr + tsk_getu32(fs->endian, xfs->fs->sb_blocksize))) - 1; |
1139 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_block_tail_p(XFS_INFO*, xfs_dir2_data_hdr*) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_block_tail_p(XFS_INFO*, xfs_dir2_data_hdr*) |
1140 | | |
1141 | | /* |
1142 | | * Pointer to the leaf entries embedded in a data block (1-block format) |
1143 | | */ |
1144 | | static inline struct xfs_dir2_leaf_entry * |
1145 | | xfs_dir2_block_leaf_p([[maybe_unused]] XFS_INFO *xfs, struct xfs_dir2_block_tail *btp) |
1146 | 0 | { |
1147 | 0 | uint32_t count = btp->count; |
1148 | 0 | return ((struct xfs_dir2_leaf_entry *)btp) - count; |
1149 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_block_leaf_p(XFS_INFO*, xfs_dir2_block_tail*) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_block_leaf_p(XFS_INFO*, xfs_dir2_block_tail*) |
1150 | | |
1151 | | static inline |
1152 | 0 | TSK_OFF_T xfs_inode_get_offset(XFS_INFO * xfs, TSK_INUM_T a_addr){ |
1153 | 0 | TSK_FS_INFO *fs = (TSK_FS_INFO *) & xfs->fs_info; |
1154 | 0 | TSK_OFF_T offset; |
1155 | 0 | uint8_t sb_agblklog = xfs->fs->sb_agblklog; |
1156 | 0 | uint8_t sb_inopblog = xfs->fs->sb_inopblog; |
1157 | | |
1158 | | /* lock access to grp_buf */ |
1159 | 0 | tsk_take_lock(&xfs->lock); |
1160 | |
|
1161 | 0 | uint64_t ag_num = a_addr >> (sb_agblklog + sb_inopblog); |
1162 | 0 | uint64_t blk_num = (a_addr - (ag_num << (sb_agblklog + sb_inopblog))) >> sb_inopblog; |
1163 | 0 | uint64_t sec_num = (a_addr - (ag_num << (sb_agblklog + sb_inopblog)) - (blk_num << sb_inopblog)); |
1164 | |
|
1165 | 0 | tsk_release_lock(&xfs->lock); |
1166 | |
|
1167 | 0 | TSK_OFF_T ag_offset = ag_num * (tsk_getu32(fs->endian, xfs->fs->sb_agblocks) * tsk_getu32(fs->endian, xfs->fs->sb_blocksize)); |
1168 | 0 | TSK_OFF_T blk_offset = blk_num * tsk_getu32(fs->endian, xfs->fs->sb_blocksize); |
1169 | 0 | TSK_OFF_T sec_offset = sec_num * tsk_getu16(fs->endian, xfs->fs->sb_sectsize); |
1170 | | |
1171 | 0 | offset = ag_offset + blk_offset + sec_offset; |
1172 | |
|
1173 | 0 | return offset; |
1174 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_inode_get_offset(XFS_INFO*, unsigned long) Unexecuted instantiation: xfs_dent.cpp:xfs_inode_get_offset(XFS_INFO*, unsigned long) |
1175 | | |
1176 | | typedef enum { |
1177 | | XFS_EXT_NORM, XFS_EXT_UNWRITTEN, |
1178 | | } xfs_exntst_t; |
1179 | | |
1180 | | typedef struct xfs_bmbt_irec { |
1181 | | uint64_t br_startoff; |
1182 | | uint32_t br_startblock; |
1183 | | uint64_t br_blockcount; |
1184 | | xfs_exntst_t br_state; |
1185 | | } xfs_bmbt_irec_t; |
1186 | | |
1187 | | typedef struct xfs_bmbt_rec |
1188 | | { |
1189 | | uint8_t l0[8], l1[8]; |
1190 | | } xfs_bmbt_rec_t; |
1191 | | |
1192 | | typedef xfs_off_t xfs_dir2_off_t; |
1193 | | typedef uint32_t xfs_dir2_db_t; |
1194 | | typedef uint32_t xfs_dir2_data_aoff_t; /* argument form */ |
1195 | | |
1196 | | static inline uint16_t get_unaligned_be16(const uint8_t *p) |
1197 | 0 | { |
1198 | 0 | return p[0] << 8 | p[1]; |
1199 | 0 | } Unexecuted instantiation: xfs.cpp:get_unaligned_be16(unsigned char const*) Unexecuted instantiation: xfs_dent.cpp:get_unaligned_be16(unsigned char const*) |
1200 | | |
1201 | | static inline xfs_dir2_data_aoff_t |
1202 | | xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) |
1203 | 0 | { |
1204 | 0 | return get_unaligned_be16(sfep->offset); |
1205 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_sf_get_offset(xfs_dir2_sf_entry*) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_sf_get_offset(xfs_dir2_sf_entry*) |
1206 | | |
1207 | | /* |
1208 | | * Convert block and offset to byte in space |
1209 | | */ |
1210 | | static inline xfs_dir2_off_t |
1211 | | xfs_dir2_db_off_to_byte(XFS_INFO *xfs, xfs_dir2_db_t db, |
1212 | | xfs_dir2_data_aoff_t o) |
1213 | 0 | { |
1214 | 0 | return ((xfs_dir2_off_t)db << xfs->fs->sb_blocklog) + o; |
1215 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_db_off_to_byte(XFS_INFO*, unsigned int, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_db_off_to_byte(XFS_INFO*, unsigned int, unsigned int) |
1216 | | |
1217 | | /* |
1218 | | * Convert byte in file space to dataptr. It had better be aligned. |
1219 | | */ |
1220 | | static inline xfs_dir2_dataptr_t |
1221 | | xfs_dir2_byte_to_dataptr(xfs_dir2_off_t by) |
1222 | 0 | { |
1223 | 0 | return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); |
1224 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_byte_to_dataptr(long) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_byte_to_dataptr(long) |
1225 | | |
1226 | | |
1227 | 0 | #define XFS_INO32_SIZE 4 |
1228 | 0 | #define XFS_INO64_SIZE 8 |
1229 | | |
1230 | | static void |
1231 | | xfs_bmbt_disk_get_all( |
1232 | | XFS_INFO* xfs, |
1233 | | struct xfs_bmbt_rec *rec, |
1234 | | struct xfs_bmbt_irec *irec) |
1235 | 0 | { |
1236 | 0 | uint64_t l0 = tsk_getu64(xfs->fs_info.endian, rec->l0); |
1237 | 0 | uint64_t l1 = tsk_getu64(xfs->fs_info.endian, rec->l1); |
1238 | |
|
1239 | 0 | irec->br_startoff = (l0 & xfs_mask64lo(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; |
1240 | 0 | irec->br_startblock = ((l0 & xfs_mask64lo(9)) << 43) | (l1 >> 21); |
1241 | 0 | irec->br_blockcount = l1 & xfs_mask64lo(21); |
1242 | |
|
1243 | 0 | if (l0 >> (64 - BMBT_EXNTFLAG_BITLEN)) |
1244 | 0 | irec->br_state = XFS_EXT_UNWRITTEN; |
1245 | 0 | else |
1246 | 0 | irec->br_state = XFS_EXT_NORM; |
1247 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_bmbt_disk_get_all(XFS_INFO*, xfs_bmbt_rec*, xfs_bmbt_irec*) Unexecuted instantiation: xfs_dent.cpp:xfs_bmbt_disk_get_all(XFS_INFO*, xfs_bmbt_rec*, xfs_bmbt_irec*) |
1248 | | |
1249 | | static struct xfs_dir2_data_entry * |
1250 | | xfs_dir2_data_nextentry( |
1251 | | struct xfs_dir2_data_entry *daen) |
1252 | 0 | { |
1253 | 0 | return (struct xfs_dir2_data_entry *) |
1254 | 0 | ((char*)daen + XFS_DIR3_DATA_ENTSIZE(daen->namelen)); |
1255 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_data_nextentry(xfs_dir2_data_entry*) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_data_nextentry(xfs_dir2_data_entry*) |
1256 | | |
1257 | | /* |
1258 | | * Convert block and offset to dataptr |
1259 | | */ |
1260 | | static inline xfs_dir2_dataptr_t |
1261 | | xfs_dir2_db_off_to_dataptr(XFS_INFO *xfs, xfs_dir2_db_t db, |
1262 | | xfs_dir2_data_aoff_t o) |
1263 | 0 | { |
1264 | 0 | return xfs_dir2_byte_to_dataptr(xfs_dir2_db_off_to_byte(xfs, db, o)); |
1265 | 0 | } Unexecuted instantiation: xfs.cpp:xfs_dir2_db_off_to_dataptr(XFS_INFO*, unsigned int, unsigned int) Unexecuted instantiation: xfs_dent.cpp:xfs_dir2_db_off_to_dataptr(XFS_INFO*, unsigned int, unsigned int) |
1266 | | |
1267 | | #ifdef __cplusplus |
1268 | | } |
1269 | | #endif |