(* Bitmatch library.
- * $Id: bitmatch.ml,v 1.5 2008-04-01 17:05:37 rjones Exp $
+ * $Id: bitmatch.ml,v 1.6 2008-04-01 19:10:45 rjones Exp $
*)
open Printf
let bitstring_length (_, _, len) = len
(*----------------------------------------------------------------------*)
+(* Bitwise functions.
+ *
+ * We try to isolate all bitwise functions within these modules.
+ *)
+
+module I = struct
+ (* Bitwise operations on ints. Note that we assume int <= 31 bits. *)
+ let (<<) = (lsl)
+ let (>>) = (lsr)
+ let one = 1
+ let minus_one = -1
+ let ff = 0xff
+
+ (* Create a mask so many bits wide. *)
+ let mask bits =
+ if bits < 30 then
+ pred (one << bits)
+ else if bits = 30 then
+ max_int
+ else
+ minus_one
+
+ (* Byte swap an int of a given size. *)
+ let byteswap v bits =
+ if bits <= 8 then v
+ else if bits <= 16 then (
+ let shift = bits-8 in
+ let v1 = v >> shift in
+ let v2 = (v land (mask shift)) << 8 in
+ v2 lor v1
+ ) else if bits <= 24 then (
+ let shift = bits - 16 in
+ let v1 = v >> (8+shift) in
+ let v2 = ((v >> shift) land ff) << 8 in
+ let v3 = (v land (mask shift)) << 16 in
+ v3 lor v2 lor v1
+ ) else (
+ let shift = bits - 24 in
+ let v1 = v >> (16+shift) in
+ let v2 = ((v >> (8+shift)) land ff) << 8 in
+ let v3 = ((v >> shift) land ff) << 16 in
+ let v4 = (v land (mask shift)) << 24 in
+ v4 lor v3 lor v2 lor v1
+ )
+end
+
+module I32 = struct
+ (* Bitwise operations on int32s. Note we try to keep it as similar
+ * as possible to the I module above, to make it easier to track
+ * down bugs.
+ *)
+ let (<<) = Int32.shift_left
+ let (>>) = Int32.shift_right_logical
+ let (land) = Int32.logand
+ let (lor) = Int32.logor
+ let pred = Int32.pred
+ let max_int = Int32.max_int
+ let one = Int32.one
+ let minus_one = Int32.minus_one
+ let ff = 0xff_l
+
+ (* Create a mask so many bits wide. *)
+ let mask bits =
+ if bits < 31 then
+ pred (one << bits)
+ else if bits = 31 then
+ max_int
+ else
+ minus_one
+
+ (* Byte swap an int of a given size. *)
+ let byteswap v bits =
+ if bits <= 8 then v
+ else if bits <= 16 then (
+ let shift = bits-8 in
+ let v1 = v >> shift in
+ let v2 = (v land (mask shift)) << 8 in
+ v2 lor v1
+ ) else if bits <= 24 then (
+ let shift = bits - 16 in
+ let v1 = v >> (8+shift) in
+ let v2 = ((v >> shift) land ff) << 8 in
+ let v3 = (v land (mask shift)) << 16 in
+ v3 lor v2 lor v1
+ ) else (
+ let shift = bits - 24 in
+ let v1 = v >> (16+shift) in
+ let v2 = ((v >> (8+shift)) land ff) << 8 in
+ let v3 = ((v >> shift) land ff) << 16 in
+ let v4 = (v land (mask shift)) << 24 in
+ v4 lor v3 lor v2 lor v1
+ )
+end
+
+(*----------------------------------------------------------------------*)
(* Extraction functions.
*
* NB: internal functions, called from the generated macros, and
) in
word, off+flen, len-flen
+let extract_int_le_unsigned data off len flen =
+ let v, off, len = extract_int_be_unsigned data off len flen in
+ let v = I.byteswap v flen in
+ v, off, len
+
let _make_int32_be c0 c1 c2 c3 =
Int32.logor
(Int32.logor
(Int32.shift_left c2 8))
c3
+let _make_int32_le c0 c1 c2 c3 =
+ Int32.logor
+ (Int32.logor
+ (Int32.logor
+ (Int32.shift_left c3 24)
+ (Int32.shift_left c2 16))
+ (Int32.shift_left c1 8))
+ c0
+
(* Extract exactly 32 bits. We have to consider endianness and signedness. *)
let extract_int32_be_unsigned data off len flen =
let byteoff = off lsr 3 in
) in
word, off+flen, len-flen
+let extract_int32_le_unsigned data off len flen =
+ let v, off, len = extract_int32_be_unsigned data off len flen in
+ let v = I32.byteswap v flen in
+ v, off, len
+
let _make_int64_be c0 c1 c2 c3 c4 c5 c6 c7 =
Int64.logor
(Int64.logor
if !linelen > 0 then (
let skip = (16 - !linelen) * 3 + if !linelen < 8 then 1 else 0 in
for i = 0 to skip-1 do fprintf chan " " done;
- fprintf chan " |%s|\n" linechars
+ fprintf chan " |%s|\n%!" linechars
) else
- fprintf chan "\n"
+ fprintf chan "\n%!"
(* Bitmatch library.
- * $Id: bitmatch.mli,v 1.5 2008-04-01 17:05:37 rjones Exp $
+ * $Id: bitmatch.mli,v 1.6 2008-04-01 19:10:45 rjones Exp $
*)
exception Construct_failure of string * string * int * int
val extract_int_be_unsigned : string -> int -> int -> int -> int * int * int
+val extract_int_le_unsigned : string -> int -> int -> int -> int * int * int
+
val extract_int32_be_unsigned : string -> int -> int -> int -> int32 * int * int
+val extract_int32_le_unsigned : string -> int -> int -> int -> int32 * int * int
+
val extract_int64_be_unsigned : string -> int -> int -> int -> int64 * int * int
val construct_bit : Buffer.t -> bool -> int -> unit
(* Bitmatch syntax extension.
- * $Id: pa_bitmatch.ml,v 1.4 2008-04-01 17:05:37 rjones Exp $
+ * $Id: pa_bitmatch.ml,v 1.5 2008-04-01 19:10:45 rjones Exp $
*)
open Printf
Printf.eprintf "PA_BITMATCH: TEST:\n";
Printf.eprintf " %s\n" $str:field$;
Printf.eprintf " off %d len %d\n%!" $lid:off$ $lid:len$;
+ (*Bitmatch.hexdump_bitstring stderr
+ ($lid:data$,$lid:off$,$lid:len$);*)
);
$expr$
>>
10_constr1
20_varsize
60_ping
+70_ext3_sb
--- /dev/null
+(* Parse an ext3 superblock.
+ * $Id: 70_ext3_sb.ml,v 1.1 2008-04-01 19:10:45 rjones Exp $
+ *)
+
+open Printf
+
+(*let () = Bitmatch.debug := true*)
+
+let bits = Bitmatch.bitstring_of_file "tests/ext3_sb"
+
+(* The structure is straight from /usr/include/linux/ext3_fs.h *)
+
+let () =
+ 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 *)
+
+ printf "ext3 superblock:\n";
+ printf " s_inodes_count = %ld\n" s_inodes_count;
+ printf " s_blocks_count = %ld\n" s_blocks_count;
+ printf " s_free_inodes_count = %ld\n" s_free_inodes_count;
+ printf " s_free_blocks_count = %ld\n" s_free_blocks_count
+
+ | _ ->
+ eprintf "not an ext3 superblock!\n%!";
+ exit 2