Получение пользователя, но не 100%
This commit is contained in:
parent
bc02ac8518
commit
2876a45a85
3 changed files with 159 additions and 1 deletions
16
source/app.d
16
source/app.d
|
@ -2,6 +2,7 @@ module app;
|
|||
|
||||
import dfanotify; // твой модуль сверху
|
||||
import depoll; // новый модуль для epoll
|
||||
import event_actor;
|
||||
|
||||
import core.sys.posix.fcntl : O_RDONLY, O_LARGEFILE;
|
||||
import core.stdc.errno : errno;
|
||||
|
@ -277,7 +278,16 @@ void main(string[] args)
|
|||
foreach (ev; events)
|
||||
{
|
||||
auto pname = eventProcessName(ev.pid);
|
||||
writeln("pid = ", ev.pid, "\tproc = ", pname, "\tmask = ", maskToStr(ev.mask));
|
||||
// writeln("pid = ", ev.pid, "\tproc = ", pname, "\tmask = ", maskToStr(ev.mask));
|
||||
writefln("[%s] pid = %s proc = %s mask = %s",
|
||||
(tag == TAG_PRE) ? "PRE" : "NOTIF",
|
||||
ev.pid, pname,
|
||||
maskToStr(ev.mask)
|
||||
);
|
||||
auto actor = eventActorFromPid(ev.pid);
|
||||
writeln("user=", actor.user, " uid=", actor.uid,
|
||||
" ruid=", actor.ruid, "(", actor.ruser, ")",
|
||||
" euid=", actor.euid, "(", actor.euser, ")");
|
||||
|
||||
if (tag == TAG_PRE && (ev.isOpenPerm || ev.isAccessPerm))
|
||||
{
|
||||
|
@ -329,6 +339,10 @@ void main(string[] args)
|
|||
// snag --config ... create --comment "CLOSE_WRITE - <name>" ...
|
||||
writefln(" -> HANDLE CLOSE_WRITE for: %s", ev.name);
|
||||
}
|
||||
else if (ev.isMoved)
|
||||
{
|
||||
writefln(" -> HANDLE MOVED for: %s", ev.name);
|
||||
}
|
||||
else if (ev.isModify)
|
||||
{
|
||||
writefln(" -> HANDLE MODIFY for: %s", ev.name);
|
||||
|
|
|
@ -83,6 +83,11 @@ class FanotifyEvent
|
|||
return (mask & FAN_ACCESS) != 0;
|
||||
}
|
||||
|
||||
bool isMoved() const
|
||||
{
|
||||
return (mask & FAN_MOVED_FROM) != 0;
|
||||
}
|
||||
|
||||
bool isCreate() const
|
||||
{
|
||||
return (mask & FAN_CREATE) != 0;
|
||||
|
|
139
source/event_actor.d
Normal file
139
source/event_actor.d
Normal file
|
@ -0,0 +1,139 @@
|
|||
module event_actor;
|
||||
|
||||
import core.sys.posix.pwd : passwd, getpwuid_r;
|
||||
import core.sys.posix.sys.types : uid_t;
|
||||
import core.stdc.stdlib : malloc, free;
|
||||
import core.stdc.string : strlen;
|
||||
import std.file : readText, exists;
|
||||
import std.string : splitLines, strip;
|
||||
import std.conv : to;
|
||||
|
||||
// для токенизации по пробельным
|
||||
import std.ascii : isWhite;
|
||||
import std.algorithm.iteration : splitter;
|
||||
import std.array : array;
|
||||
|
||||
struct EventActor
|
||||
{
|
||||
uid_t uid; // выбранный UID (loginuid если есть, иначе ruid)
|
||||
string user; // имя пользователя для uid (может быть пустым)
|
||||
uid_t ruid, euid, suid, fsuid;
|
||||
string ruser, euser, suser, fsuser;
|
||||
bool hasLoginuid;
|
||||
uid_t loginuid;
|
||||
string loginuser;
|
||||
}
|
||||
|
||||
private string userName(uid_t uid)
|
||||
{
|
||||
enum BUF = 4096;
|
||||
auto buf = cast(char*) malloc(BUF);
|
||||
scope (exit)
|
||||
if (buf)
|
||||
free(buf);
|
||||
passwd pwd;
|
||||
passwd* outp;
|
||||
auto rc = getpwuid_r(uid, &pwd, buf, BUF, &outp);
|
||||
if (rc == 0 && outp !is null)
|
||||
{
|
||||
return pwd.pw_name[0 .. strlen(pwd.pw_name)].idup;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Парсит строку вида: "Uid:\t<ruid>\t<euid>\t<suid>\t<fsuid>"
|
||||
private bool parseUidLine(string line, out uid_t r, out uid_t e, out uid_t s, out uid_t f)
|
||||
{
|
||||
// разобьём по любым пробельным символам
|
||||
auto toks = line.splitter!isWhite.array; // ["Uid:", "1000", "1000", "1000", "1000"]
|
||||
if (toks.length >= 5 && toks[0] == "Uid:")
|
||||
{
|
||||
try
|
||||
{
|
||||
r = toks[1].to!uid_t;
|
||||
e = toks[2].to!uid_t;
|
||||
s = toks[3].to!uid_t;
|
||||
f = toks[4].to!uid_t;
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Главная функция: кто инициировал событие (по PID из fanotify_event_metadata)
|
||||
EventActor eventActorFromPid(int pid)
|
||||
{
|
||||
EventActor a;
|
||||
if (pid <= 0)
|
||||
return a;
|
||||
|
||||
const base = "/proc/" ~ pid.to!string ~ "/";
|
||||
const statusPath = base ~ "status";
|
||||
|
||||
if (exists(statusPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
auto txt = readText(statusPath);
|
||||
uid_t r = 0, e = 0, s = 0, f = 0;
|
||||
foreach (line; txt.splitLines())
|
||||
{
|
||||
// ищем строку "Uid:"
|
||||
if (line.length >= 4 && line[0 .. 4] == "Uid:")
|
||||
{
|
||||
if (parseUidLine(line, r, e, s, f))
|
||||
{
|
||||
a.ruid = r;
|
||||
a.euid = e;
|
||||
a.suid = s;
|
||||
a.fsuid = f;
|
||||
a.ruser = userName(r);
|
||||
a.euser = userName(e);
|
||||
a.suser = userName(s);
|
||||
a.fsuser = userName(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// loginuid — владелец сессии (если audit включён)
|
||||
const loginPath = base ~ "loginuid";
|
||||
if (exists(loginPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
auto s = readText(loginPath).strip;
|
||||
if (s.length)
|
||||
{
|
||||
a.loginuid = s.to!uid_t;
|
||||
a.loginuser = userName(a.loginuid);
|
||||
a.hasLoginuid = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// выбираем «итогового» пользователя
|
||||
if (a.hasLoginuid)
|
||||
{
|
||||
a.uid = a.loginuid;
|
||||
a.user = a.loginuser.length ? a.loginuser : ("uid:" ~ a.loginuid.to!string);
|
||||
}
|
||||
else
|
||||
{
|
||||
a.uid = a.ruid;
|
||||
a.user = a.ruser.length ? a.ruser : ("uid:" ~ a.ruid.to!string);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue