95 is_created =
event & ( NOTE_LINK );
96 is_deleted =
event & ( NOTE_DELETE );
97 debug ( 4,
"type == %x; is_created == %x; is_deleted == %x", type, is_created, is_deleted );
116 static struct kevent ev = {0};
117 debug ( 10,
"Calling kqueue_sync() on \"%s\" (obj_p: %p; dir_fd: %i; fd: %i)", obj_p->
name, obj_p, obj_p->
dir_fd, obj_p->
fd );
118 ev.ident = obj_p->
fd;
119 ev.fflags = NOTE_DELETE;
121 debug ( 4,
"Unmarking the child \"%s\" (dir_fd: %i; fd: %i)", obj_p->
name, obj_p->
dir_fd, obj_p->
fd );
134 debug ( 20,
"obj_p == %p; obj_p->fd == %i; obj_p->name == \"%s\"", obj_p, obj_p->
fd, obj_p->
name );
138 debug ( 20,
"Removing children" );
146 if ( obj_p->
parent != NULL ) {
148 debug ( 20,
"Removing the obj from parent->children_tree (obj_p == %p; parent == %p; parent->children_tree == %p)", obj_p, parent, parent->
children_tree );
153 debug ( 20,
"free()-s" );
154 free ( obj_p->
name );
159static gint
monobj_filecmp ( gconstpointer _a, gconstpointer _b, gpointer _ctx_p )
166 debug ( 95,
"a == %p; b == %p", a, b );
167 int diff_inode = a->
inode - b->inode;
168 debug ( 90,
"diff_inode = %i", diff_inode );
173 int diff_device = a->
device - b->device;
174 debug ( 50,
"diff_device = %i", diff_device );
179 int diff_dir_fd = a->
dir_fd - b->dir_fd;
180 debug ( 50,
"diff_dir_fd = %i (%i - %i)", diff_dir_fd, a->
dir_fd, b->dir_fd );
185 int diff_name_hash = a->
name_hash - b->name_hash;
186 debug ( 50,
"diff_name_hash = %i", diff_name_hash );
188 if ( diff_name_hash )
189 return diff_name_hash;
191 debug ( 10,
"strcmp(\"%s\", \"%s\") = %i", a->
name, b->name, strcmp ( a->
name, b->name ) );
192 return strcmp ( a->
name, b->name );
195static int monobj_fdcmp ( gconstpointer a, gconstpointer b, gpointer _ctx_p )
203 debug ( 9,
"_ctx_p == %p", _ctx_p );
205 indexes_p =
ctx_p->indexes_p;
225 if ( obj_p == NULL ) {
233 if ( obj_p->
dir_fd == -1 )
236 obj_p->
fd = openat ( obj_p->
dir_fd, obj_p->
name, O_RDONLY | O_NOFOLLOW );
238 debug ( 4,
"obj_p-> (%p): dir_fd == %i; name == \"%s\"; fd == %i; type == %i (isdir == %i)", obj_p, obj_p->
dir_fd, obj_p->
name, obj_p->
fd, obj_p->
type, obj_p->
type == DT_DIR );
240 if ( obj_p->
fd == -1 ) {
241 debug ( 2,
"File/dir \"%s\" disappeared. Skipping", obj_p->
name );
251 switch ( obj_p->
type ) {
256 NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_DELETE,
264 NOTE_WRITE | NOTE_ATTRIB | NOTE_DELETE,
281 int changelist_id_last;
282 debug ( 20,
"obj_p == %p", obj_p );
286 if ( obj_p == NULL ) {
297 debug ( 30,
"Checking: (obj_p->changelist_id [%i] < changelist_id_last [%i]) == %i", obj_p->
changelist_id, changelist_id_last, ( obj_p->
changelist_id < changelist_id_last ) );
303 debug ( 20,
"dat->changelist: moving %i -> %i", changelist_id_last, obj_p->
changelist_id );
308 "dat->obj_p_by_clid[ obj_p->changelist_id ] == %p; "
309 "dat->obj_p_by_clid[ obj_p->changelist_id ]->fd == %i; "
310 "dat->obj_p_by_clid[ obj_p->changelist_id ]->name == \"%s\"",
319 debug ( 20,
"Removing the obj itself" );
320 g_tree_remove ( dat->
fd_btree, obj_p );
327 monobj_t *obj_p, *parent, parent_pattern;
329 debug ( 3,
"(ctx_p, %i, \"%s\", %u, %u)", dir_fd, fname, name_len, type );
331 obj_p = xcalloc (
sizeof ( *obj_p ), 1 );
333 obj_p = xmalloc (
sizeof ( *obj_p ) );
335 obj_p->
inode = inode;
344 parent_pattern.
fd = dir_fd;
345 parent = g_tree_lookup ( dat->
fd_btree, &parent_pattern );
347 if ( parent != NULL ) {
349 debug ( 20,
"Adding a child for dir_fd == %i", dir_fd );
354 debug ( 20,
"parent == %p; obj_p == %p", parent, obj_p );
364 error (
"Got error while kqueue_mark()" );
365 free ( obj_p->
name );
373 debug ( 4,
"I won't open() this object due to it's type == %u.", type );
377 debug ( 8,
"storing: inode == %u; device == %u; dir_fd == %i; fd == %i; parent == %p", obj_p->
inode, obj_p->
device, obj_p->
dir_fd, obj_p->
fd, parent );
378 g_tree_replace ( dat->
file_btree, obj_p, obj_p );
379 g_tree_replace ( dat->
fd_btree, obj_p, obj_p );
391 size_t name_len = strlen ( entry->d_name );
392 name_hash =
adler32_calc ( (
unsigned char * ) entry->d_name, name_len );
395 obj.
inode = entry->d_ino;
400 if ( ( obj_p = g_tree_lookup ( dat->
file_btree, &obj ) ) != NULL )
405 error (
"Got error while kqueue_start_watch()" );
407 obj_p->
inode = entry->d_ino;
420 const char *file_name;
425 if ( path == NULL ) {
431 debug ( 6,
"(ctx_p, indexes_p, \"%s\")", path );
433 char *dir_path, *ptr;
434 ptr = strrchr ( path,
'/' );
438 dir_fd = indexes_fpath2wd ( indexes_p,
"" );
440 dir_path = strdup ( path );
441 dir_path[ptr - path] = 0;
442 dir_fd = indexes_fpath2wd ( indexes_p, dir_path );
444 if ( dir_fd == -1 ) {
447 error (
"Cannot find file descriptor of directory \"%s\"", dir_path );
456 name_len = strlen ( file_name );
457 name_hash =
adler32_calc ( (
unsigned char * ) file_name, name_len );
462 obj.
inode = st.st_ino;
466 obj.
name = (
char * ) file_name;
468 if ( ( obj_p = g_tree_lookup ( dat->
file_btree, &obj ) ) != NULL )
471 debug ( 9,
"not monitored file/dir \"%s\", yet.", file_name );
473 const char *name_start;
474 name_start = strrchr ( path,
'/' );
476 if ( name_start == NULL )
481 if ( ( obj_p =
kqueue_start_watch (
ctx_p, st.st_ino, st.
st_dev, dir_fd, file_name, name_len, ( st.st_mode & S_IFMT ) == S_IFDIR ? DT_DIR : DT_REG ) ) == NULL )
482 error (
"Got error while kqueue_start_watch()" );
484 obj_p->
inode = st.st_ino;
485 obj_p->
device = st.st_dev;
495 struct dirent *entry;
498 if ( accpath == NULL ) {
504 debug ( 5,
"(ctx_p, indexes_p, \"%s\")", accpath );
507 error (
"Got error while kqueue_add_watch_path(ctx_p, \"%s\")", accpath );
511 dir = fdopendir ( dir_obj_p->
fd );
516 while ( ( entry = readdir ( dir ) ) ) {
517 if ( !memcmp ( entry->d_name,
".", 2 ) )
520 if ( !memcmp ( entry->d_name,
"..", 3 ) )
524 error (
"Got error while kqueue_add_watch_direntry(ctx_p, indexes_p, entry {->d_name == \"%s\"}, %u)", entry->d_name, dir_obj_p->
fd );
529 return dir_obj_p->
fd;
536 debug ( 3,
"tv_p->: tv_sec == %li; tv_usec == %li", tv_p->tv_sec, tv_p->tv_usec );
543 ts.tv_sec = tv_p->tv_sec;
544 ts.tv_nsec = tv_p->tv_usec * 1000;
553 static char filepath[PATH_MAX + 2];
555 dirpath = indexes_wd2fpath ( indexes_p, obj_p->
fd );
557 if ( dirpath != NULL )
558 return strdup ( dirpath );
560 if ( obj_p->
dir_fd == -1 ) {
562 error (
"Cannot find fd of parent directory of \"%s\"", obj_p->
name );
566 dirpath = indexes_wd2fpath ( indexes_p, obj_p->
dir_fd );
568 if ( dirpath == NULL ) {
570 error (
"Cannot find directory with fd == %u", obj_p->
dir_fd );
574 dirpath_len = strlen ( dirpath );
575 filepath_len = dirpath_len + obj_p->
name_len + 1;
578 if ( filepath_len + 1 >= PATH_MAX ) {
579 errno = ENAMETOOLONG;
580 error (
"Too long file path: \"%s/%s\"", dirpath, obj_p->
name );
585 memcpy ( filepath, dirpath, dirpath_len );
586 filepath[dirpath_len] =
'/';
587 memcpy ( &filepath[dirpath_len + 1], obj_p->
name, obj_p->
name_len + 1 );
597 if ( path_full == NULL ) {
598 error (
"Cannot get full path for \"%s\" (fd: %u)", obj_p->
name, obj_p->
fd );
603 debug ( 8,
"path_full = \"%s\"", path_full );
608 debug ( 2,
"Cannot or cancelled lstat64(\"%s\", lst). The object had been deleted (%i) or option \"--cancel-syscalls=mon_stat\" (%i) is set.", path_full, ev_p->fflags == NOTE_DELETE,
ctx_p->
flags[
CANCEL_SYSCALLS]&
CSC_MON_STAT );
609 st_mode = ( obj_p->
type == DT_DIR ? S_IFDIR : S_IFREG );
613 st_mode = lst.st_mode;
614 st_size = lst.st_size;
619 char *path_rel = NULL;
620 size_t path_rel_len = 0;
623 int ret =
sync_prequeue_loadmark ( 1,
ctx_p, indexes_p, path_full, NULL, lst_p, r.
u.
v.
objtype_old, r.
u.
v.
objtype_new, ev_p->fflags, ev_p->ident, st_mode, st_size, &path_rel, &path_rel_len, NULL );
625 if ( path_rel != NULL )
637 struct kevent ev = {0};
638 debug ( 9,
"\"%s\"", entry->d_name );
639 obj.
type = entry->d_type;
640 obj.
inode = entry->d_ino;
643 obj.
name = entry->d_name;
644 obj.
name_len = strlen ( entry->d_name );
646 debug ( 20,
"Checking if the object is already monitored (obj_p == %p)", obj_p );
648 if ( ( obj_p = g_tree_lookup ( dat->
file_btree, &obj ) ) != NULL ) {
649 debug ( 20,
"Marking the the object is found" );
650 g_tree_remove ( children_notfound, obj_p );
654 debug ( 20,
"Calling kqueue_start_watch() on the object" );
657 error (
"Got error while kqueue_start_watch()" );
661 debug ( 20,
"Calling kqueue_sync() for the object" );
662 ev.ident = obj_p->
fd;
663 ev.fflags = NOTE_LINK;
666 error (
"Got error while kqueue_sync()" );
676 free ( obj_p->
name );
684 dst = xmalloc (
sizeof ( *src ) );
685 memcpy ( dst, src,
sizeof ( *src ) );
686 dst->name = xmalloc ( src->
name_len + 2 );
704 GTree *children_tree_dup;
705 struct dirent *entry;
707 debug ( 8,
"obj_p == %p; obj_p->dir_fd == %i", obj_p, obj_p->
dir_fd );
708 debug ( 20,
"open*()-ing the directory" );
711 if ( obj_p->
dir_fd == -1 )
714 fd = openat ( obj_p->
dir_fd, obj_p->
name, O_RDONLY | O_PATH );
716 debug ( 20,
"fdopendir()-ing the directory" );
717 dir = fdopendir ( fd );
720 debug ( 20,
"dir == NULL. return 0" );
726 debug ( 8,
"children_count == %i", g_tree_nnodes ( children_tree_dup ) );
727 debug ( 20,
"reading the directory" );
729 while ( ( entry = readdir ( dir ) ) ) {
730 debug ( 10,
"file/dir: \"%s\"", entry->d_name );
732 if ( !memcmp ( entry->d_name,
".", 2 ) )
735 if ( !memcmp ( entry->d_name,
"..", 3 ) )
739 error (
"Got error while _kqueue_handle_oneevent_dircontent_item(ctx_p, obj_p, entry {->d_name == \"%s\"})", entry->d_name );
744 debug ( 20,
"searching for deleted objects from the directory" );
746 g_tree_destroy ( children_tree_dup );
756 if ( ev_p == NULL ) {
761 if ( obj_p == NULL ) {
767 debug ( 9,
"obj_p->: name == \"%s\"; dir_fd == %i; type == 0x%x (isdir == %i); fd = %i. ev_p->fflags == 0x%x", obj_p->
name, obj_p->
dir_fd, obj_p->
type, obj_p->
type == DT_DIR, obj_p->
fd, ev_p->fflags );
770 if ( obj_p->
type == DT_DIR && ( ev_p->fflags & ( NOTE_EXTEND | NOTE_WRITE ) ) )
773 if ( ev_p->fflags & ( NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_DELETE | NOTE_RENAME ) )
776 if ( ev_p->fflags & NOTE_DELETE )
784 static struct timeval tv = {0};
796 g_hash_table_remove_all ( indexes_p->
fpath2ei_ht );
800 struct kevent *ev_p = &dat->
eventlist[i++];
802 obj.
fd = ev_p->ident;
805 if ( obj_p == NULL ) {
806 debug ( 3,
"Cannot find internal structure for fd == %u. Skipping the event.", ev_p->ident );
811 error (
"Got error from kqueue_handle_oneevent()" );
uint32_t adler32_calc(const unsigned char *const data, uint32_t len)
Calculated Adler32 value for char array.
enum eventobjtype eventobjtype_t
#define KQUEUE_EVENTLISTSIZE
#define debug(debug_level,...)
#define critical_on(cond)
GTree * g_tree_dup(GTree *src, GCompareDataFunc key_compare_func, gpointer key_compare_data, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func, GDupFunc key_dup_funct, GDupFunc value_dup_funct)
gpointer monobj_dup(gpointer _obj_p)
int kqueue_mark(ctx_t *ctx_p, monobj_t *obj_p)
static int monobj_fdcmp(gconstpointer a, gconstpointer b, gpointer _ctx_p)
void child_free(monobj_t *node)
void monobj_freedup(gpointer _obj_p)
static uint32_t recognize_event(uint32_t event, int is_dir)
monobj_t * kqueue_add_watch_path(ctx_t *ctx_p, indexes_t *indexes_p, const char *const path)
int _kqueue_handle_oneevent_dircontent(ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *obj_p)
monobj_t * kqueue_add_watch_direntry(ctx_t *ctx_p, indexes_t *indexes_p, struct dirent *entry, monobj_t *dir_obj_p)
int kqueue_sync(ctx_t *ctx_p, indexes_t *indexes_p, struct kevent *ev_p, monobj_t *obj_p)
int kqueue_wait(ctx_t *ctx_p, struct indexes *indexes_p, struct timeval *tv_p)
static int _kqueue_handle_oneevent_dircontent_item(struct kqueue_data *dat, ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *dir_obj_p, struct dirent *entry, void *children_notfound)
void unmarkchild(gpointer _obj_p)
int kqueue_handle(ctx_t *ctx_p, indexes_t *indexes_p)
int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p)
int kqueue_handle_oneevent(ctx_t *ctx_p, indexes_t *indexes_p, struct kevent *ev_p, monobj_t *obj_p)
gboolean unmarkchild_for_foreach(gpointer _obj_p, gpointer _value, gpointer _ctx_p)
int kqueue_deinit(ctx_t *ctx_p)
gboolean unmarkdupchild(gpointer _obj_p, gpointer value, gpointer _ctx_p)
int kqueue_add_watch_dir(ctx_t *ctx_p, indexes_t *indexes_p, const char *const accpath)
char * kqueue_getpath(ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *obj_p)
monobj_t * kqueue_start_watch(ctx_t *ctx_p, ino_t inode, dev_t device, int dir_fd, const char *const fname, size_t name_len, unsigned char type)
static gint monobj_filecmp(gconstpointer _a, gconstpointer _b, gpointer _ctx_p)
void monobj_free(void *monobj_p)
monobj_t ** obj_p_by_clid
size_t changelist_alloced
struct kevent eventlist[256]
struct kevent * changelist
union recognize_event_return::@6 u
eventobjtype_t objtype_old
eventobjtype_t objtype_new
struct recognize_event_return::@6::@7 v
int sync_prequeue_unload(ctx_t *ctx_p, indexes_t *indexes_p)
int sync_prequeue_loadmark(int monitored, ctx_t *ctx_p, indexes_t *indexes_p, const char *path_full, const char *path_rel, stat64_t *lst_p, eventobjtype_t objtype_old, eventobjtype_t objtype_new, uint32_t event_mask, int event_wd, mode_t st_mode, off_t st_size, char **path_buf_p, size_t *path_buf_len_p, eventinfo_t *evinfo)