Добавлен вывод через библиотеку sdiff
This commit is contained in:
		
							parent
							
								
									aa214dcf96
								
							
						
					
					
						commit
						973cf8ac5a
					
				
					 3 changed files with 97 additions and 5 deletions
				
			
		
							
								
								
									
										31
									
								
								config.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								config.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
{
 | 
			
		||||
	"database": "/var/lib/dwatch/data.db",
 | 
			
		||||
	"rules": {
 | 
			
		||||
		"tracking": [
 | 
			
		||||
		],
 | 
			
		||||
		"ignore": [
 | 
			
		||||
		]
 | 
			
		||||
	},
 | 
			
		||||
	"watch": [
 | 
			
		||||
		{
 | 
			
		||||
			"path": "/path/to/watch-1",
 | 
			
		||||
			"child": true,
 | 
			
		||||
			"rules": {
 | 
			
		||||
				"tracking": [
 | 
			
		||||
				],
 | 
			
		||||
				"ignore": [
 | 
			
		||||
				]
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"path": "/path/to/watch-2",
 | 
			
		||||
			"child": false,
 | 
			
		||||
			"rules": {
 | 
			
		||||
				"tracking": [
 | 
			
		||||
				],
 | 
			
		||||
				"ignore": [
 | 
			
		||||
				]
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								dub.json
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								dub.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -8,7 +8,14 @@
 | 
			
		|||
	"name": "dwatch",
 | 
			
		||||
	"targetPath": "bin",
 | 
			
		||||
	"targetType": "executable",
 | 
			
		||||
	"libs": [
 | 
			
		||||
		"xdiff"
 | 
			
		||||
	],
 | 
			
		||||
	"dependencies": {
 | 
			
		||||
		"fanotify": "~>0.1.0"
 | 
			
		||||
		"fanotify": "~>0.1.0",
 | 
			
		||||
		"sdiff": {
 | 
			
		||||
			"repository": "git+https://git.zhirov.kz/dlang/sdiff.git",
 | 
			
		||||
			"version": "8c388b112360a9f5bf89b9aa12b1977b8967b219"
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								source/app.d
									
										
									
									
									
								
							
							
						
						
									
										62
									
								
								source/app.d
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -10,7 +10,7 @@ import core.sys.posix.sys.stat : fstat, stat_t;
 | 
			
		|||
import core.stdc.errno : errno, EINTR;
 | 
			
		||||
import core.stdc.string : strerror;
 | 
			
		||||
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.conv : to;
 | 
			
		||||
import std.exception : enforce;
 | 
			
		||||
| 
						 | 
				
			
			@ -147,6 +147,8 @@ struct Session
 | 
			
		|||
	uint uid; // LOGINUID из /proc/PID/loginuid
 | 
			
		||||
	string filePathOpen; // путь, снятый на PERM
 | 
			
		||||
	bool changed; // был CLOSE_WRITE
 | 
			
		||||
	const(ubyte)[] fileBytesSource;
 | 
			
		||||
	const(ubyte)[] fileBytesDiff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__gshared Session[DevIno] gMap; // (pid,dev,ino) -> Session
 | 
			
		||||
| 
						 | 
				
			
			@ -184,12 +186,28 @@ ulong dirMask()
 | 
			
		|||
		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)
 | 
			
		||||
{
 | 
			
		||||
	const pid = ev.pid;
 | 
			
		||||
	auto procName = readProcComm(pid);
 | 
			
		||||
	auto ids = readProcIds(pid); // <-- ruid + loginuid
 | 
			
		||||
	auto ids = readProcIds(pid);
 | 
			
		||||
 | 
			
		||||
	DevIno key;
 | 
			
		||||
	if (!getDevIno(ev.eventFd, key, pid))
 | 
			
		||||
| 
						 | 
				
			
			@ -200,13 +218,26 @@ void onOpenPerm(FanotifyEvent ev, Epoll ep)
 | 
			
		|||
 | 
			
		||||
	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)
 | 
			
		||||
	{
 | 
			
		||||
		// уже есть
 | 
			
		||||
	}
 | 
			
		||||
	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))
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +245,7 @@ void onOpenPerm(FanotifyEvent ev, Epoll ep)
 | 
			
		|||
		int pfd = -1;
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			pfd = pidfd_open(pid, 0); // на твоей системе так ок
 | 
			
		||||
			pfd = pidfd_open(pid, 0);
 | 
			
		||||
			if (pfd < 0)
 | 
			
		||||
				writeln("pidfd_open failed: ", strerror(errno).fromStringz);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +275,27 @@ void onCloseWrite(FanotifyEvent ev)
 | 
			
		|||
	if (!getDevIno(ev.eventFd, key, ev.pid))
 | 
			
		||||
		return;
 | 
			
		||||
	if (auto ps = key in gMap)
 | 
			
		||||
	{
 | 
			
		||||
		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)
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +307,10 @@ void flushAndClearForPid(int pid, Epoll ep)
 | 
			
		|||
			continue;
 | 
			
		||||
		auto s = gMap[k];
 | 
			
		||||
		if (s.changed)
 | 
			
		||||
		{
 | 
			
		||||
			logChange(s.procName, s.filePathOpen, s.uid, s.ruid);
 | 
			
		||||
			writeln(cast(string)s.fileBytesDiff);
 | 
			
		||||
		}
 | 
			
		||||
		gMap.remove(k);
 | 
			
		||||
	}
 | 
			
		||||
	if (auto p = pid in gPidfdByPid)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue