Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eio_posix: add O_DIRECTORY when opening with a trailing slash #696

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib_eio_posix/low_level.ml
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,21 @@ module Resolve = struct
close_tmp state;
Printexc.raise_with_backtrace ex bt

let trailing_slash x =
x <> "" && x.[String.length x - 1] = '/'

let open_beneath_fallback ?dirfd:base ~sw ~mode path flags =
let path = parse_rel path in
with_state base @@ fun state ->
(* Resolve the parent, then try to open the last component with [flags + nofollow].
If it's a symlink, retry with the target. *)
let rec aux leaf =
let base = current_dir state in
let flags = if trailing_slash leaf then Open_flags.(flags + directory) else flags in
match eio_openat base leaf Open_flags.(flags + nofollow) mode with
| fd -> Fd.of_unix fd ~sw ~blocking:false ~close_unix:true
| exception (Unix.Unix_error ((ELOOP | ENOTDIR | EMLINK | EUNKNOWNERR _), _, _) as e) ->
(* Note: Linux uses ELOOP or ENOTDIR. FreeBSD used EMLINK. NetBSD uses EFTYPE. *)
(* Note: Linux uses ELOOP or ENOTDIR. FreeBSD uses EMLINK. NetBSD uses EFTYPE. *)
match Eio_unix.Private.read_link_unix base leaf with
| target ->
decr_max_follows state leaf;
Expand Down Expand Up @@ -337,6 +341,7 @@ module Resolve = struct
with_parent_loop ~dirfd path (fun x y -> Ok (fn x y))

let open_unconfined ~sw ~mode dirfd path flags =
let flags = if trailing_slash path then Open_flags.(flags + directory) else flags in
Fd.use_exn_opt "openat" dirfd @@ fun dirfd ->
eio_openat dirfd path Open_flags.(flags + nonblock) mode
|> Fd.of_unix ~sw ~blocking:false ~close_unix:true
Expand Down
4 changes: 1 addition & 3 deletions lib_eio_posix/test/open_beneath.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ let test base path =
check ~mode:0 base path L.Open_flags.rdonly;
if path <> "" then (
check ~mode:0 base (path ^ "/") L.Open_flags.rdonly;
(* This doesn't work on macos, which seems to allow opening files even with
a trailing "/" (but not with a trailing "/."): *)
(* check ~mode:0 base (path ^ "/.") L.Open_flags.rdonly *)
check ~mode:0 base (path ^ "/.") L.Open_flags.rdonly
)

let test_denied base path =
Expand Down
Loading