diff --git a/tsk/fs/tsk_xfs.h b/tsk/fs/tsk_xfs.h index 9b79bb11347b3448099a8e9caf81f21985a10116..66967e78aaec3c6b9b3a0539606cd715ef24731f 100644 --- a/tsk/fs/tsk_xfs.h +++ b/tsk/fs/tsk_xfs.h @@ -155,41 +155,41 @@ typedef uint32_t xfs_alloc_ptr_t; #define XFS_IN_IXOTH 0000001 /* size of a short form block: -* uint32_t bb_magic; -* uint16_t bb_level; -* uint16_t bb_numrecs; +* uint32_t bb_magic; +* uint16_t bb_level; +* uint16_t bb_numrecs; * + -* uint32_t bb_leftsib -* uint32_t bb_rightsib +* uint32_t bb_leftsib +* uint32_t bb_rightsib */ #define XFS_BTREE_SBLOCK_LEN \ - (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + \ - sizeof(uint32_t) + sizeof(uint32_t)) + (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + \ + sizeof(uint32_t) + sizeof(uint32_t)) /* sizes of CRC enabled btree blocks: -* uint32_t bb_magic; -* uint16_t bb_level; -* uint16_t bb_numrecs; +* uint32_t bb_magic; +* uint16_t bb_level; +* uint16_t bb_numrecs; * + -* uint32_t bb_leftsib -* uint32_t bb_rightsib -* uint64_t bb_blkno; -* uint64_t bb_lsn; -* xfs_uuid_t bb_uuid; -* uint32_t bb_owner; -* uint32_t bb_crc; +* uint32_t bb_leftsib +* uint32_t bb_rightsib +* uint64_t bb_blkno; +* uint64_t bb_lsn; +* xfs_uuid_t bb_uuid; +* uint32_t bb_owner; +* uint32_t bb_crc; */ #define XFS_BTREE_SBLOCK_CRC_LEN \ - (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + \ - sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + \ + (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + \ + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + \ sizeof(xfs_uuid_t) + sizeof(uint32_t) + sizeof(uint32_t)) /* * Btree block header size depends on a superblock flag. */ #define XFS_INOBT_BLOCK_LEN(sb) \ - (xfs_sb_version_hascrc(sb) ? \ - XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) + (xfs_sb_version_hascrc(sb) ? \ + XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) typedef struct xfs_btree_sblock xfs_inobt_block_t; @@ -311,14 +311,14 @@ typedef struct xfs_dir2_sf { * NOTE: the INCOMPLETE bit must not collide with the flags bits specified * on the system call, they are "or"ed together for various operations. */ -#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ -#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ -#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ -#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ -#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) -#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) -#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) -#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) +#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ +#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ +#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ +#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ +#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) +#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) +#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) #define ATTR_SF_HDR_SIZE 3 struct xfs_attr_sf_hdr { @@ -498,24 +498,38 @@ typedef struct xfs_dir2_leaf_entry { xfs_dir2_dataptr_t address; } xfs_dir2_leaf_entry_t; -#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ -#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) -#define XFS_DIR2_LEAF_SPACE 1 -#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) -#define XFS_DIR2_FREE_SPACE 2 -#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) +#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ +#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) +#define XFS_DIR2_LEAF_SPACE 1 +#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) +#define XFS_DIR2_FREE_SPACE 2 +#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) /* ** Super Block and related definitions */ -#define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ -#define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ -#define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ -#define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ -#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ -#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ +#define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ +#define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ +#define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ +#define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ +#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ +#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ +#define XFS_SB_VERSION_NUMBITS 0x000f +#define XFS_SB_VERSION_ALLFBITS 0xfff0 +#define XFS_SB_VERSION_ATTRBIT 0x0010 +#define XFS_SB_VERSION_NLINKBIT 0x0020 +#define XFS_SB_VERSION_QUOTABIT 0x0040 +#define XFS_SB_VERSION_ALIGNBIT 0x0080 +#define XFS_SB_VERSION_DALIGNBIT 0x0100 +#define XFS_SB_VERSION_SHAREDBIT 0x0200 +#define XFS_SB_VERSION_LOGV2BIT 0x0400 +#define XFS_SB_VERSION_SECTORBIT 0x0800 +#define XFS_SB_VERSION_EXTFLGBIT 0x1000 +#define XFS_SB_VERSION_DIRV2BIT 0x2000 +#define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ +#define XFS_SB_VERSION_MOREBITSBIT 0x8000 /* * There are two words to hold XFS "feature" bits: the original @@ -533,9 +547,9 @@ typedef struct xfs_dir2_leaf_entry { #define XFS_SB_VERSION2_CRCBIT 0x00000100 /* metadata CRCs */ #define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ -#define XFS_SB_VERSION2_OKBITS \ - (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ - XFS_SB_VERSION2_ATTR2BIT | \ +#define XFS_SB_VERSION2_OKBITS \ + (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ + XFS_SB_VERSION2_ATTR2BIT | \ XFS_SB_VERSION2_PROJID32BIT | \ XFS_SB_VERSION2_FTYPE) @@ -666,13 +680,103 @@ typedef struct xfs_sb xfs_ino_t sb_rrmapino; } xfs_sb_t; +static inline bool xfs_sb_has_incompat_feature(xfs_sb *sb, uint32_t feature) +{ + return (sb->sb_features_incompat & feature) != 0; +} +static inline bool xfs_sb_version_hasattr(xfs_sb *sb) +{ + return (sb->sb_versionnum & XFS_SB_VERSION_ATTRBIT); +} +static inline int xfs_sb_version_hasnlink(xfs_sb *sb) +{ + return sb->sb_versionnum == XFS_SB_VERSION_3 || + (XFS_SB_VERSION_NUM(sb) >= XFS_SB_VERSION_4 && + (sb->sb_versionnum & XFS_SB_VERSION_NLINKBIT)); +} +static inline bool xfs_sb_version_hasquota(xfs_sb *sb) +{ + return (sb->sb_versionnum & XFS_SB_VERSION_QUOTABIT); +} +static inline bool xfs_sb_version_hasalign(xfs_sb *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5 || + (sb->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)); +} +static inline bool xfs_sb_version_hasdalign(xfs_sb *sb) +{ + return (sb->sb_versionnum & XFS_SB_VERSION_DALIGNBIT); +} +static inline int xfs_sb_version_hasshared(xfs_sb_t *sb) +{ + return XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_4 && + (sb->sb_versionnum & XFS_SB_VERSION_SHAREDBIT); +} +static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) || + (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_4 && + (sb->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)); +} +static inline bool xfs_sb_version_haslogv2(xfs_sb *sb) +{ + return XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5 || + (sb->sb_versionnum & XFS_SB_VERSION_LOGV2BIT); +} +static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) || + (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_4 && + (sb->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)); +} +static inline bool xfs_sb_version_hassector(xfs_sb *sb) +{ + return (sb->sb_versionnum & XFS_SB_VERSION_SECTORBIT); +} +static inline bool xfs_sb_version_hasasciici(xfs_sb *sb) +{ + return (sb->sb_versionnum & XFS_SB_VERSION_BORGBIT); +} +static inline bool xfs_sb_version_hasmorebits(xfs_sb *sb) +{ + return XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5 || + (sb->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT); +} +static inline bool xfs_sb_version_hasattr2(xfs_sb *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) || + (xfs_sb_version_hasmorebits(sb) && + (sb->sb_features2 & XFS_SB_VERSION2_ATTR2BIT)); +} +static inline bool xfs_sb_version_haslazysbcount(xfs_sb *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) || + (xfs_sb_version_hasmorebits(sb) && + (sb->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT)); +} +static inline bool xfs_sb_version_hasprojid32bit(xfs_sb *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) || + (xfs_sb_version_hasmorebits(sb) && + (sb->sb_features2 & XFS_SB_VERSION2_PROJID32BIT)); +} + /* * V5 superblock specific feature checks */ static inline bool xfs_sb_version_hascrc(xfs_sb *sb) { - return sb->sb_versionnum == XFS_SB_VERSION_5; + return sb->sb_versionnum == XFS_SB_VERSION_5; } +static inline int xfs_sb_version_hasftype(xfs_sb *sb) +{ + return (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5 && + xfs_sb_has_incompat_feature(sb, XFS_SB_FEAT_INCOMPAT_FTYPE)) || + (xfs_sb_version_hasmorebits(sb) && + (sb->sb_features2 & XFS_SB_VERSION2_FTYPE)); +} + + /* * Structure of an xfs file system handle. diff --git a/tsk/fs/xfs.cpp b/tsk/fs/xfs.cpp index 94554f5a8d976ba0efce901aea3e837bcfb6e17d..09a4bf7cf71bd24070f2ba6650716cf127aee835 100644 --- a/tsk/fs/xfs.cpp +++ b/tsk/fs/xfs.cpp @@ -1101,7 +1101,7 @@ xfs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr) } uint64_t aginode_num = rel_blk * (uint64_t) sb->sb_inopblock; - uint64_t inode_num = (uint64_t) ag_num << sb->sb_agblklog + aginode_num; + uint64_t inode_num = (uint64_t) ag_num << (sb->sb_agblklog + aginode_num); // Pet trick here: if the block possibly stores inodes, try to read the corresponding inode flags if (tsk_verbose) { tsk_fprintf(stderr, "trying to treat rel_block %" PRId64 " in ag %" PRId64 " as rel inode %" PRId64 " (abs inode %" PRId64 ") \n", rel_blk, ag_num, aginode_num, inode_num); } @@ -1521,6 +1521,54 @@ static uint8_t tsk_getu16(fs->endian, &sb->sb_uuid.b[8]), tsk_getu32(fs->endian, &sb->sb_uuid.b[10]), tsk_getu16(fs->endian, &sb->sb_uuid.b[14])); + + tsk_fprintf(hFile, "Version: %"); + if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_1) + tsk_fprintf(hFile, "V1"); + else if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_2) + tsk_fprintf(hFile, "V2"); + else if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_3) + tsk_fprintf(hFile, "V3"); + else if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_4) + tsk_fprintf(hFile, "V4"); + else if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) + tsk_fprintf(hFile, "V5"); + if (xfs_sb_version_hasattr(sb)) + tsk_fprintf(hFile, ",ATTR"); + if (xfs_sb_version_hasnlink(sb)) + tsk_fprintf(hFile, ",NLINK"); + if (xfs_sb_version_hasquota(sb)) + tsk_fprintf(hFile, ",QUOTA"); + if (xfs_sb_version_hasalign(sb)) + tsk_fprintf(hFile, ",ALIGN"); + if (xfs_sb_version_hasdalign(sb)) + tsk_fprintf(hFile, ",DALIGN"); + if (xfs_sb_version_hasshared(sb)) + tsk_fprintf(hFile, ",SHARED"); + if (xfs_sb_version_hasdirv2(sb)) + tsk_fprintf(hFile, ",DIRV2"); + if (xfs_sb_version_haslogv2(sb)) + tsk_fprintf(hFile, ",LOGV2"); + if (xfs_sb_version_hasextflgbit(sb)) + tsk_fprintf(hFile, ",EXTFLG"); + if (xfs_sb_version_hassector(sb)) + tsk_fprintf(hFile, ",SECTOR"); + if (xfs_sb_version_hasasciici(sb)) + tsk_fprintf(hFile, ",ASCII_CI"); + if (xfs_sb_version_hasmorebits(sb)) + tsk_fprintf(hFile, ",MOREBITS"); + if (xfs_sb_version_hasattr2(sb)) + tsk_fprintf(hFile, ",ATTR2"); + if (xfs_sb_version_haslazysbcount(sb)) + tsk_fprintf(hFile, ",LAZYSBCOUNT"); + if (xfs_sb_version_hasprojid32bit(sb)) + tsk_fprintf(hFile, ",PROJID32BIT"); + if (xfs_sb_version_hascrc(sb)) + tsk_fprintf(hFile, ",CRC"); + if (xfs_sb_version_hasftype(sb)) + tsk_fprintf(hFile, ",FTYPE"); + tsk_fprintf(hFile, "\n"); + tsk_fprintf(hFile, "Features Compat: %" PRIu32 "\n", sb->sb_features_compat); tsk_fprintf(hFile, "Features Read-Only Compat: %" PRIu32 "\n", sb->sb_features_ro_compat); if (sb->sb_features_ro_compat) { @@ -1650,7 +1698,7 @@ parse_extended_attrs(XFSFS_INFO *a_xfsfs, xfs_dinode_t *a_dino_buf, FILE *a_hFil tsk_fprintf(a_hFile, "\nExtended Attributes: \n"); - void* in_base = (void*) &a_dino_buf->di_core; + uint8_t *in_base = (uint8_t*) &a_dino_buf->di_core; uint64_t in_offset = a_xfsfs->inode_size - XFS_DFORK_ASIZE(&a_dino_buf->di_core, a_xfsfs); @@ -1717,6 +1765,12 @@ parse_extended_attrs(XFSFS_INFO *a_xfsfs, xfs_dinode_t *a_dino_buf, FILE *a_hFil sf_entry = (xfs_attr_sf_entry*) (in_base + in_offset); } } + else + { + tsk_fprintf(a_hFile, "xfs_istat: parsing non-XFS_DINODE_FMT_LOCAL" + "long-form attributes (%d) is not supported yet \n", + a_dino_buf->di_core.di_aformat); + } } /** @@ -2966,6 +3020,11 @@ TSK_FS_INFO * return NULL; } + if(XFS_SB_VERSION_NUM(sb) > 4) + { + tsk_fprintf(stderr, "Version 5 and newer are not fully supported yet, be careful (current version: %d) \n", XFS_SB_VERSION_NUM(sb)); + } + len = sizeof(xfs_agi) * xfsfs->fs->sb_agcount; if ((agi = static_cast<xfs_agi *>(tsk_malloc(len))) == NULL) return NULL;