source: trunk/src/sh_files.c@ 573

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

Fix for ticket #454 (memory leak introduced in version 4.4.4).

File size: 83.3 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#if defined(SH_USE_SCANDIR)
2326 free(entryList[entry]); /* scandir() mallocs entries */
2327#endif
2328 }
2329 }
2330#if defined(SH_USE_SCANDIR)
2331 free(entryList);
2332#else
2333 while (thisEntry != NULL);
2334#endif
2335
2336 SH_MUTEX_UNLOCK(mutex_readdir);
2337
2338 closedir (thisDir);
2339
2340 ++sh.statistics.dirs_checked;
2341
2342 dirlist_orig = dirlist;
2343
2344 do {
2345
2346 /* If the directory is empty, dirlist = NULL
2347 */
2348 if (!dirlist)
2349 break;
2350
2351 if (sig_termfast == 1)
2352 {
2353 SH_FREE(theDir);
2354 SH_FREE(tmpname);
2355 SL_RETURN((0), _("sh_files_checkdir"));
2356 }
2357
2358 BREAKEXIT(sh_derr);
2359
2360 if (0 == (simple_rand(&state) % 5)) (void) sh_derr();
2361
2362 /* ---- Check the file. ----
2363 */
2364 tmpcat = SH_ALLOC(PATH_MAX);
2365 sl_strlcpy(tmpcat, iname, PATH_MAX);
2366 if (sl_strlen(tmpcat) > 1 || tmpcat[0] != '/')
2367 sl_strlcat(tmpcat, "/", PATH_MAX);
2368 sl_strlcat(tmpcat, dirlist->sh_d_name, PATH_MAX);
2369
2370 rdepth_next = rdepth - 1;
2371 class_next = class;
2372 check_flags_next = check_flags;
2373 file_class_next = class;
2374 file_check_flags_next = check_flags;
2375 checked_flag = -1;
2376 cchecked_flag = -1;
2377
2378 /* Wed Aug 24 2005 compare against dirListOne, dirListTwo
2379 * this fixes the problem that the directory special file
2380 * is checked with the policy of the parent directory
2381 */
2382 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2383 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2384 dst_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2385
2386 if (dst_ptr)
2387 {
2388 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2389 * this fixes the problem that a policy for the directory
2390 * inode erroneously becomes a policy for the directory itself.
2391 */
2392 file_class_next = dst_ptr->class;
2393 file_check_flags_next = dst_ptr->check_flags;
2394 checked_flag = dst_ptr->checked;
2395 cchecked_flag = dst_ptr->childs_checked;
2396 }
2397
2398 if (checked_flag == -1)
2399 {
2400 dst_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2401
2402 if (dst_ptr)
2403 {
2404 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2405 * this fixes the problem that a policy for the directory
2406 * inode erroneously becomes a policy for the directory itself.
2407 */
2408 file_class_next = dst_ptr->class;
2409 file_check_flags_next = dst_ptr->check_flags;
2410 checked_flag = dst_ptr->checked;
2411 cchecked_flag = dst_ptr->childs_checked;
2412 }
2413 }
2414 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2415
2416 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2417 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2418
2419 if (dst_ptr)
2420 {
2421 /* Tue Aug 6 22:13:27 CEST 2002 introduce file_class_next
2422 * this fixes the problem that a policy for the directory
2423 * inode erroneously becomes a policy for the directory itself.
2424 */
2425 file_class_next = dst_ptr->class;
2426 file_check_flags_next = dst_ptr->check_flags;
2427 checked_flag = dst_ptr->checked;
2428 /* not set, hence always FALSE */
2429 /* cchecked_flag = dst_ptr->childs_checked; */
2430
2431 if (checked_flag != S_TRUE)
2432 {
2433 /* -- need to check the file itself --
2434 */
2435 if (sh.flag.reportonce == S_TRUE)
2436 dummy = dst_ptr->is_reported;
2437 }
2438 }
2439 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2440
2441 /* ---- Has been checked already. ----
2442 */
2443 if (checked_flag == S_TRUE && cchecked_flag == S_TRUE)
2444 {
2445 /* Mar 11 2004 get ftype for complete directory count
2446 */
2447 checkit = sh_unix_get_ftype(tmpcat);
2448 if (checkit == SH_FILE_DIRECTORY)
2449 {
2450 ++theDir->NumDirs;
2451 }
2452 SH_FREE(tmpcat);
2453 dirlist = dirlist->next;
2454 continue;
2455 }
2456
2457 /* --- May be true, false, or not found. ---
2458 */
2459 if (checked_flag == S_TRUE)
2460 {
2461 /* -- need only the file type --
2462 */
2463 checkit = sh_unix_get_ftype(tmpcat);
2464 }
2465 else
2466 {
2467 /* -- need to check the file itself --
2468 */
2469 /* -- moved up --
2470 * if (dst_ptr && sh.flag.reportonce == S_TRUE)
2471 * dummy = dst_ptr->is_reported;
2472 */
2473
2474 checkit = sh_files_filecheck (file_class_next, file_check_flags_next,
2475 iname,
2476 dirlist->sh_d_name,
2477 &dummy, 0);
2478
2479
2480 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
2481 dst_ptr = (dirstack_t *) zAVLSearch(zfileList, tmpcat);
2482
2483 if (dst_ptr && checked_flag == S_FALSE)
2484 dst_ptr->checked = S_TRUE;
2485
2486 /* Thu Mar 7 15:09:40 CET 2002 Propagate the 'reported' flag
2487 */
2488 if (dst_ptr && sh.flag.reportonce == S_TRUE)
2489 dst_ptr->is_reported = dummy;
2490
2491 if (dst_ptr)
2492 dst_ptr->childs_checked = S_TRUE;
2493 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
2494 }
2495
2496 if (checkit == SH_FILE_REGULAR)
2497 ++theDir->NumRegular;
2498
2499 else if (checkit == SH_FILE_DIRECTORY)
2500 {
2501 ++theDir->NumDirs;
2502
2503 if (rdepth_next >= 0 && cchecked_flag != S_TRUE)
2504 {
2505 rdepth_next = rdepth - 1;
2506
2507 /* check whether the new directory is in the
2508 * list with a recursion depth already defined
2509 */
2510 checked_flag = -1;
2511 cchecked_flag = -1;
2512
2513 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2514 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2515 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListOne, tmpcat);
2516
2517 if (tmp_ptr)
2518 {
2519 TPT((0, FIL__, __LINE__,
2520 _("msg=<%s -> recursion depth %d\n>"),
2521 tmp_ptr->name, tmp_ptr->rdepth));
2522 rdepth_next = tmp_ptr->rdepth;
2523 class_next = tmp_ptr->class;
2524 check_flags_next = tmp_ptr->check_flags;
2525 /* 28. Aug 2001 reversed
2526 */
2527 cchecked_flag = tmp_ptr->childs_checked;
2528 checked_flag = tmp_ptr->checked;
2529 }
2530
2531 if (checked_flag == -1)
2532 {
2533 tmp_ptr = (dirstack_t *) zAVLSearch(zdirListTwo, tmpcat);
2534
2535 if (tmp_ptr)
2536 {
2537 TPT((0, FIL__, __LINE__,
2538 _("msg=<%s -> recursion depth %d\n>"),
2539 tmp_ptr->name, tmp_ptr->rdepth));
2540 rdepth_next = tmp_ptr->rdepth;
2541 class_next = tmp_ptr->class;
2542 check_flags_next = tmp_ptr->check_flags;
2543 /* 28. Aug 2001 reversed
2544 */
2545 cchecked_flag = tmp_ptr->childs_checked;
2546 checked_flag = tmp_ptr->checked;
2547 }
2548 }
2549
2550 if (tmp_ptr && cchecked_flag == S_FALSE)
2551 {
2552 tmp_ptr->childs_checked = S_TRUE;
2553 /*
2554 * 04. Feb 2006 avoid double checking
2555 */
2556 tmp_ptr->checked = S_TRUE;
2557 }
2558 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
2559
2560 if (cchecked_flag == S_FALSE)
2561 {
2562 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2563 tmpcat, dirlist->sh_d_name);
2564 /*
2565 tmp_ptr->childs_checked = S_TRUE;
2566 tmp_ptr->checked = S_TRUE;
2567 */
2568 }
2569 else if (checked_flag == -1)
2570 sh_files_checkdir (class_next, check_flags_next, rdepth_next,
2571 tmpcat, dirlist->sh_d_name);
2572
2573 }
2574 }
2575
2576 else if (checkit == SH_FILE_SYMLINK) ++theDir->NumSymlinks;
2577 else if (checkit == SH_FILE_FIFO) ++theDir->NumFifos;
2578 else if (checkit == SH_FILE_SOCKET) ++theDir->NumSockets;
2579 else if (checkit == SH_FILE_CDEV) ++theDir->NumCDev;
2580 else if (checkit == SH_FILE_BDEV) ++theDir->NumBDev;
2581 else if (checkit == SH_FILE_DOOR) ++theDir->NumDoor;
2582 else if (checkit == SH_FILE_PORT) ++theDir->NumPort;
2583
2584 SH_FREE(tmpcat);
2585
2586 if ((sig_termfast == 1) || (sig_terminate == 1))
2587 {
2588 SH_FREE(theDir);
2589 sh_dummy_dirlist = NULL;
2590 SH_FREE(tmpname);
2591 SL_RETURN((0), _("sh_files_checkdir"));
2592 }
2593
2594 dirlist = dirlist->next;
2595
2596 /* -- moved up, only affects zfileList anyway
2597 * if (dst_ptr)
2598 * dst_ptr->childs_checked = S_TRUE;
2599 */
2600
2601 } while (dirlist != NULL);
2602
2603 if (flag_err_info == S_TRUE)
2604 {
2605 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
2606 theDir->NumDirs,
2607 theDir->NumRegular,
2608 theDir->NumSymlinks,
2609 theDir->NumFifos,
2610 theDir->NumSockets,
2611 theDir->NumCDev,
2612 theDir->NumBDev);
2613 }
2614
2615 kill_sh_dirlist (dirlist_orig);
2616
2617#if !defined(HOST_IS_DARWIN)
2618 /*
2619 * Hardlink check; not done on MacOS X because of resource forks
2620 */
2621 if ((sh_check_hardlinks == S_TRUE) && (hardlink_num != theDir->NumDirs))
2622 {
2623 if (0 != sh_files_hle_test(hardlink_num-theDir->NumDirs, iname))
2624 {
2625 len = strlen(tmpname);
2626 if (sl_ok_adds(len, 256))
2627 len += 256;
2628 tmpcat = SH_ALLOC(len);
2629 sl_snprintf(tmpcat, len,
2630 _("%s: subdirectory count (%d) != hardlinks (%d)"),
2631 tmpname, theDir->NumDirs, hardlink_num);
2632 sh_error_handle (ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__, 0,
2633 MSG_E_SUBGEN, tmpcat, _("sh_files_checkdir"));
2634 SH_FREE(tmpcat);
2635 }
2636 }
2637#endif
2638
2639 SH_FREE(tmpname);
2640 SH_FREE(theDir);
2641
2642 sh_dummy_dirlist = NULL;
2643
2644 SL_RETURN((0), _("sh_files_checkdir"));
2645}
2646
2647void sh_files_fixup_mask (int class, unsigned long * check_flags)
2648{
2649 if (class == SH_LEVEL_ALLIGNORE)
2650 MODI_SET((*check_flags), MODI_ALLIGNORE);
2651 sh_tiger_get_mask_hashtype(check_flags);
2652 return;
2653}
2654
2655int get_the_fd (SL_TICKET ticket);
2656
2657static int sh_use_rsrc = S_FALSE;
2658
2659int sh_files_use_rsrc(const char * str)
2660{
2661 return sh_util_flagval(str, &sh_use_rsrc);
2662}
2663
2664static void * sh_dummy_fileName;
2665static void * sh_dummy_tmpname;
2666static void * sh_dummy_tmpdir;
2667
2668ShFileType sh_files_filecheck (int class, unsigned long check_flags,
2669 const char * dirName,
2670 const char * infileName,
2671 int * reported,
2672 int rsrcflag)
2673{
2674 /* 28 Aug 2001 allow NULL fileName
2675 */
2676 char * fullpath;
2677 char fileHash[2*(KEY_LEN + 1)];
2678 int status;
2679 file_type * theFile;
2680 char * tmpdir;
2681 char * tmpname;
2682 const char * fileName;
2683#if !defined(O_NOATIME)
2684 struct utimbuf utime_buf;
2685#endif
2686 static unsigned int state = 1;
2687 char sc;
2688
2689 SL_ENTER(_("sh_files_filecheck"));
2690
2691 fullpath = SH_ALLOC(PATH_MAX);
2692 theFile = SH_ALLOC(sizeof(file_type));
2693
2694 /* Take the address to keep gcc from putting it into a register.
2695 * Avoids the 'clobbered by longjmp' warning.
2696 */
2697 sh_dummy_fileName = (void *) &fileName;
2698 sh_dummy_tmpname = (void *) &tmpname;
2699 sh_dummy_tmpdir = (void *) &tmpdir;
2700
2701 BREAKEXIT(sh_derr);
2702
2703 if (0 == (simple_rand(&state) % 2)) (void) sh_derr();
2704
2705 if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
2706 && (infileName[0] == '/') && (infileName[1] == '\0'))
2707 {
2708 fileName = NULL;
2709 }
2710 else
2711 {
2712 fileName = infileName;
2713 }
2714
2715 /* fileName may be NULL if this is a directory
2716 */
2717 if (dirName == NULL /* || fileName == NULL */)
2718 {
2719 SH_MUTEX_LOCK(mutex_thread_nolog);
2720 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_NULL);
2721 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2722 SH_FREE(fullpath);
2723 SH_FREE(theFile);
2724 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2725 }
2726
2727 if ((fileName != NULL) && (class != SH_LEVEL_ALLIGNORE) &&
2728 (0 != sh_util_obscurename (ShDFLevel[SH_ERR_T_NAME],
2729 fileName, S_FALSE)))
2730 {
2731 if ((dirName != NULL) && (dirName[0] == '/') && (dirName[1] == '\0'))
2732 {
2733 tmpname = sh_util_safe_name (fileName);
2734 SH_MUTEX_LOCK(mutex_thread_nolog);
2735 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2736 MSG_FI_OBSC2,
2737 "", tmpname);
2738 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2739 SH_FREE(tmpname);
2740 }
2741 else
2742 {
2743 tmpdir = sh_util_safe_name (dirName);
2744 tmpname = sh_util_safe_name (fileName);
2745 SH_MUTEX_LOCK(mutex_thread_nolog);
2746 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, 0,
2747 MSG_FI_OBSC2,
2748 tmpdir, tmpname);
2749 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2750 SH_FREE(tmpname);
2751 SH_FREE(tmpdir);
2752 }
2753 }
2754
2755 /* sh_files_fullpath accepts NULL fileName
2756 */
2757 if (0 != sh_files_fullpath (dirName, fileName, fullpath))
2758 {
2759 tmpdir = sh_util_safe_name (dirName);
2760 tmpname = sh_util_safe_name (fileName);
2761 SH_MUTEX_LOCK(mutex_thread_nolog);
2762 sh_error_handle (ShDFLevel[SH_ERR_T_FILE], FIL__, __LINE__, 0,
2763 MSG_FI_2LONG2,
2764 tmpdir, tmpname);
2765 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2766 SH_FREE(tmpname);
2767 SH_FREE(tmpdir);
2768 SH_FREE(fullpath);
2769 SH_FREE(theFile);
2770 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2771 }
2772
2773 /* stat the file and determine checksum (if a regular file)
2774 */
2775 sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
2776 theFile->check_flags = check_flags /* sh_files_maskof(class) */;
2777 theFile->file_reported = (*reported);
2778 theFile->attr_string = NULL;
2779 theFile->link_path = NULL;
2780
2781 TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"), fullpath));
2782
2783 status = sh_unix_getinfo ( (class == SH_LEVEL_ALLIGNORE) ?
2784 ShDFLevel[class] : ShDFLevel[SH_ERR_T_FILE],
2785 fileName,
2786 theFile, fileHash, class);
2787
2788 if (status != 0)
2789 {
2790 TPT(( 0, FIL__, __LINE__, _("msg=<file: %s> status=<%d>\n"),
2791 fullpath, status));
2792 if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
2793 sh_hash_set_visited_true (fullpath);
2794 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2795 if (theFile->link_path) SH_FREE(theFile->link_path);
2796 SH_FREE(fullpath);
2797 SH_FREE(theFile);
2798 SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2799 }
2800
2801 if (sig_termfast == 1) {
2802 goto ret_point;
2803 }
2804
2805 /* report
2806 */
2807 if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-'))
2808 {
2809 tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
2810 SH_MUTEX_LOCK(mutex_thread_nolog);
2811 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_CSUM,
2812 fileHash, tmpname);
2813 SH_MUTEX_UNLOCK(mutex_thread_nolog);
2814 SH_FREE(tmpname);
2815 }
2816 ++sh.statistics.files_checked;
2817
2818 if ( sh.flag.checkSum == SH_CHECK_INIT)
2819 {
2820 if (class == SH_LEVEL_ALLIGNORE)
2821 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2822 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2823 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2824 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2825
2826 sh_dbIO_rootfs_strip(theFile->fullpath);
2827 if (theFile->link_path)
2828 sh_dbIO_rootfs_strip_link(theFile->link_path);
2829 sh_dbIO_data_write (theFile, fileHash);
2830 }
2831 else if (sh.flag.checkSum == SH_CHECK_CHECK
2832 /* && theFile.c_mode[0] == '-' */
2833 /* && class != SH_LEVEL_ALLIGNORE */
2834 )
2835 {
2836 if (sh.flag.update == S_TRUE)
2837 {
2838 if (class == SH_LEVEL_ALLIGNORE)
2839 MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
2840 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
2841 MODI_SET(theFile->check_flags, MODI_NOCHECK);
2842 sh_tiger_get_mask_hashtype(&(theFile->check_flags));
2843 }
2844 sh_hash_compdata (class, theFile, fileHash, NULL, -1);
2845 }
2846
2847 (*reported) = theFile->file_reported;
2848
2849 /* reset the access time
2850 */
2851#if !defined(O_NOATIME)
2852 if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0)
2853 {
2854 utime_buf.actime = (time_t) theFile->atime;
2855 utime_buf.modtime = (time_t) theFile->mtime;
2856
2857 retry_aud_utime (FIL__, __LINE__, fullpath, &utime_buf);
2858 }
2859#endif
2860
2861#if defined(HOST_IS_DARWIN)
2862 /*
2863 * Check for resource fork
2864 */
2865 if ( (sh_use_rsrc == S_TRUE) && (theFile->c_mode[0] != 'd') && (rsrcflag == 0) )
2866 {
2867 int dummy;
2868 static int rsrc_init = 0;
2869 static char rsrc[17];
2870 char * testpath = SH_ALLOC(PATH_MAX);
2871
2872 if (rsrc_init == 0) {
2873 sl_strlcpy(rsrc, _("..namedfork/rsrc"), 17);
2874 rsrc_init = 1;
2875 }
2876 sl_strlcpy (testpath, fullpath, PATH_MAX);
2877 sl_strlcat (testpath, "/", PATH_MAX);
2878 sl_strlcat (testpath, rsrc, PATH_MAX);
2879
2880 if (sl_strlen(testpath) == (17 + sl_strlen(fullpath)))
2881 {
2882 if (S_TRUE == sh_unix_file_exists (testpath))
2883 {
2884 sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1);
2885 }
2886 }
2887 SH_FREE(testpath);
2888 }
2889#else
2890 (void) rsrcflag; /* avoid compiler warning */
2891#endif
2892
2893 ret_point:
2894
2895 sc = theFile->c_mode[0];
2896
2897 if (theFile->attr_string) SH_FREE(theFile->attr_string);
2898 if (theFile->link_path) SH_FREE(theFile->link_path);
2899 SH_FREE(fullpath);
2900 SH_FREE(theFile);
2901
2902 switch (sc)
2903 {
2904 case '-': SL_RETURN(SH_FILE_REGULAR, _("sh_files_filecheck"));
2905 case 'l': SL_RETURN(SH_FILE_SYMLINK, _("sh_files_filecheck"));
2906 case 'd': SL_RETURN(SH_FILE_DIRECTORY, _("sh_files_filecheck"));
2907 case 'c': SL_RETURN(SH_FILE_CDEV, _("sh_files_filecheck"));
2908 case 'b': SL_RETURN(SH_FILE_BDEV, _("sh_files_filecheck"));
2909 case '|': SL_RETURN(SH_FILE_FIFO, _("sh_files_filecheck"));
2910 case 'D': SL_RETURN(SH_FILE_DOOR, _("sh_files_filecheck"));
2911 case 'P': SL_RETURN(SH_FILE_PORT, _("sh_files_filecheck"));
2912 case 's': SL_RETURN(SH_FILE_SOCKET, _("sh_files_filecheck"));
2913 default: SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
2914 }
2915
2916 /* notreached */
2917}
2918
2919/* concatenate statpath = testdir"/"d_name
2920 */
2921static int sh_files_fullpath (const char * testdir, const char * d_name,
2922 char * statpath)
2923{
2924 int llen = 0;
2925
2926 SL_ENTER(_("sh_files_fullpath"));
2927
2928 if (testdir != NULL)
2929 {
2930 if ( (llen = sl_strlen(testdir)) > (PATH_MAX-2) )
2931 SL_RETURN((-1),_("sh_files_fullpath"));
2932 sl_strlcpy(statpath, testdir, PATH_MAX - 1);
2933 }
2934 if (d_name != NULL)
2935 {
2936 if (llen > 1 || statpath[0] != '/')
2937 sl_strlcat(statpath, "/", PATH_MAX);
2938 if ((sl_strlen(d_name) + sl_strlen(statpath)) >= PATH_MAX)
2939 SL_RETURN((-1),_("sh_files_fullpath"));
2940 sl_strlcat(statpath, d_name, PATH_MAX);
2941 }
2942 if (statpath == NULL)
2943 SL_RETURN((-1),_("sh_files_fullpath"));
2944 SL_RETURN((0),_("sh_files_fullpath"));
2945}
2946
2947/* -----------------------------------
2948 * Routines required for inotify
2949 * -----------------------------------
2950 */
2951int sh_files_search_dir(char * name, int * class,
2952 unsigned long *check_flags, int *reported,
2953 int * rdepth)
2954{
2955 volatile int retval = 0;
2956#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2957 sh_globstack_t * testPattern;
2958 zAVLCursor cursor;
2959#endif
2960 dirstack_t * item;
2961
2962 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
2963 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
2964
2965 item = zAVLSearch(zdirListOne, name);
2966
2967 if (item)
2968 {
2969 *check_flags = item->check_flags;
2970 *class = item->class;
2971 *reported = item->is_reported;
2972 *rdepth = item->rdepth;
2973 item->checked = S_FALSE;
2974 item->childs_checked = S_FALSE;
2975 item->is_reported = S_FALSE;
2976 retval = 1;
2977 goto out;
2978 }
2979
2980 item = zAVLSearch(zdirListTwo, name);
2981
2982 if (item)
2983 {
2984 *check_flags = item->check_flags;
2985 *class = item->class;
2986 *reported = item->is_reported;
2987 *rdepth = item->rdepth;
2988 item->checked = S_FALSE;
2989 item->childs_checked = S_FALSE;
2990 item->is_reported = S_FALSE;
2991 retval = 1;
2992 goto out;
2993 }
2994
2995#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
2996 SH_MUTEX_LOCK(mutex_zglob);
2997 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
2998 testPattern;
2999 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
3000 {
3001 if (testPattern->type == SH_LIST_DIR1 ||
3002 testPattern->type == SH_LIST_DIR2)
3003 {
3004 if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
3005 {
3006 *check_flags = testPattern->check_flags;
3007 *class = testPattern->class;
3008 *rdepth = testPattern->rdepth;
3009 retval = 1;
3010 break;
3011 }
3012
3013 }
3014 }
3015 SH_MUTEX_UNLOCK(mutex_zglob);
3016#endif
3017 out:
3018 ; /* 'label at end of compound statement' */
3019 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3020 return retval;
3021}
3022
3023int sh_files_search_file(char * name, int * class,
3024 unsigned long *check_flags, int *reported)
3025{
3026 volatile int retval = 0;
3027#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
3028 sh_globstack_t * testPattern;
3029 zAVLCursor cursor;
3030#endif
3031 dirstack_t * item;
3032
3033 SH_MUTEX_LOCK(mutex_zfiles);
3034 item = zAVLSearch(zfileList, name);
3035
3036 if (item)
3037 {
3038 *check_flags = item->check_flags;
3039 *class = item->class;
3040 *reported = item->is_reported;
3041 retval = 1;
3042 }
3043 SH_MUTEX_UNLOCK(mutex_zfiles);
3044
3045#if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
3046 if (retval == 0)
3047 {
3048 SH_MUTEX_LOCK(mutex_zglob);
3049 for (testPattern = (sh_globstack_t *) zAVLFirst (&cursor, zglobList);
3050 testPattern;
3051 testPattern = (sh_globstack_t *) zAVLNext (&cursor))
3052 {
3053 if (testPattern->type == SH_LIST_FILE)
3054 {
3055 if (0 == fnmatch(testPattern->name, name,
3056 FNM_PATHNAME|FNM_PERIOD))
3057 {
3058 *check_flags = testPattern->check_flags;
3059 *class = testPattern->class;
3060 retval = 1;
3061 break;
3062 }
3063
3064 }
3065 }
3066 SH_MUTEX_UNLOCK(mutex_zglob);
3067 }
3068#endif
3069
3070 return retval;
3071}
3072
3073void sh_files_set_file_reported(const char * name)
3074{
3075 dirstack_t * item;
3076
3077 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3078 item = zAVLSearch(zfileList, name);
3079
3080 if (item)
3081 {
3082 if (sh.flag.reportonce == S_TRUE)
3083 SET_SH_FFLAG_REPORTED(item->is_reported);
3084 }
3085 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3086 return;
3087}
3088
3089void sh_files_clear_file_reported(const char * name)
3090{
3091 dirstack_t * item;
3092
3093 SH_MUTEX_LOCK_UNSAFE(mutex_zfiles);
3094 item = zAVLSearch(zfileList, name);
3095
3096 if (item)
3097 {
3098 CLEAR_SH_FFLAG_REPORTED(item->is_reported);
3099 }
3100 SH_MUTEX_UNLOCK_UNSAFE(mutex_zfiles);
3101 return;
3102}
3103
3104/* -----------------------------------
3105 *
3106 * The following two routines serve to
3107 * verify that the user has selected
3108 * a proper setup for file policies.
3109 *
3110 * -----------------------------------
3111 */
3112static int check_file(char * name)
3113{
3114 dirstack_t * pfilL;
3115 zAVLCursor cursor;
3116 volatile int retval = -1;
3117
3118 SL_ENTER(_("check_file"));
3119
3120 if (SH_FILE_DIRECTORY == sh_unix_get_ftype(name))
3121 SL_RETURN(0, _("check_file"));
3122
3123 for (pfilL = (dirstack_t *) zAVLFirst (&cursor, zfileList); pfilL;
3124 pfilL = (dirstack_t *) zAVLNext (&cursor))
3125 {
3126 if (0 == strcmp(name, pfilL->name) &&
3127 (pfilL->check_flags & MODI_ATM) == 0 &&
3128 (pfilL->check_flags & MODI_CTM) == 0 &&
3129 (pfilL->check_flags & MODI_MTM) == 0)
3130 {
3131 retval = 0;
3132 break;
3133 }
3134 }
3135
3136 SL_RETURN(retval, _("check_file"));
3137}
3138
3139static void * sh_dummy_pdirL;
3140
3141int sh_files_test_setup_int (zAVLTree * tree)
3142{
3143 int dlen, flen;
3144 zAVLCursor cursor1;
3145 zAVLCursor cursor2;
3146
3147 dirstack_t * pdirL;
3148 dirstack_t * pfilL;
3149
3150 SL_ENTER(_("sh_files_test_setup"));
3151
3152 sh_dummy_pdirL = (void *) &pdirL;
3153
3154 for (pdirL = (dirstack_t *) zAVLFirst (&cursor1, tree); pdirL;
3155 pdirL = (dirstack_t *) zAVLNext (&cursor1))
3156 {
3157 dlen = strlen(pdirL->name);
3158
3159 SH_MUTEX_LOCK(mutex_zfiles);
3160 for (pfilL = (dirstack_t *) zAVLFirst (&cursor2, zfileList); pfilL;
3161 pfilL = (dirstack_t *) zAVLNext (&cursor2))
3162 {
3163 flen = strlen(pfilL->name);
3164
3165 /* check whether file is in tree of dir
3166 */
3167 if ((pfilL->class == SH_LEVEL_READONLY) ||
3168 (pfilL->class == SH_LEVEL_NOIGNORE))
3169 {
3170 ; /* do nothing */
3171 }
3172 else
3173 {
3174 if ((flen > (dlen+1)) &&
3175 (pfilL->name[dlen] == '/') &&
3176 (NULL == strchr(&(pfilL->name[dlen+1]), '/')) && /*30-5-01*/
3177 (0 == strncmp(pfilL->name, pdirL->name, dlen)))
3178 {
3179 if ((pdirL->check_flags & MODI_ATM) != 0 ||
3180 (pdirL->check_flags & MODI_MTM) != 0 ||
3181 (pdirL->check_flags & MODI_CTM) != 0)
3182 {
3183 if (check_file (pdirL->name) != 0)
3184 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_COLL,
3185 pdirL->name, pfilL->name);
3186 }
3187 }
3188 }
3189 }
3190 SH_MUTEX_UNLOCK(mutex_zfiles);
3191 }
3192
3193 SL_RETURN((0), _("sh_files_test_setup"));
3194}
3195
3196int sh_files_test_double (zAVLTree * firstList, zAVLTree * secondList)
3197{
3198 int retval = 0;
3199 zAVLCursor cursor;
3200 dirstack_t * first;
3201
3202 for (first = (dirstack_t *) zAVLFirst (&cursor, firstList); first;
3203 first = (dirstack_t *) zAVLNext (&cursor))
3204 {
3205
3206 if (NULL != zAVLSearch(secondList, first->name))
3207 {
3208 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DOUBLE,
3209 first->name);
3210 retval = 1;
3211 }
3212 }
3213 return retval;
3214}
3215
3216extern void aud_exit (const char * file, int line, int fd);
3217
3218int sh_files_test_setup ()
3219{
3220 int retval;
3221
3222 SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
3223 SH_MUTEX_RECURSIVE_LOCK(mutex_zdirs);
3224 /* Test for modifications allowed in ReadOnly directory
3225 */
3226 sh_files_test_setup_int (zdirListOne);
3227 sh_files_test_setup_int (zdirListTwo);
3228
3229 /* Test for files/dirz defined twice
3230 */
3231 retval = sh_files_test_double (zdirListOne, zdirListTwo);
3232 if (retval != 0)
3233 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3234
3235 retval = sh_files_test_double (zdirListTwo, zdirListOne);
3236 if (retval != 0)
3237 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
3238 SH_MUTEX_RECURSIVE_UNLOCK(mutex_zdirs);
3239
3240 return 0;
3241}
3242
3243#endif
3244
3245#ifdef SH_CUTEST
3246#include "CuTest.h"
3247
3248void Test_file_lists (CuTest *tc)
3249{
3250#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3251
3252 extern int hash_remove_tree_test(char * s, char * fullpath, size_t len_s);
3253
3254 char * test;
3255 int ret;
3256
3257 sh_files_pushfile_ro("/usr/test");
3258 sh_files_pushfile_ro("/usr/bin/test");
3259 sh_files_pushfile_ro("/usr/bin/foo/test");
3260
3261 sh_files_pushdir_ro("/usr");
3262 sh_files_pushdir_attr("/usr/bin");
3263 sh_files_pushdir_ro("/usr/bin/foo");
3264
3265 add_to_dirlist(zdirListOne);
3266 add_to_dirlist(zdirListTwo);
3267 add_to_filelist(zfileList);
3268
3269 test = sh_files_findfile("/usr/tes");
3270 CuAssertTrue(tc, test == NULL);
3271 test = sh_files_findfile("/usr/test");
3272 CuAssertPtrNotNull(tc, test);
3273 test = sh_files_findfile("/usr/testi");
3274 CuAssertTrue(tc, test == NULL);
3275 test = sh_files_findfile("/test");
3276 CuAssertTrue(tc, test == NULL);
3277
3278 test = sh_files_find_mostspecific_dir("/usr/bin/foo/test");
3279 CuAssertStrEquals(tc, "/usr/bin/foo", test);
3280 test = sh_files_find_mostspecific_dir("/usr/bin/test");
3281 CuAssertStrEquals(tc, "/usr/bin", test);
3282 test = sh_files_find_mostspecific_dir("/usr/test");
3283 CuAssertStrEquals(tc, "/usr", test);
3284 test = sh_files_find_mostspecific_dir("/test");
3285 CuAssertTrue(tc, test == NULL);
3286 test = sh_files_find_mostspecific_dir("/usr/foo/test");
3287 CuAssertStrEquals(tc, "/usr", test);
3288
3289 test = sh_files_find_mostspecific_dir("/usr/bin");
3290 CuAssertStrEquals(tc, "/usr/bin", test);
3291
3292 ret = hash_remove_tree_test("/usr", "/usr/test", strlen("/usr"));
3293 CuAssertIntEquals(tc, S_FALSE, ret);
3294 ret = hash_remove_tree_test("/usr", "/usr/testi", strlen("/usr"));
3295 CuAssertIntEquals(tc, S_TRUE, ret);
3296 ret = hash_remove_tree_test("/usr", "/usr/tes", strlen("/usr"));
3297 CuAssertIntEquals(tc, S_TRUE, ret);
3298
3299 ret = hash_remove_tree_test("/usr/bin", "/usr/test", strlen("/usr/bin"));
3300 CuAssertIntEquals(tc, S_FALSE, ret);
3301 ret = hash_remove_tree_test("/usr/bin", "/usr/testi", strlen("/usr/bin"));
3302 CuAssertIntEquals(tc, S_FALSE, ret);
3303 ret = hash_remove_tree_test("/usr/bin", "/usr/tes", strlen("/usr/bin"));
3304 CuAssertIntEquals(tc, S_FALSE, ret);
3305
3306 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/test", strlen("/usr/bin"));
3307 CuAssertIntEquals(tc, S_FALSE, ret);
3308 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/testi", strlen("/usr/bin"));
3309 CuAssertIntEquals(tc, S_TRUE, ret);
3310 ret = hash_remove_tree_test("/usr/bin", "/usr/bin/tes", strlen("/usr/bin"));
3311 CuAssertIntEquals(tc, S_TRUE, ret);
3312
3313 ret = hash_remove_tree_test("/usr/bin", "/usr/bin", strlen("/usr/bin"));
3314 CuAssertIntEquals(tc, S_TRUE, ret);
3315 ret = hash_remove_tree_test("/usr", "/usr", strlen("/usr"));
3316 CuAssertIntEquals(tc, S_TRUE, ret);
3317 ret = hash_remove_tree_test("/usr", "/usrbin", strlen("/usr"));
3318 CuAssertIntEquals(tc, S_FALSE, ret);
3319 ret = hash_remove_tree_test("/", "/usrbin", strlen("/"));
3320 CuAssertIntEquals(tc, S_TRUE, ret);
3321 ret = hash_remove_tree_test("/", "/usr", strlen("/"));
3322 CuAssertIntEquals(tc, S_FALSE, ret);
3323
3324#else
3325 (void) tc; /* fix compiler warning */
3326 return;
3327#endif
3328}
3329
3330void Test_file_dequote (CuTest *tc)
3331{
3332#if (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE))
3333
3334 char str1[] = "1234567890";
3335 char str1a[] = "123456\\\"789\\r";
3336 char str1b[] = "12345678\\r9";
3337 char str1c[] = "12345678\\x0a_9";
3338 char str1d[] = "12345678\\007_9";
3339 char str1e[] = "123456789\\\\";
3340
3341 char str2[] = "1234567890\\xw";
3342 char str3[] = "1234567890\\xw99";
3343 char str4[] = "1234567890\\0ww";
3344 char str5[] = "12345\\g67890";
3345 char str6[] = "1234567890\\009a";
3346
3347 char *s, *p, *q;
3348 size_t lo, lr;
3349
3350 s = SH_ALLOC(64); sl_strlcpy(s, str1, 64); p = s; lo = strlen(s); lr = lo;
3351 q = sh_files_C_dequote(s, &lr);
3352 CuAssertPtrNotNull(tc, q);
3353 CuAssertTrue(tc, p == q);
3354 CuAssertTrue(tc, lr == lo);
3355
3356 s = SH_ALLOC(64); sl_strlcpy(s, str1a, 64); p = s; lo = strlen(s); lr = lo;
3357 q = sh_files_C_dequote(s, &lr);
3358 CuAssertPtrNotNull(tc, q);
3359 CuAssertTrue(tc, p != q);
3360 CuAssertTrue(tc, 0 == strcmp(q, "123456\"789\r"));
3361 CuAssertTrue(tc, lr == (lo-2));
3362
3363 s = SH_ALLOC(64); sl_strlcpy(s, str1b, 64); p = s; lo = strlen(s); lr = lo;
3364 q = sh_files_C_dequote(s, &lr);
3365 CuAssertPtrNotNull(tc, q);
3366 CuAssertTrue(tc, p != q);
3367 CuAssertTrue(tc, 0 == strcmp(q, "12345678\r9"));
3368 CuAssertTrue(tc, lr == (lo-1));
3369
3370 s = SH_ALLOC(64); sl_strlcpy(s, str1c, 64); p = s; lo = strlen(s); lr = lo;
3371 q = sh_files_C_dequote(s, &lr);
3372 CuAssertPtrNotNull(tc, q);
3373 CuAssertTrue(tc, p != q);
3374 CuAssertTrue(tc, 0 == strcmp(q, "12345678\x0a_9"));
3375 CuAssertTrue(tc, lr == (lo-3));
3376
3377 s = SH_ALLOC(64); sl_strlcpy(s, str1d, 64); p = s; lo = strlen(s); lr = lo;
3378 q = sh_files_C_dequote(s, &lr);
3379 CuAssertPtrNotNull(tc, q);
3380 CuAssertTrue(tc, p != q);
3381 CuAssertTrue(tc, 0 == strcmp(q, "12345678\007_9"));
3382 CuAssertTrue(tc, lr == (lo-3));
3383
3384 s = SH_ALLOC(64); sl_strlcpy(s, str1e, 64); p = s; lo = strlen(s); lr = lo;
3385 q = sh_files_C_dequote(s, &lr);
3386 CuAssertPtrNotNull(tc, q);
3387 CuAssertTrue(tc, p != q);
3388 CuAssertTrue(tc, 0 == strcmp(q, "123456789\\"));
3389 CuAssertTrue(tc, lr == (lo-1));
3390
3391 s = SH_ALLOC(64); sl_strlcpy(s, str2, 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, str3, 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, str4, 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, str5, 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 s = SH_ALLOC(64); sl_strlcpy(s, str6, 64); p = s; lo = strlen(s); lr = lo;
3412 q = sh_files_C_dequote(s, &lr);
3413 CuAssertTrue(tc, q == NULL);
3414 CuAssertTrue(tc, lr == 0);
3415
3416 return;
3417#else
3418 (void) tc; /* fix compiler warning */
3419 return;
3420#endif
3421}
3422#endif
3423
Note: See TracBrowser for help on using the repository browser.