source: trunk/src/sh_files.c@ 375

Last change on this file since 375 was 373, checked in by katerina, 13 years ago

Patch for ticket #265 (inotify). Handling of added subdirectories and file list rescan.

File size: 73.3 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 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, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26#include <limits.h>
27
28#include <errno.h>
29
30/* Must be before <utime.h> on FreeBSD
31 */
32#include <sys/types.h>
33#include <unistd.h>
34
35#include <utime.h>
36
37#ifdef HAVE_DIRENT_H
38#include <dirent.h>
39#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
40#else
41#define dirent direct
42#define NAMLEN(dirent) (dirent)->d_namlen
43#ifdef HAVE_SYS_NDIR_H
44#include <sys/ndir.h>
45#endif
46#ifdef HAVE_SYS_DIR_H
47#include <sys/dir.h>
48#endif
49#ifdef HAVE_NDIR_H
50#include <ndir.h>
51#endif
52#endif
53#define NEED_ADD_DIRENT
54
55#ifdef HAVE_GLOB_H
56#include <glob.h>
57#endif
58#ifdef HAVE_FNMATCH_H
59#include <fnmatch.h>
60#endif
61
62
63#include "samhain.h"
64
65#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
66
67#include "sh_pthread.h"
68#include "sh_error.h"
69#include "sh_utils.h"
70#include "sh_unix.h"
71#include "sh_files.h"
72#include "sh_tiger.h"
73#include "sh_hash.h"
74#include "sh_ignore.h"
75#include "sh_inotify.h"
76#include "zAVLTree.h"
77
78#undef FIL__
79#define FIL__ _("sh_files.c")
80
81extern sh_watches sh_file_watches;
82
83static char * sh_files_C_dequote (char * s, size_t * length)
84{
85 size_t i, len = *length;
86 int flag = 0;
87 char *p, *q, *po, *pend;
88
89 /* search for backslash
90 */
91 for (i = 0; i < len; ++i)
92 {
93 if (s[i] == '\\')
94 {
95 flag = 1;
96 break;
97 }
98 }
99
100 if (flag == 0 || *s == '\0')
101 return s;
102
103 po = SH_ALLOC(len+1); *po = '\0'; p = po; pend = &po[len];
104
105 i = 0; q = s;
106
107 do
108 {
109 if (*q == '\\')
110 {
111 ++q;
112
113 if (*q == '\0')
114 { *p = *q; flag = 0; break; }
115 else if (*q == 'a')
116 { *p = '\a'; ++p; ++q; }
117 else if (*q == 'b')
118 { *p = '\b'; ++p; ++q; }
119 else if (*q == 'f')
120 { *p = '\f'; ++p; ++q; }
121 else if (*q == 'n')
122 { *p = '\n'; ++p; ++q; }
123 else if (*q == 'r')
124 { *p = '\r'; ++p; ++q; }
125 else if (*q == 't')
126 { *p = '\t'; ++p; ++q; }
127 else if (*q == 'v')
128 { *p = '\v'; ++p; ++q; }
129 else if (*q == '\\')
130 { *p = '\\'; ++p; ++q; }
131 else if (*q == '\'')
132 { *p = '\''; ++p; ++q; }
133 else if (*q == '"')
134 { *p = '"'; ++p; ++q; }
135 else if (*q == 'x')
136 {
137 if (isxdigit((int) q[1]) && isxdigit((int) q[2]))
138 {
139 /* hexadecimal value following */
140 unsigned char cc = (16 * sh_util_hexchar(q[1]))
141 + sh_util_hexchar(q[2]);
142 *p = (char) cc;
143 ++p; q += 3;
144 }
145 else
146 {
147 *p = '\0'; flag = 0; break;
148 }
149 }
150 else if (isdigit((int)*q))
151 {
152 if (isdigit((int) q[1]) && q[1] < '8' &&
153 isdigit((int) q[2]) && q[2] < '8')
154 {
155 /* octal value following */
156 char tmp[4]; unsigned char cc;
157 tmp[0] = *q; ++q; tmp[1] = *q; ++q; tmp[2] = *q; ++q;
158 tmp[3] = '\0';
159 cc = strtol(tmp, NULL, 8);
160 *p = (char) cc; ++p;
161 }
162 else
163 {
164 *p = '\0'; flag = 0; break;
165 }
166 }
167 else
168 {
169 /* invalid escape sequence */
170 *p = '\0'; flag = 0; break;
171 }
172 }
173 else
174 {
175 *p = *q;
176 ++p; ++q;
177 }
178 } while (*q && p <= pend);
179
180 SL_REQUIRE (p <= pend, _("p <= pend"));
181
182 if (flag)
183 {
184 *p = '\0';
185 *length = strlen(po);
186 }
187 else
188 {
189 SH_FREE(po);
190 po = NULL;
191 *length = 0;
192 }
193
194 SL_REQUIRE (*length <= len, _("*length <= len"));
195
196 SH_FREE(s);
197 return po;
198}
199
200extern int flag_err_debug;
201extern int flag_err_info;
202
203int sh_files_reportonce(const char * c)
204{
205 int i;
206 SL_ENTER(_("sh_files_reportonce"));
207 i = sh_util_flagval(c, &(sh.flag.reportonce));
208
209 SL_RETURN(i, _("sh_files_reportonce"));
210}
211
212int sh_files_fulldetail(const char * c)
213{
214 int i;
215 SL_ENTER(_("sh_files_fulldetail"));
216 i = sh_util_flagval(c, &(sh.flag.fulldetail));
217
218 SL_RETURN((i), _("sh_files_fulldetail"));
219}
220
221
222typedef struct dir_struct {
223 long NumRegular;
224 long NumDirs;
225 long NumSymlinks;
226 long NumFifos;
227 long NumSockets;
228 long NumCDev;
229 long NumBDev;
230 long NumDoor;
231 long NumPort;
232 long NumAll;
233 long TotalBytes;
234 char DirPath[PATH_MAX];
235} dir_type;
236
237typedef struct dirstack_entry {
238 char * name;
239 int class;
240 unsigned long check_mask;
241 int rdepth;
242 short checked;
243 short childs_checked;
244 short is_reported;
245 /* struct dirstack_entry * next; */
246} dirstack_t;
247
248
249/* the destructor
250 */
251void free_dirstack (void * inptr)
252{
253 dirstack_t * here;
254
255 SL_ENTER(_("free_dirstack"));
256 if (inptr == NULL)
257 SL_RET0(_("free_dirstack"));
258 else
259 here = (dirstack_t *) inptr;
260
261 if (here->name != NULL)
262 SH_FREE(here->name);
263 SH_FREE(here);
264 SL_RET0(_("free_dirstack"));
265}
266
267/* Function to return the key for indexing
268 * the argument
269 */
270zAVLKey zdirstack_key (void const * arg)
271{
272 const dirstack_t * sa = (const dirstack_t *) arg;
273 return (zAVLKey) sa->name;
274}
275
276#define SH_LIST_FILE 0
277#define SH_LIST_DIR1 1
278#define SH_LIST_DIR2 2
279
280
281static int which_dirList = SH_LIST_DIR1;
282
283static zAVLTree * zdirListOne = NULL;
284static zAVLTree * zdirListTwo = NULL;
285static zAVLTree * zfileList = NULL;
286
287SH_MUTEX_STATIC(mutex_zfiles, PTHREAD_MUTEX_INITIALIZER);
288SH_MUTEX_STATIC(mutex_zglob, PTHREAD_MUTEX_INITIALIZER);
289SH_MUTEX_RECURSIVE(mutex_zdirs);
290
291static int sh_files_fullpath (const char * testdir,
292 const char * d_name,
293 char * statpath);
294static int sh_files_pushdir (int class, const char * str_s);
295static int sh_files_pushfile (int class, const char * str_s);
296
297static long MaxRecursionLevel = 0;
298
299/* set default recursion level
300 */
301int sh_files_setrecursion (const char * flag_s)
302{
303 long flag = 0;
304 static int reject = 0;
305
306 SL_ENTER( _("sh_files_setrecursion"));
307
308 if (reject == 1)
309 SL_RETURN((-1), _("sh_files_setrecursion"));
310
311 if (sh.flag.opts == 1)
312 reject = 1;
313
314 if (flag_s != NULL)
315 flag = (int)(atof(flag_s));
316
317 if (flag >= 0 && flag <= 99)
318 MaxRecursionLevel = flag;
319 else
320 SL_RETURN((-1), _("sh_files_setrecursion"));
321
322 SL_RETURN((0), _("sh_files_setrecursion"));
323}
324
325unsigned long sh_files_chk ()
326{
327 zAVLCursor cursor;
328 ShFileType status;
329 unsigned long fcount = 0;
330
331 char * tmp = NULL;
332
333 dirstack_t * ptr;
334 char * dir;
335 char * file;
336 int tmp_reported;
337
338 SL_ENTER(_("sh_files_chk"));
339
340 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
341 ptr = (dirstack_t *) zAVLNext(&cursor))
342 {
343
344 if (sig_urgent > 0) {
345 SL_RETURN(fcount, _("sh_files_chk"));
346 }
347
348 if (ptr->checked == S_FALSE)
349 {
350 dir = sh_util_dirname (ptr->name);
351 file = sh_util_basename (ptr->name);
352#if defined(WITH_TPT)
353 tmp = sh_util_safe_name (ptr->name);
354#endif
355
356
357 if (flag_err_info == SL_TRUE)
358 {
359 char pstr[32];
360#if !defined(WITH_TPT)
361 tmp = sh_util_safe_name (ptr->name);
362#endif
363 sl_strlcpy(pstr, sh_hash_getpolicy(ptr->class), sizeof(pstr));
364 sh_error_handle ((-1), FIL__, __LINE__, 0,
365 MSG_FI_CHK, pstr, tmp);
366 }
367
368 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
369 {
370 sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL,
371 ptr->class, ptr->check_mask,
372 SH_INOTIFY_FILE, 0);
373 }
374
375 BREAKEXIT(sh_files_filecheck);
376 tmp_reported = ptr->is_reported; /* fix aliasing warning */
377 status = sh_files_filecheck (ptr->class, ptr->check_mask, dir, file,
378 &tmp_reported, 0);
379 ptr->is_reported = tmp_reported;
380
381 TPT(( 0, FIL__, __LINE__,
382 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
383 tmp, status, ptr->is_reported));
384
385 if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
386 {
387 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
388 tmp, status));
389
390 if ( sh.flag.checkSum == SH_CHECK_INIT ||
391 sh_hash_have_it (ptr->name) >= 0)
392 {
393 if (S_FALSE == sh_ignore_chk_del(ptr->name))
394 {
395 if (0 != hashreport_missing(ptr->name,
396 (ptr->class == SH_LEVEL_ALLIGNORE) ?
397 ShDFLevel[ptr->class] :
398 ShDFLevel[SH_ERR_T_FILE])) {
399 if (tmp == NULL)
400 tmp = sh_util_safe_name (ptr->name);
401 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
402 ShDFLevel[ptr->class] :
403 ShDFLevel[SH_ERR_T_FILE],
404 FIL__, __LINE__, 0, MSG_FI_MISS,
405 tmp);
406 }
407 }
408 }
409 else /* not there at init, and still missing */
410 {
411 if (tmp == NULL)
412 tmp = sh_util_safe_name (ptr->name);
413 sh_error_handle (SH_ERR_NOTICE,
414 FIL__, __LINE__, 0,
415 MSG_FI_FAIL,
416 tmp);
417 }
418#ifndef REPLACE_OLD
419 /* this will tell that we have seen the file, and thus prevent
420 * deletion from the database, resulting in an incomplete
421 * message when the file reappears
422 */
423 if (sh.flag.checkSum != SH_CHECK_INIT)
424 sh_hash_set_visited_true(ptr->name);
425#else
426 if (sh.flag.checkSum != SH_CHECK_INIT)
427 sh_hash_set_missing(ptr->name);
428#endif
429 if (sh.flag.reportonce == S_TRUE)
430 SET_SH_FFLAG_REPORTED(ptr->is_reported);
431 }
432 else
433 {
434 /* exists (status >= 0), but was missing (reported == TRUE)
435 */
436 if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported))
437 {
438 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
439 }
440 /* Catchall
441 */
442 else if (status == SH_FILE_UNKNOWN)
443 {
444 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
445 * is reported if ptr->reported == S_TRUE because the
446 * file has been added.
447 */
448 if (sh_hash_have_it (ptr->name) >= 0 &&
449 !SH_FFLAG_REPORTED_SET(ptr->is_reported))
450 {
451 if (S_FALSE == sh_ignore_chk_del(ptr->name))
452 {
453 if (0 != hashreport_missing(ptr->name,
454 (ptr->class == SH_LEVEL_ALLIGNORE) ?
455 ShDFLevel[ptr->class] :
456 ShDFLevel[SH_ERR_T_FILE])) {
457 if (tmp == NULL)
458 tmp = sh_util_safe_name (ptr->name);
459 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
460 ShDFLevel[ptr->class] :
461 ShDFLevel[SH_ERR_T_FILE],
462 FIL__, __LINE__, 0, MSG_FI_MISS,
463 tmp);
464 }
465 }
466#ifndef REPLACE_OLD
467 if (sh.flag.checkSum != SH_CHECK_INIT)
468 sh_hash_set_visited_true(ptr->name);
469#else
470 /* delete from database
471 */
472 if (sh.flag.checkSum != SH_CHECK_INIT)
473 sh_hash_set_missing(ptr->name);
474#endif
475 }
476 else
477 {
478 if (tmp == NULL)
479 tmp = sh_util_safe_name (ptr->name);
480 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
481 MSG_FI_FAIL,
482 tmp);
483 if (sh.flag.checkSum != SH_CHECK_INIT)
484 sh_hash_set_visited_true(ptr->name);
485 }
486 }
487 ++fcount;
488 }
489
490 if (tmp != NULL)
491 {
492 SH_FREE(tmp);
493 tmp = NULL;
494 }
495 if (file)
496 SH_FREE(file);
497 if (dir)
498 SH_FREE(dir);
499
500 ptr->checked = S_TRUE;
501 }
502 }
503
504 SL_RETURN(fcount, _("sh_files_chk"));
505}
506
507int sh_files_delfilestack ()
508{
509 SL_ENTER(_("sh_files_delfilestack"));
510
511 SH_MUTEX_LOCK(mutex_zfiles);
512 zAVLFreeTree (zfileList, free_dirstack);
513 zfileList = NULL;
514 SH_MUTEX_UNLOCK(mutex_zfiles);
515
516 SL_RETURN(0, _("sh_files_delfilestack"));
517}
518
519int sh_files_setrec_int (zAVLTree * tree)
520{
521 dirstack_t * ptr;
522 zAVLCursor avlcursor;
523
524 SL_ENTER(_("sh_files_setrec"));
525 if (tree != NULL) {
526 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
527 ptr = (dirstack_t *) zAVLNext(&avlcursor))
528 {
529 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
530 {
531 ptr->rdepth = MaxRecursionLevel;
532 }
533 if (ptr->rdepth == (-1) && sh.flag.checkSum != SH_CHECK_INIT)
534 hash_remove_tree (ptr->name);
535 }
536 }
537 SL_RETURN(0, _("sh_files_setrec"));
538}
539
540int sh_files_setrec ()
541{
542 volatile int ret;
543 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
544 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
545 sh_files_setrec_int(zdirListOne);
546 ret = sh_files_setrec_int(zdirListTwo);
547 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
548
549 return ret;
550}
551
552zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
553{
554 SL_ENTER(_("sh_files_deldirstack"));
555
556 zAVLFreeTree (ptr, free_dirstack);
557
558 SL_RETURN(NULL, _("sh_files_deldirstack"));
559}
560
561int sh_files_deldirstack ()
562{
563 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
564 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
565 zdirListOne = sh_files_deldirstack_int(zdirListOne);
566 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
567 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
568 return 0;
569}
570
571void sh_files_reset()
572{
573 dirstack_t * ptr;
574 zAVLCursor avlcursor;
575
576 SL_ENTER(_("sh_files_reset"));
577
578 SH_MUTEX_LOCK(mutex_zfiles);
579 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
580 ptr = (dirstack_t *) zAVLNext(&avlcursor))
581 ptr->checked = 0;
582 SH_MUTEX_UNLOCK(mutex_zfiles);
583 SL_RET0(_("sh_files_reset"));
584}
585
586void sh_dirs_reset()
587{
588 dirstack_t * ptr;
589 zAVLCursor avlcursor1;
590 zAVLCursor avlcursor2;
591
592 SL_ENTER(_("sh_dirs_reset"));
593
594 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
595 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
596 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
597 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
598 ptr->checked = 0;
599
600 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
601 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
602 ptr->checked = 0;
603 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
604
605 SL_RET0(_("sh_dirs_reset"));
606}
607
608
609int sh_files_pushfile_prelink (const char * str_s)
610{
611 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
612}
613
614int sh_files_pushfile_user0 (const char * str_s)
615{
616 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
617}
618
619int sh_files_pushfile_user1 (const char * str_s)
620{
621 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
622}
623
624int sh_files_pushfile_user2 (const char * str_s)
625{
626 return (sh_files_pushfile (SH_LEVEL_USER2, str_s));
627}
628
629int sh_files_pushfile_user3 (const char * str_s)
630{
631 return (sh_files_pushfile (SH_LEVEL_USER3, str_s));
632}
633
634int sh_files_pushfile_user4 (const char * str_s)
635{
636 return (sh_files_pushfile (SH_LEVEL_USER4, str_s));
637}
638
639
640int sh_files_pushfile_ro (const char * str_s)
641{
642 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
643}
644
645int sh_files_pushfile_attr (const char * str_s)
646{
647 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
648}
649
650int sh_files_pushfile_log (const char * str_s)
651{
652 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
653}
654
655int sh_files_pushfile_glog (const char * str_s)
656{
657 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
658}
659
660int sh_files_pushfile_noig (const char * str_s)
661{
662 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
663}
664
665int sh_files_pushfile_allig (const char * str_s)
666{
667 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
668}
669
670
671static void sh_files_set_mask (unsigned long * mask,
672 unsigned long val, int act)
673{
674 SL_ENTER(_("sh_files_set_mask"));
675
676 if (act == 0)
677 (*mask) = val;
678 else if (act > 0)
679 (*mask) |= val;
680 else
681 (*mask) &= ~val;
682
683 SL_RET0(_("sh_files_set_mask"));
684}
685
686/* set mask(class)
687 */
688static int sh_files_parse_mask (unsigned long * mask, const char * str)
689{
690 int l, i = 0, act = 0, k = 0;
691 char myword[64];
692
693 SL_ENTER(_("sh_files_parse_mask"));
694
695 if (str == NULL)
696 {
697 SL_RETURN ( (-1), _("sh_files_parse_mask"));
698 }
699 else
700 l = sl_strlen(str);
701
702 while (i < l) {
703 if (str[i] == '\0')
704 break;
705 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
706 {
707 ++i;
708 continue;
709 }
710
711 if (str[i] == '+')
712 {
713 act = +1; ++i;
714 continue;
715 }
716 else if (str[i] == '-')
717 {
718 act = -1; ++i;
719 continue;
720 }
721 else /* a word */
722 {
723 k = 0;
724 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
725 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
726 myword[k] = str[i];
727 ++i; ++k;
728 }
729 myword[k] = '\0';
730
731/* checksum */
732 if (0 == strncmp(myword, _("CHK"), 3))
733 sh_files_set_mask (mask, MODI_CHK, act);
734/* link */
735 if (0 == strncmp(myword, _("LNK"), 3))
736 sh_files_set_mask (mask, MODI_LNK, act);
737/* inode */
738 if (0 == strncmp(myword, _("RDEV"), 3))
739 sh_files_set_mask (mask, MODI_RDEV, act);
740/* inode */
741 if (0 == strncmp(myword, _("INO"), 3))
742 sh_files_set_mask (mask, MODI_INO, act);
743/* user */
744 if (0 == strncmp(myword, _("USR"), 3))
745 sh_files_set_mask (mask, MODI_USR, act);
746/* group */
747 if (0 == strncmp(myword, _("GRP"), 3))
748 sh_files_set_mask (mask, MODI_GRP, act);
749/* mtime */
750 if (0 == strncmp(myword, _("MTM"), 3))
751 sh_files_set_mask (mask, MODI_MTM, act);
752/* ctime */
753 if (0 == strncmp(myword, _("CTM"), 3))
754 sh_files_set_mask (mask, MODI_CTM, act);
755/* atime */
756 if (0 == strncmp(myword, _("ATM"), 3))
757 sh_files_set_mask (mask, MODI_ATM, act);
758/* size */
759 if (0 == strncmp(myword, _("SIZ"), 3))
760 sh_files_set_mask (mask, MODI_SIZ, act);
761/* file mode */
762 if (0 == strncmp(myword, _("MOD"), 3))
763 sh_files_set_mask (mask, MODI_MOD, act);
764/* hardlinks */
765 if (0 == strncmp(myword, _("HLN"), 3))
766 sh_files_set_mask (mask, MODI_HLN, act);
767/* size may grow */
768 if (0 == strncmp(myword, _("GROW"), 3))
769 sh_files_set_mask (mask, MODI_SGROW, act);
770/* use prelink */
771 if (0 == strncmp(myword, _("PRE"), 3))
772 sh_files_set_mask (mask, MODI_PREL, act);
773/* get content */
774 if (0 == strncmp(myword, _("TXT"), 3))
775 sh_files_set_mask (mask, MODI_TXT, act);
776/* get content */
777 if (0 == strncmp(myword, _("AUDIT"), 3))
778 sh_files_set_mask (mask, MODI_AUDIT, act);
779 }
780 }
781 SL_RETURN ( (0), _("sh_files_parse_mask"));
782}
783
784int sh_files_redef_prelink(const char * str)
785{
786 return (sh_files_parse_mask(&mask_PRELINK, str));
787}
788int sh_files_redef_user0(const char * str)
789{
790 return (sh_files_parse_mask(&mask_USER0, str));
791}
792int sh_files_redef_user1(const char * str)
793{
794 return (sh_files_parse_mask(&mask_USER1, str));
795}
796int sh_files_redef_user2(const char * str)
797{
798 return (sh_files_parse_mask(&mask_USER2, str));
799}
800int sh_files_redef_user3(const char * str)
801{
802 return (sh_files_parse_mask(&mask_USER3, str));
803}
804int sh_files_redef_user4(const char * str)
805{
806 return (sh_files_parse_mask(&mask_USER4, str));
807}
808int sh_files_redef_readonly(const char * str)
809{
810 return (sh_files_parse_mask(&mask_READONLY, str));
811}
812int sh_files_redef_loggrow(const char * str)
813{
814 return (sh_files_parse_mask(&mask_LOGGROW, str));
815}
816int sh_files_redef_logfiles(const char * str)
817{
818 return (sh_files_parse_mask(&mask_LOGFILES, str));
819}
820int sh_files_redef_attributes(const char * str)
821{
822 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
823}
824int sh_files_redef_noignore(const char * str)
825{
826 return (sh_files_parse_mask(&mask_NOIGNORE, str));
827}
828int sh_files_redef_allignore(const char * str)
829{
830 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
831}
832
833unsigned long sh_files_maskof (int class)
834{
835 switch (class)
836 {
837 case SH_LEVEL_READONLY:
838 return (unsigned long) mask_READONLY;
839 case SH_LEVEL_ATTRIBUTES:
840 return (unsigned long) mask_ATTRIBUTES;
841 case SH_LEVEL_LOGFILES:
842 return (unsigned long) mask_LOGFILES;
843 case SH_LEVEL_LOGGROW:
844 return (unsigned long) mask_LOGGROW;
845 case SH_LEVEL_ALLIGNORE:
846 return (unsigned long) mask_ALLIGNORE;
847 case SH_LEVEL_NOIGNORE:
848 return (unsigned long) mask_NOIGNORE;
849 case SH_LEVEL_USER0:
850 return (unsigned long) mask_USER0;
851 case SH_LEVEL_USER1:
852 return (unsigned long) mask_USER1;
853 case SH_LEVEL_USER2:
854 return (unsigned long) mask_USER2;
855 case SH_LEVEL_USER3:
856 return (unsigned long) mask_USER3;
857 case SH_LEVEL_USER4:
858 return (unsigned long) mask_USER4;
859 case SH_LEVEL_PRELINK:
860 return (unsigned long) mask_PRELINK;
861 default:
862 return (unsigned long) 0;
863 }
864}
865
866#ifdef HAVE_GLOB_H
867int sh_files_has_metachar (const char * str)
868{
869 SL_ENTER(_("sh_files_has_metachar"));
870 if (NULL != strchr(str, '*'))
871 SL_RETURN(1, _("sh_files_has_metachar"));
872 else if (NULL != strchr(str, '?'))
873 SL_RETURN(1, _("sh_files_has_metachar"));
874 else if (NULL != (strchr(str, '[')))
875 SL_RETURN(1, _("sh_files_has_metachar"));
876 else
877 SL_RETURN(0, _("sh_files_has_metachar"));
878}
879
880
881int sh_files_globerr (const char * epath, int errnum)
882{
883 char * p;
884 char errbuf[SH_ERRBUF_SIZE];
885
886 SL_ENTER(_("sh_files_globerr"));
887
888 if (errnum == ENOTDIR || errnum == ENOENT)
889 {
890 SL_RETURN(0, _("sh_files_globerr"));
891 }
892
893 p = sh_util_safe_name (epath);
894 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
895 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
896 SH_FREE(p);
897
898 SL_RETURN(0, _("sh_files_globerr"));
899}
900
901/* #ifdef HAVE_GLOB_H
902 */
903#endif
904
905int sh_files_push_file_int (int class, const char * str_s, size_t len)
906{
907 dirstack_t * new_item_ptr;
908 char * fileName;
909 int ret;
910 int count = 0;
911
912 SL_ENTER(_("sh_files_push_file_int"));
913
914 fileName = SH_ALLOC(len+1);
915 sl_strlcpy(fileName, str_s, len+1);
916
917 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
918
919 new_item_ptr->name = fileName;
920 new_item_ptr->class = class;
921 new_item_ptr->check_mask = sh_files_maskof(class);
922 new_item_ptr->rdepth = 0;
923 new_item_ptr->checked = S_FALSE;
924 new_item_ptr->is_reported = 0;
925 new_item_ptr->childs_checked = S_FALSE;
926
927 SH_MUTEX_LOCK(mutex_zfiles);
928 if (zfileList == NULL)
929 {
930 zfileList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
931 if (zfileList == NULL)
932 {
933 (void) safe_logger (0, 0, NULL);
934 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
935 }
936 }
937
938 ret = zAVLInsert (zfileList, new_item_ptr);
939 SH_MUTEX_UNLOCK(mutex_zfiles);
940
941 if (-1 == ret)
942 {
943 (void) safe_logger (0, 0, NULL);
944 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
945 }
946 else if (3 == ret)
947 {
948 if (sh.flag.started != S_TRUE)
949 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
950 fileName);
951 SH_FREE(fileName);
952 SH_FREE(new_item_ptr);
953 new_item_ptr = NULL;
954 }
955 else
956 {
957 int reported;
958 unsigned long check_mask = sh_files_maskof(class);
959
960 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
961 {
962 sh_files_filecheck (class, check_mask, str_s, NULL,
963 &reported, 0);
964 if (SH_FFLAG_REPORTED_SET(reported))
965 sh_files_set_file_reported(str_s);
966 sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL,
967 class, check_mask,
968 SH_INOTIFY_FILE, 0);
969 }
970
971 if (MODI_AUDIT_ENABLED(check_mask))
972 {
973 sh_audit_mark(str_s);
974 }
975 ++count;
976 }
977 SL_RETURN(count, _("sh_files_push_file_int"));
978}
979
980int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth);
981
982#ifdef HAVE_GLOB_H
983
984typedef struct globstack_entry {
985 char * name;
986 int class;
987 unsigned long check_mask;
988 int rdepth;
989 short type;
990 /* struct dirstack_entry * next; */
991} sh_globstack_t;
992
993static zAVLTree * zglobList = NULL;
994
995static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
996 unsigned long check_mask_in, int flag)
997{
998 int globstatus = -1;
999 unsigned int gloop;
1000 glob_t pglob;
1001
1002 int count = 0;
1003 volatile unsigned long check_mask = check_mask_in;
1004
1005 SL_ENTER(_("sh_files_pushglob"));
1006
1007 pglob.gl_offs = 0;
1008 globstatus = glob (p, 0, sh_files_globerr, &pglob);
1009
1010 if (globstatus == 0 && pglob.gl_pathc > 0)
1011 {
1012
1013 if (sh.flag.checkSum != SH_CHECK_INIT)
1014 {
1015 sh_globstack_t * new_item_ptr;
1016 char * fileName;
1017 int ret;
1018
1019 SH_MUTEX_TRYLOCK(mutex_zfiles);
1020 fileName = sh_util_strdup (p);
1021
1022 new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t));
1023
1024 new_item_ptr->name = fileName;
1025 new_item_ptr->class = class;
1026 new_item_ptr->check_mask = (flag == 0) ? sh_files_maskof(class) : check_mask;
1027 new_item_ptr->rdepth = rdepth;
1028 new_item_ptr->type = type;
1029
1030 if (zglobList == NULL)
1031 {
1032 zglobList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1033 if (zglobList == NULL)
1034 {
1035 (void) safe_logger (0, 0, NULL);
1036 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1037 }
1038 }
1039
1040 ret = zAVLInsert (zglobList, new_item_ptr);
1041
1042 if (ret != 0) /* already in list */
1043 {
1044 SH_FREE(fileName);
1045 SH_FREE(new_item_ptr);
1046 }
1047 SH_MUTEX_TRYLOCK_UNLOCK(mutex_zfiles);
1048 }
1049
1050 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1051 {
1052 if (type == SH_LIST_FILE)
1053 {
1054 count += sh_files_push_file_int (class, pglob.gl_pathv[gloop],
1055 sl_strlen(pglob.gl_pathv[gloop]));
1056 }
1057 else
1058 {
1059 which_dirList = type;
1060
1061 count += sh_files_push_dir_int (class, pglob.gl_pathv[gloop],
1062 sl_strlen(pglob.gl_pathv[gloop]), rdepth);
1063 }
1064 }
1065 }
1066 else
1067 {
1068 char * tmp = sh_util_safe_name (p);
1069
1070 if (pglob.gl_pathc == 0
1071#ifdef GLOB_NOMATCH
1072 || globstatus == GLOB_NOMATCH
1073#endif
1074 )
1075 sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE,
1076 FIL__, __LINE__,
1077 globstatus, MSG_FI_GLOB,
1078 _("No matches found"), tmp);
1079#ifdef GLOB_NOSPACE
1080 else if (globstatus == GLOB_NOSPACE)
1081 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1082 globstatus, MSG_FI_GLOB,
1083 _("Out of memory"), tmp);
1084#endif
1085#ifdef GLOB_ABORTED
1086 else if (globstatus == GLOB_ABORTED)
1087 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1088 globstatus, MSG_FI_GLOB,
1089 _("Read error"), tmp);
1090#endif
1091 else
1092 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1093 globstatus, MSG_FI_GLOB,
1094 _("Unknown error"), tmp);
1095
1096 SH_FREE(tmp);
1097
1098 }
1099
1100 globfree(&pglob);
1101 SL_RETURN(count, _("sh_files_pushglob"));
1102 return count;
1103}
1104
1105void sh_files_check_globFilePatterns()
1106{
1107 sh_globstack_t * testPattern;
1108 zAVLCursor cursor;
1109
1110 SL_ENTER(_("sh_files_check_globPatterns"));
1111
1112 SH_MUTEX_LOCK(mutex_zglob);
1113 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1114 testPattern;
1115 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1116 {
1117 if (testPattern->type == SH_LIST_FILE)
1118 {
1119 sh_files_pushglob(testPattern->class, testPattern->type,
1120 testPattern->name, testPattern->rdepth,
1121 testPattern->check_mask, 1);
1122 }
1123 }
1124 SH_MUTEX_UNLOCK(mutex_zglob);
1125 SL_RET0(_("sh_files_check_globPatterns"));
1126}
1127
1128void sh_files_check_globPatterns()
1129{
1130 sh_globstack_t * testPattern;
1131 zAVLCursor cursor;
1132
1133 SL_ENTER(_("sh_files_check_globPatterns"));
1134
1135 SH_MUTEX_LOCK(mutex_zglob);
1136 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1137 testPattern;
1138 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1139 {
1140 sh_files_pushglob(testPattern->class, testPattern->type,
1141 testPattern->name, testPattern->rdepth,
1142 testPattern->check_mask, 1);
1143 }
1144 SH_MUTEX_UNLOCK(mutex_zglob);
1145 SL_RET0(_("sh_files_check_globPatterns"));
1146}
1147
1148/* the destructor
1149 */
1150void free_globstack (void * inptr)
1151{
1152 sh_globstack_t * here;
1153
1154 SL_ENTER(_("free_globstack"));
1155 if (inptr == NULL)
1156 SL_RET0(_("free_globstack"));
1157 else
1158 here = (sh_globstack_t *) inptr;
1159
1160 if (here->name != NULL)
1161 SH_FREE(here->name);
1162 SH_FREE(here);
1163 SL_RET0(_("free_globstack"));
1164}
1165
1166int sh_files_delglobstack ()
1167{
1168 SL_ENTER(_("sh_files_delglobstack"));
1169
1170 SH_MUTEX_LOCK(mutex_zglob);
1171 zAVLFreeTree (zglobList, free_globstack);
1172 zglobList = NULL;
1173 SH_MUTEX_UNLOCK(mutex_zglob);
1174
1175 SL_RETURN(0, _("sh_files_delglobstack"));
1176}
1177
1178
1179#else
1180void sh_files_check_globPatterns()
1181{
1182 return;
1183}
1184int sh_files_delglobstack ()
1185{
1186 return 0;
1187}
1188#endif
1189
1190static int sh_files_pushfile (int class, const char * str_s)
1191{
1192 size_t len;
1193 char * tmp;
1194 char * p;
1195
1196 static int reject = 0;
1197
1198 SL_ENTER(_("sh_files_pushfile"));
1199
1200 if (reject == 1)
1201 SL_RETURN((-1),_("sh_files_pushfile"));
1202
1203 /* if we push a filename from the command line, make sure it
1204 * is the only one -- and will stay the only one
1205 */
1206 if (sh.flag.opts == 1)
1207 {
1208 sh_files_delfilestack ();
1209 sh_files_deldirstack ();
1210 sh_files_delglobstack ();
1211 reject = 1;
1212 }
1213
1214 if (str_s == NULL || str_s[0] == '\0')
1215 SL_RETURN((-1),_("sh_files_pushfile"));
1216
1217 len = sl_strlen(str_s);
1218
1219 if ( (str_s[0] == '"' && str_s[len-1] == '"' ) ||
1220 (str_s[0] == '\'' && str_s[len-1] == '\'') )
1221 {
1222 if (len < 3)
1223 SL_RETURN((-1),_("sh_files_pushfile"));
1224 --len;
1225 p = sh_util_strdup_l(&str_s[1], len);
1226 p[len-1] = '\0';
1227 --len;
1228 }
1229 else
1230 {
1231 p = sh_util_strdup_l(str_s, len);
1232 }
1233
1234 p = sh_files_C_dequote(p, &len);
1235 if (!p || len == 0)
1236 SL_RETURN((-1), _("sh_files_pushfile"));
1237
1238 if (len >= PATH_MAX)
1239 {
1240 /* Name too long
1241 */
1242 tmp = sh_util_safe_name (p);
1243 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1244 tmp);
1245 SH_FREE(tmp);
1246 SL_RETURN((-1),_("sh_files_pushfile"));
1247 }
1248 else if (p[0] != '/')
1249 {
1250 /* Not an absolute path
1251 */
1252 tmp = sh_util_safe_name (p);
1253 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1254 tmp);
1255 SH_FREE(tmp);
1256 SL_RETURN((-1),_("sh_files_pushfile"));
1257 }
1258 else
1259 {
1260 /* remove a terminating '/', take care of the
1261 * special case of the root directory.
1262 */
1263 if (p[len-1] == '/' && len > 1)
1264 {
1265 p[len-1] = '\0';
1266 --len;
1267 }
1268 }
1269
1270#ifdef HAVE_GLOB_H
1271 if (0 == sh_files_has_metachar(p))
1272 {
1273 sh_files_push_file_int (class, p, len);
1274 }
1275 else
1276 {
1277 sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0);
1278 }
1279
1280#else
1281 sh_files_push_file_int (class, p, len);
1282#endif
1283
1284 SH_FREE(p);
1285 SL_RETURN((0),_("sh_files_pushfile"));
1286}
1287
1288
1289/* ------ directories ----- */
1290
1291int sh_files_is_allignore_int (char * str, zAVLTree * tree)
1292{
1293 dirstack_t * ptr;
1294
1295 SL_ENTER(_("sh_files_is_allignore"));
1296
1297 if (tree)
1298 {
1299 ptr = zAVLSearch(tree, str);
1300 if (ptr)
1301 {
1302 if (ptr->class == SH_LEVEL_ALLIGNORE)
1303 SL_RETURN( 1, _("sh_files_is_allignore"));
1304 else
1305 SL_RETURN( 0, _("sh_files_is_allignore"));
1306 }
1307 }
1308 SL_RETURN( 0, _("sh_files_is_allignore"));
1309}
1310
1311int sh_files_is_allignore (char * str)
1312{
1313 int retval = 0;
1314
1315 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1316 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1317 retval = sh_files_is_allignore_int(str, zdirListOne);
1318
1319 if (NULL != zdirListTwo && retval == 0)
1320 {
1321 retval = sh_files_is_allignore_int(str, zdirListTwo);
1322 }
1323 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1324 return retval;
1325}
1326
1327static void * sh_dummy_ptr;
1328
1329unsigned long sh_dirs_chk (int which)
1330{
1331 zAVLTree * tree;
1332 zAVLCursor cursor;
1333 dirstack_t * ptr;
1334 dirstack_t * dst_ptr;
1335 int status;
1336 volatile unsigned long dcount = 0;
1337 char * tmp;
1338
1339 SL_ENTER(_("sh_dirs_chk"));
1340
1341 sh_dummy_ptr = (void *) &ptr;
1342
1343 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1344 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1345 if (which == 1)
1346 tree = zdirListOne;
1347 else
1348 tree = zdirListTwo;
1349
1350 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
1351 ptr = (dirstack_t *) zAVLNext(&cursor))
1352 {
1353 if (sig_urgent > 0) {
1354 goto out;
1355 }
1356
1357 if (ptr->checked == S_FALSE)
1358 {
1359 SH_MUTEX_LOCK(mutex_zfiles);
1360 /* 28 Aug 2001 check the top level directory
1361 */
1362 status = S_FALSE;
1363 dst_ptr = zAVLSearch(zfileList, ptr->name);
1364 if (dst_ptr)
1365 {
1366 if (dst_ptr->checked == S_FALSE)
1367 {
1368 BREAKEXIT(sh_files_filecheck);
1369 sh_files_filecheck (dst_ptr->class, dst_ptr->check_mask,
1370 ptr->name,
1371 NULL, &status, 0);
1372 dst_ptr->checked = S_TRUE;
1373 status = S_TRUE;
1374 }
1375 else
1376 {
1377 status = S_TRUE;
1378 }
1379 }
1380 SH_MUTEX_UNLOCK(mutex_zfiles);
1381
1382 if (status == S_FALSE)
1383 sh_files_filecheck (ptr->class, ptr->check_mask,
1384 ptr->name, NULL, &status, 0);
1385
1386 BREAKEXIT(sh_files_checkdir);
1387 status = sh_files_checkdir (ptr->class, ptr->check_mask,
1388 ptr->rdepth, ptr->name,
1389 ptr->name);
1390
1391 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1392 {
1393 /* directory is missing
1394 */
1395 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1396 {
1397 if (0 != hashreport_missing(ptr->name,
1398 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1399 ShDFLevel[ptr->class] :
1400 ShDFLevel[SH_ERR_T_DIR])) {
1401 tmp = sh_util_safe_name (ptr->name);
1402 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1403 ShDFLevel[ptr->class] :
1404 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1405 0, MSG_FI_MISS, tmp);
1406 SH_FREE(tmp);
1407 }
1408 }
1409 if (sh.flag.reportonce == S_TRUE)
1410 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1411 }
1412 else
1413 {
1414 /* exists (status >= 0), but was missing (reported == TRUE)
1415 */
1416 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1417 {
1418 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1419#if 0
1420 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1421 * above, which will catch missing directories anyway
1422 */
1423 tmp = sh_util_safe_name (ptr->name);
1424 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1425 ShDFLevel[ptr->class] :
1426 ShDFLevel[SH_ERR_T_DIR],
1427 FIL__, __LINE__, 0, MSG_FI_ADD,
1428 tmp);
1429 SH_FREE(tmp);
1430#endif
1431 }
1432 else if (status == SH_FILE_UNKNOWN)
1433 {
1434 /* catchall
1435 */
1436 tmp = sh_util_safe_name (ptr->name);
1437 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1438 MSG_FI_FAIL,
1439 tmp);
1440 SH_FREE(tmp);
1441 if (sh.flag.checkSum != SH_CHECK_INIT)
1442 sh_hash_set_visited_true(ptr->name);
1443 }
1444
1445 ++dcount;
1446 }
1447 ptr->checked = S_TRUE;
1448 ptr->childs_checked = S_TRUE;
1449 }
1450
1451 if (sig_urgent > 0) {
1452 goto out;
1453 }
1454
1455 }
1456 out:
1457 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1458
1459 SL_RETURN(dcount, _("sh_dirs_chk"));
1460}
1461
1462int sh_files_pushdir_prelink (const char * str_s)
1463{
1464 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1465}
1466
1467int sh_files_pushdir_user0 (const char * str_s)
1468{
1469 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1470}
1471
1472int sh_files_pushdir_user1 (const char * str_s)
1473{
1474 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1475}
1476
1477int sh_files_pushdir_user2 (const char * str_s)
1478{
1479 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1480}
1481
1482int sh_files_pushdir_user3 (const char * str_s)
1483{
1484 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1485}
1486
1487int sh_files_pushdir_user4 (const char * str_s)
1488{
1489 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1490}
1491
1492int sh_files_pushdir_attr (const char * str_s)
1493{
1494 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1495}
1496
1497int sh_files_pushdir_ro (const char * str_s)
1498{
1499 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1500}
1501
1502int sh_files_pushdir_log (const char * str_s)
1503{
1504 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1505}
1506
1507int sh_files_pushdir_glog (const char * str_s)
1508{
1509 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1510}
1511
1512int sh_files_pushdir_noig (const char * str_s)
1513{
1514 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1515}
1516
1517int sh_files_pushdir_allig (const char * str_s)
1518{
1519 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1520}
1521
1522int set_dirList (int which)
1523{
1524 if (which == 2)
1525 which_dirList = SH_LIST_DIR2;
1526 else
1527 which_dirList = SH_LIST_DIR1;
1528 return 0;
1529}
1530
1531int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth)
1532{
1533 zAVLTree * tree;
1534 dirstack_t * new_item_ptr;
1535 char * dirName;
1536 int ret;
1537
1538 SL_ENTER(_("sh_files_push_dir_int"));
1539
1540 dirName = SH_ALLOC(len+1);
1541 sl_strlcpy(dirName, tail, len+1);
1542
1543 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1544
1545 new_item_ptr->name = dirName;
1546 new_item_ptr->class = class;
1547 new_item_ptr->check_mask = sh_files_maskof(class);
1548 new_item_ptr->rdepth = rdepth;
1549 new_item_ptr->checked = S_FALSE;
1550 new_item_ptr->is_reported = 0;
1551 new_item_ptr->childs_checked = S_FALSE;
1552
1553 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1554 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1555 if (which_dirList == SH_LIST_DIR1)
1556 {
1557 tree = zdirListOne;
1558 }
1559 else
1560 {
1561 tree = zdirListTwo;
1562 }
1563
1564 if (tree == NULL)
1565 {
1566 tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1567 if (tree == NULL)
1568 {
1569 (void) safe_logger (0, 0, NULL);
1570 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1571 }
1572 if (which_dirList == SH_LIST_DIR1)
1573 zdirListOne = tree;
1574 else
1575 zdirListTwo = tree;
1576 }
1577
1578 ret = zAVLInsert (tree, new_item_ptr);
1579 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1580
1581 if (-1 == ret)
1582 {
1583 (void) safe_logger (0, 0, NULL);
1584 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1585 }
1586 if (3 == ret)
1587 {
1588 if (sh.flag.started != S_TRUE)
1589 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1590 dirName);
1591 SH_FREE(dirName);
1592 SH_FREE(new_item_ptr);
1593 new_item_ptr = NULL;
1594 }
1595 else
1596 {
1597 unsigned long mask = sh_files_maskof(class);
1598 if (MODI_AUDIT_ENABLED(mask))
1599 {
1600 sh_audit_mark(tail);
1601 }
1602 }
1603 SL_RETURN(0, _("sh_files_push_dir_int"));
1604}
1605
1606static int sh_files_pushdir (int class, const char * str_s)
1607{
1608 char * tmp;
1609 size_t len;
1610 int rdepth = 0;
1611 char * tail = NULL;
1612 char * p;
1613
1614 SL_ENTER(_("sh_files_pushdir"));
1615
1616 if (sh.flag.opts == 1) {
1617 sh_files_delfilestack ();
1618 sh_files_deldirstack ();
1619 sh_files_delglobstack ();
1620 }
1621
1622 if (str_s == NULL || str_s[0] == '\0')
1623 SL_RETURN((-1),_("sh_files_pushdir"));
1624
1625 len = sl_strlen(str_s);
1626
1627 if ( (str_s[0] == '"' && str_s[len-1] == '"' ) ||
1628 (str_s[0] == '\'' && str_s[len-1] == '\'') )
1629 {
1630 if (len < 3)
1631 SL_RETURN((-1),_("sh_files_pushdir"));
1632 --len;
1633 p = sh_util_strdup_l(&str_s[1], len);
1634 p[len-1] = '\0';
1635 --len;
1636 }
1637 else
1638 {
1639 p = sh_util_strdup_l(str_s, len);
1640 }
1641
1642 p = sh_files_C_dequote(p, &len);
1643 if (!p || len == 0)
1644 SL_RETURN((-1), _("sh_files_pushdir"));
1645
1646 if (p[0] != '/')
1647 {
1648 rdepth = strtol(p, &tail, 10);
1649 if (tail == p)
1650 {
1651 SH_FREE(p);
1652 SL_RETURN((-1), _("sh_files_pushdir"));
1653 }
1654 }
1655 else
1656 tail = p;
1657
1658
1659 if (tail == p)
1660 {
1661 /* Setting to an invalid number will force MaxRecursionLevel,
1662 * see sh_files_setrec_int()
1663 */
1664 rdepth = (-2);
1665 }
1666 else if ( (rdepth < (-1) || rdepth > 99) ||
1667 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1668 {
1669 SH_FREE(p);
1670 SL_RETURN((-1), _("sh_files_pushdir"));
1671 }
1672
1673 len = sl_strlen(tail);
1674
1675 if (len >= PATH_MAX)
1676 {
1677 tmp = sh_util_safe_name (tail);
1678 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1679 tmp);
1680 SH_FREE(tmp);
1681 SH_FREE(p);
1682 SL_RETURN((-1), _("sh_files_pushdir"));
1683 }
1684 else if (len < 1)
1685 {
1686 SH_FREE(p);
1687 SL_RETURN((-1), _("sh_files_pushdir"));
1688 }
1689 else if (tail[0] != '/')
1690 {
1691 tmp = sh_util_safe_name (tail);
1692 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1693 tmp);
1694 SH_FREE(tmp);
1695 SH_FREE(p);
1696 SL_RETURN((-1), _("sh_files_pushdir"));
1697 }
1698 else
1699 {
1700 if (tail[len-1] == '/' && len > 1)
1701 {
1702 tail[len-1] = '\0';
1703 --len;
1704 }
1705 }
1706
1707#ifdef HAVE_GLOB_H
1708 if (0 == sh_files_has_metachar(tail))
1709 {
1710 sh_files_push_dir_int (class, tail, len, rdepth);
1711 }
1712 else
1713 {
1714 sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0);
1715 }
1716#else
1717 sh_files_push_dir_int (class, tail, len, rdepth);
1718#endif
1719
1720 SH_FREE(p);
1721 SL_RETURN((0), _("sh_files_pushdir"));
1722}
1723
1724/**
1725struct sh_dirent {
1726 char * sh_d_name;
1727 struct sh_dirent * next;
1728};
1729**/
1730
1731void kill_sh_dirlist (struct sh_dirent * dirlist)
1732{
1733 struct sh_dirent * this;
1734
1735 while (dirlist)
1736 {
1737 this = dirlist->next;
1738 SH_FREE(dirlist->sh_d_name);
1739 SH_FREE(dirlist);
1740 dirlist = this;
1741 }
1742 return;
1743}
1744
1745/* -- add an entry to a directory listing
1746 */
1747struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1748 struct sh_dirent * dirlist)
1749{
1750 struct sh_dirent * this;
1751 size_t len;
1752
1753 if (thisEntry == NULL)
1754 return dirlist;
1755
1756 len = sl_strlen(thisEntry->d_name);
1757 if (len == 0)
1758 return dirlist;
1759 ++len;
1760
1761 this = SH_ALLOC(sizeof(struct sh_dirent));
1762 if (!this)
1763 return dirlist;
1764
1765 this->sh_d_name = SH_ALLOC(len);
1766 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1767
1768 this->next = dirlist;
1769 return this;
1770}
1771
1772static int sh_check_hardlinks = S_TRUE;
1773
1774/* Simply sets our boolean as to whether this check is active
1775 */
1776int sh_files_check_hardlinks (const char * opt)
1777{
1778 int i;
1779 SL_ENTER(_("sh_files_check_hardlinks"));
1780 i = sh_util_flagval(opt, &sh_check_hardlinks);
1781 SL_RETURN(i, _("sh_files_check_hardlinks"));
1782}
1783
1784struct sh_hle_struct {
1785 long offset;
1786 char * path;
1787 struct sh_hle_struct * next;
1788};
1789
1790static struct sh_hle_struct * sh_hl_exc = NULL;
1791
1792int sh_files_hle_reg (const char * str)
1793{
1794 long offset;
1795 size_t len;
1796 char * path;
1797
1798 struct sh_hle_struct * tmp = sh_hl_exc;
1799
1800 SL_ENTER(_("sh_files_hle_reg"));
1801
1802 /* Free the linked list if called with NULL argument
1803 */
1804 if (str == NULL)
1805 {
1806 while (tmp)
1807 {
1808 sh_hl_exc = tmp->next;
1809 SH_FREE(tmp->path);
1810 SH_FREE(tmp);
1811 tmp = sh_hl_exc;
1812 }
1813 sh_hl_exc = NULL;
1814 SL_RETURN(0, _("sh_files_hle_reg"));
1815 }
1816
1817 /* We expect 'offset:/path'
1818 */
1819 offset = strtol(str, &path, 0);
1820 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1821 {
1822 SL_RETURN(-1, _("sh_files_hle_reg"));
1823 }
1824 ++path;
1825 len = 1 + sl_strlen(path);
1826
1827 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1828 tmp->path = SH_ALLOC(len);
1829 sl_strlcpy (tmp->path, path, len);
1830 tmp->offset = offset;
1831 tmp->next = sh_hl_exc;
1832 sh_hl_exc = tmp;
1833
1834 SL_RETURN(0, _("sh_files_hle_reg"));
1835}
1836
1837#if !defined(HOST_IS_DARWIN)
1838static int sh_files_hle_test (int offset, char * path)
1839{
1840 struct sh_hle_struct * tmp = sh_hl_exc;
1841
1842 SL_ENTER(_("sh_files_hle_reg"));
1843
1844 while(tmp)
1845 {
1846 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1847 {
1848 SL_RETURN(0, _("sh_files_hle_test"));
1849 }
1850 tmp = tmp->next;
1851 }
1852 SL_RETURN(-1, _("sh_files_hle_test"));
1853}
1854#endif
1855
1856static void * sh_dummy_dirlist;
1857
1858/* -- Check a single directory and its content. Does not
1859 * check the directory inode itself.
1860 */
1861int sh_files_checkdir (int iclass, unsigned long check_mask,
1862 int idepth, char * iname,
1863 char * relativeName)
1864{
1865 struct sh_dirent * dirlist;
1866 struct sh_dirent * dirlist_orig;
1867
1868 DIR * thisDir = NULL;
1869 struct dirent * thisEntry;
1870 int status;
1871 int dummy = S_FALSE;
1872 dir_type * theDir;
1873 ShFileType checkit;
1874 static unsigned int state = 1;
1875
1876 file_type * theFile;
1877 char * tmpname;
1878 char * tmpcat;
1879 char errbuf[SH_ERRBUF_SIZE];
1880
1881 int rdepth = 0;
1882 int class = 0;
1883 int rdepth_next;
1884 int class_next;
1885 volatile int file_class_next;
1886 unsigned long check_mask_next;
1887 volatile unsigned long file_check_mask_next;
1888
1889 volatile int checked_flag = S_FALSE;
1890 volatile int cchecked_flag = S_FALSE;
1891
1892 dirstack_t * dst_ptr;
1893 dirstack_t * tmp_ptr;
1894
1895 int hardlink_num = 0;
1896#if !defined(HOST_IS_DARWIN)
1897 size_t len;
1898#endif
1899
1900 SL_ENTER(_("sh_files_checkdir"));
1901
1902 sh_dummy_dirlist = (void *) &dirlist;
1903
1904 if (sig_urgent > 0) {
1905 SL_RETURN((0), _("sh_files_checkdir"));
1906 }
1907
1908 if (iname == NULL || idepth < (-1))
1909 SL_RETURN((-1), _("sh_files_checkdir"));
1910
1911 if (idepth < 0)
1912 {
1913 /* hash_remove_tree (iname); */
1914 SL_RETURN((0), _("sh_files_checkdir"));
1915 }
1916
1917 rdepth = idepth;
1918 class = iclass;
1919
1920 tmpname = sh_util_safe_name (iname);
1921
1922 /* ---- check for obscure name ----
1923 */
1924 if (iclass != SH_LEVEL_ALLIGNORE)
1925 {
1926 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1927 }
1928
1929 if (flag_err_info == SL_TRUE)
1930 {
1931 char pstr[32];
1932
1933 sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr));
1934 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname);
1935 }
1936
1937 /* ---- check input ----
1938 */
1939 if ( sl_strlen(iname) >= PATH_MAX)
1940 {
1941 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1942 MSG_FI_2LONG,
1943 tmpname);
1944 SH_FREE(tmpname);
1945 SL_RETURN((-1), _("sh_files_checkdir"));
1946 }
1947
1948 /* ---- check for absolute path ---- */
1949 if ( iname[0] != '/')
1950 {
1951 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1952 MSG_FI_NOPATH,
1953 tmpname);
1954 SH_FREE(tmpname);
1955 SL_RETURN((-1), _("sh_files_checkdir"));
1956 }
1957
1958 /* ---- stat the directory ----
1959 */
1960 theFile = SH_ALLOC(sizeof(file_type));
1961 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
1962 theFile->attr_string = NULL;
1963 theFile->link_path = NULL;
1964 theFile->check_mask = check_mask;
1965
1966 (void) relativeName;
1967 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1968 iname,
1969 theFile, NULL, iclass);
1970
1971 if ((sig_termfast == 1) || (sig_terminate == 1))
1972 {
1973 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1974 if (theFile->link_path) SH_FREE(theFile->link_path);
1975 SH_FREE(theFile);
1976 SL_RETURN((0), _("sh_files_checkdir"));
1977 }
1978
1979 if (status == -1)
1980 {
1981 SH_FREE(tmpname);
1982 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1983 if (theFile->link_path) SH_FREE(theFile->link_path);
1984 SH_FREE(theFile);
1985 SL_RETURN((-1), _("sh_files_checkdir"));
1986 }
1987
1988 if (theFile->c_mode[0] != 'd')
1989 {
1990 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1991 MSG_FI_NODIR,
1992 tmpname);
1993 SH_FREE(tmpname);
1994 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1995 if (theFile->link_path) SH_FREE(theFile->link_path);
1996 SH_FREE(theFile);
1997 SL_RETURN((-1), _("sh_files_checkdir"));
1998 }
1999
2000 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
2001 {
2002 sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
2003 iclass, check_mask, SH_INOTIFY_DIR, idepth);
2004 }
2005
2006 hardlink_num = theFile->hardlinks;
2007
2008 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2009 if (theFile->link_path) SH_FREE(theFile->link_path);
2010 SH_FREE(theFile);
2011
2012 /* ---- open directory for reading ----
2013 *
2014 * opendir() will fail with ENOTDIR if the path has been changed
2015 * to a non-directory in between lstat() and opendir().
2016 */
2017 thisDir = opendir (iname);
2018
2019 if (thisDir == NULL)
2020 {
2021 status = errno;
2022 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2023 MSG_E_OPENDIR,
2024 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
2025 SH_FREE(tmpname);
2026 SL_RETURN((-1), _("sh_files_checkdir"));
2027 }
2028
2029 theDir = SH_ALLOC(sizeof(dir_type));
2030
2031 theDir->NumRegular = 0;
2032 theDir->NumDirs = 0;
2033 theDir->NumSymlinks = 0;
2034 theDir->NumFifos = 0;
2035 theDir->NumSockets = 0;
2036 theDir->NumCDev = 0;
2037 theDir->NumBDev = 0;
2038 theDir->NumDoor = 0;
2039 theDir->NumPort = 0;
2040 theDir->NumAll = 0;
2041 theDir->TotalBytes = 0;
2042 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
2043
2044
2045 /* ---- read ----
2046 */
2047 SH_MUTEX_LOCK(mutex_readdir);
2048
2049 dirlist = NULL;
2050 dirlist_orig = NULL;
2051
2052 do {
2053 thisEntry = readdir (thisDir);
2054 if (thisEntry != NULL)
2055 {
2056 ++theDir->NumAll;
2057 if (sl_strcmp (thisEntry->d_name, ".") == 0)
2058 {
2059 ++theDir->NumDirs;
2060 continue;
2061 }
2062 if (sl_strcmp (thisEntry->d_name, "..") == 0)
2063 {
2064 ++theDir->NumDirs;
2065 continue;
2066 }
2067 dirlist = addto_sh_dirlist (thisEntry, dirlist);
2068 }
2069 } while (thisEntry != NULL);
2070
2071 SH_MUTEX_UNLOCK(mutex_readdir);
2072
2073 closedir (thisDir);
2074
2075 ++sh.statistics.dirs_checked;
2076
2077 dirlist_orig = dirlist;
2078
2079 do {
2080
2081 /* If the directory is empty, dirlist = NULL
2082 */
2083 if (!dirlist)
2084 break;
2085
2086 if (sig_termfast == 1)
2087 {
2088 SH_FREE(theDir);
2089 SL_RETURN((0), _("sh_files_checkdir"));
2090 }
2091
2092 BREAKEXIT(sh_derr);
2093
2094#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2095 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
2096#else
2097 if (0 == state * (rand() % 5)) (void) sh_derr();
2098#endif
2099
2100 /* ---- Check the file. ----
2101 */
2102 tmpcat = SH_ALLOC(PATH_MAX);
2103 sl_strlcpy(tmpcat, iname, PATH_MAX);
2104 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
2105 sl_strlcat(tmpcat, "/", PATH_MAX);
2106 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
2107
2108 rdepth_next = rdepth - 1;
2109 class_next = class;
2110 check_mask_next = check_mask;
2111 file_class_next = class;
2112 file_check_mask_next = check_mask;
2113 checked_flag = -1;
2114 cchecked_flag = -1;
2115
2116 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
2117 * this fixes the problem that the directory special file
2118 * is checked with the policy of the parent directory
2119 */
2120 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2121 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2122 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2123
2124 if (dst_ptr)
2125 {
2126 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2127 * this fixes the problem that a policy for the directory
2128 * inode erroneously becomes a policy for the directory itself.
2129 */
2130 file_class_next = dst_ptr->class;
2131 file_check_mask_next = dst_ptr->check_mask;
2132 checked_flag = dst_ptr->checked;
2133 cchecked_flag = dst_ptr->childs_checked;
2134 }
2135
2136 if (checked_flag == -1)
2137 {
2138 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2139
2140 if (dst_ptr)
2141 {
2142 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2143 * this fixes the problem that a policy for the directory
2144 * inode erroneously becomes a policy for the directory itself.
2145 */
2146 file_class_next = dst_ptr->class;
2147 file_check_mask_next = dst_ptr->check_mask;
2148 checked_flag = dst_ptr->checked;
2149 cchecked_flag = dst_ptr->childs_checked;
2150 }
2151 }
2152 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2153
2154 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2155 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2156
2157 if (dst_ptr)
2158 {
2159 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2160 * this fixes the problem that a policy for the directory
2161 * inode erroneously becomes a policy for the directory itself.
2162 */
2163 file_class_next = dst_ptr->class;
2164 file_check_mask_next = dst_ptr->check_mask;
2165 checked_flag = dst_ptr->checked;
2166 /* not set, hence always FALSE */
2167 /* cchecked_flag = dst_ptr->childs_checked; */
2168
2169 if (checked_flag != S_TRUE)
2170 {
2171 /* -- need to check the file itself --
2172 */
2173 if (sh.flag.reportonce == S_TRUE)
2174 dummy = dst_ptr->is_reported;
2175 }
2176 }
2177 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2178
2179 /* ---- Has been checked already. ----
2180 */
2181 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2182 {
2183 /* Mar 11 2004 get ftype for complete directory count
2184 */
2185 checkit = sh_unix_get_ftype(tmpcat);
2186 if (checkit == SH_FILE_DIRECTORY)
2187 {
2188 ++theDir->NumDirs;
2189 }
2190 SH_FREE(tmpcat);
2191 dirlist = dirlist->next;
2192 continue;
2193 }
2194
2195 /* --- May be true, false, or not found. ---
2196 */
2197 if (checked_flag == S_TRUE)
2198 {
2199 /* -- need only the file type --
2200 */
2201 checkit = sh_unix_get_ftype(tmpcat);
2202 }
2203 else
2204 {
2205 /* -- need to check the file itself --
2206 */
2207 /* -- moved up --
2208 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
2209 * dummy = dst_ptr->is_reported;
2210 */
2211
2212 checkit = sh_files_filecheck (file_class_next, file_check_mask_next,
2213 iname,
2214 dirlist->sh_d_name,
2215 &dummy, 0);
2216
2217
2218 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2219 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2220
2221 if (dst_ptr && checked_flag == S_FALSE)
2222 dst_ptr->checked = S_TRUE;
2223
2224 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2225 */
2226 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2227 dst_ptr->is_reported = dummy;
2228
2229 if (dst_ptr)
2230 dst_ptr->childs_checked = S_TRUE;
2231 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2232 }
2233
2234 if (checkit == SH_FILE_REGULAR)
2235 ++theDir->NumRegular;
2236
2237 else if (checkit == SH_FILE_DIRECTORY)
2238 {
2239 ++theDir->NumDirs;
2240
2241 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2242 {
2243 rdepth_next = rdepth - 1;
2244
2245 /* check whether the new directory is in the
2246 * list with a recursion depth already defined
2247 */
2248 checked_flag = -1;
2249 cchecked_flag = -1;
2250
2251 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2252 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2253 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2254
2255 if (tmp_ptr)
2256 {
2257 TPT((0, FIL__, __LINE__,
2258 _("msg=<%s -> recursion depth %d\n>"),
2259 tmp_ptr->name, tmp_ptr->rdepth));
2260 rdepth_next = tmp_ptr->rdepth;
2261 class_next = tmp_ptr->class;
2262 check_mask_next = tmp_ptr->check_mask;
2263 /* 28. Aug 2001 reversed
2264 */
2265 cchecked_flag = tmp_ptr->childs_checked;
2266 checked_flag = tmp_ptr->checked;
2267 }
2268
2269 if (checked_flag == -1)
2270 {
2271 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2272
2273 if (tmp_ptr)
2274 {
2275 TPT((0, FIL__, __LINE__,
2276 _("msg=<%s -> recursion depth %d\n>"),
2277 tmp_ptr->name, tmp_ptr->rdepth));
2278 rdepth_next = tmp_ptr->rdepth;
2279 class_next = tmp_ptr->class;
2280 check_mask_next = tmp_ptr->check_mask;
2281 /* 28. Aug 2001 reversed
2282 */
2283 cchecked_flag = tmp_ptr->childs_checked;
2284 checked_flag = tmp_ptr->checked;
2285 }
2286 }
2287
2288 if (tmp_ptr && cchecked_flag == S_FALSE)
2289 {
2290 tmp_ptr->childs_checked = S_TRUE;
2291 /*
2292 * 04. Feb 2006 avoid double checking
2293 */
2294 tmp_ptr->checked = S_TRUE;
2295 }
2296 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2297
2298 if (cchecked_flag == S_FALSE)
2299 {
2300 sh_files_checkdir (class_next, check_mask_next, rdepth_next,
2301 tmpcat, dirlist->sh_d_name);
2302 /*
2303 tmp_ptr->childs_checked = S_TRUE;
2304 tmp_ptr->checked = S_TRUE;
2305 */
2306 }
2307 else if (checked_flag == -1)
2308 sh_files_checkdir (class_next, check_mask_next, rdepth_next,
2309 tmpcat, dirlist->sh_d_name);
2310
2311 }
2312 }
2313
2314 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2315 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2316 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2317 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2318 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2319 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2320 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2321
2322 SH_FREE(tmpcat);
2323
2324 if ((sig_termfast == 1) || (sig_terminate == 1))
2325 {
2326 SH_FREE(theDir);
2327 SL_RETURN((0), _("sh_files_checkdir"));
2328 }
2329
2330 dirlist = dirlist->next;
2331
2332 /* -- moved up, only affects zfileList anyway
2333 * if (dst_ptr)
2334 * dst_ptr->childs_checked = S_TRUE;
2335 */
2336
2337 } while (dirlist != NULL);
2338
2339 if (flag_err_info == SL_TRUE)
2340 {
2341 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2342 theDir->NumDirs,
2343 theDir->NumRegular,
2344 theDir->NumSymlinks,
2345 theDir->NumFifos,
2346 theDir->NumSockets,
2347 theDir->NumCDev,
2348 theDir->NumBDev);
2349 }
2350
2351 kill_sh_dirlist (dirlist_orig);
2352
2353#if !defined(HOST_IS_DARWIN)
2354 /*
2355 * Hardlink check; not done on MacOS X because of resource forks
2356 */
2357 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2358 {
2359 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2360 {
2361 len = strlen(tmpname);
2362 if (sl_ok_adds(len, 256))
2363 len += 256;
2364 tmpcat = SH_ALLOC(len);
2365 sl_snprintf(tmpcat, len,
2366 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2367 tmpname, theDir->NumDirs, hardlink_num);
2368 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2369 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2370 SH_FREE(tmpcat);
2371 }
2372 }
2373#endif
2374
2375 SH_FREE(tmpname);
2376 SH_FREE(theDir);
2377
2378 SL_RETURN((0), _("sh_files_checkdir"));
2379}
2380
2381int get_the_fd (SL_TICKET ticket);
2382
2383static int sh_use_rsrc = S_FALSE;
2384
2385int sh_files_use_rsrc(const char * str)
2386{
2387 return sh_util_flagval(str, &sh_use_rsrc);
2388}
2389
2390static void * sh_dummy_fileName;
2391static void * sh_dummy_tmpname;
2392static void * sh_dummy_tmpdir;
2393
2394ShFileType sh_files_filecheck (int class, unsigned long check_mask,
2395 const char * dirName,
2396 const char * infileName,
2397 int * reported,
2398 int rsrcflag)
2399{
2400 /* 28 Aug 2001 allow NULL fileName
2401 */
2402 char * fullpath;
2403 char fileHash[2*(KEY_LEN + 1)];
2404 int status;
2405 file_type * theFile;
2406 char * tmpdir;
2407 char * tmpname;
2408 const char * fileName;
2409 struct utimbuf utime_buf;
2410 static unsigned int state = 1;
2411 char sc;
2412
2413 SL_ENTER(_("sh_files_filecheck"));
2414
2415 fullpath = SH_ALLOC(PATH_MAX);
2416 theFile = SH_ALLOC(sizeof(file_type));
2417
2418 /* Take the address to keep gcc from putting it into a register.
2419 * Avoids the 'clobbered by longjmp' warning.
2420 */
2421 sh_dummy_fileName = (void *) &fileName;
2422 sh_dummy_tmpname = (void *) &tmpname;
2423 sh_dummy_tmpdir = (void *) &tmpdir;
2424
2425 BREAKEXIT(sh_derr);
2426
2427#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2428 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
2429#else
2430 if (0 == state * (rand() % 2)) (void) sh_derr();
2431#endif
2432
2433 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2434 && (infileName[0] == '/') && (infileName[1] == '\0'))
2435 {
2436 fileName = NULL;
2437 }
2438 else
2439 {
2440 fileName = infileName;
2441 }
2442
2443 /* fileName may be NULL if this is a directory
2444 */
2445 if (dirName == NULL /* || fileName == NULL */)
2446 {
2447 SH_MUTEX_LOCK(mutex_thread_nolog);
2448 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2449 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2450 SH_FREE(fullpath);
2451 SH_FREE(theFile);
2452 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2453 }
2454
2455 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2456 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2457 fileName, S_FALSE)))
2458 {
2459 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2460 {
2461 tmpname = sh_util_safe_name (fileName);
2462 SH_MUTEX_LOCK(mutex_thread_nolog);
2463 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2464 MSG_FI_OBSC2,
2465 "", tmpname);
2466 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2467 SH_FREE(tmpname);
2468 }
2469 else
2470 {
2471 tmpdir = sh_util_safe_name (dirName);
2472 tmpname = sh_util_safe_name (fileName);
2473 SH_MUTEX_LOCK(mutex_thread_nolog);
2474 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2475 MSG_FI_OBSC2,
2476 tmpdir, tmpname);
2477 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2478 SH_FREE(tmpname);
2479 SH_FREE(tmpdir);
2480 }
2481 }
2482
2483 /* sh_files_fullpath accepts NULL fileName
2484 */
2485 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2486 {
2487 tmpdir = sh_util_safe_name (dirName);
2488 tmpname = sh_util_safe_name (fileName);
2489 SH_MUTEX_LOCK(mutex_thread_nolog);
2490 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2491 MSG_FI_2LONG2,
2492 tmpdir, tmpname);
2493 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2494 SH_FREE(tmpname);
2495 SH_FREE(tmpdir);
2496 SH_FREE(fullpath);
2497 SH_FREE(theFile);
2498 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2499 }
2500
2501
2502 /* stat the file and determine checksum (if a regular file)
2503 */
2504 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2505 theFile->check_mask = check_mask /* sh_files_maskof(class) */;
2506 theFile->file_reported = (*reported);
2507 theFile->attr_string = NULL;
2508 theFile->link_path = NULL;
2509
2510 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2511
2512 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2513 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2514 fileName,
2515 theFile, fileHash, class);
2516
2517 if (status != 0)
2518 {
2519 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2520 fullpath, status));
2521 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2522 sh_hash_set_visited_true (fullpath);
2523 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2524 if (theFile->link_path) SH_FREE(theFile->link_path);
2525 SH_FREE(fullpath);
2526 SH_FREE(theFile);
2527 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2528 }
2529
2530 if (sig_termfast == 1) {
2531 goto ret_point;
2532 }
2533
2534 /* report
2535 */
2536 if ((flag_err_debug == SL_TRUE) && (theFile->c_mode[0] == '-'))
2537 {
2538 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2539 SH_MUTEX_LOCK(mutex_thread_nolog);
2540 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2541 fileHash, tmpname);
2542 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2543 SH_FREE(tmpname);
2544 }
2545 ++sh.statistics.files_checked;
2546
2547 if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */)
2548 {
2549 sh_hash_pushdata (theFile, fileHash);
2550 }
2551 else if (sh.flag.checkSum == SH_CHECK_CHECK
2552 /* && theFile.c_mode[0] == '-' */
2553 /* && class != SH_LEVEL_ALLIGNORE */
2554 )
2555 {
2556 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2557 }
2558
2559 (*reported) = theFile->file_reported;
2560
2561 /* reset the access time
2562 */
2563 if (class == SH_LEVEL_NOIGNORE && (theFile->check_mask & MODI_ATM) != 0)
2564 {
2565 utime_buf.actime = (time_t) theFile->atime;
2566 utime_buf.modtime = (time_t) theFile->mtime;
2567#if !defined(O_NOATIME)
2568 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2569#endif
2570 }
2571
2572#if defined(HOST_IS_DARWIN)
2573 /*
2574 * Check for resource fork
2575 */
2576 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2577 {
2578 int dummy;
2579 static int rsrc_init = 0;
2580 static char rsrc[17];
2581 char * testpath = SH_ALLOC(PATH_MAX);
2582
2583 if (rsrc_init == 0) {
2584 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2585 rsrc_init = 1;
2586 }
2587 sl_strlcpy (testpath, fullpath, PATH_MAX);
2588 sl_strlcat (testpath, "/", PATH_MAX);
2589 sl_strlcat (testpath, rsrc, PATH_MAX);
2590
2591 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2592 {
2593 if (S_TRUE == sh_unix_file_exists (testpath))
2594 {
2595 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
2596 }
2597 }
2598 SH_FREE(testpath);
2599 }
2600#else
2601 (void) rsrcflag; /* avoid compiler warning */
2602#endif
2603
2604 ret_point:
2605
2606 sc = theFile->c_mode[0];
2607
2608 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2609 if (theFile->link_path) SH_FREE(theFile->link_path);
2610 SH_FREE(fullpath);
2611 SH_FREE(theFile);
2612
2613 switch (sc)
2614 {
2615 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2616 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2617 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2618 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2619 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2620 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2621 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2622 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2623 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2624 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2625 }
2626
2627 /* notreached */
2628}
2629
2630/* concatenate statpath = testdir"/"d_name
2631 */
2632static int sh_files_fullpath (const char * testdir, const char * d_name,
2633 char * statpath)
2634{
2635 int llen = 0;
2636
2637 SL_ENTER(_("sh_files_fullpath"));
2638
2639 if (testdir != NULL)
2640 {
2641 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2642 SL_RETURN((-1),_("sh_files_fullpath"));
2643 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2644 }
2645 if (d_name != NULL)
2646 {
2647 if (llen > 1 || statpath[0] != '/')
2648 sl_strlcat(statpath, "/", PATH_MAX);
2649 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2650 SL_RETURN((-1),_("sh_files_fullpath"));
2651 sl_strlcat(statpath, d_name, PATH_MAX);
2652 }
2653 if (statpath == NULL)
2654 SL_RETURN((-1),_("sh_files_fullpath"));
2655 SL_RETURN((0),_("sh_files_fullpath"));
2656}
2657
2658/* -----------------------------------
2659 * Routines required for inotify
2660 * -----------------------------------
2661 */
2662int sh_files_search_dir(char * name, int * class,
2663 unsigned long *check_mask, int *reported,
2664 int * rdepth)
2665{
2666 int retval = 0;
2667#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2668 sh_globstack_t * testPattern;
2669 zAVLCursor cursor;
2670#endif
2671 dirstack_t * item;
2672
2673 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2674 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2675
2676 item = zAVLSearch(zdirListOne, name);
2677
2678 if (item)
2679 {
2680 *check_mask = item->check_mask;
2681 *class = item->class;
2682 *reported = item->is_reported;
2683 *rdepth = item->rdepth;
2684 item->checked = S_FALSE;
2685 item->childs_checked = S_FALSE;
2686 item->is_reported = S_FALSE;
2687 retval = 1;
2688 goto out;
2689 }
2690
2691 item = zAVLSearch(zdirListTwo, name);
2692
2693 if (item)
2694 {
2695 *check_mask = item->check_mask;
2696 *class = item->class;
2697 *reported = item->is_reported;
2698 *rdepth = item->rdepth;
2699 item->checked = S_FALSE;
2700 item->childs_checked = S_FALSE;
2701 item->is_reported = S_FALSE;
2702 retval = 1;
2703 goto out;
2704 }
2705
2706#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2707 SH_MUTEX_LOCK(mutex_zglob);
2708 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2709 testPattern;
2710 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2711 {
2712 if (testPattern->type == SH_LIST_DIR1 ||
2713 testPattern->type == SH_LIST_DIR2)
2714 {
2715 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
2716 {
2717 *check_mask = testPattern->check_mask;
2718 *class = testPattern->class;
2719 *rdepth = testPattern->rdepth;
2720 retval = 1;
2721 break;
2722 }
2723
2724 }
2725 }
2726 SH_MUTEX_UNLOCK(mutex_zglob);
2727#endif
2728 out:
2729 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2730 return retval;
2731}
2732
2733int sh_files_search_file(char * name, int * class,
2734 unsigned long *check_mask, int *reported)
2735{
2736 int retval = 0;
2737#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2738 sh_globstack_t * testPattern;
2739 zAVLCursor cursor;
2740#endif
2741 dirstack_t * item;
2742
2743 SH_MUTEX_LOCK(mutex_zfiles);
2744 item = zAVLSearch(zfileList, name);
2745
2746 if (item)
2747 {
2748 *check_mask = item->check_mask;
2749 *class = item->class;
2750 *reported = item->is_reported;
2751 retval = 1;
2752 goto out;
2753 }
2754
2755#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2756 SH_MUTEX_LOCK(mutex_zglob);
2757 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2758 testPattern;
2759 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2760 {
2761 if (testPattern->type == SH_LIST_FILE)
2762 {
2763 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
2764 {
2765 *check_mask = testPattern->check_mask;
2766 *class = testPattern->class;
2767 retval = 1;
2768 break;
2769 }
2770
2771 }
2772 }
2773 SH_MUTEX_UNLOCK(mutex_zglob);
2774#endif
2775 out:
2776 SH_MUTEX_UNLOCK(mutex_zfiles);
2777 return retval;
2778}
2779
2780void sh_files_set_file_reported(const char * name)
2781{
2782 dirstack_t * item;
2783
2784 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2785 item = zAVLSearch(zfileList, name);
2786
2787 if (item)
2788 {
2789 if (sh.flag.reportonce == S_TRUE)
2790 SET_SH_FFLAG_REPORTED(item->is_reported);
2791 }
2792 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2793 return;
2794}
2795
2796void sh_files_clear_file_reported(const char * name)
2797{
2798 dirstack_t * item;
2799
2800 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2801 item = zAVLSearch(zfileList, name);
2802
2803 if (item)
2804 {
2805 CLEAR_SH_FFLAG_REPORTED(item->is_reported);
2806 }
2807 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2808 return;
2809}
2810
2811/* -----------------------------------
2812 *
2813 * The following two routines serve to
2814 * verify that the user has selected
2815 * a proper setup for file policies.
2816 *
2817 * -----------------------------------
2818 */
2819static int check_file(char * name)
2820{
2821 dirstack_t * pfilL;
2822 zAVLCursor cursor;
2823 volatile int retval = -1;
2824
2825 SL_ENTER(_("check_file"));
2826
2827 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2828 SL_RETURN(0, _("check_file"));
2829
2830 SH_MUTEX_LOCK(mutex_zfiles);
2831 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2832 pfilL = (dirstack_t *) zAVLNext (&cursor))
2833 {
2834 if (0 == strcmp(name, pfilL->name) &&
2835 (pfilL->check_mask & MODI_ATM) == 0 &&
2836 (pfilL->check_mask & MODI_CTM) == 0 &&
2837 (pfilL->check_mask & MODI_MTM) == 0)
2838 {
2839 retval = 0;
2840 break;
2841 }
2842 }
2843 SH_MUTEX_UNLOCK(mutex_zfiles);
2844
2845 SL_RETURN(retval, _("check_file"));
2846}
2847
2848static void * sh_dummy_pdirL;
2849
2850int sh_files_test_setup_int (zAVLTree * tree)
2851{
2852 int dlen, flen;
2853 zAVLCursor cursor1;
2854 zAVLCursor cursor2;
2855
2856 dirstack_t * pdirL;
2857 dirstack_t * pfilL;
2858
2859 SL_ENTER(_("sh_files_test_setup"));
2860
2861 sh_dummy_pdirL = (void *) &pdirL;
2862
2863 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2864 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2865 {
2866 dlen = strlen(pdirL->name);
2867
2868 SH_MUTEX_LOCK(mutex_zfiles);
2869 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2870 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2871 {
2872 flen = strlen(pfilL->name);
2873
2874 /* check whether file is in tree of dir
2875 */
2876 if ((pfilL->class == SH_LEVEL_READONLY) ||
2877 (pfilL->class == SH_LEVEL_NOIGNORE))
2878 {
2879 ; /* do nothing */
2880 }
2881 else
2882 {
2883 if ((flen > (dlen+1)) &&
2884 (pfilL->name[dlen] == '/') &&
2885 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2886 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2887 {
2888 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2889 (pdirL->check_mask & MODI_MTM) != 0 ||
2890 (pdirL->check_mask & MODI_CTM) != 0)
2891 {
2892 if (check_file (pdirL->name) != 0)
2893 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2894 pdirL->name, pfilL->name);
2895 }
2896 }
2897 }
2898 }
2899 SH_MUTEX_UNLOCK(mutex_zfiles);
2900 }
2901
2902 SL_RETURN((0), _("sh_files_test_setup"));
2903}
2904
2905int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2906{
2907 int retval = 0;
2908 zAVLCursor cursor;
2909 dirstack_t * first;
2910
2911 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2912 first = (dirstack_t *) zAVLNext (&cursor))
2913 {
2914
2915 if (NULL != zAVLSearch(secondList, first->name))
2916 {
2917 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2918 first->name);
2919 retval = 1;
2920 }
2921 }
2922 return retval;
2923}
2924
2925extern void aud_exit (const char * file, int line, int fd);
2926
2927int sh_files_test_setup ()
2928{
2929 int retval;
2930
2931 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2932 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2933 /* Test for modifications allowed in ReadOnly directory
2934 */
2935 sh_files_test_setup_int (zdirListOne);
2936 sh_files_test_setup_int (zdirListTwo);
2937
2938 /* Test for files/dirz defined twice
2939 */
2940 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2941 if (retval != 0)
2942 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2943
2944 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2945 if (retval != 0)
2946 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2947 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2948
2949 return 0;
2950}
2951
2952#endif
2953
2954#ifdef SH_CUTEST
2955#include "CuTest.h"
2956
2957void Test_file_dequote (CuTest *tc)
2958{
2959#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
2960
2961 char str1[] = "1234567890";
2962 char str1a[] = "123456\\\"789\\r";
2963 char str1b[] = "12345678\\r9";
2964 char str1c[] = "12345678\\x0a_9";
2965 char str1d[] = "12345678\\007_9";
2966 char str1e[] = "123456789\\\\";
2967
2968 char str2[] = "1234567890\\xw";
2969 char str3[] = "1234567890\\xw99";
2970 char str4[] = "1234567890\\0ww";
2971 char str5[] = "12345\\g67890";
2972 char str6[] = "1234567890\\009a";
2973
2974 char *s, *p, *q;
2975 size_t lo, lr;
2976
2977 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
2978 q = sh_files_C_dequote(s, &lr);
2979 CuAssertPtrNotNull(tc, q);
2980 CuAssertTrue(tc, p == q);
2981 CuAssertTrue(tc, lr == lo);
2982
2983 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
2984 q = sh_files_C_dequote(s, &lr);
2985 CuAssertPtrNotNull(tc, q);
2986 CuAssertTrue(tc, p != q);
2987 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
2988 CuAssertTrue(tc, lr == (lo-2));
2989
2990 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
2991 q = sh_files_C_dequote(s, &lr);
2992 CuAssertPtrNotNull(tc, q);
2993 CuAssertTrue(tc, p != q);
2994 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
2995 CuAssertTrue(tc, lr == (lo-1));
2996
2997 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
2998 q = sh_files_C_dequote(s, &lr);
2999 CuAssertPtrNotNull(tc, q);
3000 CuAssertTrue(tc, p != q);
3001 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
3002 CuAssertTrue(tc, lr == (lo-3));
3003
3004 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
3005 q = sh_files_C_dequote(s, &lr);
3006 CuAssertPtrNotNull(tc, q);
3007 CuAssertTrue(tc, p != q);
3008 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
3009 CuAssertTrue(tc, lr == (lo-3));
3010
3011 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
3012 q = sh_files_C_dequote(s, &lr);
3013 CuAssertPtrNotNull(tc, q);
3014 CuAssertTrue(tc, p != q);
3015 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
3016 CuAssertTrue(tc, lr == (lo-1));
3017
3018 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
3019 q = sh_files_C_dequote(s, &lr);
3020 CuAssertTrue(tc, q == NULL);
3021 CuAssertTrue(tc, lr == 0);
3022
3023 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
3024 q = sh_files_C_dequote(s, &lr);
3025 CuAssertTrue(tc, q == NULL);
3026 CuAssertTrue(tc, lr == 0);
3027
3028 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
3029 q = sh_files_C_dequote(s, &lr);
3030 CuAssertTrue(tc, q == NULL);
3031 CuAssertTrue(tc, lr == 0);
3032
3033 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
3034 q = sh_files_C_dequote(s, &lr);
3035 CuAssertTrue(tc, q == NULL);
3036 CuAssertTrue(tc, lr == 0);
3037
3038 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
3039 q = sh_files_C_dequote(s, &lr);
3040 CuAssertTrue(tc, q == NULL);
3041 CuAssertTrue(tc, lr == 0);
3042
3043 return;
3044#else
3045 (void) tc; /* fix compiler warning */
3046 return;
3047#endif
3048}
3049#endif
3050
Note: See TracBrowser for help on using the repository browser.