let real_slurp path =
  let cwd = Sys.getcwd () in
  let abs x = if Filename.is_implicit x || Filename.is_relative x then cwd/x else x in
  let visited = Hashtbl.create 1024 in
  let rec scandir path names =
    let (file_acc, dir_acc) =
      Array.fold_left begin fun ((file_acc, dir_acc) as acc) name ->
        match do_entry true path name with
        | None -> acc
        | Some((Dir _|Error _) as entry) -> (file_acc, entry :: dir_acc)
        | Some((File _) as entry) -> (entry :: file_acc, dir_acc)
        | Some Nothing -> acc
      end
      ([], [])
      names
    in
    file_acc @ dir_acc
  and do_entry link_mode path name =
    let fn = path/name in
    let absfn = abs fn in
    match
      try
        Good(if link_mode then My_unix.lstat absfn else My_unix.stat absfn)
      with
      | x -> Bad x
    with
    | Bad x -> Some(Error x)
    | Good st ->
      let key = st.My_unix.stat_key in
      if try Hashtbl.find visited key with Not_found -> false
      then None
      else
        begin
          Hashtbl.add visited key true;
          let res =
            match st.My_unix.stat_file_kind with
            | My_unix.FK_link ->
                let fn' = My_unix.readlink absfn in
                if sys_file_exists (abs fn') then
                  do_entry false path name
                else
                  Some(File(path, name, lazy st, ()))
            | My_unix.FK_dir ->
                (match sys_readdir absfn with
                | Good names -> Some(Dir(path, name, lazy st, (), lazy (scandir fn names)))
                | Bad exn -> Some(Error exn))
            | My_unix.FK_other -> None
            | My_unix.FK_file -> Some(File(path, name, lazy st, ())) in
          Hashtbl.replace visited key false;
          res
        end
  in
  match do_entry true "" path with
  | None -> raise Not_found
  | Some entry -> entry