source: trunk/src/sh_files.c@ 377

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

Fix for ticket #272 (Compile errors on RHEL5, gcc 4.1.2).

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