source: trunk/src/sh_files.c@ 479

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

Fix for ticket #364 (gcc 4.9 compiler bugs).

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