redmine

Added mon_dtracepipe.* files

  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 +}
  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 +