source: trunk/src/sh_files.c@ 353

Last change on this file since 353 was 310, checked in by katerina, 14 years ago

Add option to skip checksum for certain files (ticket #232). Also fix for #231 (missing warning on invalid recursion depth).

File size: 63.9 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_pushfile"));
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 (tail == p)
1547 {
1548 /* Setting to an invalid number will force MaxRecursionLevel,
1549 * see sh_files_setrec_int()
1550 */
1551 rdepth = (-2);
1552 }
1553 else if ( (rdepth < (-1) || rdepth > 99) ||
1554 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1555 {
1556 SH_FREE(p);
1557 SL_RETURN((-1), _("sh_files_pushdir"));
1558 }
1559
1560 len = sl_strlen(tail);
1561
1562 if (len >= PATH_MAX)
1563 {
1564 tmp = sh_util_safe_name (tail);
1565 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1566 tmp);
1567 SH_FREE(tmp);
1568 SH_FREE(p);
1569 SL_RETURN((-1), _("sh_files_pushdir"));
1570 }
1571 else if (len < 1)
1572 {
1573 SH_FREE(p);
1574 SL_RETURN((-1), _("sh_files_pushdir"));
1575 }
1576 else if (tail[0] != '/')
1577 {
1578 tmp = sh_util_safe_name (tail);
1579 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1580 tmp);
1581 SH_FREE(tmp);
1582 SH_FREE(p);
1583 SL_RETURN((-1), _("sh_files_pushdir"));
1584 }
1585 else
1586 {
1587 if (tail[len-1] == '/' && len > 1)
1588 {
1589 tail[len-1] = '\0';
1590 --len;
1591 }
1592 }
1593
1594#ifdef HAVE_GLOB_H
1595 if (0 == sh_files_has_metachar(tail))
1596 {
1597 sh_files_push_dir_int (class, tail, len, rdepth);
1598 }
1599 else
1600 {
1601 sh_files_pushglob (class, which_dirList, tail, rdepth);
1602 }
1603#else
1604 sh_files_push_dir_int (class, tail, len, rdepth);
1605#endif
1606
1607 SH_FREE(p);
1608 SL_RETURN((0), _("sh_files_pushdir"));
1609}
1610
1611/**
1612struct sh_dirent {
1613 char * sh_d_name;
1614 struct sh_dirent * next;
1615};
1616**/
1617
1618void kill_sh_dirlist (struct sh_dirent * dirlist)
1619{
1620 struct sh_dirent * this;
1621
1622 while (dirlist)
1623 {
1624 this = dirlist->next;
1625 SH_FREE(dirlist->sh_d_name);
1626 SH_FREE(dirlist);
1627 dirlist = this;
1628 }
1629 return;
1630}
1631
1632/* -- add an entry to a directory listing
1633 */
1634struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1635 struct sh_dirent * dirlist)
1636{
1637 struct sh_dirent * this;
1638 size_t len;
1639
1640 if (thisEntry == NULL)
1641 return dirlist;
1642
1643 len = sl_strlen(thisEntry->d_name);
1644 if (len == 0)
1645 return dirlist;
1646 ++len;
1647
1648 this = SH_ALLOC(sizeof(struct sh_dirent));
1649 if (!this)
1650 return dirlist;
1651
1652 this->sh_d_name = SH_ALLOC(len);
1653 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1654
1655 this->next = dirlist;
1656 return this;
1657}
1658
1659static int sh_check_hardlinks = S_TRUE;
1660
1661/* Simply sets our boolean as to whether this check is active
1662 */
1663int sh_files_check_hardlinks (const char * opt)
1664{
1665 int i;
1666 SL_ENTER(_("sh_files_check_hardlinks"));
1667 i = sh_util_flagval(opt, &sh_check_hardlinks);
1668 SL_RETURN(i, _("sh_files_check_hardlinks"));
1669}
1670
1671struct sh_hle_struct {
1672 long offset;
1673 char * path;
1674 struct sh_hle_struct * next;
1675};
1676
1677static struct sh_hle_struct * sh_hl_exc = NULL;
1678
1679int sh_files_hle_reg (const char * str)
1680{
1681 long offset;
1682 size_t len;
1683 char * path;
1684
1685 struct sh_hle_struct * tmp = sh_hl_exc;
1686
1687 SL_ENTER(_("sh_files_hle_reg"));
1688
1689 /* Free the linked list if called with NULL argument
1690 */
1691 if (str == NULL)
1692 {
1693 while (tmp)
1694 {
1695 sh_hl_exc = tmp->next;
1696 SH_FREE(tmp->path);
1697 SH_FREE(tmp);
1698 tmp = sh_hl_exc;
1699 }
1700 sh_hl_exc = NULL;
1701 SL_RETURN(0, _("sh_files_hle_reg"));
1702 }
1703
1704 /* We expect 'offset:/path'
1705 */
1706 offset = strtol(str, &path, 0);
1707 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
1708 {
1709 SL_RETURN(-1, _("sh_files_hle_reg"));
1710 }
1711 ++path;
1712 len = 1 + sl_strlen(path);
1713
1714 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
1715 tmp->path = SH_ALLOC(len);
1716 sl_strlcpy (tmp->path, path, len);
1717 tmp->offset = offset;
1718 tmp->next = sh_hl_exc;
1719 sh_hl_exc = tmp;
1720
1721 SL_RETURN(0, _("sh_files_hle_reg"));
1722}
1723
1724#if !defined(HOST_IS_DARWIN)
1725static int sh_files_hle_test (int offset, char * path)
1726{
1727 struct sh_hle_struct * tmp = sh_hl_exc;
1728
1729 SL_ENTER(_("sh_files_hle_reg"));
1730
1731 while(tmp)
1732 {
1733 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
1734 {
1735 SL_RETURN(0, _("sh_files_hle_test"));
1736 }
1737 tmp = tmp->next;
1738 }
1739 SL_RETURN(-1, _("sh_files_hle_test"));
1740}
1741#endif
1742
1743/* -- check a single directory and its content
1744 */
1745static int sh_files_checkdir (int iclass, int idepth, char * iname,
1746 char * relativeName)
1747{
1748 struct sh_dirent * dirlist;
1749 struct sh_dirent * dirlist_orig;
1750
1751 DIR * thisDir = NULL;
1752 struct dirent * thisEntry;
1753 int status;
1754 int dummy = S_FALSE;
1755 dir_type * theDir;
1756 ShFileType checkit;
1757 static unsigned int state = 1;
1758
1759 file_type * theFile;
1760 char * tmpname;
1761 char * tmpcat;
1762 char errbuf[SH_ERRBUF_SIZE];
1763
1764 int rdepth = 0;
1765 int class = 0;
1766 int rdepth_next;
1767 int class_next;
1768 int file_class_next;
1769
1770 int checked_flag = S_FALSE;
1771 int cchecked_flag = S_FALSE;
1772
1773 dirstack_t * dst_ptr;
1774 dirstack_t * tmp_ptr;
1775
1776 int hardlink_num = 0;
1777#if !defined(HOST_IS_DARWIN)
1778 size_t len;
1779#endif
1780
1781 SL_ENTER(_("sh_files_checkdir"));
1782
1783 if (sig_urgent > 0) {
1784 SL_RETURN((0), _("sh_files_checkdir"));
1785 }
1786
1787 if (iname == NULL || idepth < (-1))
1788 SL_RETURN((-1), _("sh_files_checkdir"));
1789
1790 if (idepth < 0)
1791 {
1792 /* hash_remove_tree (iname); */
1793 SL_RETURN((0), _("sh_files_checkdir"));
1794 }
1795
1796 rdepth = idepth;
1797 class = iclass;
1798
1799 tmpname = sh_util_safe_name (iname);
1800
1801 /* ---- check for obscure name ----
1802 */
1803 if (iclass != SH_LEVEL_ALLIGNORE)
1804 {
1805 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
1806 }
1807
1808 if (flag_err_info == SL_TRUE)
1809 {
1810 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, tmpname);
1811 }
1812
1813 /* ---- check input ----
1814 */
1815 if ( sl_strlen(iname) >= PATH_MAX)
1816 {
1817 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1818 MSG_FI_2LONG,
1819 tmpname);
1820 SH_FREE(tmpname);
1821 SL_RETURN((-1), _("sh_files_checkdir"));
1822 }
1823
1824 /* ---- check for absolute path ---- */
1825 if ( iname[0] != '/')
1826 {
1827 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1828 MSG_FI_NOPATH,
1829 tmpname);
1830 SH_FREE(tmpname);
1831 SL_RETURN((-1), _("sh_files_checkdir"));
1832 }
1833
1834
1835 /* ---- stat the directory ----
1836 */
1837 theFile = SH_ALLOC(sizeof(file_type));
1838 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
1839 theFile->attr_string = NULL;
1840 theFile->link_path = NULL;
1841
1842 (void) relativeName;
1843 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
1844 iname,
1845 theFile, NULL, iclass);
1846
1847 if ((sig_termfast == 1) || (sig_terminate == 1))
1848 {
1849 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1850 if (theFile->link_path) SH_FREE(theFile->link_path);
1851 SH_FREE(theFile);
1852 SL_RETURN((0), _("sh_files_checkdir"));
1853 }
1854
1855 if (status == -1)
1856 {
1857 SH_FREE(tmpname);
1858 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1859 if (theFile->link_path) SH_FREE(theFile->link_path);
1860 SH_FREE(theFile);
1861 SL_RETURN((-1), _("sh_files_checkdir"));
1862 }
1863
1864 if (theFile->c_mode[0] != 'd')
1865 {
1866 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1867 MSG_FI_NODIR,
1868 tmpname);
1869 SH_FREE(tmpname);
1870 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1871 if (theFile->link_path) SH_FREE(theFile->link_path);
1872 SH_FREE(theFile);
1873 SL_RETURN((-1), _("sh_files_checkdir"));
1874 }
1875
1876 hardlink_num = theFile->hardlinks;
1877
1878 if (theFile->attr_string) SH_FREE(theFile->attr_string);
1879 if (theFile->link_path) SH_FREE(theFile->link_path);
1880 SH_FREE(theFile);
1881
1882 /* ---- open directory for reading ----
1883 *
1884 * opendir() will fail with ENOTDIR if the path has been changed
1885 * to a non-directory in between lstat() and opendir().
1886 */
1887 thisDir = opendir (iname);
1888
1889 if (thisDir == NULL)
1890 {
1891 status = errno;
1892 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
1893 MSG_E_OPENDIR,
1894 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
1895 SH_FREE(tmpname);
1896 SL_RETURN((-1), _("sh_files_checkdir"));
1897 }
1898
1899 theDir = SH_ALLOC(sizeof(dir_type));
1900
1901 theDir->NumRegular = 0;
1902 theDir->NumDirs = 0;
1903 theDir->NumSymlinks = 0;
1904 theDir->NumFifos = 0;
1905 theDir->NumSockets = 0;
1906 theDir->NumCDev = 0;
1907 theDir->NumBDev = 0;
1908 theDir->NumDoor = 0;
1909 theDir->NumPort = 0;
1910 theDir->NumAll = 0;
1911 theDir->TotalBytes = 0;
1912 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
1913
1914
1915 /* ---- read ----
1916 */
1917 SH_MUTEX_LOCK(mutex_readdir);
1918
1919 dirlist = NULL;
1920 dirlist_orig = NULL;
1921
1922 do {
1923 thisEntry = readdir (thisDir);
1924 if (thisEntry != NULL)
1925 {
1926 ++theDir->NumAll;
1927 if (sl_strcmp (thisEntry->d_name, ".") == 0)
1928 {
1929 ++theDir->NumDirs;
1930 continue;
1931 }
1932 if (sl_strcmp (thisEntry->d_name, "..") == 0)
1933 {
1934 ++theDir->NumDirs;
1935 continue;
1936 }
1937 dirlist = addto_sh_dirlist (thisEntry, dirlist);
1938 }
1939 } while (thisEntry != NULL);
1940
1941 SH_MUTEX_UNLOCK(mutex_readdir);
1942
1943 closedir (thisDir);
1944
1945 ++sh.statistics.dirs_checked;
1946
1947 dirlist_orig = dirlist;
1948
1949 do {
1950
1951 /* If the directory is empty, dirlist = NULL
1952 */
1953 if (!dirlist)
1954 break;
1955
1956 if (sig_termfast == 1)
1957 {
1958 SH_FREE(theDir);
1959 SL_RETURN((0), _("sh_files_checkdir"));
1960 }
1961
1962 BREAKEXIT(sh_derr);
1963
1964#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
1965 if (0 == (rand_r(&state) % 5)) (void) sh_derr();
1966#else
1967 if (0 == state * (rand() % 5)) (void) sh_derr();
1968#endif
1969
1970 /* ---- Check the file. ----
1971 */
1972 tmpcat = SH_ALLOC(PATH_MAX);
1973 sl_strlcpy(tmpcat, iname, PATH_MAX);
1974 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
1975 sl_strlcat(tmpcat, "/", PATH_MAX);
1976 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
1977
1978 rdepth_next = rdepth - 1;
1979 class_next = class;
1980 file_class_next = class;
1981 checked_flag = -1;
1982 cchecked_flag = -1;
1983
1984 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
1985 * this fixes the problem that the directory special file
1986 * is checked with the policy of the parent directory
1987 */
1988 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
1989
1990 if (dst_ptr)
1991 {
1992 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
1993 * this fixes the problem that a policy for the directory
1994 * inode erroneously becomes a policy for the directory itself.
1995 */
1996 file_class_next = dst_ptr->class;
1997 checked_flag = dst_ptr->checked;
1998 cchecked_flag = dst_ptr->childs_checked;
1999 }
2000
2001 if (checked_flag == -1)
2002 {
2003 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2004
2005 if (dst_ptr)
2006 {
2007 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2008 * this fixes the problem that a policy for the directory
2009 * inode erroneously becomes a policy for the directory itself.
2010 */
2011 file_class_next = dst_ptr->class;
2012 checked_flag = dst_ptr->checked;
2013 cchecked_flag = dst_ptr->childs_checked;
2014 }
2015 }
2016
2017 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2018
2019 if (dst_ptr)
2020 {
2021 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2022 * this fixes the problem that a policy for the directory
2023 * inode erroneously becomes a policy for the directory itself.
2024 */
2025 file_class_next = dst_ptr->class;
2026 checked_flag = dst_ptr->checked;
2027 /* not set, hence always FALSE */
2028 /* cchecked_flag = dst_ptr->childs_checked; */
2029 }
2030
2031 /* ---- Has been checked already. ----
2032 */
2033 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2034 {
2035 /* Mar 11 2004 get ftype for complete directory count
2036 */
2037 checkit = sh_unix_get_ftype(tmpcat);
2038 if (checkit == SH_FILE_DIRECTORY)
2039 {
2040 ++theDir->NumDirs;
2041 }
2042 SH_FREE(tmpcat);
2043 dirlist = dirlist->next;
2044 continue;
2045 }
2046
2047 /* --- May be true, false, or not found. ---
2048 */
2049 if (checked_flag == S_TRUE)
2050 {
2051 /* -- need only the file type --
2052 */
2053 checkit = sh_unix_get_ftype(tmpcat);
2054 }
2055 else
2056 {
2057 /* -- need to check the file itself --
2058 */
2059 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2060 dummy = dst_ptr->is_reported;
2061
2062 checkit = sh_files_filecheck (file_class_next,
2063 iname,
2064 dirlist->sh_d_name,
2065 &dummy, 0);
2066
2067 if (dst_ptr && checked_flag == S_FALSE)
2068 dst_ptr->checked = S_TRUE;
2069 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2070 */
2071 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2072 dst_ptr->is_reported = dummy;
2073 }
2074
2075 if (checkit == SH_FILE_REGULAR)
2076 ++theDir->NumRegular;
2077
2078 else if (checkit == SH_FILE_DIRECTORY)
2079 {
2080 ++theDir->NumDirs;
2081 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2082 {
2083 rdepth_next = rdepth - 1;
2084
2085 /* check whether the new directory is in the
2086 * list with a recursion depth already defined
2087 */
2088 checked_flag = -1;
2089 cchecked_flag = -1;
2090
2091 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2092
2093 if (tmp_ptr)
2094 {
2095 TPT((0, FIL__, __LINE__,
2096 _("msg=<%s -> recursion depth %d\n>"),
2097 tmp_ptr->name, tmp_ptr->rdepth));
2098 rdepth_next = tmp_ptr->rdepth;
2099 class_next = tmp_ptr->class;
2100 /* 28. Aug 2001 reversed
2101 */
2102 cchecked_flag = tmp_ptr->childs_checked;
2103 checked_flag = tmp_ptr->checked;
2104 }
2105
2106 if (checked_flag == -1)
2107 {
2108 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2109
2110 if (tmp_ptr)
2111 {
2112 TPT((0, FIL__, __LINE__,
2113 _("msg=<%s -> recursion depth %d\n>"),
2114 tmp_ptr->name, tmp_ptr->rdepth));
2115 rdepth_next = tmp_ptr->rdepth;
2116 class_next = tmp_ptr->class;
2117 /* 28. Aug 2001 reversed
2118 */
2119 cchecked_flag = tmp_ptr->childs_checked;
2120 checked_flag = tmp_ptr->checked;
2121 }
2122 }
2123
2124 if (cchecked_flag == S_FALSE)
2125 {
2126 sh_files_checkdir (class_next, rdepth_next, tmpcat,
2127 dirlist->sh_d_name);
2128 tmp_ptr->childs_checked = S_TRUE;
2129 /*
2130 * 04. Feb 2006 avoid double checking
2131 */
2132 tmp_ptr->checked = S_TRUE;
2133 }
2134 else if (checked_flag == -1)
2135 sh_files_checkdir (class_next, rdepth_next, tmpcat,
2136 dirlist->sh_d_name);
2137
2138 }
2139 }
2140
2141 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2142 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2143 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2144 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2145 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2146 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2147 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2148
2149 SH_FREE(tmpcat);
2150
2151 if ((sig_termfast == 1) || (sig_terminate == 1))
2152 {
2153 SH_FREE(theDir);
2154 SL_RETURN((0), _("sh_files_checkdir"));
2155 }
2156
2157 dirlist = dirlist->next;
2158
2159 if (dst_ptr)
2160 dst_ptr->childs_checked = S_TRUE;
2161
2162 } while (dirlist != NULL);
2163
2164 if (flag_err_info == SL_TRUE)
2165 {
2166 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2167 theDir->NumDirs,
2168 theDir->NumRegular,
2169 theDir->NumSymlinks,
2170 theDir->NumFifos,
2171 theDir->NumSockets,
2172 theDir->NumCDev,
2173 theDir->NumBDev);
2174 }
2175
2176 kill_sh_dirlist (dirlist_orig);
2177
2178#if !defined(HOST_IS_DARWIN)
2179 /*
2180 * Hardlink check; not done on MacOS X because of resource forks
2181 */
2182 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2183 {
2184 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2185 {
2186 len = strlen(tmpname);
2187 if (sl_ok_adds(len, 256))
2188 len += 256;
2189 tmpcat = SH_ALLOC(len);
2190 sl_snprintf(tmpcat, len,
2191 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2192 tmpname, theDir->NumDirs, hardlink_num);
2193 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2194 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2195 SH_FREE(tmpcat);
2196 }
2197 }
2198#endif
2199
2200 SH_FREE(tmpname);
2201 SH_FREE(theDir);
2202
2203 SL_RETURN((0), _("sh_files_checkdir"));
2204}
2205
2206int get_the_fd (SL_TICKET ticket);
2207
2208static int sh_use_rsrc = S_FALSE;
2209
2210int sh_files_use_rsrc(const char * str)
2211{
2212 return sh_util_flagval(str, &sh_use_rsrc);
2213}
2214
2215static ShFileType sh_files_filecheck (int class, char * dirName,
2216 char * infileName,
2217 int * reported,
2218 int rsrcflag)
2219{
2220 /* 28 Aug 2001 allow NULL fileName
2221 */
2222 char * fullpath;
2223 char fileHash[2*(KEY_LEN + 1)];
2224 int status;
2225 file_type * theFile;
2226 char * tmpdir;
2227 char * tmpname;
2228 char * fileName;
2229 struct utimbuf utime_buf;
2230 static unsigned int state = 1;
2231 char sc;
2232
2233 SL_ENTER(_("sh_files_filecheck"));
2234
2235 fullpath = SH_ALLOC(PATH_MAX);
2236 theFile = SH_ALLOC(sizeof(file_type));
2237
2238 BREAKEXIT(sh_derr);
2239
2240#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
2241 if (0 == (rand_r(&state) % 2)) (void) sh_derr();
2242#else
2243 if (0 == state * (rand() % 2)) (void) sh_derr();
2244#endif
2245
2246 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2247 && (infileName[0] == '/') && (infileName[1] == '\0'))
2248 {
2249 fileName = NULL;
2250 }
2251 else
2252 {
2253 fileName = infileName;
2254 }
2255
2256 /* fileName may be NULL if this is a directory
2257 */
2258 if (dirName == NULL /* || fileName == NULL */)
2259 {
2260 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2261 SH_FREE(fullpath);
2262 SH_FREE(theFile);
2263 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2264 }
2265
2266 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2267 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2268 fileName, S_FALSE)))
2269 {
2270 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2271 {
2272 tmpname = sh_util_safe_name (fileName);
2273 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2274 MSG_FI_OBSC2,
2275 "", tmpname);
2276 SH_FREE(tmpname);
2277 }
2278 else
2279 {
2280 tmpdir = sh_util_safe_name (dirName);
2281 tmpname = sh_util_safe_name (fileName);
2282 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2283 MSG_FI_OBSC2,
2284 tmpdir, tmpname);
2285 SH_FREE(tmpname);
2286 SH_FREE(tmpdir);
2287 }
2288 }
2289
2290 /* sh_files_fullpath accepts NULL fileName
2291 */
2292 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2293 {
2294 tmpdir = sh_util_safe_name (dirName);
2295 tmpname = sh_util_safe_name (fileName);
2296 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2297 MSG_FI_2LONG2,
2298 tmpdir, tmpname);
2299 SH_FREE(tmpname);
2300 SH_FREE(tmpdir);
2301 SH_FREE(fullpath);
2302 SH_FREE(theFile);
2303 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2304 }
2305
2306
2307 /* stat the file and determine checksum (if a regular file)
2308 */
2309 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2310 theFile->check_mask = sh_files_maskof(class);
2311 theFile->file_reported = (*reported);
2312 theFile->attr_string = NULL;
2313 theFile->link_path = NULL;
2314
2315 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2316
2317 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2318 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2319 fileName,
2320 theFile, fileHash, class);
2321
2322 if (status != 0)
2323 {
2324 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2325 fullpath, status));
2326 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2327 sh_hash_set_visited_true (fullpath);
2328 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2329 if (theFile->link_path) SH_FREE(theFile->link_path);
2330 SH_FREE(fullpath);
2331 SH_FREE(theFile);
2332 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2333 }
2334
2335 if (sig_termfast == 1) {
2336 goto ret_point;
2337 }
2338
2339 /* report
2340 */
2341 if ((flag_err_debug == SL_TRUE) && (theFile->c_mode[0] == '-'))
2342 {
2343 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2344 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2345 fileHash, tmpname);
2346 SH_FREE(tmpname);
2347 }
2348 ++sh.statistics.files_checked;
2349
2350 if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */)
2351 {
2352 sh_hash_pushdata (theFile, fileHash);
2353 }
2354 else if (sh.flag.checkSum == SH_CHECK_CHECK
2355 /* && theFile.c_mode[0] == '-' */
2356 /* && class != SH_LEVEL_ALLIGNORE */
2357 )
2358 {
2359 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2360 }
2361
2362 (*reported) = theFile->file_reported;
2363
2364 /* reset the access time
2365 */
2366 if (class == SH_LEVEL_NOIGNORE && (theFile->check_mask & MODI_ATM) != 0)
2367 {
2368 utime_buf.actime = (time_t) theFile->atime;
2369 utime_buf.modtime = (time_t) theFile->mtime;
2370#if !defined(O_NOATIME)
2371 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2372#endif
2373 }
2374
2375#if defined(HOST_IS_DARWIN)
2376 /*
2377 * Check for resource fork
2378 */
2379 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2380 {
2381 int dummy;
2382 static int rsrc_init = 0;
2383 static char rsrc[17];
2384 char * testpath = SH_ALLOC(PATH_MAX);
2385
2386 if (rsrc_init == 0) {
2387 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2388 rsrc_init = 1;
2389 }
2390 sl_strlcpy (testpath, fullpath, PATH_MAX);
2391 sl_strlcat (testpath, "/", PATH_MAX);
2392 sl_strlcat (testpath, rsrc, PATH_MAX);
2393
2394 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2395 {
2396 if (S_TRUE == sh_unix_file_exists (testpath))
2397 {
2398 sh_files_filecheck (class, fullpath, rsrc, &dummy, 1);
2399 }
2400 }
2401 SH_FREE(testpath);
2402 }
2403#else
2404 (void) rsrcflag; /* avoid compiler warning */
2405#endif
2406
2407 ret_point:
2408
2409 sc = theFile->c_mode[0];
2410
2411 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2412 if (theFile->link_path) SH_FREE(theFile->link_path);
2413 SH_FREE(fullpath);
2414 SH_FREE(theFile);
2415
2416 switch (sc)
2417 {
2418 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2419 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2420 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2421 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2422 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2423 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2424 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2425 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2426 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2427 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2428 }
2429
2430 /* notreached */
2431}
2432
2433/* concatenate statpath = testdir"/"d_name
2434 */
2435static int sh_files_fullpath (char * testdir, char * d_name, char * statpath)
2436{
2437 int llen = 0;
2438
2439 SL_ENTER(_("sh_files_fullpath"));
2440
2441 if (testdir != NULL)
2442 {
2443 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2444 SL_RETURN((-1),_("sh_files_fullpath"));
2445 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2446 }
2447 if (d_name != NULL)
2448 {
2449 if (llen > 1 || statpath[0] != '/')
2450 sl_strlcat(statpath, "/", PATH_MAX);
2451 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2452 SL_RETURN((-1),_("sh_files_fullpath"));
2453 sl_strlcat(statpath, d_name, PATH_MAX);
2454 }
2455 if (statpath == NULL)
2456 SL_RETURN((-1),_("sh_files_fullpath"));
2457 SL_RETURN((0),_("sh_files_fullpath"));
2458}
2459
2460
2461/* -----------------------------------
2462 *
2463 * The following two routines serve to
2464 * verify that the user has selected
2465 * a proper setup for file policies.
2466 *
2467 * -----------------------------------
2468 */
2469static int check_file(char * name)
2470{
2471 dirstack_t * pfilL;
2472 zAVLCursor cursor;
2473
2474 SL_ENTER(_("check_file"));
2475
2476 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
2477 SL_RETURN(0, _("check_file"));
2478
2479 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
2480 pfilL = (dirstack_t *) zAVLNext (&cursor))
2481 {
2482 if (0 == strcmp(name, pfilL->name) &&
2483 (pfilL->check_mask & MODI_ATM) == 0 &&
2484 (pfilL->check_mask & MODI_CTM) == 0 &&
2485 (pfilL->check_mask & MODI_MTM) == 0)
2486 SL_RETURN(0, _("check_file"));
2487 }
2488 SL_RETURN((-1), _("check_file"));
2489}
2490
2491int sh_files_test_setup_int (zAVLTree * tree)
2492{
2493 int dlen, flen;
2494 zAVLCursor cursor1;
2495 zAVLCursor cursor2;
2496
2497 dirstack_t * pdirL;
2498 dirstack_t * pfilL;
2499
2500 SL_ENTER(_("sh_files_test_setup"));
2501
2502 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
2503 pdirL = (dirstack_t *) zAVLNext (&cursor1))
2504 {
2505 dlen = strlen(pdirL->name);
2506
2507 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
2508 pfilL = (dirstack_t *) zAVLNext (&cursor2))
2509 {
2510 flen = strlen(pfilL->name);
2511
2512 /* check whether file is in tree of dir
2513 */
2514 if ((pfilL->class == SH_LEVEL_READONLY) ||
2515 (pfilL->class == SH_LEVEL_NOIGNORE))
2516 {
2517 ; /* do nothing */
2518 }
2519 else
2520 {
2521 if ((flen > (dlen+1)) &&
2522 (pfilL->name[dlen] == '/') &&
2523 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
2524 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
2525 {
2526 if ((pdirL->check_mask & MODI_ATM) != 0 ||
2527 (pdirL->check_mask & MODI_MTM) != 0 ||
2528 (pdirL->check_mask & MODI_CTM) != 0)
2529 {
2530 if (check_file (pdirL->name) != 0)
2531 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
2532 pdirL->name, pfilL->name);
2533 }
2534 }
2535 }
2536 }
2537 }
2538
2539 SL_RETURN((0), _("sh_files_test_setup"));
2540}
2541
2542int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
2543{
2544 int retval = 0;
2545 zAVLCursor cursor;
2546 dirstack_t * first;
2547
2548 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
2549 first = (dirstack_t *) zAVLNext (&cursor))
2550 {
2551
2552 if (NULL != zAVLSearch(secondList, first->name))
2553 {
2554 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
2555 first->name);
2556 retval = 1;
2557 }
2558 }
2559 return retval;
2560}
2561
2562extern void aud_exit (const char * file, int line, int fd);
2563
2564int sh_files_test_setup ()
2565{
2566 int retval = 0;
2567
2568 /* Test for modifications allowed in ReadOnly directory
2569 */
2570 sh_files_test_setup_int (zdirListOne);
2571 sh_files_test_setup_int (zdirListTwo);
2572
2573 /* Test for files/dirz defined twice
2574 */
2575 retval = sh_files_test_double (zdirListOne, zdirListTwo);
2576 if (retval != 0)
2577 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2578
2579 retval = sh_files_test_double (zdirListTwo, zdirListOne);
2580 if (retval != 0)
2581 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2582
2583
2584 /*
2585 retval = sh_files_test_double (zfileList, NULL);
2586 if (retval != 0)
2587 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2588 */
2589 return 0;
2590}
2591
2592#endif
2593
2594#ifdef SH_CUTEST
2595#include "CuTest.h"
2596
2597void Test_file_dequote (CuTest *tc)
2598{
2599#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
2600
2601 char str1[] = "1234567890";
2602 char str1a[] = "123456\\\"789\\r";
2603 char str1b[] = "12345678\\r9";
2604 char str1c[] = "12345678\\x0a_9";
2605 char str1d[] = "12345678\\007_9";
2606 char str1e[] = "123456789\\\\";
2607
2608 char str2[] = "1234567890\\xw";
2609 char str3[] = "1234567890\\xw99";
2610 char str4[] = "1234567890\\0ww";
2611 char str5[] = "12345\\g67890";
2612 char str6[] = "1234567890\\009a";
2613
2614 char *s, *p, *q;
2615 size_t lo, lr;
2616
2617 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
2618 q = sh_files_C_dequote(s, &lr);
2619 CuAssertPtrNotNull(tc, q);
2620 CuAssertTrue(tc, p == q);
2621 CuAssertTrue(tc, lr == lo);
2622
2623 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
2624 q = sh_files_C_dequote(s, &lr);
2625 CuAssertPtrNotNull(tc, q);
2626 CuAssertTrue(tc, p != q);
2627 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
2628 CuAssertTrue(tc, lr == (lo-2));
2629
2630 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
2631 q = sh_files_C_dequote(s, &lr);
2632 CuAssertPtrNotNull(tc, q);
2633 CuAssertTrue(tc, p != q);
2634 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
2635 CuAssertTrue(tc, lr == (lo-1));
2636
2637 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
2638 q = sh_files_C_dequote(s, &lr);
2639 CuAssertPtrNotNull(tc, q);
2640 CuAssertTrue(tc, p != q);
2641 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
2642 CuAssertTrue(tc, lr == (lo-3));
2643
2644 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
2645 q = sh_files_C_dequote(s, &lr);
2646 CuAssertPtrNotNull(tc, q);
2647 CuAssertTrue(tc, p != q);
2648 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
2649 CuAssertTrue(tc, lr == (lo-3));
2650
2651 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
2652 q = sh_files_C_dequote(s, &lr);
2653 CuAssertPtrNotNull(tc, q);
2654 CuAssertTrue(tc, p != q);
2655 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
2656 CuAssertTrue(tc, lr == (lo-1));
2657
2658 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
2659 q = sh_files_C_dequote(s, &lr);
2660 CuAssertTrue(tc, q == NULL);
2661 CuAssertTrue(tc, lr == 0);
2662
2663 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
2664 q = sh_files_C_dequote(s, &lr);
2665 CuAssertTrue(tc, q == NULL);
2666 CuAssertTrue(tc, lr == 0);
2667
2668 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
2669 q = sh_files_C_dequote(s, &lr);
2670 CuAssertTrue(tc, q == NULL);
2671 CuAssertTrue(tc, lr == 0);
2672
2673 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
2674 q = sh_files_C_dequote(s, &lr);
2675 CuAssertTrue(tc, q == NULL);
2676 CuAssertTrue(tc, lr == 0);
2677
2678 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
2679 q = sh_files_C_dequote(s, &lr);
2680 CuAssertTrue(tc, q == NULL);
2681 CuAssertTrue(tc, lr == 0);
2682
2683 return;
2684#else
2685 (void) tc; /* fix compiler warning */
2686 return;
2687#endif
2688}
2689#endif
2690
Note: See TracBrowser for help on using the repository browser.