source: trunk/src/sh_files.c@ 371

Last change on this file since 371 was 371, checked in by katerina, 13 years ago

Patch for ticket #265 (inotify support).

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