1 #include "../test.h"
2 #include "../builders/build_file.h"
3 #include "../../src/alloc.h"
4 #include "config.h"
5 #include "../../src/client/find.h"
6 #include "../../src/client/find_logic.h"
7 #include "../../src/conffile.h"
8 #include "../../src/fsops.h"
9 #include "../../src/prepend.h"
10 #include "../../src/server/protocol1/link.h"
11
12 #define BASE "utest_find"
13 #define CONFBASE "utest_find_conf"
14
15 static char fullpath[4096]; // absolute path to base
16 static struct strlist *e=NULL;
17 static struct strlist *expected=NULL;
18
create_file(const char * path,size_t s)19 static void create_file(const char *path, size_t s)
20 {
21 FILE *fp;
22 fail_unless((fp=fopen(path, "wb+"))!=NULL);
23 while(s-->0)
24 fail_unless(fprintf(fp, "0")==1);
25 fail_unless(!fclose(fp));
26 }
27
send_file_callback(struct asfd * asfd,struct FF_PKT * ff,struct conf ** confs)28 static int send_file_callback(__attribute__ ((unused)) struct asfd *asfd,
29 struct FF_PKT *ff, __attribute__ ((unused)) struct conf **confs)
30 {
31 fail_unless(e!=NULL);
32 fail_unless(!strcmp(e->path, ff->fname));
33 fail_unless(e->flag==(long)ff->type);
34 if(ff->type==FT_LNK_S || ff->type==FT_LNK_H)
35 {
36 // Putting the link target in the next strlist item.
37 e=e->next;
38 fail_unless(!strcmp(e->path, ff->link));
39 fail_unless(!e->flag);
40 }
41 e=e->next;
42 return 0;
43 }
44
setup_conf(void)45 static struct conf **setup_conf(void)
46 {
47 struct conf **confs=NULL;
48 fail_unless((confs=confs_alloc())!=NULL);
49 fail_unless(!confs_init(confs));
50 return confs;
51 }
52
setup(struct conf *** confs)53 static struct FF_PKT *setup(struct conf ***confs)
54 {
55 struct FF_PKT *ff;
56 fail_unless(!recursive_delete(BASE));
57
58 // Create the root directory, so that we can figure out the absolute
59 // path to it, then delete it so that the root directory can be
60 // included when setting up the expected file system.
61 fail_unless(!mkdir(BASE, 0777));
62 fail_unless(realpath(BASE, fullpath)!=NULL);
63 fail_unless(!recursive_delete(BASE));
64
65 fail_unless((ff=find_files_init(send_file_callback))!=NULL);
66 *confs=setup_conf();
67 return ff;
68 }
69
tear_down(struct FF_PKT ** ff,struct conf *** confs)70 static void tear_down(struct FF_PKT **ff, struct conf ***confs)
71 {
72 fail_unless(e==NULL);
73 find_files_free(ff);
74 confs_free(confs);
75 strlists_free(&expected);
76 fail_unless(recursive_delete(BASE)==0);
77 // cleanup our logic caches
78 free_logic_cache();
79 alloc_check();
80 }
81
82 #define NOT_FOUND 0
83 #define FOUND 1
84
add_file(int find,const char * path,size_t s)85 static void add_file(int find, const char *path, size_t s)
86 {
87 char *tmp;
88 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
89 create_file(tmp, s);
90 if(find==FOUND)
91 fail_unless(!strlist_add(&expected, tmp, (long)FT_REG));
92 free_w(&tmp);
93 }
94
add_dir(int find,const char * path)95 static void add_dir(int find, const char *path)
96 {
97 char *tmp;
98 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
99 fail_unless(!mkdir(tmp, 0777));
100 if(find==FOUND)
101 fail_unless(!strlist_add(&expected, tmp, (long)FT_DIR));
102 free_w(&tmp);
103 }
104
add_slnk_raw(int find,const char * path,const char * link)105 static void add_slnk_raw(int find, const char *path, const char *link)
106 {
107 char *tmp;
108 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
109 fail_unless(!symlink(link, tmp));
110 if(find==FOUND)
111 {
112 fail_unless(!strlist_add(&expected, tmp, (long)FT_RAW));
113 }
114 free_w(&tmp);
115 }
116
add_slnk(int find,const char * path,const char * link)117 static void add_slnk(int find, const char *path, const char *link)
118 {
119 char *tmp;
120 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
121 fail_unless(!symlink(link, tmp));
122 if(find==FOUND)
123 {
124 fail_unless(!strlist_add(&expected, tmp, (long)FT_LNK_S));
125 fail_unless(!strlist_add(&expected, link, 0));
126 }
127 free_w(&tmp);
128 }
129
add_hlnk(int find,const char * path,const char * link)130 static void add_hlnk(int find, const char *path, const char *link)
131 {
132 char *src;
133 char *dst;
134 fail_unless((src=prepend_s(fullpath, path))!=NULL);
135 fail_unless((dst=prepend_s(fullpath, link))!=NULL);
136 fail_unless(!do_link(dst, src, NULL, NULL, 0));
137 if(find==FOUND)
138 {
139 fail_unless(!strlist_add(&expected, src, (long)FT_LNK_H));
140 fail_unless(!strlist_add(&expected, dst, 0));
141 }
142 free_w(&src);
143 free_w(&dst);
144 }
145
add_nostat(int find,const char * path)146 static void add_nostat(int find, const char *path)
147 {
148 char *tmp;
149 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
150 if(find==FOUND)
151 fail_unless(!strlist_add(&expected, tmp, (long)FT_NOSTAT));
152 free_w(&tmp);
153 }
154
add_sock(int find,const char * path)155 static void add_sock(int find, const char *path)
156 {
157 char *tmp;
158 long ftype=(long)FT_SPEC;
159 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
160 fail_unless(!mksock(tmp));
161 if(find==FOUND)
162 fail_unless(!strlist_add(&expected, tmp, ftype));
163 free_w(&tmp);
164 }
165
do_add_fifo(int find,const char * path,mode_t mode,long ftype)166 static void do_add_fifo(int find, const char *path, mode_t mode, long ftype)
167 {
168 char *tmp;
169 fail_unless((tmp=prepend_s(fullpath, path))!=NULL);
170 fail_unless(!mkfifo(tmp, mode));
171 if(find==FOUND)
172 fail_unless(!strlist_add(&expected, tmp, ftype));
173 free_w(&tmp);
174 }
175
add_fifo(int find,const char * path)176 static void add_fifo(int find, const char *path)
177 {
178 do_add_fifo(find, path, S_IFIFO, (long)FT_FIFO);
179 }
180
add_fifo_special(int find,const char * path)181 static void add_fifo_special(int find, const char *path)
182 {
183 do_add_fifo(find, path, S_IFIFO, (long)FT_SPEC);
184 }
185
run_find(const char * buf,struct FF_PKT * ff,struct conf ** confs)186 static void run_find(const char *buf, struct FF_PKT *ff, struct conf **confs)
187 {
188 struct strlist *l;
189 const char *conffile=CONFBASE "/burp.conf";
190 fail_unless(!recursive_delete(CONFBASE));
191 build_file(conffile, buf);
192 fail_unless(!conf_load_global_only(conffile, confs));
193 for(l=get_strlist(confs[OPT_STARTDIR]); l; l=l->next) if(l->flag)
194 fail_unless(!find_files_begin(NULL, ff, confs, l->path));
195 fail_unless(!recursive_delete(CONFBASE));
196 }
197
198 static char extra_config[8192]="";
199
do_test(void setup_entries (void))200 static void do_test(void setup_entries(void))
201 {
202 struct FF_PKT *ff;
203 char *buf=NULL;
204 struct conf **confs=NULL;
205 ff=setup(&confs);
206
207 setup_entries();
208 e=expected;
209
210 fail_unless(!astrcat(&buf, MIN_CLIENT_CONF, __func__));
211 fail_unless(!astrcat(&buf, extra_config, __func__));
212
213 run_find(buf, ff, confs);
214
215 free_w(&buf);
216 tear_down(&ff, &confs);
217 }
218
simple_entries(void)219 static void simple_entries(void)
220 {
221 add_dir( FOUND, "");
222 add_file(FOUND, "a", 1);
223 add_file(FOUND, "b", 2);
224 add_file(FOUND, "c", 3);
225 add_dir (FOUND, "d");
226 add_slnk(FOUND, "e", "a");
227 add_hlnk(FOUND, "f", "a");
228 add_hlnk(FOUND, "g", "a");
229 add_fifo_special(FOUND, "h");
230 add_sock(FOUND, "i");
231 snprintf(extra_config, sizeof(extra_config), "include=%s", fullpath);
232 }
233
min_file_size(void)234 static void min_file_size(void)
235 {
236 add_dir( FOUND, "");
237 add_file(NOT_FOUND, "a", 1);
238 add_file( FOUND, "b", 2);
239 add_file( FOUND, "c", 3);
240 add_dir ( FOUND, "d");
241 snprintf(extra_config, sizeof(extra_config),
242 "include=%s\nmin_file_size=2", fullpath);
243 }
244
max_file_size(void)245 static void max_file_size(void)
246 {
247 add_dir( FOUND, "");
248 add_file( FOUND, "a", 1);
249 add_file( FOUND, "b", 2);
250 add_file(NOT_FOUND, "c", 3);
251 add_dir ( FOUND, "d");
252 snprintf(extra_config, sizeof(extra_config),
253 "include=%s\nmax_file_size=2", fullpath);
254 }
255
exclude_extension(void)256 static void exclude_extension(void)
257 {
258 add_dir( FOUND, "");
259 add_file(NOT_FOUND, "a.c", 1);
260 add_file(NOT_FOUND, "a.h", 2);
261 add_file( FOUND, "b", 2);
262 add_file( FOUND, "b.x", 2);
263 add_file(NOT_FOUND, "c.c", 3);
264 add_dir ( FOUND, "d");
265 snprintf(extra_config, sizeof(extra_config),
266 "include=%s\n"
267 "exclude_ext=c\n"
268 "exclude_ext=h\n", fullpath);
269 }
270
include_extension(void)271 static void include_extension(void)
272 {
273 add_dir( FOUND, "");
274 add_file( FOUND, "a.c", 1);
275 add_file( FOUND, "a.h", 2);
276 add_file(NOT_FOUND, "b", 2);
277 add_file(NOT_FOUND, "b.x", 2);
278 add_file( FOUND, "c.c", 3);
279 add_dir (NOT_FOUND, "d");
280 add_file( FOUND, "d/e.c", 3);
281 snprintf(extra_config, sizeof(extra_config),
282 "include=%s\n"
283 "include_ext=c\n"
284 "include_ext=h\n", fullpath);
285 }
286
exclude_dir(void)287 static void exclude_dir(void)
288 {
289 add_dir( FOUND, "");
290 add_file( FOUND, "a", 1);
291 add_dir (NOT_FOUND, "d");
292 add_file(NOT_FOUND, "d/x", 1);
293 add_file( FOUND, "e", 3);
294 snprintf(extra_config, sizeof(extra_config),
295 "include=%s\n"
296 "exclude=%s/d\n",
297 fullpath, fullpath);
298 }
299
include_inside_exclude(void)300 static void include_inside_exclude(void)
301 {
302 add_dir( FOUND, "");
303 add_file( FOUND, "a", 1);
304 add_dir (NOT_FOUND, "d");
305 add_file(NOT_FOUND, "d/b", 1);
306 add_dir ( FOUND, "d/i");
307 add_file( FOUND, "d/i/m", 2);
308 add_file(NOT_FOUND, "d/x", 1);
309 add_file( FOUND, "e", 3);
310 snprintf(extra_config, sizeof(extra_config),
311 "include=%s\n"
312 "exclude=%s/d\n"
313 "include=%s/d/i\n",
314 fullpath, fullpath, fullpath);
315 }
316
nobackup(void)317 static void nobackup(void)
318 {
319 add_dir( FOUND, "");
320 add_file( FOUND, "a", 1);
321 add_dir ( FOUND, "d");
322 add_file(NOT_FOUND, "d/.nobackup", 0);
323 add_file(NOT_FOUND, "d/b", 1);
324 add_dir (NOT_FOUND, "d/i");
325 add_file(NOT_FOUND, "d/x", 1);
326 add_file( FOUND, "e", 3);
327 add_dir ( FOUND, "f");
328 add_file(NOT_FOUND, "f/.exclude", 0);
329 add_file(NOT_FOUND, "f/b", 1);
330 add_dir ( FOUND, "g");
331 snprintf(extra_config, sizeof(extra_config),
332 "include=%s\n"
333 "nobackup=.nobackup\n"
334 "nobackup=.exclude\n",
335 fullpath);
336 }
337
symlink_as_blockdev(void)338 static void symlink_as_blockdev(void)
339 {
340 add_dir( FOUND, "");
341 add_file( FOUND, "a", 1);
342 add_slnk_raw(FOUND, "e", "a");
343 add_slnk_raw(FOUND, "f", "a");
344 snprintf(extra_config, sizeof(extra_config),
345 "include=%s\n"
346 "read_blockdev=%s/e\n"
347 "read_blockdev=%s/f\n",
348 fullpath, fullpath, fullpath);
349 }
350
fifo_individual(void)351 static void fifo_individual(void)
352 {
353 add_dir( FOUND, "");
354 add_fifo( FOUND, "a");
355 add_fifo( FOUND, "b");
356 add_fifo_special(FOUND, "c");
357 snprintf(extra_config, sizeof(extra_config),
358 "include=%s\n"
359 "read_fifo=%s/a\n"
360 "read_fifo=%s/b\n",
361 fullpath, fullpath, fullpath);
362 }
363
fifo_all(void)364 static void fifo_all(void)
365 {
366 add_dir( FOUND, "");
367 add_fifo( FOUND, "a");
368 add_fifo( FOUND, "b");
369 snprintf(extra_config, sizeof(extra_config),
370 "include=%s\n"
371 "read_all_fifos=1\n",
372 fullpath);
373 }
374
exclude_regex(void)375 static void exclude_regex(void)
376 {
377 add_dir( FOUND, "");
378 add_file( FOUND, "a", 1);
379 add_file( FOUND, "b", 1);
380 add_file( FOUND, "c", 1);
381 add_file(NOT_FOUND, "dnotthisone", 1);
382 add_dir ( FOUND, "e");
383 add_dir (NOT_FOUND, "e/fexc");
384 add_file(NOT_FOUND, "fnotthisone", 1);
385 snprintf(extra_config, sizeof(extra_config),
386 "include=%s\n"
387 "exclude_regex=not\n"
388 "exclude_regex=exc\n",
389 fullpath);
390 }
391
include_regex(void)392 static void include_regex(void)
393 {
394 add_dir( NOT_FOUND, "");
395 add_file( FOUND, "a", 1);
396 add_file(NOT_FOUND, "blah", 1);
397 add_file( FOUND, "blahb", 1);
398 add_file( FOUND, "haaa", 1);
399 add_file(NOT_FOUND, "x", 1);
400 snprintf(extra_config, sizeof(extra_config),
401 "include=%s\n"
402 "include_regex=a$\n"
403 "include_regex=b$\n",
404 fullpath);
405 }
406
exclude_logic(void)407 static void exclude_logic(void)
408 {
409 add_dir( FOUND, "");
410 add_file( FOUND, "a", 2);
411 add_file(NOT_FOUND, "a.ost", 6);
412 add_file( FOUND, "b.ost", 2);
413 add_file(NOT_FOUND, "caa", 15);
414 add_file(NOT_FOUND, "cbb", 16);
415 add_file( FOUND, "cc", 15);
416 add_file( FOUND, "haaaab", 9);
417 add_file(NOT_FOUND, "haaab", 8);
418 add_file(NOT_FOUND, "y", 4);
419 add_file( FOUND, "z", 2);
420 snprintf(extra_config, sizeof(extra_config),
421 "include=%s\n"
422 "exclude_logic=file_size>=5 and file_ext=ost\n"
423 "exclude_logic=(file_size>=3 and file_size<=5) or (file_size=8 and path_match=^%s/.*b$)\n"
424 "exclude_logic=(file_size>=10 and file_size<=20) and (file_ext=zoro or file_match='^c(a|b)')\n"
425 "exclude_logic=(file_size>=30 or file_size<2\n"
426 "exclude_logic=this expression isnt valid\n"
427 "exclude_logic=another unvalid expression\n",
428 fullpath, fullpath);
429 }
430
multi_includes(void)431 static void multi_includes(void)
432 {
433 add_dir( NOT_FOUND, "");
434 add_file( FOUND, "a", 1);
435 add_file(NOT_FOUND, "b", 2);
436 add_file(NOT_FOUND, "c", 3);
437 add_dir ( FOUND, "d");
438 add_dir ( FOUND, "d/a");
439 add_dir (NOT_FOUND, "d/a/b");
440 add_dir ( FOUND, "d/a/b/c");
441 add_nostat( FOUND, "d/a/b/c/d");
442 add_nostat( FOUND, "d/a/b/c/d/e");
443 add_slnk(NOT_FOUND, "e", "a");
444 add_hlnk(NOT_FOUND, "g", "a");
445 snprintf(extra_config, sizeof(extra_config),
446 "include=%s/a\n"
447 "include=%s/d\n"
448 "exclude=%s/d/a/b\n"
449 "include=%s/d/a/b/c\n"
450 "include=%s/d/a/b/c/d\n"
451 "include=%s/d/a/b/c/d/e\n",
452 fullpath, fullpath, fullpath, fullpath, fullpath, fullpath);
453 }
454
START_TEST(test_find)455 START_TEST(test_find)
456 {
457 do_test(simple_entries);
458 do_test(min_file_size);
459 do_test(max_file_size);
460 do_test(exclude_extension);
461 do_test(include_extension);
462 do_test(exclude_dir);
463 do_test(include_inside_exclude);
464 do_test(nobackup);
465 do_test(symlink_as_blockdev);
466 do_test(fifo_individual);
467 do_test(fifo_all);
468 do_test(exclude_regex);
469 do_test(include_regex);
470 do_test(multi_includes);
471 do_test(exclude_logic);
472 }
473 END_TEST
474
START_TEST(test_large_file_support)475 START_TEST(test_large_file_support)
476 {
477 // 32 bit machines need the correct build parameters to support
478 // large files. Try to detect problems here.
479 fail_unless(sizeof(off_t)>=8);
480 }
481 END_TEST
482
START_TEST(test_file_is_included_no_incext)483 START_TEST(test_file_is_included_no_incext)
484 {
485 struct conf **confs;
486 confs=setup_conf();
487 add_to_strlist(confs[OPT_INCEXCDIR], "/", 1);
488 add_to_strlist(confs[OPT_INCEXCDIR], "/blah", 0);
489 add_to_strlist(confs[OPT_INCEXCDIR], "/tmp", 0);
490 add_to_strlist(confs[OPT_INCEXCDIR], "/tmp/some/sub/dir", 1);
491
492 fail_unless(file_is_included_no_incext(confs, "/blah2"));
493 fail_unless(file_is_included_no_incext(confs, "/blah2/blah3"));
494 fail_unless(file_is_included_no_incext(confs, "/tmp/some/sub/dir/1"));
495 fail_unless(!file_is_included_no_incext(confs, "/tmp"));
496 fail_unless(!file_is_included_no_incext(confs, "/tmp/blah"));
497 fail_unless(!file_is_included_no_incext(confs, "/tmp/some/sub"));
498
499 confs_free(&confs);
500 alloc_check();
501 }
502 END_TEST
503
suite_client_find(void)504 Suite *suite_client_find(void)
505 {
506 Suite *s;
507 TCase *tc_core;
508
509 s=suite_create("client_find");
510
511 tc_core=tcase_create("Core");
512
513 tcase_add_test(tc_core, test_find);
514 tcase_add_test(tc_core, test_large_file_support);
515 tcase_add_test(tc_core, test_file_is_included_no_incext);
516 suite_add_tcase(s, tc_core);
517
518 return s;
519 }
520