Coverage Report

Created: 2025-08-29 06:55

/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