source: trunk/src/sh_files.c@ 581

Last change on this file since 581 was 579, checked in by katerina, 16 months ago

Fix for ticket #467 (memleak).

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