let error_to_string = function   | `System (where, what) ->     sprintf "System error while %s: %s"       begin match where with       | `File_info s -> sprintf "getting info on %S" s       | `Make_directory s -> sprintf "making directory %S" s          (* | `IO of [ `File_exists of string | `Wrong_path of string ] *)       | `File_tree s -> sprintf "getting file tree from %S" s       | `Move s -> sprintf "moving %S" s       | `Copy s -> sprintf "copying %S" s       | `Make_symlink (s1, s2) -> sprintf "Making symlink from target %S to %s" s1 s2       | `Remove s -> sprintf "removing %S" s       | `List_directory s -> sprintf "listing directory %S" s       end       begin match what with       | `Already_exists -> "Already exists"       | `IO _ as e -> sprintf "I/O Error %S" (IO.error_to_string e)       | `File_not_found s -> sprintf "File not found (%S)" s       | `Not_a_directory s -> sprintf "Not a directory (%S)" s       | `File_exists s -> sprintf "File exists (%S)" s       | `Wrong_path s -> sprintf "Wrong path (%S)" s       | `Wrong_file_kind (s, k) ->         sprintf "Wrong kind of file (%S: %s)" s (file_info_to_string k)       | `Exn e -> sprintf "Exception %s" (exn e)       | `Wrong_access_rights o -> sprintf "wrong access rights: 0o%o" o       end   | `Shell (cmd, err) ->     sprintf "Shell command %S failed: %s" cmd       (Shell.status_to_string err)