ext4 utils: Refactor read_ext, and expose some of the functions
Make read_ext an externally useable function. Use case is to
enable fast encryption by being able to look at whether each block
is in use or not.
Bug: 11985952
Change-Id: Ief71f408a55db7261c75ebe974620415ed8cfd29
diff --git a/ext4_utils/ext2simg.c b/ext4_utils/ext2simg.c
index 7b63836..6406729 100644
--- a/ext4_utils/ext2simg.c
+++ b/ext4_utils/ext2simg.c
@@ -53,66 +53,6 @@
fprintf(stderr, " -S don't use sparse output format\n");
}
-static int read_ext(int fd)
-{
- off64_t ret;
- struct ext4_super_block sb;
-
- ret = lseek64(fd, 1024, SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to superblock");
-
- ret = read(fd, &sb, sizeof(sb));
- if (ret < 0)
- critical_error_errno("failed to read superblock");
- if (ret != sizeof(sb))
- critical_error("failed to read all of superblock");
-
- ext4_parse_sb(&sb);
-
- ret = lseek64(fd, info.len, SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to end of input image");
-
- ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to block group descriptors");
-
- ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks);
- if (ret < 0)
- critical_error_errno("failed to read block group descriptors");
- if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks)
- critical_error("failed to read all of block group descriptors");
-
- if (verbose) {
- printf("Found filesystem with parameters:\n");
- printf(" Size: %llu\n", info.len);
- printf(" Block size: %d\n", info.block_size);
- printf(" Blocks per group: %d\n", info.blocks_per_group);
- printf(" Inodes per group: %d\n", info.inodes_per_group);
- printf(" Inode size: %d\n", info.inode_size);
- printf(" Label: %s\n", info.label);
- printf(" Blocks: %llu\n", aux_info.len_blocks);
- printf(" Block groups: %d\n", aux_info.groups);
- printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
- printf(" Used %d/%d inodes and %d/%d blocks\n",
- aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
- aux_info.sb->s_inodes_count,
- aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
- aux_info.sb->s_blocks_count_lo);
- }
-
- return 0;
-}
-
-static int bitmap_get_bit(u8 *bitmap, u32 bit)
-{
- if (bitmap[bit / 8] & 1 << (bit % 8))
- return 1;
-
- return 0;
-}
-
static int build_sparse_ext(int fd, const char *filename)
{
unsigned int i;
@@ -228,7 +168,7 @@
if (infd < 0)
critical_error_errno("failed to open input image");
- read_ext(infd);
+ read_ext(infd, verbose);
info.sparse_file = sparse_file_new(info.block_size, info.len);
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index d4fbc7c..1b70afe 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -62,6 +62,21 @@
return (a == b) ? 1 : 0;
}
+int bitmap_get_bit(u8 *bitmap, u32 bit)
+{
+ if (bitmap[bit / 8] & (1 << (bit % 8)))
+ return 1;
+
+ return 0;
+}
+
+void bitmap_clear_bit(u8 *bitmap, u32 bit)
+{
+ bitmap[bit / 8] &= ~(1 << (bit % 8));
+
+ return;
+}
+
/* Returns 1 if the bg contains a backup superblock. On filesystems with
the sparse_super feature, only block groups 0, 1, and powers of 3, 5,
and 7 have backup superblocks. Otherwise, all block groups have backup
@@ -81,6 +96,38 @@
return 0;
}
+/* Function to read the primary superblock */
+void read_sb(int fd, struct ext4_super_block *sb)
+{
+ off64_t ret;
+
+ ret = lseek64(fd, 1024, SEEK_SET);
+ if (ret < 0)
+ critical_error_errno("failed to seek to superblock");
+
+ ret = read(fd, sb, sizeof(*sb));
+ if (ret < 0)
+ critical_error_errno("failed to read superblock");
+ if (ret != sizeof(*sb))
+ critical_error("failed to read all of superblock");
+}
+
+/* Function to write a primary or backup superblock at a given offset */
+void write_sb(int fd, unsigned long long offset, struct ext4_super_block *sb)
+{
+ off64_t ret;
+
+ ret = lseek64(fd, offset, SEEK_SET);
+ if (ret < 0)
+ critical_error_errno("failed to seek to superblock");
+
+ ret = write(fd, sb, sizeof(*sb));
+ if (ret < 0)
+ critical_error_errno("failed to write superblock");
+ if (ret != sizeof(*sb))
+ critical_error("failed to write all of superblock");
+}
+
/* Write the filesystem image to a file */
void write_ext4_image(int fd, int gz, int sparse, int crc)
{
@@ -450,3 +497,48 @@
return num;
}
+
+int read_ext(int fd, int verbose)
+{
+ off64_t ret;
+ struct ext4_super_block sb;
+
+ read_sb(fd, &sb);
+
+ ext4_parse_sb(&sb);
+
+ ret = lseek64(fd, info.len, SEEK_SET);
+ if (ret < 0)
+ critical_error_errno("failed to seek to end of input image");
+
+ ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET);
+ if (ret < 0)
+ critical_error_errno("failed to seek to block group descriptors");
+
+ ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks);
+ if (ret < 0)
+ critical_error_errno("failed to read block group descriptors");
+ if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks)
+ critical_error("failed to read all of block group descriptors");
+
+ if (verbose) {
+ printf("Found filesystem with parameters:\n");
+ printf(" Size: %llu\n", info.len);
+ printf(" Block size: %d\n", info.block_size);
+ printf(" Blocks per group: %d\n", info.blocks_per_group);
+ printf(" Inodes per group: %d\n", info.inodes_per_group);
+ printf(" Inode size: %d\n", info.inode_size);
+ printf(" Label: %s\n", info.label);
+ printf(" Blocks: %llu\n", aux_info.len_blocks);
+ printf(" Block groups: %d\n", aux_info.groups);
+ printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
+ printf(" Used %d/%d inodes and %d/%d blocks\n",
+ aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
+ aux_info.sb->s_inodes_count,
+ aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
+ aux_info.sb->s_blocks_count_lo);
+ }
+
+ return 0;
+}
+
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 1e13a90..7f96ac2 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -156,7 +156,11 @@
return i - 1;
}
+int bitmap_get_bit(u8 *bitmap, u32 bit);
+void bitmap_clear_bit(u8 *bitmap, u32 bit);
int ext4_bg_has_super_block(int bg);
+void read_sb(int fd, struct ext4_super_block *sb);
+void write_sb(int fd, unsigned long long offset, struct ext4_super_block *sb);
void write_ext4_image(int fd, int gz, int sparse, int crc);
void ext4_create_fs_aux_info(void);
void ext4_free_fs_aux_info(void);
@@ -181,6 +185,8 @@
int sparse, int crc, int wipe,
struct selabel_handle *sehnd, int verbose, time_t fixed_time);
+int read_ext(int fd, int verbose);
+
#ifdef __cplusplus
}
#endif
diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c
index d271116..0e51765 100644
--- a/ext4_utils/ext4fixup.c
+++ b/ext4_utils/ext4fixup.c
@@ -83,42 +83,6 @@
return (group * new_inodes_per_group) + offset + 1;
}
-/* Function to read the primary superblock */
-static void read_sb(int fd, struct ext4_super_block *sb)
-{
- off64_t ret;
-
- ret = lseek64(fd, 1024, SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to superblock");
-
- ret = read(fd, sb, sizeof(*sb));
- if (ret < 0)
- critical_error_errno("failed to read superblock");
- if (ret != sizeof(*sb))
- critical_error("failed to read all of superblock");
-}
-
-/* Function to write a primary or backup superblock at a given offset */
-static void write_sb(int fd, unsigned long long offset, struct ext4_super_block *sb)
-{
- off64_t ret;
-
- if (no_write) {
- return;
- }
-
- ret = lseek64(fd, offset, SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to superblock");
-
- ret = write(fd, sb, sizeof(*sb));
- if (ret < 0)
- critical_error_errno("failed to write superblock");
- if (ret != sizeof(*sb))
- critical_error("failed to write all of superblock");
-}
-
static int get_fs_fixup_state(int fd)
{
unsigned long long magic;
@@ -191,64 +155,9 @@
/* we are done, so make the filesystem mountable again */
sb.s_desc_size &= ~1;
}
- write_sb(fd, 1024, &sb);
- return 0;
-}
-
-static int read_ext(int fd)
-{
- off64_t ret;
- struct ext4_super_block sb;
-
- read_sb(fd, &sb);
-
- ext4_parse_sb(&sb);
-
- if (info.feat_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) {
- critical_error("Filesystem needs recovery first, mount and unmount to do that\n");
- }
-
- /* Clear the low bit which is set while this tool is in progress.
- * If the tool crashes, it will still be set when we restart.
- * The low bit is set to make the filesystem unmountable while
- * it is being fixed up. Also allow 0, which means the old ext2
- * size is in use.
- */
- if (((sb.s_desc_size & ~1) != sizeof(struct ext2_group_desc)) &&
- ((sb.s_desc_size & ~1) != 0))
- critical_error("error: bg_desc_size != sizeof(struct ext2_group_desc)\n");
-
- ret = lseek64(fd, info.len, SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to end of input image");
-
- ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET);
- if (ret < 0)
- critical_error_errno("failed to seek to block group descriptors");
-
- ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks);
- if (ret < 0)
- critical_error_errno("failed to read block group descriptors");
- if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks)
- critical_error("failed to read all of block group descriptors");
-
- if (verbose) {
- printf("Found filesystem with parameters:\n");
- printf(" Size: %llu\n", info.len);
- printf(" Block size: %d\n", info.block_size);
- printf(" Blocks per group: %d\n", info.blocks_per_group);
- printf(" Inodes per group: %d\n", info.inodes_per_group);
- printf(" Inode size: %d\n", info.inode_size);
- printf(" Label: %s\n", info.label);
- printf(" Blocks: %llu\n", aux_info.len_blocks);
- printf(" Block groups: %d\n", aux_info.groups);
- printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks);
- printf(" Used %d/%d inodes and %d/%d blocks\n",
- aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count,
- aux_info.sb->s_inodes_count,
- aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
- aux_info.sb->s_blocks_count_lo);
+ if (!no_write) {
+ write_sb(fd, 1024, &sb);
}
return 0;
@@ -320,21 +229,6 @@
return 0;
}
-static int bitmap_get_bit(u8 *bitmap, u32 bit)
-{
- if (bitmap[bit / 8] & (1 << (bit % 8)))
- return 1;
-
- return 0;
-}
-
-static void bitmap_clear_bit(u8 *bitmap, u32 bit)
-{
- bitmap[bit / 8] &= ~(1 << (bit % 8));
-
- return;
-}
-
static void check_inode_bitmap(int fd, unsigned int bg_num)
{
unsigned int inode_bitmap_block_num;
@@ -425,7 +319,13 @@
sb.s_desc_size &= ~1;
}
- write_sb(fd, (unsigned long long)i * info.blocks_per_group * info.block_size + sb_offset, &sb);
+ if (!no_write) {
+ write_sb(fd,
+ (unsigned long long)i
+ * info.blocks_per_group * info.block_size
+ + sb_offset,
+ &sb);
+ }
ret = lseek64(fd, ((unsigned long long)i * info.blocks_per_group * info.block_size) +
(info.block_size * (aux_info.first_data_block + 1)), SEEK_SET);
@@ -805,7 +705,21 @@
if (fd < 0)
critical_error_errno("failed to open filesystem image");
- read_ext(fd);
+ read_ext(fd, verbose);
+
+ if (info.feat_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) {
+ critical_error("Filesystem needs recovery first, mount and unmount to do that\n");
+ }
+
+ /* Clear the low bit which is set while this tool is in progress.
+ * If the tool crashes, it will still be set when we restart.
+ * The low bit is set to make the filesystem unmountable while
+ * it is being fixed up. Also allow 0, which means the old ext2
+ * size is in use.
+ */
+ if (((aux_info.sb->s_desc_size & ~1) != sizeof(struct ext2_group_desc)) &&
+ ((aux_info.sb->s_desc_size & ~1) != 0))
+ critical_error("error: bg_desc_size != sizeof(struct ext2_group_desc)\n");
if ((info.feat_incompat & EXT4_FEATURE_INCOMPAT_FILETYPE) == 0) {
critical_error("Expected filesystem to have filetype flag set\n");