source: trunk/src/sh_files.c@ 278

Last change on this file since 278 was 256, checked in by katerina, 15 years ago

Evaluated glob patterns at each check (ticket #173).

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