-(* Int64 operators for convenience. *)
-let (+^) = Int64.add
-let (-^) = Int64.sub
-let ( *^ ) = Int64.mul
-let (/^) = Int64.div
-
-let sector_size = Virt_df.sector_size
-let read_int32_le = Virt_df.read_int32_le
-
-let probe_ext2 target part_type fd start size =
- LargeFile.lseek fd ((start+^2L) *^ sector_size) SEEK_SET;
- let str = String.create 128 in
- if read fd str 0 128 <> 128 then
- failwith "error reading ext2/ext3 magic"
- else (
- if str.[56] != '\x53' || str.[57] != '\xEF' then (
- Virt_df.ProbeFailed "partition marked EXT2/3 but no valid filesystem"
- ) else (
- (* Refer to <linux/ext2_fs.h> *)
- let s_inodes_count = read_int32_le str 0 in
- let s_blocks_count = read_int32_le str 4 in
- let s_r_blocks_count = read_int32_le str 8 in
- let s_free_blocks_count = read_int32_le str 12 in
- let s_free_inodes_count = read_int32_le str 16 in
- let s_first_data_block = read_int32_le str 20 in
- let s_log_block_size = read_int32_le str 24 in
- (*let s_log_frag_size = read_int32_le str 28 in*)
- let s_blocks_per_group = read_int32_le str 32 in
-
- (* Work out the block size in bytes. *)
- let s_log_block_size = Int64.to_int s_log_block_size in
- let block_size = 1024L in
- let block_size = Int64.shift_left block_size s_log_block_size in
-
- (* Number of groups. *)
- let s_groups_count =
- (s_blocks_count -^ s_first_data_block -^ 1L)
- /^ s_blocks_per_group +^ 1L in
+open Virt_df_gettext.Gettext
+open Virt_df
+
+let superblock_offset = 1024L
+
+let probe_ext2 dev =
+ (* Load the superblock. *)
+ let bits = dev#read_bitstring superblock_offset 1024 in
+
+ (* The structure is straight from /usr/include/linux/ext3_fs.h *)
+ bitmatch bits with
+ | s_inodes_count : 32 : littleendian; (* Inodes count *)
+ s_blocks_count : 32 : littleendian; (* Blocks count *)
+ s_r_blocks_count : 32 : littleendian; (* Reserved blocks count *)
+ s_free_blocks_count : 32 : littleendian; (* Free blocks count *)
+ s_free_inodes_count : 32 : littleendian; (* Free inodes count *)
+ s_first_data_block : 32 : littleendian; (* First Data Block *)
+ s_log_block_size : 32 : littleendian; (* Block size *)
+ s_log_frag_size : 32 : littleendian; (* Fragment size *)
+ s_blocks_per_group : 32 : littleendian; (* # Blocks per group *)
+ s_frags_per_group : 32 : littleendian; (* # Fragments per group *)
+ s_inodes_per_group : 32 : littleendian; (* # Inodes per group *)
+ s_mtime : 32 : littleendian; (* Mount time *)
+ s_wtime : 32 : littleendian; (* Write time *)
+ s_mnt_count : 16 : littleendian; (* Mount count *)
+ s_max_mnt_count : 16 : littleendian; (* Maximal mount count *)
+ 0xef53 : 16 : littleendian; (* Magic signature *)
+ s_state : 16 : littleendian; (* File system state *)
+ s_errors : 16 : littleendian; (* Behaviour when detecting errors *)
+ s_minor_rev_level : 16 : littleendian; (* minor revision level *)
+ s_lastcheck : 32 : littleendian; (* time of last check *)
+ s_checkinterval : 32 : littleendian; (* max. time between checks *)
+ s_creator_os : 32 : littleendian; (* OS *)
+ s_rev_level : 32 : littleendian; (* Revision level *)
+ s_def_resuid : 16 : littleendian; (* Default uid for reserved blocks *)
+ s_def_resgid : 16 : littleendian; (* Default gid for reserved blocks *)
+ s_first_ino : 32 : littleendian; (* First non-reserved inode *)
+ s_inode_size : 16 : littleendian; (* size of inode structure *)
+ s_block_group_nr : 16 : littleendian; (* block group # of this superblock *)
+ s_feature_compat : 32 : littleendian; (* compatible feature set *)
+ s_feature_incompat : 32 : littleendian; (* incompatible feature set *)
+ s_feature_ro_compat : 32 : littleendian; (* readonly-compatible feature set *)
+ s_uuid : 128 : bitstring; (* 128-bit uuid for volume *)
+ s_volume_name : 128 : bitstring; (* volume name XXX string *)
+ s_last_mounted : 512 : bitstring; (* directory where last mounted XXX string *)
+ s_algorithm_usage_bitmap : 32 : littleendian; (* For compression *)
+ s_prealloc_blocks : 8; (* Nr of blocks to try to preallocate*)
+ s_prealloc_dir_blocks : 8; (* Nr to preallocate for dirs *)
+ s_reserved_gdt_blocks : 16 : littleendian; (* Per group desc for online growth *)
+ s_journal_uuid : 128 : bitstring; (* uuid of journal superblock *)
+ s_journal_inum : 32 : littleendian; (* inode number of journal file *)
+ s_journal_dev : 32 : littleendian; (* device number of journal file *)
+ s_last_orphan : 32 : littleendian; (* start of list of inodes to delete *)
+ s_hash_seed0 : 32 : littleendian; (* HTREE hash seed *)
+ s_hash_seed1 : 32 : littleendian;
+ s_hash_seed2 : 32 : littleendian;
+ s_hash_seed3 : 32 : littleendian;
+ s_def_hash_version : 8; (* Default hash version to use *)
+ 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 *)
+ s_reserved : 6080 : bitstring -> (* Padding to the end of the block *)
+
+ (* Work out the block size in bytes. *)
+ let s_log_block_size = Int32.to_int s_log_block_size in
+ let block_size = 1024L in
+ let block_size = Int64.shift_left block_size 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