experimental hashing with oxcaml
1let hex_of_bytes bytes =
2 let buf = Buffer.create (Bytes.length bytes * 2) in
3 Bytes.iter
4 (fun c -> Buffer.add_string buf (Printf.sprintf "%02x" (Char.code c)))
5 bytes;
6 Buffer.contents buf
7
8let hash_file filename =
9 try
10 let fd = Unix.openfile filename [ Unix.O_RDONLY ] 0 in
11 let stats = Unix.fstat fd in
12 let file_size = stats.Unix.st_size in
13
14 if file_size = 0 then (
15 (* Handle empty files *)
16 Unix.close fd;
17 let digest = Oxsha.hash_string "" in
18 Ok (hex_of_bytes digest)
19 ) else (
20 let mapped =
21 Unix.map_file fd Bigarray.char Bigarray.c_layout false [| file_size |]
22 in
23 let ba = Bigarray.array1_of_genarray mapped in
24 Unix.close fd;
25
26 let digest = Oxsha.hash ba in
27 Ok (hex_of_bytes digest)
28 )
29 with e -> Error e
30
31let () =
32 if Array.length Sys.argv < 2 then (
33 Printf.eprintf "Usage: %s FILE [FILE...]\n" Sys.argv.(0);
34 Printf.eprintf "Print SHA256 (256-bit) checksums.\n";
35 exit 1
36 );
37
38 let exit_code = ref 0 in
39
40 for i = 1 to Array.length Sys.argv - 1 do
41 let filename = Sys.argv.(i) in
42 match hash_file filename with
43 | Ok hash -> Printf.printf "%s %s\n" hash filename
44 | Error (Sys_error msg) ->
45 Printf.eprintf "%s: %s\n" Sys.argv.(0) msg;
46 exit_code := 1
47 | Error e ->
48 Printf.eprintf "%s: %s: %s\n" Sys.argv.(0) filename
49 (Printexc.to_string e);
50 exit_code := 1
51 done;
52
53 exit !exit_code