source: trunk/src/sh_files.c@ 564

Last change on this file since 564 was 564, checked in by katerina, 3 years ago

Fix for ticket #452 (reproducible database generation).

File size: 83.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#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) && defined(HAVE_DIRENT_H) && defined(HAVE_SCANDIR)
23
24/* Linux */
25#if defined(__linux__)
26#define _XOPEN_SOURCE 700
27#define SH_USE_SCANDIR 1
28
29/* FreeBSD */
30#elif defined(__FreeBSD__)
31
32#if __FreeBSD__ >= 8
33#define __XSI_VISIBLE 700
34#define SH_USE_SCANDIR 1
35#endif
36
37/* OpenBSD */
38#elif defined(__OpenBSD__)
39#define __POSIX_VISIBLE 200809
40#define SH_USE_SCANDIR 1
41
42#elif defined(__NetBSD__)
43#define _NETBSD_SOURCE
44#define SH_USE_SCANDIR 1
45
46/* other os */
47#else
48#define _XOPEN_SOURCE 500
49
50#endif
51
52#elif defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
53#define _XOPEN_SOURCE 500
54#endif
55
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#include <ctype.h>
60#include <limits.h>
61
62#include <errno.h>
63
64/* Must be before <utime.h> on FreeBSD
65 */
66#include <sys/types.h>
67#include <unistd.h>
68#include <sys/stat.h>
69#include <fcntl.h>
70
71#if !defined(O_NOATIME)
72#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__) || defined(__PPC__))
73#define O_NOATIME 01000000
74#endif
75#endif
76
77#include <utime.h>
78
79#ifdef HAVE_DIRENT_H
80#include <dirent.h>
81#define NAMLEN(dirent) sl_strlen((dirent)->d_name)
82#else
83#define dirent direct
84#define NAMLEN(dirent) (dirent)->d_namlen
85#ifdef HAVE_SYS_NDIR_H
86#include <sys/ndir.h>
87#endif
88#ifdef HAVE_SYS_DIR_H
89#include <sys/dir.h>
90#endif
91#ifdef HAVE_NDIR_H
92#include <ndir.h>
93#endif
94#endif
95#define NEED_ADD_DIRENT
96
97#ifdef HAVE_GLOB_H
98#include <glob.h>
99#endif
100#ifdef HAVE_FNMATCH_H
101#include <fnmatch.h>
102#endif
103
104
105#include "samhain.h"
106
107#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
108
109#include "sh_pthread.h"
110#include "sh_error.h"
111#include "sh_utils.h"
112#include "sh_unix.h"
113#include "sh_files.h"
114#include "sh_tiger.h"
115#include "sh_hash.h"
116#include "sh_ignore.h"
117#include "sh_inotify.h"
118#include "zAVLTree.h"
119#include "sh_dbIO.h"
120
121#undef FIL__
122#define FIL__ _("sh_files.c")
123
124extern sh_watches sh_file_watches;
125
126static char * sh_files_C_dequote (char * s, size_t * length)
127{
128 size_t i, len = *length;
129 int flag = 0;
130 char *p, *q, *po, *pend;
131
132 /* search for backslash
133 */
134 for (i = 0; i < len; ++i)
135 {
136 if (s[i] == '\\')
137 {
138 flag = 1;
139 break;
140 }
141 }
142
143 if (flag == 0 || *s == '\0')
144 return s;
145
146 po = SH_ALLOC(len+1); *po = '\0'; p = po; pend = &po[len];
147
148 q = s;
149
150 do
151 {
152 if (*q == '\\')
153 {
154 ++q;
155
156 if (*q == '\0')
157 { *p = *q; flag = 0; break; }
158 else if (*q == 'a')
159 { *p = '\a'; ++p; ++q; }
160 else if (*q == 'b')
161 { *p = '\b'; ++p; ++q; }
162 else if (*q == 'f')
163 { *p = '\f'; ++p; ++q; }
164 else if (*q == 'n')
165 { *p = '\n'; ++p; ++q; }
166 else if (*q == 'r')
167 { *p = '\r'; ++p; ++q; }
168 else if (*q == 't')
169 { *p = '\t'; ++p; ++q; }
170 else if (*q == 'v')
171 { *p = '\v'; ++p; ++q; }
172 else if (*q == '\\')
173 { *p = '\\'; ++p; ++q; }
174 else if (*q == '\'')
175 { *p = '\''; ++p; ++q; }
176 else if (*q == '"')
177 { *p = '"'; ++p; ++q; }
178 else if (*q == 'x')
179 {
180 if (isxdigit((int) q[1]) && isxdigit((int) q[2]))
181 {
182 /* hexadecimal value following */
183 unsigned char cc = (16 * sh_util_hexchar(q[1]))
184 + sh_util_hexchar(q[2]);
185 *p = (char) cc;
186 ++p; q += 3;
187 }
188 else
189 {
190 *p = '\0'; flag = 0; break;
191 }
192 }
193 else if (isdigit((int)*q))
194 {
195 if (isdigit((int) q[1]) && q[1] < '8' &&
196 isdigit((int) q[2]) && q[2] < '8')
197 {
198 /* octal value following */
199 char tmp[4]; unsigned char cc;
200 tmp[0] = *q; ++q; tmp[1] = *q; ++q; tmp[2] = *q; ++q;
201 tmp[3] = '\0';
202 cc = strtol(tmp, NULL, 8);
203 *p = (char) cc; ++p;
204 }
205 else
206 {
207 *p = '\0'; flag = 0; break;
208 }
209 }
210 else
211 {
212 /* invalid escape sequence */
213 *p = '\0'; flag = 0; break;
214 }
215 }
216 else
217 {
218 *p = *q;
219 ++p; ++q;
220 }
221 } while (*q && p <= pend);
222
223 SL_REQUIRE (p <= pend, _("p <= pend"));
224
225 if (flag)
226 {
227 *p = '\0';
228 *length = strlen(po);
229 }
230 else
231 {
232 SH_FREE(po);
233 po = NULL;
234 *length = 0;
235 }
236
237 SL_REQUIRE (*length <= len, _("*length <= len"));
238
239 SH_FREE(s);
240 return po;
241}
242
243char * sh_files_parse_input(const char * str_s, size_t * len)
244{
245 char * p;
246
247 if (!str_s || *str_s == '\0')
248 return NULL;
249
250 *len = sl_strlen(str_s);
251 if (sh.flag.checkSum == SH_CHECK_INIT)
252 {
253 size_t addspace = sh_dbIO_get_rootfs_len();
254 if (addspace != 0 && S_TRUE == sl_ok_adds (*len, addspace))
255 *len += addspace;
256 }
257
258 if ( (str_s[0] == '"' && str_s[*len-1] == '"' ) ||
259 (str_s[0] == '\'' && str_s[*len-1] == '\'') )
260 {
261 if (*len < 3)
262 return NULL;
263 --(*len);
264 p = sh_util_strdup_l(&str_s[1], *len);
265 p[*len-1] = '\0';
266 --(*len);
267 }
268 else
269 {
270 p = sh_util_strdup_l(str_s, *len);
271 }
272
273 p = sh_files_C_dequote(p, len);
274
275 return p;
276}
277
278
279extern int flag_err_debug;
280extern int flag_err_info;
281
282int sh_files_reportonce(const char * c)
283{
284 int i;
285 SL_ENTER(_("sh_files_reportonce"));
286 i = sh_util_flagval(c, &(sh.flag.reportonce));
287
288 SL_RETURN(i, _("sh_files_reportonce"));
289}
290
291int sh_files_fulldetail(const char * c)
292{
293 int i;
294 SL_ENTER(_("sh_files_fulldetail"));
295 i = sh_util_flagval(c, &(sh.flag.fulldetail));
296
297 SL_RETURN((i), _("sh_files_fulldetail"));
298}
299
300
301typedef struct dir_struct {
302 long NumRegular;
303 long NumDirs;
304 long NumSymlinks;
305 long NumFifos;
306 long NumSockets;
307 long NumCDev;
308 long NumBDev;
309 long NumDoor;
310 long NumPort;
311 long NumAll;
312 long TotalBytes;
313 char DirPath[PATH_MAX];
314} dir_type;
315
316typedef struct dirstack_entry {
317 char * name;
318 int class;
319 unsigned long check_flags;
320 int rdepth;
321 short checked;
322 short childs_checked;
323 short is_reported;
324 /* struct dirstack_entry * next; */
325} dirstack_t;
326
327
328/* the destructor
329 */
330void free_dirstack (void * inptr)
331{
332 dirstack_t * here;
333
334 SL_ENTER(_("free_dirstack"));
335 if (inptr == NULL)
336 SL_RET0(_("free_dirstack"));
337 else
338 here = (dirstack_t *) inptr;
339
340 if (here->name != NULL)
341 SH_FREE(here->name);
342 SH_FREE(here);
343 SL_RET0(_("free_dirstack"));
344}
345
346/* Function to return the key for indexing
347 * the argument
348 */
349zAVLKey zdirstack_key (void const * arg)
350{
351 const dirstack_t * sa = (const dirstack_t *) arg;
352 return (zAVLKey) sa->name;
353}
354
355#define SH_LIST_FILE 0
356#define SH_LIST_DIR1 1
357#define SH_LIST_DIR2 2
358
359
360static int which_dirList = SH_LIST_DIR1;
361
362static zAVLTree * zdirListOne = NULL;
363static zAVLTree * zdirListTwo = NULL;
364static zAVLTree * zfileList = NULL;
365
366SH_MUTEX_STATIC(mutex_zfiles, PTHREAD_MUTEX_INITIALIZER);
367SH_MUTEX_STATIC(mutex_zglob, PTHREAD_MUTEX_INITIALIZER);
368SH_MUTEX_RECURSIVE(mutex_zdirs);
369
370static int sh_files_fullpath (const char * testdir,
371 const char * d_name,
372 char * statpath);
373static int sh_files_pushdir (int class, const char * str_s);
374static int sh_files_pushfile (int class, const char * str_s);
375
376static long MaxRecursionLevel = 0;
377
378/* set default recursion level
379 */
380int sh_files_setrecursion (const char * flag_s)
381{
382 long flag = 0;
383 static int reject = 0;
384
385 SL_ENTER( _("sh_files_setrecursion"));
386
387 if (reject == 1)
388 SL_RETURN((-1), _("sh_files_setrecursion"));
389
390 if (sh.flag.opts == S_TRUE)
391 reject = 1;
392
393 if (flag_s != NULL)
394 flag = (int)(atof(flag_s));
395
396 if (flag >= 0 && flag <= 99)
397 MaxRecursionLevel = flag;
398 else
399 SL_RETURN((-1), _("sh_files_setrecursion"));
400
401 SL_RETURN((0), _("sh_files_setrecursion"));
402}
403
404static int handle_filecheck_ret(dirstack_t * ptr, char * tmp_in, int status)
405{
406 int fcount = 0;
407 char * tmp;
408
409 if (!tmp_in)
410 tmp = sh_util_safe_name (ptr->name);
411 else
412 tmp = tmp_in;
413
414 if (status == SH_FILE_UNKNOWN && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
415 {
416 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
417 tmp, status));
418
419 if ( sh.flag.checkSum == SH_CHECK_INIT ||
420 sh_hash_have_it (ptr->name) >= 0)
421 {
422 if (S_FALSE == sh_ignore_chk_del(ptr->name))
423 {
424 if (0 != hashreport_missing(ptr->name,
425 (ptr->class == SH_LEVEL_ALLIGNORE) ?
426 ShDFLevel[ptr->class] :
427 ShDFLevel[SH_ERR_T_FILE])) {
428 if (tmp == NULL)
429 tmp = sh_util_safe_name (ptr->name);
430 if (!sh_global_check_silent)
431 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
432 ShDFLevel[ptr->class] :
433 ShDFLevel[SH_ERR_T_FILE],
434 FIL__, __LINE__, 0, MSG_FI_MISS,
435 tmp);
436 ++sh.statistics.files_report;
437 }
438 }
439 }
440 else /* not there at init, and still missing */
441 {
442 if (tmp == NULL)
443 tmp = sh_util_safe_name (ptr->name);
444 sh_error_handle (SH_ERR_NOTICE,
445 FIL__, __LINE__, 0,
446 MSG_FI_FAIL,
447 tmp);
448 }
449
450 if (sh.flag.checkSum != SH_CHECK_INIT)
451 sh_hash_set_missing(ptr->name);
452
453 if (sh.flag.reportonce == S_TRUE)
454 SET_SH_FFLAG_REPORTED(ptr->is_reported);
455 }
456 else
457 {
458 /* exists (status >= 0), but was missing (reported == TRUE)
459 */
460 if (status != SH_FILE_UNKNOWN && SH_FFLAG_REPORTED_SET(ptr->is_reported))
461 {
462 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
463 sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT);
464 }
465
466 /* Catchall
467 */
468 else if (status == SH_FILE_UNKNOWN)
469 {
470 /* Thu Mar 7 15:09:40 CET 2002 Make sure missing file
471 * is reported if ptr->reported == S_TRUE because the
472 * file has been added.
473 */
474 if (sh_hash_have_it (ptr->name) >= 0 &&
475 !SH_FFLAG_REPORTED_SET(ptr->is_reported))
476 {
477 if (S_FALSE == sh_ignore_chk_del(ptr->name))
478 {
479 if (0 != hashreport_missing(ptr->name,
480 (ptr->class == SH_LEVEL_ALLIGNORE) ?
481 ShDFLevel[ptr->class] :
482 ShDFLevel[SH_ERR_T_FILE])) {
483 if (tmp == NULL)
484 tmp = sh_util_safe_name (ptr->name);
485 if (!sh_global_check_silent)
486 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE)?
487 ShDFLevel[ptr->class] :
488 ShDFLevel[SH_ERR_T_FILE],
489 FIL__, __LINE__, 0, MSG_FI_MISS,
490 tmp);
491 ++sh.statistics.files_report;
492 }
493 }
494
495 /* delete from database
496 */
497 if (sh.flag.checkSum != SH_CHECK_INIT)
498 sh_hash_set_missing(ptr->name);
499 }
500 else
501 {
502 if (tmp == NULL)
503 tmp = sh_util_safe_name (ptr->name);
504 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
505 MSG_FI_FAIL,
506 tmp);
507 if (sh.flag.checkSum != SH_CHECK_INIT)
508 sh_hash_set_visited_true(ptr->name);
509 }
510 }
511
512 ++fcount;
513 }
514 if (!tmp_in)
515 SH_FREE(tmp);
516
517 return fcount;
518}
519
520
521unsigned long sh_files_chk ()
522{
523 zAVLCursor cursor;
524 ShFileType status;
525 unsigned long fcount = 0;
526
527 char * tmp = NULL;
528
529 dirstack_t * ptr;
530 char * dir;
531 char * file;
532 int tmp_reported;
533
534 SL_ENTER(_("sh_files_chk"));
535
536 for (ptr = (dirstack_t *) zAVLFirst(&cursor, zfileList); ptr;
537 ptr = (dirstack_t *) zAVLNext(&cursor))
538 {
539
540 if (sig_urgent > 0) {
541 SL_RETURN(fcount, _("sh_files_chk"));
542 }
543
544 if (ptr->checked == S_FALSE)
545 {
546 dir = sh_util_dirname (ptr->name);
547 file = sh_util_basename (ptr->name);
548#if defined(WITH_TPT)
549 tmp = sh_util_safe_name (ptr->name);
550#endif
551
552
553 if (flag_err_info == S_TRUE)
554 {
555 char pstr[32];
556#if !defined(WITH_TPT)
557 tmp = sh_util_safe_name (ptr->name);
558#endif
559 sl_strlcpy(pstr, sh_hash_getpolicy(ptr->class), sizeof(pstr));
560 sh_error_handle ((-1), FIL__, __LINE__, 0,
561 MSG_FI_CHK, pstr, tmp);
562 }
563
564 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
565 {
566 sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL,
567 ptr->class, ptr->check_flags,
568 SH_INOTIFY_FILE, 0);
569 }
570
571 BREAKEXIT(sh_files_filecheck);
572 tmp_reported = ptr->is_reported; /* fix aliasing warning */
573 status = sh_files_filecheck (ptr->class, ptr->check_flags, dir, file,
574 &tmp_reported, 0);
575 ptr->is_reported = tmp_reported;
576
577 TPT(( 0, FIL__, __LINE__,
578 _("msg=<filecheck complete: %s> status=<%d> reported=<%d>\n"),
579 tmp, status, ptr->is_reported));
580
581 fcount += handle_filecheck_ret(ptr, tmp, status);
582
583 if (tmp != NULL)
584 {
585 SH_FREE(tmp);
586 tmp = NULL;
587 }
588 if (file)
589 SH_FREE(file);
590 if (dir)
591 SH_FREE(dir);
592
593 ptr->checked = S_TRUE;
594 }
595 }
596
597 SL_RETURN(fcount, _("sh_files_chk"));
598}
599
600static zAVLTree * fileTree = NULL;
601static zAVLTree * dirTree = NULL;
602
603static void clear_lists()
604{
605 if (fileTree) {
606 zAVL_string_reset(fileTree);
607 fileTree = NULL;
608 }
609 if (dirTree) {
610 zAVL_string_reset(dirTree);
611 dirTree = NULL;
612 }
613 return;
614}
615
616static void add_to_filelist(zAVLTree * tree)
617{
618 dirstack_t * ptr;
619 zAVLCursor avlcursor;
620
621 SL_ENTER(_("add_to_filelist"));
622
623 SH_MUTEX_LOCK(mutex_zfiles);
624 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
625 ptr = (dirstack_t *) zAVLNext(&avlcursor))
626 zAVL_string_set (&fileTree, ptr->name);
627 SH_MUTEX_UNLOCK(mutex_zfiles);
628 SL_RET0(_("add_to_filelist"));
629}
630static void add_to_dirlist(zAVLTree * tree)
631{
632 dirstack_t * ptr;
633 zAVLCursor avlcursor;
634
635 SL_ENTER(_("add_to_dirlist"));
636
637 SH_MUTEX_LOCK(mutex_zfiles);
638 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
639 ptr = (dirstack_t *) zAVLNext(&avlcursor))
640 zAVL_string_set (&dirTree, ptr->name);
641 SH_MUTEX_UNLOCK(mutex_zfiles);
642 SL_RET0(_("add_to_dirlist"));
643}
644char * sh_files_findfile(const char * path)
645{
646 return zAVL_string_get (fileTree, path);
647}
648
649void * sh_dummy_621_candidate;
650
651static char * intern_find_morespecific_dir(zAVLTree * tree,
652 const char * path, size_t * len)
653{
654 dirstack_t * ptr;
655 zAVLCursor avlcursor;
656 size_t l_path = strlen(path);
657 size_t l_name;
658 char * candidate = NULL;
659 volatile size_t l_candidate = 0;
660
661 if (NULL == tree)
662 return NULL;
663
664 sh_dummy_621_candidate = (void *) &candidate;
665
666 SH_MUTEX_LOCK(mutex_zfiles);
667 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
668 ptr = (dirstack_t *) zAVLNext(&avlcursor))
669 {
670 l_name = strlen(ptr->name);
671 if (l_name <= l_path)
672 {
673 if (0 == strncmp(ptr->name, path, l_name))
674 {
675 if ((l_name == l_path) || (path[l_name] == '/'))
676 {
677 if (!candidate || (l_candidate < l_name))
678 {
679 candidate = ptr->name;
680 l_candidate = l_name;
681 *len = l_candidate;
682 }
683 }
684 }
685 }
686 }
687 SH_MUTEX_UNLOCK(mutex_zfiles);
688 return candidate;
689}
690char * sh_files_find_mostspecific_dir(const char * path)
691{
692 size_t l_one = 0;
693 size_t l_two = 0;
694 char * one;
695 char * two;
696
697 one = intern_find_morespecific_dir(zdirListOne, path, &l_one);
698 two = intern_find_morespecific_dir(zdirListTwo, path, &l_two);
699
700 if (l_one > l_two) return one;
701 else return two;
702}
703
704int sh_files_delfilestack ()
705{
706 SL_ENTER(_("sh_files_delfilestack"));
707
708 SH_MUTEX_LOCK(mutex_zfiles);
709 zAVLFreeTree (zfileList, free_dirstack);
710 zfileList = NULL;
711 SH_MUTEX_UNLOCK(mutex_zfiles);
712
713 SL_RETURN(0, _("sh_files_delfilestack"));
714}
715
716int sh_files_setrec_int (zAVLTree * tree)
717{
718 dirstack_t * ptr;
719 zAVLCursor avlcursor;
720
721 SL_ENTER(_("sh_files_setrec"));
722 if (tree != NULL) {
723 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, tree); ptr;
724 ptr = (dirstack_t *) zAVLNext(&avlcursor))
725 {
726 if (ptr->rdepth < (-1) || ptr->rdepth > 99)
727 {
728 ptr->rdepth = MaxRecursionLevel;
729 }
730
731 if ( (ptr->rdepth == (-1)) &&
732 (ptr->class == SH_LEVEL_ALLIGNORE) &&
733 (sh.flag.checkSum != SH_CHECK_INIT))
734 hash_remove_tree (ptr->name);
735 }
736 }
737 SL_RETURN(0, _("sh_files_setrec"));
738}
739
740int sh_files_setrec ()
741{
742 volatile int ret;
743 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
744 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
745 clear_lists();
746 add_to_dirlist(zdirListOne);
747 add_to_dirlist(zdirListTwo);
748 add_to_filelist(zfileList);
749 sh_files_setrec_int(zdirListOne);
750 ret = sh_files_setrec_int(zdirListTwo);
751 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
752
753 return ret;
754}
755
756zAVLTree * sh_files_deldirstack_int (zAVLTree * ptr)
757{
758 SL_ENTER(_("sh_files_deldirstack"));
759
760 zAVLFreeTree (ptr, free_dirstack);
761
762 SL_RETURN(NULL, _("sh_files_deldirstack"));
763}
764
765int sh_files_deldirstack ()
766{
767 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
768 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
769 zdirListOne = sh_files_deldirstack_int(zdirListOne);
770 zdirListTwo = sh_files_deldirstack_int(zdirListTwo);
771 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
772 return 0;
773}
774
775void sh_files_reset()
776{
777 dirstack_t * ptr;
778 zAVLCursor avlcursor;
779
780 SL_ENTER(_("sh_files_reset"));
781
782 SH_MUTEX_LOCK(mutex_zfiles);
783 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor, zfileList); ptr;
784 ptr = (dirstack_t *) zAVLNext(&avlcursor))
785 ptr->checked = 0;
786 SH_MUTEX_UNLOCK(mutex_zfiles);
787 SL_RET0(_("sh_files_reset"));
788}
789
790void sh_dirs_reset()
791{
792 dirstack_t * ptr;
793 zAVLCursor avlcursor1;
794 zAVLCursor avlcursor2;
795
796 SL_ENTER(_("sh_dirs_reset"));
797
798 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
799 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
800 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor1, zdirListOne); ptr;
801 ptr = (dirstack_t *) zAVLNext(&avlcursor1))
802 ptr->checked = 0;
803
804 for (ptr = (dirstack_t *) zAVLFirst(&avlcursor2, zdirListTwo); ptr;
805 ptr = (dirstack_t *) zAVLNext(&avlcursor2))
806 ptr->checked = 0;
807 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
808
809 SL_RET0(_("sh_dirs_reset"));
810}
811
812
813int sh_files_pushfile_prelink (const char * str_s)
814{
815 return (sh_files_pushfile (SH_LEVEL_PRELINK, str_s));
816}
817
818int sh_files_pushfile_user0 (const char * str_s)
819{
820 return (sh_files_pushfile (SH_LEVEL_USER0, str_s));
821}
822
823int sh_files_pushfile_user1 (const char * str_s)
824{
825 return (sh_files_pushfile (SH_LEVEL_USER1, str_s));
826}
827
828int sh_files_pushfile_user2 (const char * str_s)
829{
830 return (sh_files_pushfile (SH_LEVEL_USER2, str_s));
831}
832
833int sh_files_pushfile_user3 (const char * str_s)
834{
835 return (sh_files_pushfile (SH_LEVEL_USER3, str_s));
836}
837
838int sh_files_pushfile_user4 (const char * str_s)
839{
840 return (sh_files_pushfile (SH_LEVEL_USER4, str_s));
841}
842
843
844int sh_files_pushfile_ro (const char * str_s)
845{
846 return (sh_files_pushfile (SH_LEVEL_READONLY, str_s));
847}
848
849int sh_files_pushfile_attr (const char * str_s)
850{
851 return (sh_files_pushfile (SH_LEVEL_ATTRIBUTES, str_s));
852}
853
854int sh_files_pushfile_log (const char * str_s)
855{
856 return (sh_files_pushfile (SH_LEVEL_LOGFILES, str_s));
857}
858
859int sh_files_pushfile_glog (const char * str_s)
860{
861 return (sh_files_pushfile (SH_LEVEL_LOGGROW, str_s));
862}
863
864int sh_files_pushfile_noig (const char * str_s)
865{
866 return (sh_files_pushfile (SH_LEVEL_NOIGNORE, str_s));
867}
868
869int sh_files_pushfile_allig (const char * str_s)
870{
871 return (sh_files_pushfile (SH_LEVEL_ALLIGNORE, str_s));
872}
873
874
875static void sh_files_set_mask (unsigned long * mask,
876 unsigned long val, int act)
877{
878 SL_ENTER(_("sh_files_set_mask"));
879
880 if (act == 0)
881 (*mask) = val;
882 else if (act > 0)
883 (*mask) |= val;
884 else
885 (*mask) &= ~val;
886
887 SL_RET0(_("sh_files_set_mask"));
888}
889
890/* set mask(class)
891 */
892static int sh_files_parse_mask (unsigned long * mask, const char * str)
893{
894 int l, i = 0, act = 0, k = 0;
895 char myword[64];
896
897 SL_ENTER(_("sh_files_parse_mask"));
898
899 myword[0] = '\0';
900
901 if (str == NULL)
902 {
903 SL_RETURN ( (-1), _("sh_files_parse_mask"));
904 }
905 else
906 l = sl_strlen(str);
907
908 while (i < l) {
909
910 if (str[i] == '\0')
911 break;
912
913 if (str[i] == ' ' || str[i] == '\t' || str[i] == ',')
914 {
915 ++i;
916 continue;
917 }
918
919 if (str[i] == '+')
920 {
921 act = +1; ++i;
922 myword[0] = '\0';
923 goto getword;
924 }
925 else if (str[i] == '-')
926 {
927 act = -1; ++i;
928 myword[0] = '\0';
929 goto getword;
930 }
931 else /* a word */
932 {
933 getword:
934 k = 0;
935 while (k < 63 && str[i] != ' ' && str[i] != '\t' && str[i] != ','
936 && str[i] != '+' && str[i] != '-' && str[i] != '\0') {
937 myword[k] = str[i];
938 ++i; ++k;
939 }
940 myword[k] = '\0';
941
942 if (sl_strlen(myword) == 0)
943 {
944 SL_RETURN ( (-1), _("sh_files_parse_mask"));
945 }
946
947/* checksum */
948 if (0 == strcmp(myword, _("CHK")))
949 sh_files_set_mask (mask, MODI_CHK, act);
950/* link */
951 else if (0 == strcmp(myword, _("LNK")))
952 sh_files_set_mask (mask, MODI_LNK, act);
953/* inode */
954 else if (0 == strcmp(myword, _("RDEV")))
955 sh_files_set_mask (mask, MODI_RDEV, act);
956/* inode */
957 else if (0 == strcmp(myword, _("INO")))
958 sh_files_set_mask (mask, MODI_INO, act);
959/* user */
960 else if (0 == strcmp(myword, _("USR")))
961 sh_files_set_mask (mask, MODI_USR, act);
962/* group */
963 else if (0 == strcmp(myword, _("GRP")))
964 sh_files_set_mask (mask, MODI_GRP, act);
965/* mtime */
966 else if (0 == strcmp(myword, _("MTM")))
967 sh_files_set_mask (mask, MODI_MTM, act);
968/* ctime */
969 else if (0 == strcmp(myword, _("CTM")))
970 sh_files_set_mask (mask, MODI_CTM, act);
971/* atime */
972 else if (0 == strcmp(myword, _("ATM")))
973 sh_files_set_mask (mask, MODI_ATM, act);
974/* size */
975 else if (0 == strcmp(myword, _("SIZ")))
976 sh_files_set_mask (mask, MODI_SIZ, act);
977/* file mode */
978 else if (0 == strcmp(myword, _("MOD")))
979 sh_files_set_mask (mask, MODI_MOD, act);
980/* hardlinks */
981 else if (0 == strcmp(myword, _("HLN")))
982 sh_files_set_mask (mask, MODI_HLN, act);
983/* size may grow */
984 else if (0 == strcmp(myword, _("SGROW")))
985 sh_files_set_mask (mask, MODI_SGROW, act);
986/* use prelink */
987 else if (0 == strcmp(myword, _("PRE")))
988 sh_files_set_mask (mask, MODI_PREL, act);
989/* get content */
990 else if (0 == strcmp(myword, _("TXT")))
991 sh_files_set_mask (mask, MODI_TXT, act);
992/* get audit report */
993 else if (0 == strcmp(myword, _("AUDIT")))
994 sh_files_set_mask (mask, MODI_AUDIT, act);
995 else
996 {
997 SL_RETURN ( (-1), _("sh_files_parse_mask"));
998 }
999 act = 0;
1000 myword[0] = '\0';
1001 }
1002 }
1003 SL_RETURN ( (0), _("sh_files_parse_mask"));
1004}
1005
1006int sh_files_redef_prelink(const char * str)
1007{
1008 return (sh_files_parse_mask(&mask_PRELINK, str));
1009}
1010int sh_files_redef_user0(const char * str)
1011{
1012 return (sh_files_parse_mask(&mask_USER0, str));
1013}
1014int sh_files_redef_user1(const char * str)
1015{
1016 return (sh_files_parse_mask(&mask_USER1, str));
1017}
1018int sh_files_redef_user2(const char * str)
1019{
1020 return (sh_files_parse_mask(&mask_USER2, str));
1021}
1022int sh_files_redef_user3(const char * str)
1023{
1024 return (sh_files_parse_mask(&mask_USER3, str));
1025}
1026int sh_files_redef_user4(const char * str)
1027{
1028 return (sh_files_parse_mask(&mask_USER4, str));
1029}
1030int sh_files_redef_readonly(const char * str)
1031{
1032 return (sh_files_parse_mask(&mask_READONLY, str));
1033}
1034int sh_files_redef_loggrow(const char * str)
1035{
1036 return (sh_files_parse_mask(&mask_LOGGROW, str));
1037}
1038int sh_files_redef_logfiles(const char * str)
1039{
1040 return (sh_files_parse_mask(&mask_LOGFILES, str));
1041}
1042int sh_files_redef_attributes(const char * str)
1043{
1044 return (sh_files_parse_mask(&mask_ATTRIBUTES, str));
1045}
1046int sh_files_redef_noignore(const char * str)
1047{
1048 return (sh_files_parse_mask(&mask_NOIGNORE, str));
1049}
1050int sh_files_redef_allignore(const char * str)
1051{
1052 return (sh_files_parse_mask(&mask_ALLIGNORE, str));
1053}
1054
1055unsigned long sh_files_maskof (int class)
1056{
1057 switch (class)
1058 {
1059 case SH_LEVEL_READONLY:
1060 return (unsigned long) (mask_READONLY | MODI_INIT);
1061 case SH_LEVEL_ATTRIBUTES:
1062 return (unsigned long) (mask_ATTRIBUTES | MODI_INIT);
1063 case SH_LEVEL_LOGFILES:
1064 return (unsigned long) (mask_LOGFILES | MODI_INIT);
1065 case SH_LEVEL_LOGGROW:
1066 return (unsigned long) (mask_LOGGROW | MODI_INIT);
1067 case SH_LEVEL_ALLIGNORE:
1068 return (unsigned long) (mask_ALLIGNORE | MODI_INIT);
1069 case SH_LEVEL_NOIGNORE:
1070 return (unsigned long) (mask_NOIGNORE | MODI_INIT);
1071 case SH_LEVEL_USER0:
1072 return (unsigned long) (mask_USER0 | MODI_INIT);
1073 case SH_LEVEL_USER1:
1074 return (unsigned long) (mask_USER1 | MODI_INIT);
1075 case SH_LEVEL_USER2:
1076 return (unsigned long) (mask_USER2 | MODI_INIT);
1077 case SH_LEVEL_USER3:
1078 return (unsigned long) (mask_USER3 | MODI_INIT);
1079 case SH_LEVEL_USER4:
1080 return (unsigned long) (mask_USER4 | MODI_INIT);
1081 case SH_LEVEL_PRELINK:
1082 return (unsigned long) (mask_PRELINK | MODI_INIT);
1083 default:
1084 return (unsigned long) 0;
1085 }
1086}
1087
1088#ifdef HAVE_GLOB_H
1089int sh_files_has_metachar (const char * str)
1090{
1091 SL_ENTER(_("sh_files_has_metachar"));
1092 if (NULL != strchr(str, '*'))
1093 SL_RETURN(1, _("sh_files_has_metachar"));
1094 else if (NULL != strchr(str, '?'))
1095 SL_RETURN(1, _("sh_files_has_metachar"));
1096 else if (NULL != (strchr(str, '[')))
1097 SL_RETURN(1, _("sh_files_has_metachar"));
1098 else
1099 SL_RETURN(0, _("sh_files_has_metachar"));
1100}
1101
1102
1103int sh_files_globerr (const char * epath, int errnum)
1104{
1105 char * p;
1106 char errbuf[SH_ERRBUF_SIZE];
1107
1108 SL_ENTER(_("sh_files_globerr"));
1109
1110 if (errnum == ENOTDIR || errnum == ENOENT)
1111 {
1112 SL_RETURN(0, _("sh_files_globerr"));
1113 }
1114
1115 p = sh_util_safe_name (epath);
1116 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, errnum, MSG_FI_GLOB,
1117 sh_error_message (errnum, errbuf, sizeof(errbuf)), p);
1118 SH_FREE(p);
1119
1120 SL_RETURN(0, _("sh_files_globerr"));
1121}
1122
1123/* #ifdef HAVE_GLOB_H
1124 */
1125#endif
1126
1127int sh_files_push_file_int (int class, const char * str_s, size_t len,
1128 unsigned long check_flags)
1129{
1130 dirstack_t * new_item_ptr;
1131 char * fileName;
1132 int ret;
1133 volatile int count = 0;
1134
1135 SL_ENTER(_("sh_files_push_file_int"));
1136
1137 fileName = SH_ALLOC(len+1);
1138 sl_strlcpy(fileName, str_s, len+1);
1139
1140 new_item_ptr = (dirstack_t *) SH_ALLOC (sizeof(dirstack_t));
1141
1142 new_item_ptr->name = fileName;
1143 new_item_ptr->class = class;
1144 new_item_ptr->check_flags = check_flags;
1145 new_item_ptr->rdepth = 0;
1146 new_item_ptr->checked = S_FALSE;
1147 new_item_ptr->is_reported = 0;
1148 new_item_ptr->childs_checked = S_FALSE;
1149
1150 SH_MUTEX_LOCK(mutex_zfiles);
1151 if (zfileList == NULL)
1152 {
1153 zfileList = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1154 if (zfileList == NULL)
1155 {
1156 (void) safe_logger (0, 0, NULL);
1157 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1158 }
1159 }
1160
1161 ret = zAVLInsert (zfileList, new_item_ptr);
1162 SH_MUTEX_UNLOCK(mutex_zfiles);
1163
1164 if (-1 == ret)
1165 {
1166 (void) safe_logger (0, 0, NULL);
1167 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1168 }
1169 else if (3 == ret)
1170 {
1171 if (sh.flag.started != S_TRUE)
1172 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1173 fileName);
1174 SH_FREE(fileName);
1175 SH_FREE(new_item_ptr);
1176 new_item_ptr = NULL;
1177 }
1178 else
1179 {
1180 int reported;
1181 unsigned long check_flags = sh_files_maskof(class);
1182
1183 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
1184 {
1185 sh_files_filecheck (class, check_flags, str_s, NULL,
1186 &reported, 0);
1187 if (SH_FFLAG_REPORTED_SET(reported))
1188 sh_files_set_file_reported(str_s);
1189 sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL,
1190 class, check_flags,
1191 SH_INOTIFY_FILE, 0);
1192 }
1193
1194 if (MODI_AUDIT_ENABLED(check_flags))
1195 {
1196 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1197 _("Setting audit watch"),
1198 _("sh_files_push_file_int"), str_s);
1199 sh_audit_mark(str_s);
1200 }
1201 ++count;
1202 }
1203 SL_RETURN(count, _("sh_files_push_file_int"));
1204}
1205
1206int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags);
1207
1208#ifdef HAVE_GLOB_H
1209
1210typedef struct globstack_entry {
1211 char * name;
1212 char * type_name;
1213 int class;
1214 unsigned long check_flags;
1215 int rdepth;
1216 short type;
1217 /* struct dirstack_entry * next; */
1218} sh_globstack_t;
1219
1220static zAVLTree * zglobList = NULL;
1221
1222zAVLKey zglobstack_key (void const * arg)
1223{
1224 const sh_globstack_t * sa = (const sh_globstack_t *) arg;
1225 return (zAVLKey) sa->type_name;
1226}
1227
1228
1229static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
1230 unsigned long check_flags_in, int flag)
1231{
1232 int globstatus = -1;
1233 unsigned int gloop;
1234 glob_t pglob;
1235
1236 volatile int count = 0;
1237 volatile unsigned long check_flags = (flag == 0) ? sh_files_maskof(class) : check_flags_in;
1238
1239 SL_ENTER(_("sh_files_pushglob"));
1240
1241 pglob.gl_offs = 0;
1242 globstatus = glob (p, 0, sh_files_globerr, &pglob);
1243
1244 if (sh.flag.checkSum != SH_CHECK_INIT)
1245 {
1246 sh_globstack_t * new_item_ptr;
1247 char * fileName;
1248 char * typeName;
1249 int ret;
1250
1251 SH_MUTEX_TRYLOCK(mutex_zfiles);
1252 fileName = sh_util_strdup (p);
1253 typeName = sh_util_strconcat ((type == SH_LIST_FILE) ? "F" : "D", p, NULL);
1254
1255 new_item_ptr = (sh_globstack_t *) SH_ALLOC (sizeof(sh_globstack_t));
1256
1257 new_item_ptr->name = fileName;
1258 new_item_ptr->type_name = typeName;
1259 new_item_ptr->class = class;
1260 new_item_ptr->check_flags = check_flags;
1261 new_item_ptr->rdepth = rdepth;
1262 new_item_ptr->type = type;
1263
1264 if (zglobList == NULL)
1265 {
1266 zglobList = zAVLAllocTree (zglobstack_key, zAVL_KEY_STRING);
1267 if (zglobList == NULL)
1268 {
1269 (void) safe_logger (0, 0, NULL);
1270 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1271 }
1272 }
1273
1274 ret = zAVLInsert (zglobList, new_item_ptr);
1275
1276 if (ret != 0) /* already in list */
1277 {
1278 SH_FREE(fileName);
1279 SH_FREE(typeName);
1280 SH_FREE(new_item_ptr);
1281 }
1282 SH_MUTEX_TRYLOCK_UNLOCK(mutex_zfiles);
1283 }
1284
1285
1286 if (globstatus == 0 && pglob.gl_pathc > 0)
1287 {
1288 for (gloop = 0; gloop < (unsigned int) pglob.gl_pathc; ++gloop)
1289 {
1290 if (type == SH_LIST_FILE)
1291 {
1292 count += sh_files_push_file_int (class, pglob.gl_pathv[gloop],
1293 sl_strlen(pglob.gl_pathv[gloop]), check_flags);
1294 }
1295 else
1296 {
1297 which_dirList = type;
1298
1299 count += sh_files_push_dir_int (class, pglob.gl_pathv[gloop],
1300 sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_flags);
1301 }
1302 }
1303 }
1304 else
1305 {
1306 char * tmp = sh_util_safe_name (p);
1307
1308 if (pglob.gl_pathc == 0
1309#ifdef GLOB_NOMATCH
1310 || globstatus == GLOB_NOMATCH
1311#endif
1312 )
1313 sh_error_handle ((sh.flag.started != S_TRUE) ? SH_ERR_ERR : SH_ERR_NOTICE,
1314 FIL__, __LINE__,
1315 globstatus, MSG_FI_GLOB,
1316 _("No matches found"), tmp);
1317#ifdef GLOB_NOSPACE
1318 else if (globstatus == GLOB_NOSPACE)
1319 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1320 globstatus, MSG_FI_GLOB,
1321 _("Out of memory"), tmp);
1322#endif
1323#ifdef GLOB_ABORTED
1324 else if (globstatus == GLOB_ABORTED)
1325 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1326 globstatus, MSG_FI_GLOB,
1327 _("Read error"), tmp);
1328#endif
1329 else
1330 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__,
1331 globstatus, MSG_FI_GLOB,
1332 _("Unknown error"), tmp);
1333
1334 SH_FREE(tmp);
1335
1336 }
1337
1338 globfree(&pglob);
1339 SL_RETURN(count, _("sh_files_pushglob"));
1340 return count;
1341}
1342
1343void sh_files_check_globFilePatterns()
1344{
1345 sh_globstack_t * testPattern;
1346 zAVLCursor cursor;
1347
1348 SL_ENTER(_("sh_files_check_globPatterns"));
1349
1350 SH_MUTEX_LOCK(mutex_zglob);
1351 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1352 testPattern;
1353 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1354 {
1355 if (testPattern->type == SH_LIST_FILE)
1356 {
1357 sh_files_pushglob(testPattern->class, testPattern->type,
1358 testPattern->name, testPattern->rdepth,
1359 testPattern->check_flags, 1);
1360 }
1361 }
1362 SH_MUTEX_UNLOCK(mutex_zglob);
1363 SL_RET0(_("sh_files_check_globPatterns"));
1364}
1365
1366void sh_files_check_globPatterns()
1367{
1368 sh_globstack_t * testPattern;
1369 zAVLCursor cursor;
1370
1371 SL_ENTER(_("sh_files_check_globPatterns"));
1372
1373 SH_MUTEX_LOCK(mutex_zglob);
1374 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
1375 testPattern;
1376 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
1377 {
1378 sh_files_pushglob(testPattern->class, testPattern->type,
1379 testPattern->name, testPattern->rdepth,
1380 testPattern->check_flags, 1);
1381 }
1382 SH_MUTEX_UNLOCK(mutex_zglob);
1383 SL_RET0(_("sh_files_check_globPatterns"));
1384}
1385
1386/* the destructor
1387 */
1388void free_globstack (void * inptr)
1389{
1390 sh_globstack_t * here;
1391
1392 SL_ENTER(_("free_globstack"));
1393 if (inptr == NULL)
1394 SL_RET0(_("free_globstack"));
1395 else
1396 here = (sh_globstack_t *) inptr;
1397
1398 if (here->name != NULL)
1399 SH_FREE(here->name);
1400 if (here->type_name != NULL)
1401 SH_FREE(here->type_name);
1402 SH_FREE(here);
1403 SL_RET0(_("free_globstack"));
1404}
1405
1406int sh_files_delglobstack ()
1407{
1408 SL_ENTER(_("sh_files_delglobstack"));
1409
1410 SH_MUTEX_LOCK(mutex_zglob);
1411 zAVLFreeTree (zglobList, free_globstack);
1412 zglobList = NULL;
1413 SH_MUTEX_UNLOCK(mutex_zglob);
1414
1415 SL_RETURN(0, _("sh_files_delglobstack"));
1416}
1417
1418
1419#else
1420void sh_files_check_globPatterns()
1421{
1422 return;
1423}
1424int sh_files_delglobstack ()
1425{
1426 return 0;
1427}
1428#endif
1429
1430static int sh_files_pushfile (int class, const char * str_s)
1431{
1432 size_t len;
1433 char * tmp;
1434 char * p;
1435
1436 static int reject = 0;
1437
1438 SL_ENTER(_("sh_files_pushfile"));
1439
1440 if (reject == 1)
1441 SL_RETURN((-1),_("sh_files_pushfile"));
1442
1443 /* if we push a filename from the command line, make sure it
1444 * is the only one -- and will stay the only one
1445 */
1446 if (sh.flag.opts == S_TRUE)
1447 {
1448 sh_files_delfilestack ();
1449 sh_files_deldirstack ();
1450 sh_files_delglobstack ();
1451 reject = 1;
1452 }
1453
1454 p = sh_files_parse_input(str_s, &len);
1455 if (!p || len == 0)
1456 SL_RETURN((-1), _("sh_files_pushfile"));
1457
1458 if (sh.flag.checkSum == SH_CHECK_INIT)
1459 p = sh_dbIO_rootfs_prepend(p);
1460
1461 if (len >= PATH_MAX)
1462 {
1463 /* Name too long
1464 */
1465 tmp = sh_util_safe_name (p);
1466 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1467 tmp);
1468 SH_FREE(tmp);
1469 SL_RETURN((-1),_("sh_files_pushfile"));
1470 }
1471 else if (p[0] != '/')
1472 {
1473 /* Not an absolute path
1474 */
1475 tmp = sh_util_safe_name (p);
1476 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1477 tmp);
1478 SH_FREE(tmp);
1479 SL_RETURN((-1),_("sh_files_pushfile"));
1480 }
1481 else
1482 {
1483 /* remove a terminating '/', take care of the
1484 * special case of the root directory.
1485 */
1486 if (p[len-1] == '/' && len > 1)
1487 {
1488 p[len-1] = '\0';
1489 --len;
1490 }
1491 }
1492
1493#ifdef HAVE_GLOB_H
1494 if (0 == sh_files_has_metachar(p))
1495 {
1496 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1497 }
1498 else
1499 {
1500 sh_files_pushglob (class, SH_LIST_FILE, p, 0, 0, 0);
1501 }
1502
1503#else
1504 sh_files_push_file_int (class, p, len, sh_files_maskof(class));
1505#endif
1506
1507 SH_FREE(p);
1508 SL_RETURN((0),_("sh_files_pushfile"));
1509}
1510
1511
1512/* ------ directories ----- */
1513
1514int sh_files_is_allignore_int (char * str, zAVLTree * tree)
1515{
1516 dirstack_t * ptr;
1517
1518 SL_ENTER(_("sh_files_is_allignore"));
1519
1520 if (tree)
1521 {
1522 ptr = zAVLSearch(tree, str);
1523 if (ptr)
1524 {
1525 if (ptr->class == SH_LEVEL_ALLIGNORE)
1526 SL_RETURN( 1, _("sh_files_is_allignore"));
1527 else
1528 SL_RETURN( 0, _("sh_files_is_allignore"));
1529 }
1530 }
1531 SL_RETURN( 0, _("sh_files_is_allignore"));
1532}
1533
1534int sh_files_is_allignore (char * str)
1535{
1536 int retval = 0;
1537
1538 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1539 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1540 retval = sh_files_is_allignore_int(str, zdirListOne);
1541
1542 if (NULL != zdirListTwo && retval == 0)
1543 {
1544 retval = sh_files_is_allignore_int(str, zdirListTwo);
1545 }
1546 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1547 return retval;
1548}
1549
1550void * sh_dummy_1493_ptr;
1551
1552unsigned long sh_dirs_chk (int which)
1553{
1554 zAVLTree * tree;
1555 zAVLCursor cursor;
1556 dirstack_t * ptr;
1557 dirstack_t * dst_ptr;
1558 int status;
1559 int tmp_reported;
1560 volatile int filetype = SH_FILE_UNKNOWN;
1561 volatile unsigned long dcount = 0;
1562 char * tmp;
1563
1564 SL_ENTER(_("sh_dirs_chk"));
1565
1566 sh_dummy_1493_ptr = (void *) &ptr;
1567
1568 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1569 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1570 if (which == 1)
1571 tree = zdirListOne;
1572 else
1573 tree = zdirListTwo;
1574
1575 for (ptr = (dirstack_t *) zAVLFirst(&cursor, tree); ptr;
1576 ptr = (dirstack_t *) zAVLNext(&cursor))
1577 {
1578 if (sig_urgent > 0) {
1579 goto out;
1580 }
1581
1582 if (ptr->checked == S_FALSE)
1583 {
1584 SH_MUTEX_LOCK(mutex_zfiles);
1585 /* 28 Aug 2001 check the top level directory
1586 */
1587 status = S_FALSE;
1588 dst_ptr = zAVLSearch(zfileList, ptr->name);
1589 if (dst_ptr)
1590 {
1591 if (dst_ptr->checked == S_FALSE)
1592 {
1593 BREAKEXIT(sh_files_filecheck);
1594 tmp_reported = dst_ptr->is_reported;
1595 filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_flags,
1596 ptr->name,
1597 NULL, &tmp_reported, 0);
1598 dst_ptr->is_reported = tmp_reported;
1599 (void) handle_filecheck_ret(dst_ptr, NULL, filetype);
1600
1601 dst_ptr->checked = S_TRUE;
1602 status = S_TRUE;
1603 }
1604 else
1605 {
1606 status = S_TRUE;
1607 }
1608 }
1609 SH_MUTEX_UNLOCK(mutex_zfiles);
1610
1611 if (status == S_FALSE)
1612 {
1613 tmp_reported = ptr->is_reported;
1614 filetype = sh_files_filecheck (ptr->class, ptr->check_flags,
1615 ptr->name, NULL, &tmp_reported, 0);
1616 ptr->is_reported = tmp_reported;
1617 (void) handle_filecheck_ret(ptr, NULL, filetype);
1618 }
1619
1620 BREAKEXIT(sh_files_checkdir);
1621 status = sh_files_checkdir (ptr->class, ptr->check_flags,
1622 ptr->rdepth, ptr->name,
1623 ptr->name);
1624
1625 if (status < 0 && (!SH_FFLAG_REPORTED_SET(ptr->is_reported)))
1626 {
1627 /* directory is missing
1628 */
1629 if (S_FALSE == sh_ignore_chk_del(ptr->name))
1630 {
1631 if (0 != hashreport_missing(ptr->name,
1632 (ptr->class == SH_LEVEL_ALLIGNORE) ?
1633 ShDFLevel[ptr->class] :
1634 ShDFLevel[SH_ERR_T_DIR])) {
1635 tmp = sh_util_safe_name (ptr->name);
1636 if (!sh_global_check_silent)
1637 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1638 ShDFLevel[ptr->class] :
1639 ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
1640 0, MSG_FI_MISS, tmp);
1641 ++sh.statistics.files_report;
1642 SH_FREE(tmp);
1643 }
1644 }
1645 if (sh.flag.reportonce == S_TRUE)
1646 SET_SH_FFLAG_REPORTED(ptr->is_reported);
1647 }
1648 else
1649 {
1650 /* exists (status >= 0), but was missing (reported == TRUE)
1651 */
1652 if (status >= 0 && SH_FFLAG_REPORTED_SET(ptr->is_reported))
1653 {
1654 CLEAR_SH_FFLAG_REPORTED(ptr->is_reported);
1655 sh_hash_clear_flag(ptr->name, SH_FFLAG_ENOENT);
1656#if 0
1657 /* obsoleted (really?) by the mandatory sh_files_filecheck()
1658 * above, which will catch missing directories anyway
1659 */
1660 tmp = sh_util_safe_name (ptr->name);
1661 if (!sh_global_check_silent)
1662 sh_error_handle ((ptr->class == SH_LEVEL_ALLIGNORE) ?
1663 ShDFLevel[ptr->class] :
1664 ShDFLevel[SH_ERR_T_DIR],
1665 FIL__, __LINE__, 0, MSG_FI_ADD,
1666 tmp);
1667 ++sh.statistics.files_report;
1668 SH_FREE(tmp);
1669#endif
1670 }
1671 else if (status == SH_FILE_UNKNOWN)
1672 {
1673 /* catchall
1674 */
1675 tmp = sh_util_safe_name (ptr->name);
1676 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0,
1677 MSG_FI_FAIL,
1678 tmp);
1679 SH_FREE(tmp);
1680 if (sh.flag.checkSum != SH_CHECK_INIT)
1681 sh_hash_set_visited_true(ptr->name);
1682 }
1683
1684 ++dcount;
1685 }
1686 ptr->checked = S_TRUE;
1687 ptr->childs_checked = S_TRUE;
1688 }
1689
1690 if (sig_urgent > 0) {
1691 goto out;
1692 }
1693
1694 }
1695 out:
1696 ; /* 'label at end of compound statement' */
1697 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1698
1699 SL_RETURN(dcount, _("sh_dirs_chk"));
1700}
1701
1702int sh_files_pushdir_prelink (const char * str_s)
1703{
1704 return (sh_files_pushdir (SH_LEVEL_PRELINK, str_s));
1705}
1706
1707int sh_files_pushdir_user0 (const char * str_s)
1708{
1709 return (sh_files_pushdir (SH_LEVEL_USER0, str_s));
1710}
1711
1712int sh_files_pushdir_user1 (const char * str_s)
1713{
1714 return (sh_files_pushdir (SH_LEVEL_USER1, str_s));
1715}
1716
1717int sh_files_pushdir_user2 (const char * str_s)
1718{
1719 return (sh_files_pushdir (SH_LEVEL_USER2, str_s));
1720}
1721
1722int sh_files_pushdir_user3 (const char * str_s)
1723{
1724 return (sh_files_pushdir (SH_LEVEL_USER3, str_s));
1725}
1726
1727int sh_files_pushdir_user4 (const char * str_s)
1728{
1729 return (sh_files_pushdir (SH_LEVEL_USER4, str_s));
1730}
1731
1732int sh_files_pushdir_attr (const char * str_s)
1733{
1734 return (sh_files_pushdir (SH_LEVEL_ATTRIBUTES, str_s));
1735}
1736
1737int sh_files_pushdir_ro (const char * str_s)
1738{
1739 return (sh_files_pushdir (SH_LEVEL_READONLY, str_s));
1740}
1741
1742int sh_files_pushdir_log (const char * str_s)
1743{
1744 return (sh_files_pushdir (SH_LEVEL_LOGFILES, str_s));
1745}
1746
1747int sh_files_pushdir_glog (const char * str_s)
1748{
1749 return (sh_files_pushdir (SH_LEVEL_LOGGROW, str_s));
1750}
1751
1752int sh_files_pushdir_noig (const char * str_s)
1753{
1754 return (sh_files_pushdir (SH_LEVEL_NOIGNORE, str_s));
1755}
1756
1757int sh_files_pushdir_allig (const char * str_s)
1758{
1759 return (sh_files_pushdir (SH_LEVEL_ALLIGNORE, str_s));
1760}
1761
1762int set_dirList (int which)
1763{
1764 if (which == 2)
1765 which_dirList = SH_LIST_DIR2;
1766 else
1767 which_dirList = SH_LIST_DIR1;
1768 return 0;
1769}
1770
1771int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags)
1772{
1773 zAVLTree * tree;
1774 dirstack_t * new_item_ptr;
1775 char * dirName;
1776 int ret;
1777
1778 SL_ENTER(_("sh_files_push_dir_int"));
1779
1780 dirName = SH_ALLOC(len+1);
1781 sl_strlcpy(dirName, tail, len+1);
1782
1783 new_item_ptr = (dirstack_t * ) SH_ALLOC (sizeof(dirstack_t));
1784
1785 new_item_ptr->name = dirName;
1786 new_item_ptr->class = class;
1787 new_item_ptr->check_flags = check_flags;
1788 new_item_ptr->rdepth = rdepth;
1789 new_item_ptr->checked = S_FALSE;
1790 new_item_ptr->is_reported = 0;
1791 new_item_ptr->childs_checked = S_FALSE;
1792
1793 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
1794 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
1795 if (which_dirList == SH_LIST_DIR1)
1796 {
1797 tree = zdirListOne;
1798 }
1799 else
1800 {
1801 tree = zdirListTwo;
1802 }
1803
1804 if (tree == NULL)
1805 {
1806 tree = zAVLAllocTree (zdirstack_key, zAVL_KEY_STRING);
1807 if (tree == NULL)
1808 {
1809 (void) safe_logger (0, 0, NULL);
1810 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1811 }
1812 if (which_dirList == SH_LIST_DIR1)
1813 zdirListOne = tree;
1814 else
1815 zdirListTwo = tree;
1816 }
1817
1818 ret = zAVLInsert (tree, new_item_ptr);
1819 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
1820
1821 if (-1 == ret)
1822 {
1823 (void) safe_logger (0, 0, NULL);
1824 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
1825 }
1826 if (3 == ret)
1827 {
1828 if (sh.flag.started != S_TRUE)
1829 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
1830 dirName);
1831 SH_FREE(dirName);
1832 SH_FREE(new_item_ptr);
1833 new_item_ptr = NULL;
1834 }
1835 else
1836 {
1837 if (MODI_AUDIT_ENABLED(check_flags))
1838 {
1839 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1840 _("Setting audit watch"),
1841 _("sh_files_push_file_int"), tail);
1842 sh_audit_mark(tail);
1843 }
1844 }
1845 SL_RETURN(0, _("sh_files_push_dir_int"));
1846}
1847
1848static int sh_files_pushdir (int class, const char * str_s)
1849{
1850 char * tmp;
1851 size_t len;
1852 int rdepth = 0;
1853 char * tail = NULL;
1854 char * p;
1855
1856 SL_ENTER(_("sh_files_pushdir"));
1857
1858 if (sh.flag.opts == S_TRUE) {
1859 sh_files_delfilestack ();
1860 sh_files_deldirstack ();
1861 sh_files_delglobstack ();
1862 }
1863
1864 p = sh_files_parse_input(str_s, &len);
1865 if (!p || len == 0)
1866 SL_RETURN((-1),_("sh_files_pushdir"));
1867
1868 if (p[0] != '/')
1869 {
1870 rdepth = strtol(p, &tail, 10);
1871 if (tail == p)
1872 {
1873 SH_FREE(p);
1874 SL_RETURN((-1), _("sh_files_pushdir"));
1875 }
1876 }
1877 else
1878 tail = p;
1879
1880
1881 if (tail == p)
1882 {
1883 /* Setting to an invalid number will force MaxRecursionLevel,
1884 * see sh_files_setrec_int()
1885 */
1886 rdepth = (-2);
1887 }
1888 else if ( (rdepth < (-1) || rdepth > 99) ||
1889 ((rdepth == (-1)) && (class != SH_LEVEL_ALLIGNORE)) )
1890 {
1891 SH_FREE(p);
1892 SL_RETURN((-1), _("sh_files_pushdir"));
1893 }
1894
1895 if (sh.flag.checkSum == SH_CHECK_INIT)
1896 tail = sh_dbIO_rootfs_prepend(tail);
1897
1898 len = sl_strlen(tail);
1899
1900 if (len >= PATH_MAX)
1901 {
1902 tmp = sh_util_safe_name (tail);
1903 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_2LONG,
1904 tmp);
1905 SH_FREE(tmp);
1906 SH_FREE(p);
1907 SL_RETURN((-1), _("sh_files_pushdir"));
1908 }
1909 else if (len < 1)
1910 {
1911 SH_FREE(p);
1912 SL_RETURN((-1), _("sh_files_pushdir"));
1913 }
1914 else if (tail[0] != '/')
1915 {
1916 tmp = sh_util_safe_name (tail);
1917 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NOPATH,
1918 tmp);
1919 SH_FREE(tmp);
1920 SH_FREE(p);
1921 SL_RETURN((-1), _("sh_files_pushdir"));
1922 }
1923 else
1924 {
1925 if (tail[len-1] == '/' && len > 1)
1926 {
1927 tail[len-1] = '\0';
1928 --len;
1929 }
1930 }
1931
1932#ifdef HAVE_GLOB_H
1933 if (0 == sh_files_has_metachar(tail))
1934 {
1935 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1936 }
1937 else
1938 {
1939 sh_files_pushglob (class, which_dirList, tail, rdepth, 0, 0);
1940 }
1941#else
1942 sh_files_push_dir_int (class, tail, len, rdepth, sh_files_maskof(class));
1943#endif
1944
1945 SH_FREE(p);
1946 SL_RETURN((0), _("sh_files_pushdir"));
1947}
1948
1949/**
1950struct sh_dirent {
1951 char * sh_d_name;
1952 struct sh_dirent * next;
1953};
1954**/
1955
1956void kill_sh_dirlist (struct sh_dirent * dirlist)
1957{
1958 struct sh_dirent * this;
1959
1960 while (dirlist)
1961 {
1962 this = dirlist->next;
1963 SH_FREE(dirlist->sh_d_name);
1964 SH_FREE(dirlist);
1965 dirlist = this;
1966 }
1967 return;
1968}
1969
1970/* -- add an entry to a directory listing
1971 */
1972struct sh_dirent * addto_sh_dirlist (struct dirent * thisEntry,
1973 struct sh_dirent * dirlist)
1974{
1975 struct sh_dirent * this;
1976 size_t len;
1977
1978 if (thisEntry == NULL)
1979 return dirlist;
1980
1981 len = sl_strlen(thisEntry->d_name);
1982 if (len == 0)
1983 return dirlist;
1984 ++len;
1985
1986 this = SH_ALLOC(sizeof(struct sh_dirent));
1987 if (!this)
1988 return dirlist;
1989
1990 this->sh_d_name = SH_ALLOC(len);
1991 sl_strlcpy(this->sh_d_name, thisEntry->d_name, len);
1992
1993 this->next = dirlist;
1994 return this;
1995}
1996
1997static int sh_check_hardlinks = S_TRUE;
1998
1999/* Simply sets our boolean as to whether this check is active
2000 */
2001int sh_files_check_hardlinks (const char * opt)
2002{
2003 int i;
2004 SL_ENTER(_("sh_files_check_hardlinks"));
2005 i = sh_util_flagval(opt, &sh_check_hardlinks);
2006 SL_RETURN(i, _("sh_files_check_hardlinks"));
2007}
2008
2009struct sh_hle_struct {
2010 long offset;
2011 char * path;
2012 struct sh_hle_struct * next;
2013};
2014
2015static struct sh_hle_struct * sh_hl_exc = NULL;
2016
2017int sh_files_hle_reg (const char * str)
2018{
2019 long offset;
2020 size_t len;
2021 char * path;
2022
2023 struct sh_hle_struct * tmp = sh_hl_exc;
2024
2025 SL_ENTER(_("sh_files_hle_reg"));
2026
2027 /* Free the linked list if called with NULL argument
2028 */
2029 if (str == NULL)
2030 {
2031 while (tmp)
2032 {
2033 sh_hl_exc = tmp->next;
2034 SH_FREE(tmp->path);
2035 SH_FREE(tmp);
2036 tmp = sh_hl_exc;
2037 }
2038 sh_hl_exc = NULL;
2039 SL_RETURN(0, _("sh_files_hle_reg"));
2040 }
2041
2042 /* We expect 'offset:/path'
2043 */
2044 offset = strtol(str, &path, 0);
2045 if ((path == NULL) || (*path == '\0') || (*path != ':') || (path[1] != '/'))
2046 {
2047 SL_RETURN(-1, _("sh_files_hle_reg"));
2048 }
2049 ++path;
2050 len = 1 + sl_strlen(path);
2051
2052 tmp = SH_ALLOC(sizeof(struct sh_hle_struct));
2053 tmp->path = SH_ALLOC(len);
2054 sl_strlcpy (tmp->path, path, len);
2055 tmp->offset = offset;
2056 tmp->next = sh_hl_exc;
2057 sh_hl_exc = tmp;
2058
2059 SL_RETURN(0, _("sh_files_hle_reg"));
2060}
2061
2062#if !defined(HOST_IS_DARWIN)
2063static int sh_files_hle_test (int offset, char * path)
2064{
2065 struct sh_hle_struct * tmp = sh_hl_exc;
2066
2067 SL_ENTER(_("sh_files_hle_reg"));
2068
2069 while(tmp)
2070 {
2071 if ((offset == tmp->offset) && (0 == strcmp(path, tmp->path)))
2072 {
2073 SL_RETURN(0, _("sh_files_hle_test"));
2074 }
2075 tmp = tmp->next;
2076 }
2077#ifdef HAVE_FNMATCH_H
2078 if ( (offset == 1) && (0 == fnmatch(_("/run/user/*"), path, FNM_PATHNAME)) )
2079 {
2080 /* gvfs directory in /run/user/username/ */
2081 SL_RETURN(0, _("sh_files_hle_test"));
2082 }
2083#endif
2084
2085 SL_RETURN(-1, _("sh_files_hle_test"));
2086}
2087#endif
2088
2089/* This is the LCG from Numerical Recipies. Deterministic.
2090 */
2091static unsigned int simple_rand(unsigned int * state)
2092{
2093 *state = 1664525 * (*state) + 1013904223;
2094 return *state;
2095}
2096
2097void * sh_dummy_dirlist;
2098void * sh_dummy_tmpcat;
2099
2100/* -- Check a single directory and its content. Does not
2101 * check the directory inode itself.
2102 */
2103int sh_files_checkdir (int iclass, unsigned long check_flags,
2104 int idepth, char * iname,
2105 char * relativeName)
2106{
2107 struct sh_dirent * dirlist;
2108 struct sh_dirent * dirlist_orig;
2109
2110 DIR * thisDir = NULL;
2111 struct dirent * thisEntry;
2112#if defined(SH_USE_SCANDIR)
2113 struct dirent **entryList;
2114 int entry;
2115#endif
2116 int status;
2117 int dummy = S_FALSE;
2118 dir_type * theDir;
2119 ShFileType checkit;
2120 static unsigned int state = 1;
2121
2122 file_type * theFile;
2123 char * tmpname;
2124 char * tmpcat;
2125 char errbuf[SH_ERRBUF_SIZE];
2126
2127 int rdepth = 0;
2128 int class = 0;
2129 volatile int rdepth_next;
2130 volatile int class_next;
2131 volatile int file_class_next;
2132 volatile unsigned long check_flags_next;
2133 volatile unsigned long file_check_flags_next;
2134
2135 volatile int checked_flag = S_FALSE;
2136 volatile int cchecked_flag = S_FALSE;
2137
2138 dirstack_t * dst_ptr;
2139 dirstack_t * tmp_ptr;
2140
2141 int hardlink_num = 0;
2142#if !defined(HOST_IS_DARWIN)
2143 size_t len;
2144#endif
2145
2146 SL_ENTER(_("sh_files_checkdir"));
2147
2148 if (sig_urgent > 0) {
2149 SL_RETURN((0), _("sh_files_checkdir"));
2150 }
2151
2152 if (iname == NULL || idepth < (-1))
2153 SL_RETURN((-1), _("sh_files_checkdir"));
2154
2155 if (idepth < 0)
2156 {
2157 /* hash_remove_tree (iname); */
2158 SL_RETURN((0), _("sh_files_checkdir"));
2159 }
2160
2161 rdepth = idepth;
2162 class = iclass;
2163
2164 tmpname = sh_util_safe_name (iname);
2165
2166 /* ---- check for obscure name ----
2167 */
2168 if (iclass != SH_LEVEL_ALLIGNORE)
2169 {
2170 sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME], iname, S_TRUE);
2171 }
2172
2173 if (flag_err_info == S_TRUE)
2174 {
2175 char pstr[32];
2176
2177 sl_strlcpy(pstr, sh_hash_getpolicy(iclass), sizeof(pstr));
2178 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CHK, pstr, tmpname);
2179 }
2180
2181 /* ---- check input ----
2182 */
2183 if ( sl_strlen(iname) >= PATH_MAX)
2184 {
2185 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2186 MSG_FI_2LONG,
2187 tmpname);
2188 SH_FREE(tmpname);
2189 SL_RETURN((-1), _("sh_files_checkdir"));
2190 }
2191
2192 /* ---- check for absolute path ---- */
2193 if ( iname[0] != '/')
2194 {
2195 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2196 MSG_FI_NOPATH,
2197 tmpname);
2198 SH_FREE(tmpname);
2199 SL_RETURN((-1), _("sh_files_checkdir"));
2200 }
2201
2202 /* ---- stat the directory ----
2203 */
2204 theFile = SH_ALLOC(sizeof(file_type));
2205 sl_strlcpy (theFile->fullpath, iname, PATH_MAX);
2206 theFile->attr_string = NULL;
2207 theFile->link_path = NULL;
2208 theFile->check_flags = check_flags;
2209
2210 (void) relativeName;
2211 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_DIR],
2212 iname,
2213 theFile, NULL, iclass);
2214
2215 if ((sig_termfast == 1) || (sig_terminate == 1))
2216 {
2217 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2218 if (theFile->link_path) SH_FREE(theFile->link_path);
2219 SH_FREE(theFile);
2220 SH_FREE(tmpname);
2221 SL_RETURN((0), _("sh_files_checkdir"));
2222 }
2223
2224 if (status == -1)
2225 {
2226 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2227 if (theFile->link_path) SH_FREE(theFile->link_path);
2228 SH_FREE(theFile);
2229 SH_FREE(tmpname);
2230 SL_RETURN((-1), _("sh_files_checkdir"));
2231 }
2232
2233 if (theFile->c_mode[0] != 'd')
2234 {
2235 if (!sh_global_check_silent)
2236 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2237 MSG_FI_NODIR,
2238 tmpname);
2239 ++sh.statistics.files_nodir;
2240 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2241 if (theFile->link_path) SH_FREE(theFile->link_path);
2242 SH_FREE(theFile);
2243 SH_FREE(tmpname);
2244 SL_RETURN((-1), _("sh_files_checkdir"));
2245 }
2246
2247 if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
2248 {
2249 sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
2250 iclass, check_flags, SH_INOTIFY_DIR, idepth);
2251 }
2252
2253 hardlink_num = theFile->hardlinks;
2254
2255 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2256 if (theFile->link_path) SH_FREE(theFile->link_path);
2257 SH_FREE(theFile);
2258
2259 /* ---- open directory for reading ----
2260 *
2261 * opendir() will fail with ENOTDIR if the path has been changed
2262 * to a non-directory in between lstat() and opendir().
2263 */
2264 thisDir = opendir (iname);
2265
2266 if (thisDir == NULL)
2267 {
2268 status = errno;
2269 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2270 MSG_E_OPENDIR,
2271 sh_error_message (status, errbuf, sizeof(errbuf)), tmpname);
2272 SH_FREE(tmpname);
2273 SL_RETURN((-1), _("sh_files_checkdir"));
2274 }
2275
2276 theDir = SH_ALLOC(sizeof(dir_type));
2277
2278 theDir->NumRegular = 0;
2279 theDir->NumDirs = 0;
2280 theDir->NumSymlinks = 0;
2281 theDir->NumFifos = 0;
2282 theDir->NumSockets = 0;
2283 theDir->NumCDev = 0;
2284 theDir->NumBDev = 0;
2285 theDir->NumDoor = 0;
2286 theDir->NumPort = 0;
2287 theDir->NumAll = 0;
2288 theDir->TotalBytes = 0;
2289 sl_strlcpy (theDir->DirPath, iname, PATH_MAX);
2290
2291
2292 sh_dummy_dirlist = (void *) &dirlist;
2293 sh_dummy_tmpcat = (void *) &tmpcat;
2294
2295 /* ---- read ----
2296 */
2297 SH_MUTEX_LOCK(mutex_readdir);
2298
2299 dirlist = NULL;
2300 dirlist_orig = NULL;
2301
2302#if defined(SH_USE_SCANDIR)
2303 entry = scandir(iname, &entryList, 0, alphasort);
2304 while(entry > 0) { /* scandir() may return -1 on error! */
2305 entry--;
2306 thisEntry = entryList[entry];
2307#else
2308 do {
2309 thisEntry = readdir (thisDir);
2310#endif
2311 if (thisEntry != NULL)
2312 {
2313 ++theDir->NumAll;
2314 if (sl_strcmp (thisEntry->d_name, ".") == 0)
2315 {
2316 ++theDir->NumDirs;
2317 continue;
2318 }
2319 if (sl_strcmp (thisEntry->d_name, "..") == 0)
2320 {
2321 ++theDir->NumDirs;
2322 continue;
2323 }
2324 dirlist = addto_sh_dirlist (thisEntry, dirlist);
2325 }
2326 }
2327#if !defined(SH_USE_SCANDIR)
2328 while (thisEntry != NULL);
2329#endif
2330
2331 SH_MUTEX_UNLOCK(mutex_readdir);
2332
2333 closedir (thisDir);
2334
2335 ++sh.statistics.dirs_checked;
2336
2337 dirlist_orig = dirlist;
2338
2339 do {
2340
2341 /* If the directory is empty, dirlist = NULL
2342 */
2343 if (!dirlist)
2344 break;
2345
2346 if (sig_termfast == 1)
2347 {
2348 SH_FREE(theDir);
2349 SH_FREE(tmpname);
2350 SL_RETURN((0), _("sh_files_checkdir"));
2351 }
2352
2353 BREAKEXIT(sh_derr);
2354
2355 if (0 == (simple_rand(&state) % 5)) (void) sh_derr();
2356
2357 /* ---- Check the file. ----
2358 */
2359 tmpcat = SH_ALLOC(PATH_MAX);
2360 sl_strlcpy(tmpcat, iname, PATH_MAX);
2361 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
2362 sl_strlcat(tmpcat, "/", PATH_MAX);
2363 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
2364
2365 rdepth_next = rdepth - 1;
2366 class_next = class;
2367 check_flags_next = check_flags;
2368 file_class_next = class;
2369 file_check_flags_next = check_flags;
2370 checked_flag = -1;
2371 cchecked_flag = -1;
2372
2373 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
2374 * this fixes the problem that the directory special file
2375 * is checked with the policy of the parent directory
2376 */
2377 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2378 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2379 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2380
2381 if (dst_ptr)
2382 {
2383 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2384 * this fixes the problem that a policy for the directory
2385 * inode erroneously becomes a policy for the directory itself.
2386 */
2387 file_class_next = dst_ptr->class;
2388 file_check_flags_next = dst_ptr->check_flags;
2389 checked_flag = dst_ptr->checked;
2390 cchecked_flag = dst_ptr->childs_checked;
2391 }
2392
2393 if (checked_flag == -1)
2394 {
2395 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2396
2397 if (dst_ptr)
2398 {
2399 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2400 * this fixes the problem that a policy for the directory
2401 * inode erroneously becomes a policy for the directory itself.
2402 */
2403 file_class_next = dst_ptr->class;
2404 file_check_flags_next = dst_ptr->check_flags;
2405 checked_flag = dst_ptr->checked;
2406 cchecked_flag = dst_ptr->childs_checked;
2407 }
2408 }
2409 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2410
2411 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2412 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2413
2414 if (dst_ptr)
2415 {
2416 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2417 * this fixes the problem that a policy for the directory
2418 * inode erroneously becomes a policy for the directory itself.
2419 */
2420 file_class_next = dst_ptr->class;
2421 file_check_flags_next = dst_ptr->check_flags;
2422 checked_flag = dst_ptr->checked;
2423 /* not set, hence always FALSE */
2424 /* cchecked_flag = dst_ptr->childs_checked; */
2425
2426 if (checked_flag != S_TRUE)
2427 {
2428 /* -- need to check the file itself --
2429 */
2430 if (sh.flag.reportonce == S_TRUE)
2431 dummy = dst_ptr->is_reported;
2432 }
2433 }
2434 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2435
2436 /* ---- Has been checked already. ----
2437 */
2438 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2439 {
2440 /* Mar 11 2004 get ftype for complete directory count
2441 */
2442 checkit = sh_unix_get_ftype(tmpcat);
2443 if (checkit == SH_FILE_DIRECTORY)
2444 {
2445 ++theDir->NumDirs;
2446 }
2447 SH_FREE(tmpcat);
2448 dirlist = dirlist->next;
2449 continue;
2450 }
2451
2452 /* --- May be true, false, or not found. ---
2453 */
2454 if (checked_flag == S_TRUE)
2455 {
2456 /* -- need only the file type --
2457 */
2458 checkit = sh_unix_get_ftype(tmpcat);
2459 }
2460 else
2461 {
2462 /* -- need to check the file itself --
2463 */
2464 /* -- moved up --
2465 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
2466 * dummy = dst_ptr->is_reported;
2467 */
2468
2469 checkit = sh_files_filecheck (file_class_next, file_check_flags_next,
2470 iname,
2471 dirlist->sh_d_name,
2472 &dummy, 0);
2473
2474
2475 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2476 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2477
2478 if (dst_ptr && checked_flag == S_FALSE)
2479 dst_ptr->checked = S_TRUE;
2480
2481 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2482 */
2483 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2484 dst_ptr->is_reported = dummy;
2485
2486 if (dst_ptr)
2487 dst_ptr->childs_checked = S_TRUE;
2488 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2489 }
2490
2491 if (checkit == SH_FILE_REGULAR)
2492 ++theDir->NumRegular;
2493
2494 else if (checkit == SH_FILE_DIRECTORY)
2495 {
2496 ++theDir->NumDirs;
2497
2498 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2499 {
2500 rdepth_next = rdepth - 1;
2501
2502 /* check whether the new directory is in the
2503 * list with a recursion depth already defined
2504 */
2505 checked_flag = -1;
2506 cchecked_flag = -1;
2507
2508 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2509 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2510 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2511
2512 if (tmp_ptr)
2513 {
2514 TPT((0, FIL__, __LINE__,
2515 _("msg=<%s -> recursion depth %d\n>"),
2516 tmp_ptr->name, tmp_ptr->rdepth));
2517 rdepth_next = tmp_ptr->rdepth;
2518 class_next = tmp_ptr->class;
2519 check_flags_next = tmp_ptr->check_flags;
2520 /* 28. Aug 2001 reversed
2521 */
2522 cchecked_flag = tmp_ptr->childs_checked;
2523 checked_flag = tmp_ptr->checked;
2524 }
2525
2526 if (checked_flag == -1)
2527 {
2528 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2529
2530 if (tmp_ptr)
2531 {
2532 TPT((0, FIL__, __LINE__,
2533 _("msg=<%s -> recursion depth %d\n>"),
2534 tmp_ptr->name, tmp_ptr->rdepth));
2535 rdepth_next = tmp_ptr->rdepth;
2536 class_next = tmp_ptr->class;
2537 check_flags_next = tmp_ptr->check_flags;
2538 /* 28. Aug 2001 reversed
2539 */
2540 cchecked_flag = tmp_ptr->childs_checked;
2541 checked_flag = tmp_ptr->checked;
2542 }
2543 }
2544
2545 if (tmp_ptr && cchecked_flag == S_FALSE)
2546 {
2547 tmp_ptr->childs_checked = S_TRUE;
2548 /*
2549 * 04. Feb 2006 avoid double checking
2550 */
2551 tmp_ptr->checked = S_TRUE;
2552 }
2553 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2554
2555 if (cchecked_flag == S_FALSE)
2556 {
2557 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2558 tmpcat, dirlist->sh_d_name);
2559 /*
2560 tmp_ptr->childs_checked = S_TRUE;
2561 tmp_ptr->checked = S_TRUE;
2562 */
2563 }
2564 else if (checked_flag == -1)
2565 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2566 tmpcat, dirlist->sh_d_name);
2567
2568 }
2569 }
2570
2571 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2572 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2573 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2574 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2575 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2576 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2577 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2578
2579 SH_FREE(tmpcat);
2580
2581 if ((sig_termfast == 1) || (sig_terminate == 1))
2582 {
2583 SH_FREE(theDir);
2584 sh_dummy_dirlist = NULL;
2585 SH_FREE(tmpname);
2586 SL_RETURN((0), _("sh_files_checkdir"));
2587 }
2588
2589 dirlist = dirlist->next;
2590
2591 /* -- moved up, only affects zfileList anyway
2592 * if (dst_ptr)
2593 * dst_ptr->childs_checked = S_TRUE;
2594 */
2595
2596 } while (dirlist != NULL);
2597
2598 if (flag_err_info == S_TRUE)
2599 {
2600 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2601 theDir->NumDirs,
2602 theDir->NumRegular,
2603 theDir->NumSymlinks,
2604 theDir->NumFifos,
2605 theDir->NumSockets,
2606 theDir->NumCDev,
2607 theDir->NumBDev);
2608 }
2609
2610 kill_sh_dirlist (dirlist_orig);
2611
2612#if !defined(HOST_IS_DARWIN)
2613 /*
2614 * Hardlink check; not done on MacOS X because of resource forks
2615 */
2616 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2617 {
2618 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2619 {
2620 len = strlen(tmpname);
2621 if (sl_ok_adds(len, 256))
2622 len += 256;
2623 tmpcat = SH_ALLOC(len);
2624 sl_snprintf(tmpcat, len,
2625 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2626 tmpname, theDir->NumDirs, hardlink_num);
2627 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2628 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2629 SH_FREE(tmpcat);
2630 }
2631 }
2632#endif
2633
2634 SH_FREE(tmpname);
2635 SH_FREE(theDir);
2636
2637 sh_dummy_dirlist = NULL;
2638
2639 SL_RETURN((0), _("sh_files_checkdir"));
2640}
2641
2642void sh_files_fixup_mask (int class, unsigned long * check_flags)
2643{
2644 if (class == SH_LEVEL_ALLIGNORE)
2645 MODI_SET((*check_flags), MODI_ALLIGNORE);
2646 sh_tiger_get_mask_hashtype(check_flags);
2647 return;
2648}
2649
2650int get_the_fd (SL_TICKET ticket);
2651
2652static int sh_use_rsrc = S_FALSE;
2653
2654int sh_files_use_rsrc(const char * str)
2655{
2656 return sh_util_flagval(str, &sh_use_rsrc);
2657}
2658
2659static void * sh_dummy_fileName;
2660static void * sh_dummy_tmpname;
2661static void * sh_dummy_tmpdir;
2662
2663ShFileType sh_files_filecheck (int class, unsigned long check_flags,
2664 const char * dirName,
2665 const char * infileName,
2666 int * reported,
2667 int rsrcflag)
2668{
2669 /* 28 Aug 2001 allow NULL fileName
2670 */
2671 char * fullpath;
2672 char fileHash[2*(KEY_LEN + 1)];
2673 int status;
2674 file_type * theFile;
2675 char * tmpdir;
2676 char * tmpname;
2677 const char * fileName;
2678#if !defined(O_NOATIME)
2679 struct utimbuf utime_buf;
2680#endif
2681 static unsigned int state = 1;
2682 char sc;
2683
2684 SL_ENTER(_("sh_files_filecheck"));
2685
2686 fullpath = SH_ALLOC(PATH_MAX);
2687 theFile = SH_ALLOC(sizeof(file_type));
2688
2689 /* Take the address to keep gcc from putting it into a register.
2690 * Avoids the 'clobbered by longjmp' warning.
2691 */
2692 sh_dummy_fileName = (void *) &fileName;
2693 sh_dummy_tmpname = (void *) &tmpname;
2694 sh_dummy_tmpdir = (void *) &tmpdir;
2695
2696 BREAKEXIT(sh_derr);
2697
2698 if (0 == (simple_rand(&state) % 2)) (void) sh_derr();
2699
2700 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2701 && (infileName[0] == '/') && (infileName[1] == '\0'))
2702 {
2703 fileName = NULL;
2704 }
2705 else
2706 {
2707 fileName = infileName;
2708 }
2709
2710 /* fileName may be NULL if this is a directory
2711 */
2712 if (dirName == NULL /* || fileName == NULL */)
2713 {
2714 SH_MUTEX_LOCK(mutex_thread_nolog);
2715 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2716 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2717 SH_FREE(fullpath);
2718 SH_FREE(theFile);
2719 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2720 }
2721
2722 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2723 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2724 fileName, S_FALSE)))
2725 {
2726 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2727 {
2728 tmpname = sh_util_safe_name (fileName);
2729 SH_MUTEX_LOCK(mutex_thread_nolog);
2730 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2731 MSG_FI_OBSC2,
2732 "", tmpname);
2733 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2734 SH_FREE(tmpname);
2735 }
2736 else
2737 {
2738 tmpdir = sh_util_safe_name (dirName);
2739 tmpname = sh_util_safe_name (fileName);
2740 SH_MUTEX_LOCK(mutex_thread_nolog);
2741 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2742 MSG_FI_OBSC2,
2743 tmpdir, tmpname);
2744 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2745 SH_FREE(tmpname);
2746 SH_FREE(tmpdir);
2747 }
2748 }
2749
2750 /* sh_files_fullpath accepts NULL fileName
2751 */
2752 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2753 {
2754 tmpdir = sh_util_safe_name (dirName);
2755 tmpname = sh_util_safe_name (fileName);
2756 SH_MUTEX_LOCK(mutex_thread_nolog);
2757 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2758 MSG_FI_2LONG2,
2759 tmpdir, tmpname);
2760 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2761 SH_FREE(tmpname);
2762 SH_FREE(tmpdir);
2763 SH_FREE(fullpath);
2764 SH_FREE(theFile);
2765 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2766 }
2767
2768 /* stat the file and determine checksum (if a regular file)
2769 */
2770 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2771 theFile->check_flags = check_flags /* sh_files_maskof(class) */;
2772 theFile->file_reported = (*reported);
2773 theFile->attr_string = NULL;
2774 theFile->link_path = NULL;
2775
2776 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2777
2778 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2779 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2780 fileName,
2781 theFile, fileHash, class);
2782
2783 if (status != 0)
2784 {
2785 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2786 fullpath, status));
2787 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2788 sh_hash_set_visited_true (fullpath);
2789 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2790 if (theFile->link_path) SH_FREE(theFile->link_path);
2791 SH_FREE(fullpath);
2792 SH_FREE(theFile);
2793 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2794 }
2795
2796 if (sig_termfast == 1) {
2797 goto ret_point;
2798 }
2799
2800 /* report
2801 */
2802 if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-'))
2803 {
2804 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2805 SH_MUTEX_LOCK(mutex_thread_nolog);
2806 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2807 fileHash, tmpname);
2808 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2809 SH_FREE(tmpname);
2810 }
2811 ++sh.statistics.files_checked;
2812
2813 if ( sh.flag.checkSum == SH_CHECK_INIT)
2814 {
2815 if (class == SH_LEVEL_ALLIGNORE)
2816 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2817 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2818 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2819 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2820
2821 sh_dbIO_rootfs_strip(theFile->fullpath);
2822 if (theFile->link_path)
2823 sh_dbIO_rootfs_strip_link(theFile->link_path);
2824 sh_dbIO_data_write (theFile, fileHash);
2825 }
2826 else if (sh.flag.checkSum == SH_CHECK_CHECK
2827 /* && theFile.c_mode[0] == '-' */
2828 /* && class != SH_LEVEL_ALLIGNORE */
2829 )
2830 {
2831 if (sh.flag.update == S_TRUE)
2832 {
2833 if (class == SH_LEVEL_ALLIGNORE)
2834 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2835 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2836 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2837 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2838 }
2839 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2840 }
2841
2842 (*reported) = theFile->file_reported;
2843
2844 /* reset the access time
2845 */
2846#if !defined(O_NOATIME)
2847 if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0)
2848 {
2849 utime_buf.actime = (time_t) theFile->atime;
2850 utime_buf.modtime = (time_t) theFile->mtime;
2851
2852 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2853 }
2854#endif
2855
2856#if defined(HOST_IS_DARWIN)
2857 /*
2858 * Check for resource fork
2859 */
2860 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2861 {
2862 int dummy;
2863 static int rsrc_init = 0;
2864 static char rsrc[17];
2865 char * testpath = SH_ALLOC(PATH_MAX);
2866
2867 if (rsrc_init == 0) {
2868 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2869 rsrc_init = 1;
2870 }
2871 sl_strlcpy (testpath, fullpath, PATH_MAX);
2872 sl_strlcat (testpath, "/", PATH_MAX);
2873 sl_strlcat (testpath, rsrc, PATH_MAX);
2874
2875 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2876 {
2877 if (S_TRUE == sh_unix_file_exists (testpath))
2878 {
2879 sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1);
2880 }
2881 }
2882 SH_FREE(testpath);
2883 }
2884#else
2885 (void) rsrcflag; /* avoid compiler warning */
2886#endif
2887
2888 ret_point:
2889
2890 sc = theFile->c_mode[0];
2891
2892 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2893 if (theFile->link_path) SH_FREE(theFile->link_path);
2894 SH_FREE(fullpath);
2895 SH_FREE(theFile);
2896
2897 switch (sc)
2898 {
2899 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2900 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2901 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2902 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2903 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2904 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2905 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2906 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2907 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2908 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2909 }
2910
2911 /* notreached */
2912}
2913
2914/* concatenate statpath = testdir"/"d_name
2915 */
2916static int sh_files_fullpath (const char * testdir, const char * d_name,
2917 char * statpath)
2918{
2919 int llen = 0;
2920
2921 SL_ENTER(_("sh_files_fullpath"));
2922
2923 if (testdir != NULL)
2924 {
2925 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2926 SL_RETURN((-1),_("sh_files_fullpath"));
2927 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2928 }
2929 if (d_name != NULL)
2930 {
2931 if (llen > 1 || statpath[0] != '/')
2932 sl_strlcat(statpath, "/", PATH_MAX);
2933 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2934 SL_RETURN((-1),_("sh_files_fullpath"));
2935 sl_strlcat(statpath, d_name, PATH_MAX);
2936 }
2937 if (statpath == NULL)
2938 SL_RETURN((-1),_("sh_files_fullpath"));
2939 SL_RETURN((0),_("sh_files_fullpath"));
2940}
2941
2942/* -----------------------------------
2943 * Routines required for inotify
2944 * -----------------------------------
2945 */
2946int sh_files_search_dir(char * name, int * class,
2947 unsigned long *check_flags, int *reported,
2948 int * rdepth)
2949{
2950 volatile int retval = 0;
2951#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2952 sh_globstack_t * testPattern;
2953 zAVLCursor cursor;
2954#endif
2955 dirstack_t * item;
2956
2957 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2958 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2959
2960 item = zAVLSearch(zdirListOne, name);
2961
2962 if (item)
2963 {
2964 *check_flags = item->check_flags;
2965 *class = item->class;
2966 *reported = item->is_reported;
2967 *rdepth = item->rdepth;
2968 item->checked = S_FALSE;
2969 item->childs_checked = S_FALSE;
2970 item->is_reported = S_FALSE;
2971 retval = 1;
2972 goto out;
2973 }
2974
2975 item = zAVLSearch(zdirListTwo, name);
2976
2977 if (item)
2978 {
2979 *check_flags = item->check_flags;
2980 *class = item->class;
2981 *reported = item->is_reported;
2982 *rdepth = item->rdepth;
2983 item->checked = S_FALSE;
2984 item->childs_checked = S_FALSE;
2985 item->is_reported = S_FALSE;
2986 retval = 1;
2987 goto out;
2988 }
2989
2990#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2991 SH_MUTEX_LOCK(mutex_zglob);
2992 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2993 testPattern;
2994 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
2995 {
2996 if (testPattern->type == SH_LIST_DIR1 ||
2997 testPattern->type == SH_LIST_DIR2)
2998 {
2999 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
3000 {
3001 *check_flags = testPattern->check_flags;
3002 *class = testPattern->class;
3003 *rdepth = testPattern->rdepth;
3004 retval = 1;
3005 break;
3006 }
3007
3008 }
3009 }
3010 SH_MUTEX_UNLOCK(mutex_zglob);
3011#endif
3012 out:
3013 ; /* 'label at end of compound statement' */
3014 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3015 return retval;
3016}
3017
3018int sh_files_search_file(char * name, int * class,
3019 unsigned long *check_flags, int *reported)
3020{
3021 volatile int retval = 0;
3022#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
3023 sh_globstack_t * testPattern;
3024 zAVLCursor cursor;
3025#endif
3026 dirstack_t * item;
3027
3028 SH_MUTEX_LOCK(mutex_zfiles);
3029 item = zAVLSearch(zfileList, name);
3030
3031 if (item)
3032 {
3033 *check_flags = item->check_flags;
3034 *class = item->class;
3035 *reported = item->is_reported;
3036 retval = 1;
3037 }
3038 SH_MUTEX_UNLOCK(mutex_zfiles);
3039
3040#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
3041 if (retval == 0)
3042 {
3043 SH_MUTEX_LOCK(mutex_zglob);
3044 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
3045 testPattern;
3046 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
3047 {
3048 if (testPattern->type == SH_LIST_FILE)
3049 {
3050 if (0 == fnmatch(testPattern->name, name,
3051 FNM_PATHNAME|FNM_PERIOD))
3052 {
3053 *check_flags = testPattern->check_flags;
3054 *class = testPattern->class;
3055 retval = 1;
3056 break;
3057 }
3058
3059 }
3060 }
3061 SH_MUTEX_UNLOCK(mutex_zglob);
3062 }
3063#endif
3064
3065 return retval;
3066}
3067
3068void sh_files_set_file_reported(const char * name)
3069{
3070 dirstack_t * item;
3071
3072 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3073 item = zAVLSearch(zfileList, name);
3074
3075 if (item)
3076 {
3077 if (sh.flag.reportonce == S_TRUE)
3078 SET_SH_FFLAG_REPORTED(item->is_reported);
3079 }
3080 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3081 return;
3082}
3083
3084void sh_files_clear_file_reported(const char * name)
3085{
3086 dirstack_t * item;
3087
3088 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3089 item = zAVLSearch(zfileList, name);
3090
3091 if (item)
3092 {
3093 CLEAR_SH_FFLAG_REPORTED(item->is_reported);
3094 }
3095 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3096 return;
3097}
3098
3099/* -----------------------------------
3100 *
3101 * The following two routines serve to
3102 * verify that the user has selected
3103 * a proper setup for file policies.
3104 *
3105 * -----------------------------------
3106 */
3107static int check_file(char * name)
3108{
3109 dirstack_t * pfilL;
3110 zAVLCursor cursor;
3111 volatile int retval = -1;
3112
3113 SL_ENTER(_("check_file"));
3114
3115 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
3116 SL_RETURN(0, _("check_file"));
3117
3118 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
3119 pfilL = (dirstack_t *) zAVLNext (&cursor))
3120 {
3121 if (0 == strcmp(name, pfilL->name) &&
3122 (pfilL->check_flags & MODI_ATM) == 0 &&
3123 (pfilL->check_flags & MODI_CTM) == 0 &&
3124 (pfilL->check_flags & MODI_MTM) == 0)
3125 {
3126 retval = 0;
3127 break;
3128 }
3129 }
3130
3131 SL_RETURN(retval, _("check_file"));
3132}
3133
3134static void * sh_dummy_pdirL;
3135
3136int sh_files_test_setup_int (zAVLTree * tree)
3137{
3138 int dlen, flen;
3139 zAVLCursor cursor1;
3140 zAVLCursor cursor2;
3141
3142 dirstack_t * pdirL;
3143 dirstack_t * pfilL;
3144
3145 SL_ENTER(_("sh_files_test_setup"));
3146
3147 sh_dummy_pdirL = (void *) &pdirL;
3148
3149 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
3150 pdirL = (dirstack_t *) zAVLNext (&cursor1))
3151 {
3152 dlen = strlen(pdirL->name);
3153
3154 SH_MUTEX_LOCK(mutex_zfiles);
3155 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
3156 pfilL = (dirstack_t *) zAVLNext (&cursor2))
3157 {
3158 flen = strlen(pfilL->name);
3159
3160 /* check whether file is in tree of dir
3161 */
3162 if ((pfilL->class == SH_LEVEL_READONLY) ||
3163 (pfilL->class == SH_LEVEL_NOIGNORE))
3164 {
3165 ; /* do nothing */
3166 }
3167 else
3168 {
3169 if ((flen > (dlen+1)) &&
3170 (pfilL->name[dlen] == '/') &&
3171 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
3172 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
3173 {
3174 if ((pdirL->check_flags & MODI_ATM) != 0 ||
3175 (pdirL->check_flags & MODI_MTM) != 0 ||
3176 (pdirL->check_flags & MODI_CTM) != 0)
3177 {
3178 if (check_file (pdirL->name) != 0)
3179 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
3180 pdirL->name, pfilL->name);
3181 }
3182 }
3183 }
3184 }
3185 SH_MUTEX_UNLOCK(mutex_zfiles);
3186 }
3187
3188 SL_RETURN((0), _("sh_files_test_setup"));
3189}
3190
3191int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
3192{
3193 int retval = 0;
3194 zAVLCursor cursor;
3195 dirstack_t * first;
3196
3197 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
3198 first = (dirstack_t *) zAVLNext (&cursor))
3199 {
3200
3201 if (NULL != zAVLSearch(secondList, first->name))
3202 {
3203 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
3204 first->name);
3205 retval = 1;
3206 }
3207 }
3208 return retval;
3209}
3210
3211extern void aud_exit (const char * file, int line, int fd);
3212
3213int sh_files_test_setup ()
3214{
3215 int retval;
3216
3217 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
3218 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
3219 /* Test for modifications allowed in ReadOnly directory
3220 */
3221 sh_files_test_setup_int (zdirListOne);
3222 sh_files_test_setup_int (zdirListTwo);
3223
3224 /* Test for files/dirz defined twice
3225 */
3226 retval = sh_files_test_double (zdirListOne, zdirListTwo);
3227 if (retval != 0)
3228 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3229
3230 retval = sh_files_test_double (zdirListTwo, zdirListOne);
3231 if (retval != 0)
3232 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3233 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3234
3235 return 0;
3236}
3237
3238#endif
3239
3240#ifdef SH_CUTEST
3241#include "CuTest.h"
3242
3243void Test_file_lists (CuTest *tc)
3244{
3245#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3246
3247 extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s);
3248
3249 char * test;
3250 int ret;
3251
3252 sh_files_pushfile_ro("/usr/test");
3253 sh_files_pushfile_ro("/usr/bin/test");
3254 sh_files_pushfile_ro("/usr/bin/foo/test");
3255
3256 sh_files_pushdir_ro("/usr");
3257 sh_files_pushdir_attr("/usr/bin");
3258 sh_files_pushdir_ro("/usr/bin/foo");
3259
3260 add_to_dirlist(zdirListOne);
3261 add_to_dirlist(zdirListTwo);
3262 add_to_filelist(zfileList);
3263
3264 test = sh_files_findfile("/usr/tes");
3265 CuAssertTrue(tc, test == NULL);
3266 test = sh_files_findfile("/usr/test");
3267 CuAssertPtrNotNull(tc, test);
3268 test = sh_files_findfile("/usr/testi");
3269 CuAssertTrue(tc, test == NULL);
3270 test = sh_files_findfile("/test");
3271 CuAssertTrue(tc, test == NULL);
3272
3273 test = sh_files_find_mostspecific_dir("/usr/bin/foo/test");
3274 CuAssertStrEquals(tc, "/usr/bin/foo", test);
3275 test = sh_files_find_mostspecific_dir("/usr/bin/test");
3276 CuAssertStrEquals(tc, "/usr/bin", test);
3277 test = sh_files_find_mostspecific_dir("/usr/test");
3278 CuAssertStrEquals(tc, "/usr", test);
3279 test = sh_files_find_mostspecific_dir("/test");
3280 CuAssertTrue(tc, test == NULL);
3281 test = sh_files_find_mostspecific_dir("/usr/foo/test");
3282 CuAssertStrEquals(tc, "/usr", test);
3283
3284 test = sh_files_find_mostspecific_dir("/usr/bin");
3285 CuAssertStrEquals(tc, "/usr/bin", test);
3286
3287 ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr"));
3288 CuAssertIntEquals(tc, S_FALSE, ret);
3289 ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr"));
3290 CuAssertIntEquals(tc, S_TRUE, ret);
3291 ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr"));
3292 CuAssertIntEquals(tc, S_TRUE, ret);
3293
3294 ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin"));
3295 CuAssertIntEquals(tc, S_FALSE, ret);
3296 ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin"));
3297 CuAssertIntEquals(tc, S_FALSE, ret);
3298 ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin"));
3299 CuAssertIntEquals(tc, S_FALSE, ret);
3300
3301 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin"));
3302 CuAssertIntEquals(tc, S_FALSE, ret);
3303 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin"));
3304 CuAssertIntEquals(tc, S_TRUE, ret);
3305 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin"));
3306 CuAssertIntEquals(tc, S_TRUE, ret);
3307
3308 ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin"));
3309 CuAssertIntEquals(tc, S_TRUE, ret);
3310 ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr"));
3311 CuAssertIntEquals(tc, S_TRUE, ret);
3312 ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr"));
3313 CuAssertIntEquals(tc, S_FALSE, ret);
3314 ret = hash_remove_tree_test("/", "/usrbin", strlen("/"));
3315 CuAssertIntEquals(tc, S_TRUE, ret);
3316 ret = hash_remove_tree_test("/", "/usr", strlen("/"));
3317 CuAssertIntEquals(tc, S_FALSE, ret);
3318
3319#else
3320 (void) tc; /* fix compiler warning */
3321 return;
3322#endif
3323}
3324
3325void Test_file_dequote (CuTest *tc)
3326{
3327#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3328
3329 char str1[] = "1234567890";
3330 char str1a[] = "123456\\\"789\\r";
3331 char str1b[] = "12345678\\r9";
3332 char str1c[] = "12345678\\x0a_9";
3333 char str1d[] = "12345678\\007_9";
3334 char str1e[] = "123456789\\\\";
3335
3336 char str2[] = "1234567890\\xw";
3337 char str3[] = "1234567890\\xw99";
3338 char str4[] = "1234567890\\0ww";
3339 char str5[] = "12345\\g67890";
3340 char str6[] = "1234567890\\009a";
3341
3342 char *s, *p, *q;
3343 size_t lo, lr;
3344
3345 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
3346 q = sh_files_C_dequote(s, &lr);
3347 CuAssertPtrNotNull(tc, q);
3348 CuAssertTrue(tc, p == q);
3349 CuAssertTrue(tc, lr == lo);
3350
3351 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
3352 q = sh_files_C_dequote(s, &lr);
3353 CuAssertPtrNotNull(tc, q);
3354 CuAssertTrue(tc, p != q);
3355 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
3356 CuAssertTrue(tc, lr == (lo-2));
3357
3358 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
3359 q = sh_files_C_dequote(s, &lr);
3360 CuAssertPtrNotNull(tc, q);
3361 CuAssertTrue(tc, p != q);
3362 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
3363 CuAssertTrue(tc, lr == (lo-1));
3364
3365 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
3366 q = sh_files_C_dequote(s, &lr);
3367 CuAssertPtrNotNull(tc, q);
3368 CuAssertTrue(tc, p != q);
3369 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
3370 CuAssertTrue(tc, lr == (lo-3));
3371
3372 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
3373 q = sh_files_C_dequote(s, &lr);
3374 CuAssertPtrNotNull(tc, q);
3375 CuAssertTrue(tc, p != q);
3376 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
3377 CuAssertTrue(tc, lr == (lo-3));
3378
3379 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
3380 q = sh_files_C_dequote(s, &lr);
3381 CuAssertPtrNotNull(tc, q);
3382 CuAssertTrue(tc, p != q);
3383 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
3384 CuAssertTrue(tc, lr == (lo-1));
3385
3386 s = SH_ALLOC(64); sl_strlcpy(s, str2, 64); p = s; lo = strlen(s); lr = lo;
3387 q = sh_files_C_dequote(s, &lr);
3388 CuAssertTrue(tc, q == NULL);
3389 CuAssertTrue(tc, lr == 0);
3390
3391 s = SH_ALLOC(64); sl_strlcpy(s, str3, 64); p = s; lo = strlen(s); lr = lo;
3392 q = sh_files_C_dequote(s, &lr);
3393 CuAssertTrue(tc, q == NULL);
3394 CuAssertTrue(tc, lr == 0);
3395
3396 s = SH_ALLOC(64); sl_strlcpy(s, str4, 64); p = s; lo = strlen(s); lr = lo;
3397 q = sh_files_C_dequote(s, &lr);
3398 CuAssertTrue(tc, q == NULL);
3399 CuAssertTrue(tc, lr == 0);
3400
3401 s = SH_ALLOC(64); sl_strlcpy(s, str5, 64); p = s; lo = strlen(s); lr = lo;
3402 q = sh_files_C_dequote(s, &lr);
3403 CuAssertTrue(tc, q == NULL);
3404 CuAssertTrue(tc, lr == 0);
3405
3406 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
3407 q = sh_files_C_dequote(s, &lr);
3408 CuAssertTrue(tc, q == NULL);
3409 CuAssertTrue(tc, lr == 0);
3410
3411 return;
3412#else
3413 (void) tc; /* fix compiler warning */
3414 return;
3415#endif
3416}
3417#endif
3418
Note: See TracBrowser for help on using the repository browser.