Skip to content

Commit

Permalink
Expose uv_os_get_group
Browse files Browse the repository at this point in the history
  • Loading branch information
aantron committed Dec 15, 2023
1 parent 74041c4 commit fa3bc3e
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 4 deletions.
8 changes: 8 additions & 0 deletions src/c/luv_c_function_descriptions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1803,6 +1803,14 @@ struct
let free_passwd =
foreign "uv_os_free_passwd"
(ptr t @-> returning void)

let get_group =
foreign "uv_os_get_group"
(ptr Types.Passwd.group @-> ulong @-> returning error_code)

let free_group =
foreign "uv_os_free_group"
(ptr Types.Passwd.group @-> returning void)
end

module Env =
Expand Down
7 changes: 7 additions & 0 deletions src/c/luv_c_type_descriptions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,13 @@ struct
let shell = field t "shell" string_opt
let homedir = field t "homedir" string
let () = seal t

let group : ([ `Group ] structure) typ =
typedef (structure "`Group") "uv_group_t"
let groupname = field group "groupname" string
let group_gid = field group "gid" ulong
let members = field group "members" (ptr (ptr char))
let () = seal group
end

module Time =
Expand Down
14 changes: 14 additions & 0 deletions src/c/shims.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,4 +700,18 @@
{
return ENOSYS;
}

typedef struct {
char *groupname;
unsigned long gid;
char **members;
} uv_group_t;

static int uv_os_get_group(uv_group_t *group, unsigned long gid)
{
return ENOSYS;
}
static void uv_os_free_group(uv_passwd_t *group)
{
}
#endif
1 change: 1 addition & 0 deletions src/feature/detect_features.ml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ let () =
needs 23 "open_osfhandle" "See {!Luv.File.open_osfhandle}.";
needs 31 "os_environ" "See {!Luv.Env.environ}.";
needs 6 "os_homedir" "See {!Luv.Path.homedir}.";
needs 45 "os_get_group" "See {!Luv.Passwd.get_group}.";
needs 9 "os_get_passwd" "See {!Luv.Passwd.get_passwd}.";
needs 45 "os_get_passwd_uid" "See {!Luv.Passwd.get_passwd}.";
needs 12 "os_getenv" "See {!Luv.Env.getenv}.";
Expand Down
46 changes: 45 additions & 1 deletion src/passwd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@



type t = {
type user = {
username : string;
uid : Unsigned.ulong;
gid : Unsigned.ulong;
shell : string option;
homedir : string;
}

type t = user

let get_passwd ?uid () =
let c_passwd = Ctypes.make C.Types.Passwd.t in
let pointer = Ctypes.addr c_passwd in
Expand All @@ -31,3 +33,45 @@ let get_passwd ?uid () =
C.Functions.Passwd.free_passwd pointer;
passwd
end

type group = {
groupname : string;
gid : Unsigned.ulong;
members : string list;
}

let strlen c_string =
let rec loop i =
if Ctypes.(!@ (c_string +@ i)) = '\x00' then
i
else
loop (i + 1)
in
loop 0

let string_list_from_c c_strings =
let rec loop i acc =
let c_string = Ctypes.(!@ (c_strings +@ i)) in
if Ctypes.is_null c_string then
List.rev acc
else
let length = strlen c_string in
let s = Ctypes.string_from_ptr c_string ~length in
loop (i + 1) (s::acc)
in
loop 0 []

let get_group gid =
let c_group = Ctypes.make C.Types.Passwd.group in
C.Functions.Passwd.get_group (Ctypes.addr c_group) gid
|> Error.to_result_lazy begin fun () ->
let module G = C.Types.Passwd in
let group = {
groupname = Ctypes.getf c_group G.groupname;
gid = Ctypes.getf c_group G.group_gid;
members = Ctypes.getf c_group G.members |> string_list_from_c;
}
in
C.Functions.Passwd.free_group (Ctypes.addr c_group);
group
end
24 changes: 22 additions & 2 deletions src/passwd.mli
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@



type t = {
type user = {
username : string;
uid : Unsigned.ulong;
gid : Unsigned.ulong;
Expand All @@ -13,7 +13,11 @@ type t = {
(** Binds {{:http://docs.libuv.org/en/v1.x/misc.html#c.uv_passwd_t}
[uv_passwd_t]}. *)

val get_passwd : ?uid:Unsigned.ulong -> unit -> (t, Error.t) result
(**/**)
type t = user
(**/**)

val get_passwd : ?uid:Unsigned.ulong -> unit -> (user, Error.t) result
(** Gets passwd entry for the current user or the user with the given uid.
Binds {{:http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_get_passwd}
Expand All @@ -28,3 +32,19 @@ val get_passwd : ?uid:Unsigned.ulong -> unit -> (t, Error.t) result
The [?uid] argument requires Luv 0.5.13 and libuv 1.45.0.
{{!Luv.Require} Feature check}: [Luv.Require.(has os_get_passwd_uid)] *)

type group = {
groupname : string;
gid : Unsigned.ulong;
members : string list;
}
(** Binds [uv_group_t]. *)

val get_group : Unsigned.ulong -> (group, Error.t) result
(** Gets the entry for the group with the given gid.
Binds [uv_os_get_group].
Requires Luv 0.5.13 and libuv 1.45.0.
{{!Luv.Require} Feature check}: [Luv.Require.(has os_get_group)] *)
2 changes: 1 addition & 1 deletion src/process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ let null_callback =
let c_string_array strings =
(* The array-of-pointers doesn't hold a reference to the individual string
pointers, so we need to allocate and return them so the consumer can ensure
they stayed referenced to avoid the GC cleaning them up early. *)
they stay referenced to avoid the GC cleaning them up early. *)
let c_string_ptrs = strings @ [""]
|> List.map Ctypes.(CArray.of_string)
|> List.map Ctypes.CArray.start
Expand Down

0 comments on commit fa3bc3e

Please sign in to comment.