add cycle and max depth to symlink following

This commit is contained in:
Rudi Grinberg 2018-05-15 19:29:20 +07:00
parent c9916f4a76
commit ac078fcdbb
3 changed files with 34 additions and 9 deletions

View File

@ -157,7 +157,16 @@ let ignore_file fn ~is_directory =
let load ?(extra_ignored_subtrees=Path.Set.empty) path =
let rec walk seen_real_paths path ~project ~ignored : Dir.t =
let realpath = Path.follow_symlink path in
let realpath =
Path.follow_symlink path
|> Result.map_error ~f:(function
| `Maximum_depth_exceeded ->
die "maximum symlink depth exceeded while scanning %s"
(Path.to_string_maybe_quoted path)
| `Cycle_detected ->
die "cycle detected while scanning %s"
(Path.to_string_maybe_quoted path))
|> Result.ok_exn in
if List.mem realpath ~set:seen_real_paths then
die "Path %s has already been scanned. \
Cannot scan it again through symlink %s"

View File

@ -522,13 +522,27 @@ let extension = Filename.extension
let pp ppf t = Format.pp_print_string ppf (to_string t)
let follow_symlink p =
match (
match Unix.readlink (to_string p) with
| p -> Some p
| exception Unix.Unix_error (Unix.EINVAL, "readlink", _) -> None
) with
| None -> p
| Some realpath ->
let readlink fn =
match Unix.readlink fn with
| exception Unix.Unix_error ((EINVAL | ENOENT), "readlink", _) -> None
| p -> Some p in
match readlink p with
| None -> Result.Ok p
| Some p ->
let rec follow n fn =
if n = 0 then
Result.Error `Maximum_depth_exceeded
else
match readlink fn with
| None -> Result.Ok fn
| Some p ->
if p = fn then
Result.Error `Cycle_detected
else
follow (pred n) p
in
let open Result.O in
follow 256 (to_string p) >>| fun realpath ->
if not (is_local realpath) then
of_string realpath
else

View File

@ -144,4 +144,6 @@ val build_dir_exists : unit -> bool
val ensure_build_dir_exists : unit -> unit
val follow_symlink : t -> t
val follow_symlink
: t
-> (t, [ `Cycle_detected | `Maximum_depth_exceeded ]) Result.t