source: trunk/src/sh_files.c@ 404

Last change on this file since 404 was 402, checked in by katerina, 13 years ago

Fix for ticket #298, #299 (inotify related extraneous warnings and messages).

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