source: trunk/src/sh_hash.c@ 496

Last change on this file since 496 was 492, checked in by katerina, 9 years ago

Fix for ticket #388 (logfile rotation).

File size: 79.1 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000, 2001, 2002 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 <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28#include <ctype.h>
29
30#ifdef MAJOR_IN_MKDEV
31#include <sys/mkdev.h>
32#else
33#ifdef MAJOR_IN_SYSMACROS
34#include <sys/sysmacros.h>
35#endif
36#endif
37
38#ifdef HAVE_MEMORY_H
39#include <memory.h>
40#endif
41
42
43#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
44
45#include "samhain.h"
46#include "sh_utils.h"
47#include "sh_unix.h"
48#include "sh_dbIO_int.h"
49#include "sh_dbIO.h"
50#include "sh_hash.h"
51#include "sh_error.h"
52#include "sh_tiger.h"
53#include "sh_gpg.h"
54#include "sh_unix.h"
55#include "sh_files.h"
56#include "sh_ignore.h"
57#include "sh_pthread.h"
58
59#if defined(SH_WITH_CLIENT)
60#include "sh_xfer.h"
61#endif
62
63
64#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
65
66
67#undef FIL__
68#define FIL__ _("sh_hash.c")
69
70SH_MUTEX_INIT(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
71
72static char * all_items (file_type * theFile, char * fileHash, int is_new);
73
74static const char *policy[] = {
75 N_("[]"),
76 N_("[ReadOnly]"),
77 N_("[LogFiles]"),
78 N_("[GrowingLogs]"),
79 N_("[IgnoreNone]"),
80 N_("[IgnoreAll]"),
81 N_("[Attributes]"),
82 N_("[User0]"),
83 N_("[User1]"),
84 N_("[User2]"),
85 N_("[User3]"),
86 N_("[User4]"),
87 N_("[Prelink]"),
88 NULL
89};
90
91static int report_checkflags = S_FALSE;
92int set_report_checkflags(const char * c)
93{
94 return sh_util_flagval(c, &report_checkflags);
95}
96int get_report_checkflags()
97{
98 return report_checkflags;
99}
100
101
102
103const char * sh_hash_getpolicy(int class)
104{
105 if (class > 0 && class < SH_ERR_T_DIR)
106 return _(policy[class]);
107 return _("[indef]");
108}
109
110/**********************************
111 *
112 * hash table functions
113 *
114 **********************************
115 */
116
117#include "sh_hash.h"
118
119
120/**************************************************************
121 *
122 * create a file_type from a sh_file_t
123 *
124 **************************************************************/
125file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
126{
127 file_type * theFile;
128
129 SL_ENTER(_("sh_hash_create_ft"));
130
131 theFile = SH_ALLOC(sizeof(file_type));
132
133 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
134 theFile->mode = p->theFile.mode;
135#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
136 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
137 theFile->attributes = p->theFile.attributes;
138#endif
139
140 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
141 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
142 {
143 theFile->link_path = sh_util_strdup(p->linkpath);
144 }
145 else
146 {
147 theFile->link_path = NULL;
148 }
149 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
150
151 theFile->mtime = p->theFile.mtime;
152 theFile->ctime = p->theFile.ctime;
153 theFile->atime = p->theFile.atime;
154
155 theFile->size = p->theFile.size;
156
157 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
158 theFile->group = p->theFile.group;
159 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
160 theFile->owner = p->theFile.owner;
161
162 theFile->ino = p->theFile.ino;
163 theFile->rdev = p->theFile.rdev;
164 theFile->dev = p->theFile.dev;
165 theFile->hardlinks = p->theFile.hardlinks;
166 theFile->check_flags = p->theFile.checkflags;
167
168 if (p->attr_string)
169 theFile->attr_string = sh_util_strdup(p->attr_string);
170 else
171 theFile->attr_string = NULL;
172
173 SL_RETURN((theFile), _("sh_hash_create_ft"));
174}
175
176struct two_sh_file_t {
177 sh_file_t * prev;
178 sh_file_t * this;
179};
180
181static sh_file_t * hashsearch (const char * s);
182static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index);
183
184
185/**************************************************************
186 *
187 * >>>> The internal database <<<
188 *
189 **************************************************************/
190
191static sh_file_t * tab[TABSIZE];
192
193sh_file_t ** get_default_data_table()
194{
195 return tab;
196}
197
198/**************************************************************
199 *
200 * compute hash function
201 *
202 **************************************************************/
203
204static int hashfunc(const char *s)
205{
206 unsigned int n = 0;
207
208 for ( ; *s; s++)
209 n = 31 * n + *s;
210
211 return n & (TABSIZE - 1); /* % TABSIZE */;
212}
213
214
215int hashreport_missing( char *fullpath, int level)
216{
217 sh_file_t * p;
218 char * tmp;
219 char fileHash[KEY_LEN + 1];
220 file_type * theFile;
221 char * str;
222 char hashbuf[KEYBUF_SIZE];
223 volatile int retval;
224
225 /* -------- find the entry for the file ---------------- */
226
227 SH_MUTEX_LOCK(mutex_hash);
228
229 retval = 0;
230
231 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
232 p = hashsearch(fullpath);
233 else
234 p = hashsearch( sh_tiger_hash(fullpath,
235 TIGER_DATA,
236 sl_strlen(fullpath),
237 hashbuf, sizeof(hashbuf))
238 );
239 if (p == NULL)
240 {
241 retval = -1;
242 goto unlock_and_return;
243 }
244
245 theFile = sh_hash_create_ft (p, fileHash);
246 str = all_items(theFile, fileHash, 0);
247 tmp = sh_util_safe_name(fullpath);
248
249 SH_MUTEX_LOCK(mutex_thread_nolog);
250 if (!sh_global_check_silent)
251 sh_error_handle (level, FIL__, __LINE__, 0,
252 MSG_FI_MISS2, tmp, str);
253 SH_MUTEX_UNLOCK(mutex_thread_nolog);
254 ++sh.statistics.files_report;
255
256 SH_FREE(tmp);
257 SH_FREE(str);
258 if (theFile->attr_string) SH_FREE(theFile->attr_string);
259 if (theFile->link_path) SH_FREE(theFile->link_path);
260 SH_FREE(theFile);
261
262 unlock_and_return:
263 ; /* 'label at end of compound statement */
264 SH_MUTEX_UNLOCK(mutex_hash);
265
266 /* remove here to avoid second message from hash_unvisited */
267 if (retval == 0)
268 sh_hash_remove (fullpath);
269
270 return retval;
271}
272
273
274/**************************************************************
275 *
276 * search for files not visited, and check whether they exist
277 *
278 **************************************************************/
279static sh_file_t * delete_db_entry(sh_file_t *p)
280{
281 if (p->fullpath)
282 {
283 SH_FREE(p->fullpath);
284 p->fullpath = NULL;
285 }
286 if (p->linkpath)
287 {
288 SH_FREE(p->linkpath);
289 p->linkpath = NULL;
290 }
291 if (p->attr_string)
292 {
293 SH_FREE(p->attr_string);
294 p->attr_string = NULL;
295 }
296 SH_FREE(p);
297 return NULL;
298}
299
300static void hash_unvisited (int j,
301 sh_file_t *prev, sh_file_t *p, ShErrLevel level)
302{
303 struct stat buf;
304 int i;
305 char * tmp;
306 char * ptr;
307 char fileHash[KEY_LEN + 1];
308 file_type * theFile;
309 char * str;
310
311 SL_ENTER(_("hash_unvisited"));
312
313 if (p->next != NULL)
314 hash_unvisited (j, p, p->next, level);
315
316 if (p->fullpath == NULL)
317 {
318 SL_RET0(_("hash_unvisited"));
319 }
320
321 /* Not a fully qualified path, i.e. some info stored by some module
322 */
323 if (p->fullpath[0] != '/')
324 {
325 SL_RET0(_("hash_unvisited"));
326 }
327
328 /* visited flag not set: not seen;
329 * checked flag set: not seen (i.e. missing), and already checked
330 * reported flag not set: not reported yet
331 * allignore flag not set: not under IgnoreAll
332 *
333 * Files/directories under IgnoreAll are noticed as missing already
334 * during the file check.
335 */
336 if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags))
337 && (!SH_FFLAG_REPORTED_SET(p->fflags))
338 /* && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)) */)
339 {
340 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
341
342 /* if file does not exist
343 */
344 if (0 != i)
345 {
346 ptr = sh_util_dirname (p->fullpath);
347 if (ptr)
348 {
349 /* If any of the parent directories is under IgnoreAll
350 */
351 if ((0 != sh_files_is_allignore(ptr)) || SH_FFLAG_ALLIGNORE_SET(p->fflags))
352 level = ShDFLevel[SH_LEVEL_ALLIGNORE];
353 SH_FREE(ptr);
354 }
355
356 /* Only report if !SH_FFLAG_CHECKED_SET
357 */
358 if (!SH_FFLAG_CHECKED_SET(p->fflags))
359 {
360 if (S_FALSE == sh_ignore_chk_del(p->fullpath))
361 {
362 tmp = sh_util_safe_name(p->fullpath);
363
364 theFile = sh_hash_create_ft (p, fileHash);
365 str = all_items(theFile, fileHash, 0);
366 if (!sh_global_check_silent)
367 sh_error_handle (level, FIL__, __LINE__, 0,
368 MSG_FI_MISS2, tmp, str);
369 ++sh.statistics.files_report;
370 SH_FREE(str);
371 if (theFile->attr_string) SH_FREE(theFile->attr_string);
372 if (theFile->link_path) SH_FREE(theFile->link_path);
373 SH_FREE(theFile);
374
375 SH_FREE(tmp);
376 }
377 }
378
379 /* We rewrite the db on update, thus we need to keep this
380 * if the user does not want to purge it from the db.
381 */
382
383 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
384 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
385 {
386 /* Remove the old entry
387 */
388 if (prev == p)
389 tab[j] = p->next;
390 else
391 prev->next = p->next;
392
393 delete_db_entry(p);
394
395 SL_RET0(_("hash_unvisited"));
396 }
397 }
398 }
399
400 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
401 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
402 {
403 if (S_FALSE == sh_ignore_chk_new(p->fullpath))
404 {
405 tmp = sh_util_safe_name(p->fullpath);
406
407 theFile = sh_hash_create_ft (p, fileHash);
408 str = all_items(theFile, fileHash, 0);
409 if (!sh_global_check_silent)
410 sh_error_handle (level, FIL__, __LINE__, 0,
411 MSG_FI_MISS2, tmp, str);
412 ++sh.statistics.files_report;
413 SH_FREE(str);
414 if (theFile->attr_string)
415 SH_FREE(theFile->attr_string);
416 SH_FREE(theFile);
417
418 SH_FREE(tmp);
419 }
420
421 CLEAR_SH_FFLAG_REPORTED(p->fflags);
422 }
423
424 if (sh.flag.reportonce == S_FALSE)
425 CLEAR_SH_FFLAG_REPORTED(p->fflags);
426
427 CLEAR_SH_FFLAG_VISITED(p->fflags);
428 CLEAR_SH_FFLAG_CHECKED(p->fflags);
429 SET_SH_FFLAG_ENOENT(p->fflags);
430
431 SL_RET0(_("hash_unvisited"));
432}
433
434
435
436/*********************************************************************
437 *
438 * Search for files in the database that have been deleted from disk.
439 *
440 *********************************************************************/
441void sh_hash_unvisited (ShErrLevel level)
442{
443 int i;
444
445 SL_ENTER(_("sh_hash_unvisited"));
446
447 SH_MUTEX_LOCK(mutex_hash);
448 for (i = 0; i < TABSIZE; ++i)
449 {
450 if (tab[i] != NULL)
451 hash_unvisited (i, tab[i], tab[i], level);
452 }
453 SH_MUTEX_UNLOCK(mutex_hash);
454
455 SL_RET0(_("hash_unvisited"));
456}
457
458/*********************************************************************
459 *
460 * Remove a single file from the database.
461 *
462 *********************************************************************/
463void sh_hash_remove_unconditional (const char * path)
464{
465 struct two_sh_file_t entries;
466 int index;
467
468 SL_ENTER(_("sh_hash_remove_unconditional"));
469
470 SH_MUTEX_LOCK(mutex_hash);
471 if (0 == hashsearch_prev (path, &entries, &index))
472 {
473 sh_file_t * p = entries.this;
474
475 /* Remove the old entry
476 */
477 if (entries.prev == p)
478 tab[index] = p->next;
479 else
480 entries.prev->next = p->next;
481
482 delete_db_entry(p);
483 }
484 SH_MUTEX_UNLOCK(mutex_hash);
485
486 SL_RET0(_("sh_hash_remove_unconditional"));
487}
488
489void sh_hash_remove (const char * path)
490{
491 SL_ENTER(_("sh_hash_remove"));
492
493 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
494 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
495 {
496 sh_hash_remove_unconditional (path);
497 }
498 SL_RET0(_("sh_hash_remove"));
499}
500
501
502/*********************************************************************
503 *
504 * Search for unvisited entries in the database, custom error handler.
505 *
506 *********************************************************************/
507void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key))
508{
509 int i;
510 sh_file_t *p = NULL;
511 sh_file_t *prev = NULL;
512 sh_file_t *next = NULL;
513
514 SL_ENTER(_("sh_hash_unvisited_custom"));
515
516 SH_MUTEX_LOCK(mutex_hash);
517 for (i = 0; i < TABSIZE; ++i)
518 {
519 if (tab[i] != NULL)
520 {
521 p = tab[i]; prev = p;
522
523 do
524 {
525 next = p->next;
526
527 if (p->fullpath &&
528 prefix == p->fullpath[0])
529 {
530 if ((!SH_FFLAG_VISITED_SET(p->fflags))
531 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
532 {
533 handler(p->fullpath);
534
535 if (!SH_FFLAG_CHECKED_SET(p->fflags))
536 {
537 /* delete */
538 if (tab[i] == p)
539 {
540 tab[i] = p->next;
541 prev = tab[i];
542 next = prev;
543 }
544 else
545 {
546 prev->next = p->next;
547 next = prev->next;
548 }
549
550 p = delete_db_entry(p);
551 }
552 }
553 if (p)
554 {
555 CLEAR_SH_FFLAG_VISITED(p->fflags);
556 CLEAR_SH_FFLAG_CHECKED(p->fflags);
557 }
558 }
559 if (p)
560 prev = p;
561 p = next;
562 }
563 while (p);
564 }
565 }
566 SH_MUTEX_UNLOCK(mutex_hash);
567
568 SL_RET0(_("hash_unvisited_custom"));
569}
570
571
572/**********************************************************************
573 *
574 * delete hash array
575 *
576 **********************************************************************/
577static void hash_kill (sh_file_t *p)
578{
579 SL_ENTER(_("hash_kill"));
580
581 if (p == NULL)
582 SL_RET0(_("hash_kill"));
583
584 if (p->next != NULL)
585 hash_kill (p->next);
586
587 if (p->fullpath)
588 {
589 SH_FREE(p->fullpath);
590 p->fullpath = NULL;
591 }
592 if (p->linkpath)
593 {
594 SH_FREE(p->linkpath);
595 p->linkpath = NULL;
596 }
597 if (p->attr_string)
598 {
599 SH_FREE(p->attr_string);
600 p->attr_string = NULL;
601 }
602 SH_FREE(p);
603 p = NULL;
604 SL_RET0(_("hash_kill"));
605}
606
607
608/***********************************************************************
609 *
610 * get info out of hash array
611 *
612 ***********************************************************************/
613static sh_file_t * hashsearch (const char * s)
614{
615 sh_file_t * p;
616
617 SL_ENTER(_("hashsearch"));
618
619 if (s)
620 {
621 for (p = tab[hashfunc(s)]; p; p = p->next)
622 if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath)))
623 SL_RETURN( p, _("hashsearch"));
624 }
625 SL_RETURN( NULL, _("hashsearch"));
626}
627
628static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index)
629{
630 sh_file_t * this;
631 sh_file_t * prev = NULL;
632
633 SL_ENTER(_("hashsearch_prev"));
634
635 if (s)
636 {
637 *index = hashfunc(s);
638 this = tab[*index];
639 prev = this;
640
641 if (this)
642 {
643 do {
644 if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
645 {
646 a->prev = prev;
647 a->this = this;
648 SL_RETURN( 0, _("hashsearch_prev"));
649 }
650 prev = this;
651 this = this->next;
652 } while(this);
653 }
654 }
655 SL_RETURN( -1, _("hashsearch"));
656}
657
658
659/***********************************************************************
660 *
661 * insert into hash array
662 *
663 ***********************************************************************/
664void hashinsert (sh_file_t * mtab[TABSIZE], sh_file_t * s)
665{
666 sh_file_t * p;
667 sh_file_t * q;
668 int key;
669
670 SL_ENTER(_("hashinsert"));
671
672 key = hashfunc(s->fullpath);
673
674 if (mtab[key] == NULL)
675 {
676 mtab[key] = s;
677 mtab[key]->next = NULL;
678 SL_RET0(_("hashinsert"));
679 }
680 else
681 {
682 p = mtab[key];
683 while (1)
684 {
685 if (p && p->fullpath && 0 == strcmp(s->fullpath, p->fullpath))
686 {
687 q = p->next;
688 SH_FREE(p->fullpath);
689 if(p->linkpath) SH_FREE(p->linkpath);
690 if(p->attr_string) SH_FREE(p->attr_string);
691 memcpy(p, s, sizeof(sh_file_t));
692 p->next = q;
693 SH_FREE(s); s = NULL;
694 SL_RET0(_("hashinsert"));
695 }
696 else if (p && p->next == NULL)
697 {
698 p->next = s;
699 p->next->next = NULL;
700 SL_RET0(_("hashinsert"));
701 }
702 if (p)
703 p = p->next;
704 else /* cannot really happen, but llvm/clang does not know */
705 break;
706 }
707 }
708 /* notreached */
709}
710
711
712
713/******************************************************************
714 *
715 * ------- Check functions -------
716 *
717 ******************************************************************/
718
719static int IsInit = 0;
720
721void sh_hash_set_initialized()
722{
723 IsInit = 1;
724 return;
725}
726
727int sh_hash_get_initialized()
728{
729 return IsInit;
730}
731
732
733/******************************************************************
734 *
735 * Initialize
736 *
737 ******************************************************************/
738void sh_hash_init ()
739{
740 volatile int retval = 0;
741 volatile int exitval = EXIT_SUCCESS;
742
743 SL_ENTER(_("sh_hash_init"));
744
745 if ( sh.flag.checkSum == SH_CHECK_INIT )
746 {
747 dlog(1, FIL__, __LINE__,
748 _("Attempt to load the baseline database during initialisation. This is an internal error, please report it to the developer.\n"));
749 SH_ABORT;
750 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
751 }
752
753 SH_MUTEX_LOCK(mutex_hash);
754
755 if (IsInit == 1)
756 {
757 goto unlock_and_return;
758 }
759
760 /* Initialization completed.
761 */
762 retval = sh_dbIO_load_db(tab);
763
764 if (0 == retval)
765 IsInit = 1;
766 else
767 exitval = EXIT_FAILURE;
768
769 unlock_and_return:
770 ; /* 'label at end of compound statement */
771 SH_MUTEX_UNLOCK(mutex_hash);
772 if (retval == 0)
773 {
774 SL_RET0(_("sh_hash_init"));
775 }
776 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
777 aud_exit (FIL__, __LINE__, exitval);
778}
779
780void sh_hash_init_and_checksum()
781{
782 TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
783 if (sh.flag.checkSum == SH_CHECK_CHECK)
784 {
785 if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
786 {
787 char hashbuf[KEYBUF_SIZE];
788 (void) sl_strlcpy(sh.data.hash,
789 sh_tiger_hash (file_path('D', 'R'),
790 TIGER_FILE, TIGER_NOLIM,
791 hashbuf, sizeof(hashbuf)),
792 KEY_LEN+1);
793 }
794
795 /* this eventually fetches the file from server to get checksum
796 */
797 sh_hash_init ();
798 }
799 return;
800}
801
802/*****************************************************************
803 *
804 * delete hash array
805 *
806 *****************************************************************/
807void sh_hash_hashdelete ()
808{
809 int i;
810
811 SL_ENTER(_("sh_hash_hashdelete"));
812
813 /* need deadlock detection here if called from exit handler
814 */
815 SH_MUTEX_TRYLOCK(mutex_hash);
816
817 if (IsInit == 0)
818 goto unlock_and_exit;
819
820 for (i = 0; i < TABSIZE; ++i)
821 if (tab[i] != NULL)
822 {
823 hash_kill (tab[i]);
824 tab[i] = NULL;
825 }
826 IsInit = 0;
827
828 unlock_and_exit:
829 ; /* 'label at end of compound statement */
830 SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash);
831
832 SL_RET0(_("sh_hash_hashdelete"));
833}
834
835static int sh_loosedircheck = S_FALSE;
836
837int sh_hash_loosedircheck(const char * str)
838{
839 return sh_util_flagval(str, &sh_loosedircheck);
840}
841
842
843
844
845/*********************************************************************
846 *
847 * Check whether a file is present in the database.
848 *
849 *********************************************************************/
850static sh_file_t * sh_hash_have_it_int (const char * newname)
851{
852 sh_file_t * p;
853 char hashbuf[KEYBUF_SIZE];
854
855 SL_ENTER(_("sh_hash_have_it_int"));
856
857 if (newname == NULL)
858 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
859
860 if (sl_strlen(newname) <= MAX_PATH_STORE)
861 p = hashsearch(newname);
862 else
863 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
864 hashbuf, sizeof(hashbuf)) );
865 if (p == NULL)
866 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
867
868 SL_RETURN( (p), _("sh_hash_have_it_int"));
869}
870
871int sh_hash_have_it (const char * newname)
872{
873 sh_file_t * p;
874 int retval;
875
876 if (IsInit != 1)
877 sh_hash_init();
878
879 SH_MUTEX_LOCK(mutex_hash);
880
881 retval = 0;
882
883 p = sh_hash_have_it_int (newname);
884
885 if (!p)
886 retval = (-1);
887 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
888 (p->modi_mask & MODI_CHK) != 0 &&
889 (p->modi_mask & MODI_MOD) != 0)
890 retval = 1;
891 SH_MUTEX_UNLOCK(mutex_hash);
892
893 return retval;
894}
895
896int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash)
897{
898 sh_file_t * p;
899 int retval;
900
901 if (IsInit != 1)
902 sh_hash_init();
903
904 tmpFile->link_path = NULL;
905 tmpFile->attr_string = NULL;
906
907 SH_MUTEX_LOCK(mutex_hash);
908
909 retval = (-1);
910
911 p = sh_hash_have_it_int (newname);
912 if (p)
913 {
914 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
915 if (p->linkpath)
916 tmpFile->link_path = sh_util_strdup (p->linkpath);
917 tmpFile->size = p->theFile.size;
918 tmpFile->mtime = p->theFile.mtime;
919 tmpFile->ctime = p->theFile.ctime;
920 tmpFile->atime = p->theFile.atime;
921
922 if (NULL != fileHash)
923 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
924
925 tmpFile->attr_string = NULL;
926 retval = 0;
927 }
928 SH_MUTEX_UNLOCK(mutex_hash);
929
930 return retval;
931}
932
933int sh_hash_getflags (char * filename)
934{
935 sh_file_t * p;
936 int retval = 0;
937
938 if ( sh.flag.checkSum != SH_CHECK_INIT )
939 {
940 if (IsInit != 1)
941 sh_hash_init();
942
943 SH_MUTEX_LOCK(mutex_hash);
944 p = sh_hash_have_it_int (filename);
945 if (p)
946 retval = p->fflags;
947 else
948 retval = -1;
949 SH_MUTEX_UNLOCK(mutex_hash);
950 }
951 return retval;
952}
953
954int sh_hash_setflags (char * filename, int flags)
955{
956 sh_file_t * p;
957 int retval = 0;
958
959 if ( sh.flag.checkSum != SH_CHECK_INIT )
960 {
961 if (IsInit != 1)
962 sh_hash_init();
963
964 SH_MUTEX_LOCK(mutex_hash);
965 p = sh_hash_have_it_int (filename);
966 if (p)
967 {
968 p->fflags = flags;
969 retval = 0;
970 }
971 else
972 retval = -1;
973 SH_MUTEX_UNLOCK(mutex_hash);
974 }
975 return retval;
976}
977
978/* needs lock to be threadsafe
979 */
980void sh_hash_set_flag (char * filename, int flag_to_set)
981{
982 sh_file_t * p;
983
984 if ( sh.flag.checkSum != SH_CHECK_INIT )
985 {
986 if (IsInit != 1)
987 sh_hash_init();
988
989 SH_MUTEX_LOCK(mutex_hash);
990 p = sh_hash_have_it_int (filename);
991 if (p)
992 {
993 p->fflags |= flag_to_set;
994 }
995 SH_MUTEX_UNLOCK(mutex_hash);
996 }
997 return;
998}
999
1000/* needs lock to be threadsafe
1001 */
1002void sh_hash_clear_flag (char * filename, int flag_to_clear)
1003{
1004 sh_file_t * p;
1005
1006 if ( sh.flag.checkSum != SH_CHECK_INIT )
1007 {
1008 if (IsInit != 1)
1009 sh_hash_init();
1010
1011 SH_MUTEX_LOCK(mutex_hash);
1012 p = sh_hash_have_it_int (filename);
1013 if (p)
1014 {
1015 p->fflags &= ~flag_to_clear;
1016 }
1017 SH_MUTEX_UNLOCK(mutex_hash);
1018 }
1019 return;
1020}
1021
1022
1023/*****************************************************************
1024 *
1025 * Set a file's status to 'visited'. This is required for
1026 * files that should be ignored, and may be present in the
1027 * database, but not on disk.
1028 *
1029 *****************************************************************/
1030static int sh_hash_set_visited_int (char * newname, int flag)
1031{
1032 sh_file_t * p;
1033 char hashbuf[KEYBUF_SIZE];
1034 int retval;
1035
1036 SL_ENTER(_("sh_hash_set_visited_int"));
1037
1038 if (newname == NULL)
1039 SL_RETURN((-1), _("sh_hash_set_visited_int"));
1040
1041 if (IsInit != 1)
1042 sh_hash_init();
1043
1044 SH_MUTEX_LOCK(mutex_hash);
1045
1046 if (sl_strlen(newname) <= MAX_PATH_STORE)
1047 p = hashsearch(newname);
1048 else
1049 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1050 hashbuf, sizeof(hashbuf)));
1051
1052 if (p)
1053 {
1054 if (flag == SH_FFLAG_CHECKED)
1055 {
1056 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1057 CLEAR_SH_FFLAG_VISITED(p->fflags);
1058 SET_SH_FFLAG_CHECKED(p->fflags);
1059 }
1060 else
1061 {
1062 SET_SH_FFLAG_VISITED(p->fflags);
1063 CLEAR_SH_FFLAG_CHECKED(p->fflags);
1064 if (flag == SH_FFLAG_REPORTED)
1065 SET_SH_FFLAG_REPORTED(p->fflags);
1066 else
1067 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1068 }
1069 retval = 0;
1070 }
1071 else
1072 retval = -1;
1073
1074 SH_MUTEX_UNLOCK(mutex_hash);
1075 SL_RETURN((retval), _("sh_hash_set_visited_int"));
1076}
1077
1078
1079/* cause the record to be deleted without a 'missing' message
1080 */
1081int sh_hash_set_missing (char * newname)
1082{
1083 int i;
1084 SL_ENTER(_("sh_hash_set_missing"));
1085
1086 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
1087
1088 if (sh.flag.checkSum != SH_CHECK_INIT) {
1089 sh_hash_remove(newname);
1090 }
1091
1092 SL_RETURN(i, _("sh_hash_set_missing"));
1093}
1094
1095/* mark the file as visited and reported
1096 */
1097int sh_hash_set_visited (char * newname)
1098{
1099 int i;
1100 SL_ENTER(_("sh_hash_set_visited"));
1101 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
1102 SL_RETURN(i, _("sh_hash_set_visited"));
1103}
1104
1105/* mark the file as visited and NOT reported
1106 * used to avoid deletion of file from internal database
1107 */
1108int sh_hash_set_visited_true (char * newname)
1109{
1110 int i;
1111 SL_ENTER(_("sh_hash_set_visited_true"));
1112 i = sh_hash_set_visited_int(newname, 0);
1113 SL_RETURN(i, _("sh_hash_set_visited_true"));
1114}
1115
1116
1117/******************************************************************
1118 *
1119 * Data entry for arbitrary data into database
1120 *
1121 ******************************************************************/
1122
1123void sh_hash_push2db (const char * key, struct store2db * save)
1124{
1125 int i = 0;
1126 char * p;
1127 char i2h[2];
1128 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
1129
1130 int size = save->size;
1131 unsigned char * str = save->str;
1132
1133
1134 tmpFile->attr_string = NULL;
1135 tmpFile->link_path = NULL;
1136
1137 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
1138 tmpFile->size = save->val0;
1139 tmpFile->mtime = save->val1;
1140 tmpFile->ctime = save->val2;
1141 tmpFile->atime = save->val3;
1142
1143 tmpFile->mode = 0;
1144 tmpFile->owner = 0;
1145 tmpFile->group = 0;
1146 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
1147 sl_strlcpy(tmpFile->c_group, _("root"), 5);
1148
1149 tmpFile->check_flags = 0;
1150
1151 if ((str != NULL) && (size < (PATH_MAX/2)-1))
1152 {
1153 tmpFile->c_mode[0] = 'l';
1154 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
1155 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
1156 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
1157 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
1158 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
1159 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
1160 for (i = 0; i < size; ++i)
1161 {
1162 p = sh_util_charhex (str[i],i2h);
1163 tmpFile->link_path[2*i] = p[0];
1164 tmpFile->link_path[2*i+1] = p[1];
1165 tmpFile->link_path[2*i+2] = '\0';
1166 }
1167 }
1168 else
1169 {
1170 for (i = 0; i < 10; ++i)
1171 tmpFile->c_mode[i] = '-';
1172 tmpFile->c_mode[10] = '\0';
1173 tmpFile->link_path = sh_util_strdup("-");
1174 }
1175
1176 if (sh.flag.checkSum == SH_CHECK_INIT)
1177 sh_dbIO_data_write (tmpFile,
1178 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
1179 else
1180 sh_hash_pushdata_memory (tmpFile,
1181 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
1182
1183 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1184 SH_FREE(tmpFile);
1185 return;
1186}
1187
1188extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
1189
1190char * sh_hash_db2pop (const char * key, struct store2db * save)
1191{
1192 size_t len;
1193 char * p;
1194 int i;
1195 char * retval = NULL;
1196 char fileHash[KEY_LEN+1];
1197 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
1198
1199 save->size = 0;
1200
1201 if (0 == sh_hash_get_it (key, tmpFile, fileHash))
1202 {
1203 save->val0 = tmpFile->size;
1204 save->val1 = tmpFile->mtime;
1205 save->val2 = tmpFile->ctime;
1206 save->val3 = tmpFile->atime;
1207
1208 sl_strlcpy(save->checksum, fileHash, KEY_LEN+1);
1209
1210 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
1211 {
1212 len = strlen(tmpFile->link_path);
1213
1214 p = SH_ALLOC((len/2)+1);
1215 i = sh_util_hextobinary (p, tmpFile->link_path, len);
1216
1217 if (i == 0)
1218 {
1219 save->size = (len/2);
1220 p[save->size] = '\0';
1221 retval = p;
1222 }
1223 else
1224 {
1225 SH_FREE(p);
1226 save->size = 0;
1227 }
1228 }
1229 else
1230 {
1231 save->size = 0;
1232 }
1233 }
1234 else
1235 {
1236 save->size = -1;
1237 save->val0 = 0;
1238 save->val1 = 0;
1239 save->val2 = 0;
1240 save->val3 = 0;
1241 }
1242 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1243 SH_FREE(tmpFile);
1244 return retval;
1245}
1246
1247
1248
1249
1250/******************************************************************
1251 *
1252 * Data entry in hash table
1253 *
1254 ******************************************************************/
1255sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
1256{
1257 sh_file_t * fp;
1258 sh_filestore_t p;
1259
1260 size_t len;
1261 char * fullpath;
1262 char * linkpath;
1263 char * attr_string = NULL;
1264 char hashbuf[KEYBUF_SIZE];
1265
1266 SL_ENTER(_("sh_hash_push_int"));
1267
1268 fp = SH_ALLOC(sizeof(sh_file_t));
1269
1270 p.mark = REC_MAGIC;
1271 if (buf->attr_string)
1272 p.mark |= REC_FLAGS_ATTR;
1273 sl_strlcpy(p.c_mode, buf->c_mode, 11);
1274 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1275 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1276 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1277#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1278 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
1279#endif
1280
1281#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1282 p.attributes = (UINT32) buf->attributes;
1283#endif
1284 p.linkmode = (UINT32) buf->linkmode;
1285 p.hardlinks = (UINT32) buf->hardlinks;
1286 p.dev = (UINT64) buf->dev;
1287 p.rdev = (UINT64) buf->rdev;
1288 p.mode = (UINT32) buf->mode;
1289 p.ino = (UINT32) buf->ino;
1290 p.size = (UINT64) buf->size;
1291 p.mtime = (UINT64) buf->mtime;
1292 p.atime = (UINT64) buf->atime;
1293 p.ctime = (UINT64) buf->ctime;
1294 p.owner = (UINT32) buf->owner;
1295 p.group = (UINT32) buf->group;
1296
1297 p.checkflags = (UINT32) buf->check_flags;
1298
1299 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
1300 fp->fflags = 0; /* init fflags */
1301 fp->modi_mask = 0L;
1302
1303 if (buf->attr_string)
1304 attr_string = sh_util_strdup(buf->attr_string);
1305 fp->attr_string = attr_string;
1306
1307 len = sl_strlen(buf->fullpath);
1308 if (len <= MAX_PATH_STORE)
1309 {
1310 fullpath = SH_ALLOC(len+1);
1311 sl_strlcpy(fullpath, buf->fullpath, len+1);
1312 }
1313 else
1314 {
1315 fullpath = SH_ALLOC(KEY_LEN + 1);
1316 sl_strlcpy(fullpath,
1317 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
1318 hashbuf, sizeof(hashbuf)),
1319 KEY_LEN+1);
1320 }
1321 fp->fullpath = fullpath;
1322
1323 if (buf->link_path)
1324 {
1325 len = sl_strlen(buf->link_path);
1326 if (len <= MAX_PATH_STORE)
1327 {
1328 linkpath = SH_ALLOC(len+1);
1329 sl_strlcpy(linkpath, buf->link_path, len+1);
1330 }
1331 else
1332 {
1333 linkpath = SH_ALLOC(KEY_LEN + 1);
1334 sl_strlcpy(linkpath,
1335 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
1336 hashbuf, sizeof(hashbuf)),
1337 KEY_LEN+1);
1338 }
1339 fp->linkpath = linkpath;
1340 }
1341 else
1342 fp->linkpath = NULL;
1343
1344 SL_RETURN( fp, _("sh_hash_push_int"));
1345}
1346
1347#ifdef HAVE_INTTYPES_H
1348#include <inttypes.h>
1349#else
1350#ifdef HAVE_STDINT_H
1351#include <stdint.h>
1352#endif
1353#endif
1354
1355#ifndef PRIu64
1356#ifdef HAVE_LONG_32
1357#define PRIu64 "llu"
1358#else
1359#define PRIu64 "lu"
1360#endif
1361#endif
1362
1363char * sh_hash_size_format()
1364{
1365 static char form_rval[81];
1366
1367 SL_ENTER(_("sh_hash_size_format"));
1368
1369
1370#ifdef SH_USE_XML
1371 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
1372 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
1373#else
1374 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
1375 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
1376#endif
1377
1378 SL_RETURN( form_rval, _("sh_hash_size_format"));
1379}
1380
1381
1382#ifdef SH_USE_XML
1383static char * all_items (file_type * theFile, char * fileHash, int is_new)
1384{
1385 char timstr1c[32];
1386 char timstr1a[32];
1387 char timstr1m[32];
1388
1389 char * tmp_lnk;
1390 char * format;
1391
1392 char * tmp = SH_ALLOC(SH_MSG_BUF);
1393 char * msg = SH_ALLOC(SH_MSG_BUF);
1394
1395 tmp[0] = '\0';
1396 msg[0] = '\0';
1397
1398 if (report_checkflags != S_FALSE)
1399 {
1400 if (is_new)
1401 format = _("checkflags_new=\"0%lo\" ");
1402 else
1403 format = _("checkflags_old=\"0%lo\" ");
1404 sl_snprintf(tmp, SH_MSG_BUF, format,
1405 (unsigned long) theFile->check_flags);
1406 sl_strlcat(msg, tmp, SH_MSG_BUF);
1407 }
1408
1409#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1410 if (is_new)
1411 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
1412 else
1413 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
1414 sl_snprintf(tmp, SH_MSG_BUF, format,
1415 theFile->c_mode,
1416 theFile->c_attributes,
1417 (long) theFile->mode,
1418 (long) theFile->attributes
1419 );
1420#else
1421 if (is_new)
1422 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
1423 else
1424 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
1425
1426 sl_snprintf(tmp, SH_MSG_BUF, format,
1427 theFile->c_mode,
1428 (long) theFile->mode
1429 );
1430#endif
1431 sl_strlcat(msg, tmp, SH_MSG_BUF);
1432
1433 if (is_new)
1434 format = _("hardlinks_new=\"%lu\" ");
1435 else
1436 format = _("hardlinks_old=\"%lu\" ");
1437 sl_snprintf(tmp, SH_MSG_BUF, format,
1438 (unsigned long) theFile->hardlinks);
1439 sl_strlcat(msg, tmp, SH_MSG_BUF);
1440
1441
1442 if (is_new)
1443 format = _("idevice_new=\"%lu\" ");
1444 else
1445 format = _("idevice_old=\"%lu\" ");
1446 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1447 sl_strlcat(msg, tmp, SH_MSG_BUF);
1448
1449
1450 if (is_new)
1451 format = _("inode_new=\"%lu\" ");
1452 else
1453 format = _("inode_old=\"%lu\" ");
1454 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1455 sl_strlcat(msg, tmp, SH_MSG_BUF);
1456
1457 /*
1458 * also report device for prelude
1459 */
1460#if defined(HAVE_LIBPRELUDE)
1461 if (is_new)
1462 format = _("dev_new=\"%lu,%lu\" ");
1463 else
1464 format = _("dev_old=\"%lu,%lu\" ");
1465 sl_snprintf(tmp, SH_MSG_BUF, format,
1466 (unsigned long) major(theFile->dev),
1467 (unsigned long) minor(theFile->dev));
1468 sl_strlcat(msg, tmp, SH_MSG_BUF);
1469#endif
1470
1471
1472 if (is_new)
1473 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
1474 else
1475 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
1476 sl_snprintf(tmp, SH_MSG_BUF, format,
1477 theFile->c_owner, (long) theFile->owner);
1478 sl_strlcat(msg, tmp, SH_MSG_BUF);
1479
1480
1481 if (is_new)
1482 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
1483 else
1484 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
1485 sl_snprintf(tmp, SH_MSG_BUF, format,
1486 theFile->c_group, (long) theFile->group);
1487 sl_strlcat(msg, tmp, SH_MSG_BUF);
1488
1489
1490 if (is_new)
1491 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
1492 (UINT64) 0, (UINT64) theFile->size);
1493 else
1494 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
1495 (UINT64) theFile->size, (UINT64) 0);
1496 sl_strlcat(msg, tmp, SH_MSG_BUF);
1497
1498
1499 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
1500 if (is_new)
1501 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
1502 else
1503 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
1504 sl_strlcat(msg, tmp, SH_MSG_BUF);
1505
1506 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
1507 if (is_new)
1508 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
1509 else
1510 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
1511 sl_strlcat(msg, tmp, SH_MSG_BUF);
1512
1513 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
1514 if (is_new)
1515 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
1516 else
1517 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
1518 sl_strlcat(msg, tmp, SH_MSG_BUF);
1519
1520 if (is_new)
1521 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
1522 else
1523 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
1524 sl_strlcat(msg, tmp, SH_MSG_BUF);
1525
1526 if (theFile->c_mode[0] == 'l' ||
1527 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
1528 {
1529 tmp_lnk = sh_util_safe_name(theFile->link_path);
1530 if (tmp_lnk)
1531 {
1532 if (is_new)
1533 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
1534 else
1535 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
1536 SH_FREE(tmp_lnk);
1537 sl_strlcat(msg, tmp, SH_MSG_BUF);
1538 }
1539 }
1540
1541 if (theFile->attr_string)
1542 {
1543 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1544 if (tmp_lnk)
1545 {
1546 if (is_new)
1547 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
1548 else
1549 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
1550 SH_FREE(tmp_lnk);
1551 sl_strlcat(msg, tmp, SH_MSG_BUF);
1552 }
1553 }
1554
1555
1556 SH_FREE(tmp);
1557 return (msg);
1558}
1559#else
1560static char * all_items (file_type * theFile, char * fileHash, int is_new)
1561{
1562 char timstr1c[32];
1563 char timstr1a[32];
1564 char timstr1m[32];
1565
1566 char * tmp_lnk;
1567 char * format;
1568
1569 char * tmp = SH_ALLOC(SH_MSG_BUF);
1570 char * msg = SH_ALLOC(SH_MSG_BUF);
1571
1572 tmp[0] = '\0';
1573 msg[0] = '\0';
1574
1575 if (report_checkflags == S_TRUE)
1576 {
1577 if (is_new)
1578 format = _("checkflags_new=<0%lo> ");
1579 else
1580 format = _("checkflags_old=<0%lo> ");
1581 sl_snprintf(tmp, SH_MSG_BUF, format,
1582 (unsigned long) theFile->check_flags);
1583 sl_strlcat(msg, tmp, SH_MSG_BUF);
1584 }
1585
1586
1587#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1588 if (is_new)
1589 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
1590 else
1591 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
1592 sl_snprintf(tmp, SH_MSG_BUF, format,
1593 theFile->c_mode,
1594 theFile->c_attributes,
1595 (long) theFile->mode,
1596 (long) theFile->attributes
1597 );
1598#else
1599 if (is_new)
1600 format = _("mode_new=<%s>, imode_new=<%ld>, ");
1601 else
1602 format = _("mode_old=<%s>, imode_old=<%ld>, ");
1603
1604 sl_snprintf(tmp, SH_MSG_BUF, format,
1605 theFile->c_mode,
1606 (long) theFile->mode
1607 );
1608#endif
1609 sl_strlcat(msg, tmp, SH_MSG_BUF);
1610
1611 if (is_new)
1612 format = _("hardlinks_new=<%lu>, ");
1613 else
1614 format = _("hardlinks_old=<%lu>, ");
1615 sl_snprintf(tmp, SH_MSG_BUF, format,
1616 (unsigned long) theFile->hardlinks);
1617 sl_strlcat(msg, tmp, SH_MSG_BUF);
1618
1619
1620 if (is_new)
1621 format = _("idevice_new=<%lu>, ");
1622 else
1623 format = _("idevice_old=<%lu>, ");
1624 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1625 sl_strlcat(msg, tmp, SH_MSG_BUF);
1626
1627
1628 if (is_new)
1629 format = _("inode_new=<%lu>, ");
1630 else
1631 format = _("inode_old=<%lu>, ");
1632 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1633 sl_strlcat(msg, tmp, SH_MSG_BUF);
1634
1635
1636 /*
1637 * also report device for prelude
1638 */
1639#if defined(HAVE_LIBPRELUDE)
1640 if (is_new)
1641 format = _("dev_new=<%lu,%lu>, ");
1642 else
1643 format = _("dev_old=<%lu,%lu>, ");
1644 sl_snprintf(tmp, SH_MSG_BUF, format,
1645 (unsigned long) major(theFile->dev),
1646 (unsigned long) minor(theFile->dev));
1647 sl_strlcat(msg, tmp, SH_MSG_BUF);
1648#endif
1649
1650 if (is_new)
1651 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
1652 else
1653 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
1654 sl_snprintf(tmp, SH_MSG_BUF, format,
1655 theFile->c_owner, (long) theFile->owner);
1656 sl_strlcat(msg, tmp, SH_MSG_BUF);
1657
1658
1659 if (is_new)
1660 format = _("group_new=<%s>, igroup_new=<%ld>, ");
1661 else
1662 format = _("group_old=<%s>, igroup_old=<%ld>, ");
1663 sl_snprintf(tmp, SH_MSG_BUF, format,
1664 theFile->c_group, (long) theFile->group);
1665 sl_strlcat(msg, tmp, SH_MSG_BUF);
1666
1667
1668 if (is_new)
1669 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
1670 (UINT64) 0, (UINT64) theFile->size);
1671 else
1672 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
1673 (UINT64) theFile->size, (UINT64) 0);
1674 sl_strlcat(msg, tmp, SH_MSG_BUF);
1675
1676
1677 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
1678 if (is_new)
1679 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
1680 else
1681 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
1682 sl_strlcat(msg, tmp, SH_MSG_BUF);
1683
1684 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
1685 if (is_new)
1686 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
1687 else
1688 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
1689 sl_strlcat(msg, tmp, SH_MSG_BUF);
1690
1691 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
1692 if (is_new)
1693 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
1694 else
1695 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
1696 sl_strlcat(msg, tmp, SH_MSG_BUF);
1697
1698 if (is_new)
1699 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
1700 else
1701 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
1702 sl_strlcat(msg, tmp, SH_MSG_BUF);
1703
1704 if (theFile->c_mode[0] == 'l' ||
1705 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
1706 {
1707 tmp_lnk = sh_util_safe_name(theFile->link_path);
1708 if (tmp_lnk)
1709 {
1710 if (is_new)
1711 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
1712 else
1713 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
1714 SH_FREE(tmp_lnk);
1715 sl_strlcat(msg, tmp, SH_MSG_BUF);
1716 }
1717 }
1718
1719 if (theFile->attr_string)
1720 {
1721 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1722 if (tmp_lnk)
1723 {
1724 if (is_new)
1725 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
1726 else
1727 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
1728 SH_FREE(tmp_lnk);
1729 sl_strlcat(msg, tmp, SH_MSG_BUF);
1730 }
1731 }
1732
1733 SH_FREE(tmp);
1734 return (msg);
1735}
1736#endif
1737
1738void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
1739{
1740 sh_file_t * p;
1741
1742 SL_ENTER(_("sh_hash_pushdata_memory"));
1743
1744 p = sh_hash_push_int(theFile, fileHash);
1745 if (p)
1746 {
1747 SH_MUTEX_LOCK(mutex_hash);
1748 hashinsert (tab, p);
1749 p->modi_mask = theFile->check_flags;
1750 SH_MUTEX_UNLOCK(mutex_hash);
1751 }
1752
1753 SL_RET0(_("sh_hash_pushdata_memory"));
1754}
1755
1756int sh_hash_is_null_file(file_type * theFile)
1757{
1758 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1759 theFile->ino == 0 && theFile->ctime == 0)
1760 {
1761 return S_TRUE;
1762 }
1763 return S_FALSE;
1764}
1765
1766int sh_hash_is_null_record(sh_filestore_t * theFile)
1767{
1768 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1769 theFile->ino == 0 && theFile->ctime == 0)
1770 {
1771 return S_TRUE;
1772 }
1773 return S_FALSE;
1774}
1775
1776void sh_hash_insert_null(char * str)
1777{
1778 file_type theFile = { 0, 0, {'\0'}, 0, 0, 0, 0, 0,
1779#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1780 0, {'\0'},
1781#endif
1782 {'\0'}, 0, {'\0'}, 0, {'\0'},
1783 0, 0, 0, 0, 0, 0, 0, NULL, 0, {'\0'}, 0, NULL
1784 }; /* clang compiler bails out on standard conforming init with just {0} */
1785 char fileHash[KEY_LEN+1];
1786 char hashbuf[KEYBUF_SIZE];
1787
1788 sl_strlcpy(fileHash, SH_KEY_NULL, sizeof(fileHash));
1789 theFile.hardlinks = SH_DEADFILE;
1790
1791 if (sl_strlen(str) < PATH_MAX)
1792 sl_strlcpy(theFile.fullpath, str, PATH_MAX);
1793 else
1794 sl_strlcpy(theFile.fullpath,
1795 sh_tiger_hash(str, TIGER_DATA, sl_strlen(str),
1796 hashbuf, sizeof(hashbuf)),
1797 PATH_MAX);
1798
1799 sh_hash_pushdata_memory(&theFile, fileHash);
1800 return;
1801}
1802
1803static int handle_notfound(int log_severity, int class,
1804 file_type * theFile, char * fileHash)
1805{
1806 sh_file_t * p;
1807 int retval = 0;
1808
1809 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
1810 {
1811 char * tmp = sh_util_safe_name(theFile->fullpath);
1812 char * str;
1813
1814 sh_files_fixup_mask(class, &(theFile->check_flags));
1815 str = all_items (theFile, fileHash, 1);
1816
1817 if (!sh_global_check_silent)
1818 sh_error_handle (log_severity, FIL__, __LINE__, 0,
1819 MSG_FI_ADD2,
1820 tmp, str);
1821 ++sh.statistics.files_report;
1822 SH_FREE(str);
1823 SH_FREE(tmp);
1824 }
1825
1826 if (sh.flag.reportonce == S_TRUE)
1827 SET_SH_FFLAG_REPORTED(theFile->file_reported);
1828
1829 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
1830 {
1831 p = sh_hash_push_int(theFile, fileHash);
1832 if (p)
1833 {
1834 hashinsert (tab, p);
1835 p->modi_mask = theFile->check_flags;
1836 p->theFile.checkflags = p->modi_mask;
1837 }
1838 }
1839
1840 else if (S_TRUE == sh.flag.update)
1841 {
1842 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
1843 {
1844 p = sh_hash_push_int(theFile, fileHash);
1845 if (p)
1846 {
1847 hashinsert (tab, p);
1848 p->modi_mask = theFile->check_flags;
1849 p->theFile.checkflags = p->modi_mask;
1850 }
1851 }
1852 else
1853 retval = 1;
1854 }
1855 return retval;
1856}
1857
1858/*****************************************************************
1859 *
1860 * Compare a file with the database status.
1861 *
1862 *****************************************************************/
1863int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
1864 char * policy_override, int severity_override)
1865{
1866 char * msg;
1867 sh_file_t * p;
1868 char * tmp;
1869 char * tmp_path;
1870 char * tmp_lnk;
1871 char * tmp_lnk_old;
1872
1873 char timstr1c[32];
1874 char timstr2c[32];
1875 char timstr1a[32];
1876 char timstr2a[32];
1877 char timstr1m[32];
1878 char timstr2m[32];
1879 char linkHash[KEY_LEN+1];
1880 char * linkComp;
1881 int maxcomp;
1882 volatile int checksum_flag = 0;
1883
1884 char change_code[16];
1885 int i;
1886
1887 unsigned long modi_mask;
1888
1889 char log_policy[32];
1890 volatile int log_severity;
1891 char hashbuf[KEYBUF_SIZE];
1892 struct {
1893 unsigned long oldflags;
1894 unsigned long newflags;
1895 } cf_report;
1896
1897 int retval;
1898
1899 SL_ENTER(_("sh_hash_compdata"));
1900
1901 if (IsInit != 1) sh_hash_init();
1902
1903 if (severity_override < 0)
1904 log_severity = ShDFLevel[class];
1905 else
1906 log_severity = severity_override;
1907
1908 if (policy_override != NULL)
1909 sl_strlcpy (log_policy, policy_override, 32);
1910
1911 /* -------- find the entry for the file ---------------- */
1912
1913 SH_MUTEX_LOCK(mutex_hash);
1914
1915 modi_mask = 0;
1916 retval = 0;
1917
1918 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
1919 p = hashsearch(theFile->fullpath);
1920 else
1921 p = hashsearch( sh_tiger_hash(theFile->fullpath,
1922 TIGER_DATA,
1923 sl_strlen(theFile->fullpath),
1924 hashbuf, sizeof(hashbuf))
1925 );
1926
1927
1928 /* --------- Not found in database. ------------
1929 */
1930
1931 if (p == NULL)
1932 {
1933 retval = handle_notfound(log_severity, class, theFile, fileHash);
1934 goto unlock_and_return;
1935 }
1936
1937 /* --------- Skip if we don't want to report changes. ------------
1938 */
1939
1940 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
1941 {
1942 MODI_SET(theFile->check_flags, MODI_NOCHECK);
1943 p->modi_mask = theFile->check_flags;
1944 p->theFile.checkflags = p->modi_mask;
1945 goto unlock_and_return;
1946 }
1947
1948 cf_report.oldflags = p->theFile.checkflags;
1949 cf_report.newflags = theFile->check_flags;
1950
1951 p->modi_mask = theFile->check_flags;
1952 p->theFile.checkflags = p->modi_mask;
1953
1954 /* initialize change_code */
1955 for (i = 0; i < 15; ++i)
1956 change_code[i] = '-';
1957 change_code[15] = '\0';
1958
1959 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
1960 theFile->fullpath, fileHash, p->theFile.checksum));
1961
1962 if ( (fileHash != NULL) &&
1963 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
1964 (theFile->check_flags & MODI_CHK) != 0)
1965 {
1966 checksum_flag = 1;
1967
1968 if ((theFile->check_flags & MODI_SGROW) == 0)
1969 {
1970 modi_mask |= MODI_CHK;
1971 change_code[0] = 'C';
1972 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1973 }
1974 else
1975 {
1976 if (0 != strncmp (&fileHash[KEY_LEN + 1], p->theFile.checksum, KEY_LEN))
1977 {
1978 if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size,
1979 (UINT64) p->theFile.ino, p->theFile.checksum,
1980 p->theFile.checkflags))
1981 {
1982 modi_mask |= MODI_CHK;
1983 change_code[0] = 'C';
1984 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1985 }
1986 else
1987 {
1988 /* logfile has been rotated */
1989 p->theFile.size = theFile->size;
1990 p->theFile.ino = theFile->ino;
1991 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
1992 }
1993 }
1994 else
1995 {
1996 p->theFile.size = theFile->size;
1997 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
1998 }
1999 }
2000 }
2001
2002 if (p->theFile.c_mode[0] == 'l')
2003 {
2004 if (!(theFile->link_path) &&
2005 (theFile->check_flags & MODI_LNK) != 0)
2006 {
2007 linkComp = NULL;
2008 modi_mask |= MODI_LNK;
2009 change_code[1] = 'L';
2010 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2011 }
2012 else
2013 {
2014 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2015 {
2016 sl_strlcpy(linkHash,
2017 sh_tiger_hash(theFile->link_path,
2018 TIGER_DATA,
2019 sl_strlen(theFile->link_path),
2020 hashbuf, sizeof(hashbuf)),
2021 MAX_PATH_STORE+1);
2022 linkComp = linkHash;
2023 maxcomp = KEY_LEN;
2024 }
2025 else
2026 {
2027 linkComp = theFile->link_path;
2028 maxcomp = MAX_PATH_STORE;
2029 }
2030
2031 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
2032 (theFile->check_flags & MODI_LNK) != 0)
2033 {
2034 modi_mask |= MODI_LNK;
2035 change_code[1] = 'L';
2036 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2037 }
2038 }
2039 }
2040
2041 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2042 {
2043 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2044 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2045 (theFile->check_flags & MODI_RDEV) != 0)
2046 {
2047 modi_mask |= MODI_RDEV;
2048 change_code[2] = 'D';
2049 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2050 }
2051 }
2052
2053 /* cast to UINT32 in case ino_t is not 32bit
2054 */
2055 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2056 (theFile->check_flags & MODI_INO) != 0)
2057 {
2058 if ((theFile->check_flags & MODI_SGROW) == 0)
2059 {
2060 modi_mask |= MODI_INO;
2061 change_code[3] = 'I';
2062 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2063 }
2064 else
2065 {
2066 /* growing log, checksum ok but inode changed
2067 */
2068 if (checksum_flag == 0)
2069 {
2070 if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size,
2071 (UINT64) p->theFile.ino, p->theFile.checksum,
2072 p->theFile.checkflags))
2073 {
2074 modi_mask |= MODI_INO;
2075 change_code[3] = 'I';
2076 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2077 }
2078 else
2079 {
2080 /* logfile has been rotated */
2081 p->theFile.size = theFile->size;
2082 p->theFile.ino = theFile->ino;
2083 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2084 }
2085 }
2086 else
2087 {
2088 modi_mask |= MODI_INO;
2089 change_code[3] = 'I';
2090 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2091 }
2092 }
2093 }
2094
2095 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
2096 (theFile->check_flags & MODI_HLN) != 0)
2097 {
2098 modi_mask |= MODI_HLN;
2099 change_code[4] = 'H';
2100 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2101 }
2102
2103
2104 if ( ( (theFile->mode != p->theFile.mode)
2105#if defined(USE_ACL) || defined(USE_XATTR)
2106 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2107 (
2108 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2109 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2110 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2111 )
2112 )
2113#endif
2114#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2115 || (theFile->attributes != p->theFile.attributes)
2116#endif
2117 )
2118 && (theFile->check_flags & MODI_MOD) != 0)
2119 {
2120 modi_mask |= MODI_MOD;
2121 change_code[5] = 'M';
2122 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2123 /*
2124 * report link path if switch link/no link
2125 */
2126 if ((theFile->check_flags & MODI_LNK) != 0 &&
2127 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
2128 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
2129 {
2130 modi_mask |= MODI_LNK;
2131 change_code[1] = 'L';
2132 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2133 }
2134 }
2135
2136 if ( theFile->owner != (uid_t) p->theFile.owner &&
2137 (theFile->check_flags & MODI_USR) != 0)
2138 {
2139 modi_mask |= MODI_USR;
2140 change_code[6] = 'U';
2141 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
2142 }
2143
2144 if ( theFile->group != (gid_t) p->theFile.group &&
2145 (theFile->check_flags & MODI_GRP) != 0)
2146 {
2147 modi_mask |= MODI_GRP;
2148 change_code[7] = 'G';
2149 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
2150 }
2151
2152
2153 if ( theFile->mtime != (time_t) p->theFile.mtime &&
2154 (theFile->check_flags & MODI_MTM) != 0)
2155 {
2156 modi_mask |= MODI_MTM;
2157 change_code[8] = 'T';
2158 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
2159 }
2160
2161 if ( (theFile->check_flags & MODI_ATM) != 0 &&
2162 theFile->atime != (time_t) p->theFile.atime)
2163 {
2164 modi_mask |= MODI_ATM;
2165 change_code[8] = 'T';
2166 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
2167 }
2168
2169
2170 /* Resetting the access time will set a new ctime. Thus, either we ignore
2171 * the access time or the ctime for NOIGNORE
2172 */
2173 if ( theFile->ctime != (time_t) p->theFile.ctime &&
2174 (theFile->check_flags & MODI_CTM) != 0)
2175 {
2176 modi_mask |= MODI_CTM;
2177 change_code[8] = 'T';
2178 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
2179 }
2180
2181 if ( theFile->size != (off_t) p->theFile.size &&
2182 (theFile->check_flags & MODI_SIZ) != 0)
2183 {
2184 if ((theFile->check_flags & MODI_SGROW) == 0 ||
2185 theFile->size < (off_t) p->theFile.size)
2186 {
2187 modi_mask |= MODI_SIZ;
2188 change_code[9] = 'S';
2189 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
2190 }
2191 }
2192 change_code[10] = '\0';
2193
2194 /* --- Directories special case ---
2195 */
2196 if (p->theFile.c_mode[0] == 'd' &&
2197 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
2198 sh_loosedircheck == S_TRUE)
2199 {
2200 modi_mask = 0;
2201 }
2202
2203 /* --- Report full details. ---
2204 */
2205 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
2206 {
2207 if ((theFile->check_flags & MODI_ATM) == 0)
2208 modi_mask = MASK_READONLY_;
2209 else
2210 modi_mask = MASK_NOIGNORE_;
2211 }
2212
2213 /* --- Report on modified files. ---
2214 */
2215 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
2216 {
2217 tmp = SH_ALLOC(SH_MSG_BUF);
2218 msg = SH_ALLOC(SH_MSG_BUF);
2219 msg[0] = '\0';
2220
2221 sh_files_fixup_mask(class, &(cf_report.newflags));
2222
2223 if ( (report_checkflags != S_FALSE) && (cf_report.oldflags != cf_report.newflags))
2224 {
2225 sl_snprintf(tmp, SH_MSG_BUF,
2226#ifdef SH_USE_XML
2227 _("checkflags_old=\"0%lo\" checkflags_new=\"0%lo\" "),
2228#else
2229 _("checkflags_old=<0%lo>, checkflags_new=<0%lo>, "),
2230#endif
2231 cf_report.oldflags, cf_report.newflags);
2232 sl_strlcat(msg, tmp, SH_MSG_BUF);
2233 }
2234
2235 if ( ((modi_mask & MODI_MOD) != 0)
2236#if defined(HAVE_LIBPRELUDE)
2237 || ((modi_mask & MODI_USR) != 0)
2238 || ((modi_mask & MODI_GRP) != 0)
2239#endif
2240 )
2241 {
2242#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2243 sl_snprintf(tmp, SH_MSG_BUF,
2244#ifdef SH_USE_XML
2245 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
2246#else
2247 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
2248#endif
2249 p->theFile.c_mode, theFile->c_mode,
2250 p->theFile.c_attributes, theFile->c_attributes
2251#ifdef SH_USE_XML
2252 , (long) p->theFile.mode, (long) theFile->mode,
2253 (long) p->theFile.attributes,
2254 (long) theFile->attributes
2255#endif
2256 );
2257#else
2258#ifdef SH_USE_XML
2259 sl_snprintf(tmp, SH_MSG_BUF,
2260 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
2261 p->theFile.c_mode, theFile->c_mode,
2262 (long) p->theFile.mode, (long) theFile->mode);
2263#else
2264 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
2265 p->theFile.c_mode, theFile->c_mode);
2266#endif
2267#endif
2268 sl_strlcat(msg, tmp, SH_MSG_BUF);
2269
2270#if defined(USE_ACL) || defined(USE_XATTR)
2271 if (theFile->attr_string != NULL || p->attr_string != NULL)
2272 {
2273 sl_snprintf(tmp, SH_MSG_BUF,
2274#ifdef SH_USE_XML
2275 _("acl_old=\"%s\" acl_new=\"%s\" "),
2276#else
2277 _("acl_old=<%s>, acl_new=<%s>, "),
2278#endif
2279 (p->attr_string) ? p->attr_string : _("none"),
2280 (theFile->attr_string) ? theFile->attr_string : _("none"));
2281
2282 sl_strlcat(msg, tmp, SH_MSG_BUF);
2283 }
2284#endif
2285
2286 if ((modi_mask & MODI_MOD) != 0)
2287 {
2288 /*
2289 * We postpone update if sh.flag.update == S_TRUE because
2290 * in interactive mode the user may not accept the change.
2291 */
2292 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2293 {
2294 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2295 p->theFile.mode = theFile->mode;
2296#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2297 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
2298 p->theFile.attributes = theFile->attributes;
2299#endif
2300#if defined(USE_ACL) || defined(USE_XATTR)
2301 if (p->attr_string == NULL && theFile->attr_string != NULL)
2302 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2303 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2304 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2305 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2306 {
2307 if (0 != strcmp(theFile->attr_string, p->attr_string))
2308 {
2309 SH_FREE(p->attr_string);
2310 p->attr_string = sh_util_strdup (theFile->attr_string);
2311 }
2312 }
2313#endif
2314 }
2315 }
2316
2317 }
2318
2319 if ((modi_mask & MODI_HLN) != 0)
2320 {
2321 sl_snprintf(tmp, SH_MSG_BUF,
2322#ifdef SH_USE_XML
2323 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
2324#else
2325 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
2326#endif
2327 (unsigned long) p->theFile.hardlinks,
2328 (unsigned long) theFile->hardlinks);
2329 sl_strlcat(msg, tmp, SH_MSG_BUF);
2330
2331 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2332 p->theFile.hardlinks = theFile->hardlinks;
2333 }
2334
2335 if ((modi_mask & MODI_RDEV) != 0)
2336 {
2337 sl_snprintf(tmp, SH_MSG_BUF,
2338#ifdef SH_USE_XML
2339 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
2340#else
2341 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
2342#endif
2343 (unsigned long) major(p->theFile.rdev),
2344 (unsigned long) minor(p->theFile.rdev),
2345 (unsigned long) major(theFile->rdev),
2346 (unsigned long) minor(theFile->rdev)
2347#ifdef SH_USE_XML
2348 , (unsigned long) p->theFile.rdev,
2349 (unsigned long) theFile->rdev
2350#endif
2351 );
2352 sl_strlcat(msg, tmp, SH_MSG_BUF);
2353
2354 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2355 p->theFile.rdev = theFile->rdev;
2356 }
2357
2358 if ((modi_mask & MODI_INO) != 0)
2359 {
2360 sl_snprintf(tmp, SH_MSG_BUF,
2361#ifdef SH_USE_XML
2362 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
2363#else
2364 _("inode_old=<%lu>, inode_new=<%lu>, "),
2365#endif
2366 (unsigned long) p->theFile.ino,
2367 (unsigned long) theFile->ino);
2368 sl_strlcat(msg, tmp, SH_MSG_BUF);
2369
2370 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2371 {
2372 p->theFile.ino = theFile->ino;
2373 p->theFile.dev = theFile->dev;
2374 }
2375 }
2376
2377
2378 /*
2379 * also report device for prelude
2380 */
2381#if defined(HAVE_LIBPRELUDE)
2382 if ((modi_mask & MODI_INO) != 0)
2383 {
2384 sl_snprintf(tmp, SH_MSG_BUF,
2385#ifdef SH_USE_XML
2386 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
2387#else
2388 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
2389#endif
2390 (unsigned long) major(p->theFile.dev),
2391 (unsigned long) minor(p->theFile.dev),
2392 (unsigned long) major(theFile->dev),
2393 (unsigned long) minor(theFile->dev)
2394 );
2395 sl_strlcat(msg, tmp, SH_MSG_BUF);
2396
2397 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2398 p->theFile.dev = theFile->dev;
2399 }
2400#endif
2401
2402 if ( ((modi_mask & MODI_USR) != 0)
2403#if defined(HAVE_LIBPRELUDE)
2404 || ((modi_mask & MODI_MOD) != 0)
2405#endif
2406 )
2407 {
2408#ifdef SH_USE_XML
2409 sl_snprintf(tmp, SH_MSG_BUF,
2410 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
2411#else
2412 sl_snprintf(tmp, SH_MSG_BUF,
2413 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
2414#endif
2415 p->theFile.c_owner, theFile->c_owner,
2416 (long) p->theFile.owner, (long) theFile->owner
2417 );
2418 sl_strlcat(msg, tmp, SH_MSG_BUF);
2419
2420 if ((modi_mask & MODI_USR) != 0) {
2421 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2422 {
2423 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2424 p->theFile.owner = theFile->owner;
2425 }
2426 }
2427 }
2428
2429 if ( ((modi_mask & MODI_GRP) != 0)
2430#if defined(HAVE_LIBPRELUDE)
2431 || ((modi_mask & MODI_MOD) != 0)
2432#endif
2433 )
2434 {
2435#ifdef SH_USE_XML
2436 sl_snprintf(tmp, SH_MSG_BUF,
2437 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
2438 p->theFile.c_group, theFile->c_group,
2439 (long) p->theFile.group, (long) theFile->group);
2440#else
2441 sl_snprintf(tmp, SH_MSG_BUF,
2442 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
2443 p->theFile.c_group, theFile->c_group,
2444 (long) p->theFile.group, (long) theFile->group);
2445#endif
2446
2447 sl_strlcat(msg, tmp, SH_MSG_BUF);
2448
2449 if ((modi_mask & MODI_GRP) != 0) {
2450 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2451 {
2452 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2453 p->theFile.group = theFile->group;
2454 }
2455 }
2456 }
2457
2458 if ((modi_mask & MODI_SIZ) != 0)
2459 {
2460 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2461 (UINT64) p->theFile.size,
2462 (UINT64) theFile->size);
2463 sl_strlcat(msg, tmp, SH_MSG_BUF);
2464
2465 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2466 p->theFile.size = theFile->size;
2467 }
2468
2469 if ((modi_mask & MODI_CTM) != 0)
2470 {
2471 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
2472 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
2473#ifdef SH_USE_XML
2474 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
2475 timstr1c, timstr2c);
2476#else
2477 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
2478 timstr1c, timstr2c);
2479#endif
2480 sl_strlcat(msg, tmp, SH_MSG_BUF);
2481
2482 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2483 p->theFile.ctime = theFile->ctime;
2484 }
2485
2486 if ((modi_mask & MODI_ATM) != 0)
2487 {
2488 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
2489 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
2490#ifdef SH_USE_XML
2491 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
2492 timstr1a, timstr2a);
2493#else
2494 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
2495 timstr1a, timstr2a);
2496#endif
2497 sl_strlcat(msg, tmp, SH_MSG_BUF);
2498
2499 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2500 p->theFile.atime = theFile->atime;
2501 }
2502
2503 if ((modi_mask & MODI_MTM) != 0)
2504 {
2505 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
2506 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
2507#ifdef SH_USE_XML
2508 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
2509 timstr1m, timstr2m);
2510#else
2511 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
2512 timstr1m, timstr2m);
2513#endif
2514 sl_strlcat(msg, tmp, SH_MSG_BUF);
2515
2516 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2517 p->theFile.mtime = theFile->mtime;
2518 }
2519
2520
2521 if ((modi_mask & MODI_CHK) != 0)
2522 {
2523 sl_snprintf(tmp, SH_MSG_BUF,
2524#ifdef SH_USE_XML
2525 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
2526#else
2527 _("chksum_old=<%s>, chksum_new=<%s>, "),
2528#endif
2529 p->theFile.checksum, fileHash);
2530 sl_strlcat(msg, tmp, SH_MSG_BUF);
2531
2532 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2533 {
2534 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2535 if ((theFile->check_flags & MODI_SGROW) != 0)
2536 p->theFile.size = theFile->size;
2537 }
2538
2539
2540 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
2541 strlen(theFile->link_path) > 2)
2542 modi_mask |= MODI_LNK;
2543 }
2544
2545
2546 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
2547 {
2548 if (theFile->link_path)
2549 tmp_lnk = sh_util_safe_name(theFile->link_path);
2550 else
2551 tmp_lnk = sh_util_strdup("-");
2552 if (p->linkpath)
2553 tmp_lnk_old = sh_util_safe_name(p->linkpath);
2554 else
2555 tmp_lnk_old = sh_util_strdup("-");
2556#ifdef SH_USE_XML
2557 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
2558 tmp_lnk_old, tmp_lnk);
2559#else
2560 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "),
2561 tmp_lnk_old, tmp_lnk);
2562#endif
2563 SH_FREE(tmp_lnk);
2564 SH_FREE(tmp_lnk_old);
2565 sl_strlcat(msg, tmp, SH_MSG_BUF);
2566
2567 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2568 {
2569 if (p->linkpath != NULL)
2570 SH_FREE(p->linkpath);
2571 if (!(theFile->link_path))
2572 p->linkpath = sh_util_strdup("-");
2573 else
2574 p->linkpath = sh_util_strdup(theFile->link_path);
2575 }
2576 }
2577
2578 if (MODI_AUDIT_ENABLED(theFile->check_flags))
2579 {
2580 char result[256];
2581
2582 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__,
2583 0, MSG_E_SUBGPATH,
2584 _("Fetching audit record"),
2585 _("sh_hash"), theFile->fullpath );
2586
2587 if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, theFile->ctime, result, sizeof(result)))
2588 {
2589#ifdef SH_USE_XML
2590 sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
2591#else
2592 sl_strlcat(msg, _("obj=<"), SH_MSG_BUF);
2593#endif
2594
2595 sl_strlcat(msg, result, SH_MSG_BUF);
2596
2597#ifdef SH_USE_XML
2598 sl_strlcat(msg, _("\" "), SH_MSG_BUF);
2599#else
2600 sl_strlcat(msg, _(">"), SH_MSG_BUF);
2601#endif
2602 }
2603 }
2604
2605 /****************************************************
2606 *
2607 * REPORT on file change
2608 *
2609 ****************************************************/
2610 tmp_path = sh_util_safe_name(theFile->fullpath);
2611 if (!sh_global_check_silent)
2612 sh_error_handle(log_severity, FIL__, __LINE__,
2613 (long) modi_mask, MSG_FI_CHAN,
2614 (policy_override == NULL) ? _(policy[class]):log_policy,
2615 change_code, tmp_path, msg);
2616 ++sh.statistics.files_report;
2617
2618 SH_FREE(tmp_path);
2619 SH_FREE(tmp);
2620 SH_FREE(msg);
2621
2622 if (S_TRUE == sh.flag.update)
2623 {
2624 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
2625 {
2626 /* user does not want to update, thus we replace
2627 * with data from the baseline database
2628 */
2629 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
2630 theFile->mode = p->theFile.mode;
2631#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2632 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
2633 theFile->attributes = p->theFile.attributes;
2634#endif
2635#if defined(USE_ACL) || defined(USE_XATTR)
2636 if (theFile->attr_string == NULL && p->attr_string != NULL)
2637 { theFile->attr_string = sh_util_strdup (p->attr_string); }
2638 else if (theFile->attr_string != NULL && p->attr_string == NULL)
2639 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
2640 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2641 {
2642 if (0 != strcmp(theFile->attr_string, p->attr_string))
2643 {
2644 SH_FREE(theFile->attr_string);
2645 theFile->attr_string = sh_util_strdup (p->attr_string);
2646 }
2647 }
2648#endif
2649
2650 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
2651 {
2652 if (theFile->link_path)
2653 SH_FREE(theFile->link_path);
2654 if (p->linkpath)
2655 theFile->link_path = sh_util_strdup(p->linkpath);
2656 else
2657 theFile->link_path = sh_util_strdup("-");
2658 }
2659 else
2660 {
2661 if (theFile->link_path)
2662 SH_FREE(theFile->link_path);
2663 if (p->linkpath)
2664 theFile->link_path = sh_util_strdup(p->linkpath);
2665 else
2666 theFile->link_path = NULL;
2667 }
2668
2669 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
2670
2671 theFile->mtime = p->theFile.mtime;
2672 theFile->ctime = p->theFile.ctime;
2673 theFile->atime = p->theFile.atime;
2674
2675 theFile->size = p->theFile.size;
2676
2677 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
2678 theFile->group = p->theFile.group;
2679 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
2680 theFile->owner = p->theFile.owner;
2681
2682 theFile->ino = p->theFile.ino;
2683 theFile->rdev = p->theFile.rdev;
2684 theFile->dev = p->theFile.dev;
2685 theFile->hardlinks = p->theFile.hardlinks;
2686
2687 SET_SH_FFLAG_VISITED(p->fflags);
2688 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2689 retval = 1;
2690 goto unlock_and_return;
2691 }
2692 else /* if (sh.flag.reportonce == S_TRUE) */
2693 {
2694 /* we replace the data in the in-memory copy of the
2695 * baseline database, because otherwise we would get
2696 * another warning if the suidcheck runs
2697 */
2698 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2699 p->theFile.mode = theFile->mode;
2700#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2701 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
2702 p->theFile.attributes = theFile->attributes;
2703#endif
2704#if defined(USE_ACL) || defined(USE_XATTR)
2705 if (p->attr_string == NULL && theFile->attr_string != NULL)
2706 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2707 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2708 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2709 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2710 {
2711 if (0 != strcmp(theFile->attr_string, p->attr_string))
2712 {
2713 SH_FREE(p->attr_string);
2714 p->attr_string = sh_util_strdup (theFile->attr_string);
2715 }
2716 }
2717#endif
2718
2719 if (theFile->c_mode[0] == 'l' || theFile->link_path)
2720 {
2721 if (p->linkpath != NULL)
2722 SH_FREE(p->linkpath);
2723 p->linkpath = sh_util_strdup(theFile->link_path);
2724 }
2725 else
2726 {
2727 if (p->linkpath != NULL)
2728 SH_FREE(p->linkpath);
2729 p->linkpath = sh_util_strdup("-");
2730 }
2731
2732 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2733
2734 p->theFile.mtime = theFile->mtime;
2735 p->theFile.ctime = theFile->ctime;
2736 p->theFile.atime = theFile->atime;
2737
2738 p->theFile.size = theFile->size;
2739
2740 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2741 p->theFile.group = theFile->group;
2742 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2743 p->theFile.owner = theFile->owner;
2744
2745 p->theFile.ino = theFile->ino;
2746 p->theFile.rdev = theFile->rdev;
2747 p->theFile.dev = theFile->dev;
2748 p->theFile.hardlinks = theFile->hardlinks;
2749 }
2750 }
2751 }
2752
2753 SET_SH_FFLAG_VISITED(p->fflags);
2754 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2755
2756 unlock_and_return:
2757 ; /* 'label at end of compound statement */
2758 SH_MUTEX_UNLOCK(mutex_hash);
2759 SL_RETURN(retval, _("sh_hash_compdata"));
2760}
2761
2762int hash_full_tree ()
2763{
2764 sh_file_t * p;
2765 int i;
2766
2767 SL_ENTER(_("hash_full_tree"));
2768
2769 if (IsInit != 1)
2770 SL_RETURN(0, _("hash_full_tree"));
2771
2772 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
2773 for (i = 0; i < TABSIZE; ++i)
2774 {
2775 for (p = tab[i]; p; p = p->next)
2776 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
2777 }
2778 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
2779 SL_RETURN (0, _("hash_full_tree"));
2780}
2781
2782#if !defined(SH_CUTEST)
2783static
2784#endif
2785int hash_remove_tree_test(char * s, char * fullpath, size_t len_s)
2786{
2787 size_t len_p;
2788 char * test;
2789
2790 len_p = strlen(fullpath);
2791
2792 if (len_p >= len_s)
2793 {
2794 if (0 == strncmp(s, fullpath, len_s))
2795 {
2796 if (len_p > len_s)
2797 {
2798 /* continue if not inside directory;
2799 * len_s > 1 because everything is inside '/'
2800 */
2801 if ((len_s > 1) && (fullpath[len_s] != '/'))
2802 return S_FALSE;
2803
2804 test = sh_files_find_mostspecific_dir(fullpath);
2805
2806 if (test && 0 != strcmp(test, s)) {
2807 /* There is a more specific directory, continue */
2808 return S_FALSE;
2809 }
2810
2811 if (NULL == sh_files_findfile(fullpath)) {
2812 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2813 return S_TRUE;
2814 }
2815 }
2816 else /* len_p == len */
2817 {
2818 /* it is 's' itself, mark and continue
2819 * unless there is a policy for the inode itself
2820 */
2821 if (NULL == sh_files_findfile(fullpath)) {
2822 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2823 return S_TRUE;
2824 }
2825 else {
2826 return S_FALSE;
2827 }
2828 }
2829
2830 } /* if path is in tree */
2831 } /* if path is possibly in tree */
2832 return S_FALSE;
2833}
2834
2835
2836int hash_remove_tree (char * s)
2837{
2838 sh_file_t * p;
2839 size_t len_s;
2840 unsigned int i;
2841
2842 SL_ENTER(_("hash_remove_tree"));
2843
2844 if (!s || *s == '\0')
2845 SL_RETURN ((-1), _("hash_remove_tree"));
2846
2847 len_s = sl_strlen(s);
2848
2849 if (IsInit != 1)
2850 sh_hash_init();
2851
2852 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
2853 for (i = 0; i < TABSIZE; ++i)
2854 {
2855 for (p = tab[i]; p; p = p->next)
2856 {
2857 if (p->fullpath)
2858 {
2859 /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */
2860 if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) {
2861 SET_SH_FFLAG_ALLIGNORE(p->fflags);
2862 MODI_SET(p->theFile.checkflags, MODI_ALLIGNORE);
2863 }
2864 } /* if path is not null */
2865
2866 }
2867 }
2868 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
2869 SL_RETURN ((0), _("hash_remove_tree"));
2870}
2871
2872#if TIME_WITH_SYS_TIME
2873#include <sys/time.h>
2874#include <time.h>
2875#else
2876#if HAVE_SYS_TIME_H
2877#include <sys/time.h>
2878#else
2879#include <time.h>
2880#endif
2881#endif
2882
2883static int ListFullDetail = S_FALSE;
2884static int ListWithDelimiter = S_FALSE;
2885static char * ListFile = NULL;
2886
2887int set_list_file (const char * c)
2888{
2889 ListFile = sh_util_strdup(c);
2890 return 0;
2891}
2892char * get_list_file()
2893{
2894 return ListFile;
2895}
2896
2897int set_full_detail (const char * c)
2898{
2899 (void) c;
2900 ListFullDetail = S_TRUE;
2901 return 0;
2902}
2903
2904int set_list_delimited (const char * c)
2905{
2906 (void) c;
2907 ListFullDetail = S_TRUE;
2908 ListWithDelimiter = S_TRUE;
2909 return 0;
2910}
2911
2912/* Always quote the string, except if it is empty. Quote quotes by
2913 * doubling them.
2914 */
2915char * csv_escape(const char * str)
2916{
2917 const char * p = str;
2918 const char * q;
2919
2920 size_t size = 0;
2921 size_t flag_quote = 0;
2922
2923 char * new;
2924 char * pnew;
2925
2926 if (p)
2927 {
2928
2929 while (*p)
2930 {
2931 if (*p == '"')
2932 ++flag_quote;
2933
2934 ++size; ++p;
2935 }
2936
2937 if (sl_ok_adds(size, flag_quote))
2938 size += flag_quote; /* double each quote */
2939 else
2940 return NULL;
2941
2942 if (sl_ok_adds(size, 3))
2943 size += 3; /* two quotes and terminating null */
2944 else
2945 return NULL;
2946
2947 new = SH_ALLOC(size);
2948
2949 if (flag_quote != 0)
2950 {
2951 new[0] = '"';
2952 pnew = &new[1];
2953 q = str;
2954 while (*q)
2955 {
2956 *pnew = *q;
2957 if (*pnew == '"')
2958 {
2959 ++pnew; *pnew = '"';
2960 }
2961 ++pnew; ++q;
2962 }
2963 *pnew = '"'; ++pnew;
2964 *pnew = '\0';
2965 }
2966 else
2967 {
2968 if (size > 3)
2969 {
2970 new[0] = '"';
2971 sl_strlcpy (&new[1], str, size-1);
2972 new[size-2] = '"';
2973 new[size-1] = '\0';
2974 }
2975 else
2976 {
2977 new[0] = '\0';
2978 }
2979 }
2980
2981 return new;
2982 }
2983 return NULL;
2984}
2985
2986int isHexKey(char * s)
2987{
2988 int i;
2989
2990 for (i = 0; i < KEY_LEN; ++i)
2991 {
2992 if (*s)
2993 {
2994 if ((*s >= '0' && *s <= '9') ||
2995 (*s >= 'A' && *s <= 'F') ||
2996 (*s >= 'a' && *s <= 'f'))
2997 {
2998 ++s;
2999 continue;
3000 }
3001 }
3002 return S_FALSE;
3003 }
3004 return S_TRUE;
3005}
3006
3007#include "sh_checksum.h"
3008
3009static char * KEYBUFtolower (char * s, char * result)
3010{
3011 char * r = result;
3012 if (s)
3013 {
3014 for (; *s; ++s)
3015 {
3016 *r = tolower((unsigned char) *s); ++r;
3017 }
3018 *r = '\0';
3019 }
3020 return result;
3021}
3022
3023void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3024{
3025 char * tmp;
3026 char * esc;
3027 char str[81];
3028 char hexdigest[SHA256_DIGEST_STRING_LENGTH];
3029 char keybuffer[KEYBUF_SIZE];
3030
3031 if (ListWithDelimiter == S_TRUE)
3032 {
3033 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3034 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3035 p->theFile.c_mode, (int) p->theFile.mode,
3036 p->theFile.c_attributes, (int) p->theFile.attributes,
3037 (int) p->theFile.hardlinks,
3038 p->theFile.c_owner, (int) p->theFile.owner,
3039 p->theFile.c_group, (int) p->theFile.group);
3040 }
3041 else
3042 {
3043 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3044 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3045 p->theFile.c_mode, (int) p->theFile.mode,
3046 p->theFile.c_attributes, (int) p->theFile.attributes,
3047 (int) p->theFile.hardlinks,
3048 p->theFile.c_owner, (int) p->theFile.owner,
3049 p->theFile.c_group, (int) p->theFile.group);
3050 }
3051
3052 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3053 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3054 else
3055 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3056
3057 printf( _(" %8s"), str);
3058 if (ListWithDelimiter == S_TRUE)
3059 putchar(',');
3060
3061 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3062 if (ListWithDelimiter == S_TRUE)
3063 putchar(',');
3064 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3065 if (ListWithDelimiter == S_TRUE)
3066 putchar(',');
3067 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3068 if (ListWithDelimiter == S_TRUE)
3069 putchar(',');
3070
3071 if (isHexKey(p->theFile.checksum))
3072 printf( _(" %s"), KEYBUFtolower(p->theFile.checksum, keybuffer));
3073 else
3074 printf( _(" %s"), SHA256_Base2Hex(p->theFile.checksum, hexdigest));
3075 if (ListWithDelimiter == S_TRUE)
3076 putchar(',');
3077
3078 tmp = sh_util_safe_name(p->fullpath);
3079 if (ListWithDelimiter != S_TRUE)
3080 {
3081 printf( _(" %s"), tmp);
3082 }
3083 else
3084 {
3085 esc = csv_escape(tmp);
3086 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3087 if (esc)
3088 SH_FREE(esc);
3089 }
3090 SH_FREE(tmp);
3091
3092 if ('l' == p->theFile.c_mode[0])
3093 {
3094 tmp = sh_util_safe_name(p->linkpath);
3095 if (ListWithDelimiter != S_TRUE)
3096 {
3097 printf(_(" -> %s"), tmp);
3098 }
3099 else
3100 {
3101 esc = csv_escape(tmp);
3102 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3103 if (esc)
3104 SH_FREE(esc);
3105 }
3106 SH_FREE(tmp);
3107 }
3108
3109 if (p->attr_string)
3110 {
3111 tmp = sh_util_safe_name(p->attr_string);
3112 if (ListWithDelimiter != S_TRUE)
3113 {
3114 printf(_(" %s"), tmp);
3115 }
3116 else
3117 {
3118 esc = csv_escape(tmp);
3119 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3120 if (esc)
3121 SH_FREE(esc);
3122 }
3123 SH_FREE(tmp);
3124 }
3125 else
3126 {
3127 if (ListWithDelimiter == S_TRUE)
3128 printf("%s",_(" no_attr"));
3129 }
3130 putchar('\n');
3131
3132 return;
3133}
3134
3135void sh_hash_list_db_entry (sh_file_t * p)
3136{
3137 char nowtime[128];
3138 char thetime[128];
3139 char * tmp;
3140 time_t now = time(NULL);
3141 time_t then = (time_t) p->theFile.mtime;
3142 struct tm * time_ptr;
3143
3144#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3145 struct tm time_tm;
3146#endif
3147
3148 if (ListFullDetail != S_FALSE)
3149 {
3150 sh_hash_list_db_entry_full_detail (p);
3151 return;
3152 }
3153
3154#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3155 time_ptr = gmtime_r(&then, &time_tm);
3156 if (!time_ptr)
3157 return;
3158 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3159 time_ptr = gmtime_r(&now, &time_tm);
3160 if (!time_ptr)
3161 return;
3162 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3163 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3164 {
3165 time_ptr = gmtime_r(&then, &time_tm);
3166 if (!time_ptr)
3167 return;
3168 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3169 }
3170#else
3171 time_ptr = gmtime(&then);
3172 if (!time_ptr)
3173 return;
3174 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3175 time_ptr = gmtime(&now);
3176 if (!time_ptr)
3177 return;
3178 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3179 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3180 {
3181 time_ptr = gmtime(&then);
3182 if (!time_ptr)
3183 return;
3184 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3185 }
3186#endif
3187
3188 tmp = sh_util_safe_name(p->fullpath);
3189 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3190 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3191 p->theFile.c_mode, (int) p->theFile.hardlinks,
3192 p->theFile.c_owner, p->theFile.c_group,
3193 (int) major((dev_t)p->theFile.rdev),
3194 (int) minor((dev_t)p->theFile.rdev),
3195 thetime,
3196 tmp);
3197 else
3198 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3199 p->theFile.c_mode, (int) p->theFile.hardlinks,
3200 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3201 thetime,
3202 tmp);
3203 SH_FREE(tmp);
3204
3205 if ('l' == p->theFile.c_mode[0])
3206 {
3207 tmp = sh_util_safe_name(p->linkpath);
3208 printf(_(" -> %s\n"), tmp);
3209 SH_FREE(tmp);
3210 }
3211 else
3212 printf("\n");
3213
3214 return;
3215}
3216
3217#ifdef HAVE_LIBZ
3218#include <zlib.h>
3219#endif
3220
3221int sh_hash_printcontent(char * linkpath)
3222{
3223#ifdef HAVE_LIBZ
3224 unsigned char * decoded;
3225 unsigned char * decompressed = NULL;
3226 size_t dlen;
3227 unsigned long clen;
3228 unsigned long clen_o;
3229 int res;
3230
3231 if (linkpath && *linkpath != '-')
3232 {
3233 dlen = sh_util_base64_dec_alloc (&decoded,
3234 (unsigned char *)linkpath,
3235 strlen(linkpath));
3236
3237 clen = dlen * 2 + 1;
3238
3239 do {
3240 if (decompressed)
3241 SH_FREE(decompressed);
3242 clen += dlen; clen_o = clen;
3243 decompressed = SH_ALLOC(clen);
3244 res = uncompress(decompressed, &clen, decoded, dlen);
3245 if (res == Z_MEM_ERROR)
3246 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
3247 if (res == Z_DATA_ERROR)
3248 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
3249 } while (res == Z_BUF_ERROR || clen == clen_o);
3250
3251 decompressed[clen] = '\0';
3252 fputs( (char*) decompressed, stdout);
3253 SH_FREE(decompressed);
3254 return 0;
3255 }
3256#else
3257 (void) linkpath;
3258#endif
3259 fprintf(stderr, "%s",_("Error: No data available\n"));
3260 return -1;
3261}
3262
3263/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
3264#endif
Note: See TracBrowser for help on using the repository browser.