source: trunk/src/sh_files.c@ 247

Last change on this file since 247 was 242, checked in by katerina, 15 years ago

Fix for ticket #162 (doesn't run on MacOS X).

File size: 55.5 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <limits.h>
26
27#include <errno.h>
28
29/* Must be before <utime.h> on FreeBSD
30 */
31#include <sys/types.h>
32#include <unistd.h>
33
34#include <utime.h>
35
36#ifdef HAVE_DIRENT_H
37#include <dirent.h>
38#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
39#else
40#define dirent direct
41#define NAMLEN(dirent) (dirent)->d_namlen
42#ifdef HAVE_SYS_NDIR_H
43#include <sys/ndir.h>
44#endif
45#ifdef HAVE_SYS_DIR_H
46#include <sys/dir.h>
47#endif
48#ifdef HAVE_NDIR_H
49#include <ndir.h>
50#endif
51#endif
52#define NEED_ADD_DIRENT
53
54#ifdef HAVE_GLOB_H
55#include <glob.h>
56#endif
57
58#include "samhain.h"
59
60#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
61
62#include "sh_pthread.h"
63#include "sh_error.h"
64#include "sh_utils.h"
65#include "sh_unix.h"
66#include "sh_files.h"
67#include "sh_tiger.h"
68#include "sh_hash.h"
69#include "sh_ignore.h"
70#include "zAVLTree.h"
71
72#undef FIL__
73#define FIL__ _("sh_files.c")
74
75extern int flag_err_debug;
76extern int flag_err_info;
77
78int sh_files_reportonce(const char * c)
79{
80 int i;
81 SL_ENTER(_("sh_files_reportonce"));
82 i = sh_util_flagval(c, &(sh.flag.reportonce));
83
84 SL_RETURN(i, _("sh_files_reportonce"));
85}
86
87int sh_files_fulldetail(const char * c)
88{
89 int i;
90 SL_ENTER(_("sh_files_fulldetail"));
91 i = sh_util_flagval(c, &(sh.flag.fulldetail));
92
93 SL_RETURN((i), _("sh_files_fulldetail"));
94}
95
96
97typedef struct dir_struct {
98 long NumRegular;
99 long NumDirs;
100 long NumSymlinks;
101 long NumFifos;
102 long NumSockets;
103 long NumCDev;
104 long NumBDev;
105 long NumDoor;
106 long NumPort;
107 long NumAll;
108 long TotalBytes;
109 char DirPath[PATH_MAX];
110} dir_type;
111
112typedef struct dirstack_entry {
113 char * name;
114 int class;
115 unsigned long check_mask;
116 int rdepth;
117 short checked;
118 short childs_checked;
119 short is_reported;
120 /* struct dirstack_entry * next; */
121} dirstack_t;
122
123
124/* the destructor
125 */
126void free_dirstack (void * inptr)
127{
128 dirstack_t * here;
129
130 SL_ENTER(_("free_dirstack"));
131 if (inptr == NULL)
132 SL_RET0(_("free_dirstack"));
133 else
134 here = (dirstack_t *) inptr;
135
136 if (here->name != NULL)
137 SH_FREE(here->name);
138 SH_FREE(here);
139 SL_RET0(_("free_dirstack"));
140}
141
142/* Function to return the key for indexing
143 * the argument
144 */
145zAVLKey zdirstack_key (void const * arg)
146{
147 const dirstack_t * sa = (const dirstack_t *) arg;
148 return (zAVLKey) sa->name;
149}
150
151
152static zAVLTree * zdirListOne = NULL;
153static zAVLTree * zdirListTwo = NULL;
154static zAVLTree * zfileList = NULL;
155
156
157static int sh_files_fullpath (char * testdir, char * d_name,
158 char * statpath);
159static int sh_files_pushdir (int class, const char * str_s);
160static int sh_files_pushfile (int class, const char * str_s);
161static int sh_files_checkdir (int class, int rdepth, char * dirName,
162 char * relativeName);
163static ShFileType sh_files_filecheck (int class, char * dirName,
164 char * fileName, int * reported,
165 int rsrcflag);
166
167static long MaxRecursionLevel = 0;
168
169/* set default recursion level
170 */
171int sh_files_setrecursion (const char * flag_s)
172{
173 long flag = 0;
174 static int reject = 0;
175
176 SL_ENTER( _("sh_files_setrecursion"));
177
178 if (reject == 1)
179 SL_RETURN((-1), _("sh_files_setrecursion"));
180
181 if (sh.flag.opts == 1)
182 reject = 1;
183
184 if (flag_s != NULL)
185 flag = (int)(atof(flag_s));
186
187 if (flag >= 0 && flag <= 99)
188 MaxRecursionLevel = flag;
189 else
190 SL_RETURN((-1), _("sh_files_setrecursion"));
191
192 SL_RETURN((0), _("sh_files_setrecursion"));
193}
194
195unsigned long sh_files_chk ()
196{
197 zAVLCursor cursor;
198 ShFileType status;
199 unsigned long fcount = 0;
200
201 char * tmp = NULL;
202
203 dirstack_t * ptr;
204 char * dir;
205 char * file;
206 int tmp_reported;
207
208 SL_ENTER(_("sh_files_chk"));
209
210 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
211 ptr = (dirstack_t *) zAVLNext(&cursor))
212 {
213
214 if (sig_urgent > 0) {
215 SL_RETURN(fcount, _("sh_files_chk"));
216 }
217
218 if (ptr->checked == S_FALSE)
219 {
220 dir = sh_util_dirname (ptr->name);
221 file = sh_util_basename (ptr->name);
222#if defined(WITH_TPT)
223 tmp = sh_util_safe_name (ptr->name);
224#endif
225
226
227 if (flag_err_info == SL_TRUE)
228 {
229#if !defined(WITH_TPT)
230 tmp = sh_util_safe_name (ptr->name);
231#endif
232 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, tmp);
233 }
234
235 BREAKEXIT(sh_files_filecheck);
236 tmp_reported = ptr->is_reported; /* fix aliasing warning */
237 status = sh_files_filecheck (ptr->class, dir, file,
238 &tmp_reported, 0);
239 ptr->is_reported = tmp_reported;
240
241 TPT(( 0, FIL__, __LINE__,
242 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
243 tmp, status, ptr->is_reported));
244
245 if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
246 {
247 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
248 tmp, status));
249
250 if ( sh.flag.checkSum == SH_CHECK_INIT ||
251 sh_hash_have_it (ptr->name) >= 0)
252 {
253 if (S_FALSE == sh_ignore_chk_del(ptr->name))
254 {
255 if (0 != hashreport_missing(ptr->name,
256 (ptr->class == SH_LEVEL_ALLIGNORE) ?
257 ShDFLevel[ptr->class] :
258 ShDFLevel[SH_ERR_T_FILE])) {
259 if (tmp == NULL)
260 tmp = sh_util_safe_name (ptr->name);
261 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
262 ShDFLevel[ptr->class] :
263 ShDFLevel[SH_ERR_T_FILE],
264 FIL__, __LINE__, 0, MSG_FI_MISS,
265 tmp);
266 }
267 }
268 }
269 else /* not there at init, and still missing */
270 {
271 if (tmp == NULL)
272 tmp = sh_util_safe_name (ptr->name);
273 sh_error_handle (SH_ERR_NOTICE,
274 FIL__, __LINE__, 0,
275 MSG_FI_FAIL,
276 tmp);
277 }
278#ifndef REPLACE_OLD
279 /* this will tell that we have seen the file, and thus prevent
280 * deletion from the database, resulting in an incomplete
281 * message when the file reappears
282 */
283 if (sh.flag.checkSum != SH_CHECK_INIT)
284 sh_hash_set_visited_true(ptr->name);
285#else
286 if (sh.flag.checkSum != SH_CHECK_INIT)
287 sh_hash_set_missing(ptr->name);
288#endif
289 if (sh.flag.reportonce == S_TRUE)
290 SET_SH_FFLAG_REPORTED(ptr->is_reported);
291 }
292 else
293 {
294 /* exists (status >= 0), but was missing (reported == TRUE)
295 */
296 if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported))
297 {
298 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
299 }
300 /* Catchall
301 */
302 else if (status == SH_FILE_UNKNOWN)
303 {
304 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
305 * is reported if ptr->reported == S_TRUE because the
306 * file has been added.
307 */
308 if (sh_hash_have_it (ptr->name) >= 0)
309 {
310 if (S_FALSE == sh_ignore_chk_del(ptr->name))
311 {
312 if (0 != hashreport_missing(ptr->name,
313 (ptr->class == SH_LEVEL_ALLIGNORE) ?
314 ShDFLevel[ptr->class] :
315 ShDFLevel[SH_ERR_T_FILE])) {
316 if (tmp == NULL)
317 tmp = sh_util_safe_name (ptr->name);
318 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
319 ShDFLevel[ptr->class] :
320 ShDFLevel[SH_ERR_T_FILE],
321 FIL__, __LINE__, 0, MSG_FI_MISS,
322 tmp);
323 }
324 }
325#ifndef REPLACE_OLD
326 if (sh.flag.checkSum != SH_CHECK_INIT)
327 sh_hash_set_visited_true(ptr->name);
328#else
329 /* delete from database
330 */
331 if (sh.flag.checkSum != SH_CHECK_INIT)
332 sh_hash_set_missing(ptr->name);
333#endif
334 }
335 else
336 {
337 if (tmp == NULL)
338 tmp = sh_util_safe_name (ptr->name);
339 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
340 MSG_FI_FAIL,
341 tmp);
342 if (sh.flag.checkSum != SH_CHECK_INIT)
343 sh_hash_set_visited_true(ptr->name);
344 }
345 }
346 ++fcount;
347 }
348
349 if (tmp != NULL)
350 {
351 SH_FREE(tmp);
352 tmp = NULL;
353 }
354 if (file)
355 SH_FREE(file);
356 if (dir)
357 SH_FREE(dir);
358
359 ptr->checked = S_TRUE;
360 }
361 }
362
363 SL_RETURN(fcount, _("sh_files_chk"));
364}
365
366int sh_files_delfilestack ()
367{
368 SL_ENTER(_("sh_files_delfilestack"));
369
370 zAVLFreeTree (zfileList, free_dirstack);
371 zfileList = NULL;
372
373 SL_RETURN(0, _("sh_files_delfilestack"));
374}
375
376int sh_files_setrec_int (zAVLTree * tree)
377{
378 dirstack_t * ptr;
379 zAVLCursor avlcursor;
380
381 SL_ENTER(_("sh_files_setrec"));
382 if (tree != NULL) {
383 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
384 ptr = (dirstack_t *) zAVLNext(&avlcursor))
385 {
386 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
387 {
388 ptr->rdepth = MaxRecursionLevel;
389 }
390 if (ptr->rdepth == (-1) && sh.flag.checkSum != SH_CHECK_INIT)
391 hash_remove_tree (ptr->name);
392 }
393 }
394 SL_RETURN(0, _("sh_files_setrec"));
395}
396
397int sh_files_setrec ()
398{
399 sh_files_setrec_int(zdirListOne);
400 return sh_files_setrec_int(zdirListTwo);
401}
402
403zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
404{
405 SL_ENTER(_("sh_files_deldirstack"));
406
407 zAVLFreeTree (ptr, free_dirstack);
408
409 SL_RETURN(NULL, _("sh_files_deldirstack"));
410}
411
412int sh_files_deldirstack ()
413{
414 zdirListOne = sh_files_deldirstack_int(zdirListOne);
415 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
416 return 0;
417}
418
419void sh_files_reset()
420{
421 dirstack_t * ptr;
422 zAVLCursor avlcursor;
423
424 SL_ENTER(_("sh_files_reset"));
425
426 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
427 ptr = (dirstack_t *) zAVLNext(&avlcursor))
428 ptr->checked = 0;
429
430 SL_RET0(_("sh_files_reset"));
431}
432
433void sh_dirs_reset()
434{
435 dirstack_t * ptr;
436 zAVLCursor avlcursor1;
437 zAVLCursor avlcursor2;
438
439 SL_ENTER(_("sh_dirs_reset"));
440
441 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
442 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
443 ptr->checked = 0;
444
445 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
446 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
447 ptr->checked = 0;
448
449 SL_RET0(_("sh_dirs_reset"));
450}
451
452
453int sh_files_pushfile_prelink (const char * str_s)
454{
455 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
456}
457
458int sh_files_pushfile_user0 (const char * str_s)
459{
460 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
461}
462
463int sh_files_pushfile_user1 (const char * str_s)
464{
465 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
466}
467
468int sh_files_pushfile_user2 (const char * str_s)
469{
470 return (sh_files_pushfile (SH_LEVEL_USER2, str_s));
471}
472
473int sh_files_pushfile_user3 (const char * str_s)
474{
475 return (sh_files_pushfile (SH_LEVEL_USER3, str_s));
476}
477
478int sh_files_pushfile_user4 (const char * str_s)
479{
480 return (sh_files_pushfile (SH_LEVEL_USER4, str_s));
481}
482
483
484int sh_files_pushfile_ro (const char * str_s)
485{
486 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
487}
488
489int sh_files_pushfile_attr (const char * str_s)
490{
491 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
492}
493
494int sh_files_pushfile_log (const char * str_s)
495{
496 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
497}
498
499int sh_files_pushfile_glog (const char * str_s)
500{
501 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
502}
503
504int sh_files_pushfile_noig (const char * str_s)
505{
506 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
507}
508
509int sh_files_pushfile_allig (const char * str_s)
510{
511 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
512}
513
514
515static void sh_files_set_mask (unsigned long * mask,
516 unsigned long val, int act)
517{
518 SL_ENTER(_("sh_files_set_mask"));
519
520 if (act == 0)
521 (*mask) = val;
522 else if (act > 0)
523 (*mask) |= val;
524 else
525 (*mask) &= ~val;
526
527 SL_RET0(_("sh_files_set_mask"));
528}
529
530/* set mask(class)
531 */
532static int sh_files_parse_mask (unsigned long * mask, const char * str)
533{
534 int l, i = 0, act = 0, k = 0;
535 char myword[64];
536
537 SL_ENTER(_("sh_files_parse_mask"));
538
539 if (str == NULL)
540 {
541 SL_RETURN ( (-1), _("sh_files_parse_mask"));
542 }
543 else
544 l = sl_strlen(str);
545
546 while (i < l) {
547 if (str[i] == '\0')
548 break;
549 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
550 {
551 ++i;
552 continue;
553 }
554
555 if (str[i] == '+')
556 {
557 act = +1; ++i;
558 continue;
559 }
560 else if (str[i] == '-')
561 {
562 act = -1; ++i;
563 continue;
564 }
565 else /* a word */
566 {
567 k = 0;
568 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
569 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
570 myword[k] = str[i];
571 ++i; ++k;
572 }
573 myword[k] = '\0';
574
575/* checksum */
576 if (0 == strncmp(myword, _("CHK"), 3))
577 sh_files_set_mask (mask, MODI_CHK, act);
578/* link */
579 if (0 == strncmp(myword, _("LNK"), 3))
580 sh_files_set_mask (mask, MODI_LNK, act);
581/* inode */
582 if (0 == strncmp(myword, _("RDEV"), 3))
583 sh_files_set_mask (mask, MODI_RDEV, act);
584/* inode */
585 if (0 == strncmp(myword, _("INO"), 3))
586 sh_files_set_mask (mask, MODI_INO, act);
587/* user */
588 if (0 == strncmp(myword, _("USR"), 3))
589 sh_files_set_mask (mask, MODI_USR, act);
590/* group */
591 if (0 == strncmp(myword, _("GRP"), 3))
592 sh_files_set_mask (mask, MODI_GRP, act);
593/* mtime */
594 if (0 == strncmp(myword, _("MTM"), 3))
595 sh_files_set_mask (mask, MODI_MTM, act);
596/* ctime */
597 if (0 == strncmp(myword, _("CTM"), 3))
598 sh_files_set_mask (mask, MODI_CTM, act);
599/* atime */
600 if (0 == strncmp(myword, _("ATM"), 3))
601 sh_files_set_mask (mask, MODI_ATM, act);
602/* size */
603 if (0 == strncmp(myword, _("SIZ"), 3))
604 sh_files_set_mask (mask, MODI_SIZ, act);
605/* file mode */
606 if (0 == strncmp(myword, _("MOD"), 3))
607 sh_files_set_mask (mask, MODI_MOD, act);
608/* hardlinks */
609 if (0 == strncmp(myword, _("HLN"), 3))
610 sh_files_set_mask (mask, MODI_HLN, act);
611/* size may grow */
612 if (0 == strncmp(myword, _("GROW"), 3))
613 sh_files_set_mask (mask, MODI_SGROW, act);
614/* use prelink */
615 if (0 == strncmp(myword, _("PRE"), 3))
616 sh_files_set_mask (mask, MODI_PREL, act);
617/* get content */
618 if (0 == strncmp(myword, _("TXT"), 3))
619 sh_files_set_mask (mask, MODI_TXT, act);
620
621 }
622 }
623 SL_RETURN ( (0), _("sh_files_parse_mask"));
624}
625
626int sh_files_redef_prelink(const char * str)
627{
628 return (sh_files_parse_mask(&mask_PRELINK, str));
629}
630int sh_files_redef_user0(const char * str)
631{
632 return (sh_files_parse_mask(&mask_USER0, str));
633}
634int sh_files_redef_user1(const char * str)
635{
636 return (sh_files_parse_mask(&mask_USER1, str));
637}
638int sh_files_redef_user2(const char * str)
639{
640 return (sh_files_parse_mask(&mask_USER2, str));
641}
642int sh_files_redef_user3(const char * str)
643{
644 return (sh_files_parse_mask(&mask_USER3, str));
645}
646int sh_files_redef_user4(const char * str)
647{
648 return (sh_files_parse_mask(&mask_USER4, str));
649}
650int sh_files_redef_readonly(const char * str)
651{
652 return (sh_files_parse_mask(&mask_READONLY, str));
653}
654int sh_files_redef_loggrow(const char * str)
655{
656 return (sh_files_parse_mask(&mask_LOGGROW, str));
657}
658int sh_files_redef_logfiles(const char * str)
659{
660 return (sh_files_parse_mask(&mask_LOGFILES, str));
661}
662int sh_files_redef_attributes(const char * str)
663{
664 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
665}
666int sh_files_redef_noignore(const char * str)
667{
668 return (sh_files_parse_mask(&mask_NOIGNORE, str));
669}
670int sh_files_redef_allignore(const char * str)
671{
672 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
673}
674
675unsigned long sh_files_maskof (int class)
676{
677 switch (class)
678 {
679 case SH_LEVEL_READONLY:
680 return (unsigned long) mask_READONLY;
681 case SH_LEVEL_ATTRIBUTES:
682 return (unsigned long) mask_ATTRIBUTES;
683 case SH_LEVEL_LOGFILES:
684 return (unsigned long) mask_LOGFILES;
685 case SH_LEVEL_LOGGROW:
686 return (unsigned long) mask_LOGGROW;
687 case SH_LEVEL_ALLIGNORE:
688 return (unsigned long) mask_ALLIGNORE;
689 case SH_LEVEL_NOIGNORE:
690 return (unsigned long) mask_NOIGNORE;
691 case SH_LEVEL_USER0:
692 return (unsigned long) mask_USER0;
693 case SH_LEVEL_USER1:
694 return (unsigned long) mask_USER1;
695 case SH_LEVEL_USER2:
696 return (unsigned long) mask_USER2;
697 case SH_LEVEL_USER3:
698 return (unsigned long) mask_USER3;
699 case SH_LEVEL_USER4:
700 return (unsigned long) mask_USER4;
701 case SH_LEVEL_PRELINK:
702 return (unsigned long) mask_PRELINK;
703 default:
704 return (unsigned long) 0;
705 }
706}
707
708#ifdef HAVE_GLOB_H
709int sh_files_has_metachar (const char * str)
710{
711 SL_ENTER(_("sh_files_has_metachar"));
712 if (NULL != strchr(str, '*'))
713 SL_RETURN(1, _("sh_files_has_metachar"));
714 else if (NULL != strchr(str, '?'))
715 SL_RETURN(1, _("sh_files_has_metachar"));
716 else if (NULL != (strchr(str, '[')))
717 SL_RETURN(1, _("sh_files_has_metachar"));
718 else
719 SL_RETURN(0, _("sh_files_has_metachar"));
720}
721
722
723int sh_files_globerr (const char * epath, int errnum)
724{
725 char * p;
726 char errbuf[SH_ERRBUF_SIZE];
727
728 SL_ENTER(_("sh_files_globerr"));
729
730 if (errnum == ENOTDIR || errnum == ENOENT)
731 {
732 SL_RETURN(0, _("sh_files_globerr"));
733 }
734
735 p = sh_util_safe_name (epath);
736 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
737 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
738 SH_FREE(p);
739
740 SL_RETURN(0, _("sh_files_globerr"));
741}
742
743/* #ifdef HAVE_GLOB_H
744 */
745#endif
746
747int sh_files_push_file_int (int class, const char * str_s, size_t len)
748{
749 dirstack_t * new_item_ptr;
750 char * fileName;
751 int ret;
752
753 SL_ENTER(_("sh_files_push_file_int"));
754
755 fileName = SH_ALLOC(len+1);
756 sl_strlcpy(fileName, str_s, len+1);
757
758 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
759
760 new_item_ptr->name = fileName;
761 new_item_ptr->class = class;
762 new_item_ptr->check_mask = sh_files_maskof(class);
763 new_item_ptr->rdepth = 0;
764 new_item_ptr->checked = S_FALSE;
765 new_item_ptr->is_reported = 0;
766 new_item_ptr->childs_checked = S_FALSE;
767
768 if (zfileList == NULL)
769 {
770 zfileList = zAVLAllocTree (zdirstack_key);
771 if (zfileList == NULL)
772 {
773 (void) safe_logger (0, 0, NULL);
774 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
775 }
776 }
777
778 ret = zAVLInsert (zfileList, new_item_ptr);
779
780 if (-1 == ret)
781 {
782 (void) safe_logger (0, 0, NULL);
783 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
784 }
785 if (3 == ret)
786 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
787 fileName);
788
789 SL_RETURN(0, _("sh_files_push_file_int"));
790}
791
792
793static int sh_files_pushfile (int class, const char * str_s)
794{
795 size_t len;
796 char * tmp;
797 char * p;
798#ifdef HAVE_GLOB_H
799 int globstatus = -1;
800 unsigned int gloop;
801 glob_t pglob;
802#endif
803
804 static int reject = 0;
805
806 SL_ENTER(_("sh_files_pushfile"));
807
808 if (reject == 1)
809 SL_RETURN((-1),_("sh_files_pushfile"));
810
811 /* if we push a filename from the command line, make sure it
812 * is the only one -- and will stay the only one
813 */
814 if (sh.flag.opts == 1)
815 {
816 sh_files_delfilestack ();
817 sh_files_deldirstack ();
818 reject = 1;
819 }
820
821 if (str_s == NULL)
822 SL_RETURN((-1),_("sh_files_pushfile"));
823
824 len = sl_strlen(str_s);
825
826 if (len >= PATH_MAX)
827 {
828 /* Name too long
829 */
830 tmp = sh_util_safe_name (str_s);
831 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
832 tmp);
833 SH_FREE(tmp);
834 SL_RETURN((-1),_("sh_files_pushfile"));
835 }
836 else if (len < 1)
837 {
838 /* Should not happen (str_s == NULL caught further above)
839 */
840 SL_RETURN((-1),_("sh_files_pushfile"));
841 }
842 else if (str_s[0] != '/')
843 {
844 /* Not an absolute path
845 */
846 tmp = sh_util_safe_name (str_s);
847 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
848 tmp);
849 SH_FREE(tmp);
850 SL_RETURN((-1),_("sh_files_pushfile"));
851 }
852 else
853 {
854 /* remove a terminating '/', take care of the
855 * special case of the root directory.
856 */
857 p = sh_util_strdup (str_s);
858 if (p[len-1] == '/' && len > 1)
859 {
860 p[len-1] = '\0';
861 --len;
862 }
863
864 }
865
866#ifdef HAVE_GLOB_H
867 if (0 == sh_files_has_metachar(p))
868 {
869 sh_files_push_file_int (class, p, len);
870 }
871 else
872 {
873 pglob.gl_offs = 0;
874 globstatus = glob (p, 0, sh_files_globerr, &pglob);
875
876 if (globstatus == 0 && pglob.gl_pathc > 0)
877 {
878 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
879 sh_files_push_file_int (class, pglob.gl_pathv[gloop],
880 sl_strlen(pglob.gl_pathv[gloop]));
881 }
882 else
883 {
884 tmp = sh_util_safe_name (p);
885
886 if (pglob.gl_pathc == 0
887#ifdef GLOB_NOMATCH
888 || globstatus == GLOB_NOMATCH
889#endif
890 )
891 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
892 globstatus, MSG_FI_GLOB,
893 _("No matches found"), tmp);
894#ifdef GLOB_NOSPACE
895 else if (globstatus == GLOB_NOSPACE)
896 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
897 globstatus, MSG_FI_GLOB,
898 _("Out of memory"), tmp);
899#endif
900#ifdef GLOB_ABORTED
901 else if (globstatus == GLOB_ABORTED)
902 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
903 globstatus, MSG_FI_GLOB,
904 _("Read error"), tmp);
905#endif
906 else
907 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
908 globstatus, MSG_FI_GLOB,
909 _("Unknown error"), tmp);
910
911 SH_FREE(tmp);
912
913 }
914
915 globfree(&pglob);
916 }
917
918#else
919 sh_files_push_file_int (class, p, len);
920#endif
921
922 SH_FREE(p);
923 SL_RETURN((0),_("sh_files_pushfile"));
924}
925
926
927/* ------ directories ----- */
928
929int sh_files_is_allignore_int (char * str, zAVLTree * tree)
930{
931 dirstack_t * ptr;
932
933 SL_ENTER(_("sh_files_is_allignore"));
934
935 if (tree)
936 {
937 ptr = zAVLSearch(tree, str);
938 if (ptr)
939 {
940 if (ptr->class == SH_LEVEL_ALLIGNORE)
941 SL_RETURN( 1, _("sh_files_is_allignore"));
942 else
943 SL_RETURN( 0, _("sh_files_is_allignore"));
944 }
945 }
946 SL_RETURN( 0, _("sh_files_is_allignore"));
947}
948
949int sh_files_is_allignore (char * str)
950{
951 if (1 == sh_files_is_allignore_int(str, zdirListOne))
952 return 1;
953 if (NULL == zdirListTwo)
954 return 0;
955 return sh_files_is_allignore_int(str, zdirListTwo);
956}
957
958unsigned long sh_dirs_chk (int which)
959{
960 zAVLTree * tree;
961 zAVLCursor cursor;
962 dirstack_t * ptr;
963 dirstack_t * dst_ptr;
964 int status;
965 unsigned long dcount = 0;
966 char * tmp;
967
968 SL_ENTER(_("sh_dirs_chk"));
969
970 if (which == 1)
971 tree = zdirListOne;
972 else
973 tree = zdirListTwo;
974
975 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
976 ptr = (dirstack_t *) zAVLNext(&cursor))
977 {
978 if (sig_urgent > 0) {
979 SL_RETURN(dcount, _("sh_dirs_chk"));
980 }
981
982 if (ptr->checked == S_FALSE)
983 {
984 /* 28 Aug 2001 check the top level directory
985 */
986 status = S_FALSE;
987 dst_ptr = zAVLSearch(zfileList, ptr->name);
988 if (dst_ptr)
989 {
990 if (dst_ptr->checked == S_FALSE)
991 {
992 BREAKEXIT(sh_files_filecheck);
993 sh_files_filecheck (dst_ptr->class, ptr->name,
994 NULL, &status, 0);
995 dst_ptr->checked = S_TRUE;
996 status = S_TRUE;
997 }
998 else
999 {
1000 status = S_TRUE;
1001 }
1002 }
1003
1004 if (status == S_FALSE)
1005 sh_files_filecheck (ptr->class, ptr->name, NULL, &status, 0);
1006
1007 BREAKEXIT(sh_files_checkdir);
1008 status = sh_files_checkdir (ptr->class, ptr->rdepth, ptr->name,
1009 ptr->name);
1010
1011 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1012 {
1013 /* directory is missing
1014 */
1015 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1016 {
1017 if (0 != hashreport_missing(ptr->name,
1018 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1019 ShDFLevel[ptr->class] :
1020 ShDFLevel[SH_ERR_T_DIR])) {
1021 tmp = sh_util_safe_name (ptr->name);
1022 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1023 ShDFLevel[ptr->class] :
1024 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1025 0, MSG_FI_MISS, tmp);
1026 SH_FREE(tmp);
1027 }
1028 }
1029 if (sh.flag.reportonce == S_TRUE)
1030 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1031 }
1032 else
1033 {
1034 /* exists (status >= 0), but was missing (reported == TRUE)
1035 */
1036 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1037 {
1038 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1039#if 0
1040 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1041 * above, which will catch missing directories anyway
1042 */
1043 tmp = sh_util_safe_name (ptr->name);
1044 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1045 ShDFLevel[ptr->class] :
1046 ShDFLevel[SH_ERR_T_DIR],
1047 FIL__, __LINE__, 0, MSG_FI_ADD,
1048 tmp);
1049 SH_FREE(tmp);
1050#endif
1051 }
1052 else if (status == SH_FILE_UNKNOWN)
1053 {
1054 /* catchall
1055 */
1056 tmp = sh_util_safe_name (ptr->name);
1057 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1058 MSG_FI_FAIL,
1059 tmp);
1060 SH_FREE(tmp);
1061 if (sh.flag.checkSum != SH_CHECK_INIT)
1062 sh_hash_set_visited_true(ptr->name);
1063 }
1064
1065 ++dcount;
1066 }
1067 ptr->checked = S_TRUE;
1068 ptr->childs_checked = S_TRUE;
1069 }
1070
1071 if (sig_urgent > 0) {
1072 SL_RETURN(dcount, _("sh_dirs_chk"));
1073 }
1074
1075 }
1076 SL_RETURN(dcount, _("sh_dirs_chk"));
1077}
1078
1079int sh_files_pushdir_prelink (const char * str_s)
1080{
1081 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1082}
1083
1084int sh_files_pushdir_user0 (const char * str_s)
1085{
1086 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1087}
1088
1089int sh_files_pushdir_user1 (const char * str_s)
1090{
1091 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1092}
1093
1094int sh_files_pushdir_user2 (const char * str_s)
1095{
1096 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1097}
1098
1099int sh_files_pushdir_user3 (const char * str_s)
1100{
1101 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1102}
1103
1104int sh_files_pushdir_user4 (const char * str_s)
1105{
1106 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1107}
1108
1109int sh_files_pushdir_attr (const char * str_s)
1110{
1111 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1112}
1113
1114int sh_files_pushdir_ro (const char * str_s)
1115{
1116 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1117}
1118
1119int sh_files_pushdir_log (const char * str_s)
1120{
1121 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1122}
1123
1124int sh_files_pushdir_glog (const char * str_s)
1125{
1126 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1127}
1128
1129int sh_files_pushdir_noig (const char * str_s)
1130{
1131 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1132}
1133
1134int sh_files_pushdir_allig (const char * str_s)
1135{
1136 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1137}
1138
1139static int which_dirList = 1;
1140
1141int set_dirList (int which)
1142{
1143 if (which == 2)
1144 which_dirList = 2;
1145 else
1146 which_dirList = 1;
1147 return 0;
1148}
1149
1150int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth)
1151{
1152 zAVLTree * tree;
1153 dirstack_t * new_item_ptr;
1154 char * dirName;
1155 int ret;
1156
1157 SL_ENTER(_("sh_files_push_dir_int"));
1158
1159 dirName = SH_ALLOC(len+1);
1160 sl_strlcpy(dirName, tail, len+1);
1161
1162 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1163
1164 new_item_ptr->name = dirName;
1165 new_item_ptr->class = class;
1166 new_item_ptr->check_mask = sh_files_maskof(class);
1167 new_item_ptr->rdepth = rdepth;
1168 new_item_ptr->checked = S_FALSE;
1169 new_item_ptr->is_reported = 0;
1170 new_item_ptr->childs_checked = S_FALSE;
1171
1172 if (which_dirList == 1)
1173 {
1174 tree = zdirListOne;
1175 }
1176 else
1177 {
1178 tree = zdirListTwo;
1179 }
1180
1181 if (tree == NULL)
1182 {
1183 tree = zAVLAllocTree (zdirstack_key);
1184 if (tree == NULL)
1185 {
1186 (void) safe_logger (0, 0, NULL);
1187 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1188 }
1189 if (which_dirList == 1)
1190 zdirListOne = tree;
1191 else
1192 zdirListTwo = tree;
1193 }
1194
1195 ret = zAVLInsert (tree, new_item_ptr);
1196
1197 if (-1 == ret)
1198 {
1199 (void) safe_logger (0, 0, NULL);
1200 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1201 }
1202 if (3 == ret)
1203 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1204 dirName);
1205
1206 SL_RETURN(0, _("sh_files_push_dir_int"));
1207}
1208
1209static int sh_files_pushdir (int class, const char * str_s)
1210{
1211 char * tmp;
1212 size_t len;
1213 int rdepth = 0;
1214 char * tail = NULL;
1215 char * p;
1216
1217#ifdef HAVE_GLOB_H
1218 glob_t pglob;
1219 int globstatus = -1;
1220 unsigned int gloop;
1221#endif
1222
1223 SL_ENTER(_("sh_files_pushdir"));
1224
1225 if (sh.flag.opts == 1) {
1226 sh_files_delfilestack ();
1227 sh_files_deldirstack ();
1228 }
1229
1230 if (str_s == NULL)
1231 SL_RETURN((-1), _("sh_files_pushdir"));
1232
1233 p = sh_util_strdup (str_s);
1234
1235 if (p[0] != '/')
1236 {
1237 rdepth = strtol(p, &tail, 10);
1238 if (tail == p)
1239 {
1240 SH_FREE(p);
1241 SL_RETURN((-1), _("sh_files_pushdir"));
1242 }
1243 }
1244 else
1245 tail = p;
1246
1247
1248 if (rdepth < (-1) || tail == p || rdepth > 99)
1249 rdepth = (-2);
1250
1251 len = sl_strlen(tail);
1252
1253 if (len >= PATH_MAX)
1254 {
1255 tmp = sh_util_safe_name (tail);
1256 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1257 tmp);
1258 SH_FREE(tmp);
1259 SH_FREE(p);
1260 SL_RETURN((-1), _("sh_files_pushdir"));
1261 }
1262 else if (len < 1)
1263 {
1264 SH_FREE(p);
1265 SL_RETURN((-1), _("sh_files_pushdir"));
1266 }
1267 else if (tail[0] != '/')
1268 {
1269 tmp = sh_util_safe_name (tail);
1270 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1271 tmp);
1272 SH_FREE(tmp);
1273 SH_FREE(p);
1274 SL_RETURN((-1), _("sh_files_pushdir"));
1275 }
1276 else
1277 {
1278
1279 if (tail[len-1] == '/' && len > 1)
1280 {
1281 tail[len-1] = '\0';
1282 --len;
1283 }
1284
1285 }
1286
1287#ifdef HAVE_GLOB_H
1288 if (0 == sh_files_has_metachar(tail))
1289 {
1290 sh_files_push_dir_int (class, tail, len, rdepth);
1291 }
1292 else
1293 {
1294 pglob.gl_offs = 0;
1295 globstatus = glob (tail, 0, sh_files_globerr, &pglob);
1296
1297 if (globstatus == 0 && pglob.gl_pathc > 0)
1298 {
1299 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1300 sh_files_push_dir_int (class,
1301 pglob.gl_pathv[gloop],
1302 sl_strlen(pglob.gl_pathv[gloop]),
1303 rdepth);
1304 }
1305 else
1306 {
1307 tmp = sh_util_safe_name (tail);
1308
1309 if (pglob.gl_pathc == 0
1310#ifdef GLOB_NOMATCH
1311 || globstatus == GLOB_NOMATCH
1312#endif
1313 )
1314 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1315 globstatus, MSG_FI_GLOB,
1316 _("No matches found"), tmp);
1317#ifdef GLOB_NOSPACE
1318 else if (globstatus == GLOB_NOSPACE)
1319 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1320 globstatus, MSG_FI_GLOB,
1321 _("Out of memory"), tmp);
1322#endif
1323#ifdef GLOB_ABORTED
1324 else if (globstatus == GLOB_ABORTED)
1325 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1326 globstatus, MSG_FI_GLOB,
1327 _("Read error"), tmp);
1328#endif
1329 else
1330 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1331 globstatus, MSG_FI_GLOB,
1332 _("Unknown error"), tmp);
1333 SH_FREE(tmp);
1334 }
1335
1336 globfree(&pglob);
1337 }
1338#else
1339 sh_files_push_dir_int (class, tail, len, rdepth);
1340#endif
1341
1342 SH_FREE(p);
1343 SL_RETURN((0), _("sh_files_pushdir"));
1344}
1345
1346/**
1347struct sh_dirent {
1348 char * sh_d_name;
1349 struct sh_dirent * next;
1350};
1351**/
1352
1353void kill_sh_dirlist (struct sh_dirent * dirlist)
1354{
1355 struct sh_dirent * this;
1356
1357 while (dirlist)
1358 {
1359 this = dirlist->next;
1360 SH_FREE(dirlist->sh_d_name);
1361 SH_FREE(dirlist);
1362 dirlist = this;
1363 }
1364 return;
1365}
1366
1367/* -- add an entry to a directory listing
1368 */
1369struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1370 struct sh_dirent * dirlist)
1371{
1372 struct sh_dirent * this;
1373 size_t len;
1374
1375 if (thisEntry == NULL)
1376 return dirlist;
1377
1378 len = sl_strlen(thisEntry->d_name);
1379 if (len == 0)
1380 return dirlist;
1381 ++len;
1382
1383 this = SH_ALLOC(sizeof(struct sh_dirent));
1384 if (!this)
1385 return dirlist;
1386
1387 this->sh_d_name = SH_ALLOC(len);
1388 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1389
1390 this->next = dirlist;
1391 return this;
1392}
1393
1394static int sh_check_hardlinks = S_TRUE;
1395
1396/* Simply sets our boolean as to whether this check is active
1397 */
1398int sh_files_check_hardlinks (const char * opt)
1399{
1400 int i;
1401 SL_ENTER(_("sh_files_check_hardlinks"));
1402 i = sh_util_flagval(opt, &sh_check_hardlinks);
1403 SL_RETURN(i, _("sh_files_check_hardlinks"));
1404}
1405
1406struct sh_hle_struct {
1407 long offset;
1408 char * path;
1409 struct sh_hle_struct * next;
1410};
1411
1412static struct sh_hle_struct * sh_hl_exc = NULL;
1413
1414int sh_files_hle_reg (const char * str)
1415{
1416 long offset;
1417 size_t len;
1418 char * path;
1419
1420 struct sh_hle_struct * tmp = sh_hl_exc;
1421
1422 SL_ENTER(_("sh_files_hle_reg"));
1423
1424 /* Free the linked list if called with NULL argument
1425 */
1426 if (str == NULL)
1427 {
1428 while (tmp)
1429 {
1430 sh_hl_exc = tmp->next;
1431 SH_FREE(tmp->path);
1432 SH_FREE(tmp);
1433 tmp = sh_hl_exc;
1434 }
1435 sh_hl_exc = NULL;
1436 SL_RETURN(0, _("sh_files_hle_reg"));
1437 }
1438
1439 /* We expect 'offset:/path'
1440 */
1441 offset = strtol(str, &path, 0);
1442 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1443 {
1444 SL_RETURN(-1, _("sh_files_hle_reg"));
1445 }
1446 ++path;
1447 len = 1 + sl_strlen(path);
1448
1449 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1450 tmp->path = SH_ALLOC(len);
1451 sl_strlcpy (tmp->path, path, len);
1452 tmp->offset = offset;
1453 tmp->next = sh_hl_exc;
1454 sh_hl_exc = tmp;
1455
1456 SL_RETURN(0, _("sh_files_hle_reg"));
1457}
1458
1459#if !defined(HOST_IS_DARWIN)
1460static int sh_files_hle_test (int offset, char * path)
1461{
1462 struct sh_hle_struct * tmp = sh_hl_exc;
1463
1464 SL_ENTER(_("sh_files_hle_reg"));
1465
1466 while(tmp)
1467 {
1468 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1469 {
1470 SL_RETURN(0, _("sh_files_hle_test"));
1471 }
1472 tmp = tmp->next;
1473 }
1474 SL_RETURN(-1, _("sh_files_hle_test"));
1475}
1476#endif
1477
1478/* -- check a single directory and its content
1479 */
1480static int sh_files_checkdir (int iclass, int idepth, char * iname,
1481 char * relativeName)
1482{
1483 struct sh_dirent * dirlist;
1484 struct sh_dirent * dirlist_orig;
1485
1486 DIR * thisDir = NULL;
1487 struct dirent * thisEntry;
1488 int status;
1489 int dummy = S_FALSE;
1490 dir_type * theDir;
1491 ShFileType checkit;
1492 static unsigned int state = 1;
1493
1494 file_type * theFile;
1495 char * tmpname;
1496 char * tmpcat;
1497 char errbuf[SH_ERRBUF_SIZE];
1498
1499 int rdepth = 0;
1500 int class = 0;
1501 int rdepth_next;
1502 int class_next;
1503 int file_class_next;
1504
1505 int checked_flag = S_FALSE;
1506 int cchecked_flag = S_FALSE;
1507
1508 dirstack_t * dst_ptr;
1509 dirstack_t * tmp_ptr;
1510
1511 int hardlink_num = 0;
1512#if !defined(HOST_IS_DARWIN)
1513 size_t len;
1514#endif
1515
1516 SL_ENTER(_("sh_files_checkdir"));
1517
1518 if (sig_urgent > 0) {
1519 SL_RETURN((0), _("sh_files_checkdir"));
1520 }
1521
1522 if (iname == NULL || idepth < (-1))
1523 SL_RETURN((-1), _("sh_files_checkdir"));
1524
1525 if (idepth < 0)
1526 {
1527 /* hash_remove_tree (iname); */
1528 SL_RETURN((0), _("sh_files_checkdir"));
1529 }
1530
1531 rdepth = idepth;
1532 class = iclass;
1533
1534 tmpname = sh_util_safe_name (iname);
1535
1536 /* ---- check for obscure name ----
1537 */
1538 if (iclass != SH_LEVEL_ALLIGNORE)
1539 {
1540 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1541 }
1542
1543 if (flag_err_info == SL_TRUE)
1544 {
1545 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, tmpname);
1546 }
1547
1548 /* ---- check input ----
1549 */
1550 if ( sl_strlen(iname) >= PATH_MAX)
1551 {
1552 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1553 MSG_FI_2LONG,
1554 tmpname);
1555 SH_FREE(tmpname);
1556 SL_RETURN((-1), _("sh_files_checkdir"));
1557 }
1558
1559 /* ---- check for absolute path ---- */
1560 if ( iname[0] != '/')
1561 {
1562 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1563 MSG_FI_NOPATH,
1564 tmpname);
1565 SH_FREE(tmpname);
1566 SL_RETURN((-1), _("sh_files_checkdir"));
1567 }
1568
1569
1570 /* ---- stat the directory ----
1571 */
1572 theFile = SH_ALLOC(sizeof(file_type));
1573 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
1574 theFile->attr_string = NULL;
1575 theFile->link_path = NULL;
1576
1577 (void) relativeName;
1578 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1579 iname,
1580 theFile, NULL, iclass);
1581
1582 if ((sig_termfast == 1) || (sig_terminate == 1))
1583 {
1584 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1585 if (theFile->link_path) SH_FREE(theFile->link_path);
1586 SH_FREE(theFile);
1587 SL_RETURN((0), _("sh_files_checkdir"));
1588 }
1589
1590 if (status == -1)
1591 {
1592 SH_FREE(tmpname);
1593 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1594 if (theFile->link_path) SH_FREE(theFile->link_path);
1595 SH_FREE(theFile);
1596 SL_RETURN((-1), _("sh_files_checkdir"));
1597 }
1598
1599 if (theFile->c_mode[0] != 'd')
1600 {
1601 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1602 MSG_FI_NODIR,
1603 tmpname);
1604 SH_FREE(tmpname);
1605 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1606 if (theFile->link_path) SH_FREE(theFile->link_path);
1607 SH_FREE(theFile);
1608 SL_RETURN((-1), _("sh_files_checkdir"));
1609 }
1610
1611 hardlink_num = theFile->hardlinks;
1612
1613 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1614 if (theFile->link_path) SH_FREE(theFile->link_path);
1615 SH_FREE(theFile);
1616
1617 /* ---- open directory for reading ----
1618 *
1619 * opendir() will fail with ENOTDIR if the path has been changed
1620 * to a non-directory in between lstat() and opendir().
1621 */
1622 thisDir = opendir (iname);
1623
1624 if (thisDir == NULL)
1625 {
1626 status = errno;
1627 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1628 MSG_E_OPENDIR,
1629 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
1630 SH_FREE(tmpname);
1631 SL_RETURN((-1), _("sh_files_checkdir"));
1632 }
1633
1634 theDir = SH_ALLOC(sizeof(dir_type));
1635
1636 theDir->NumRegular = 0;
1637 theDir->NumDirs = 0;
1638 theDir->NumSymlinks = 0;
1639 theDir->NumFifos = 0;
1640 theDir->NumSockets = 0;
1641 theDir->NumCDev = 0;
1642 theDir->NumBDev = 0;
1643 theDir->NumDoor = 0;
1644 theDir->NumPort = 0;
1645 theDir->NumAll = 0;
1646 theDir->TotalBytes = 0;
1647 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
1648
1649
1650 /* ---- read ----
1651 */
1652 SH_MUTEX_LOCK(mutex_readdir);
1653
1654 dirlist = NULL;
1655 dirlist_orig = NULL;
1656
1657 do {
1658 thisEntry = readdir (thisDir);
1659 if (thisEntry != NULL)
1660 {
1661 ++theDir->NumAll;
1662 if (sl_strcmp (thisEntry->d_name, ".") == 0)
1663 {
1664 ++theDir->NumDirs;
1665 continue;
1666 }
1667 if (sl_strcmp (thisEntry->d_name, "..") == 0)
1668 {
1669 ++theDir->NumDirs;
1670 continue;
1671 }
1672 dirlist = addto_sh_dirlist (thisEntry, dirlist);
1673 }
1674 } while (thisEntry != NULL);
1675
1676 SH_MUTEX_UNLOCK(mutex_readdir);
1677
1678 closedir (thisDir);
1679
1680 ++sh.statistics.dirs_checked;
1681
1682 dirlist_orig = dirlist;
1683
1684 do {
1685
1686 /* If the directory is empty, dirlist = NULL
1687 */
1688 if (!dirlist)
1689 break;
1690
1691 if (sig_termfast == 1)
1692 {
1693 SH_FREE(theDir);
1694 SL_RETURN((0), _("sh_files_checkdir"));
1695 }
1696
1697 BREAKEXIT(sh_derr);
1698
1699#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1700 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
1701#else
1702 if (0 == state * (rand() % 5)) (void) sh_derr();
1703#endif
1704
1705 /* ---- Check the file. ----
1706 */
1707 tmpcat = SH_ALLOC(PATH_MAX);
1708 sl_strlcpy(tmpcat, iname, PATH_MAX);
1709 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
1710 sl_strlcat(tmpcat, "/", PATH_MAX);
1711 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
1712
1713 rdepth_next = rdepth - 1;
1714 class_next = class;
1715 file_class_next = class;
1716 checked_flag = -1;
1717 cchecked_flag = -1;
1718
1719 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
1720 * this fixes the problem that the directory special file
1721 * is checked with the policy of the parent directory
1722 */
1723 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1724
1725 if (dst_ptr)
1726 {
1727 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1728 * this fixes the problem that a policy for the directory
1729 * inode erroneously becomes a policy for the directory itself.
1730 */
1731 file_class_next = dst_ptr->class;
1732 checked_flag = dst_ptr->checked;
1733 cchecked_flag = dst_ptr->childs_checked;
1734 }
1735
1736 if (checked_flag == -1)
1737 {
1738 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
1739
1740 if (dst_ptr)
1741 {
1742 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1743 * this fixes the problem that a policy for the directory
1744 * inode erroneously becomes a policy for the directory itself.
1745 */
1746 file_class_next = dst_ptr->class;
1747 checked_flag = dst_ptr->checked;
1748 cchecked_flag = dst_ptr->childs_checked;
1749 }
1750 }
1751
1752 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
1753
1754 if (dst_ptr)
1755 {
1756 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1757 * this fixes the problem that a policy for the directory
1758 * inode erroneously becomes a policy for the directory itself.
1759 */
1760 file_class_next = dst_ptr->class;
1761 checked_flag = dst_ptr->checked;
1762 /* not set, hence always FALSE */
1763 /* cchecked_flag = dst_ptr->childs_checked; */
1764 }
1765
1766 /* ---- Has been checked already. ----
1767 */
1768 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
1769 {
1770 /* Mar 11 2004 get ftype for complete directory count
1771 */
1772 checkit = sh_unix_get_ftype(tmpcat);
1773 if (checkit == SH_FILE_DIRECTORY)
1774 {
1775 ++theDir->NumDirs;
1776 }
1777 SH_FREE(tmpcat);
1778 dirlist = dirlist->next;
1779 continue;
1780 }
1781
1782 /* --- May be true, false, or not found. ---
1783 */
1784 if (checked_flag == S_TRUE)
1785 {
1786 /* -- need only the file type --
1787 */
1788 checkit = sh_unix_get_ftype(tmpcat);
1789 }
1790 else
1791 {
1792 /* -- need to check the file itself --
1793 */
1794 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1795 dummy = dst_ptr->is_reported;
1796
1797 checkit = sh_files_filecheck (file_class_next,
1798 iname,
1799 dirlist->sh_d_name,
1800 &dummy, 0);
1801
1802 if (dst_ptr && checked_flag == S_FALSE)
1803 dst_ptr->checked = S_TRUE;
1804 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
1805 */
1806 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1807 dst_ptr->is_reported = dummy;
1808 }
1809
1810 if (checkit == SH_FILE_REGULAR)
1811 ++theDir->NumRegular;
1812
1813 else if (checkit == SH_FILE_DIRECTORY)
1814 {
1815 ++theDir->NumDirs;
1816 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
1817 {
1818 rdepth_next = rdepth - 1;
1819
1820 /* check whether the new directory is in the
1821 * list with a recursion depth already defined
1822 */
1823 checked_flag = -1;
1824 cchecked_flag = -1;
1825
1826 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1827
1828 if (tmp_ptr)
1829 {
1830 TPT((0, FIL__, __LINE__,
1831 _("msg=<%s -> recursion depth %d\n>"),
1832 tmp_ptr->name, tmp_ptr->rdepth));
1833 rdepth_next = tmp_ptr->rdepth;
1834 class_next = tmp_ptr->class;
1835 /* 28. Aug 2001 reversed
1836 */
1837 cchecked_flag = tmp_ptr->childs_checked;
1838 checked_flag = tmp_ptr->checked;
1839 }
1840
1841 if (checked_flag == -1)
1842 {
1843 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
1844
1845 if (tmp_ptr)
1846 {
1847 TPT((0, FIL__, __LINE__,
1848 _("msg=<%s -> recursion depth %d\n>"),
1849 tmp_ptr->name, tmp_ptr->rdepth));
1850 rdepth_next = tmp_ptr->rdepth;
1851 class_next = tmp_ptr->class;
1852 /* 28. Aug 2001 reversed
1853 */
1854 cchecked_flag = tmp_ptr->childs_checked;
1855 checked_flag = tmp_ptr->checked;
1856 }
1857 }
1858
1859 if (cchecked_flag == S_FALSE)
1860 {
1861 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1862 dirlist->sh_d_name);
1863 tmp_ptr->childs_checked = S_TRUE;
1864 /*
1865 * 04. Feb 2006 avoid double checking
1866 */
1867 tmp_ptr->checked = S_TRUE;
1868 }
1869 else if (checked_flag == -1)
1870 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1871 dirlist->sh_d_name);
1872
1873 }
1874 }
1875
1876 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
1877 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
1878 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
1879 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
1880 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
1881 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
1882 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
1883
1884 SH_FREE(tmpcat);
1885
1886 if ((sig_termfast == 1) || (sig_terminate == 1))
1887 {
1888 SH_FREE(theDir);
1889 SL_RETURN((0), _("sh_files_checkdir"));
1890 }
1891
1892 dirlist = dirlist->next;
1893
1894 if (dst_ptr)
1895 dst_ptr->childs_checked = S_TRUE;
1896
1897 } while (dirlist != NULL);
1898
1899 if (flag_err_info == SL_TRUE)
1900 {
1901 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
1902 theDir->NumDirs,
1903 theDir->NumRegular,
1904 theDir->NumSymlinks,
1905 theDir->NumFifos,
1906 theDir->NumSockets,
1907 theDir->NumCDev,
1908 theDir->NumBDev);
1909 }
1910
1911 kill_sh_dirlist (dirlist_orig);
1912
1913#if !defined(HOST_IS_DARWIN)
1914 /*
1915 * Hardlink check; not done on MacOS X because of resource forks
1916 */
1917 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
1918 {
1919 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
1920 {
1921 len = strlen(tmpname);
1922 if (sl_ok_adds(len, 256))
1923 len += 256;
1924 tmpcat = SH_ALLOC(len);
1925 sl_snprintf(tmpcat, len,
1926 _("%s: subdirectory count (%d) != hardlinks (%d)"),
1927 tmpname, theDir->NumDirs, hardlink_num);
1928 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1929 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
1930 SH_FREE(tmpcat);
1931 }
1932 }
1933#endif
1934
1935 SH_FREE(tmpname);
1936 SH_FREE(theDir);
1937
1938 SL_RETURN((0), _("sh_files_checkdir"));
1939}
1940
1941int get_the_fd (SL_TICKET ticket);
1942
1943
1944static ShFileType sh_files_filecheck (int class, char * dirName,
1945 char * infileName,
1946 int * reported,
1947 int rsrcflag)
1948{
1949 /* 28 Aug 2001 allow NULL fileName
1950 */
1951 char * fullpath;
1952 char fileHash[2*(KEY_LEN + 1)];
1953 int status;
1954 file_type * theFile;
1955 char * tmpdir;
1956 char * tmpname;
1957 char * fileName;
1958 struct utimbuf utime_buf;
1959 static unsigned int state = 1;
1960 char sc;
1961
1962 SL_ENTER(_("sh_files_filecheck"));
1963
1964 fullpath = SH_ALLOC(PATH_MAX);
1965 theFile = SH_ALLOC(sizeof(file_type));
1966
1967 BREAKEXIT(sh_derr);
1968
1969#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1970 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
1971#else
1972 if (0 == state * (rand() % 2)) (void) sh_derr();
1973#endif
1974
1975 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
1976 && (infileName[0] == '/') && (infileName[1] == '\0'))
1977 {
1978 fileName = NULL;
1979 }
1980 else
1981 {
1982 fileName = infileName;
1983 }
1984
1985 /* fileName may be NULL if this is a directory
1986 */
1987 if (dirName == NULL /* || fileName == NULL */)
1988 {
1989 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
1990 SH_FREE(fullpath);
1991 SH_FREE(theFile);
1992 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
1993 }
1994
1995 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
1996 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
1997 fileName, S_FALSE)))
1998 {
1999 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2000 {
2001 tmpname = sh_util_safe_name (fileName);
2002 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2003 MSG_FI_OBSC2,
2004 "", tmpname);
2005 SH_FREE(tmpname);
2006 }
2007 else
2008 {
2009 tmpdir = sh_util_safe_name (dirName);
2010 tmpname = sh_util_safe_name (fileName);
2011 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2012 MSG_FI_OBSC2,
2013 tmpdir, tmpname);
2014 SH_FREE(tmpname);
2015 SH_FREE(tmpdir);
2016 }
2017 }
2018
2019 /* sh_files_fullpath accepts NULL fileName
2020 */
2021 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2022 {
2023 tmpdir = sh_util_safe_name (dirName);
2024 tmpname = sh_util_safe_name (fileName);
2025 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2026 MSG_FI_2LONG2,
2027 tmpdir, tmpname);
2028 SH_FREE(tmpname);
2029 SH_FREE(tmpdir);
2030 SH_FREE(fullpath);
2031 SH_FREE(theFile);
2032 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2033 }
2034
2035
2036 /* stat the file and determine checksum (if a regular file)
2037 */
2038 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2039 theFile->check_mask = sh_files_maskof(class);
2040 theFile->file_reported = (*reported);
2041 theFile->attr_string = NULL;
2042 theFile->link_path = NULL;
2043
2044 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2045
2046 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2047 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2048 fileName,
2049 theFile, fileHash, class);
2050
2051 if (status != 0)
2052 {
2053 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2054 fullpath, status));
2055 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2056 sh_hash_set_visited_true (fullpath);
2057 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2058 if (theFile->link_path) SH_FREE(theFile->link_path);
2059 SH_FREE(fullpath);
2060 SH_FREE(theFile);
2061 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2062 }
2063
2064 if (sig_termfast == 1) {
2065 goto ret_point;
2066 }
2067
2068 /* report
2069 */
2070 if ((flag_err_debug == SL_TRUE) && (theFile->c_mode[0] == '-'))
2071 {
2072 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2073 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2074 fileHash, tmpname);
2075 SH_FREE(tmpname);
2076 }
2077 ++sh.statistics.files_checked;
2078
2079 if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */)
2080 {
2081 sh_hash_pushdata (theFile, fileHash);
2082 }
2083 else if (sh.flag.checkSum == SH_CHECK_CHECK
2084 /* && theFile.c_mode[0] == '-' */
2085 /* && class != SH_LEVEL_ALLIGNORE */
2086 )
2087 {
2088 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2089 }
2090
2091 (*reported) = theFile->file_reported;
2092
2093 /* reset the access time
2094 */
2095 if (class == SH_LEVEL_NOIGNORE && (theFile->check_mask & MODI_ATM) != 0)
2096 {
2097 utime_buf.actime = (time_t) theFile->atime;
2098 utime_buf.modtime = (time_t) theFile->mtime;
2099#if !defined(O_NOATIME)
2100 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2101#endif
2102 }
2103
2104#ifdef HOST_IS_DARWIN
2105 /*
2106 * Check for resource fork
2107 */
2108 if ( (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2109 {
2110 int dummy;
2111 static int rsrc_init = 0;
2112 static char rsrc[17];
2113 char * testpath = SH_ALLOC(PATH_MAX);
2114
2115 if (rsrc_init == 0) {
2116 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2117 rsrc_init = 1;
2118 }
2119 sl_strlcpy (testpath, fullpath, PATH_MAX);
2120 sl_strlcat (testpath, "/", PATH_MAX);
2121 sl_strlcat (testpath, rsrc, PATH_MAX);
2122
2123 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2124 {
2125 if (S_TRUE == sh_unix_file_exists (testpath))
2126 {
2127 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
2128 }
2129 }
2130 SH_FREE(testpath);
2131 }
2132#else
2133 (void) rsrcflag; /* avoid compiler warning */
2134#endif
2135
2136 ret_point:
2137
2138 sc = theFile->c_mode[0];
2139
2140 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2141 if (theFile->link_path) SH_FREE(theFile->link_path);
2142 SH_FREE(fullpath);
2143 SH_FREE(theFile);
2144
2145 switch (sc)
2146 {
2147 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2148 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2149 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2150 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2151 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2152 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2153 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2154 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2155 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2156 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2157 }
2158
2159 /* notreached */
2160}
2161
2162/* concatenate statpath = testdir"/"d_name
2163 */
2164static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
2165{
2166 int llen = 0;
2167
2168 SL_ENTER(_("sh_files_fullpath"));
2169
2170 if (testdir != NULL)
2171 {
2172 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2173 SL_RETURN((-1),_("sh_files_fullpath"));
2174 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2175 }
2176 if (d_name != NULL)
2177 {
2178 if (llen > 1 || statpath[0] != '/')
2179 sl_strlcat(statpath, "/", PATH_MAX);
2180 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2181 SL_RETURN((-1),_("sh_files_fullpath"));
2182 sl_strlcat(statpath, d_name, PATH_MAX);
2183 }
2184 if (statpath == NULL)
2185 SL_RETURN((-1),_("sh_files_fullpath"));
2186 SL_RETURN((0),_("sh_files_fullpath"));
2187}
2188
2189
2190/* -----------------------------------
2191 *
2192 * The following two routines serve to
2193 * verify that the user has selected
2194 * a proper setup for file policies.
2195 *
2196 * -----------------------------------
2197 */
2198static int check_file(char * name)
2199{
2200 dirstack_t * pfilL;
2201 zAVLCursor cursor;
2202
2203 SL_ENTER(_("check_file"));
2204
2205 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2206 SL_RETURN(0, _("check_file"));
2207
2208 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2209 pfilL = (dirstack_t *) zAVLNext (&cursor))
2210 {
2211 if (0 == strcmp(name, pfilL->name) &&
2212 (pfilL->check_mask & MODI_ATM) == 0 &&
2213 (pfilL->check_mask & MODI_CTM) == 0 &&
2214 (pfilL->check_mask & MODI_MTM) == 0)
2215 SL_RETURN(0, _("check_file"));
2216 }
2217 SL_RETURN((-1), _("check_file"));
2218}
2219
2220int sh_files_test_setup_int (zAVLTree * tree)
2221{
2222 int dlen, flen;
2223 zAVLCursor cursor1;
2224 zAVLCursor cursor2;
2225
2226 dirstack_t * pdirL;
2227 dirstack_t * pfilL;
2228
2229 SL_ENTER(_("sh_files_test_setup"));
2230
2231 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2232 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2233 {
2234 dlen = strlen(pdirL->name);
2235
2236 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2237 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2238 {
2239 flen = strlen(pfilL->name);
2240
2241 /* check whether file is in tree of dir
2242 */
2243 if ((pfilL->class == SH_LEVEL_READONLY) ||
2244 (pfilL->class == SH_LEVEL_NOIGNORE))
2245 {
2246 ; /* do nothing */
2247 }
2248 else
2249 {
2250 if ((flen > (dlen+1)) &&
2251 (pfilL->name[dlen] == '/') &&
2252 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2253 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2254 {
2255 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2256 (pdirL->check_mask & MODI_MTM) != 0 ||
2257 (pdirL->check_mask & MODI_CTM) != 0)
2258 {
2259 if (check_file (pdirL->name) != 0)
2260 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2261 pdirL->name, pfilL->name);
2262 }
2263 }
2264 }
2265 }
2266 }
2267
2268 SL_RETURN((0), _("sh_files_test_setup"));
2269}
2270
2271int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2272{
2273 int retval = 0;
2274 zAVLCursor cursor;
2275 dirstack_t * first;
2276
2277 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2278 first = (dirstack_t *) zAVLNext (&cursor))
2279 {
2280
2281 if (NULL != zAVLSearch(secondList, first->name))
2282 {
2283 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2284 first->name);
2285 retval = 1;
2286 }
2287 }
2288 return retval;
2289}
2290
2291extern void aud_exit (const char * file, int line, int fd);
2292
2293int sh_files_test_setup ()
2294{
2295 int retval = 0;
2296
2297 /* Test for modifications allowed in ReadOnly directory
2298 */
2299 sh_files_test_setup_int (zdirListOne);
2300 sh_files_test_setup_int (zdirListTwo);
2301
2302 /* Test for files/dirz defined twice
2303 */
2304 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2305 if (retval != 0)
2306 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2307
2308 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2309 if (retval != 0)
2310 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2311
2312
2313 /*
2314 retval = sh_files_test_double (zfileList, NULL);
2315 if (retval != 0)
2316 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2317 */
2318 return 0;
2319}
2320
2321#endif
Note: See TracBrowser for help on using the repository browser.