From bc02ac8518c34ee9cab2d5afab67663cd4bacb52 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Fri, 29 Aug 2025 01:27:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=86=D0=B5=D1=81=D1=81=D0=B0=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82?= =?UTF-8?q?=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/app.d | 87 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/source/app.d b/source/app.d index 3b56af9..fffdac5 100644 --- a/source/app.d +++ b/source/app.d @@ -6,7 +6,7 @@ import depoll; // новый модуль для epoll import core.sys.posix.fcntl : O_RDONLY, O_LARGEFILE; import core.stdc.errno : errno; import core.stdc.string : strerror; -import std.string : fromStringz, toStringz, join; +import std.string : fromStringz, toStringz, join, strip; import std.conv : to; import std.stdio : writeln, writefln; import std.getopt; @@ -18,6 +18,8 @@ import std.exception; import std.path : baseName; +import std.file : readText, exists, read; + /// Вернуть путь для fd из события PRE_CONTENT. /// Может вернуть "(deleted)" или пустую строку, если объект без имени. string pathFromEventFd(int fd) @@ -35,6 +37,76 @@ string pathFromEventFd(int fd) return cast(string) buf[0 .. n].idup; } +/// Возвращает "имя процесса" для события fanotify. +/// Приоритет: /proc//comm → имя ссылки /proc//exe → первый токен из cmdline. +/// Если всё сломалось — "pid:". +string eventProcessName(int pid) +{ + // 1) /proc//comm — самое точное короткое имя + const commPath = "/proc/" ~ pid.to!string ~ "/comm"; + try + { + if (exists(commPath)) + { + auto s = readText(commPath).strip; // там обычно одна строка с \n + if (s.length) + return s; + } + } + catch (Exception e) + { + } + + // 2) /proc//exe — полный путь к исполняемому файлу + try + { + char[4096] buf; + auto link = "/proc/" ~ pid.to!string ~ "/exe"; + auto n = readlink(link.toStringz, buf.ptr, buf.length); + if (n > 0) + { + auto exePath = cast(string) buf[0 .. n].idup; + auto name = baseName(exePath); + if (name.length) + return name; + } + } + catch (Exception e) + { + } + + // 3) /proc//cmdline — первый NUL-разделённый аргумент + try + { + const cmdPath = "/proc/" ~ pid.to!string ~ "/cmdline"; + if (exists(cmdPath)) + { + auto bytes = cast(const(ubyte)[]) read(cmdPath); + if (bytes.length) + { + // до первого \0 + size_t i = 0; + for (; i < bytes.length && bytes[i] != 0; ++i) + { + } + auto first = cast(string) bytes[0 .. i].idup; + if (first.length) + { + auto name = baseName(first); + if (name.length) + return name; + } + } + } + } + catch (Exception e) + { + } + + // fallback + return "pid:" ~ pid.to!string; +} + // Удобная печать маски (для живых логов) string maskToStr(uint64_t m) { @@ -204,6 +276,9 @@ void main(string[] args) foreach (ev; events) { + auto pname = eventProcessName(ev.pid); + writeln("pid = ", ev.pid, "\tproc = ", pname, "\tmask = ", maskToStr(ev.mask)); + if (tag == TAG_PRE && (ev.isOpenPerm || ev.isAccessPerm)) { string path = pathFromEventFd(ev.eventFd); @@ -214,11 +289,11 @@ void main(string[] args) } // Лог - writefln("[%s] pid=%s mask=%s name=%s", - (tag == TAG_PRE) ? "PRE" : "NOTIF", - ev.pid.to!string, - maskToStr(ev.mask), - ev.name.length ? ev.name : "(unknown)"); + // writefln("[%s] pid=%s mask=%s name=%s", + // (tag == TAG_PRE) ? "PRE" : "NOTIF", + // ev.pid.to!string, + // maskToStr(ev.mask), + // ev.name.length ? ev.name : "(unknown)"); // --- ВЕТКА РЕШЕНИЯ ДЛЯ PERM-СОБЫТИЙ --- // if (tag == TAG_PRE &&