Welcome, guest | Sign In | My Account | Store | Cart
'''
    Low level inotify wrapper
'''

from os import read, close
from struct import unpack
from fcntl import ioctl
from termios import FIONREAD
from time import sleep
from ctypes import cdll, c_int, POINTER
from errno import errorcode

libc = cdll.LoadLibrary('libc.so.6')
libc.__errno_location.restype = POINTER(c_int)
def geterr(): return errorcode[libc.__errno_location().contents.value]

class Inotify(object):
    def __init__(self):
        self.fd = libc.inotify_init()
        if self.fd == -1:
            print 'inotify INIT err :', geterr()
            raise OSError()
    def read(self):
        size_int = c_int()
        while ioctl(self.fd, FIONREAD, size_int)==-1: sleep(1)
        size = size_int.value
        if not size: return
        data = read(self.fd, size)
        deb = 0
        while deb < size:
            fin = deb+16
            wd, mask, cookie, name_len = unpack('iIII', data[deb:fin])
            deb, fin = fin, fin+name_len
            name = unpack('%ds' % name_len, data[deb:fin])
            name = name[0].rstrip('\0')
            deb = fin
            yield wd, mask, cookie, name
    def add_watch(self, path, mask):
        wd = libc.inotify_add_watch(self.fd, path, mask)
        if wd == -1: print 'inotify ADD err :', geterr()
        return wd
    def rm_watch(self, wd):
        ret = libc.inotify_rm_watch(self.fd, wd)
        if ret == -1: print 'inotify RM err :', geterr()
    def close(self):
        close(self.fd)

FLAGS = {
    'ACCESS'      : 0x00000001, # IN_ACCESS
    'MODIFY'      : 0x00000002, # IN_MODIFY
    'ATTRIB'      : 0x00000004, # IN_ATTRIB
    'WRITE'       : 0x00000008, # IN_CLOSE_WRITE
    'CLOSE'       : 0x00000010, # IN_CLOSE_NOWRITE
    'OPEN'        : 0x00000020, # IN_OPEN
    'MOVED_FROM'  : 0x00000040, # IN_MOVED_FROM
    'MOVED_TO'    : 0x00000080, # IN_MOVED_TO
    'CREATE'      : 0x00000100, # IN_CREATE
    'DELETE'      : 0x00000200, # IN_DELETE
    'DELETE_SELF' : 0x00000400, # IN_DELETE_SELF
    'MOVE_SELF'   : 0x00000800, # IN_MOVE_SELF
    'UNMOUNT'     : 0x00002000, # IN_UNMOUNT
    'Q_OVERFLOW'  : 0x00004000, # IN_Q_OVERFLOW
    'IGNORED'     : 0x00008000, # IN_IGNORED
    'ONLYDIR'     : 0x01000000, # IN_ONLYDIR
    'DONT_FOLLOW' : 0x02000000, # IN_DONT_FOLLOW
    'MASK_ADD'    : 0x20000000, # IN_MASK_ADD
    'ISDIR'       : 0x40000000, # IN_ISDIR
    'ONESHOT'     : 0x80000000, # IN_ONESHOT
}

def mask_str(mask):
    return ' | '.join(name for name, val in FLAGS.items() if val & mask)

Diff to Previous Revision

--- revision 9 2009-04-19 01:11:58
+++ revision 10 2013-08-12 14:39:57
@@ -24,6 +24,7 @@
         size_int = c_int()
         while ioctl(self.fd, FIONREAD, size_int)==-1: sleep(1)
         size = size_int.value
+        if not size: return
         data = read(self.fd, size)
         deb = 0
         while deb < size:

History