source: trunk/src/sh_files.c@ 288

Last change on this file since 288 was 286, checked in by katerina, 14 years ago

Fix for ticket #211 (samhain_kmem compile problems) and ticket #210 (line length, filename quoting in config file).

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