source: trunk/src/sh_files.c@ 300

Last change on this file since 300 was 294, checked in by katerina, 14 years ago

Tikets #213 and #214 (Use auditd to determine who changed a file, Windows registry check).

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