let readlink fln =
    let ctst = compile_filter Is_link
    in
    let rec readlink_aux already_read fln = 
      let newly_read = prevent_recursion already_read fln
      in
      let dirs = all_upper_dir fln
      in
      try 
        let src_link = List.find ctst (List.rev dirs)
        in
        let dst_link = Unix.readlink src_link 
        in
        let real_link = 
          if is_relative dst_link then
            reduce (concat (dirname src_link) dst_link)
          else
            reduce dst_link
        in
        readlink_aux newly_read (reparent src_link real_link fln)
      with Not_found ->
        fln
    in 
    readlink_aux SetFilename.empty (make_absolute (pwd ()) fln)