X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fdiskimage_ext2.ml;h=994ae3490615f0420a3885dfe01d58b288b438a0;hb=b7900f7f60d4b5179e123c91de125cff72d50324;hp=ade794023c9cd427fc7f85e8d100b3cf05004df8;hpb=71536ae75dceb08e0f3c3403033fb2eb25a08883;p=virt-df.git diff --git a/lib/diskimage_ext2.ml b/lib/diskimage_ext2.ml index ade7940..994ae34 100644 --- a/lib/diskimage_ext2.ml +++ b/lib/diskimage_ext2.ml @@ -2,19 +2,20 @@ (C) Copyright 2007 Richard W.M. Jones, Red Hat Inc. http://libvirt.org/ - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version, + with the OCaml linking exception described in ../COPYING.LIB. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Support for EXT2/EXT3 filesystems. *) @@ -31,11 +32,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 +160,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 block_size = ~^1024 <^< Int32.to_int s_log_block_size in - (* 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 + (* Number of groups. *) + let groups_count = + Int63.of_int32 ( + (s_blocks_count -* s_first_data_block -* 1l) + /* s_blocks_per_group +* 1l + ) 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 + { 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,47 +243,53 @@ 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 - { - fs_cb = callbacks; + 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 -and callbacks = { - fs_cb_name = id; - fs_cb_printable_name = "Linux ext2/3"; - fs_cb_offset_is_free = offset_is_free; -} +and callbacks = + let i = ref 0 in + fun () -> { + fs_cb_uq = (incr i; !i); + fs_cb_name = id; + fs_cb_printable_name = "Linux ext2/3"; + fs_cb_offset_is_free = offset_is_free; + } (* Register the plugin. *) let () = register_plugin ~filesystem:probe id