* %End-Header%
*/
+#include "config.h"
#include "ext2fs.h"
/*
}
/*
+ * Return the number of blocks in a group
+ */
+int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group)
+{
+ int num_blocks;
+
+ if (group == fs->group_desc_count - 1) {
+ num_blocks = (ext2fs_blocks_count(fs->super) -
+ fs->super->s_first_data_block) %
+ fs->super->s_blocks_per_group;
+ if (!num_blocks)
+ num_blocks = fs->super->s_blocks_per_group;
+ } else
+ num_blocks = fs->super->s_blocks_per_group;
+
+ return num_blocks;
+}
+
+/*
* Return the inode data block count
*/
blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
struct ext2_inode *inode)
{
return (inode->i_blocks |
- (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
+ ((fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
+ (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
(inode->i_file_acl ? fs->blocksize >> 9 : 0);
}
struct ext2_inode *inode)
{
return (inode->i_blocks |
- (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ?
+ ((fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ?
(__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
}
* do the swap there.
*/
struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
- struct ext2_group_desc *gdp,
+ struct opaque_ext2_group_desc *gdp,
dgrp_t group)
{
if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT)
return (struct ext2_group_desc *) gdp + group;
}
+/* Do the same but as an ext4 group desc for internal use here */
+static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
+ struct opaque_ext2_group_desc *gdp,
+ dgrp_t group)
+{
+ return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group);
+}
+
+/*
+ * Return the block bitmap checksum of a group
+ */
+__u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group)
+{
+ struct ext4_group_desc *gdp;
+ __u32 csum;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ csum = gdp->bg_block_bitmap_csum_lo;
+ if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+ csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16);
+ return csum;
+}
+
/*
* Return the block bitmap block of a group
*/
blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- return gdp->bg_block_bitmap |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u64) gdp->bg_block_bitmap_hi << 32 : 0);
- }
+ struct ext4_group_desc *gdp;
- return fs->group_desc[group].bg_block_bitmap;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_block_bitmap |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64)gdp->bg_block_bitmap_hi << 32 : 0);
}
/*
*/
void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_block_bitmap = blk;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
- } else
- fs->group_desc[group].bg_block_bitmap = blk;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_block_bitmap = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
+}
+
+/*
+ * Return the inode bitmap checksum of a group
+ */
+__u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group)
+{
+ struct ext4_group_desc *gdp;
+ __u32 csum;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ csum = gdp->bg_inode_bitmap_csum_lo;
+ if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
+ csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16);
+ return csum;
}
/*
*/
blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- return gdp->bg_inode_bitmap |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
- }
-
- return fs->group_desc[group].bg_inode_bitmap;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_inode_bitmap |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
}
/*
*/
void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_inode_bitmap = blk;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
- } else
- fs->group_desc[group].bg_inode_bitmap = blk;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_inode_bitmap = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
}
/*
*/
blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- return gdp->bg_inode_table |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u64) gdp->bg_inode_table_hi << 32 : 0);
- }
+ struct ext4_group_desc *gdp;
- return fs->group_desc[group].bg_inode_table;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_inode_table |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64) gdp->bg_inode_table_hi << 32 : 0);
}
/*
*/
void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_inode_table = blk;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_inode_table_hi = (__u64) blk >> 32;
- } else
- fs->group_desc[group].bg_inode_table = blk;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_inode_table = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_inode_table_hi = (__u64) blk >> 32;
}
/*
*/
__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- return gdp->bg_free_blocks_count |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
- }
-
- return fs->group_desc[group].bg_free_blocks_count;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_free_blocks_count |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
}
/*
*/
void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_free_blocks_count = n;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
- } else
- fs->group_desc[group].bg_free_blocks_count = n;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_free_blocks_count = n;
+
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
}
/*
*/
__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- return gdp->bg_free_inodes_count |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
- }
-
- return fs->group_desc[group].bg_free_inodes_count;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_free_inodes_count |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
}
/*
*/
void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_free_inodes_count = n;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
- } else
- fs->group_desc[group].bg_free_inodes_count = n;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_free_inodes_count = n;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
}
/*
*/
__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- return gdp->bg_used_dirs_count |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
- }
+ struct ext4_group_desc *gdp;
- return fs->group_desc[group].bg_used_dirs_count;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_used_dirs_count |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
}
/*
*/
void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_used_dirs_count = n;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
- } else
- fs->group_desc[group].bg_used_dirs_count = n;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_used_dirs_count = n;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
}
/*
*/
__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- return gdp->bg_itable_unused |
- (fs->super->s_feature_incompat
- & EXT4_FEATURE_INCOMPAT_64BIT ?
- (__u32) gdp->bg_itable_unused_hi << 16 : 0);
- }
-
- return fs->group_desc[group].bg_itable_unused;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_itable_unused |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u32) gdp->bg_itable_unused_hi << 16 : 0);
}
/*
*/
void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
- gdp->bg_itable_unused = n;
- if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
- gdp->bg_itable_unused_hi = (__u32) n >> 16;
- } else
- fs->group_desc[group].bg_itable_unused = n;
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_itable_unused = n;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_itable_unused_hi = (__u32) n >> 16;
}
/*
*/
__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- return gdp->bg_flags;
- }
-
- return fs->group_desc[group].bg_flags;
-}
-
-/*
- * Set the flags for this block group
- */
-void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
-{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- gdp->bg_flags = bg_flags;
- return;
- }
+ struct ext4_group_desc *gdp;
- fs->group_desc[group].bg_flags = bg_flags;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_flags;
}
/*
- * Clear the flags for this block group
+ * Zero out the flags for this block group
*/
-void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
+void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- gdp->bg_flags = 0;
- return;
- }
+ struct ext4_group_desc *gdp;
- fs->group_desc[group].bg_flags = 0;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_flags = 0;
+ return;
}
/*
* Get the value of a particular flag for this block group
*/
-int ext2fs_bg_flag_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
+int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- return gdp->bg_flags & bg_flag;
- }
-
- return fs->group_desc[group].bg_flags & bg_flag;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_flags & bg_flag;
}
/*
- * Set a particular flag for this block group
+ * Set a flag or set of flags for this block group
*/
-void ext2fs_bg_flag_set(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
+void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- gdp->bg_flags |= bg_flag;
- return;
- }
-
- fs->group_desc[group].bg_flags |= bg_flag;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_flags |= bg_flags;
+ return;
}
/*
- * Clear a particular flag for this block group
+ * Clear a flag or set of flags for this block group
*/
-void ext2fs_bg_flag_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
+void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
+ struct ext4_group_desc *gdp;
- gdp->bg_flags &= ~bg_flag;
- return;
- }
-
- fs->group_desc[group].bg_flags &= ~bg_flag;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_flags &= ~bg_flags;
+ return;
}
/*
*/
__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- return gdp->bg_checksum;
- }
+ struct ext4_group_desc *gdp;
- return fs->group_desc[group].bg_checksum;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_checksum;
}
/*
*/
void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum)
{
- if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) {
- struct ext4_group_desc *gdp;
- gdp = (struct ext4_group_desc *) (fs->group_desc) + group;
-
- gdp->bg_checksum = checksum;
- return;
- }
+ struct ext4_group_desc *gdp;
- fs->group_desc[group].bg_checksum = checksum;
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_checksum = checksum;
+ return;
}
/*
* Get the acl block of a file
- *
- * XXX Ignoring 64-bit file system flag - most places where this is
- * called don't have access to the fs struct, and the high bits should
- * be 0 in the non-64-bit case anyway.
*/
-blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode)
+blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
{
- return (inode->i_file_acl |
- (__u64) inode->osd2.linux2.l_i_file_acl_high << 32);
+ blk64_t blk = inode->i_file_acl;
+
+ if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
+ return blk;
}
/*
* Set the acl block of a file
*/
-void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk)
+void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
+ blk64_t blk)
{
inode->i_file_acl = blk;
- inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
+ if (fs && fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
}