source: trunk/src/sh_files.c@ 308

Last change on this file since 308 was 307, checked in by katerina, 14 years ago

Fix for ticket #229 (malfunction on CentOS 4.8 / gcc4), documentation update.

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