source: trunk/src/sh_files.c@ 156

Last change on this file since 156 was 137, checked in by rainer, 17 years ago

Fix compile errors.

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