r14926: change the inotify backend to implement the rather unusual semantics
authorAndrew Tridgell <tridge@samba.org>
Wed, 5 Apr 2006 08:52:55 +0000 (08:52 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:00:17 +0000 (14:00 -0500)
for rename. The cookies in inotify tell us (indirectly!) if its a
rename between directories or not
(This used to be commit 13574a8d0c7228bf36a6debe4853f693c9f8f543)

source4/ntvfs/sysdep/inotify.c

index c95c39ff01a3e9e688b3c46ab8c90a2753ef2709..70ef4918cb7e255cb938182d6179c7eec8fa2df2 100644 (file)
@@ -90,8 +90,13 @@ static int inotify_destructor(void *ptr)
 
 /*
   dispatch one inotify event
+  
+  the cookies are used to correctly handle renames
 */
-static void inotify_dispatch(struct inotify_private *in, struct inotify_event *e)
+static void inotify_dispatch(struct inotify_private *in, 
+                            struct inotify_event *e, 
+                            uint32_t prev_cookie,
+                            uint32_t next_cookie)
 {
        struct watch_context *w;
        struct notify_event ne;
@@ -101,11 +106,24 @@ static void inotify_dispatch(struct inotify_private *in, struct inotify_event *e
                return;
        }
 
-       /* map the inotify mask to a action */
+       /* map the inotify mask to a action. This gets complicated for
+          renames */
        if (e->mask & IN_CREATE) {
                ne.action = NOTIFY_ACTION_ADDED;
        } else if (e->mask & IN_DELETE) {
                ne.action = NOTIFY_ACTION_REMOVED;
+       } else if (e->mask & IN_MOVED_FROM) {
+               if (e->cookie == next_cookie) {
+                       ne.action = NOTIFY_ACTION_OLD_NAME;
+               } else {
+                       ne.action = NOTIFY_ACTION_REMOVED;
+               }
+       } else if (e->mask & IN_MOVED_TO) {
+               if (e->cookie == prev_cookie) {
+                       ne.action = NOTIFY_ACTION_NEW_NAME;
+               } else {
+                       ne.action = NOTIFY_ACTION_ADDED;
+               }
        } else {
                ne.action = NOTIFY_ACTION_MODIFIED;
        }
@@ -129,6 +147,7 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde,
        struct inotify_private *in = talloc_get_type(private, struct inotify_private);
        int bufsize = 0;
        struct inotify_event *e0, *e;
+       uint32_t prev_cookie=0;
 
        /*
          we must use FIONREAD as we cannot predict the length of the
@@ -152,9 +171,14 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde,
 
        /* we can get more than one event in the buffer */
        while (bufsize >= sizeof(*e)) {
-               inotify_dispatch(in, e);
+               struct inotify_event *e2 = NULL;
                bufsize -= e->len + sizeof(*e);
-               e = (struct inotify_event *)(e->len + sizeof(*e) + (char *)e);
+               if (bufsize >= sizeof(*e)) {
+                       e2 = (struct inotify_event *)(e->len + sizeof(*e) + (char *)e);
+               }
+               inotify_dispatch(in, e, prev_cookie, e2?e2->cookie:0);
+               prev_cookie = e->cookie;
+               e = e2;
        }
 
        talloc_free(e0);