Root/
| 1 | #ifdef ENABLE_INOTIFY |
| 2 | #include "debug.h" |
| 3 | |
| 4 | #include <climits> |
| 5 | #include <dirent.h> |
| 6 | #include <pthread.h> |
| 7 | #include <SDL.h> |
| 8 | #include <signal.h> |
| 9 | #include <sys/inotify.h> |
| 10 | #include <unistd.h> |
| 11 | |
| 12 | #include "inputmanager.h" |
| 13 | #include "monitor.h" |
| 14 | #include "utilities.h" |
| 15 | |
| 16 | void Monitor::inject_event(bool is_add, const char *path) |
| 17 | { |
| 18 | if (is_add) |
| 19 | inject_user_event(OPEN_PACKAGE, strdup(path)); |
| 20 | else |
| 21 | inject_user_event(REMOVE_LINKS, strdup(path)); |
| 22 | } |
| 23 | |
| 24 | bool Monitor::event_accepted(struct inotify_event &event) |
| 25 | { |
| 26 | /* Don't bother other files than OPKs */ |
| 27 | size_t len = strlen(event.name); |
| 28 | return len >= 5 && !strncmp(event.name + len - 4, ".opk", 4); |
| 29 | } |
| 30 | |
| 31 | int Monitor::run() |
| 32 | { |
| 33 | DEBUG("Starting inotify thread for path %s...\n", path.c_str()); |
| 34 | |
| 35 | int fd = inotify_init1(IN_CLOEXEC); |
| 36 | if (fd < 0) { |
| 37 | ERROR("Unable to start inotify\n"); |
| 38 | return fd; |
| 39 | } |
| 40 | |
| 41 | int wd = inotify_add_watch(fd, path.c_str(), mask); |
| 42 | if (wd < 0) { |
| 43 | ERROR("Unable to add inotify watch on '%s': %s\n", |
| 44 | path.c_str(), strerror(errno)); |
| 45 | close(fd); |
| 46 | return wd; |
| 47 | } |
| 48 | |
| 49 | DEBUG("Starting watching directory %s\n", path.c_str()); |
| 50 | |
| 51 | for (;;) { |
| 52 | size_t len = sizeof(struct inotify_event) + NAME_MAX + 1; |
| 53 | struct inotify_event event; |
| 54 | char buf[256]; |
| 55 | |
| 56 | read(fd, &event, len); |
| 57 | |
| 58 | if (event.mask & (IN_DELETE_SELF | IN_MOVE_SELF)) { |
| 59 | inject_event(false, path.c_str()); |
| 60 | break; |
| 61 | } |
| 62 | |
| 63 | sprintf(buf, "%s/%s", path.c_str(), event.name); |
| 64 | |
| 65 | if (!event_accepted(event)) |
| 66 | continue; |
| 67 | |
| 68 | inject_event(event.mask & (IN_MOVED_TO | IN_CLOSE_WRITE | IN_CREATE), buf); |
| 69 | } |
| 70 | |
| 71 | return 0; |
| 72 | } |
| 73 | |
| 74 | static void * inotify_thd(void *p) |
| 75 | { |
| 76 | Monitor *monitor = (Monitor *) p; |
| 77 | monitor->run(); |
| 78 | return NULL; |
| 79 | } |
| 80 | |
| 81 | Monitor::Monitor(std::string path, unsigned int flags) : path(path) |
| 82 | { |
| 83 | mask = flags; |
| 84 | pthread_create(&thd, NULL, inotify_thd, (void *) this); |
| 85 | } |
| 86 | |
| 87 | Monitor::~Monitor() |
| 88 | { |
| 89 | pthread_cancel(thd); |
| 90 | pthread_join(thd, NULL); |
| 91 | DEBUG("Monitor thread stopped (was watching %s)\n", path.c_str()); |
| 92 | } |
| 93 | #endif |
| 94 |
Branches:
install_locations
master
opkrun
packages
