source: trunk/src/sh_files.c@ 237

Last change on this file since 237 was 227, checked in by katerina, 16 years ago

Fix warnings with -fstack-check

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