source: trunk/src/sh_files.c@ 464

Last change on this file since 464 was 458, checked in by katerina, 10 years ago

Fix for ticket #358 (repetitive lstat warning) and #359 (reporting of added/deleted top level directories).

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