+*)
+
+and offset_is_free parts offset =
+ let privs = get_private_data parts in
+
+ (* The first partition is somehow privileged in that we assume
+ * everything before this is not free. Usually this is the first
+ * 63 sectors containing the MBR itself and sectors which should
+ * be blank but in reality contain all sorts of stupid hacks like
+ * alternate partitioning schemes.
+ *)
+ match privs with
+ | [] -> false
+ | { mbr_part_start = start; mbr_part_size = size } :: rest ->
+ if offset < start +^ size then
+ false
+ else (
+ let rec loop = function
+ | [] -> true (* not in a partition, must be free *)
+ | { mbr_part_start = start; mbr_part_size = size } :: rest ->
+ if start <= offset && offset < start +^ size then
+ false
+ else
+ loop rest
+ in
+ loop rest
+ )
+
+and callbacks =
+ let i = ref 0 in
+ fun () -> {
+ parts_cb_uq = (incr i; !i);
+ parts_cb_name = id;
+ parts_cb_offset_is_free = offset_is_free;
+ }
+
+(* Register the plugin. *)
+let () = register_plugin ~partitioner:probe id