2013-07-16 20:36:18 +03:00
|
|
|
#ifdef ENABLE_INOTIFY
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <SDL.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/inotify.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "monitor.h"
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
void Monitor::inject_event(bool is_add, const char *path)
|
|
|
|
{
|
|
|
|
SDL_UserEvent e = {
|
|
|
|
.type = SDL_USEREVENT,
|
|
|
|
.code = (int) is_add,
|
|
|
|
.data1 = strdup(path),
|
|
|
|
.data2 = NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Inject an user event, that will be handled as a "repaint"
|
|
|
|
* event by the InputManager */
|
|
|
|
SDL_PushEvent((SDL_Event *) &e);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Monitor::event_accepted(struct inotify_event &event)
|
|
|
|
{
|
|
|
|
/* Don't bother other files than OPKs */
|
|
|
|
size_t len = strlen(event.name);
|
|
|
|
return len >= 5 && !strncmp(event.name + len - 4, ".opk", 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Monitor::run(void)
|
2013-07-16 20:36:18 +03:00
|
|
|
{
|
|
|
|
int wd, fd;
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
DEBUG("Starting inotify thread for path %s...\n", path.c_str());
|
2013-07-16 20:36:18 +03:00
|
|
|
|
|
|
|
fd = inotify_init();
|
2013-07-19 04:32:23 +03:00
|
|
|
if (fd < 0) {
|
2013-07-16 20:36:18 +03:00
|
|
|
ERROR("Unable to start inotify\n");
|
2013-07-19 04:32:23 +03:00
|
|
|
return fd;
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
wd = inotify_add_watch(fd, path.c_str(), mask);
|
|
|
|
if (wd < 0) {
|
2013-07-16 20:36:18 +03:00
|
|
|
ERROR("Unable to add inotify watch\n");
|
|
|
|
close(fd);
|
2013-07-19 04:32:23 +03:00
|
|
|
return wd;
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
DEBUG("Starting watching directory %s\n", path.c_str());
|
2013-07-16 20:36:18 +03:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
size_t len = sizeof(struct inotify_event) + NAME_MAX + 1;
|
|
|
|
struct inotify_event event;
|
|
|
|
char buf[256];
|
|
|
|
|
|
|
|
read(fd, &event, len);
|
2013-07-19 04:34:03 +03:00
|
|
|
|
|
|
|
if (event.mask & (IN_DELETE_SELF | IN_MOVE_SELF)) {
|
|
|
|
inject_event(false, path.c_str());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
sprintf(buf, "%s/%s", path.c_str(), event.name);
|
2013-07-16 20:36:18 +03:00
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
if (!event_accepted(event))
|
2013-07-16 20:36:18 +03:00
|
|
|
continue;
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
inject_event(event.mask & (IN_MOVED_TO | IN_CLOSE_WRITE |
|
|
|
|
IN_CREATE), buf);
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
2013-07-19 04:32:23 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void * inotify_thd(void *p)
|
|
|
|
{
|
|
|
|
Monitor *monitor = (Monitor *) p;
|
|
|
|
monitor->run();
|
|
|
|
return NULL;
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
|
|
|
|
2013-07-19 04:32:23 +03:00
|
|
|
Monitor::Monitor(std::string path, unsigned int flags) : path(path)
|
2013-07-16 20:36:18 +03:00
|
|
|
{
|
2013-07-19 04:32:23 +03:00
|
|
|
mask = flags;
|
|
|
|
pthread_create(&thd, NULL, inotify_thd, (void *) this);
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Monitor::~Monitor(void)
|
|
|
|
{
|
2013-07-19 21:29:51 +03:00
|
|
|
pthread_cancel(thd);
|
|
|
|
pthread_join(thd, NULL);
|
2013-07-19 21:35:45 +03:00
|
|
|
DEBUG("Monitor thread stopped (was watching %s)\n", path.c_str());
|
2013-07-16 20:36:18 +03:00
|
|
|
}
|
|
|
|
#endif
|