source: trunk/src/sh_files.c@ 306

Last change on this file since 306 was 305, checked in by katerina, 14 years ago

Fix for ticker #226 (incorrect handling of missing files when secondary schedule is active).

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