| 143 | } |
| 144 | |
| 145 | int watch() |
| 146 | { |
| 147 | while (!_exit) { |
| 148 | TempAllocator512 ta; |
| 149 | |
| 150 | fd_set set; |
| 151 | struct timeval timeout; |
| 152 | u32 cookie = 0; |
| 153 | u32 cookie_mask = 0; |
| 154 | DynamicString cookie_path(ta); |
| 155 | |
| 156 | FD_ZERO(&set); |
| 157 | FD_SET(_fd, &set); |
| 158 | |
| 159 | timeout.tv_sec = 0; |
| 160 | timeout.tv_usec = 32*1000; |
| 161 | |
| 162 | int select_ret; |
| 163 | // select returns 0 if timeout, 1 if input available, -1 if error. |
| 164 | if ((select_ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout)) == 1) { |
| 165 | #define BUF_LEN sizeof(struct inotify_event) + NAME_MAX + 1 |
| 166 | char buf[BUF_LEN*16]; |
| 167 | #undef BUF_LEN |
| 168 | ssize_t len = read(_fd, buf, sizeof(buf)); |
| 169 | if (len == 0) |
| 170 | return 0; |
| 171 | if (len == -1) |
| 172 | return -1; |
| 173 | |
| 174 | for (char *p = buf; p < buf + len;) { |
| 175 | inotify_event *ev = (inotify_event *)p; |
| 176 | |
| 177 | if (ev->mask & IN_IGNORED) { |
| 178 | // Watch was removed explicitly (inotify_rm_watch(2)) or |
| 179 | // automatically (file was deleted, or filesystem was |
| 180 | // unmounted). |
| 181 | hash_map::remove(_watches, ev->wd); |
| 182 | } |
| 183 | if (ev->mask & IN_CREATE) { |
| 184 | DynamicString path(ta); |
| 185 | full_path(path, ev->wd, ev->name); |
| 186 | |
| 187 | write(FileMonitorEvent::CREATED |
| 188 | , ev->mask & IN_ISDIR |
| 189 | , path.c_str() |
| 190 | , NULL |
| 191 | ); |
| 192 | |
| 193 | // From INOTIFY(7), Limitations and caveats: |
| 194 | // If monitoring an entire directory subtree, and a new subdirectory |
| 195 | // is created in that tree or an existing directory is renamed into |
| 196 | // that tree, be aware that by the time you create a watch for the |
| 197 | // new subdirectory, new files (and subdirectories) may already exist |
| 198 | // inside the subdirectory. Therefore, you may want to scan the |
| 199 | // contents of the subdirectory immediately after adding the watch |
| 200 | // (and, if desired, recursively add watches for any subdirectories |
| 201 | // that it contains). |
| 202 | if (ev->mask & IN_ISDIR) |
no test coverage detected