Created
May 12, 2017 05:57
-
-
Save niamtokik/1a8788b66b0be4cbf337d3c4df659f03 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% | |
% extract namespace information from linux procfs. | |
% | |
-module(namespace). | |
-compile(export_all). | |
-include_lib("eunit/include/eunit.hrl"). | |
-record(pid, { id :: integer(), | |
cgroup = 0 :: integer(), | |
ipc = 0 :: integer(), | |
mnt = 0 :: integer(), | |
net = 0 :: integer(), | |
pid = 0 :: integer(), | |
user = 0 :: integer(), | |
uts = 0 :: integer() }). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
procfs() -> | |
"/proc". | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
procfs(Pid) when is_integer(Pid) -> | |
procfs(erlang:integer_to_list(Pid)); | |
procfs(Pid) -> | |
procfs() ++ "/" ++ Pid. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
procfs(Pid, cgroup) -> | |
procfs(Pid, erlang:atom_to_list(cgroup)); | |
procfs(Pid, pid) -> | |
procfs(Pid, erlang:atom_to_list(pid)); | |
procfs(Pid, user) -> | |
procfs(Pid, erlang:atom_to_list(user)); | |
procfs(Pid, net) -> | |
procfs(Pid, erlang:atom_to_list(net)); | |
procfs(Pid, uts) -> | |
procfs(Pid, erlang:atom_to_list(uts)); | |
procfs(Pid, ipc) -> | |
procfs(Pid, erlang:atom_to_list(ipc)); | |
procfs(Pid, mnt) -> | |
procfs(Pid, erlang:atom_to_list(mnt)); | |
procfs(Pid, Namespace) | |
when is_list(Namespace) -> | |
procfs(Pid) ++ "/ns/" ++ Namespace. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
read_namespace(Link) -> | |
try file:read_link(Link) | |
of | |
{ok, Data} -> namespace_parser(Data); | |
_ -> "" | |
catch | |
error:Reason -> {error, Reason} | |
end. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
read_namespace(Pid, Namespace) -> | |
read_namespace(procfs(Pid,Namespace)). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_parser("cgroup:[" ++ Namespace) -> | |
{cgroup, namespace_parser(Namespace, [])}; | |
namespace_parser("ipc:[" ++ Namespace) -> | |
{ipc, namespace_parser(Namespace, [])}; | |
namespace_parser("mnt:[" ++ Namespace) -> | |
{mnt, namespace_parser(Namespace, [])}; | |
namespace_parser("net:[" ++ Namespace) -> | |
{net, namespace_parser(Namespace, [])}; | |
namespace_parser("pid:[" ++ Namespace) -> | |
{pid, namespace_parser(Namespace, [])}; | |
namespace_parser("user:[" ++ Namespace) -> | |
{user, namespace_parser(Namespace, [])}; | |
namespace_parser("uts:[" ++ Namespace) -> | |
{uts, namespace_parser(Namespace, [])}; | |
namespace_parser(_) -> | |
{error, not_namespace}. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_parser([$]], Buf) -> | |
erlang:list_to_integer(lists:reverse(Buf)); | |
namespace_parser([H|T], Buf) | |
when H >= $0 andalso H =< $9 -> | |
namespace_parser(T, [H] ++ Buf). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_read_link(Link) -> | |
try file:read_link(Link) | |
of | |
{ok, Data} -> namespace_link_extract(Data); | |
_Else -> _Else | |
catch | |
error:Reason -> {error, Reason} | |
end. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_link_extract_test() -> | |
TEST001_IN=namespace_link_extract("cgroup:[4026531835]"), | |
TEST001_OUT={cgroup, 4026531835}, | |
?assertEqual(TEST001_IN, TEST001_OUT), | |
TEST002_IN=namespace_link_extract("ipc:[4026531839]"), | |
TEST002_OUT={ipc, 4026531839}, | |
?assertEqual(TEST002_IN, TEST002_OUT), | |
TEST003_IN=namespace_link_extract("mnt:[4026531840]"), | |
TEST003_OUT={mnt, 4026531840}, | |
?assertEqual(TEST003_IN, TEST003_OUT), | |
TEST004_IN=namespace_link_extract("net:[4026531957]"), | |
TEST004_OUT={net, 4026531957}, | |
?assertEqual(TEST004_IN, TEST004_OUT), | |
TEST005_IN=namespace_link_extract("pid:[4026531836]"), | |
TEST005_OUT={pid, 4026531836}, | |
?assertEqual(TEST005_IN, TEST005_OUT), | |
TEST006_IN=namespace_link_extract("user:[4026531837]"), | |
TEST006_OUT={user, 4026531837}, | |
?assertEqual(TEST006_IN, TEST006_OUT), | |
TEST007_IN=namespace_link_extract("uts:[4026531838]"), | |
TEST007_OUT={uts, 4026531838}, | |
?assertEqual(TEST007_IN, TEST007_OUT). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_link_extract("cgroup:[" ++ NS) -> | |
{cgroup, namespace_link_extract(NS)}; | |
namespace_link_extract("ipc:[" ++ NS) -> | |
{ipc, namespace_link_extract(NS)}; | |
namespace_link_extract("mnt:[" ++ NS) -> | |
{mnt, namespace_link_extract(NS)}; | |
namespace_link_extract("net:[" ++ NS) -> | |
{net, namespace_link_extract(NS)}; | |
namespace_link_extract("pid:[" ++ NS) -> | |
{pid,namespace_link_extract(NS)}; | |
namespace_link_extract("user:[" ++ NS) -> | |
{user, namespace_link_extract(NS)}; | |
namespace_link_extract("uts:[" ++ NS) -> | |
{uts, namespace_link_extract(NS)}; | |
namespace_link_extract(NS) when is_list(NS) -> | |
erlang:list_to_integer(namespace_link_extract(NS, [])). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
namespace_link_extract([$]], Buf) -> | |
lists:reverse(Buf); | |
namespace_link_extract([H|T], Buf) | |
when H >= $0 andalso H =< $9 -> | |
namespace_link_extract(T, [H] ++ Buf). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
is_process(Path) -> | |
try erlang:list_to_integer(Path) | |
of | |
_ -> true | |
catch | |
throw:_ -> false; | |
error:_ -> false | |
end. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
get_pids_as_list() -> | |
{ok, Directories} = file:read_dir("/proc"), | |
[ File || File <- Directories, is_process(File) =:= true ]. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
get_ns(Pid) when is_integer(Pid) -> | |
get_ns(erlang:integer_to_list(Pid)); | |
get_ns(Pid) when is_list(Pid)-> | |
{ok, Files} = file:list_dir("/proc/" ++ Pid ++ "/ns"), | |
lists:map(fun namespace_read_link/1, Files). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
pid_to_record(Pid) when is_list(Pid) -> | |
pid_to_record(erlang:list_to_integer(Pid)); | |
pid_to_record(Pid) when is_integer(Pid) -> | |
#pid{ id = Pid }. | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
ns_to_record(PidStruct) -> | |
Pid = PidStruct#pid.id, | |
lists:foldr(fun ns_to_record/2, PidStruct, get_ns(Pid)). | |
%%-------------------------------------------------------------------- | |
%% | |
%%-------------------------------------------------------------------- | |
ns_to_record({cgroup, Value}, PidStruct) -> | |
PidStruct#pid{ cgroup = Value }; | |
ns_to_record({ipc, Value}, PidStruct) -> | |
PidStruct#pid{ ipc = Value }; | |
ns_to_record({mnt, Value}, PidStruct) -> | |
PidStruct#pid{ mnt = Value }; | |
ns_to_record({net, Value}, PidStruct) -> | |
PidStruct#pid{ net = Value }; | |
ns_to_record({pid, Value}, PidStruct) -> | |
PidStruct#pid{ pid = Value }; | |
ns_to_record({uts, Value}, PidStruct) -> | |
PidStruct#pid{ uts = Value }. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment