Packages

Query system, runtime and environment information

Current section

Files

Jump to
tinman src tinman_ffi.erl
Raw

src/tinman_ffi.erl

-module(tinman_ffi).
-export([platform/0, is_windows/0, arch/0, version/0, hostname/0, endianness/0,
used_memory/0, cpu_count/0, available_parallelism/0, runtime/0, runtime_version/0,
is_online/0, is_tty/0, is_test/0, process_id/0, libc_type/0, read_file/1, file_exists/1,
os_cmd/1, env/1]).
platform() ->
case os:type() of
{unix, Unix} ->
atom_to_binary(Unix);
{Family, _} ->
atom_to_binary(Family)
end.
is_windows() ->
case os:type() of
{win32, _} ->
true;
_ ->
false
end.
arch() ->
[Arch | _] =
string:split(
erlang:system_info(system_architecture), "-"),
list_to_binary(Arch).
version() ->
case os:version() of
{Major, Minor, Patch} ->
{ok, {version, Major, Minor, Patch}};
_ ->
{error, nil}
end.
hostname() ->
{ok, Hostname} = inet:gethostname(),
list_to_binary(Hostname).
endianness() ->
case erlang:system_info(endian) of
big ->
big_endian;
little ->
little_endian
end.
used_memory() ->
erlang:memory(total).
cpu_count() ->
case erlang:system_info(logical_processors) of
unknown ->
{error, nil};
Count ->
{ok, Count}
end.
available_parallelism() ->
case erlang:system_info(logical_processors_available) of
unknown ->
erlang:system_info(schedulers_online);
Count ->
min(Count, erlang:system_info(schedulers_online))
end.
runtime() ->
list_to_binary(erlang:system_info(machine)).
runtime_version() ->
list_to_binary(erlang:system_info(version)).
is_online() ->
case inet:getifaddrs() of
{ok, Interfaces} ->
has_non_internal_interface(Interfaces);
_ ->
false
end.
has_non_internal_interface([]) ->
false;
has_non_internal_interface([{_Name, Props} | Rest]) ->
case is_interface_online(Props) of
true ->
true;
false ->
has_non_internal_interface(Rest)
end.
is_interface_online(Props) ->
Flags = proplists:get_value(flags, Props, []),
Internal = lists:member(loopback, Flags),
HwAddr = proplists:get_value(hwaddr, Props),
HasValidMac = HwAddr =/= undefined andalso HwAddr =/= [0, 0, 0, 0, 0, 0],
not Internal andalso HasValidMac.
is_tty() ->
case io:columns() of
{ok, _} ->
% Check io:getopts for stdin, stdout, and terminal flags
Opts = io:getopts(),
HasStdin = proplists:get_value(stdin, Opts, false),
HasStdout = proplists:get_value(stdout, Opts, false),
HasStdin and HasStdout;
{error, _} ->
false
end.
is_test() ->
try
throw(check_stack)
catch
_:_:Stack ->
case lists:reverse(Stack) of
% Pattern 1: application_master -> *.start: from within app start, need to check the command line
[{application_master, _, _, _}, {_UserModule, start, _, _} | _] ->
OsPid = os:getpid(),
PsCmd = "ps -p " ++ OsPid ++ " -o command=",
CommandLine = os:cmd(PsCmd),
string:str(CommandLine, "_test") > 0;
% Pattern 2: *@@main.run_module -> *_test.main: directly in test start module
[{MainModule, run_module, _, _}, {TestModule, main, _, _} | _] ->
gleam@string:ends_with(atom_to_binary(MainModule), <<"@@main">>)
andalso gleam@string:ends_with(atom_to_binary(TestModule), <<"_test">>);
% Pattern 3: eunit_proc -> ... (called from within a test function)
[{eunit_proc, _, _, _} | _] ->
true;
_ ->
false
end
end.
%% -------------------- Process Information --------------------
process_id() ->
list_to_integer(os:getpid()).
libc_type() ->
case os:type() of
{unix, linux} ->
Arch = erlang:system_info(system_architecture),
Parts = string:split(Arch, "-", all),
case lists:member("musl", Parts) of
true ->
{ok, musl};
false ->
{ok, glibc}
end;
_ ->
{error, nil}
end.
read_file(Path) ->
case file:read_file(Path) of
{ok, Binary} ->
{ok, Binary};
{error, _} ->
{error, nil}
end.
file_exists(Path) ->
case filelib:is_file(binary_to_list(Path)) of
true ->
true;
false ->
false
end.
os_cmd(Command) ->
Result = os:cmd(binary_to_list(Command)),
list_to_binary(Result).
env(Name) ->
case os:getenv(binary_to_list(Name)) of
false ->
<<>>;
Value ->
list_to_binary(Value)
end.