source: trunk/src/sh_files.c@ 122

Last change on this file since 122 was 114, checked in by rainer, 17 years ago

Revision of file flag code.

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