redmine

Added mon_dtracepipe.* files

/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "malloc.h"
#include "error.h"
#include "indexes.h"
#include "sync.h"
#include "mon_dtracepipe.h"
#define DTRACE_SCRIPT "BEGIN\
{\
dir = $1;\
dirlen = strlen(dir);\
}\
\
syscall::open*:entry\
/\
arg1 & (O_WRONLY|O_RDWR) &&\
substr(copyinstr(arg0),0,dirlen)==dir\
/\
{\
printf("%s\n",copyinstr(arg0));\
}\
\
syscall::mkdir*:entry\
/\
substr(copyinstr(arg0),0,dirlen)==dir\
/\
{\
printf("%s\n",copyinstr(arg0));\
}"
struct mondata {
FILE *pipe;
};
typedef struct mondata mondata_t;
#define DTRACEPIPE_INIT_ERROR {\
free(ctx_p->fsmondata);\
ctx_p->fsmondata = NULL;\
return -1;\
}
int dtracepipe_init(ctx_t *ctx_p) {
char cmd[BUFSIZ];
ctx_p->fsmondata = xcalloc(sizeof(mondata_t), 1);
mondata_t *mondata = ctx_p->fsmondata;
if (snprintf(cmd, "%s -n '%s' '%s'", DTRACE_PATH, DTRACE_SCRIPT, ) >= BUFSIZ) {
errno = EMSGSIZE;
error("Too long cmd.");
DTRACEPIPE_INIT_ERROR;
}
FILE *pipe = popen(cmd, "r");
if (pipe == NULL) {
error("Cannot popen(\""DTRACE_PATH"\", \"r\")");
DTRACEPIPE_INIT_ERROR;
}
if (setvbuf(pipe, NULL, _IONBF, 0)) {
error("Cannot set unbuffered mode for pipe of \""DTRACE_PATH"\" process");
DTRACEPIPE_INIT_ERROR;
}
mondata->pipe = pipe;
return 0;
}
char *dtracepipe_wait_line = NULL;
size_t dtracepipe_wait_line_siz;
int dtracepipe_wait(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p) {
mondata_t *mondata = ctx_p->fsmondata;
struct timeval timeout_abs, tv_abs;
int dontwait = 0;
struct dtracepipe_event *event_p = &mondata->event;
if (timeout_p->tv_sec == 0 && timeout_p->tv_usec == 0)
dontwait = 1;
if (!dontwait) {
gettimeofday(&tv_abs, NULL);
timeradd(&tv_abs, timeout_p, &timeout_abs);
}
int pipe_fd = fileno(mondata->pipe);
while (42) {
int path_count;
// Checking if there already a recond in mondata
if (*event_p->path) {
debug(2, "we have an event. return 1.");
return 1;
}
// Getting a record
{
debug(3, "select() with timeout %li.%06li secs (dontwait == %u).", timeout_p->tv_sec, timeout_p->tv_usec, dontwait);
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(pipe_fd, &rfds);
int rc = select(pipe_fd+1, &rfds, NULL, NULL, timeout_p);
if (rc == 0 || rc == -1)
return rc;
line_len = getline(&dtracepipe_wait_line, &dtracepipe_wait_line_siz, mondata->pipe);
if (line_len == -1) {
error("Cannot read line from \""DTRACE_PATH"\" pipe [using getline()]");
return -1;
}
if (!dontwait) {
debug(5, "old timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec);
gettimeofday(&tv_abs, NULL);
if (timercmp(&timeout_abs, &tv_abs, <))
timersub(&timeout_abs, &tv_abs, timeout_p);
else
memset(timeout_p, 0, sizeof(*timeout_p));
debug(5, "new timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec);
}
}
// Parsing the record
path_count = 0;
debug(3, "parsing the event");
while (au_parsed < au_len) {
if (au_fetch_tok(&tok, &au_buf[au_parsed], au_len - au_parsed) == -1)
return -1;
au_parsed += tok.len;
switch (tok.id) {
case AUT_HEADER32:
case AUT_HEADER32_EX:
case AUT_HEADER64:
case AUT_HEADER64_EX: {
event_p->type = tok.tt.hdr32.e_type;
path_count = 0;
break;
}
case AUT_PATH: {
char *ptr;
int dir_wd, dir_iswatched;
ptr = memrchr(tok.tt.path.path, '/', tok.tt.path.len);
#ifdef PARANOID
if (ptr == NULL)
critical("relative path received from au_fetch_tok(): \"%s\" (len: %u)", tok.tt.path.path, tok.tt.path.len);
#endif
debug(6, "Event on \"%s\".", tok.tt.path.path);
*ptr = 0;
dir_wd = indexes_fpath2wd(indexes_p, tok.tt.path.path);
dir_iswatched = (dir_wd != -1);
debug(7, "Directory is \"%s\". dir_wd == %i; dir_iswatched == %u", tok.tt.path.path, dir_wd, dir_iswatched);
*ptr = '/';
if (dir_iswatched) {
debug(5, "Event on \"%s\" is watched. Pushing. path_count == %u", tok.tt.path.path, path_count);
switch (path_count) {
case 0:
memcpy(event_p->path, tok.tt.path.path, tok.tt.path.len+1);
break;
case 1:
memcpy(event_p->path_to, tok.tt.path.path, tok.tt.path.len+1);
break;
#ifdef PARANOID
default:
warning("To many paths on BSM event: \"%s\" (already count: %u)", tok.tt.path.path, path_count);
break;
#endif
}
}
path_count++;
break;
}
default:
continue;
}
}
// Cleanup
debug(4, "clean up");
free(au_buf);
au_buf = NULL;
au_len = 0;
au_parsed = 0;
}
return -1;
}
int dtracepipe_handle(struct ctx *ctx_p, struct indexes *indexes_p) {
return -1;
}
int dtracepipe_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath) {
return -1;
}
int dtracepipe_deinit(ctx_t *ctx_p) {
mondata_t *mondata = ctx_p->fsmondata;
free(dtracepipe_wait_line);
free(mondata);
return -1;
}
... ...
/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int dtracepipe_init(ctx_t *ctx_p);
extern int dtracepipe_wait(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *tv_p);
extern int dtracepipe_handle(struct ctx *ctx_p, struct indexes *indexes_p);
extern int dtracepipe_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath);
extern int dtracepipe_deinit(ctx_t *ctx_p);
... ...