source: trunk/src/sh_files.c@ 446

Last change on this file since 446 was 440, checked in by katerina, 11 years ago

Fix for ticket #344 (Problems with Ubuntu 13.04)

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