let file_info ?(follow_symlink=false) path =
let stat_fun =
if follow_symlink then Lwt_unix.stat else Lwt_unix.lstat in
Lwt.catch
Lwt.(fun () -> stat_fun path >>= fun s -> return (`Ok (`Unix_stats s)))
begin function
| Unix.Unix_error (Unix.ENOENT, cmd, arg) -> return `Absent
| e -> fail_sys (`File_info path, `Exn e)
end
>>= fun m ->
let open Lwt_unix in
begin match m with
| `Absent -> return `Absent
| `Unix_stats stats ->
begin match stats.st_kind with
| S_DIR -> return (`Directory)
| S_REG -> return (`Regular_file (stats.st_size))
| S_LNK ->
begin
catch_deferred (fun () -> lwt_unix_readlink path)
>>< begin function
| `Ok s -> return s
| `Error e -> fail (`System (`File_info path, `Exn e))
end
end
>>= fun destination ->
return (`Symlink destination)
| S_CHR -> return (`Character_device)
| S_BLK -> return (`Block_device)
| S_FIFO -> return (`Fifo)
| S_SOCK -> return (`Socket)
end
end