1 /* Copyright 2012-present Facebook, Inc.
2 * Licensed under the Apache License, Version 2.0 */
3
4 #ifndef WATCHMAN_H
5 #define WATCHMAN_H
6
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10
11 #define _GNU_SOURCE 1
12 #include "config.h"
13
14 #include <assert.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #include <ctype.h>
19 #include <stdint.h>
20 #include <sys/stat.h>
21 #if HAVE_SYS_INOTIFY_H
22 # include <sys/inotify.h>
23 #endif
24 #if HAVE_SYS_EVENT_H
25 # include <sys/event.h>
26 #endif
27 #if HAVE_PORT_H
28 # include <port.h>
29 #endif
30 #include <signal.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <pthread.h>
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <dirent.h>
38 #include <stdbool.h>
39 #include <sys/time.h>
40 #include <time.h>
41 #ifndef _WIN32
42 #include <libgen.h>
43 #endif
44 #include <inttypes.h>
45 #include <limits.h>
46 #ifndef _WIN32
47 #include <sys/socket.h>
48 #include <sys/un.h>
49 #endif
50 #include <fcntl.h>
51 #if defined(__linux__) && !defined(O_CLOEXEC)
52 # define O_CLOEXEC 02000000 /* set close_on_exec, from asm/fcntl.h */
53 #endif
54 #ifndef O_CLOEXEC
55 # define O_CLOEXEC 0
56 #endif
57 #ifndef _WIN32
58 #include <sys/poll.h>
59 #include <sys/wait.h>
60 #endif
61 #ifdef HAVE_PCRE_H
62 # include <pcre.h>
63 #endif
64 #ifdef HAVE_EXECINFO_H
65 # include <execinfo.h>
66 #endif
67 #ifndef _WIN32
68 #include <sys/uio.h>
69 #include <pwd.h>
70 #include <sysexits.h>
71 #endif
72 #include <spawn.h>
73 #include <stddef.h>
74 #ifdef HAVE_SYS_PARAM_H
75 # include <sys/param.h>
76 #endif
77 #ifdef HAVE_SYS_RESOURCE_H
78 # include <sys/resource.h>
79 #endif
80 #ifndef _WIN32
81 // Not explicitly exported on Darwin, so we get to define it.
82 extern char **environ;
83 #endif
84
85 #ifdef _WIN32
86 # define PRIsize_t "Iu"
87 #else
88 # define PRIsize_t "zu"
89 #endif
90
91 #ifndef WATCHMAN_DIR_SEP
92 # define WATCHMAN_DIR_SEP '/'
93 # define WATCHMAN_DIR_DOT '.'
94 #endif
95
96 #ifdef _WIN32
97 # define PRIsize_t "Iu"
98 #else
99 # define PRIsize_t "zu"
100 #endif
101
102 extern char *poisoned_reason;
103
104 #include "watchman_hash.h"
105 #include "watchman_stream.h"
106
107 #include "jansson.h"
108
109 #ifdef HAVE_CORESERVICES_CORESERVICES_H
110 # include <CoreServices/CoreServices.h>
111 # if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
112 # define HAVE_FSEVENTS 0
113 # else
114 # define HAVE_FSEVENTS 1
115 # endif
116 #endif
117
118 // Helpers for pasting __LINE__ for symbol generation
119 #define w_paste2(pre, post) pre ## post
120 #define w_paste1(pre, post) w_paste2(pre, post)
121 #define w_gen_symbol(pre) w_paste1(pre, __LINE__)
122
123 // We make use of constructors to glue together modules
124 // without maintaining static lists of things in the build
125 // configuration. These are helpers to make this work
126 // more portably
127 #ifdef _WIN32
128 #pragma section(".CRT$XCU", read)
129 # define w_ctor_fn_type(sym) void __cdecl sym(void)
130 # define w_ctor_fn_reg(sym) \
131 static __declspec(allocate(".CRT$XCU")) \
132 void (__cdecl * w_paste1(sym, _reg))(void) = sym;
133 #else
134 # define w_ctor_fn_type(sym) \
135 __attribute__((constructor)) void sym(void)
136 # define w_ctor_fn_reg(sym) /* not needed */
137 #endif
138
139 /* sane, reasonably large filename size that we'll use
140 * throughout; POSIX seems to define smallish buffers
141 * that seem risky */
142 #define WATCHMAN_NAME_MAX 4096
143
144 // rpmbuild may enable fortify which turns on
145 // warn_unused_result on a number of system functions.
146 // This gives us a reasonably clean way to suppress
147 // these warnings when we're using stack protection.
148 #if __USE_FORTIFY_LEVEL > 0
149 # define ignore_result(x) \
150 do { __typeof__(x) _res = x; (void)_res; } while(0)
151 #elif _MSC_VER >= 1400
152 # define ignore_result(x) \
153 do { int _res = (int)x; (void)_res; } while(0)
154 #else
155 # define ignore_result(x) x
156 #endif
157
158 // self-documenting hint to the compiler that we didn't use it
159 #define unused_parameter(x) (void)x
160
w_refcnt_add(volatile long * refcnt)161 static inline void w_refcnt_add(volatile long *refcnt)
162 {
163 (void)__sync_fetch_and_add(refcnt, 1);
164 }
165
166 /* returns true if we deleted the last ref */
w_refcnt_del(volatile long * refcnt)167 static inline bool w_refcnt_del(volatile long *refcnt)
168 {
169 return __sync_add_and_fetch(refcnt, -1) == 0;
170 }
171
w_set_cloexec(int fd)172 static inline void w_set_cloexec(int fd)
173 {
174 #ifndef _WIN32
175 ignore_result(fcntl(fd, F_SETFD, FD_CLOEXEC));
176 #else
177 unused_parameter(fd);
178 #endif
179 }
180
w_set_nonblock(int fd)181 static inline void w_set_nonblock(int fd)
182 {
183 #ifndef _WIN32
184 ignore_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK));
185 #else
186 unused_parameter(fd);
187 #endif
188 }
189
w_clear_nonblock(int fd)190 static inline void w_clear_nonblock(int fd)
191 {
192 #ifndef _WIN32
193 ignore_result(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK));
194 #else
195 unused_parameter(fd);
196 #endif
197 }
198
199 // Make a temporary file name and open it.
200 // Marks the file as CLOEXEC
201 w_stm_t w_mkstemp(char *templ);
202 char *w_realpath(const char *filename);
203 bool w_is_path_absolute(const char *path);
204
205 #ifndef _WIN32
w_path_exists(const char * path)206 static inline bool w_path_exists(const char *path) {
207 return access(path, F_OK) == 0;
208 }
209 #else
210 bool w_path_exists(const char *path);
211 #endif
212
213 struct watchman_string;
214 typedef struct watchman_string w_string_t;
215 struct watchman_string {
216 long refcnt;
217 uint32_t hval;
218 uint32_t len;
219 w_string_t *slice;
220 const char *buf;
221 };
222
223 /* small for testing, but should make this greater than the number of dirs we
224 * have in our repos to avoid realloc */
225 #define HINT_NUM_DIRS 128*1024
226
227 /* We leverage the fact that our aligned pointers will never set the LSB of a
228 * pointer value. We can use the LSB to indicate whether kqueue entries are
229 * dirs or files */
230 #define SET_DIR_BIT(dir) ((void*)(((intptr_t)dir) | 0x1))
231 #define IS_DIR_BIT_SET(dir) ((((intptr_t)dir) & 0x1) == 0x1)
232 #define DECODE_DIR(dir) ((void*)(((intptr_t)dir) & ~0x1))
233
234 struct watchman_file;
235 struct watchman_dir;
236 struct watchman_root;
237 struct watchman_pending_fs;
238 struct watchman_trigger_command;
239 typedef struct watchman_root w_root_t;
240
241 // Process global state for the selected watcher
242 typedef void *watchman_global_watcher_t;
243 // Per-watch state for the selected watcher
244 typedef void *watchman_watcher_t;
245
246 struct watchman_clock {
247 uint32_t ticks;
248 struct timeval tv;
249 };
250 typedef struct watchman_clock w_clock_t;
251
252 #define W_PENDING_RECURSIVE 1
253 #define W_PENDING_VIA_NOTIFY 2
254 #define W_PENDING_CRAWL_ONLY 4
255 struct watchman_pending_fs {
256 struct watchman_pending_fs *next;
257 w_string_t *path;
258 struct timeval now;
259 int flags;
260 };
261
262 struct watchman_pending_collection {
263 struct watchman_pending_fs *pending;
264 w_ht_t *pending_uniq;
265 pthread_mutex_t lock;
266 pthread_cond_t cond;
267 bool pinged;
268 };
269
270 bool w_pending_coll_init(struct watchman_pending_collection *coll);
271 void w_pending_coll_destroy(struct watchman_pending_collection *coll);
272 void w_pending_coll_drain(struct watchman_pending_collection *coll);
273 void w_pending_coll_lock(struct watchman_pending_collection *coll);
274 void w_pending_coll_unlock(struct watchman_pending_collection *coll);
275 bool w_pending_coll_add(struct watchman_pending_collection *coll,
276 w_string_t *path, struct timeval now, int flags);
277 bool w_pending_coll_add_rel(struct watchman_pending_collection *coll,
278 struct watchman_dir *dir, const char *name,
279 struct timeval now, int flags);
280 void w_pending_coll_append(struct watchman_pending_collection *target,
281 struct watchman_pending_collection *src);
282 struct watchman_pending_fs *w_pending_coll_pop(
283 struct watchman_pending_collection *coll);
284 bool w_pending_coll_lock_and_wait(struct watchman_pending_collection *coll,
285 int timeoutms);
286 void w_pending_coll_ping(struct watchman_pending_collection *coll);
287 uint32_t w_pending_coll_size(struct watchman_pending_collection *coll);
288 void w_pending_fs_free(struct watchman_pending_fs *p);
289
290 struct watchman_dir {
291 /* full path */
292 w_string_t *path;
293 /* files contained in this dir (keyed by file->name) */
294 w_ht_t *files;
295 /* child dirs contained in this dir (keyed by dir->path) */
296 w_ht_t *dirs;
297 };
298
299 struct watchman_ops {
300 // What's it called??
301 const char *name;
302
303 // if this watcher notifies for individual files contained within
304 // a watched dir, false if it only notifies for dirs
305 #define WATCHER_HAS_PER_FILE_NOTIFICATIONS 1
306 // if renames do not reliably report the individual
307 // files renamed in the hierarchy
308 #define WATCHER_COALESCED_RENAME 2
309 unsigned flags;
310
311 // Perform any global initialization needed for the watcher mechanism
312 // and return a context pointer that will be passed to all other ops
313 watchman_global_watcher_t (*global_init)(void);
314
315 // Perform global shutdown of the watcher at process shutdown time.
316 // We're not guaranteed that this will be called, depending on how
317 // the process is shutdown
318 void (*global_dtor)(watchman_global_watcher_t watcher);
319
320 // Perform watcher-specific initialization for a watched root.
321 // Do not start threads here
322 bool (*root_init)(watchman_global_watcher_t watcher, w_root_t *root,
323 char **errmsg);
324
325 // Start up threads or similar. Called in the context of the
326 // notify thread
327 bool (*root_start)(watchman_global_watcher_t watcher, w_root_t *root);
328
329 // Perform watcher-specific cleanup for a watched root when it is freed
330 void (*root_dtor)(watchman_global_watcher_t watcher, w_root_t *root);
331
332 // Initiate an OS-level watch on the provided file
333 bool (*root_start_watch_file)(watchman_global_watcher_t watcher,
334 w_root_t *root, struct watchman_file *file);
335
336 // Cancel an OS-level watch on the provided file
337 void (*root_stop_watch_file)(watchman_global_watcher_t watcher,
338 w_root_t *root, struct watchman_file *file);
339
340 // Initiate an OS-level watch on the provided dir, return a DIR
341 // handle, or NULL on error
342 struct watchman_dir_handle *(*root_start_watch_dir)(
343 watchman_global_watcher_t watcher,
344 w_root_t *root, struct watchman_dir *dir, struct timeval now,
345 const char *path);
346
347 // Cancel an OS-level watch on the provided dir
348 void (*root_stop_watch_dir)(watchman_global_watcher_t watcher,
349 w_root_t *root, struct watchman_dir *dir);
350
351 // Signal any threads to terminate. Do not join them here.
352 void (*root_signal_threads)(watchman_global_watcher_t watcher,
353 w_root_t *root);
354
355 // Consume any available notifications. If there are none pending,
356 // does not block.
357 bool (*root_consume_notify)(watchman_global_watcher_t watcher,
358 w_root_t *root, struct watchman_pending_collection *coll);
359
360 // Wait for an inotify event to become available
361 bool (*root_wait_notify)(watchman_global_watcher_t watcher,
362 w_root_t *root, int timeoutms);
363
364 // Called when freeing a file node
365 void (*file_free)(watchman_global_watcher_t watcher,
366 struct watchman_file *file);
367 };
368
369 struct watchman_stat {
370 struct timespec atime, mtime, ctime;
371 off_t size;
372 mode_t mode;
373 uid_t uid;
374 gid_t gid;
375 ino_t ino;
376 dev_t dev;
377 nlink_t nlink;
378 };
379
380 /* opaque (system dependent) type for walking dir contents */
381 struct watchman_dir_handle;
382
383 struct watchman_dir_ent {
384 bool has_stat;
385 char *d_name;
386 struct watchman_stat stat;
387 };
388
389 struct watchman_dir_handle *w_dir_open(const char *path);
390 struct watchman_dir_ent *w_dir_read(struct watchman_dir_handle *dir);
391 void w_dir_close(struct watchman_dir_handle *dir);
392 int w_dir_fd(struct watchman_dir_handle *dir);
393
394 struct watchman_file {
395 /* our name within the parent dir */
396 w_string_t *name;
397 /* the parent dir */
398 struct watchman_dir *parent;
399
400 /* linkage to files ordered by changed time */
401 struct watchman_file *prev, *next;
402
403 /* linkage to files ordered by common suffix */
404 struct watchman_file *suffix_prev, *suffix_next;
405
406 /* the time we last observed a change to this file */
407 w_clock_t otime;
408 /* the time we first observed this file OR the time
409 * that this file switched from !exists to exists.
410 * This is thus the "created time" */
411 w_clock_t ctime;
412
413 /* whether we believe that this file still exists */
414 bool exists;
415 /* whether we think this file might not exist */
416 bool maybe_deleted;
417
418 /* cache stat results so we can tell if an entry
419 * changed */
420 struct watchman_stat stat;
421 };
422
423 #define WATCHMAN_COOKIE_PREFIX ".watchman-cookie-"
424 struct watchman_query_cookie {
425 pthread_cond_t cond;
426 bool seen;
427 };
428
429 #define WATCHMAN_IO_BUF_SIZE 1048576
430 #define WATCHMAN_BATCH_LIMIT (16*1024)
431 #define DEFAULT_SETTLE_PERIOD 20
432 #define DEFAULT_QUERY_SYNC_MS 60000
433
434 /* Prune out nodes that were deleted roughly 12-36 hours ago */
435 #define DEFAULT_GC_AGE (86400/2)
436 #define DEFAULT_GC_INTERVAL 86400
437
438 /* Idle out watches that haven't had activity in several days */
439 #define DEFAULT_REAP_AGE (86400*5)
440
441 struct watchman_root {
442 long refcnt;
443
444 /* path to root */
445 w_string_t *root_path;
446 bool case_sensitive;
447
448 /* our locking granularity is per-root */
449 pthread_mutex_t lock;
450 pthread_t notify_thread;
451 pthread_t io_thread;
452
453 /* map of rule id => struct watchman_trigger_command */
454 w_ht_t *commands;
455
456 /* path to the query cookie dir */
457 w_string_t *query_cookie_dir;
458 w_string_t *query_cookie_prefix;
459 w_ht_t *query_cookies;
460
461 /* map of dir name => dirname
462 * if the map has an entry for a given dir, we're ignoring it */
463 w_ht_t *ignore_vcs;
464 w_ht_t *ignore_dirs;
465
466 int trigger_settle;
467 int gc_interval;
468 int gc_age;
469 int idle_reap_age;
470
471 /* config options loaded via json file */
472 json_t *config_file;
473
474 /* how many times we've had to recrawl */
475 int recrawl_count;
476 w_string_t *last_recrawl_reason;
477
478 // Why we failed to watch
479 w_string_t *failure_reason;
480
481 // Last ad-hoc warning message
482 w_string_t *warning;
483
484 /* queue of items that we need to stat/process */
485 struct watchman_pending_collection pending;
486
487 // map of state name => watchman_client_state_assertion for
488 // asserted states
489 w_ht_t *asserted_states;
490
491 /* --- everything below this point will be reset on w_root_init --- */
492 bool _init_sentinel_;
493
494 /* root number */
495 uint32_t number;
496
497 // Watcher specific state
498 watchman_watcher_t watch;
499
500 /* map of dir name to a dir */
501 w_ht_t *dirname_to_dir;
502
503 /* the most recently changed file */
504 struct watchman_file *latest_file;
505
506 /* current tick */
507 uint32_t ticks;
508
509 bool done_initial;
510 /* if true, we've decided that we should re-crawl the root
511 * for the sake of ensuring consistency */
512 bool should_recrawl;
513 bool cancelled;
514
515 /* map of cursor name => last observed tick value */
516 w_ht_t *cursors;
517
518 /* map of filename suffix => watchman_file at the head
519 * of the suffix index. Linkage via suffix_next */
520 w_ht_t *suffixes;
521
522 uint32_t next_cmd_id;
523 uint32_t last_trigger_tick;
524 uint32_t pending_trigger_tick;
525 uint32_t pending_sub_tick;
526 uint32_t last_age_out_tick;
527 uint32_t last_recheck_tick;
528 time_t last_age_out_timestamp;
529 time_t last_cmd_timestamp;
530 time_t last_reap_timestamp;
531 };
532
533 enum w_pdu_type {
534 need_data,
535 is_json_compact,
536 is_json_pretty,
537 is_bser
538 };
539
540 struct watchman_json_buffer {
541 char *buf;
542 uint32_t allocd;
543 uint32_t rpos, wpos;
544 enum w_pdu_type pdu_type;
545 };
546 typedef struct watchman_json_buffer w_jbuffer_t;
547 bool w_json_buffer_init(w_jbuffer_t *jr);
548 void w_json_buffer_reset(w_jbuffer_t *jr);
549 void w_json_buffer_free(w_jbuffer_t *jr);
550 json_t *w_json_buffer_next(w_jbuffer_t *jr, w_stm_t stm, json_error_t *jerr);
551 bool w_json_buffer_passthru(w_jbuffer_t *jr,
552 enum w_pdu_type output_pdu,
553 w_jbuffer_t *output_pdu_buf,
554 w_stm_t stm);
555 bool w_json_buffer_write(w_jbuffer_t *jr, w_stm_t stm, json_t *json, int flags);
556 bool w_json_buffer_write_bser(w_jbuffer_t *jr, w_stm_t stm, json_t *json);
557 bool w_ser_write_pdu(enum w_pdu_type pdu_type,
558 w_jbuffer_t *jr, w_stm_t stm, json_t *json);
559
560 #define BSER_MAGIC "\x00\x01"
561 int w_bser_write_pdu(json_t *json, json_dump_callback_t dump, void *data);
562 int w_bser_dump(json_t *json, json_dump_callback_t dump, void *data);
563 bool bunser_int(const char *buf, json_int_t avail,
564 json_int_t *needed, json_int_t *val);
565 json_t *bunser(const char *buf, const char *end,
566 json_int_t *needed, json_error_t *jerr);
567
568 struct watchman_client_response {
569 struct watchman_client_response *next;
570 json_t *json;
571 };
572
573 struct watchman_client_subscription;
574
575 struct watchman_client_state_assertion {
576 w_root_t *root; // Holds a ref on the root
577 w_string_t *name;
578 long id;
579 };
580
581 struct watchman_client {
582 w_stm_t stm;
583 w_evt_t ping;
584 int log_level;
585 w_jbuffer_t reader, writer;
586 bool client_mode;
587 enum w_pdu_type pdu_type;
588
589 struct watchman_client_response *head, *tail;
590 /* map of subscription name => struct watchman_client_subscription */
591 w_ht_t *subscriptions;
592
593 /* map of unique id => watchman_client_state_assertion */
594 w_ht_t *states;
595 long next_state_id;
596 };
597 extern pthread_mutex_t w_client_lock;
598 extern w_ht_t *clients;
599
600 void w_client_vacate_states(struct watchman_client *client);
601
602 void w_mark_dead(pid_t pid);
603 bool w_reap_children(bool block);
604
605 #define W_LOG_OFF 0
606 #define W_LOG_ERR 1
607 #define W_LOG_DBG 2
608 #define W_LOG_FATAL -1
609
610 #ifndef WATCHMAN_FMT_STRING
611 # define WATCHMAN_FMT_STRING(x) x
612 #endif
613
614 extern int log_level;
615 extern char *log_name;
616 const char *w_set_thread_name(const char *fmt, ...);
617 const char *w_get_thread_name(void);
618 void w_setup_signal_handlers(void);
619 void w_log(int level, WATCHMAN_FMT_STRING(const char *fmt), ...)
620 #ifdef __GNUC__
621 __attribute__((format(printf, 2, 3)))
622 #endif
623 ;
624 void w_request_shutdown(void);
625
626 bool w_should_log_to_clients(int level);
627 void w_log_to_clients(int level, const char *buf);
628
629 bool w_is_ignored(w_root_t *root, const char *path, uint32_t pathlen);
630 void w_timeoutms_to_abs_timespec(int timeoutms, struct timespec *deadline);
631
632 json_t *w_string_to_json(w_string_t *str);
633 w_string_t *w_string_new(const char *str);
634 #ifdef _WIN32
635 w_string_t *w_string_new_wchar(WCHAR *str, int len);
636 #endif
637 w_string_t *w_string_make_printf(const char *format, ...);
638 w_string_t *w_string_new_lower(const char *str);
639 w_string_t *w_string_dup_lower(w_string_t *str);
640 w_string_t *w_string_suffix(w_string_t *str);
641 bool w_string_suffix_match(w_string_t *str, w_string_t *suffix);
642 w_string_t *w_string_slice(w_string_t *str, uint32_t start, uint32_t len);
643 char *w_string_dup_buf(const w_string_t *str);
644 void w_string_addref(w_string_t *str);
645 void w_string_delref(w_string_t *str);
646 int w_string_compare(const w_string_t *a, const w_string_t *b);
647 bool w_string_equal(const w_string_t *a, const w_string_t *b);
648 bool w_string_equal_cstring(const w_string_t *a, const char *b);
649 bool w_string_equal_caseless(const w_string_t *a, const w_string_t *b);
650 w_string_t *w_string_dirname(w_string_t *str);
651 w_string_t *w_string_basename(w_string_t *str);
652 w_string_t *w_string_new_basename(const char *path);
653 w_string_t *w_string_canon_path(w_string_t *str);
654 void w_string_in_place_normalize_separators(w_string_t **str, char target_sep);
655 w_string_t *w_string_normalize_separators(w_string_t *str, char target_sep);
656 w_string_t *w_string_path_cat(w_string_t *parent, w_string_t *rhs);
657 w_string_t *w_string_path_cat_cstr(w_string_t *parent, const char *rhs);
658 bool w_string_startswith(w_string_t *str, w_string_t *prefix);
659 bool w_string_startswith_caseless(w_string_t *str, w_string_t *prefix);
660 w_string_t *w_string_shell_escape(const w_string_t *str);
661 w_string_t *w_string_implode(json_t *arr, const char *delim);
662
663 // Returns the name of the filesystem for the specified path
664 w_string_t *w_fstype(const char *path);
665
666 void w_root_crawl_recursive(w_root_t *root, w_string_t *dir_name, time_t now);
667 w_root_t *w_root_resolve(const char *path, bool auto_watch, char **errmsg);
668 w_root_t *w_root_resolve_for_client_mode(const char *filename, char **errmsg);
669 char *w_find_enclosing_root(const char *filename, char **relpath);
670 struct watchman_file *w_root_resolve_file(w_root_t *root,
671 struct watchman_dir *dir, w_string_t *file_name,
672 struct timeval now);
673
674 void w_root_perform_age_out(w_root_t *root, int min_age);
675 void w_root_free_watched_roots(void);
676 void w_root_schedule_recrawl(w_root_t *root, const char *why);
677 bool w_root_cancel(w_root_t *root);
678 bool w_root_stop_watch(w_root_t *root);
679 json_t *w_root_stop_watch_all(void);
680 void w_root_mark_deleted(w_root_t *root, struct watchman_dir *dir,
681 struct timeval now, bool recursive);
682 void w_root_reap(void);
683 void w_root_delref(w_root_t *root);
684 void w_root_addref(w_root_t *root);
685 void w_root_set_warning(w_root_t *root, w_string_t *str);
686
687 struct watchman_dir *w_root_resolve_dir(w_root_t *root,
688 w_string_t *dir_name, bool create);
689 void w_root_process_path(w_root_t *root,
690 struct watchman_pending_collection *coll, w_string_t *full_path,
691 struct timeval now, int flags,
692 struct watchman_dir_ent *pre_stat);
693 bool w_root_process_pending(w_root_t *root,
694 struct watchman_pending_collection *coll,
695 bool pull_from_root);
696
697 void w_root_mark_file_changed(w_root_t *root, struct watchman_file *file,
698 struct timeval now);
699
700 bool w_root_sync_to_now(w_root_t *root, int timeoutms);
701
702 void w_root_lock(w_root_t *root);
703 void w_root_unlock(w_root_t *root);
704
705 /* Bob Jenkins' lookup3.c hash function */
706 uint32_t w_hash_bytes(const void *key, size_t length, uint32_t initval);
707
708 struct watchman_rule_match {
709 uint32_t root_number;
710 w_string_t *relname;
711 bool is_new;
712 struct watchman_file *file;
713 };
714
715 enum w_clockspec_tag {
716 w_cs_timestamp,
717 w_cs_clock,
718 w_cs_named_cursor
719 };
720
721 struct w_clockspec {
722 enum w_clockspec_tag tag;
723 union {
724 struct timeval timestamp;
725 struct {
726 uint64_t start_time;
727 int pid;
728 uint32_t root_number;
729 uint32_t ticks;
730 } clock;
731 struct {
732 w_string_t *cursor;
733 } named_cursor;
734 };
735 };
736
737 struct w_query_since {
738 bool is_timestamp;
739 union {
740 struct timeval timestamp;
741 struct {
742 bool is_fresh_instance;
743 uint32_t ticks;
744 } clock;
745 };
746 };
747
748 void w_run_subscription_rules(
749 struct watchman_client *client,
750 struct watchman_client_subscription *sub,
751 w_root_t *root);
752
753 void w_match_results_free(uint32_t num_matches,
754 struct watchman_rule_match *matches);
755
next_power_2(uint32_t n)756 static inline uint32_t next_power_2(uint32_t n)
757 {
758 n |= (n >> 16);
759 n |= (n >> 8);
760 n |= (n >> 4);
761 n |= (n >> 2);
762 n |= (n >> 1);
763 return n + 1;
764 }
765
766 /* compare two timevals and return -1 if a is < b, 0 if a == b,
767 * or 1 if b > a */
w_timeval_compare(struct timeval a,struct timeval b)768 static inline int w_timeval_compare(struct timeval a, struct timeval b)
769 {
770 if (a.tv_sec < b.tv_sec) {
771 return -1;
772 }
773 if (a.tv_sec > b.tv_sec) {
774 return 1;
775 }
776 if (a.tv_usec < b.tv_usec) {
777 return -1;
778 }
779 if (a.tv_usec > b.tv_usec) {
780 return 1;
781 }
782 return 0;
783 }
784
785 #define WATCHMAN_USEC_IN_SEC 1000000
786 #define WATCHMAN_NSEC_IN_USEC 1000
787 #define WATCHMAN_NSEC_IN_SEC (1000 * 1000 * 1000)
788 #define WATCHMAN_NSEC_IN_MSEC 1000000
789
790 #if defined(__APPLE__) || defined(__FreeBSD__) \
791 || (defined(__NetBSD__) && (__NetBSD_Version__ < 6099000000))
792 /* BSD-style subsecond timespec */
793 #define WATCHMAN_ST_TIMESPEC(type) st_##type##timespec
794 #else
795 /* POSIX standard timespec */
796 #define WATCHMAN_ST_TIMESPEC(type) st_##type##tim
797 #endif
798
w_timeval_add(const struct timeval a,const struct timeval b,struct timeval * result)799 static inline void w_timeval_add(const struct timeval a,
800 const struct timeval b, struct timeval *result)
801 {
802 result->tv_sec = a.tv_sec + b.tv_sec;
803 result->tv_usec = a.tv_usec + b.tv_usec;
804
805 if (result->tv_usec > WATCHMAN_USEC_IN_SEC) {
806 result->tv_sec++;
807 result->tv_usec -= WATCHMAN_USEC_IN_SEC;
808 }
809 }
810
w_timeval_sub(const struct timeval a,const struct timeval b,struct timeval * result)811 static inline void w_timeval_sub(const struct timeval a,
812 const struct timeval b, struct timeval *result)
813 {
814 result->tv_sec = a.tv_sec - b.tv_sec;
815 result->tv_usec = a.tv_usec - b.tv_usec;
816
817 if (result->tv_usec < 0) {
818 result->tv_sec--;
819 result->tv_usec += WATCHMAN_USEC_IN_SEC;
820 }
821 }
822
w_timeval_to_timespec(const struct timeval a,struct timespec * ts)823 static inline void w_timeval_to_timespec(
824 const struct timeval a, struct timespec *ts)
825 {
826 ts->tv_sec = a.tv_sec;
827 ts->tv_nsec = a.tv_usec * WATCHMAN_NSEC_IN_USEC;
828 }
829
w_timeval_diff(struct timeval start,struct timeval end)830 static inline double w_timeval_diff(struct timeval start, struct timeval end)
831 {
832 double s = start.tv_sec + ((double)start.tv_usec)/WATCHMAN_USEC_IN_SEC;
833 double e = end.tv_sec + ((double)end.tv_usec)/WATCHMAN_USEC_IN_SEC;
834
835 return e - s;
836 }
837
838 extern const char *watchman_tmp_dir;
839 extern char *watchman_state_file;
840 extern int dont_save_state;
841 bool w_state_save(void);
842 bool w_state_load(void);
843 bool w_root_save_state(json_t *state);
844 bool w_root_load_state(json_t *state);
845 json_t *w_root_trigger_list_to_json(w_root_t *root);
846 json_t *w_root_watch_list_to_json(void);
847
848 bool w_start_listener(const char *socket_path);
849 void w_check_my_sock(void);
850 char **w_argv_copy_from_json(json_t *arr, int skip);
851
852 w_ht_t *w_envp_make_ht(void);
853 char **w_envp_make_from_ht(w_ht_t *ht, uint32_t *env_size);
854 void w_envp_set_cstring(w_ht_t *envht, const char *key, const char *val);
855 void w_envp_set(w_ht_t *envht, const char *key, w_string_t *val);
856 void w_envp_set_list(w_ht_t *envht, const char *key, json_t *arr);
857 void w_envp_set_bool(w_ht_t *envht, const char *key, bool val);
858 void w_envp_unset(w_ht_t *envht, const char *key);
859
860 struct watchman_getopt {
861 /* name of long option: --optname */
862 const char *optname;
863 /* if non-zero, short option character */
864 int shortopt;
865 /* help text shown in the usage information */
866 const char *helptext;
867 /* whether we accept an argument */
868 enum {
869 OPT_NONE,
870 REQ_STRING,
871 REQ_INT,
872 } argtype;
873 /* if an argument was provided, *val will be set to
874 * point to the option value.
875 * Because we only update the option if one was provided
876 * by the user, you can safely pre-initialize the val
877 * pointer to your choice of default.
878 * */
879 void *val;
880
881 /* if argtype != OPT_NONE, this is the label used to
882 * refer to the argument in the help text. If left
883 * blank, we'll use the string "ARG" as a generic
884 * alternative */
885 const char *arglabel;
886
887 // Whether this option should be passed to the child
888 // when running under the gimli monitor
889 int is_daemon;
890 #define IS_DAEMON 1
891 #define NOT_DAEMON 0
892 };
893
894 #ifndef MIN
895 # define MIN(a, b) (a) < (b) ? (a) : (b)
896 #endif
897 #ifndef MAX
898 # define MAX(a, b) (a) > (b) ? (a) : (b)
899 #endif
900
901 bool w_getopt(struct watchman_getopt *opts, int *argcp, char ***argvp,
902 char ***daemon_argv);
903 void usage(struct watchman_getopt *opts, FILE *where);
904 void print_command_list_for_help(FILE *where);
905
906 struct w_clockspec *w_clockspec_new_clock(uint32_t root_number, uint32_t ticks);
907 struct w_clockspec *w_clockspec_parse(json_t *value);
908 void w_clockspec_eval(w_root_t *root,
909 const struct w_clockspec *spec,
910 struct w_query_since *since);
911 void w_clockspec_free(struct w_clockspec *spec);
912
913 const char *get_sock_name(void);
914
915 // Helps write shorter lines
set_prop(json_t * obj,const char * key,json_t * val)916 static inline void set_prop(json_t *obj, const char *key, json_t *val)
917 {
918 json_object_set_new_nocheck(obj, key, val);
919 }
920
921 void cfg_shutdown(void);
922 void cfg_set_arg(const char *name, json_t *val);
923 void cfg_load_global_config_file(void);
924 json_t *cfg_get_json(w_root_t *root, const char *name);
925 const char *cfg_get_string(w_root_t *root, const char *name,
926 const char *defval);
927 json_int_t cfg_get_int(w_root_t *root, const char *name,
928 json_int_t defval);
929 bool cfg_get_bool(w_root_t *root, const char *name, bool defval);
930 double cfg_get_double(w_root_t *root, const char *name, double defval);
931 const char *cfg_get_trouble_url(void);
932 json_t *cfg_compute_root_files(bool *enforcing);
933
934 #include "watchman_query.h"
935 #include "watchman_cmd.h"
936 struct watchman_client_subscription {
937 w_root_t *root;
938 w_string_t *name;
939 w_query *query;
940 bool vcs_defer;
941 uint32_t last_sub_tick;
942 struct w_query_field_list field_list;
943 // map of statename => bool. If true, policy is drop, else defer
944 w_ht_t *drop_or_defer;
945 };
946
947 struct watchman_trigger_command {
948 w_string_t *triggername;
949 w_query *query;
950 json_t *definition;
951 json_t *command;
952 w_ht_t *envht;
953
954 struct w_query_field_list field_list;
955 int append_files;
956 enum {
957 input_dev_null,
958 input_json,
959 input_name_list
960 } stdin_style;
961 uint32_t max_files_stdin;
962
963 int stdout_flags;
964 int stderr_flags;
965 const char *stdout_name;
966 const char *stderr_name;
967
968 /* While we are running, this holds the pid
969 * of the running process */
970 pid_t current_proc;
971 };
972
973 void w_trigger_command_free(struct watchman_trigger_command *cmd);
974 void w_assess_trigger(w_root_t *root, struct watchman_trigger_command *cmd);
975 struct watchman_trigger_command *w_build_trigger_from_def(
976 w_root_t *root, json_t *trig, char **errmsg);
977
978 void set_poison_state(w_root_t *root, w_string_t *dir,
979 struct timeval now, const char *syscall, int err,
980 const char *reason);
981
982 void watchman_watcher_init(void);
983 void watchman_watcher_dtor(void);
984 void handle_open_errno(w_root_t *root, struct watchman_dir *dir,
985 struct timeval now, const char *syscall, int err,
986 const char *reason);
987 void stop_watching_dir(w_root_t *root, struct watchman_dir *dir);
988 uint32_t u32_strlen(const char *str);
989 int w_lstat(const char *path, struct stat *st, bool case_sensitive);
990
991 extern struct watchman_ops fsevents_watcher;
992 extern struct watchman_ops kqueue_watcher;
993 extern struct watchman_ops inotify_watcher;
994 extern struct watchman_ops portfs_watcher;
995 extern struct watchman_ops win32_watcher;
996
997 void w_ioprio_set_low(void);
998 void w_ioprio_set_normal(void);
999
1000 struct flag_map {
1001 uint32_t value;
1002 const char *label;
1003 };
1004 void w_expand_flags(const struct flag_map *fmap, uint32_t flags,
1005 char *buf, size_t len);
1006
1007 #ifdef __cplusplus
1008 }
1009 #endif
1010
1011 #endif
1012
1013 /* vim:ts=2:sw=2:et:
1014 */
1015