From 03c07275c17acf1286d939e8d558a754fa0353c9 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 1 Jan 1970 00:00:00 +0000 Subject: [PATCH] Store parsed superblock in private data. --- lib/diskimage_ext2.ml | 184 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 156 insertions(+), 28 deletions(-) diff --git a/lib/diskimage_ext2.ml b/lib/diskimage_ext2.ml index 09c7c58..3ce0819 100644 --- a/lib/diskimage_ext2.ml +++ b/lib/diskimage_ext2.ml @@ -31,11 +31,79 @@ let ( -* ) = Int32.sub let ( ** ) = Int32.mul let ( /* ) = Int32.div +(* The fields in an ext2/3 superblock. *) +type ext2_sb = { + s_inodes_count : int32; + s_blocks_count : int32; + s_r_blocks_count : int32; + s_free_blocks_count : int32; + s_free_inodes_count : int32; + s_first_data_block : int32; + s_log_block_size : int32; + s_log_frag_size : int32; + s_blocks_per_group : int32; + s_frags_per_group : int32; + s_inodes_per_group : int32; + s_mtime : int32; + s_wtime : int32; + s_mnt_count : int; + s_max_mnt_count : int; + s_state : int; + s_errors : int; + s_minor_rev_level : int; + s_lastcheck : int32; + s_checkinterval : int32; + s_creator_os : int32; + s_rev_level : int32; + s_def_resuid : int; + s_def_resgid : int; + s_first_ino : int32; + s_inode_size : int; + s_block_group_nr : int; + s_feature_compat : int32; + s_feature_incompat : int32; + s_feature_ro_compat : int32; + s_uuid : string; + s_volume_name : string; + s_last_mounted : string; + s_algorithm_usage_bitmap : int32; + s_prealloc_blocks : int; + s_prealloc_dir_blocks : int; + s_reserved_gdt_blocks : int; + s_journal_uuid : string; + s_journal_inum : int32; + s_journal_dev : int32; + s_last_orphan : int32; + s_hash_seed0 : int32; + s_hash_seed1 : int32; + s_hash_seed2 : int32; + s_hash_seed3 : int32; + s_def_hash_version : int; + s_reserved_char_pad : int; + s_reserved_word_pad : int; + s_default_mount_opts : int32; + s_first_meta_bg : int32; + + (* Computed fields, don't appear in superblock: *) + block_size : int63; + groups_count : int63; +} + +(* Private data functions. *) +let attach_private_data, get_private_data = + private_data_functions (fun {fs_cb = {fs_cb_uq = u}} -> u) + let id = "ext2" let superblock_offset = ~^1024 let superblock_len = ~^1024 -let rec probe dev = +(* Parse ext2/3 superblock and return a big structure containing + * all the fields. Also there are some extra fields which don't + * appear in the superblock itself, but are computed from other fields. + * + * If the device doesn't contain a superblock, raises Not_found. + *) +let parse_ext2_sb dev = (* Load the superblock. *) let bits = dev#read_bitstring superblock_offset superblock_len in @@ -91,19 +159,76 @@ let rec probe dev = s_reserved_char_pad : 8; s_reserved_word_pad : 16 : littleendian; s_default_mount_opts : 32 : littleendian; - s_first_meta_bg : 32 : littleendian; (* First metablock block group *) - _ : 6080 : bitstring } -> (* Padding to the end of the block *) + s_first_meta_bg : 32 : littleendian } -> (* First metablock block group *) - (* Work out the block size in bytes. *) - let s_log_block_size = Int32.to_int s_log_block_size in - let block_size = ~^1024 <^< s_log_block_size in + (* Work out the block size in bytes. *) + let block_size = ~^1024 <^< Int32.to_int s_log_block_size in - (* Number of groups. *) - let s_groups_count = - Int64.of_int32 ( - (s_blocks_count -* s_first_data_block -* 1l) - /* s_blocks_per_group +* 1l - ) in + (* Number of groups. *) + let groups_count = + Int63.of_int32 ( + (s_blocks_count -* s_first_data_block -* 1l) + /* s_blocks_per_group +* 1l + ) in + + { s_inodes_count = s_inodes_count; + s_blocks_count = s_blocks_count; + s_r_blocks_count = s_r_blocks_count; + s_free_blocks_count = s_free_blocks_count; + s_free_inodes_count = s_free_inodes_count; + s_first_data_block = s_first_data_block; + s_log_block_size = s_log_block_size; + s_log_frag_size = s_log_frag_size; + s_blocks_per_group = s_blocks_per_group; + s_frags_per_group = s_frags_per_group; + s_inodes_per_group = s_inodes_per_group; + s_mtime = s_mtime; + s_wtime = s_wtime; + s_mnt_count = s_mnt_count; + s_max_mnt_count = s_max_mnt_count; + s_state = s_state; + s_errors = s_errors; + s_minor_rev_level = s_minor_rev_level; + s_lastcheck = s_lastcheck; + s_checkinterval = s_checkinterval; + s_creator_os = s_creator_os; + s_rev_level = s_rev_level; + s_def_resuid = s_def_resuid; + s_def_resgid = s_def_resgid; + s_first_ino = s_first_ino; + s_inode_size = s_inode_size; + s_block_group_nr = s_block_group_nr; + s_feature_compat = s_feature_compat; + s_feature_incompat = s_feature_incompat; + s_feature_ro_compat = s_feature_ro_compat; + s_uuid = s_uuid; + s_volume_name = s_volume_name; + s_last_mounted = s_last_mounted; + s_algorithm_usage_bitmap = s_algorithm_usage_bitmap; + s_prealloc_blocks = s_prealloc_blocks; + s_prealloc_dir_blocks = s_prealloc_dir_blocks; + s_reserved_gdt_blocks = s_reserved_gdt_blocks; + s_journal_uuid = s_journal_uuid; + s_journal_inum = s_journal_inum; + s_journal_dev = s_journal_dev; + s_last_orphan = s_last_orphan; + s_hash_seed0 = s_hash_seed0; + s_hash_seed1 = s_hash_seed1; + s_hash_seed2 = s_hash_seed2; + s_hash_seed3 = s_hash_seed3; + s_def_hash_version = s_def_hash_version; + s_reserved_char_pad = s_reserved_char_pad; + s_reserved_word_pad = s_reserved_word_pad; + s_default_mount_opts = s_default_mount_opts; + s_first_meta_bg = s_first_meta_bg; + block_size = block_size; + groups_count = groups_count } + + | { _ } -> + raise Not_found (* Not an EXT2/3 superblock. *) + +let rec probe dev = + let sb = parse_ext2_sb dev in (* May raise Not_found. *) (* (* Number of group descriptors per block. *) @@ -117,39 +242,42 @@ let rec probe dev = (* Calculate the block overhead (used by superblocks, inodes, etc.) * See fs/ext2/super.c. *) - let overhead = Int63.of_int32 s_first_data_block in + let overhead = Int63.of_int32 sb.s_first_data_block in let overhead = (* XXX *) overhead in (* The blocksize of the filesystem is likely to be quite different * from that of the underlying device, so create an overlay device * with the natural filesystem blocksize. *) - let fs_dev = new blocksize_overlay block_size dev in + let fs_dev = new blocksize_overlay sb.block_size dev in - { + let fs = { fs_cb = callbacks (); fs_dev = fs_dev; - fs_blocksize = block_size; - fs_blocks_total = Int63.of_int32 s_blocks_count -^ overhead; + fs_blocksize = sb.block_size; + fs_blocks_total = Int63.of_int32 sb.s_blocks_count -^ overhead; fs_is_swap = false; - fs_blocks_reserved = Int63.of_int32 s_r_blocks_count; - fs_blocks_avail = Int63.of_int32 s_free_blocks_count; + fs_blocks_reserved = Int63.of_int32 sb.s_r_blocks_count; + fs_blocks_avail = Int63.of_int32 sb.s_free_blocks_count; fs_blocks_used = - Int63.of_int32 s_blocks_count -^ overhead - -^ Int63.of_int32 s_free_blocks_count; - fs_inodes_total = Int63.of_int32 s_inodes_count; + Int63.of_int32 sb.s_blocks_count -^ overhead + -^ Int63.of_int32 sb.s_free_blocks_count; + fs_inodes_total = Int63.of_int32 sb.s_inodes_count; fs_inodes_reserved = ~^0; (* XXX? *) - fs_inodes_avail = Int63.of_int32 s_free_inodes_count; - fs_inodes_used = Int63.of_int32 s_inodes_count + fs_inodes_avail = Int63.of_int32 sb.s_free_inodes_count; + fs_inodes_used = Int63.of_int32 sb.s_inodes_count (*-^ 0*) - -^ Int63.of_int32 s_free_inodes_count; - } + -^ Int63.of_int32 sb.s_free_inodes_count; + } in - | { _ } -> - raise Not_found (* Not an EXT2/3 superblock. *) + (* Attach the original superblock as private data so we can + * get to it quickly in other callbacks. + *) + attach_private_data fs sb; + fs and offset_is_free _ _ = false -- 1.8.3.1