source: trunk/src/sh_files.c@ 136

Last change on this file since 136 was 132, checked in by rainer, 17 years ago

Make utility functions thread-safe.

File size: 54.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
37#ifdef HAVE_DIRENT_H
38#include <dirent.h>
39#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
40#else
41#define dirent direct
42#define NAMLEN(dirent) (dirent)->d_namlen
43#ifdef HAVE_SYS_NDIR_H
44#include <sys/ndir.h>
45#endif
46#ifdef HAVE_SYS_DIR_H
47#include <sys/dir.h>
48#endif
49#ifdef HAVE_NDIR_H
50#include <ndir.h>
51#endif
52#endif
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
618 }
619 }
620 SL_RETURN ( (0), _("sh_files_parse_mask"));
621}
622
623int sh_files_redef_prelink(const char * str)
624{
625 return (sh_files_parse_mask(&mask_PRELINK, str));
626}
627int sh_files_redef_user0(const char * str)
628{
629 return (sh_files_parse_mask(&mask_USER0, str));
630}
631int sh_files_redef_user1(const char * str)
632{
633 return (sh_files_parse_mask(&mask_USER1, str));
634}
635int sh_files_redef_user2(const char * str)
636{
637 return (sh_files_parse_mask(&mask_USER2, str));
638}
639int sh_files_redef_user3(const char * str)
640{
641 return (sh_files_parse_mask(&mask_USER3, str));
642}
643int sh_files_redef_user4(const char * str)
644{
645 return (sh_files_parse_mask(&mask_USER4, str));
646}
647int sh_files_redef_readonly(const char * str)
648{
649 return (sh_files_parse_mask(&mask_READONLY, str));
650}
651int sh_files_redef_loggrow(const char * str)
652{
653 return (sh_files_parse_mask(&mask_LOGGROW, str));
654}
655int sh_files_redef_logfiles(const char * str)
656{
657 return (sh_files_parse_mask(&mask_LOGFILES, str));
658}
659int sh_files_redef_attributes(const char * str)
660{
661 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
662}
663int sh_files_redef_noignore(const char * str)
664{
665 return (sh_files_parse_mask(&mask_NOIGNORE, str));
666}
667int sh_files_redef_allignore(const char * str)
668{
669 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
670}
671
672unsigned long sh_files_maskof (int class)
673{
674 switch (class)
675 {
676 case SH_LEVEL_READONLY:
677 return (unsigned long) mask_READONLY;
678 case SH_LEVEL_ATTRIBUTES:
679 return (unsigned long) mask_ATTRIBUTES;
680 case SH_LEVEL_LOGFILES:
681 return (unsigned long) mask_LOGFILES;
682 case SH_LEVEL_LOGGROW:
683 return (unsigned long) mask_LOGGROW;
684 case SH_LEVEL_ALLIGNORE:
685 return (unsigned long) mask_ALLIGNORE;
686 case SH_LEVEL_NOIGNORE:
687 return (unsigned long) mask_NOIGNORE;
688 case SH_LEVEL_USER0:
689 return (unsigned long) mask_USER0;
690 case SH_LEVEL_USER1:
691 return (unsigned long) mask_USER1;
692 case SH_LEVEL_USER2:
693 return (unsigned long) mask_USER2;
694 case SH_LEVEL_USER3:
695 return (unsigned long) mask_USER3;
696 case SH_LEVEL_USER4:
697 return (unsigned long) mask_USER4;
698 case SH_LEVEL_PRELINK:
699 return (unsigned long) mask_PRELINK;
700 default:
701 return (unsigned long) 0;
702 }
703}
704
705#ifdef HAVE_GLOB_H
706int sh_files_has_metachar (const char * str)
707{
708 SL_ENTER(_("sh_files_has_metachar"));
709 if (NULL != strchr(str, '*'))
710 SL_RETURN(1, _("sh_files_has_metachar"));
711 else if (NULL != strchr(str, '?'))
712 SL_RETURN(1, _("sh_files_has_metachar"));
713 else if (NULL != (strchr(str, '[')))
714 SL_RETURN(1, _("sh_files_has_metachar"));
715 else
716 SL_RETURN(0, _("sh_files_has_metachar"));
717}
718
719
720int sh_files_globerr (const char * epath, int errnum)
721{
722 char * p;
723 char errbuf[SH_ERRBUF_SIZE];
724
725 SL_ENTER(_("sh_files_globerr"));
726
727 if (errnum == ENOTDIR || errnum == ENOENT)
728 {
729 SL_RETURN(0, _("sh_files_globerr"));
730 }
731
732 p = sh_util_safe_name (epath);
733 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
734 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
735 SH_FREE(p);
736
737 SL_RETURN(0, _("sh_files_globerr"));
738}
739
740/* #ifdef HAVE_GLOB_H
741 */
742#endif
743
744int sh_files_push_file_int (int class, const char * str_s, size_t len)
745{
746 dirstack_t * new_item_ptr;
747 char * fileName;
748 int ret;
749
750 SL_ENTER(_("sh_files_push_file_int"));
751
752 fileName = SH_ALLOC(len+1);
753 sl_strlcpy(fileName, str_s, len+1);
754
755 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
756
757 new_item_ptr->name = fileName;
758 new_item_ptr->class = class;
759 new_item_ptr->check_mask = sh_files_maskof(class);
760 new_item_ptr->rdepth = 0;
761 new_item_ptr->checked = S_FALSE;
762 new_item_ptr->is_reported = 0;
763 new_item_ptr->childs_checked = S_FALSE;
764
765 if (zfileList == NULL)
766 {
767 zfileList = zAVLAllocTree (zdirstack_key);
768 if (zfileList == NULL)
769 {
770 (void) safe_logger (0, 0, NULL);
771 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
772 }
773 }
774
775 ret = zAVLInsert (zfileList, new_item_ptr);
776
777 if (-1 == ret)
778 {
779 (void) safe_logger (0, 0, NULL);
780 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
781 }
782 if (3 == ret)
783 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
784 fileName);
785
786 SL_RETURN(0, _("sh_files_push_file_int"));
787}
788
789
790static int sh_files_pushfile (int class, const char * str_s)
791{
792 size_t len;
793 char * tmp;
794 char * p;
795#ifdef HAVE_GLOB_H
796 int globstatus = -1;
797 unsigned int gloop;
798 glob_t pglob;
799#endif
800
801 static int reject = 0;
802
803 SL_ENTER(_("sh_files_pushfile"));
804
805 if (reject == 1)
806 SL_RETURN((-1),_("sh_files_pushfile"));
807
808 /* if we push a filename from the command line, make sure it
809 * is the only one -- and will stay the only one
810 */
811 if (sh.flag.opts == 1)
812 {
813 sh_files_delfilestack ();
814 sh_files_deldirstack ();
815 reject = 1;
816 }
817
818 if (str_s == NULL)
819 SL_RETURN((-1),_("sh_files_pushfile"));
820
821 len = sl_strlen(str_s);
822
823 if (len >= PATH_MAX)
824 {
825 /* Name too long
826 */
827 tmp = sh_util_safe_name (str_s);
828 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
829 tmp);
830 SH_FREE(tmp);
831 SL_RETURN((-1),_("sh_files_pushfile"));
832 }
833 else if (len < 1)
834 {
835 /* Should not happen (str_s == NULL caught further above)
836 */
837 SL_RETURN((-1),_("sh_files_pushfile"));
838 }
839 else if (str_s[0] != '/')
840 {
841 /* Not an absolute path
842 */
843 tmp = sh_util_safe_name (str_s);
844 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
845 tmp);
846 SH_FREE(tmp);
847 SL_RETURN((-1),_("sh_files_pushfile"));
848 }
849 else
850 {
851 /* remove a terminating '/', take care of the
852 * special case of the root directory.
853 */
854 p = sh_util_strdup (str_s);
855 if (p[len-1] == '/' && len > 1)
856 {
857 p[len-1] = '\0';
858 --len;
859 }
860
861 }
862
863#ifdef HAVE_GLOB_H
864 if (0 == sh_files_has_metachar(p))
865 {
866 sh_files_push_file_int (class, p, len);
867 }
868 else
869 {
870 pglob.gl_offs = 0;
871 globstatus = glob (p, 0, sh_files_globerr, &pglob);
872
873 if (globstatus == 0 && pglob.gl_pathc > 0)
874 {
875 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
876 sh_files_push_file_int (class, pglob.gl_pathv[gloop],
877 sl_strlen(pglob.gl_pathv[gloop]));
878 }
879 else
880 {
881 tmp = sh_util_safe_name (p);
882
883 if (pglob.gl_pathc == 0
884#ifdef GLOB_NOMATCH
885 || globstatus == GLOB_NOMATCH
886#endif
887 )
888 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
889 globstatus, MSG_FI_GLOB,
890 _("No matches found"), tmp);
891#ifdef GLOB_NOSPACE
892 else if (globstatus == GLOB_NOSPACE)
893 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
894 globstatus, MSG_FI_GLOB,
895 _("Out of memory"), tmp);
896#endif
897#ifdef GLOB_ABORTED
898 else if (globstatus == GLOB_ABORTED)
899 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
900 globstatus, MSG_FI_GLOB,
901 _("Read error"), tmp);
902#endif
903 else
904 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
905 globstatus, MSG_FI_GLOB,
906 _("Unknown error"), tmp);
907
908 SH_FREE(tmp);
909
910 }
911
912 globfree(&pglob);
913 }
914
915#else
916 sh_files_push_file_int (class, p, len);
917#endif
918
919 SH_FREE(p);
920 SL_RETURN((0),_("sh_files_pushfile"));
921}
922
923
924/* ------ directories ----- */
925
926int sh_files_is_allignore_int (char * str, zAVLTree * tree)
927{
928 dirstack_t * ptr;
929
930 SL_ENTER(_("sh_files_is_allignore"));
931
932 if (tree)
933 {
934 ptr = zAVLSearch(tree, str);
935 if (ptr)
936 {
937 if (ptr->class == SH_LEVEL_ALLIGNORE)
938 SL_RETURN( 1, _("sh_files_is_allignore"));
939 else
940 SL_RETURN( 0, _("sh_files_is_allignore"));
941 }
942 }
943 SL_RETURN( 0, _("sh_files_is_allignore"));
944}
945
946int sh_files_is_allignore (char * str)
947{
948 if (1 == sh_files_is_allignore_int(str, zdirListOne))
949 return 1;
950 if (NULL == zdirListTwo)
951 return 0;
952 return sh_files_is_allignore_int(str, zdirListTwo);
953}
954
955unsigned long sh_dirs_chk (int which)
956{
957 zAVLTree * tree;
958 zAVLCursor cursor;
959 dirstack_t * ptr;
960 dirstack_t * dst_ptr;
961 int status;
962 unsigned long dcount = 0;
963 char * tmp;
964
965 SL_ENTER(_("sh_dirs_chk"));
966
967 if (which == 1)
968 tree = zdirListOne;
969 else
970 tree = zdirListTwo;
971
972 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
973 ptr = (dirstack_t *) zAVLNext(&cursor))
974 {
975 if (sig_urgent > 0) {
976 SL_RETURN(dcount, _("sh_dirs_chk"));
977 }
978
979 if (ptr->checked == S_FALSE)
980 {
981 /* 28 Aug 2001 check the top level directory
982 */
983 status = S_FALSE;
984 dst_ptr = zAVLSearch(zfileList, ptr->name);
985 if (dst_ptr)
986 {
987 if (dst_ptr->checked == S_FALSE)
988 {
989 BREAKEXIT(sh_files_filecheck);
990 sh_files_filecheck (dst_ptr->class, ptr->name,
991 NULL, &status, 0);
992 dst_ptr->checked = S_TRUE;
993 status = S_TRUE;
994 }
995 else
996 {
997 status = S_TRUE;
998 }
999 }
1000
1001 if (status == S_FALSE)
1002 sh_files_filecheck (ptr->class, ptr->name, NULL, &status, 0);
1003
1004 BREAKEXIT(sh_files_checkdir);
1005 status = sh_files_checkdir (ptr->class, ptr->rdepth, ptr->name,
1006 ptr->name);
1007
1008 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1009 {
1010 /* directory is missing
1011 */
1012 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1013 {
1014 if (0 != hashreport_missing(ptr->name,
1015 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1016 ShDFLevel[ptr->class] :
1017 ShDFLevel[SH_ERR_T_DIR])) {
1018 tmp = sh_util_safe_name (ptr->name);
1019 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1020 ShDFLevel[ptr->class] :
1021 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1022 0, MSG_FI_MISS, tmp);
1023 SH_FREE(tmp);
1024 }
1025 }
1026 if (sh.flag.reportonce == S_TRUE)
1027 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1028 }
1029 else
1030 {
1031 /* exists (status >= 0), but was missing (reported == TRUE)
1032 */
1033 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1034 {
1035 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1036#if 0
1037 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1038 * above, which will catch missing directories anyway
1039 */
1040 tmp = sh_util_safe_name (ptr->name);
1041 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1042 ShDFLevel[ptr->class] :
1043 ShDFLevel[SH_ERR_T_DIR],
1044 FIL__, __LINE__, 0, MSG_FI_ADD,
1045 tmp);
1046 SH_FREE(tmp);
1047#endif
1048 }
1049 else if (status == SH_FILE_UNKNOWN)
1050 {
1051 /* catchall
1052 */
1053 tmp = sh_util_safe_name (ptr->name);
1054 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1055 MSG_FI_FAIL,
1056 tmp);
1057 SH_FREE(tmp);
1058 if (sh.flag.checkSum != SH_CHECK_INIT)
1059 sh_hash_set_visited_true(ptr->name);
1060 }
1061
1062 ++dcount;
1063 }
1064 ptr->checked = S_TRUE;
1065 ptr->childs_checked = S_TRUE;
1066 }
1067
1068 if (sig_urgent > 0) {
1069 SL_RETURN(dcount, _("sh_dirs_chk"));
1070 }
1071
1072 }
1073 SL_RETURN(dcount, _("sh_dirs_chk"));
1074}
1075
1076int sh_files_pushdir_prelink (const char * str_s)
1077{
1078 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1079}
1080
1081int sh_files_pushdir_user0 (const char * str_s)
1082{
1083 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1084}
1085
1086int sh_files_pushdir_user1 (const char * str_s)
1087{
1088 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1089}
1090
1091int sh_files_pushdir_user2 (const char * str_s)
1092{
1093 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1094}
1095
1096int sh_files_pushdir_user3 (const char * str_s)
1097{
1098 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1099}
1100
1101int sh_files_pushdir_user4 (const char * str_s)
1102{
1103 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1104}
1105
1106int sh_files_pushdir_attr (const char * str_s)
1107{
1108 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1109}
1110
1111int sh_files_pushdir_ro (const char * str_s)
1112{
1113 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1114}
1115
1116int sh_files_pushdir_log (const char * str_s)
1117{
1118 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1119}
1120
1121int sh_files_pushdir_glog (const char * str_s)
1122{
1123 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1124}
1125
1126int sh_files_pushdir_noig (const char * str_s)
1127{
1128 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1129}
1130
1131int sh_files_pushdir_allig (const char * str_s)
1132{
1133 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1134}
1135
1136static int which_dirList = 1;
1137
1138int set_dirList (int which)
1139{
1140 if (which == 2)
1141 which_dirList = 2;
1142 else
1143 which_dirList = 1;
1144 return 0;
1145}
1146
1147int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth)
1148{
1149 zAVLTree * tree;
1150 dirstack_t * new_item_ptr;
1151 char * dirName;
1152 int ret;
1153
1154 SL_ENTER(_("sh_files_push_dir_int"));
1155
1156 dirName = SH_ALLOC(len+1);
1157 sl_strlcpy(dirName, tail, len+1);
1158
1159 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1160
1161 new_item_ptr->name = dirName;
1162 new_item_ptr->class = class;
1163 new_item_ptr->check_mask = sh_files_maskof(class);
1164 new_item_ptr->rdepth = rdepth;
1165 new_item_ptr->checked = S_FALSE;
1166 new_item_ptr->is_reported = 0;
1167 new_item_ptr->childs_checked = S_FALSE;
1168
1169 if (which_dirList == 1)
1170 {
1171 tree = zdirListOne;
1172 }
1173 else
1174 {
1175 tree = zdirListTwo;
1176 }
1177
1178 if (tree == NULL)
1179 {
1180 tree = zAVLAllocTree (zdirstack_key);
1181 if (tree == NULL)
1182 {
1183 (void) safe_logger (0, 0, NULL);
1184 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1185 }
1186 if (which_dirList == 1)
1187 zdirListOne = tree;
1188 else
1189 zdirListTwo = tree;
1190 }
1191
1192 ret = zAVLInsert (tree, new_item_ptr);
1193
1194 if (-1 == ret)
1195 {
1196 (void) safe_logger (0, 0, NULL);
1197 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1198 }
1199 if (3 == ret)
1200 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1201 dirName);
1202
1203 SL_RETURN(0, _("sh_files_push_dir_int"));
1204}
1205
1206static int sh_files_pushdir (int class, const char * str_s)
1207{
1208 char * tmp;
1209 size_t len;
1210 int rdepth = 0;
1211 char * tail = NULL;
1212 char * p;
1213
1214#ifdef HAVE_GLOB_H
1215 glob_t pglob;
1216 int globstatus = -1;
1217 unsigned int gloop;
1218#endif
1219
1220 SL_ENTER(_("sh_files_pushdir"));
1221
1222 if (sh.flag.opts == 1) {
1223 sh_files_delfilestack ();
1224 sh_files_deldirstack ();
1225 }
1226
1227 if (str_s == NULL)
1228 SL_RETURN((-1), _("sh_files_pushdir"));
1229
1230 p = sh_util_strdup (str_s);
1231
1232 if (p[0] != '/')
1233 {
1234 rdepth = strtol(p, &tail, 10);
1235 if (tail == p)
1236 {
1237 SH_FREE(p);
1238 SL_RETURN((-1), _("sh_files_pushdir"));
1239 }
1240 }
1241 else
1242 tail = p;
1243
1244
1245 if (rdepth < (-1) || tail == p || rdepth > 99)
1246 rdepth = (-2);
1247
1248 len = sl_strlen(tail);
1249
1250 if (len >= PATH_MAX)
1251 {
1252 tmp = sh_util_safe_name (tail);
1253 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1254 tmp);
1255 SH_FREE(tmp);
1256 SH_FREE(p);
1257 SL_RETURN((-1), _("sh_files_pushdir"));
1258 }
1259 else if (len < 1)
1260 {
1261 SH_FREE(p);
1262 SL_RETURN((-1), _("sh_files_pushdir"));
1263 }
1264 else if (tail[0] != '/')
1265 {
1266 tmp = sh_util_safe_name (tail);
1267 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1268 tmp);
1269 SH_FREE(tmp);
1270 SH_FREE(p);
1271 SL_RETURN((-1), _("sh_files_pushdir"));
1272 }
1273 else
1274 {
1275
1276 if (tail[len-1] == '/' && len > 1)
1277 {
1278 tail[len-1] = '\0';
1279 --len;
1280 }
1281
1282 }
1283
1284#ifdef HAVE_GLOB_H
1285 if (0 == sh_files_has_metachar(tail))
1286 {
1287 sh_files_push_dir_int (class, tail, len, rdepth);
1288 }
1289 else
1290 {
1291 pglob.gl_offs = 0;
1292 globstatus = glob (tail, 0, sh_files_globerr, &pglob);
1293
1294 if (globstatus == 0 && pglob.gl_pathc > 0)
1295 {
1296 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1297 sh_files_push_dir_int (class,
1298 pglob.gl_pathv[gloop],
1299 sl_strlen(pglob.gl_pathv[gloop]),
1300 rdepth);
1301 }
1302 else
1303 {
1304 tmp = sh_util_safe_name (tail);
1305
1306 if (pglob.gl_pathc == 0
1307#ifdef GLOB_NOMATCH
1308 || globstatus == GLOB_NOMATCH
1309#endif
1310 )
1311 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1312 globstatus, MSG_FI_GLOB,
1313 _("No matches found"), tmp);
1314#ifdef GLOB_NOSPACE
1315 else if (globstatus == GLOB_NOSPACE)
1316 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1317 globstatus, MSG_FI_GLOB,
1318 _("Out of memory"), tmp);
1319#endif
1320#ifdef GLOB_ABORTED
1321 else if (globstatus == GLOB_ABORTED)
1322 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1323 globstatus, MSG_FI_GLOB,
1324 _("Read error"), tmp);
1325#endif
1326 else
1327 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1328 globstatus, MSG_FI_GLOB,
1329 _("Unknown error"), tmp);
1330 SH_FREE(tmp);
1331 }
1332
1333 globfree(&pglob);
1334 }
1335#else
1336 sh_files_push_dir_int (class, tail, len, rdepth);
1337#endif
1338
1339 SH_FREE(p);
1340 SL_RETURN((0), _("sh_files_pushdir"));
1341}
1342
1343/**
1344struct sh_dirent {
1345 char * sh_d_name;
1346 struct sh_dirent * next;
1347};
1348**/
1349
1350void kill_sh_dirlist (struct sh_dirent * dirlist)
1351{
1352 struct sh_dirent * this;
1353
1354 while (dirlist)
1355 {
1356 this = dirlist->next;
1357 SH_FREE(dirlist->sh_d_name);
1358 SH_FREE(dirlist);
1359 dirlist = this;
1360 }
1361 return;
1362}
1363
1364/* -- add an entry to a directory listing
1365 */
1366struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1367 struct sh_dirent * dirlist)
1368{
1369 struct sh_dirent * this;
1370 size_t len;
1371
1372 if (thisEntry == NULL)
1373 return dirlist;
1374
1375 len = sl_strlen(thisEntry->d_name);
1376 if (len == 0)
1377 return dirlist;
1378 ++len;
1379
1380 this = SH_ALLOC(sizeof(struct sh_dirent));
1381 if (!this)
1382 return dirlist;
1383
1384 this->sh_d_name = SH_ALLOC(len);
1385 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1386
1387 this->next = dirlist;
1388 return this;
1389}
1390
1391static int sh_check_hardlinks = S_TRUE;
1392
1393/* Simply sets our boolean as to whether this check is active
1394 */
1395int sh_files_check_hardlinks (const char * opt)
1396{
1397 int i;
1398 SL_ENTER(_("sh_files_check_hardlinks"));
1399 i = sh_util_flagval(opt, &sh_check_hardlinks);
1400 SL_RETURN(i, _("sh_files_check_hardlinks"));
1401}
1402
1403struct sh_hle_struct {
1404 long offset;
1405 char * path;
1406 struct sh_hle_struct * next;
1407};
1408
1409static struct sh_hle_struct * sh_hl_exc = NULL;
1410
1411int sh_files_hle_reg (const char * str)
1412{
1413 long offset;
1414 size_t len;
1415 char * path;
1416
1417 struct sh_hle_struct * tmp = sh_hl_exc;
1418
1419 SL_ENTER(_("sh_files_hle_reg"));
1420
1421 /* Free the linked list if called with NULL argument
1422 */
1423 if (str == NULL)
1424 {
1425 while (tmp)
1426 {
1427 sh_hl_exc = tmp->next;
1428 SH_FREE(tmp->path);
1429 SH_FREE(tmp);
1430 tmp = sh_hl_exc;
1431 }
1432 sh_hl_exc = NULL;
1433 SL_RETURN(0, _("sh_files_hle_reg"));
1434 }
1435
1436 /* We expect 'offset:/path'
1437 */
1438 offset = strtol(str, &path, 0);
1439 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1440 {
1441 SL_RETURN(-1, _("sh_files_hle_reg"));
1442 }
1443 ++path;
1444 len = 1 + sl_strlen(path);
1445
1446 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1447 tmp->path = SH_ALLOC(len);
1448 sl_strlcpy (tmp->path, path, len);
1449 tmp->offset = offset;
1450 tmp->next = sh_hl_exc;
1451 sh_hl_exc = tmp;
1452
1453 SL_RETURN(0, _("sh_files_hle_reg"));
1454}
1455
1456#if !defined(HOST_IS_DARWIN)
1457static int sh_files_hle_test (int offset, char * path)
1458{
1459 struct sh_hle_struct * tmp = sh_hl_exc;
1460
1461 SL_ENTER(_("sh_files_hle_reg"));
1462
1463 while(tmp)
1464 {
1465 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1466 {
1467 SL_RETURN(0, _("sh_files_hle_test"));
1468 }
1469 tmp = tmp->next;
1470 }
1471 SL_RETURN(-1, _("sh_files_hle_test"));
1472}
1473#endif
1474
1475/* -- check a single directory and its content
1476 */
1477static int sh_files_checkdir (int iclass, int idepth, char * iname,
1478 char * relativeName)
1479{
1480 struct sh_dirent * dirlist = NULL;
1481 struct sh_dirent * dirlist_orig = NULL;
1482
1483 DIR * thisDir = NULL;
1484 struct dirent * thisEntry;
1485 int status;
1486 int dummy = S_FALSE;
1487 dir_type theDir;
1488 ShFileType checkit;
1489 static unsigned int state = 1;
1490
1491 file_type theFile;
1492 char * tmpname;
1493 char * tmpcat;
1494 char errbuf[SH_ERRBUF_SIZE];
1495
1496 int rdepth = 0;
1497 int class = 0;
1498 int rdepth_next;
1499 int class_next;
1500 int file_class_next;
1501
1502 int checked_flag = S_FALSE;
1503 int cchecked_flag = S_FALSE;
1504
1505 dirstack_t * dst_ptr;
1506 dirstack_t * tmp_ptr;
1507
1508 int hardlink_num = 0;
1509#if !defined(HOST_IS_DARWIN)
1510 size_t len;
1511#endif
1512
1513 SL_ENTER(_("sh_files_checkdir"));
1514
1515 if (sig_urgent > 0) {
1516 SL_RETURN((0), _("sh_files_checkdir"));
1517 }
1518
1519 if (iname == NULL || idepth < (-1))
1520 SL_RETURN((-1), _("sh_files_checkdir"));
1521
1522 if (idepth < 0)
1523 {
1524 /* hash_remove_tree (iname); */
1525 SL_RETURN((0), _("sh_files_checkdir"));
1526 }
1527
1528 rdepth = idepth;
1529 class = iclass;
1530
1531 tmpname = sh_util_safe_name (iname);
1532
1533 /* ---- check for obscure name ----
1534 */
1535 if (iclass != SH_LEVEL_ALLIGNORE)
1536 {
1537 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1538 }
1539
1540 if (flag_err_info == SL_TRUE)
1541 {
1542 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, tmpname);
1543 }
1544
1545 /* ---- check input ----
1546 */
1547 if ( sl_strlen(iname) >= PATH_MAX)
1548 {
1549 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1550 MSG_FI_2LONG,
1551 tmpname);
1552 SH_FREE(tmpname);
1553 SL_RETURN((-1), _("sh_files_checkdir"));
1554 }
1555
1556 /* ---- check for absolute path ---- */
1557 if ( iname[0] != '/')
1558 {
1559 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1560 MSG_FI_NOPATH,
1561 tmpname);
1562 SH_FREE(tmpname);
1563 SL_RETURN((-1), _("sh_files_checkdir"));
1564 }
1565
1566
1567 /* ---- stat the directory ----
1568 */
1569 sl_strlcpy (theFile.fullpath, iname, PATH_MAX);
1570 theFile.attr_string = NULL;
1571
1572 (void) relativeName;
1573 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1574 iname,
1575 &theFile, NULL, iclass);
1576
1577 if ((sig_termfast == 1) || (sig_terminate == 1))
1578 {
1579 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1580 SL_RETURN((0), _("sh_files_checkdir"));
1581 }
1582
1583 if (status == -1)
1584 {
1585 SH_FREE(tmpname);
1586 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1587 SL_RETURN((-1), _("sh_files_checkdir"));
1588 }
1589
1590 if (theFile.c_mode[0] != 'd')
1591 {
1592 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1593 MSG_FI_NODIR,
1594 tmpname);
1595 SH_FREE(tmpname);
1596 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1597 SL_RETURN((-1), _("sh_files_checkdir"));
1598 }
1599
1600 hardlink_num = theFile.hardlinks;
1601
1602
1603 /* ---- open directory for reading ----
1604 *
1605 * opendir() will fail with ENOTDIR if the path has been changed
1606 * to a non-directory in between lstat() and opendir().
1607 */
1608 thisDir = opendir (iname);
1609
1610 if (thisDir == NULL)
1611 {
1612 status = errno;
1613 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1614 MSG_E_OPENDIR,
1615 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
1616 SH_FREE(tmpname);
1617
1618 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1619 SL_RETURN((-1), _("sh_files_checkdir"));
1620 }
1621
1622 theDir.NumRegular = 0;
1623 theDir.NumDirs = 0;
1624 theDir.NumSymlinks = 0;
1625 theDir.NumFifos = 0;
1626 theDir.NumSockets = 0;
1627 theDir.NumCDev = 0;
1628 theDir.NumBDev = 0;
1629 theDir.NumDoor = 0;
1630 theDir.NumPort = 0;
1631 theDir.NumAll = 0;
1632 theDir.TotalBytes = 0;
1633 sl_strlcpy (theDir.DirPath, iname, PATH_MAX);
1634
1635
1636 /* ---- read ----
1637 */
1638 SH_MUTEX_LOCK(readdir_lock);
1639
1640 do {
1641 thisEntry = readdir (thisDir);
1642 if (thisEntry != NULL)
1643 {
1644 ++theDir.NumAll;
1645 if (sl_strcmp (thisEntry->d_name, ".") == 0)
1646 {
1647 ++theDir.NumDirs;
1648 continue;
1649 }
1650 if (sl_strcmp (thisEntry->d_name, "..") == 0)
1651 {
1652 ++theDir.NumDirs;
1653 continue;
1654 }
1655 dirlist = addto_sh_dirlist (thisEntry, dirlist);
1656 }
1657 } while (thisEntry != NULL);
1658
1659 SH_MUTEX_UNLOCK(readdir_lock);
1660
1661 closedir (thisDir);
1662
1663 ++sh.statistics.dirs_checked;
1664
1665 dirlist_orig = dirlist;
1666
1667 do {
1668
1669 /* If the directory is empty, dirlist = NULL
1670 */
1671 if (!dirlist)
1672 break;
1673
1674 if (sig_termfast == 1)
1675 {
1676 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1677 SL_RETURN((0), _("sh_files_checkdir"));
1678 }
1679
1680 BREAKEXIT(sh_derr);
1681
1682#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1683 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
1684#else
1685 if (0 == state * (rand() % 5)) (void) sh_derr();
1686#endif
1687
1688 /* ---- Check the file. ----
1689 */
1690 tmpcat = SH_ALLOC(PATH_MAX);
1691 sl_strlcpy(tmpcat, iname, PATH_MAX);
1692 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
1693 sl_strlcat(tmpcat, "/", PATH_MAX);
1694 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
1695
1696 rdepth_next = rdepth - 1;
1697 class_next = class;
1698 file_class_next = class;
1699 checked_flag = -1;
1700 cchecked_flag = -1;
1701
1702 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
1703 * this fixes the problem that the directory special file
1704 * is checked with the policy of the parent directory
1705 */
1706 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1707
1708 if (dst_ptr)
1709 {
1710 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1711 * this fixes the problem that a policy for the directory
1712 * inode erroneously becomes a policy for the directory itself.
1713 */
1714 file_class_next = dst_ptr->class;
1715 checked_flag = dst_ptr->checked;
1716 cchecked_flag = dst_ptr->childs_checked;
1717 }
1718
1719 if (checked_flag == -1)
1720 {
1721 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
1722
1723 if (dst_ptr)
1724 {
1725 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1726 * this fixes the problem that a policy for the directory
1727 * inode erroneously becomes a policy for the directory itself.
1728 */
1729 file_class_next = dst_ptr->class;
1730 checked_flag = dst_ptr->checked;
1731 cchecked_flag = dst_ptr->childs_checked;
1732 }
1733 }
1734
1735 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
1736
1737 if (dst_ptr)
1738 {
1739 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1740 * this fixes the problem that a policy for the directory
1741 * inode erroneously becomes a policy for the directory itself.
1742 */
1743 file_class_next = dst_ptr->class;
1744 checked_flag = dst_ptr->checked;
1745 /* not set, hence always FALSE */
1746 /* cchecked_flag = dst_ptr->childs_checked; */
1747 }
1748
1749 /* ---- Has been checked already. ----
1750 */
1751 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
1752 {
1753 /* Mar 11 2004 get ftype for complete directory count
1754 */
1755 checkit = sh_unix_get_ftype(tmpcat);
1756 if (checkit == SH_FILE_DIRECTORY)
1757 {
1758 ++theDir.NumDirs;
1759 }
1760 SH_FREE(tmpcat);
1761 dirlist = dirlist->next;
1762 continue;
1763 }
1764
1765 /* --- May be true, false, or not found. ---
1766 */
1767 if (checked_flag == S_TRUE)
1768 {
1769 /* -- need only the file type --
1770 */
1771 checkit = sh_unix_get_ftype(tmpcat);
1772 }
1773 else
1774 {
1775 /* -- need to check the file itself --
1776 */
1777 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1778 dummy = dst_ptr->is_reported;
1779
1780 checkit = sh_files_filecheck (file_class_next,
1781 iname,
1782 dirlist->sh_d_name,
1783 &dummy, 0);
1784
1785 if (dst_ptr && checked_flag == S_FALSE)
1786 dst_ptr->checked = S_TRUE;
1787 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
1788 */
1789 if (dst_ptr && sh.flag.reportonce == S_TRUE)
1790 dst_ptr->is_reported = dummy;
1791 }
1792
1793 if (checkit == SH_FILE_REGULAR)
1794 ++theDir.NumRegular;
1795
1796 else if (checkit == SH_FILE_DIRECTORY)
1797 {
1798 ++theDir.NumDirs;
1799 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
1800 {
1801 rdepth_next = rdepth - 1;
1802
1803 /* check whether the new directory is in the
1804 * list with a recursion depth already defined
1805 */
1806 checked_flag = -1;
1807 cchecked_flag = -1;
1808
1809 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1810
1811 if (tmp_ptr)
1812 {
1813 TPT((0, FIL__, __LINE__,
1814 _("msg=<%s -> recursion depth %d\n>"),
1815 tmp_ptr->name, tmp_ptr->rdepth));
1816 rdepth_next = tmp_ptr->rdepth;
1817 class_next = tmp_ptr->class;
1818 /* 28. Aug 2001 reversed
1819 */
1820 cchecked_flag = tmp_ptr->childs_checked;
1821 checked_flag = tmp_ptr->checked;
1822 }
1823
1824 if (checked_flag == -1)
1825 {
1826 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, 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
1842 if (cchecked_flag == S_FALSE)
1843 {
1844 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1845 dirlist->sh_d_name);
1846 tmp_ptr->childs_checked = S_TRUE;
1847 /*
1848 * 04. Feb 2006 avoid double checking
1849 */
1850 tmp_ptr->checked = S_TRUE;
1851 }
1852 else if (checked_flag == -1)
1853 sh_files_checkdir (class_next, rdepth_next, tmpcat,
1854 dirlist->sh_d_name);
1855
1856 }
1857 }
1858
1859 else if (checkit == SH_FILE_SYMLINK) ++theDir.NumSymlinks;
1860 else if (checkit == SH_FILE_FIFO) ++theDir.NumFifos;
1861 else if (checkit == SH_FILE_SOCKET) ++theDir.NumSockets;
1862 else if (checkit == SH_FILE_CDEV) ++theDir.NumCDev;
1863 else if (checkit == SH_FILE_BDEV) ++theDir.NumBDev;
1864 else if (checkit == SH_FILE_DOOR) ++theDir.NumDoor;
1865 else if (checkit == SH_FILE_PORT) ++theDir.NumPort;
1866
1867 SH_FREE(tmpcat);
1868
1869 if ((sig_termfast == 1) || (sig_terminate == 1))
1870 {
1871 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1872 SL_RETURN((0), _("sh_files_checkdir"));
1873 }
1874
1875 dirlist = dirlist->next;
1876
1877 if (dst_ptr)
1878 dst_ptr->childs_checked = S_TRUE;
1879
1880 } while (dirlist != NULL);
1881
1882 if (flag_err_info == SL_TRUE)
1883 {
1884 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
1885 theDir.NumDirs,
1886 theDir.NumRegular,
1887 theDir.NumSymlinks,
1888 theDir.NumFifos,
1889 theDir.NumSockets,
1890 theDir.NumCDev,
1891 theDir.NumBDev);
1892 }
1893
1894 kill_sh_dirlist (dirlist_orig);
1895
1896#if !defined(HOST_IS_DARWIN)
1897 /*
1898 * Hardlink check; not done on MacOS X because of resource forks
1899 */
1900 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir.NumDirs))
1901 {
1902 if (0 != sh_files_hle_test(hardlink_num-theDir.NumDirs, iname))
1903 {
1904 len = strlen(tmpname);
1905 if (sl_ok_adds(len, 256))
1906 len += 256;
1907 tmpcat = SH_ALLOC(len);
1908 sl_snprintf(tmpcat, len,
1909 _("%s: subdirectory count (%d) != hardlinks (%d)"),
1910 tmpname, theDir.NumDirs, hardlink_num);
1911 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1912 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
1913 SH_FREE(tmpcat);
1914 }
1915 }
1916#endif
1917
1918 if (theFile.attr_string) SH_FREE(theFile.attr_string);
1919 SH_FREE(tmpname);
1920
1921 SL_RETURN((0), _("sh_files_checkdir"));
1922}
1923
1924int get_the_fd (SL_TICKET ticket);
1925
1926
1927static ShFileType sh_files_filecheck (int class, char * dirName,
1928 char * infileName,
1929 int * reported,
1930 int rsrcflag)
1931{
1932 /* 28 Aug 2001 allow NULL fileName
1933 */
1934 char fullpath[PATH_MAX];
1935 char fileHash[2*(KEY_LEN + 1)];
1936 int status;
1937 file_type theFile;
1938 char * tmpdir;
1939 char * tmpname;
1940 char * fileName;
1941 struct utimbuf utime_buf;
1942 static unsigned int state = 1;
1943
1944 SL_ENTER(_("sh_files_filecheck"));
1945
1946 BREAKEXIT(sh_derr);
1947
1948#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1949 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
1950#else
1951 if (0 == state * (rand() % 2)) (void) sh_derr();
1952#endif
1953
1954 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
1955 && (infileName[0] == '/') && (infileName[1] == '\0'))
1956 {
1957 fileName = NULL;
1958 }
1959 else
1960 {
1961 fileName = infileName;
1962 }
1963
1964 /* fileName may be NULL if this is a directory
1965 */
1966 if (dirName == NULL /* || fileName == NULL */)
1967 {
1968 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
1969 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
1970 }
1971
1972 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
1973 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
1974 fileName, S_FALSE)))
1975 {
1976 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
1977 {
1978 tmpname = sh_util_safe_name (fileName);
1979 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
1980 MSG_FI_OBSC2,
1981 "", tmpname);
1982 SH_FREE(tmpname);
1983 }
1984 else
1985 {
1986 tmpdir = sh_util_safe_name (dirName);
1987 tmpname = sh_util_safe_name (fileName);
1988 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
1989 MSG_FI_OBSC2,
1990 tmpdir, tmpname);
1991 SH_FREE(tmpname);
1992 SH_FREE(tmpdir);
1993 }
1994 }
1995
1996 /* sh_files_fullpath accepts NULL fileName
1997 */
1998 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
1999 {
2000 tmpdir = sh_util_safe_name (dirName);
2001 tmpname = sh_util_safe_name (fileName);
2002 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2003 MSG_FI_2LONG2,
2004 tmpdir, tmpname);
2005 SH_FREE(tmpname);
2006 SH_FREE(tmpdir);
2007 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2008 }
2009
2010
2011 /* stat the file and determine checksum (if a regular file)
2012 */
2013 sl_strlcpy (theFile.fullpath, fullpath, PATH_MAX);
2014 theFile.check_mask = sh_files_maskof(class);
2015 theFile.file_reported = (*reported);
2016 theFile.attr_string = NULL;
2017
2018 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2019
2020 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2021 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2022 fileName,
2023 &theFile, fileHash, class);
2024
2025 if (status != 0)
2026 {
2027 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2028 fullpath, status));
2029 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2030 sh_hash_set_visited_true (fullpath);
2031 if (theFile.attr_string)
2032 SH_FREE(theFile.attr_string);
2033 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2034 }
2035
2036 if (sig_termfast == 1) {
2037 goto ret_point;
2038 }
2039
2040 /* report
2041 */
2042 if ((flag_err_debug == SL_TRUE) && (theFile.c_mode[0] == '-'))
2043 {
2044 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2045 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2046 fileHash, tmpname);
2047 SH_FREE(tmpname);
2048 }
2049 ++sh.statistics.files_checked;
2050
2051 if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */)
2052 {
2053 sh_hash_pushdata (&theFile, fileHash);
2054 }
2055 else if (sh.flag.checkSum == SH_CHECK_CHECK
2056 /* && theFile.c_mode[0] == '-' */
2057 /* && class != SH_LEVEL_ALLIGNORE */
2058 )
2059 {
2060 sh_hash_compdata (class, &theFile, fileHash, NULL, -1);
2061 }
2062
2063 (*reported) = theFile.file_reported;
2064
2065 /* reset the access time
2066 */
2067 if (class == SH_LEVEL_NOIGNORE && (theFile.check_mask & MODI_ATM) != 0)
2068 {
2069 utime_buf.actime = (time_t) theFile.atime;
2070 utime_buf.modtime = (time_t) theFile.mtime;
2071#if !defined(O_NOATIME)
2072 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2073#endif
2074 }
2075
2076#ifdef HOST_IS_DARWIN
2077 /*
2078 * Check for resource fork
2079 */
2080 if ( (theFile.c_mode[0] != 'd') && (rsrcflag == 0) )
2081 {
2082 int dummy;
2083 static int rsrc_init = 0;
2084 static char rsrc[17];
2085 char testpath[PATH_MAX];
2086
2087 if (rsrc_init == 0) {
2088 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2089 rsrc_init = 1;
2090 }
2091 sl_strlcpy (testpath, fullpath, PATH_MAX);
2092 sl_strlcat (testpath, "/", PATH_MAX);
2093 sl_strlcat (testpath, rsrc, PATH_MAX);
2094
2095 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2096 {
2097 if (S_TRUE == sh_unix_file_exists (testpath))
2098 {
2099 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
2100 }
2101 }
2102 }
2103#else
2104 (void) rsrcflag; /* avoid compiler warning */
2105#endif
2106
2107 ret_point:
2108
2109 if (theFile.attr_string) SH_FREE(theFile.attr_string);
2110
2111 switch (theFile.c_mode[0])
2112 {
2113 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2114 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2115 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2116 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2117 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2118 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2119 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2120 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2121 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2122 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2123 }
2124
2125 /* notreached */
2126}
2127
2128/* concatenate statpath = testdir"/"d_name
2129 */
2130static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
2131{
2132 int llen = 0;
2133
2134 SL_ENTER(_("sh_files_fullpath"));
2135
2136 if (testdir != NULL)
2137 {
2138 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2139 SL_RETURN((-1),_("sh_files_fullpath"));
2140 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2141 }
2142 if (d_name != NULL)
2143 {
2144 if (llen > 1 || statpath[0] != '/')
2145 sl_strlcat(statpath, "/", PATH_MAX);
2146 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2147 SL_RETURN((-1),_("sh_files_fullpath"));
2148 sl_strlcat(statpath, d_name, PATH_MAX);
2149 }
2150 if (statpath == NULL)
2151 SL_RETURN((-1),_("sh_files_fullpath"));
2152 SL_RETURN((0),_("sh_files_fullpath"));
2153}
2154
2155
2156/* -----------------------------------
2157 *
2158 * The following two routines serve to
2159 * verify that the user has selected
2160 * a proper setup for file policies.
2161 *
2162 * -----------------------------------
2163 */
2164static int check_file(char * name)
2165{
2166 dirstack_t * pfilL;
2167 zAVLCursor cursor;
2168
2169 SL_ENTER(_("check_file"));
2170
2171 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2172 SL_RETURN(0, _("check_file"));
2173
2174 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2175 pfilL = (dirstack_t *) zAVLNext (&cursor))
2176 {
2177 if (0 == strcmp(name, pfilL->name) &&
2178 (pfilL->check_mask & MODI_ATM) == 0 &&
2179 (pfilL->check_mask & MODI_CTM) == 0 &&
2180 (pfilL->check_mask & MODI_MTM) == 0)
2181 SL_RETURN(0, _("check_file"));
2182 }
2183 SL_RETURN((-1), _("check_file"));
2184}
2185
2186int sh_files_test_setup_int (zAVLTree * tree)
2187{
2188 int dlen, flen;
2189 zAVLCursor cursor1;
2190 zAVLCursor cursor2;
2191
2192 dirstack_t * pdirL;
2193 dirstack_t * pfilL;
2194
2195 SL_ENTER(_("sh_files_test_setup"));
2196
2197 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2198 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2199 {
2200 dlen = strlen(pdirL->name);
2201
2202 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2203 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2204 {
2205 flen = strlen(pfilL->name);
2206
2207 /* check whether file is in tree of dir
2208 */
2209 if ((pfilL->class == SH_LEVEL_READONLY) ||
2210 (pfilL->class == SH_LEVEL_NOIGNORE))
2211 {
2212 ; /* do nothing */
2213 }
2214 else
2215 {
2216 if ((flen > (dlen+1)) &&
2217 (pfilL->name[dlen] == '/') &&
2218 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2219 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2220 {
2221 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2222 (pdirL->check_mask & MODI_MTM) != 0 ||
2223 (pdirL->check_mask & MODI_CTM) != 0)
2224 {
2225 if (check_file (pdirL->name) != 0)
2226 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2227 pdirL->name, pfilL->name);
2228 }
2229 }
2230 }
2231 }
2232 }
2233
2234 SL_RETURN((0), _("sh_files_test_setup"));
2235}
2236
2237int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2238{
2239 int count;
2240 int retval = 0;
2241
2242 zAVLCursor cursor;
2243
2244 dirstack_t * first;
2245
2246 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2247 first = (dirstack_t *) zAVLNext (&cursor))
2248 {
2249
2250 if (NULL != zAVLSearch(secondList, first->name))
2251 {
2252 ++count;
2253 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2254 first->name);
2255 retval = 1;
2256 }
2257 }
2258 return retval;
2259}
2260
2261extern void aud_exit (char * file, int line, int fd);
2262
2263int sh_files_test_setup ()
2264{
2265 int retval = 0;
2266
2267 /* Test for modifications allowed in ReadOnly directory
2268 */
2269 sh_files_test_setup_int (zdirListOne);
2270 sh_files_test_setup_int (zdirListTwo);
2271
2272 /* Test for files/dirz defined twice
2273 */
2274 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2275 if (retval != 0)
2276 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2277
2278 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2279 if (retval != 0)
2280 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2281
2282
2283 /*
2284 retval = sh_files_test_double (zfileList, NULL);
2285 if (retval != 0)
2286 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2287 */
2288 return 0;
2289}
2290
2291#endif
Note: See TracBrowser for help on using the repository browser.