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