cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=7ee68cb4e239ac1814ceea19e5150f1645403ae4

commit 7ee68cb4e239ac1814ceea19e5150f1645403ae4
Author: Al Poole <[email protected]>
Date:   Fri Apr 28 10:16:41 2017 -0700

    eio: improve Kevent (FreeBSD et. al)
    
    Summary: Adds initial support for file/directory creation and deletion 
detection.
    
    Reviewers: raster, cedric
    
    Reviewed By: cedric
    
    Subscribers: raster, jpeg
    
    Differential Revision: https://phab.enlightenment.org/D4811
    
    Signed-off-by: Cedric BAIL <[email protected]>
---
 src/lib/eio/eio_monitor_kevent.c | 125 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 121 insertions(+), 4 deletions(-)

diff --git a/src/lib/eio/eio_monitor_kevent.c b/src/lib/eio/eio_monitor_kevent.c
index deccb34..e4a6e06 100644
--- a/src/lib/eio/eio_monitor_kevent.c
+++ b/src/lib/eio/eio_monitor_kevent.c
@@ -19,7 +19,8 @@
 
 #include "eio_private.h"
 #include "Eio.h"
-
+#include "Eina.h"
+#include "Ecore_File.h"
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/stat.h>
@@ -37,32 +38,143 @@
 struct _Eio_Monitor_Backend
 {
    Eio_Monitor *parent;
-
+   Eina_List *prev_list;
    int fd;
 };
 
+typedef struct _Eio_File_Info Eio_File_Info;
+struct _Eio_File_Info
+{
+   const char *path;
+   Eina_Stat st;
+};
+
 static Ecore_Fd_Handler *_kqueue_fd = NULL;
 static Eina_Hash *_kevent_monitors = NULL;
 
 static void
+_eio_kevent_ls_free(Eina_List *list)
+{
+   Eio_File_Info *file;
+
+   EINA_LIST_FREE(list, file)
+     {
+        eina_stringshare_del(file->path);
+        free(file);
+     }
+}
+
+static void
 _eio_kevent_del(void *data)
 {
    Eio_Monitor_Backend *emb = data;
 
+   _eio_kevent_ls_free(emb->prev_list);
+
    if (emb->fd)
       close(emb->fd);
 
    free(emb);
 }
 
+
+static Eina_List *
+_eio_kevent_ls(const char *directory)
+{
+   Eina_Iterator *it;
+   Eina_File_Direct_Info *info;
+   Eina_List *files = NULL;
+
+   it = eina_file_direct_ls(directory);
+   if (!it) return NULL;
+
+   EINA_ITERATOR_FOREACH(it, info)
+     {
+        Eio_File_Info *file = malloc(sizeof(Eio_File_Info));
+        if (eina_file_statat(eina_iterator_container_get(it), info, &file->st))
+          {
+             free(file);
+             continue;
+          }
+        file->path = eina_stringshare_add(info->path);
+        files = eina_list_append(files, file);
+     }
+
+   return files;
+}
+
+static void
+_eio_kevent_event_find(Eio_Monitor_Backend *backend)
+{
+   Eina_List *l, *l2;
+   Eio_File_Info *file, *file2;
+   Eina_List *next_list = _eio_kevent_ls(backend->parent->path);
+
+   EINA_LIST_FOREACH(backend->prev_list, l, file)
+     {
+        Eina_Bool exists = EINA_FALSE;
+        EINA_LIST_FOREACH(next_list, l2, file2)
+          {
+             if (file->st.ino == file2->st.ino)
+               {
+                  if (file->path == file2->path)
+                    exists = EINA_TRUE;
+
+                  if (file->st.mtime != file2->st.mtime)
+                    {
+                       if (S_ISDIR(file->st.mode))
+                         _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_DIRECTORY_MODIFIED);
+                       else
+                         _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_FILE_MODIFIED);
+                    }
+               }
+          }
+
+        if (!exists)
+          {
+             if (S_ISDIR(file->st.mode))
+               _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_DIRECTORY_DELETED);
+             else
+               _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_FILE_DELETED);
+          }
+     }
+
+   EINA_LIST_FOREACH(next_list, l, file)
+     {
+        Eina_Bool exists = EINA_FALSE;
+        EINA_LIST_FOREACH(backend->prev_list, l2, file2)
+          {
+             if ((file->path == file2->path) &&
+                         (file->st.ino == file2->st.ino))
+               {
+                  exists = EINA_TRUE;
+                  break;
+               }
+          }
+
+        if (!exists)
+          {
+             if (S_ISDIR(file->st.mode))
+               _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_DIRECTORY_CREATED);
+             else
+               _eio_monitor_send(backend->parent, file->path, 
EIO_MONITOR_FILE_CREATED);
+          }
+     }
+
+   _eio_kevent_ls_free(backend->prev_list);
+
+   backend->prev_list = next_list;
+}
+
 static Eina_Bool
 _eio_kevent_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh)
 {
    Eio_Monitor_Backend *backend;
    struct kevent evs[KEVENT_NUM_EVENTS];
    int event_code = 0;
+   const struct timespec timeout = { 0, 0 };
 
-   int res = kevent(ecore_main_fd_handler_fd_get(fdh), 0, 0, evs, 
KEVENT_NUM_EVENTS, 0);
+   int res = kevent(ecore_main_fd_handler_fd_get(fdh), 0, 0, evs, 
KEVENT_NUM_EVENTS, &timeout);
 
    for(int i=0; i<res; ++i)
      {
@@ -74,6 +186,9 @@ _eio_kevent_handler(void *data EINA_UNUSED, Ecore_Fd_Handler 
*fdh)
           }
         if(evs[i].fflags & NOTE_WRITE || evs[i].fflags & NOTE_ATTRIB)
           {
+             /* Handle directory/file creation and deletion */
+             _eio_kevent_event_find(backend);
+             /* Old default behaviour */
              event_code = EIO_MONITOR_FILE_MODIFIED;
              _eio_monitor_send(backend->parent, backend->parent->path, 
event_code);
           }
@@ -129,7 +244,7 @@ void eio_monitor_backend_shutdown(void)
    fd = ecore_main_fd_handler_fd_get(_kqueue_fd);
    ecore_main_fd_handler_del(_kqueue_fd);
    _kqueue_fd = NULL;
-   
+
    if (fd < 0)
      return;
 
@@ -161,6 +276,8 @@ void eio_monitor_backend_add(Eio_Monitor *monitor)
    backend->parent = monitor;
    monitor->backend = backend;
 
+   backend->prev_list = _eio_kevent_ls(backend->parent->path);
+
    eina_hash_direct_add(_kevent_monitors, &backend->fd, backend);
 
    EV_SET(&e, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR,

-- 


Reply via email to