open Cmdliner let print_zim_header zim = Printf.printf "Zim Header:\n"; Printf.printf "\tmagic number: %lu\n" zim.Zim.Header.magic_number; Printf.printf "\tmajor version: %d\n" zim.Zim.Header.major_version; Printf.printf "\tminor version: %d\n" zim.Zim.Header.minor_version; Printf.printf "\tuuid: %s\n" (Uuidm.to_string zim.Zim.Header.uuid); Printf.printf "\tentry count: %lu\n" zim.Zim.Header.entry_count; Printf.printf "\tcluster count: %lu\n" zim.Zim.Header.cluster_count; Printf.printf "\tpath pointer position: %Lu\n" zim.Zim.Header.path_ptr_pos; Printf.printf "\ttitle pointer position: %Lu\n" zim.Zim.Header.title_ptr_pos; Printf.printf "\tcluster pointer position: %Lu\n" zim.Zim.Header.cluster_ptr_pos; Printf.printf "\tmime list position: %Lu\n" zim.Zim.Header.mime_list_pos; Printf.printf "\tmain page: %lu\n" zim.Zim.Header.main_page; Printf.printf "\tlayout page: %lu\n" zim.Zim.Header.layout_page; Printf.printf "\tchecksum position: %Lu\n" zim.Zim.Header.checksum_pos let print_int32_in_columns count lst = List.iteri (fun i zim -> if i > 0 && i mod count = 0 then Printf.printf "\n"; Printf.printf "%10lu " zim) lst; Printf.printf "\n"; () let print_zim zim = print_zim_header zim.Zim.header; Printf.printf "MIME Type List:\n"; List.iter (fun zim -> Printf.printf "\t%s\n" zim) zim.Zim.mime_type_list; Printf.printf "Path Pointer List:\n"; print_int32_in_columns 10 zim.path_ptr_list; Printf.printf "Title Pointer List:\n"; print_int32_in_columns 10 zim.title_ptr_list; () let really_input fd buf pos len = let rec loop pos remaining = if remaining > 0 then ( let len = Unix.read fd buf pos remaining in if len = 0 then raise End_of_file; loop (pos + len) (remaining - len)) in loop pos len let read_zims zims = List.iter (fun zim -> let fd = Unix.openfile zim Unix.[ O_RDONLY; O_CLOEXEC ] 0 in let f_stats = Unix.stat zim in let size = f_stats.st_size in let buf = Bytes.create size in let () = really_input fd buf 0 size in match Zim.unmarshal (Cstruct.of_bytes buf) with | Ok zim -> print_zim zim | Error err -> Printf.printf "%s" err) zims let zims = Arg.(non_empty & pos_all file [] & info [] ~docv:"zim files") let cmd = let doc = "Inspect the headers of one or more zim files." in let info = Cmd.info "zim_header_inspect" ~version:"1.0.0" ~doc in Cmd.v info Term.(const read_zims $ zims) let main () = exit (Cmd.eval cmd) let () = main ()