Showing
2 changed files
with
250 additions
and
0 deletions
mon_dtracepipe.c
0 → 100644
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 | +#include "common.h" | ||
20 | +#include "malloc.h" | ||
21 | +#include "error.h" | ||
22 | +#include "indexes.h" | ||
23 | +#include "sync.h" | ||
24 | +#include "mon_dtracepipe.h" | ||
25 | + | ||
26 | +#define DTRACE_SCRIPT "BEGIN\ | ||
27 | +{\ | ||
28 | + dir = $1;\ | ||
29 | + dirlen = strlen(dir);\ | ||
30 | +}\ | ||
31 | +\ | ||
32 | +syscall::open*:entry\ | ||
33 | +/\ | ||
34 | +arg1 & (O_WRONLY|O_RDWR) &&\ | ||
35 | + substr(copyinstr(arg0),0,dirlen)==dir\ | ||
36 | +/\ | ||
37 | +{\ | ||
38 | + printf("%s\n",copyinstr(arg0));\ | ||
39 | +}\ | ||
40 | +\ | ||
41 | +syscall::mkdir*:entry\ | ||
42 | +/\ | ||
43 | + substr(copyinstr(arg0),0,dirlen)==dir\ | ||
44 | +/\ | ||
45 | +{\ | ||
46 | + printf("%s\n",copyinstr(arg0));\ | ||
47 | +}" | ||
48 | + | ||
49 | +struct mondata { | ||
50 | + FILE *pipe; | ||
51 | +}; | ||
52 | +typedef struct mondata mondata_t; | ||
53 | + | ||
54 | +#define DTRACEPIPE_INIT_ERROR {\ | ||
55 | + free(ctx_p->fsmondata);\ | ||
56 | + ctx_p->fsmondata = NULL;\ | ||
57 | + return -1;\ | ||
58 | +} | ||
59 | + | ||
60 | +int dtracepipe_init(ctx_t *ctx_p) { | ||
61 | + char cmd[BUFSIZ]; | ||
62 | + | ||
63 | + ctx_p->fsmondata = xcalloc(sizeof(mondata_t), 1); | ||
64 | + mondata_t *mondata = ctx_p->fsmondata; | ||
65 | + | ||
66 | + if (snprintf(cmd, "%s -n '%s' '%s'", DTRACE_PATH, DTRACE_SCRIPT, ) >= BUFSIZ) { | ||
67 | + errno = EMSGSIZE; | ||
68 | + error("Too long cmd."); | ||
69 | + DTRACEPIPE_INIT_ERROR; | ||
70 | + } | ||
71 | + | ||
72 | + FILE *pipe = popen(cmd, "r"); | ||
73 | + if (pipe == NULL) { | ||
74 | + error("Cannot popen(\""DTRACE_PATH"\", \"r\")"); | ||
75 | + DTRACEPIPE_INIT_ERROR; | ||
76 | + } | ||
77 | + | ||
78 | + if (setvbuf(pipe, NULL, _IONBF, 0)) { | ||
79 | + error("Cannot set unbuffered mode for pipe of \""DTRACE_PATH"\" process"); | ||
80 | + DTRACEPIPE_INIT_ERROR; | ||
81 | + } | ||
82 | + | ||
83 | + mondata->pipe = pipe; | ||
84 | + | ||
85 | + return 0; | ||
86 | +} | ||
87 | + | ||
88 | +char *dtracepipe_wait_line = NULL; | ||
89 | +size_t dtracepipe_wait_line_siz; | ||
90 | +int dtracepipe_wait(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p) { | ||
91 | + mondata_t *mondata = ctx_p->fsmondata; | ||
92 | + struct timeval timeout_abs, tv_abs; | ||
93 | + int dontwait = 0; | ||
94 | + struct dtracepipe_event *event_p = &mondata->event; | ||
95 | + | ||
96 | + if (timeout_p->tv_sec == 0 && timeout_p->tv_usec == 0) | ||
97 | + dontwait = 1; | ||
98 | + | ||
99 | + if (!dontwait) { | ||
100 | + gettimeofday(&tv_abs, NULL); | ||
101 | + timeradd(&tv_abs, timeout_p, &timeout_abs); | ||
102 | + } | ||
103 | + | ||
104 | + int pipe_fd = fileno(mondata->pipe); | ||
105 | + | ||
106 | + while (42) { | ||
107 | + int path_count; | ||
108 | + | ||
109 | + // Checking if there already a recond in mondata | ||
110 | + if (*event_p->path) { | ||
111 | + debug(2, "we have an event. return 1."); | ||
112 | + return 1; | ||
113 | + } | ||
114 | + | ||
115 | + // Getting a record | ||
116 | + { | ||
117 | + debug(3, "select() with timeout %li.%06li secs (dontwait == %u).", timeout_p->tv_sec, timeout_p->tv_usec, dontwait); | ||
118 | + fd_set rfds; | ||
119 | + FD_ZERO(&rfds); | ||
120 | + FD_SET(pipe_fd, &rfds); | ||
121 | + int rc = select(pipe_fd+1, &rfds, NULL, NULL, timeout_p); | ||
122 | + | ||
123 | + if (rc == 0 || rc == -1) | ||
124 | + return rc; | ||
125 | + | ||
126 | + line_len = getline(&dtracepipe_wait_line, &dtracepipe_wait_line_siz, mondata->pipe); | ||
127 | + if (line_len == -1) { | ||
128 | + error("Cannot read line from \""DTRACE_PATH"\" pipe [using getline()]"); | ||
129 | + return -1; | ||
130 | + } | ||
131 | + | ||
132 | + if (!dontwait) { | ||
133 | + debug(5, "old timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec); | ||
134 | + gettimeofday(&tv_abs, NULL); | ||
135 | + if (timercmp(&timeout_abs, &tv_abs, <)) | ||
136 | + timersub(&timeout_abs, &tv_abs, timeout_p); | ||
137 | + else | ||
138 | + memset(timeout_p, 0, sizeof(*timeout_p)); | ||
139 | + debug(5, "new timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec); | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + // Parsing the record | ||
144 | + path_count = 0; | ||
145 | + debug(3, "parsing the event"); | ||
146 | + while (au_parsed < au_len) { | ||
147 | + | ||
148 | + if (au_fetch_tok(&tok, &au_buf[au_parsed], au_len - au_parsed) == -1) | ||
149 | + return -1; | ||
150 | + au_parsed += tok.len; | ||
151 | + | ||
152 | + switch (tok.id) { | ||
153 | + case AUT_HEADER32: | ||
154 | + case AUT_HEADER32_EX: | ||
155 | + case AUT_HEADER64: | ||
156 | + case AUT_HEADER64_EX: { | ||
157 | + event_p->type = tok.tt.hdr32.e_type; | ||
158 | + path_count = 0; | ||
159 | + break; | ||
160 | + } | ||
161 | + case AUT_PATH: { | ||
162 | + char *ptr; | ||
163 | + int dir_wd, dir_iswatched; | ||
164 | + | ||
165 | + ptr = memrchr(tok.tt.path.path, '/', tok.tt.path.len); | ||
166 | + | ||
167 | +#ifdef PARANOID | ||
168 | + if (ptr == NULL) | ||
169 | + critical("relative path received from au_fetch_tok(): \"%s\" (len: %u)", tok.tt.path.path, tok.tt.path.len); | ||
170 | +#endif | ||
171 | + | ||
172 | + debug(6, "Event on \"%s\".", tok.tt.path.path); | ||
173 | + *ptr = 0; | ||
174 | + dir_wd = indexes_fpath2wd(indexes_p, tok.tt.path.path); | ||
175 | + dir_iswatched = (dir_wd != -1); | ||
176 | + debug(7, "Directory is \"%s\". dir_wd == %i; dir_iswatched == %u", tok.tt.path.path, dir_wd, dir_iswatched); | ||
177 | + *ptr = '/'; | ||
178 | + | ||
179 | + if (dir_iswatched) { | ||
180 | + debug(5, "Event on \"%s\" is watched. Pushing. path_count == %u", tok.tt.path.path, path_count); | ||
181 | + switch (path_count) { | ||
182 | + case 0: | ||
183 | + memcpy(event_p->path, tok.tt.path.path, tok.tt.path.len+1); | ||
184 | + break; | ||
185 | + case 1: | ||
186 | + memcpy(event_p->path_to, tok.tt.path.path, tok.tt.path.len+1); | ||
187 | + break; | ||
188 | +#ifdef PARANOID | ||
189 | + default: | ||
190 | + warning("To many paths on BSM event: \"%s\" (already count: %u)", tok.tt.path.path, path_count); | ||
191 | + break; | ||
192 | +#endif | ||
193 | + } | ||
194 | + } | ||
195 | + path_count++; | ||
196 | + break; | ||
197 | + } | ||
198 | + default: | ||
199 | + continue; | ||
200 | + } | ||
201 | + } | ||
202 | + | ||
203 | + // Cleanup | ||
204 | + debug(4, "clean up"); | ||
205 | + free(au_buf); | ||
206 | + au_buf = NULL; | ||
207 | + au_len = 0; | ||
208 | + au_parsed = 0; | ||
209 | + } | ||
210 | + return -1; | ||
211 | +} | ||
212 | +int dtracepipe_handle(struct ctx *ctx_p, struct indexes *indexes_p) { | ||
213 | + return -1; | ||
214 | +} | ||
215 | +int dtracepipe_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath) { | ||
216 | + return -1; | ||
217 | +} | ||
218 | +int dtracepipe_deinit(ctx_t *ctx_p) { | ||
219 | + mondata_t *mondata = ctx_p->fsmondata; | ||
220 | + | ||
221 | + free(dtracepipe_wait_line); | ||
222 | + free(mondata); | ||
223 | + | ||
224 | + return -1; | ||
225 | +} |
mon_dtracepipe.h
0 → 100644
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 | +extern int dtracepipe_init(ctx_t *ctx_p); | ||
21 | +extern int dtracepipe_wait(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *tv_p); | ||
22 | +extern int dtracepipe_handle(struct ctx *ctx_p, struct indexes *indexes_p); | ||
23 | +extern int dtracepipe_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath); | ||
24 | +extern int dtracepipe_deinit(ctx_t *ctx_p); | ||
25 | + |
-
Please register or login to post a comment