From 9f83a87b68ca066f32c1bcd1688db3a5640ba64c Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 20 Nov 2024 19:54:49 +0000 Subject: [PATCH 1/8] Support chown in Eio_posix Adds support for fchownat to eio.unix and then calls this from eio_posix. --- lib_eio/fs.ml | 1 + lib_eio/path.ml | 8 ++++++ lib_eio/path.mli | 3 ++ lib_eio/unix/eio_unix.mli | 3 ++ lib_eio/unix/primitives.h | 1 + lib_eio/unix/private.ml | 10 +++++++ lib_eio/unix/stubs.c | 21 ++++++++++++++ lib_eio_posix/fs.ml | 3 ++ lib_eio_posix/low_level.ml | 7 +++++ lib_eio_posix/low_level.mli | 4 +++ tests/fs.md | 56 +++++++++++++++++++++++++++++++++++++ 11 files changed, 117 insertions(+) diff --git a/lib_eio/fs.ml b/lib_eio/fs.ml index 34505c9f1..47196239c 100644 --- a/lib_eio/fs.ml +++ b/lib_eio/fs.ml @@ -71,6 +71,7 @@ module Pi = struct val rename : t -> path -> _ dir -> path -> unit val read_link : t -> path -> string val symlink : link_to:path -> t -> path -> unit + val chown : follow:bool -> uid:int64 -> gid:int64 -> t -> path -> unit val pp : t Fmt.t val native : t -> string -> string option end diff --git a/lib_eio/path.ml b/lib_eio/path.ml index 37cd5ff09..f59961e09 100644 --- a/lib_eio/path.ml +++ b/lib_eio/path.ml @@ -238,3 +238,11 @@ let read_link t = with Exn.Io _ as ex -> let bt = Printexc.get_raw_backtrace () in Exn.reraise_with_context ex bt "reading target of symlink %a" pp t + +let chown ~follow ~uid ~gid t = + let (Resource.T (dir, ops), path) = t in + let module X = (val (Resource.get ops Fs.Pi.Dir)) in + try X.chown ~follow ~uid ~gid dir path + with Exn.Io _ as ex -> + let bt = Printexc.get_raw_backtrace () in + Exn.reraise_with_context ex bt "chowing file %a" pp t diff --git a/lib_eio/path.mli b/lib_eio/path.mli index d147f5454..8e5473b6f 100644 --- a/lib_eio/path.mli +++ b/lib_eio/path.mli @@ -217,3 +217,6 @@ val symlink : link_to:string -> _ t -> unit {[ Eio.Path.symlink (dir / "current") ~link_to:"version-1.0" ]} *) + +val chown : follow:bool -> uid:int64 -> gid:int64 -> _ t -> unit +(** [chown ~follow ~uid ~gid t] changes the ownership of [t] to be [uid, gid]. *) diff --git a/lib_eio/unix/eio_unix.mli b/lib_eio/unix/eio_unix.mli index 774ba5f6b..af3315ebb 100644 --- a/lib_eio/unix/eio_unix.mli +++ b/lib_eio/unix/eio_unix.mli @@ -107,6 +107,9 @@ module Private : sig val read_link : Fd.t option -> string -> string val read_link_unix : Unix.file_descr option -> string -> string + + val chown : flags:int -> uid:int64 -> gid:int64 -> Fd.t option -> string -> unit + val chown_unix : flags:int -> uid:int64 -> gid:int64 -> Unix.file_descr option -> string -> unit end module Pi = Pi diff --git a/lib_eio/unix/primitives.h b/lib_eio/unix/primitives.h index d43166a92..cd2b81296 100644 --- a/lib_eio/unix/primitives.h +++ b/lib_eio/unix/primitives.h @@ -9,4 +9,5 @@ CAMLprim value eio_unix_fork_fchdir(value); CAMLprim value eio_unix_fork_dups(value); CAMLprim value eio_unix_cap_enter(value); CAMLprim value eio_unix_readlinkat(value, value, value); +CAMLprim value eio_unix_fchownat(value, value, value, value, value); CAMLprim value eio_unix_is_blocking(value); diff --git a/lib_eio/unix/private.ml b/lib_eio/unix/private.ml index 961990766..01d23b339 100644 --- a/lib_eio/unix/private.ml +++ b/lib_eio/unix/private.ml @@ -33,3 +33,13 @@ let read_link_unix fd path = aux 1024 let read_link fd path = Fd.use_exn_opt "readlink" fd (fun fd -> read_link_unix fd path) + +external eio_fchownat : Unix.file_descr -> string -> int64 -> int64 -> int -> unit = "eio_unix_fchownat" + +let chown_unix ~flags ~uid ~gid fd path = + match fd with + | None -> Unix.chown path (Int64.to_int uid) (Int64.to_int gid) + | Some fd -> eio_fchownat fd path uid gid flags + +let chown ~flags ~uid ~gid fd path = + Fd.use_exn_opt "chown" fd (fun fd -> chown_unix ~uid ~gid ~flags fd path) diff --git a/lib_eio/unix/stubs.c b/lib_eio/unix/stubs.c index 78572bf4f..689254476 100644 --- a/lib_eio/unix/stubs.c +++ b/lib_eio/unix/stubs.c @@ -52,3 +52,24 @@ CAMLprim value eio_unix_readlinkat(value v_fd, value v_path, value v_cs) { CAMLreturn(Val_int(ret)); #endif } + +CAMLprim value eio_unix_fchownat(value v_fd, value v_path, value v_uid, value v_gid, value v_flags) { +#ifdef _WIN32 + caml_unix_error(EOPNOTSUPP, "fchownat not supported on Windows", v_path); +#else + CAMLparam3(v_path, v_uid, v_gid); + char *path; + int fd = Int_val(v_fd); + int ret; + caml_unix_check_path(v_path, "fchownat"); + path = caml_stat_strdup(String_val(v_path)); + caml_enter_blocking_section(); + ret = fchownat(fd, path, Int64_val(v_uid), Int64_val(v_gid), Int_val(v_flags)); + caml_leave_blocking_section(); + caml_stat_free_preserving_errno(path); + if (ret == -1) + caml_uerror("fchownat", v_path); + CAMLreturn(Val_unit); +#endif +} + diff --git a/lib_eio_posix/fs.ml b/lib_eio_posix/fs.ml index 1a20523a0..47e397c8b 100644 --- a/lib_eio_posix/fs.ml +++ b/lib_eio_posix/fs.ml @@ -97,6 +97,9 @@ end = struct let symlink ~link_to t path = Err.run (Low_level.symlink ~link_to t.fd) path + let chown ~follow ~uid ~gid t path = + Err.run (Low_level.chown ~follow ~uid ~gid t.fd) path + let open_dir t ~sw path = let flags = Low_level.Open_flags.(rdonly + directory +? path) in let fd = Err.run (Low_level.openat ~sw ~mode:0 t.fd path) flags in diff --git a/lib_eio_posix/low_level.ml b/lib_eio_posix/low_level.ml index 6026993d1..61e03b894 100644 --- a/lib_eio_posix/low_level.ml +++ b/lib_eio_posix/low_level.ml @@ -428,6 +428,13 @@ let read_link dirfd path = Resolve.with_parent "read_link" dirfd path @@ fun dirfd path -> Eio_unix.Private.read_link_unix dirfd path +let chown ~follow ~uid ~gid dirfd path = + let flags = if follow then 0 else Config.at_symlink_nofollow in + in_worker_thread "chown" @@ fun () -> + Resolve.with_parent "chown" dirfd path @@ fun dirfd path -> + let dirfd = Option.value dirfd ~default:at_fdcwd in + Eio_unix.Private.chown_unix ~flags ~uid ~gid (Some dirfd) path + type stat external create_stat : unit -> stat = "caml_eio_posix_make_stat" external eio_fstatat : stat -> Unix.file_descr -> string -> int -> unit = "caml_eio_posix_fstatat" diff --git a/lib_eio_posix/low_level.mli b/lib_eio_posix/low_level.mli index 69efe7207..a89a318e9 100644 --- a/lib_eio_posix/low_level.mli +++ b/lib_eio_posix/low_level.mli @@ -82,6 +82,10 @@ val symlink : link_to:string -> dir_fd -> string -> unit (** [symlink ~link_to dir path] will create a new symlink at [dir / path] linking to [link_to]. *) +val chown : follow:bool -> uid:int64 -> gid:int64 -> dir_fd -> string -> unit +(** [chown ~follow ~uid ~gid dir path] will change the ownership of [dir / path] + to [uid, gid]. *) + val readdir : dir_fd -> string -> string array val readv : fd -> Cstruct.t array -> int diff --git a/tests/fs.md b/tests/fs.md index 446874ad3..edf705870 100644 --- a/tests/fs.md +++ b/tests/fs.md @@ -94,6 +94,11 @@ let try_symlink ~link_to path = match Path.symlink ~link_to path with | s -> traceln "symlink %a -> %S" Path.pp path link_to | exception ex -> traceln "@[%a@]" Eio.Exn.pp ex + +let try_chown ~follow ~uid ~gid path = + match Path.chown ~follow ~uid ~gid path with + | s -> traceln "chown %a" Path.pp path + | exception ex -> traceln "@[%a@]" Eio.Exn.pp ex ``` # Basic test cases @@ -905,6 +910,57 @@ Reading at the end of a file: - : unit = () ``` +# Changing Ownership + + +```ocaml +# run @@ fun env -> + let cwd = Eio.Stdenv.cwd env in + let everyone = try Some (Unix.getgrnam "everyone") with Not_found -> None in + let stat_uid_gid path = + let stat = Eio.Path.stat ~follow:false path in + stat.Eio.File.Stat.uid, stat.gid + in + match everyone with + | None -> () + | Some entry -> + let everybody = Int64.of_int entry.gr_gid in + + let path = cwd / "owner.txt" in + let link = cwd / "link.txt" in + let symlink = cwd / "symlink.txt" in + + (* Normal chown to everyone group *) + Path.with_open_out path ~create:(`Or_truncate 0o644) ignore; + let uid_before, _gid_before = stat_uid_gid path in + Eio.Path.chown ~follow:false ~uid:uid_before ~gid:everybody path; + let uid_after, gid_after = stat_uid_gid path in + assert (uid_before = uid_after); + assert (everybody = gid_after); + + (* Chowning through a symlink *) + Path.with_open_out link ~create:(`Or_truncate 0o644) ignore; + Eio.Path.symlink ~link_to:"link.txt" symlink; + let luid1, lgid1 = stat_uid_gid link in + let suid1, sgid1 = stat_uid_gid symlink in + + (* Only chown the symlink, not the target *) + Eio.Path.chown ~follow:false ~uid:uid_before ~gid:everybody symlink; + let luid2, lgid2 = stat_uid_gid link in + let suid2, sgid2 = stat_uid_gid symlink in + assert (luid1 = luid2 && lgid1 = lgid2 && suid1 = suid2 && Int64.to_int sgid2 = entry.gr_gid); + + (* Now chown the target too *) + Eio.Path.chown ~follow:true ~uid:uid_before ~gid:everybody symlink; + let luid3, lgid3 = stat_uid_gid link in + let suid3, sgid3 = stat_uid_gid symlink in + assert (suid3 = luid3); + assert (Int64.to_int lgid3 = entry.gr_gid); + assert (Int64.to_int sgid3 = entry.gr_gid);; +- : unit = () +``` + # Cancelling while readable Ensure reads can be cancelled promptly, even if there is no need to wait: From 2c64c019c1eb74159b6206f7a4ba26b41c6b917b Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 20 Nov 2024 20:09:27 +0000 Subject: [PATCH 2/8] Support chown in Eio_linux --- lib_eio_linux/eio_linux.ml | 3 +++ lib_eio_linux/low_level.ml | 9 +++++++++ lib_eio_linux/low_level.mli | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/lib_eio_linux/eio_linux.ml b/lib_eio_linux/eio_linux.ml index ec9c8eb07..da9db4a42 100644 --- a/lib_eio_linux/eio_linux.ml +++ b/lib_eio_linux/eio_linux.ml @@ -400,6 +400,9 @@ end = struct let read_link t path = Low_level.read_link t.fd path + let chown ~follow ~uid ~gid t path = + Low_level.chown ~follow ~uid ~gid t.fd path + let close t = match t.fd with | FD x -> Fd.close x diff --git a/lib_eio_linux/low_level.ml b/lib_eio_linux/low_level.ml index 42e72bfa3..94add8b51 100644 --- a/lib_eio_linux/low_level.ml +++ b/lib_eio_linux/low_level.ml @@ -524,6 +524,15 @@ let read_link fd path = Eio_unix.run_in_systhread ~label:"read_link" (fun () -> Eio_unix.Private.read_link (Some parent) leaf) with Unix.Unix_error (code, name, arg) -> raise @@ Err.wrap_fs code name arg +let chown ~follow ~uid ~gid fd path = + let module At = Uring.Linkat_flags in + let follow = if follow then At.empty_path else At.(empty_path + symlink_follow) in + let flags = (follow :> int) in + try + with_parent_dir_fd fd path @@ fun parent leaf -> + Eio_unix.run_in_systhread ~label:"chown" (fun () -> Eio_unix.Private.chown ~flags ~uid ~gid (Some parent) leaf) + with Unix.Unix_error (code, name, arg) -> raise @@ Err.wrap_fs code name arg + (* https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml *) let getaddrinfo ~service node = let to_eio_sockaddr_t {Unix.ai_family; ai_addr; ai_socktype; ai_protocol; _ } = diff --git a/lib_eio_linux/low_level.mli b/lib_eio_linux/low_level.mli index a3736e161..4de75685d 100644 --- a/lib_eio_linux/low_level.mli +++ b/lib_eio_linux/low_level.mli @@ -153,6 +153,12 @@ val rename : dir_fd -> string -> dir_fd -> string -> unit val symlink : link_to:string -> dir_fd -> string -> unit (** [symlink ~link_to dir path] creates a new symlink at [dir / path] pointing to [link_to]. *) +val chown : follow:bool -> uid:int64 -> gid:int64 -> dir_fd -> string -> unit +(** [chown ~follow ~uid ~gid dir path] changes the ownership of [dir / path] to [uid, gid]. + + If [follow = true] and [dir / path] is a symlink, then the ownership of the {e target} is + changed. If it is [false] then the ownership of the symlink itself is changed. *) + val pipe : sw:Switch.t -> fd * fd (** [pipe ~sw] returns a pair [r, w] with the readable and writeable ends of a new pipe. *) From 961f3770d0032ce649eadd1195fe667c8ba35db2 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 20 Nov 2024 20:32:20 +0000 Subject: [PATCH 3/8] Stub out chown on Eio_windows --- lib_eio_windows/fs.ml | 4 ++++ lib_eio_windows/low_level.ml | 4 ++++ lib_eio_windows/low_level.mli | 1 + 3 files changed, 9 insertions(+) diff --git a/lib_eio_windows/fs.ml b/lib_eio_windows/fs.ml index d877b6fb5..939e4c256 100755 --- a/lib_eio_windows/fs.ml +++ b/lib_eio_windows/fs.ml @@ -164,6 +164,10 @@ end = struct with_parent_dir t path @@ fun dirfd path -> Err.run (Low_level.read_link ?dirfd) path + let chown ~follow ~uid ~gid t path = + with_parent_dir t path @@ fun dirfd path -> + Err.run (fun () -> Low_level.chown ?dirfd ~follow ~uid ~gid path) () + let rename t old_path new_dir new_path = match Handler.as_posix_dir new_dir with | None -> invalid_arg "Target is not an eio_windows directory!" diff --git a/lib_eio_windows/low_level.ml b/lib_eio_windows/low_level.ml index 85f25cd26..64ecbfbab 100755 --- a/lib_eio_windows/low_level.ml +++ b/lib_eio_windows/low_level.ml @@ -138,6 +138,10 @@ let read_link ?dirfd path = in_worker_thread @@ fun () -> Eio_unix.Private.read_link dirfd path +let chown ?dirfd ~follow:_ ~uid ~gid path = + in_worker_thread @@ fun () -> + Eio_unix.Private.chown ~flags:0 ~uid ~gid dirfd path + external eio_readv : Unix.file_descr -> Cstruct.t array -> int = "caml_eio_windows_readv" external eio_preadv : Unix.file_descr -> Cstruct.t array -> Optint.Int63.t -> int = "caml_eio_windows_preadv" diff --git a/lib_eio_windows/low_level.mli b/lib_eio_windows/low_level.mli index e2ec400bd..77b26d431 100755 --- a/lib_eio_windows/low_level.mli +++ b/lib_eio_windows/low_level.mli @@ -43,6 +43,7 @@ val lstat : string -> Unix.LargeFile.stats val realpath : string -> string val read_link : ?dirfd:fd -> string -> string +val chown : ?dirfd:fd -> follow:bool -> uid:int64 -> gid:int64 -> string -> unit val mkdir : ?dirfd:fd -> ?nofollow:bool -> mode:int -> string -> unit val unlink : ?dirfd:fd -> dir:bool -> string -> unit From 85ffd3d7b1a2cb368894f514eea93c1e40700ac3 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 20 Nov 2024 20:53:54 +0000 Subject: [PATCH 4/8] Make Eio_unix.Private.chown require a file descriptor --- lib_eio/unix/eio_unix.mli | 4 ++-- lib_eio/unix/private.ml | 6 ++---- lib_eio_linux/low_level.ml | 2 +- lib_eio_posix/low_level.ml | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib_eio/unix/eio_unix.mli b/lib_eio/unix/eio_unix.mli index af3315ebb..5f05259b3 100644 --- a/lib_eio/unix/eio_unix.mli +++ b/lib_eio/unix/eio_unix.mli @@ -108,8 +108,8 @@ module Private : sig val read_link : Fd.t option -> string -> string val read_link_unix : Unix.file_descr option -> string -> string - val chown : flags:int -> uid:int64 -> gid:int64 -> Fd.t option -> string -> unit - val chown_unix : flags:int -> uid:int64 -> gid:int64 -> Unix.file_descr option -> string -> unit + val chown : flags:int -> uid:int64 -> gid:int64 -> Fd.t -> string -> unit + val chown_unix : flags:int -> uid:int64 -> gid:int64 -> Unix.file_descr -> string -> unit end module Pi = Pi diff --git a/lib_eio/unix/private.ml b/lib_eio/unix/private.ml index 01d23b339..afbad2869 100644 --- a/lib_eio/unix/private.ml +++ b/lib_eio/unix/private.ml @@ -37,9 +37,7 @@ let read_link fd path = Fd.use_exn_opt "readlink" fd (fun fd -> read_link_unix f external eio_fchownat : Unix.file_descr -> string -> int64 -> int64 -> int -> unit = "eio_unix_fchownat" let chown_unix ~flags ~uid ~gid fd path = - match fd with - | None -> Unix.chown path (Int64.to_int uid) (Int64.to_int gid) - | Some fd -> eio_fchownat fd path uid gid flags + eio_fchownat fd path uid gid flags let chown ~flags ~uid ~gid fd path = - Fd.use_exn_opt "chown" fd (fun fd -> chown_unix ~uid ~gid ~flags fd path) + Fd.use_exn "chown" fd (fun fd -> chown_unix ~uid ~gid ~flags fd path) diff --git a/lib_eio_linux/low_level.ml b/lib_eio_linux/low_level.ml index 94add8b51..1eec23ffb 100644 --- a/lib_eio_linux/low_level.ml +++ b/lib_eio_linux/low_level.ml @@ -530,7 +530,7 @@ let chown ~follow ~uid ~gid fd path = let flags = (follow :> int) in try with_parent_dir_fd fd path @@ fun parent leaf -> - Eio_unix.run_in_systhread ~label:"chown" (fun () -> Eio_unix.Private.chown ~flags ~uid ~gid (Some parent) leaf) + Eio_unix.run_in_systhread ~label:"chown" (fun () -> Eio_unix.Private.chown ~flags ~uid ~gid parent leaf) with Unix.Unix_error (code, name, arg) -> raise @@ Err.wrap_fs code name arg (* https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml *) diff --git a/lib_eio_posix/low_level.ml b/lib_eio_posix/low_level.ml index 61e03b894..066875544 100644 --- a/lib_eio_posix/low_level.ml +++ b/lib_eio_posix/low_level.ml @@ -433,7 +433,7 @@ let chown ~follow ~uid ~gid dirfd path = in_worker_thread "chown" @@ fun () -> Resolve.with_parent "chown" dirfd path @@ fun dirfd path -> let dirfd = Option.value dirfd ~default:at_fdcwd in - Eio_unix.Private.chown_unix ~flags ~uid ~gid (Some dirfd) path + Eio_unix.Private.chown_unix ~flags ~uid ~gid dirfd path type stat external create_stat : unit -> stat = "caml_eio_posix_make_stat" From 9808d1310dd205baa69dccfae2f3e21585d1a8d7 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 20 Nov 2024 21:16:21 +0000 Subject: [PATCH 5/8] Fix eio_windows --- lib_eio_windows/low_level.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_eio_windows/low_level.ml b/lib_eio_windows/low_level.ml index 64ecbfbab..eb925364e 100755 --- a/lib_eio_windows/low_level.ml +++ b/lib_eio_windows/low_level.ml @@ -140,7 +140,9 @@ let read_link ?dirfd path = let chown ?dirfd ~follow:_ ~uid ~gid path = in_worker_thread @@ fun () -> - Eio_unix.Private.chown ~flags:0 ~uid ~gid dirfd path + match dirfd with + | None -> failwith "Chown is unsupported on Windows" + | Some dirfd -> Eio_unix.Private.chown ~flags:0 ~uid ~gid dirfd path external eio_readv : Unix.file_descr -> Cstruct.t array -> int = "caml_eio_windows_readv" From 4dd28632ee994b875900c8350996687cd08a8d02 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Fri, 22 Nov 2024 09:54:27 +0000 Subject: [PATCH 6/8] Better chown exception message Co-authored-by: Thomas Leonard --- lib_eio/path.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_eio/path.ml b/lib_eio/path.ml index f59961e09..6e57e8e93 100644 --- a/lib_eio/path.ml +++ b/lib_eio/path.ml @@ -245,4 +245,4 @@ let chown ~follow ~uid ~gid t = try X.chown ~follow ~uid ~gid dir path with Exn.Io _ as ex -> let bt = Printexc.get_raw_backtrace () in - Exn.reraise_with_context ex bt "chowing file %a" pp t + Exn.reraise_with_context ex bt "changing ownership of %a" pp t From 510c2a693fb0479fdd5cacb9382521ccfb353442 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Fri, 22 Nov 2024 10:13:24 +0000 Subject: [PATCH 7/8] Fix eio_linux chown follow symlinks --- lib_eio_linux/low_level.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_eio_linux/low_level.ml b/lib_eio_linux/low_level.ml index 1eec23ffb..e4da16a4e 100644 --- a/lib_eio_linux/low_level.ml +++ b/lib_eio_linux/low_level.ml @@ -526,7 +526,7 @@ let read_link fd path = let chown ~follow ~uid ~gid fd path = let module At = Uring.Linkat_flags in - let follow = if follow then At.empty_path else At.(empty_path + symlink_follow) in + let follow = if follow then At.(empty_path + symlink_follow) else At.empty_path in let flags = (follow :> int) in try with_parent_dir_fd fd path @@ fun parent leaf -> From 04364c5470366a12eead8f2f210b42eb908077b6 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Fri, 22 Nov 2024 10:15:15 +0000 Subject: [PATCH 8/8] Fix C stubs for chown Don't call Int64_val inside a blocking section. --- lib_eio/unix/stubs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_eio/unix/stubs.c b/lib_eio/unix/stubs.c index 689254476..b5788ac0e 100644 --- a/lib_eio/unix/stubs.c +++ b/lib_eio/unix/stubs.c @@ -60,11 +60,13 @@ CAMLprim value eio_unix_fchownat(value v_fd, value v_path, value v_uid, value v_ CAMLparam3(v_path, v_uid, v_gid); char *path; int fd = Int_val(v_fd); + uid_t uid = Int64_val(v_uid); + gid_t gid = Int64_val(v_gid); int ret; caml_unix_check_path(v_path, "fchownat"); path = caml_stat_strdup(String_val(v_path)); caml_enter_blocking_section(); - ret = fchownat(fd, path, Int64_val(v_uid), Int64_val(v_gid), Int_val(v_flags)); + ret = fchownat(fd, path, uid, gid, Int_val(v_flags)); caml_leave_blocking_section(); caml_stat_free_preserving_errno(path); if (ret == -1)