Добавлен вывод через библиотеку sdiff

This commit is contained in:
Alexander Zhirov 2025-09-01 18:10:28 +03:00
parent aa214dcf96
commit 7f54a56ef5
Signed by: alexander
GPG key ID: C8D8BE544A27C511
2 changed files with 66 additions and 5 deletions

View file

@ -8,7 +8,14 @@
"name": "dwatch", "name": "dwatch",
"targetPath": "bin", "targetPath": "bin",
"targetType": "executable", "targetType": "executable",
"libs": [
"xdiff"
],
"dependencies": { "dependencies": {
"fanotify": "~>0.1.0" "fanotify": "~>0.1.0",
"sdiff": {
"repository": "git+git+https://git.zhirov.kz/dlang/sdiff.git",
"version": "8c388b112360a9f5bf89b9aa12b1977b8967b219"
}
} }
} }

View file

@ -10,7 +10,7 @@ import core.sys.posix.sys.stat : fstat, stat_t;
import core.stdc.errno : errno, EINTR; import core.stdc.errno : errno, EINTR;
import core.stdc.string : strerror; import core.stdc.string : strerror;
import std.stdio : writeln, writefln, stderr; import std.stdio : writeln, writefln, stderr;
import std.file : isDir, readText, exists; import std.file : isDir, readText, exists, read;
import std.string : strip, splitLines, startsWith, toStringz, fromStringz, split; import std.string : strip, splitLines, startsWith, toStringz, fromStringz, split;
import std.conv : to; import std.conv : to;
import std.exception : enforce; import std.exception : enforce;
@ -147,6 +147,8 @@ struct Session
uint uid; // LOGINUID из /proc/PID/loginuid uint uid; // LOGINUID из /proc/PID/loginuid
string filePathOpen; // путь, снятый на PERM string filePathOpen; // путь, снятый на PERM
bool changed; // был CLOSE_WRITE bool changed; // был CLOSE_WRITE
const(ubyte)[] fileBytesSource;
const(ubyte)[] fileBytesDiff;
} }
__gshared Session[DevIno] gMap; // (pid,dev,ino) -> Session __gshared Session[DevIno] gMap; // (pid,dev,ino) -> Session
@ -184,12 +186,28 @@ ulong dirMask()
FAN_OPEN | FAN_CLOSE_WRITE; FAN_OPEN | FAN_CLOSE_WRITE;
} }
ubyte[] readAllFromFd(int fd)
{
import std.array : appender;
ubyte[16_384] buf; // 16 KiB буфер
auto output = appender!(ubyte[]);
for (;;)
{
auto n = read(fd, buf.ptr, buf.length);
if (n <= 0)
break;
output.put(buf[0 .. n]);
}
return output.data;
}
/// ---- обработчики ---- /// ---- обработчики ----
void onOpenPerm(FanotifyEvent ev, Epoll ep) void onOpenPerm(FanotifyEvent ev, Epoll ep)
{ {
const pid = ev.pid; const pid = ev.pid;
auto procName = readProcComm(pid); auto procName = readProcComm(pid);
auto ids = readProcIds(pid); // <-- ruid + loginuid auto ids = readProcIds(pid);
DevIno key; DevIno key;
if (!getDevIno(ev.eventFd, key, pid)) if (!getDevIno(ev.eventFd, key, pid))
@ -200,13 +218,26 @@ void onOpenPerm(FanotifyEvent ev, Epoll ep)
auto path = readlinkFdPath(ev.eventFd); auto path = readlinkFdPath(ev.eventFd);
const(ubyte)[] content;
try
{
if (path.length)
{
content = readAllFromFd(ev.eventFd);
}
}
catch (Exception e)
{
content = [];
}
if (auto ps = key in gMap) if (auto ps = key in gMap)
{ {
// уже есть // уже есть
} }
else else
{ {
gMap[key] = Session(procName, ids.ruid, ids.uid, path, false); gMap[key] = Session(procName, ids.ruid, ids.uid, path, false, content);
} }
if (!(pid in gPidfdByPid)) if (!(pid in gPidfdByPid))
@ -214,7 +245,7 @@ void onOpenPerm(FanotifyEvent ev, Epoll ep)
int pfd = -1; int pfd = -1;
try try
{ {
pfd = pidfd_open(pid, 0); // на твоей системе так ок pfd = pidfd_open(pid, 0);
if (pfd < 0) if (pfd < 0)
writeln("pidfd_open failed: ", strerror(errno).fromStringz); writeln("pidfd_open failed: ", strerror(errno).fromStringz);
} }
@ -244,7 +275,27 @@ void onCloseWrite(FanotifyEvent ev)
if (!getDevIno(ev.eventFd, key, ev.pid)) if (!getDevIno(ev.eventFd, key, ev.pid))
return; return;
if (auto ps = key in gMap) if (auto ps = key in gMap)
{
ps.changed = true; ps.changed = true;
import sdiff;
const(ubyte)[] content;
try
{
if (ps.filePathOpen.length)
content = readAllFromFd(ev.eventFd);
}
catch (Exception e)
{
content = [];
}
auto dataSource = new MMFile(ps.fileBytesSource);
auto dataChange = new MMFile(content);
ps.fileBytesDiff = dataSource.diff(dataChange).slice();
}
} }
void flushAndClearForPid(int pid, Epoll ep) void flushAndClearForPid(int pid, Epoll ep)
@ -256,7 +307,10 @@ void flushAndClearForPid(int pid, Epoll ep)
continue; continue;
auto s = gMap[k]; auto s = gMap[k];
if (s.changed) if (s.changed)
{
logChange(s.procName, s.filePathOpen, s.uid, s.ruid); logChange(s.procName, s.filePathOpen, s.uid, s.ruid);
writeln(cast(string)s.fileBytesDiff);
}
gMap.remove(k); gMap.remove(k);
} }
if (auto p = pid in gPidfdByPid) if (auto p = pid in gPidfdByPid)