source: trunk/src/sh_files.c@ 590

Last change on this file since 590 was 590, checked in by katerina, 16 hours ago

Fix for ticket #478 (cppcheck warnings).

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