#include #include #include #define B02_ALIGN(value, alignment) \ (((value) + (alignment) - 1) & ~((alignment) - 1)) #ifndef roundup2 #define roundup2(value, alignment) B02_ALIGN(value, alignment) #endif #ifdef B02_LINUX_REFERENCE typedef uint8_t u8; typedef uint8_t __u8; typedef uint32_t __u32; typedef uint16_t __le16; typedef uint32_t __le32; typedef uint64_t __le64; #define __packed __attribute__((__packed__)) #define BIT(nr) (1UL << (nr)) #define BIT_ULL(nr) (1ULL << (nr)) #define ALIGN(value, alignment) B02_ALIGN(value, alignment) #define round_up(value, alignment) ALIGN(value, alignment) #define le16_to_cpu(value) (value) #define cpu_to_le64(value) (value) #define BUILD_BUG_ON(condition) ((void)sizeof(condition)) #include "../../../../src-linux/erofs_fs.h" #define EXPECTED_ALIGN(freebsd, linux) (linux) #else #include "../../../src/erofs_fs.h" #define EXPECTED_ALIGN(freebsd, linux) (freebsd) #endif #define ASSERT_RECORD(type, size, freebsd_align, linux_align) \ _Static_assert(sizeof(type) == (size), "size " #type); \ _Static_assert(_Alignof(type) == \ EXPECTED_ALIGN(freebsd_align, linux_align), "alignment " #type) #define ASSERT_OFFSET(type, field, offset) \ _Static_assert(offsetof(type, field) == (offset), \ "offset " #type "." #field) #define ASSERT_TYPE(type, field, expected) \ _Static_assert(__builtin_types_compatible_p( \ __typeof__(((type *)0)->field), expected), \ "underlying type " #type "." #field) #define ASSERT_FIELD(type, field, offset, expected) \ ASSERT_OFFSET(type, field, offset); \ ASSERT_TYPE(type, field, expected) ASSERT_RECORD(struct erofs_deviceslot, 128, 1, 4); ASSERT_FIELD(struct erofs_deviceslot, tag, 0, uint8_t[64]); ASSERT_FIELD(struct erofs_deviceslot, blocks_lo, 64, __le32); ASSERT_FIELD(struct erofs_deviceslot, uniaddr_lo, 68, __le32); ASSERT_FIELD(struct erofs_deviceslot, blocks_hi, 72, __le16); ASSERT_FIELD(struct erofs_deviceslot, uniaddr_hi, 74, __le16); ASSERT_FIELD(struct erofs_deviceslot, reserved, 76, uint8_t[52]); ASSERT_RECORD(struct erofs_super_block, 144, 1, 8); ASSERT_FIELD(struct erofs_super_block, magic, 0, __le32); ASSERT_FIELD(struct erofs_super_block, checksum, 4, __le32); ASSERT_FIELD(struct erofs_super_block, feature_compat, 8, __le32); ASSERT_FIELD(struct erofs_super_block, blkszbits, 12, uint8_t); ASSERT_FIELD(struct erofs_super_block, sb_extslots, 13, uint8_t); ASSERT_OFFSET(struct erofs_super_block, rb, 14); ASSERT_FIELD(struct erofs_super_block, rb.rootnid_2b, 14, __le16); ASSERT_FIELD(struct erofs_super_block, rb.blocks_hi, 14, __le16); ASSERT_FIELD(struct erofs_super_block, inos, 16, __le64); ASSERT_FIELD(struct erofs_super_block, epoch, 24, __le64); ASSERT_FIELD(struct erofs_super_block, fixed_nsec, 32, __le32); ASSERT_FIELD(struct erofs_super_block, blocks_lo, 36, __le32); ASSERT_FIELD(struct erofs_super_block, meta_blkaddr, 40, __le32); ASSERT_FIELD(struct erofs_super_block, xattr_blkaddr, 44, __le32); ASSERT_FIELD(struct erofs_super_block, uuid, 48, uint8_t[16]); ASSERT_FIELD(struct erofs_super_block, volume_name, 64, uint8_t[16]); ASSERT_FIELD(struct erofs_super_block, feature_incompat, 80, __le32); ASSERT_OFFSET(struct erofs_super_block, u1, 84); ASSERT_FIELD(struct erofs_super_block, u1.available_compr_algs, 84, __le16); ASSERT_FIELD(struct erofs_super_block, u1.lz4_max_distance, 84, __le16); ASSERT_FIELD(struct erofs_super_block, extra_devices, 86, __le16); ASSERT_FIELD(struct erofs_super_block, devt_slotoff, 88, __le16); ASSERT_FIELD(struct erofs_super_block, dirblkbits, 90, uint8_t); ASSERT_FIELD(struct erofs_super_block, xattr_prefix_count, 91, uint8_t); ASSERT_FIELD(struct erofs_super_block, xattr_prefix_start, 92, __le32); ASSERT_FIELD(struct erofs_super_block, packed_nid, 96, __le64); ASSERT_FIELD(struct erofs_super_block, xattr_filter_reserved, 104, uint8_t); ASSERT_FIELD(struct erofs_super_block, ishare_xattr_prefix_id, 105, uint8_t); ASSERT_FIELD(struct erofs_super_block, reserved, 106, uint8_t[2]); ASSERT_FIELD(struct erofs_super_block, build_time, 108, __le32); ASSERT_FIELD(struct erofs_super_block, rootnid_8b, 112, __le64); ASSERT_FIELD(struct erofs_super_block, reserved2, 120, __le64); ASSERT_FIELD(struct erofs_super_block, metabox_nid, 128, __le64); ASSERT_FIELD(struct erofs_super_block, reserved3, 136, __le64); ASSERT_RECORD(struct erofs_inode_chunk_info, 4, 1, 2); ASSERT_FIELD(struct erofs_inode_chunk_info, format, 0, __le16); ASSERT_FIELD(struct erofs_inode_chunk_info, reserved, 2, __le16); ASSERT_RECORD(union erofs_inode_i_u, 4, 4, 4); ASSERT_FIELD(union erofs_inode_i_u, blocks_lo, 0, __le32); ASSERT_FIELD(union erofs_inode_i_u, startblk_lo, 0, __le32); ASSERT_FIELD(union erofs_inode_i_u, rdev, 0, __le32); ASSERT_FIELD(union erofs_inode_i_u, c, 0, struct erofs_inode_chunk_info); ASSERT_RECORD(union erofs_inode_i_nb, 2, 1, 1); ASSERT_FIELD(union erofs_inode_i_nb, nlink, 0, __le16); ASSERT_FIELD(union erofs_inode_i_nb, blocks_hi, 0, __le16); ASSERT_FIELD(union erofs_inode_i_nb, startblk_hi, 0, __le16); ASSERT_RECORD(struct erofs_inode_compact, 32, 1, 4); ASSERT_FIELD(struct erofs_inode_compact, i_format, 0, __le16); ASSERT_FIELD(struct erofs_inode_compact, i_xattr_icount, 2, __le16); ASSERT_FIELD(struct erofs_inode_compact, i_mode, 4, __le16); ASSERT_FIELD(struct erofs_inode_compact, i_nb, 6, union erofs_inode_i_nb); ASSERT_FIELD(struct erofs_inode_compact, i_size, 8, __le32); ASSERT_FIELD(struct erofs_inode_compact, i_mtime, 12, __le32); ASSERT_FIELD(struct erofs_inode_compact, i_u, 16, union erofs_inode_i_u); ASSERT_FIELD(struct erofs_inode_compact, i_ino, 20, __le32); ASSERT_FIELD(struct erofs_inode_compact, i_uid, 24, __le16); ASSERT_FIELD(struct erofs_inode_compact, i_gid, 26, __le16); ASSERT_FIELD(struct erofs_inode_compact, i_reserved, 28, __le32); ASSERT_RECORD(struct erofs_inode_extended, 64, 1, 8); ASSERT_FIELD(struct erofs_inode_extended, i_format, 0, __le16); ASSERT_FIELD(struct erofs_inode_extended, i_xattr_icount, 2, __le16); ASSERT_FIELD(struct erofs_inode_extended, i_mode, 4, __le16); ASSERT_FIELD(struct erofs_inode_extended, i_nb, 6, union erofs_inode_i_nb); ASSERT_FIELD(struct erofs_inode_extended, i_size, 8, __le64); ASSERT_FIELD(struct erofs_inode_extended, i_u, 16, union erofs_inode_i_u); ASSERT_FIELD(struct erofs_inode_extended, i_ino, 20, __le32); ASSERT_FIELD(struct erofs_inode_extended, i_uid, 24, __le32); ASSERT_FIELD(struct erofs_inode_extended, i_gid, 28, __le32); ASSERT_FIELD(struct erofs_inode_extended, i_mtime, 32, __le64); ASSERT_FIELD(struct erofs_inode_extended, i_mtime_nsec, 40, __le32); ASSERT_FIELD(struct erofs_inode_extended, i_nlink, 44, __le32); ASSERT_FIELD(struct erofs_inode_extended, i_reserved2, 48, uint8_t[16]); ASSERT_RECORD(struct erofs_xattr_ibody_header, 12, 1, 4); ASSERT_FIELD(struct erofs_xattr_ibody_header, h_name_filter, 0, __le32); ASSERT_FIELD(struct erofs_xattr_ibody_header, h_shared_count, 4, uint8_t); ASSERT_FIELD(struct erofs_xattr_ibody_header, h_reserved2, 5, uint8_t[7]); ASSERT_FIELD(struct erofs_xattr_ibody_header, h_shared_xattrs, 12, __le32[]); ASSERT_RECORD(struct erofs_xattr_entry, 4, 1, 2); ASSERT_FIELD(struct erofs_xattr_entry, e_name_len, 0, uint8_t); ASSERT_FIELD(struct erofs_xattr_entry, e_name_index, 1, uint8_t); ASSERT_FIELD(struct erofs_xattr_entry, e_value_size, 2, __le16); ASSERT_FIELD(struct erofs_xattr_entry, e_name, 4, char[]); ASSERT_RECORD(struct erofs_xattr_long_prefix, 1, 1, 1); ASSERT_FIELD(struct erofs_xattr_long_prefix, base_index, 0, uint8_t); ASSERT_FIELD(struct erofs_xattr_long_prefix, infix, 1, char[]); ASSERT_RECORD(struct erofs_inode_chunk_index, 8, 1, 4); ASSERT_FIELD(struct erofs_inode_chunk_index, startblk_hi, 0, __le16); ASSERT_FIELD(struct erofs_inode_chunk_index, device_id, 2, __le16); ASSERT_FIELD(struct erofs_inode_chunk_index, startblk_lo, 4, __le32); ASSERT_RECORD(struct erofs_dirent, 12, 1, 1); ASSERT_FIELD(struct erofs_dirent, nid, 0, __le64); ASSERT_FIELD(struct erofs_dirent, nameoff, 8, __le16); ASSERT_FIELD(struct erofs_dirent, file_type, 10, uint8_t); ASSERT_FIELD(struct erofs_dirent, reserved, 11, uint8_t); ASSERT_RECORD(struct z_erofs_lz4_cfgs, 14, 1, 1); ASSERT_FIELD(struct z_erofs_lz4_cfgs, max_distance, 0, __le16); ASSERT_FIELD(struct z_erofs_lz4_cfgs, max_pclusterblks, 2, __le16); ASSERT_FIELD(struct z_erofs_lz4_cfgs, reserved, 4, uint8_t[10]); ASSERT_RECORD(struct z_erofs_lzma_cfgs, 14, 1, 1); ASSERT_FIELD(struct z_erofs_lzma_cfgs, dict_size, 0, __le32); ASSERT_FIELD(struct z_erofs_lzma_cfgs, format, 4, __le16); ASSERT_FIELD(struct z_erofs_lzma_cfgs, reserved, 6, uint8_t[8]); ASSERT_RECORD(struct z_erofs_deflate_cfgs, 6, 1, 1); ASSERT_FIELD(struct z_erofs_deflate_cfgs, windowbits, 0, uint8_t); ASSERT_FIELD(struct z_erofs_deflate_cfgs, reserved, 1, uint8_t[5]); ASSERT_RECORD(struct z_erofs_zstd_cfgs, 6, 1, 1); ASSERT_FIELD(struct z_erofs_zstd_cfgs, format, 0, uint8_t); ASSERT_FIELD(struct z_erofs_zstd_cfgs, windowlog, 1, uint8_t); ASSERT_FIELD(struct z_erofs_zstd_cfgs, reserved, 2, uint8_t[4]); ASSERT_RECORD(struct z_erofs_map_header, 8, 1, 4); ASSERT_FIELD(struct z_erofs_map_header, h_fragmentoff, 0, __le32); ASSERT_FIELD(struct z_erofs_map_header, h_reserved1, 0, __le16); ASSERT_FIELD(struct z_erofs_map_header, h_idata_size, 2, __le16); ASSERT_FIELD(struct z_erofs_map_header, h_extents_lo, 0, __le32); ASSERT_FIELD(struct z_erofs_map_header, h_advise, 4, __le16); ASSERT_FIELD(struct z_erofs_map_header, h_algorithmtype, 6, uint8_t); ASSERT_FIELD(struct z_erofs_map_header, h_clusterbits, 7, uint8_t); ASSERT_FIELD(struct z_erofs_map_header, h_extents_hi, 6, __le16); ASSERT_RECORD(struct z_erofs_lcluster_index, 8, 1, 4); ASSERT_FIELD(struct z_erofs_lcluster_index, di_advise, 0, __le16); ASSERT_FIELD(struct z_erofs_lcluster_index, di_clusterofs, 2, __le16); ASSERT_FIELD(struct z_erofs_lcluster_index, di_u.blkaddr, 4, __le32); ASSERT_FIELD(struct z_erofs_lcluster_index, di_u.delta, 4, __le16[2]); ASSERT_RECORD(struct z_erofs_extent, 32, 1, 4); ASSERT_FIELD(struct z_erofs_extent, plen, 0, __le32); ASSERT_FIELD(struct z_erofs_extent, pstart_lo, 4, __le32); ASSERT_FIELD(struct z_erofs_extent, pstart_hi, 8, __le32); ASSERT_FIELD(struct z_erofs_extent, lstart_lo, 12, __le32); ASSERT_FIELD(struct z_erofs_extent, lstart_hi, 16, __le32); ASSERT_FIELD(struct z_erofs_extent, reserved, 20, uint8_t[12]); #define ASSERT_VALUE(expression, value) \ _Static_assert((expression) == (value), "value " #expression) ASSERT_VALUE(EROFS_SUPER_OFFSET, 1024); ASSERT_VALUE(EROFS_SB_EXTSLOT_SIZE, 16); ASSERT_VALUE(EROFS_DEVT_SLOT_SIZE, 128); ASSERT_VALUE(EROFS_FEATURE_COMPAT_SB_CHKSUM, 0x00000001); ASSERT_VALUE(EROFS_FEATURE_COMPAT_MTIME, 0x00000002); ASSERT_VALUE(EROFS_FEATURE_COMPAT_XATTR_FILTER, 0x00000004); ASSERT_VALUE(EROFS_FEATURE_COMPAT_SHARED_EA_IN_METABOX, 0x00000008); ASSERT_VALUE(EROFS_FEATURE_COMPAT_PLAIN_XATTR_PFX, 0x00000010); ASSERT_VALUE(EROFS_FEATURE_COMPAT_ISHARE_XATTRS, 0x00000020); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_LZ4_0PADDING, 0x00000001); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_COMPR_CFGS, 0x00000002); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER, 0x00000002); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_CHUNKED_FILE, 0x00000004); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_DEVICE_TABLE, 0x00000008); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_COMPR_HEAD2, 0x00000008); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_ZTAILPACKING, 0x00000010); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_FRAGMENTS, 0x00000020); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_DEDUPE, 0x00000020); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES, 0x00000040); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_48BIT, 0x00000080); ASSERT_VALUE(EROFS_FEATURE_INCOMPAT_METABOX, 0x00000100); ASSERT_VALUE(EROFS_ALL_FEATURE_INCOMPAT, 0x000001ff); ASSERT_VALUE(EROFS_INODE_FLAT_PLAIN, 0); ASSERT_VALUE(EROFS_INODE_COMPRESSED_FULL, 1); ASSERT_VALUE(EROFS_INODE_FLAT_INLINE, 2); ASSERT_VALUE(EROFS_INODE_COMPRESSED_COMPACT, 3); ASSERT_VALUE(EROFS_INODE_CHUNK_BASED, 4); ASSERT_VALUE(EROFS_INODE_DATALAYOUT_MAX, 5); ASSERT_VALUE(EROFS_I_VERSION_MASK, 0x01); ASSERT_VALUE(EROFS_I_DATALAYOUT_MASK, 0x07); ASSERT_VALUE(EROFS_I_VERSION_BIT, 0); ASSERT_VALUE(EROFS_I_DATALAYOUT_BIT, 1); ASSERT_VALUE(EROFS_I_NLINK_1_BIT, 4); ASSERT_VALUE(EROFS_I_DOT_OMITTED_BIT, 4); ASSERT_VALUE(EROFS_I_ALL, 31); ASSERT_VALUE(EROFS_CHUNK_FORMAT_BLKBITS_MASK, 0x001f); ASSERT_VALUE(EROFS_CHUNK_FORMAT_INDEXES, 0x0020); ASSERT_VALUE(EROFS_CHUNK_FORMAT_48BIT, 0x0040); ASSERT_VALUE(EROFS_CHUNK_FORMAT_ALL, 0x007f); ASSERT_VALUE(EROFS_INODE_LAYOUT_COMPACT, 0); ASSERT_VALUE(EROFS_INODE_LAYOUT_EXTENDED, 1); ASSERT_VALUE(EROFS_XATTR_INDEX_USER, 1); ASSERT_VALUE(EROFS_XATTR_INDEX_POSIX_ACL_ACCESS, 2); ASSERT_VALUE(EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT, 3); ASSERT_VALUE(EROFS_XATTR_INDEX_TRUSTED, 4); ASSERT_VALUE(EROFS_XATTR_INDEX_LUSTRE, 5); ASSERT_VALUE(EROFS_XATTR_INDEX_SECURITY, 6); ASSERT_VALUE(EROFS_XATTR_LONG_PREFIX, 0x80); ASSERT_VALUE(EROFS_XATTR_LONG_PREFIX_MASK, 0x7f); ASSERT_VALUE(EROFS_XATTR_ALIGN(0), 0); ASSERT_VALUE(EROFS_XATTR_ALIGN(1), 4); ASSERT_VALUE(EROFS_XATTR_ALIGN(5), 8); ASSERT_VALUE((uint64_t)EROFS_NULL_ADDR, UINT64_MAX); ASSERT_VALUE(EROFS_BLOCK_MAP_ENTRY_SIZE, 4); ASSERT_VALUE(EROFS_DIRENT_NID_METABOX_BIT, 63); ASSERT_VALUE(EROFS_DIRENT_NID_MASK, 0x7fffffffffffffffULL); ASSERT_VALUE(EROFS_NAME_LEN, 255); ASSERT_VALUE(Z_EROFS_PCLUSTER_MAX_SIZE, 1048576); ASSERT_VALUE(Z_EROFS_PCLUSTER_MAX_DSIZE, 12582912); ASSERT_VALUE(Z_EROFS_COMPRESSION_LZ4, 0); ASSERT_VALUE(Z_EROFS_COMPRESSION_LZMA, 1); ASSERT_VALUE(Z_EROFS_COMPRESSION_DEFLATE, 2); ASSERT_VALUE(Z_EROFS_COMPRESSION_ZSTD, 3); ASSERT_VALUE(Z_EROFS_COMPRESSION_MAX, 4); ASSERT_VALUE(Z_EROFS_ALL_COMPR_ALGS, 15); ASSERT_VALUE(Z_EROFS_LZMA_MAX_DICT_SIZE, 8388608); ASSERT_VALUE(Z_EROFS_ZSTD_MAX_DICT_SIZE, 1048576); ASSERT_VALUE(Z_EROFS_ADVISE_COMPACTED_2B, 0x0001); ASSERT_VALUE(Z_EROFS_ADVISE_EXTENTS, 0x0001); ASSERT_VALUE(Z_EROFS_ADVISE_BIG_PCLUSTER_1, 0x0002); ASSERT_VALUE(Z_EROFS_ADVISE_BIG_PCLUSTER_2, 0x0004); ASSERT_VALUE(Z_EROFS_ADVISE_INLINE_PCLUSTER, 0x0008); ASSERT_VALUE(Z_EROFS_ADVISE_INTERLACED_PCLUSTER, 0x0010); ASSERT_VALUE(Z_EROFS_ADVISE_FRAGMENT_PCLUSTER, 0x0020); ASSERT_VALUE(Z_EROFS_ADVISE_EXTRECSZ_BIT, 1); ASSERT_VALUE(Z_EROFS_ADVISE_EXTRECSZ_MASK, 3); ASSERT_VALUE(Z_EROFS_FRAGMENT_INODE_BIT, 7); ASSERT_VALUE(Z_EROFS_LCLUSTER_TYPE_PLAIN, 0); ASSERT_VALUE(Z_EROFS_LCLUSTER_TYPE_HEAD1, 1); ASSERT_VALUE(Z_EROFS_LCLUSTER_TYPE_NONHEAD, 2); ASSERT_VALUE(Z_EROFS_LCLUSTER_TYPE_HEAD2, 3); ASSERT_VALUE(Z_EROFS_LCLUSTER_TYPE_MAX, 4); ASSERT_VALUE(Z_EROFS_LI_LCLUSTER_TYPE_MASK, 3); ASSERT_VALUE(Z_EROFS_LI_PARTIAL_REF, 0x8000); ASSERT_VALUE(Z_EROFS_LI_D0_CBLKCNT, 0x0800); ASSERT_VALUE(Z_EROFS_MAP_HEADER_END(0), 8); ASSERT_VALUE(Z_EROFS_MAP_HEADER_END(1), 16); ASSERT_VALUE(Z_EROFS_FULL_INDEX_START(1), 24); ASSERT_VALUE(Z_EROFS_EXTENT_PLEN_PARTIAL, 0x08000000); ASSERT_VALUE(Z_EROFS_EXTENT_PLEN_FMT_BIT, 28); ASSERT_VALUE(Z_EROFS_EXTENT_PLEN_MASK, 0x001fffff); #ifndef B02_LINUX_REFERENCE ASSERT_VALUE(EROFS_SUPER_MAGIC_V1, 0xE0F5E1E2); ASSERT_VALUE(EROFS_INODE_LAYOUT_PLAIN, EROFS_INODE_FLAT_PLAIN); ASSERT_VALUE(EROFS_DIRENT_NID_METABOX, 0x8000000000000000ULL); ASSERT_VALUE(EROFS_FT_UNKNOWN, 0); ASSERT_VALUE(EROFS_FT_REG_FILE, 1); ASSERT_VALUE(EROFS_FT_DIR, 2); ASSERT_VALUE(EROFS_FT_CHRDEV, 3); ASSERT_VALUE(EROFS_FT_BLKDEV, 4); ASSERT_VALUE(EROFS_FT_FIFO, 5); ASSERT_VALUE(EROFS_FT_SOCK, 6); ASSERT_VALUE(EROFS_FT_SYMLINK, 7); #endif int main(void) { return (0); }