open Unix;;

(* program constants *)
let slice_size = ref 1024;;
let buffer_size = 4096 ;;
let buffer = String.create buffer_size

(* name generation function for output files *)
let slicename name index = Printf.sprintf "%s-%d" name index;;

let rec copy_data fd_in fd_out tocopy =
  if tocopy > 0 then
    let len = Unix.read fd_in buffer 0 (min tocopy buffer_sizein
    if len > 0 then begin
        ignore (Unix.write fd_out buffer 0 len);
        copy_data fd_in fd_out (tocopy - len)
      end else
      tocopy
  else
    0

(* do the job *)
let split file size =
  Printf.fprintf Pervasives.stderr "file=%s size=%d" file size;
  prerr_newline();

  let fd_in = Unix.openfile file [ O_RDONLY ] 0 in

  let rec copy_slices slice =
    let fd_out = Unix.openfile (slicename file slice)
      [O_WRONLY;O_CREAT;O_TRUNC] 0o666 in
    let left = copy_data fd_in fd_out size in
    Unix.close fd_out;
    if left = 0 then copy_slices (slice + 1)
  in
  copy_slices 0;
  Unix.close fd_in

(* errors and arguments handling functions*)
let errors = ref false;;
let process_file file =
  try split file !slice_size
  with Unix_error (e,b,c) ->
    errors := true;
    prerr_string (Sys.argv.(0)^": " ^c": " ^(error_message e));
    prerr_newline ();;

let set_size nb =
  if nb > 0 then slice_size := nb
  else raise (Arg.Bad "Size must be strictly positive");;
let usage = "Usage: " ^ Sys.argv.(0) ^ " [ option ] filename";;

(* main function *)
let mon_split () =
  Arg.parse [ ("-b"Arg.Int set_size"byte number") ] process_file usage;
  if !errors then exit 1;;

handle_unix_error mon_split();;