source: trunk/src/sh_files.c@ 388

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

Fix for ticket #283 (O_NOATIME not seen in sh_files.c).

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