source: trunk/src/sh_files.c@ 457

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

Fix for ticket #357 (Incorrect precedence for IgnoreAll).

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