From c8b280835b76687fd8b0c60c759b7d17f5f04889 Mon Sep 17 00:00:00 2001 From: Gora Khargosh Date: Sat, 11 Dec 2010 18:27:30 +0530 Subject: [PATCH] Adds wrapper class and struct for inotify_event Signed-off-by: Gora Khargosh --- watchdog/observers/inotify.py | 134 +++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/watchdog/observers/inotify.py b/watchdog/observers/inotify.py index 30026bb09..96ec4c2f0 100644 --- a/watchdog/observers/inotify.py +++ b/watchdog/observers/inotify.py @@ -86,7 +86,9 @@ c_int, \ c_char_p, \ c_uint32, \ - get_errno + get_errno, \ + sizeof, \ + Structure from watchdog.utils import absolute_path from watchdog.observers.api import \ EventEmitter, \ @@ -124,6 +126,124 @@ ("inotify_rm_watch", libc)) + class InotifyEvent(object): + """ + Inotify event struct wrapper. + + :param wd: + Watch descriptor + :param mask: + Event mask + :param cookie: + Event cookie + :param name: + Event name. + """ + def __init__(self, wd, mask, cookie, name): + self._wd = wd + self._mask = mask + self._cookie = cookie + self._name = name + + @property + def wd(self): + return self._wd + + @property + def mask(self): + return self._mask + + @property + def cookie(self): + return self._cookie + + @property + def name(self): + return self._name + + # Test event types. + @property + def is_modify(self): + return self._mask & Inotify.IN_MODIFY + + @property + def is_close_write(self): + return self._mask & Inotify.IN_CLOSE_WRITE + + @property + def is_close_nowrite(self): + return self._mask & Inotify.IN_CLOSE_NOWRITE + + @property + def is_access(self): + return self._mask & Inotify.IN_ACCESS + + @property + def is_delete(self): + return self._mask & Inotify.IN_DELETE + + @property + def is_create(self): + return self._mask & Inotify.IN_CREATE + + @property + def is_moved_from(self): + return self._mask & Inotify.IN_MOVED_FROM + + @property + def is_moved_to(self): + return self._mask & Inotify.IN_MOVED_TO + + @property + def is_move(self): + return self._mask & Inotify.IN_MOVE + + @property + def is_attrib(self): + return self._mask & Inotify.IN_ATTRIB + + @property + def is_directory(self): + return self._mask & Inotify.IN_ISDIR + + # Additional functionality. + @property + def key(self): + return (self._wd, self._mask, self._cookie, self._name) + + def __eq__(self, inotify_event): + return self.key == inotify_event.key + + def __ne__(self, inotify_event): + return self.key == inotify_event.key + + def __hash__(self): + return hash(self.key) + + + class inotify_event_struct(Structure): + """ + Structure representation of the inotify_event structure. + Used in buffer size calculations:: + + struct inotify_event { + __s32 wd; /* watch descriptor */ + __u32 mask; /* watch mask */ + __u32 cookie; /* cookie to synchronize two events */ + __u32 len; /* length (including nulls) of name */ + char name[0]; /* stub for possible name */ + }; + """ + _fields_ = [('wd', c_int), + ('mask', c_uint32), + ('cookie', c_uint32), + ('len', c_uint32), + ('name', c_char_p)] + + EVENT_SIZE = sizeof(inotify_event_struct) + DEFAULT_EVENT_BUFFER_SIZE = 1024 * (EVENT_SIZE + 16) + + class Inotify(object): """ Linux inotify(7) API wrapper class. @@ -292,6 +412,14 @@ def close(self): self._remove_all_watches() os.close(self._inotify_fd) + def read_events(self, event_buffer_size=DEFAULT_EVENT_BUFFER_SIZE): + """ + Reads events from inotify and yields them. + """ + event_buffer = os.read(self._inotify_fd, event_buffer_size) + for wd, mask, cookie, name in Inotify._parse_event_buffer(event_buffer): + yield InotifyEvent(wd, mask, cookie, name) + # Non-synchronized methods. def _add_dir_watch(self, path, recursive, mask): """ @@ -360,7 +488,7 @@ def _raise_error(): raise OSError(strerror(_errnum)) @staticmethod - def parse_event_buffer(buffer): + def _parse_event_buffer(buffer): """ Parses an event buffer of ``inotify_event`` structs returned by inotify:: @@ -409,7 +537,7 @@ def on_thread_exit(self): self._inotify.close() def queue_events(self, timeout): - pass + inotify_events = self._inotify.read_events(event_buffer_size) class InotifyObserver(BaseObserver):