clsync
Loading...
Searching...
No Matches
mon_inotify.c
Go to the documentation of this file.
1/*
2 clsync - file tree sync utility based on inotify/kqueue
3
4 Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "common.h"
21#include "error.h"
22#include "sync.h"
23#include "indexes.h"
24#include "privileged.h"
25#include "mon_inotify.h"
26
28 UEM_DIR = 0x01,
31};
32
36};
37
38static inline void recognize_event ( struct recognize_event_return *r, uint32_t event )
39{
40 eventobjtype_t type;
41 int is_created;
42 int is_deleted;
43 type = ( event & IN_ISDIR ? EOT_DIR : EOT_FILE );
44 is_created = event & ( IN_CREATE | IN_MOVED_TO );
45 is_deleted = event & ( IN_DELETE_SELF | IN_DELETE | IN_MOVED_FROM );
46 debug ( 4, "type == %x; is_created == %x; is_deleted == %x", type, is_created, is_deleted );
47 r->objtype_old = ( is_created ? EOT_DOESNTEXIST : type );
48 r->objtype_new = ( is_deleted ? EOT_DOESNTEXIST : type );
49 return;
50}
51
52int inotify_add_watch_dir ( ctx_t *ctx_p, indexes_t *indexes_p, const char *const accpath )
53{
54 ( void ) indexes_p;
55 int inotify_d = ( int ) ( long ) ctx_p->fsmondata;
56 return privileged_inotify_add_watch ( inotify_d, accpath, INOTIFY_MARKMASK, PC_INOTIFY_ADD_WATCH_DIR );
57}
58
59int inotify_wait ( ctx_t *ctx_p, struct indexes *indexes_p, struct timeval *tv_p )
60{
61 ( void ) indexes_p;
62 int inotify_d = ( int ) ( long ) ctx_p->fsmondata;
63 debug ( 3, "select with timeout %li secs (fd == %u).", tv_p->tv_sec, inotify_d );
64 fd_set rfds;
65 FD_ZERO ( &rfds );
66 FD_SET ( inotify_d, &rfds );
67 return select ( inotify_d + 1, &rfds, NULL, NULL, tv_p );
68}
69
70#define INOTIFY_HANDLE_CONTINUE {\
71 ptr += sizeof(struct inotify_event) + event->len;\
72 count++;\
73 continue;\
74 }
75
76int inotify_handle ( ctx_t *ctx_p, indexes_t *indexes_p )
77{
78 static struct timeval tv = {0};
79 int inotify_d = ( int ) ( long ) ctx_p->fsmondata;
80 int count = 0;
81 fd_set rfds;
82 FD_ZERO ( &rfds );
83 FD_SET ( inotify_d, &rfds );
84 char *path_rel = NULL;
85 size_t path_rel_len = 0;
86 char *path_full = NULL;
87 size_t path_full_size = 0;
88
89 while ( select ( FD_SETSIZE, &rfds, NULL, NULL, &tv ) ) {
90 char buf[BUFSIZ + 1];
91 size_t r = read ( inotify_d, buf, BUFSIZ );
92
93 if ( r <= 0 ) {
94 error ( "Got error while reading events from inotify with read()." );
95 count = -1;
96 goto l_inotify_handle_end;
97 }
98
99#ifdef PARANOID
100 g_hash_table_remove_all ( indexes_p->fpath2ei_ht );
101#endif
102 char *ptr = buf;
103 char *end = &buf[r];
104
105 while ( ptr < end ) {
106 struct inotify_event *event = ( struct inotify_event * ) ptr;
107
108 // Removing stale wd-s
109
110 if ( event->mask & IN_IGNORED ) {
111 debug ( 2, "Cleaning up info about watch descriptor %i.", event->wd );
112 indexes_remove_bywd ( indexes_p, event->wd );
114 }
115
116 // Getting path
117 char *fpath = indexes_wd2fpath ( indexes_p, event->wd );
118
119 if ( fpath == NULL ) {
120 debug ( 2, "Event %p on stale watch (wd: %i).", ( void * ) ( long ) event->mask, event->wd );
122 }
123
124 debug ( 2, "Event %p on \"%s\" (wd: %i; fpath: \"%s\").", ( void * ) ( long ) event->mask, event->len > 0 ? event->name : "", event->wd, fpath );
125 // Getting full path
126 size_t path_full_memreq = strlen ( fpath ) + event->len + 2;
127
128 if ( path_full_size < path_full_memreq ) {
129 path_full = xrealloc ( path_full, path_full_memreq );
130 path_full_size = path_full_memreq;
131 }
132
133 if ( event->len > 0 )
134 sprintf ( path_full, "%s/%s", fpath, event->name );
135 else
136 sprintf ( path_full, "%s", fpath );
137
138 // Getting infomation about file/dir/etc
139 struct recognize_event_return r = {0};
140 recognize_event ( &r, event->mask );
141 stat64_t lst, *lst_p;
142 mode_t st_mode;
143 size_t st_size;
144
145 if ( ( r.objtype_new == EOT_DOESNTEXIST ) || ( ctx_p->flags[CANCEL_SYSCALLS]&CSC_MON_STAT ) || privileged_lstat64 ( path_full, &lst, PC_MON_HANDLE_LSTAT64 ) ) {
146 debug ( 2, "Cannot lstat64(\"%s\", lst). Seems, that the object had been deleted (%i) or option \"--cancel-syscalls mon_stat\" (%i) is set.", path_full, r.objtype_new == EOT_DOESNTEXIST, ctx_p->flags[CANCEL_SYSCALLS]&CSC_MON_STAT );
147 st_mode = ( event->mask & IN_ISDIR ? S_IFDIR : S_IFREG );
148 st_size = 0;
149 lst_p = NULL;
150 } else {
151 st_mode = lst.st_mode;
152 st_size = lst.st_size;
153 lst_p = &lst;
154 }
155
156 if ( sync_prequeue_loadmark ( 1, ctx_p, indexes_p, path_full, NULL, lst_p, r.objtype_old, r.objtype_new, event->mask, event->wd, st_mode, st_size, &path_rel, &path_rel_len, NULL ) ) {
157 count = -1;
158 goto l_inotify_handle_end;
159 }
160
162 }
163
164 // Globally queueing captured events:
165 // Moving events from local queue to global ones
166 sync_prequeue_unload ( ctx_p, indexes_p );
167 }
168
169l_inotify_handle_end:
170
171 if ( path_full != NULL )
172 free ( path_full );
173
174 if ( path_rel != NULL )
175 free ( path_rel );
176
177 return count;
178}
179
181{
182 int inotify_d = ( int ) ( long ) ctx_p->fsmondata;
183 debug ( 3, "Closing inotify_d" );
184 return close ( inotify_d );
185}
186
enum eventobjtype eventobjtype_t
Definition clsync.h:37
@ EOT_DIR
Definition clsync.h:33
@ EOT_DOESNTEXIST
Definition clsync.h:31
@ EOT_FILE
Definition clsync.h:32
#define INOTIFY_MARKMASK
#define BUFSIZ
@ CANCEL_SYSCALLS
Definition ctx.h:128
@ CSC_MON_STAT
Definition ctx.h:310
#define error(...)
Definition error.h:36
#define debug(debug_level,...)
Definition error.h:50
event_bits
Definition mon_bsm.c:50
@ UEM_CREATED
Definition mon_inotify.c:29
@ UEM_DELETED
Definition mon_inotify.c:30
@ UEM_DIR
Definition mon_inotify.c:28
int inotify_handle(ctx_t *ctx_p, indexes_t *indexes_p)
Definition mon_inotify.c:76
int inotify_deinit(ctx_t *ctx_p)
#define INOTIFY_HANDLE_CONTINUE
Definition mon_inotify.c:70
int inotify_wait(ctx_t *ctx_p, struct indexes *indexes_p, struct timeval *tv_p)
Definition mon_inotify.c:59
static void recognize_event(struct recognize_event_return *r, uint32_t event)
Definition mon_inotify.c:38
int inotify_add_watch_dir(ctx_t *ctx_p, indexes_t *indexes_p, const char *const accpath)
Definition mon_inotify.c:52
ctx_t * ctx_p
Definition mon_kqueue.c:85
#define IN_DELETE_SELF
Definition mon_kqueue.h:36
#define IN_CREATE
Definition mon_kqueue.h:34
#define IN_MOVED_FROM
Definition mon_kqueue.h:31
#define IN_ISDIR
Definition mon_kqueue.h:39
#define IN_DELETE
Definition mon_kqueue.h:35
#define IN_MOVED_TO
Definition mon_kqueue.h:32
#define IN_IGNORED
Definition mon_kqueue.h:38
struct stat64 stat64_t
Definition port-hacks.h:65
#define privileged_lstat64(a, b, c)
Definition privileged.h:122
#define privileged_inotify_add_watch(a, b, c, d)
Definition privileged.h:128
Definition ctx.h:315
void * fsmondata
Definition ctx.h:419
int flags[(1<< 10)]
Definition ctx.h:338
GHashTable * fpath2ei_ht
Definition indexes.h:37
eventobjtype_t objtype_old
Definition mon_bsm.c:63
eventobjtype_t objtype_new
Definition mon_bsm.c:64
int sync_prequeue_unload(ctx_t *ctx_p, indexes_t *indexes_p)
Definition sync.c:2564
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)
Definition sync.c:2143