import os,ctypes,struct,time,json,signal
libc=ctypes.CDLL('libc.so.6',use_errno=True)
fd=libc.inotify_init1(0)
if fd<0: raise OSError(ctypes.get_errno())
wd=libc.inotify_add_watch(fd,b'/run/graphiti-control',0x00000100|0x00000200|0x00000008|0x00000002|0x00000004|0x00000080)
start=time.time(); events=[]
while time.time()-start<240:
import select
r,_,_=select.select([fd],[],[],1)
if not r: continue
data=os.read(fd,4096); off=0
while off+16<=len(data):
wd2,mask,cookie,nlen=struct.unpack_from('iIII',data,off); off+=16
name=data[off:off+nlen].split(b'\0',1)[0].decode(errors='replace'); off+=nlen
if name=='maintenance.lock':
procs=[]
for d in os.listdir('/proc'):
if d.isdigit():
try:
cmd=open('/proc/'+d+'/cmdline','rb').read().replace(b'\0',b' ').decode(errors='replace')
if cmd: procs.append({'pid':int(d),'cmd':cmd[:300]})
except: pass
events.append({'utc':time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()),'mask':mask,'operation':('CREATE' if mask&0x100 else '')+('WRITE' if mask&0x2 else '')+('DELETE' if mask&0x200 else '')+('MOVE' if mask&0x40 or mask&0x80 else ''),'process_snapshot':procs})
print(json.dumps({'watch_path':'/run/graphiti-control/maintenance.lock','duration_seconds':round(time.time()-start,1),'events':events},ensure_ascii=False))
os.close(fd)