source: trunk/src/sh_hash.c@ 402

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

Fix for ticket #298, #299 (inotify related extraneous warnings and messages).

File size: 102.8 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/* define this if you want version 1.3 style database file */
23/* #define OLD_BUG */
24
25/* make sure state changes of a file are always reported, even
26 * with reportonlyonce=true
27 */
28/* #define REPLACE_OLD *//* moved to samhain.h */
29
30#include <stdlib.h>
31#include <string.h>
32#include <stdio.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#ifdef MAJOR_IN_MKDEV
38#include <sys/mkdev.h>
39#else
40#ifdef MAJOR_IN_SYSMACROS
41#include <sys/sysmacros.h>
42#endif
43#endif
44
45#ifdef HAVE_MEMORY_H
46#include <memory.h>
47#endif
48
49#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
50
51#include "sh_hash.h"
52#include "sh_utils.h"
53#include "sh_error.h"
54#include "sh_tiger.h"
55#include "sh_gpg.h"
56#include "sh_unix.h"
57#include "sh_files.h"
58#include "sh_ignore.h"
59#include "sh_pthread.h"
60
61#if defined(SH_WITH_CLIENT)
62#include "sh_forward.h"
63#endif
64
65
66#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
67
68
69#undef FIL__
70#define FIL__ _("sh_hash.c")
71
72SH_MUTEX_STATIC(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
73
74const char notalink[2] = { '-', '\0' };
75
76static char * all_items (file_type * theFile, char * fileHash, int is_new);
77
78#define QUOTE_CHAR '='
79
80char * unquote_string (const char * str, size_t len)
81{
82 int i = 0, t1, t2;
83 char * tmp = NULL;
84 size_t l2, j, k = 0;
85
86 SL_ENTER(_("unquote_string"));
87
88 if (str != NULL)
89 {
90 l2 = len - 2;
91 tmp = SH_ALLOC(len + 1);
92
93 for (j = 0; j <= len; ++j)
94 {
95 if (str[j] != QUOTE_CHAR)
96 {
97 tmp[k] = str[j];
98 }
99 else if (str[j] == QUOTE_CHAR && j < l2)
100 {
101 t1 = sh_util_hexchar(str[j+1]);
102 t2 = sh_util_hexchar(str[j+2]);
103 if ((t1|t2) >= 0)
104 {
105 i = 16 * t1 + t2;
106 tmp[k] = i;
107 j += 2;
108 }
109 else
110 {
111 tmp[k] = str[j];
112 }
113 }
114 else
115 tmp[k] = str[j];
116 ++k;
117 }
118 }
119 SL_RETURN(tmp, _("unquote_string"));
120}
121
122
123static char * int2hex (unsigned char i, char * i2h)
124{
125 static char hexchars[] = "0123456789ABCDEF";
126
127 i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
128 i2h[1] = hexchars[((i) & 0x0F)]; /* low */
129
130 return i2h;
131}
132
133
134char * quote_string (const char * str, size_t len)
135{
136 char * tmp;
137 char * tmp2;
138 size_t l2, j, i = 0, k = 0;
139 char i2h[2];
140
141 SL_ENTER(_("quote_string"));
142
143 if (str == NULL)
144 {
145 SL_RETURN(NULL, _("quote_string"));
146 }
147
148 for (j = 0; j < len; ++j)
149 if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
150
151 l2 = len + 1;
152 if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
153 {
154 tmp = SH_ALLOC(len + 1 + 3*i);
155 }
156 else
157 {
158 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
159 _("integer overflow"),
160 _("quote_string"));
161 SL_RETURN(NULL, _("quote_string"));
162 }
163
164 for (j = 0; j <= len; ++j)
165 {
166 if (str[j] == '\n')
167 {
168 tmp2 = int2hex((unsigned char) '\n', i2h); /* was 'n', fixed in 1.5.4 */
169 tmp[k] = QUOTE_CHAR; ++k;
170 tmp[k] = tmp2[0]; ++k;
171 tmp[k] = tmp2[1];
172 }
173 else if (str[j] == QUOTE_CHAR)
174 {
175 tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
176 tmp[k] = QUOTE_CHAR; ++k;
177 tmp[k] = tmp2[0]; ++k;
178 tmp[k] = tmp2[1];
179 }
180 else
181 {
182 tmp[k] = str[j];
183 }
184 ++k;
185 }
186 SL_RETURN(tmp, _("quote_string"));
187}
188
189static UINT32 * swap_32 (UINT32 * iptr)
190{
191#ifdef WORDS_BIGENDIAN
192 unsigned char swap;
193 unsigned char * ii = (unsigned char *) iptr;
194 swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
195 swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
196 return iptr;
197#else
198 return iptr;
199#endif
200}
201
202static UINT64 * swap_64 (UINT64 * iptr)
203{
204#ifdef WORDS_BIGENDIAN
205#ifdef UINT64_IS_32
206 swap_32 ((UINT32*) iptr);
207#else
208 unsigned char swap;
209 unsigned char * ii = (unsigned char *) iptr;
210 swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
211 swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
212 swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
213 swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
214#endif
215 return iptr;
216#else
217 return iptr;
218#endif
219}
220
221static unsigned short * swap_short (unsigned short * iptr)
222{
223#ifdef WORDS_BIGENDIAN
224 if (sizeof(short) == 4)
225 swap_32 ((UINT32*) iptr);
226 else
227 {
228 /* alignment problem */
229 unsigned char swap;
230 static unsigned short ooop;
231 unsigned char * ii;
232 ooop = *iptr;
233 ii = (unsigned char *) &ooop;
234 /* printf("SWAP0: %hd %d\n", *iptr, sizeof(unsigned short)); */
235 swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
236 /* printf("SWAP1: %hd\n", (unsigned short) ooop); */
237#ifndef OLD_BUG
238 return &ooop;
239#endif
240 }
241 return iptr;
242#else
243 return iptr;
244#endif
245}
246
247
248typedef struct store_info {
249
250 UINT32 mode;
251 UINT32 linkmode;
252
253 UINT64 dev;
254 UINT64 rdev;
255 UINT32 hardlinks;
256 UINT32 ino;
257 UINT64 size;
258 UINT64 atime;
259 UINT64 mtime;
260 UINT64 ctime;
261 UINT32 owner;
262 UINT32 group;
263
264#ifdef OLD_BUG
265#if defined(__linux__)
266 UINT32 attributes;
267 char c_attributes[ATTRBUF_SIZE];
268#endif
269#else
270 /* #if defined(__linux__) */
271 UINT32 attributes;
272 char c_attributes[ATTRBUF_SIZE];
273 /* endif */
274#endif
275 unsigned short mark;
276 char c_owner[USER_MAX+2];
277 char c_group[GROUP_MAX+2];
278 char c_mode[CMODE_SIZE];
279 char checksum[KEY_LEN+1];
280} sh_filestore_t;
281
282typedef struct file_info {
283 sh_filestore_t theFile;
284 char * fullpath;
285 char * linkpath;
286 char * attr_string;
287 int fflags;
288 unsigned long modi_mask;
289 struct file_info * next;
290} sh_file_t;
291
292 static const char *policy[] = {
293 N_("[]"),
294 N_("[ReadOnly]"),
295 N_("[LogFiles]"),
296 N_("[GrowingLogs]"),
297 N_("[IgnoreNone]"),
298 N_("[IgnoreAll]"),
299 N_("[Attributes]"),
300 N_("[User0]"),
301 N_("[User1]"),
302 N_("[User2]"),
303 N_("[User3]"),
304 N_("[User4]"),
305 N_("[Prelink]"),
306 NULL
307 };
308
309const char * sh_hash_getpolicy(int class)
310{
311 if (class > 0 && class < SH_ERR_T_DIR)
312 return _(policy[class]);
313 return _("[indef]");
314}
315
316/**********************************
317 *
318 * hash table functions
319 *
320 **********************************
321 */
322
323#include "sh_hash.h"
324
325/* must fit an int */
326/* #define TABSIZE 2048 */
327#define TABSIZE 65536
328
329/* must fit an unsigned short */
330/* changed for V0.8, as the */
331/* database format has changed */
332
333/* changed again for V0.9 */
334/* #define REC_MAGIC 19 */
335/* changed again for V1.3 */
336#ifdef OLD_BUG
337#define REC_MAGIC 20
338#else
339/* changed again for V1.4 */
340#define REC_MAGIC 21
341#endif
342
343#define REC_FLAGS_ATTR (1<<8)
344#define REC_FLAGS_MASK 0xFF00
345
346/**************************************************************
347 *
348 * create a file_type from a sh_file_t
349 *
350 **************************************************************/
351static file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
352{
353 file_type * theFile;
354
355 SL_ENTER(_("sh_hash_create_ft"));
356
357 theFile = SH_ALLOC(sizeof(file_type));
358
359 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
360 theFile->mode = p->theFile.mode;
361#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
362 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
363 theFile->attributes = p->theFile.attributes;
364#endif
365
366 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
367 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
368 {
369 theFile->link_path = sh_util_strdup(p->linkpath);
370 }
371 else
372 {
373 theFile->link_path = NULL;
374 }
375 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
376
377 theFile->mtime = p->theFile.mtime;
378 theFile->ctime = p->theFile.ctime;
379 theFile->atime = p->theFile.atime;
380
381 theFile->size = p->theFile.size;
382
383 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
384 theFile->group = p->theFile.group;
385 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
386 theFile->owner = p->theFile.owner;
387
388 theFile->ino = p->theFile.ino;
389 theFile->rdev = p->theFile.rdev;
390 theFile->dev = p->theFile.dev;
391 theFile->hardlinks = p->theFile.hardlinks;
392
393 if (p->attr_string)
394 theFile->attr_string = sh_util_strdup(p->attr_string);
395 else
396 theFile->attr_string = NULL;
397
398 SL_RETURN((theFile), _("sh_hash_create_ft"));
399}
400
401struct two_sh_file_t {
402 sh_file_t * prev;
403 sh_file_t * this;
404};
405
406static sh_file_t * hashsearch (const char * s);
407static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index);
408
409static sh_file_t * tab[TABSIZE];
410
411/**************************************************************
412 *
413 * compute hash function
414 *
415 **************************************************************/
416
417static int hashfunc(const char *s)
418{
419 unsigned int n = 0;
420
421 for ( ; *s; s++)
422 n = 31 * n + *s;
423
424 return n & (TABSIZE - 1); /* % TABSIZE */;
425}
426
427
428int hashreport_missing( char *fullpath, int level)
429{
430 sh_file_t * p;
431 char * tmp;
432 char fileHash[KEY_LEN + 1];
433 file_type * theFile;
434 char * str;
435 char hashbuf[KEYBUF_SIZE];
436 volatile int retval;
437
438 /* -------- find the entry for the file ---------------- */
439
440 SH_MUTEX_LOCK(mutex_hash);
441
442 retval = 0;
443
444 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
445 p = hashsearch(fullpath);
446 else
447 p = hashsearch( sh_tiger_hash(fullpath,
448 TIGER_DATA,
449 sl_strlen(fullpath),
450 hashbuf, sizeof(hashbuf))
451 );
452 if (p == NULL)
453 {
454 retval = -1;
455 goto unlock_and_return;
456 }
457
458 theFile = sh_hash_create_ft (p, fileHash);
459 str = all_items(theFile, fileHash, 0);
460 tmp = sh_util_safe_name(fullpath);
461
462 SH_MUTEX_LOCK(mutex_thread_nolog);
463 sh_error_handle (level, FIL__, __LINE__, 0,
464 MSG_FI_MISS2, tmp, str);
465 SH_MUTEX_UNLOCK(mutex_thread_nolog);
466
467 SH_FREE(tmp);
468 SH_FREE(str);
469 if (theFile->attr_string) SH_FREE(theFile->attr_string);
470 if (theFile->link_path) SH_FREE(theFile->link_path);
471 SH_FREE(theFile);
472
473 unlock_and_return:
474 ; /* 'label at end of compound statement */
475 SH_MUTEX_UNLOCK(mutex_hash);
476
477 return retval;
478}
479
480
481/**************************************************************
482 *
483 * search for files not visited, and check whether they exist
484 *
485 **************************************************************/
486static sh_file_t * delete_db_entry(sh_file_t *p)
487{
488 if (p->fullpath)
489 {
490 SH_FREE(p->fullpath);
491 p->fullpath = NULL;
492 }
493 if (p->linkpath)
494 {
495 if (p->linkpath != notalink)
496 SH_FREE(p->linkpath);
497 p->linkpath = NULL;
498 }
499 if (p->attr_string)
500 {
501 SH_FREE(p->attr_string);
502 p->attr_string = NULL;
503 }
504 SH_FREE(p);
505 return NULL;
506}
507
508static void hash_unvisited (int j,
509 sh_file_t *prev, sh_file_t *p, ShErrLevel level)
510{
511 struct stat buf;
512 int i;
513 char * tmp;
514 char * ptr;
515 char fileHash[KEY_LEN + 1];
516 file_type * theFile;
517
518 char * str;
519
520
521 SL_ENTER(_("hash_unvisited"));
522
523 if (p->next != NULL)
524 hash_unvisited (j, p, p->next, level);
525
526 if (p->fullpath == NULL)
527 {
528 SL_RET0(_("hash_unvisited"));
529 }
530
531 /* Not a fully qualified path, i.e. some info stored by some module
532 */
533 if (p->fullpath[0] != '/')
534 {
535 SL_RET0(_("hash_unvisited"));
536 }
537
538 /* visited flag not set: not seen;
539 * checked flag set: not seen (i.e. missing), and already checked
540 * reported flag not set: not reported yet
541 * allignore flag not set: not under IgnoreAll
542 *
543 * Files/directories under IgnoreAll are noticed as missing already
544 * during the file check.
545 */
546 if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags))
547 && (!SH_FFLAG_REPORTED_SET(p->fflags))
548 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
549 {
550 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
551
552 /* if file does not exist
553 */
554 if (0 != i)
555 {
556 ptr = sh_util_dirname (p->fullpath);
557 if (ptr)
558 {
559 /* If any of the parent directories is under IgnoreAll
560 */
561 if (0 != sh_files_is_allignore(ptr))
562 level = ShDFLevel[SH_LEVEL_ALLIGNORE];
563 SH_FREE(ptr);
564 }
565
566 /* Only report if !SH_FFLAG_CHECKED_SET
567 */
568 if (!SH_FFLAG_CHECKED_SET(p->fflags))
569 {
570 if (S_FALSE == sh_ignore_chk_del(p->fullpath))
571 {
572 tmp = sh_util_safe_name(p->fullpath);
573
574 theFile = sh_hash_create_ft (p, fileHash);
575 str = all_items(theFile, fileHash, 0);
576 sh_error_handle (level, FIL__, __LINE__, 0,
577 MSG_FI_MISS2, tmp, str);
578 SH_FREE(str);
579 if (theFile->attr_string) SH_FREE(theFile->attr_string);
580 if (theFile->link_path) SH_FREE(theFile->link_path);
581 SH_FREE(theFile);
582
583 SH_FREE(tmp);
584 }
585 }
586
587 /* We rewrite the db on update, thus we need to keep this
588 * if the user does not want to purge it from the db.
589 */
590
591 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
592 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
593 {
594#ifdef REPLACE_OLD
595 /* Remove the old entry
596 */
597 if (prev == p)
598 tab[j] = p->next;
599 else
600 prev->next = p->next;
601
602 delete_db_entry(p);
603
604 SL_RET0(_("hash_unvisited"));
605#else
606 SET_SH_FFLAG_REPORTED(p->fflags);
607#endif
608 }
609 }
610 }
611
612 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
613 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
614 {
615 if (S_FALSE == sh_ignore_chk_new(p->fullpath))
616 {
617 tmp = sh_util_safe_name(p->fullpath);
618
619 theFile = sh_hash_create_ft (p, fileHash);
620 str = all_items(theFile, fileHash, 0);
621 sh_error_handle (level, FIL__, __LINE__, 0,
622 MSG_FI_MISS2, tmp, str);
623 SH_FREE(str);
624 if (theFile->attr_string)
625 SH_FREE(theFile->attr_string);
626 SH_FREE(theFile);
627
628 SH_FREE(tmp);
629 }
630
631 CLEAR_SH_FFLAG_REPORTED(p->fflags);
632 }
633
634 if (sh.flag.reportonce == S_FALSE)
635 CLEAR_SH_FFLAG_REPORTED(p->fflags);
636
637 CLEAR_SH_FFLAG_VISITED(p->fflags);
638 CLEAR_SH_FFLAG_CHECKED(p->fflags);
639
640 SL_RET0(_("hash_unvisited"));
641}
642
643
644
645/*********************************************************************
646 *
647 * Search for files in the database that have been deleted from disk.
648 *
649 *********************************************************************/
650void sh_hash_unvisited (ShErrLevel level)
651{
652 int i;
653
654 SL_ENTER(_("sh_hash_unvisited"));
655
656 SH_MUTEX_LOCK(mutex_hash);
657 for (i = 0; i < TABSIZE; ++i)
658 {
659 if (tab[i] != NULL)
660 hash_unvisited (i, tab[i], tab[i], level);
661 }
662 SH_MUTEX_UNLOCK(mutex_hash);
663
664 SL_RET0(_("hash_unvisited"));
665}
666
667/*********************************************************************
668 *
669 * Remove a single file from the database.
670 *
671 *********************************************************************/
672void sh_hash_remove (const char * path)
673{
674 struct two_sh_file_t entries;
675 int index;
676
677 SL_ENTER(_("sh_hash_remove"));
678
679 SH_MUTEX_LOCK(mutex_hash);
680
681 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
682 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
683 {
684 if (0 == hashsearch_prev (path, &entries, &index))
685 {
686 sh_file_t * p = entries.this;
687#ifdef REPLACE_OLD
688 /* Remove the old entry
689 */
690 if (entries.prev == p)
691 tab[index] = p->next;
692 else
693 entries.prev->next = p->next;
694
695 delete_db_entry(p);
696
697 goto end;
698#else
699 SET_SH_FFLAG_REPORTED(p->fflags);
700#endif
701 }
702 }
703
704 end:
705 ; /* 'label at end of compound statement' */
706 SH_MUTEX_UNLOCK(mutex_hash);
707
708 SL_RET0(_("sh_hash_remove"));
709}
710
711
712/*********************************************************************
713 *
714 * Search for unvisited entries in the database, custom error handler.
715 *
716 *********************************************************************/
717void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key))
718{
719 int i;
720 sh_file_t *p = NULL;
721 sh_file_t *prev = NULL;
722 sh_file_t *next = NULL;
723
724 SL_ENTER(_("sh_hash_unvisited_custom"));
725
726 SH_MUTEX_LOCK(mutex_hash);
727 for (i = 0; i < TABSIZE; ++i)
728 {
729 if (tab[i] != NULL)
730 {
731 p = tab[i]; prev = p;
732
733 do
734 {
735 next = p->next;
736
737 if (p->fullpath &&
738 prefix == p->fullpath[0])
739 {
740 if ((!SH_FFLAG_VISITED_SET(p->fflags))
741 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
742 {
743 handler(p->fullpath);
744
745 if (!SH_FFLAG_CHECKED_SET(p->fflags))
746 {
747 /* delete */
748 if (tab[i] == p)
749 {
750 tab[i] = p->next;
751 prev = tab[i];
752 next = prev;
753 }
754 else
755 {
756 prev->next = p->next;
757 next = prev->next;
758 }
759
760 p = delete_db_entry(p);
761 }
762 }
763 if (p)
764 {
765 CLEAR_SH_FFLAG_VISITED(p->fflags);
766 CLEAR_SH_FFLAG_CHECKED(p->fflags);
767 }
768 }
769 if (p)
770 prev = p;
771 p = next;
772 }
773 while (p);
774 }
775 }
776 SH_MUTEX_UNLOCK(mutex_hash);
777
778 SL_RET0(_("hash_unvisited_custom"));
779}
780
781
782/**********************************************************************
783 *
784 * delete hash array
785 *
786 **********************************************************************/
787static void hash_kill (sh_file_t *p)
788{
789 SL_ENTER(_("hash_kill"));
790
791 if (p == NULL)
792 SL_RET0(_("hash_kill"));
793
794 if (p->next != NULL)
795 hash_kill (p->next);
796
797 if (p->fullpath)
798 {
799 SH_FREE(p->fullpath);
800 p->fullpath = NULL;
801 }
802 if (p->linkpath)
803 {
804 if (p->linkpath != notalink)
805 SH_FREE(p->linkpath);
806 p->linkpath = NULL;
807 }
808 if (p->attr_string)
809 {
810 SH_FREE(p->attr_string);
811 p->attr_string = NULL;
812 }
813 SH_FREE(p);
814 p = NULL;
815 SL_RET0(_("hash_kill"));
816}
817
818
819/***********************************************************************
820 *
821 * get info out of hash array
822 *
823 ***********************************************************************/
824static sh_file_t * hashsearch (const char * s)
825{
826 sh_file_t * p;
827
828 SL_ENTER(_("hashsearch"));
829
830 if (s)
831 {
832 for (p = tab[hashfunc(s)]; p; p = p->next)
833 if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath)))
834 SL_RETURN( p, _("hashsearch"));
835 }
836 SL_RETURN( NULL, _("hashsearch"));
837}
838
839static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index)
840{
841 sh_file_t * this;
842 sh_file_t * prev = NULL;
843
844 SL_ENTER(_("hashsearch_prev"));
845
846 if (s)
847 {
848 *index = hashfunc(s);
849
850 this = tab[*index];
851
852 prev = this;
853
854 if (this)
855 {
856 do {
857
858 if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
859 {
860 a->prev = prev;
861 a->this = this;
862
863 SL_RETURN( 0, _("hashsearch_prev"));
864 }
865
866 prev = this;
867 this = this->next;
868
869 } while(this);
870 }
871 }
872 SL_RETURN( -1, _("hashsearch"));
873}
874
875
876/***********************************************************************
877 *
878 * insert into hash array
879 *
880 ***********************************************************************/
881static void hashinsert (sh_file_t * s)
882{
883 sh_file_t * p;
884 sh_file_t * q;
885 int key;
886
887 SL_ENTER(_("hashinsert"));
888
889 key = hashfunc(s->fullpath);
890
891 if (tab[key] == NULL)
892 {
893 tab[key] = s;
894 tab[key]->next = NULL;
895 SL_RET0(_("hashinsert"));
896 }
897 else
898 {
899 p = tab[key];
900 while (1)
901 {
902 if (p && p->fullpath &&
903 0 == strcmp(s->fullpath, p->fullpath))
904 {
905 q = p->next;
906 SH_FREE(p->fullpath);
907 if(p->linkpath && p->linkpath != notalink)
908 SH_FREE(p->linkpath);
909 if(p->attr_string)
910 SH_FREE(p->attr_string);
911 memcpy(p, s, sizeof(sh_file_t));
912 p->next = q;
913 SH_FREE(s);
914 s = NULL;
915 SL_RET0(_("hashinsert"));
916 }
917 else if (p && p->next == NULL)
918 {
919 p->next = s;
920 p->next->next = NULL;
921 SL_RET0(_("hashinsert"));
922 }
923 if (p)
924 p = p->next;
925 else /* cannot really happen, but llvm/clang does not know */
926 break;
927 }
928 }
929 /* notreached */
930}
931
932
933/******************************************************************
934 *
935 * Get a single line
936 *
937 ******************************************************************/
938static FILE * sh_fin_fd = NULL;
939
940static int sh_hash_getline (FILE * fd, char * line, int sizeofline)
941{
942 register int n = 0;
943 char * res;
944
945 if (sizeofline < 2) {
946 if (sizeofline > 0) line[0] = '\0';
947 return 0;
948 }
949 res = fgets(line, sizeofline, fd);
950 if (res == NULL)
951 {
952 line[0] = '\0';
953 return -1;
954 }
955 n = strlen(line);
956 if (n > 0) {
957 --n;
958 line[n] = '\0'; /* remove terminating '\n' */
959 }
960 return n;
961}
962
963static void sh_hash_getline_end (void)
964{
965 sl_fclose (FIL__, __LINE__, sh_fin_fd);
966 sh_fin_fd = NULL;
967 return;
968}
969
970/******************************************************************
971 *
972 * ------- Check functions -------
973 *
974 ******************************************************************/
975
976static int IsInit = 0;
977
978
979/******************************************************************
980 *
981 * Fast forward to start of data
982 *
983 ******************************************************************/
984int sh_hash_setdataent (SL_TICKET fd, char * line, int size, const char * file)
985{
986 long i;
987 extern int get_the_fd (SL_TICKET ticket);
988
989 SL_ENTER(_("sh_hash_setdataent"));
990
991 sl_rewind (fd);
992
993 if (sh_fin_fd != NULL)
994 {
995 sl_fclose (FIL__, __LINE__, sh_fin_fd);
996 sh_fin_fd = NULL;
997 }
998
999 sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
1000 if (!sh_fin_fd)
1001 {
1002 dlog(1, FIL__, __LINE__,
1003 _("The file signature database: %s is not readable.\n"),
1004 (NULL == file) ? _("(null)") : file);
1005 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1006 ( (NULL == file) ? _("(null)") : file)
1007 );
1008 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1009 }
1010
1011 while (1)
1012 {
1013 i = sh_hash_getline (sh_fin_fd, line, size);
1014 if (i < 0 )
1015 {
1016 SH_FREE(line);
1017 dlog(1, FIL__, __LINE__,
1018 _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
1019 (NULL == file) ? _("(null)") : file);
1020
1021 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1022 ( (NULL == file) ? _("(null)") : file)
1023 );
1024 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1025 }
1026
1027#if defined(SH_STEALTH)
1028 if (0 == sl_strncmp (line, N_("[SOF]"), 5))
1029#else
1030 if (0 == sl_strncmp (line, _("[SOF]"), 5))
1031#endif
1032 break;
1033 }
1034 SL_RETURN( 1, _("sh_hash_setdataent"));
1035}
1036
1037static int sh_hash_setdataent_old (SL_TICKET fd, char * line, int size,
1038 char * file)
1039{
1040 long i;
1041
1042 SL_ENTER(_("sh_hash_setdataent_old"));
1043
1044 sl_rewind (fd);
1045
1046 while (1)
1047 {
1048 i = sh_unix_getline (fd, line, size-1);
1049 if (i < 0 )
1050 {
1051 SH_FREE(line);
1052 dlog(1, FIL__, __LINE__,
1053 _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
1054 (NULL == file) ? _("(null)") : file);
1055
1056 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1057 ( (NULL == file) ? _("(null)") : file)
1058 );
1059 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1060 }
1061
1062#if defined(SH_STEALTH)
1063 if (0 == sl_strncmp (line, N_("[SOF]"), 5))
1064#else
1065 if (0 == sl_strncmp (line, _("[SOF]"), 5))
1066#endif
1067 break;
1068 }
1069 SL_RETURN( 1, _("sh_hash_setdataent_old"));
1070}
1071
1072/******************************************************************
1073 *
1074 * Read next record
1075 *
1076 ******************************************************************/
1077sh_file_t * sh_hash_getdataent (SL_TICKET fd, char * line, int size)
1078{
1079 sh_file_t * p;
1080 sh_filestore_t ft;
1081 long i;
1082 size_t len;
1083 char * fullpath;
1084 char * linkpath;
1085 char * attr_string = NULL;
1086 char * tmp;
1087
1088 SL_ENTER(_("sh_hash_getdataent"));
1089
1090 (void) fd;
1091
1092 /* Read next record -- Part One
1093 */
1094 p = SH_ALLOC(sizeof(sh_file_t));
1095
1096 i = fread (&ft, sizeof(sh_filestore_t), 1, sh_fin_fd);
1097 /* i = sl_read(fd, &ft, sizeof(sh_filestore_t)); */
1098 /* if ( SL_ISERROR(i) || i == 0) */
1099 if (i < 1)
1100 {
1101 SH_FREE(p);
1102 SL_RETURN( NULL, _("sh_hash_getdataent"));
1103 }
1104
1105 swap_32(&(ft.mode));
1106 swap_32(&(ft.linkmode));
1107 swap_64(&(ft.dev));
1108 swap_64(&(ft.rdev));
1109 swap_32(&(ft.hardlinks));
1110 swap_32(&(ft.ino));
1111 swap_64(&(ft.size));
1112 swap_64(&(ft.atime));
1113 swap_64(&(ft.mtime));
1114 swap_64(&(ft.ctime));
1115 swap_32(&(ft.owner));
1116 swap_32(&(ft.group));
1117#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1118 swap_32(&(ft.attributes));
1119#endif
1120#ifdef OLD_BUG
1121 swap_short(&(ft.mark));
1122#else
1123 ft.mark = *(swap_short(&(ft.mark)));
1124#endif
1125
1126 if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
1127 {
1128 SH_FREE(p);
1129 SL_RETURN( NULL, _("sh_hash_getdataent"));
1130 }
1131
1132 /* Read next record -- Part Two -- Fullpath
1133 */
1134 i = sh_hash_getline (sh_fin_fd, line, size);
1135 if (i <= 0 )
1136 {
1137 SH_FREE(line);
1138 SH_FREE(p);
1139 dlog(1, FIL__, __LINE__,
1140 _("There is a corrupt record in the file signature database: %s\nThe file path is missing.\n"),
1141 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1142 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1143 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1144 file_path('D', 'R'))
1145 );
1146 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1147 }
1148
1149 tmp = unquote_string (line, i);
1150 len = sl_strlen(tmp)+1;
1151 fullpath = SH_ALLOC(len);
1152 (void) sl_strlcpy (fullpath, tmp, len);
1153 if (tmp)
1154 SH_FREE(tmp);
1155 if (fullpath[len-2] == '\n')
1156 fullpath[len-2] = '\0';
1157
1158 /* Read next record -- Part Three -- Linkpath
1159 */
1160 i = sh_hash_getline (sh_fin_fd, line, size);
1161 if (i <= 0 )
1162 {
1163 SH_FREE(line);
1164 SH_FREE(fullpath);
1165 SH_FREE(p);
1166 dlog(1, FIL__, __LINE__,
1167 _("There is a corrupt record in the file signature database: %s\nThe link path (or its placeholder) is missing.\n"),
1168 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1169 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1170 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1171 file_path('D', 'R'))
1172 );
1173 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1174 }
1175
1176 tmp = unquote_string (line, i);
1177
1178 if ( tmp && tmp[0] == '-' &&
1179 (tmp[1] == '\0' || (tmp[1] == '\n' && tmp[2] == '\0')))
1180 {
1181 linkpath = (char *)notalink;
1182 }
1183 else
1184 {
1185 len = sl_strlen(tmp);
1186 linkpath = sh_util_strdup_l(tmp, len);
1187 if (len > 0 && linkpath[len-1] == '\n')
1188 linkpath[len-1] = '\0';
1189 }
1190
1191 if (tmp)
1192 SH_FREE(tmp);
1193
1194 /* Read next record -- Part Four -- attr_string
1195 */
1196 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1197 {
1198 i = sh_hash_getline (sh_fin_fd, line, size);
1199 if (i <= 0 )
1200 {
1201 SH_FREE(line);
1202 SH_FREE(fullpath);
1203 if (linkpath != notalink)
1204 SH_FREE(linkpath);
1205 SH_FREE(p);
1206 dlog(1, FIL__, __LINE__,
1207 _("There is a corrupt record in the file signature database: %s\nThe attribute string is missing.\n"),
1208 (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
1209 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
1210 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1211 file_path('D', 'R'))
1212 );
1213 aud_exit (FIL__, __LINE__,EXIT_FAILURE);
1214 }
1215
1216 tmp = unquote_string (line, i);
1217
1218 len = sl_strlen(tmp)+1;
1219 attr_string = SH_ALLOC(len);
1220 (void) sl_strlcpy (attr_string, tmp, len);
1221 if (tmp)
1222 SH_FREE(tmp);
1223 if (attr_string[len-2] == '\n')
1224 attr_string[len-2] = '\0';
1225 }
1226
1227 /* Read next record -- Part Four -- Decode
1228 */
1229#if defined(SH_STEALTH)
1230 sh_do_decode(fullpath, sl_strlen(fullpath));
1231
1232#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1233 sh_do_decode(ft.c_attributes, sl_strlen(ft.c_attributes));
1234#endif
1235
1236 sh_do_decode(ft.c_mode, sl_strlen(ft.c_mode));
1237 sh_do_decode(ft.c_owner, sl_strlen(ft.c_owner));
1238 sh_do_decode(ft.c_group, sl_strlen(ft.c_group));
1239 sh_do_decode(ft.checksum, sl_strlen(ft.checksum));
1240
1241 /* TXT entries are c_mode[0] != 'l' and do not get decoded
1242 */
1243 if (ft.c_mode[0] == 'l' && linkpath != notalink)
1244 {
1245 sh_do_decode(linkpath, sl_strlen(linkpath));
1246 }
1247
1248 if ((ft.mark & REC_FLAGS_ATTR) != 0)
1249 {
1250 sh_do_decode(attr_string, sl_strlen(attr_string));
1251 }
1252#endif
1253
1254 memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
1255
1256 /* init fflags, such that suid files in
1257 * database are recognized as such
1258 */
1259 {
1260 mode_t mode = (mode_t) ft.mode;
1261
1262 if (S_ISREG(mode) &&
1263 (0 !=(S_ISUID & mode) ||
1264#if defined(HOST_IS_LINUX)
1265 (0 !=(S_ISGID & mode) &&
1266 0 !=(S_IXGRP & mode))
1267#else
1268 0 !=(S_ISGID & mode)
1269#endif
1270 )
1271 )
1272 p->fflags = SH_FFLAG_SUIDCHK;
1273
1274 else
1275 p->fflags = 0;
1276 }
1277
1278 p->modi_mask = 0L;
1279 p->fullpath = fullpath;
1280 p->linkpath = linkpath;
1281
1282 p->attr_string = attr_string;
1283
1284 /* set to an invalid value
1285 */
1286 ft.mark = (REC_MAGIC + 5);
1287
1288 SL_RETURN( p, _("sh_hash_getdataent"));
1289}
1290
1291/******************************************************************
1292 *
1293 * Initialize
1294 *
1295 ******************************************************************/
1296void sh_hash_init ()
1297{
1298
1299#define FGETS_BUF 16384
1300
1301 sh_file_t * p;
1302 SL_TICKET fd;
1303 long i;
1304 int count = 0;
1305 char * line = NULL;
1306
1307#if defined(WITH_GPG) || defined(WITH_PGP)
1308 extern int get_the_fd (SL_TICKET ticket);
1309
1310 SL_TICKET fdTmp = (-1);
1311#endif
1312 char hashbuf[KEYBUF_SIZE];
1313
1314 volatile int retval = 0;
1315 volatile int exitval = EXIT_SUCCESS;
1316
1317 SL_ENTER(_("sh_hash_init"));
1318
1319 SH_MUTEX_LOCK(mutex_hash);
1320
1321 if (IsInit == 1)
1322 {
1323 goto unlock_and_return;
1324 }
1325
1326 fd = (-1);
1327
1328#if defined(SH_WITH_CLIENT)
1329
1330 /* Data file from Server
1331 */
1332
1333 if (fd == (-1) && 0 == sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1334 {
1335 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
1336 fd = sh_forward_req_file(_("DATA"));
1337 if (SL_ISERROR(fd))
1338 {
1339 dlog(1, FIL__, __LINE__,
1340 _("Could not retrieve the file signature database from the server(errnum = %ld).\nPossible reasons include:\n - the server is not running,\n - session key negotiation failed (see the manual for proper setup), or\n - the server cannot access the file.\n"), fd);
1341 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1342 sh.prg_name);
1343 retval = 1; exitval = EXIT_FAILURE;
1344 goto unlock_and_return;
1345 }
1346 sl_rewind (fd);
1347
1348 sl_strlcpy (sh.data.hash,
1349 sh_tiger_hash (file_path('D', 'R'),
1350 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
1351 KEY_LEN+1);
1352 sl_rewind (fd);
1353 }
1354 else
1355#endif
1356 /* Local data file
1357 */
1358
1359 if (fd == (-1))
1360 {
1361 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__,
1362 file_path('D', 'R'), SL_YESPRIV)))
1363 {
1364 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"),
1365 file_path('D', 'R')));
1366 dlog(1, FIL__, __LINE__,
1367 _("Could not open the local file signature database for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"),
1368 sl_get_errmsg(), fd, (int) sl_ret_euid());
1369 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1370 sh.prg_name);
1371 retval = 1; exitval = EXIT_FAILURE;
1372 goto unlock_and_return;
1373 }
1374
1375 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
1376 file_path('D', 'R')));
1377
1378 if (0 != sl_strncmp(sh.data.hash,
1379 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1380 hashbuf, sizeof(hashbuf)),
1381 KEY_LEN)
1382 && sh.flag.checkSum != SH_CHECK_INIT)
1383 {
1384 dlog(1, FIL__, __LINE__,
1385 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
1386 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1387 hashbuf, sizeof(hashbuf)));
1388 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1389 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1390 file_path('D', 'R') )
1391 );
1392 retval = 1; exitval = EXIT_FAILURE;
1393 goto unlock_and_return;
1394 }
1395 sl_rewind (fd);
1396
1397 } /* new 1.4.8 */
1398
1399 if (sig_termfast == 1) /* SIGTERM */
1400 {
1401 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1402 --sig_raised; --sig_urgent;
1403 retval = 1; exitval = EXIT_SUCCESS;
1404 goto unlock_and_return;
1405 }
1406
1407#if defined(WITH_GPG) || defined(WITH_PGP)
1408
1409 /* extract the data and copy to temporary file
1410 */
1411 fdTmp = sh_gpg_extract_signed(fd);
1412
1413 if (sig_termfast == 1) /* SIGTERM */
1414 {
1415 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1416 --sig_raised; --sig_urgent;
1417 retval = 1; exitval = EXIT_SUCCESS;
1418 goto unlock_and_return;
1419 }
1420
1421 sl_close(fd);
1422 fd = fdTmp;
1423
1424 /* Validate signature of open file.
1425 */
1426 if (0 != sh_gpg_check_sign (0, fd, 2))
1427 {
1428 retval = 1; exitval = EXIT_FAILURE;
1429 goto unlock_and_return;
1430 }
1431 sl_rewind (fd);
1432#endif
1433
1434 line = SH_ALLOC(MAX_PATH_STORE+2);
1435
1436 /* fast forward to start of data
1437 */
1438 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
1439
1440 for (i = 0; i < TABSIZE; ++i)
1441 tab[i] = NULL;
1442
1443 while (1)
1444 {
1445 if (sig_termfast == 1) /* SIGTERM */
1446 {
1447 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1448 --sig_raised; --sig_urgent;
1449 retval = 1; exitval = EXIT_SUCCESS;
1450 SH_FREE(line);
1451 line = NULL;
1452 goto unlock_and_return;
1453 }
1454
1455 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
1456 if (p != NULL)
1457 {
1458 hashinsert (p);
1459 ++count;
1460 }
1461 else
1462 break;
1463 }
1464
1465 /* Initialization completed.
1466 */
1467 IsInit = 1;
1468
1469 if (line != NULL)
1470 SH_FREE(line);
1471
1472 /* Always keep db in memory, so we have no open file
1473 */
1474 sl_close (fd);
1475 sh_hash_getline_end();
1476 /* fd = -1; */
1477
1478 unlock_and_return:
1479 ; /* 'label at end of compound statement */
1480 SH_MUTEX_UNLOCK(mutex_hash);
1481 if (retval == 0)
1482 {
1483 SL_RET0(_("sh_hash_init"));
1484 }
1485 aud_exit (FIL__, __LINE__, exitval);
1486}
1487
1488/*****************************************************************
1489 *
1490 * delete hash array
1491 *
1492 *****************************************************************/
1493void sh_hash_hashdelete ()
1494{
1495 int i;
1496
1497 SL_ENTER(_("sh_hash_hashdelete"));
1498
1499 /* need deadlock detection here if called from exit handler
1500 */
1501 SH_MUTEX_TRYLOCK(mutex_hash);
1502
1503 if (IsInit == 0)
1504 goto unlock_and_exit;
1505
1506 for (i = 0; i < TABSIZE; ++i)
1507 if (tab[i] != NULL)
1508 {
1509 hash_kill (tab[i]);
1510 tab[i] = NULL;
1511 }
1512 IsInit = 0;
1513
1514 unlock_and_exit:
1515 ; /* 'label at end of compound statement */
1516 SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash);
1517
1518 SL_RET0(_("sh_hash_hashdelete"));
1519}
1520
1521/******************************************************************
1522 *
1523 * Insert a file into the database.
1524 *
1525 ******************************************************************/
1526static int pushdata_isfirst = 1;
1527static SL_TICKET pushdata_fd = -1;
1528
1529static int pushdata_stdout = S_FALSE;
1530
1531static char * sh_db_version_string = NULL;
1532
1533int sh_hash_pushdata_stdout (const char * str)
1534{
1535 if (!str)
1536 { pushdata_stdout = S_TRUE; return 0; }
1537 return -1;
1538}
1539
1540int sh_hash_version_string(const char * str)
1541{
1542 if (str)
1543 {
1544 if (sh_db_version_string != NULL) {
1545 SH_FREE(sh_db_version_string);
1546 }
1547 if (0 == sl_strncmp(str, _("NULL"), 4))
1548 {
1549 sh_db_version_string = NULL;
1550 return 0;
1551 }
1552 sh_db_version_string = sh_util_strdup(str);
1553 return 0;
1554 }
1555 return -1;
1556}
1557
1558static int sh_loosedircheck = S_FALSE;
1559
1560int sh_hash_loosedircheck(const char * str)
1561{
1562 return sh_util_flagval(str, &sh_loosedircheck);
1563}
1564
1565
1566static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
1567{
1568 static long p_count = 0;
1569
1570 int status = 0;
1571
1572 char * tmp;
1573 size_t tmp_len = 0;
1574 size_t old_len = 0;
1575 size_t path_len = 0;
1576
1577 sh_filestore_t p;
1578
1579 struct stat sbuf;
1580
1581 char * fullpath = NULL;
1582 char * linkpath = NULL;
1583 char * attr_string = NULL;
1584
1585 char * line = NULL;
1586
1587 char timestring[81];
1588
1589#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1590 int i;
1591#endif
1592
1593 SL_ENTER(_("sh_hash_pushdata_int"));
1594
1595 fullpath = SH_ALLOC(MAX_PATH_STORE+1);
1596 linkpath = SH_ALLOC(MAX_PATH_STORE+1);
1597
1598 linkpath[0] = '-';
1599 linkpath[1] = '\0';
1600 fullpath[0] = '-';
1601 fullpath[1] = '\0';
1602
1603 if (!buf) {
1604 memset(&p, '\0', sizeof(sh_filestore_t));
1605 }
1606
1607 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1608 {
1609 dlog(1, FIL__, __LINE__,
1610 _("You cannot write the database to stdout when you use update rather than init.\n"));
1611 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1612 _("Writing database to stdout with update"),
1613 sh.prg_name,
1614 _("sh_hash_pushdata_int"));
1615 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1616 }
1617
1618 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1619 {
1620 dlog(1, FIL__, __LINE__,
1621 _("You cannot write the database to stdout when running with suid privileges.\n"));
1622 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1623 _("Writing database to stdout when suid"),
1624 sh.prg_name,
1625 _("sh_hash_pushdata_int"));
1626 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1627 }
1628
1629
1630 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
1631 ( (NULL == file_path('D', 'W')) ||
1632 (0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
1633 {
1634 dlog(1, FIL__, __LINE__,
1635 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1636 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1637 _("No local path for database specified"),
1638 sh.prg_name,
1639 _("sh_hash_pushdata_int"));
1640 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1641 }
1642
1643
1644 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
1645 {
1646 /* Warn that file already exists; file_path != NULL here because
1647 * checked above
1648 */
1649 if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
1650 {
1651 if (sh.flag.update == S_FALSE)
1652 {
1653 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1654 file_path('D', 'W'));
1655 }
1656 }
1657 }
1658
1659
1660 if (sh.flag.update == S_FALSE)
1661 {
1662 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1663 {
1664 if ( SL_ISERROR(pushdata_fd = sl_open_write(FIL__, __LINE__,
1665 file_path('D', 'W'),
1666 SL_YESPRIV)))
1667 {
1668 SH_FREE(fullpath);
1669 SH_FREE(linkpath);
1670 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1671 geteuid(), file_path('D', 'W'));
1672 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1673 }
1674
1675 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1676 {
1677 SH_FREE(fullpath);
1678 SH_FREE(linkpath);
1679 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1680 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1681 file_path('D', 'W'));
1682 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1683 }
1684
1685 if ( SL_ISERROR(status = sl_forward(pushdata_fd)))
1686 {
1687 SH_FREE(fullpath);
1688 SH_FREE(linkpath);
1689 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1690 _("Failed to seek to end of baseline database"),
1691 _("sh_hash_pushdata_int"),
1692 file_path('D', 'W'));
1693 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1694 }
1695 }
1696 }
1697 else /* update == TRUE */
1698 {
1699 if (pushdata_isfirst == 1)
1700 {
1701 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
1702 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(FIL__, __LINE__,
1703 file_path('D', 'W'),
1704 SL_YESPRIV))){
1705 SH_FREE(fullpath);
1706 SH_FREE(linkpath);
1707 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1708 geteuid(), file_path('D', 'W'));
1709 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1710 }
1711
1712 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1713 {
1714 SH_FREE(fullpath);
1715 SH_FREE(linkpath);
1716 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1717 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1718 file_path('D', 'W'));
1719 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1720 }
1721
1722 line = SH_ALLOC(MAX_PATH_STORE+1);
1723 if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line,
1724 MAX_PATH_STORE,
1725 file_path('D', 'W'))))
1726 {
1727 SH_FREE(fullpath);
1728 SH_FREE(linkpath);
1729 SH_FREE(line);
1730 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1731 }
1732 SH_FREE(line);
1733 }
1734 }
1735
1736 if (buf != NULL && buf->fullpath != NULL) {
1737
1738 old_len = sl_strlen(buf->fullpath);
1739#if defined(SH_STEALTH)
1740 sh_do_encode(buf->fullpath, old_len);
1741#endif
1742 tmp = quote_string(buf->fullpath, old_len);
1743 tmp_len = sl_strlen(tmp);
1744#if defined(SH_STEALTH)
1745 sh_do_decode(buf->fullpath, old_len);
1746#endif
1747
1748 if (tmp && tmp_len <= MAX_PATH_STORE)
1749 {
1750 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1751 }
1752 else
1753 {
1754 char hashbuf[KEYBUF_SIZE];
1755
1756 sl_strlcpy(fullpath,
1757 sh_tiger_hash (buf->fullpath,
1758 TIGER_DATA, old_len,
1759 hashbuf, sizeof(hashbuf)),
1760 KEY_LEN+1);
1761 }
1762 if (tmp) SH_FREE(tmp);
1763 }
1764
1765 path_len = sl_strlen(fullpath);
1766#if defined(SH_STEALTH)
1767 sh_do_encode(fullpath, path_len);
1768#endif
1769
1770 tmp = quote_string(fullpath, path_len);
1771 if (tmp) {
1772 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1773 SH_FREE(tmp);
1774 }
1775
1776 /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded
1777 */
1778 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
1779 {
1780
1781 old_len = sl_strlen(buf->link_path);
1782#if defined(SH_STEALTH)
1783 if (buf->c_mode[0] == 'l')
1784 sh_do_encode(buf->link_path, old_len);
1785#endif
1786 tmp = quote_string(buf->link_path, old_len);
1787 tmp_len = sl_strlen(tmp);
1788#if defined(SH_STEALTH)
1789 if (buf->c_mode[0] == 'l')
1790 sh_do_decode(buf->link_path, old_len);
1791#endif
1792
1793 if (tmp && tmp_len <= MAX_PATH_STORE)
1794 {
1795 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
1796 }
1797 else
1798 {
1799 char hashbuf[KEYBUF_SIZE];
1800 sl_strlcpy(linkpath,
1801 sh_tiger_hash (buf->link_path,
1802 TIGER_DATA, old_len,
1803 hashbuf, sizeof(hashbuf)),
1804 KEY_LEN+1);
1805 }
1806 if (tmp) SH_FREE(tmp);
1807
1808 path_len = sl_strlen(linkpath);
1809#if defined(SH_STEALTH)
1810 if (buf->c_mode[0] == 'l')
1811 sh_do_encode(linkpath, path_len);
1812#endif
1813 tmp = quote_string(linkpath, path_len);
1814 if (tmp)
1815 {
1816 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1817 SH_FREE(tmp);
1818 }
1819 }
1820
1821 if (buf != NULL && buf->attr_string != NULL)
1822 {
1823 old_len = sl_strlen(buf->attr_string);
1824#if defined(SH_STEALTH)
1825 sh_do_encode(buf->attr_string, old_len);
1826#endif
1827 tmp = quote_string(buf->attr_string, old_len);
1828 if (tmp)
1829 {
1830 attr_string = tmp;
1831 tmp = NULL;
1832 }
1833#if defined(SH_STEALTH)
1834 sh_do_decode(buf->attr_string, old_len);
1835#endif
1836 }
1837
1838
1839 if (buf != NULL) {
1840 p.mark = REC_MAGIC;
1841 if (attr_string)
1842 p.mark |= REC_FLAGS_ATTR;
1843 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
1844 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1845 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1846 if (fileHash) {
1847 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1848 }
1849#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1850 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1851#else
1852 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1853 p.c_attributes[ATTRBUF_USED] = '\0';
1854#endif
1855
1856#if defined(SH_STEALTH)
1857 sh_do_encode(p.c_mode, sl_strlen(p.c_mode));
1858 sh_do_encode(p.c_owner, sl_strlen(p.c_owner));
1859 sh_do_encode(p.c_group, sl_strlen(p.c_group));
1860 sh_do_encode(p.checksum, sl_strlen(p.checksum));
1861
1862 sh_do_encode(p.c_attributes, sl_strlen(p.c_attributes));
1863#endif
1864
1865#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1866 p.attributes = (UINT32) buf->attributes;
1867#else
1868 p.attributes = 0;
1869#endif
1870 p.linkmode = (UINT32) buf->linkmode;
1871 p.hardlinks = (UINT32) buf->hardlinks;
1872 p.dev = (UINT64) buf->dev;
1873 p.rdev = (UINT64) buf->rdev;
1874 p.mode = (UINT32) buf->mode;
1875 p.ino = (UINT32) buf->ino;
1876 p.size = (UINT64) buf->size;
1877 p.mtime = (UINT64) buf->mtime;
1878 p.atime = (UINT64) buf->atime;
1879 p.ctime = (UINT64) buf->ctime;
1880 p.owner = (UINT32) buf->owner;
1881 p.group = (UINT32) buf->group;
1882
1883 swap_32(&(p.mode));
1884 swap_32(&(p.linkmode));
1885 swap_64(&(p.dev));
1886 swap_64(&(p.rdev));
1887 swap_32(&(p.hardlinks));
1888 swap_32(&(p.ino));
1889 swap_64(&(p.size));
1890 swap_64(&(p.atime));
1891 swap_64(&(p.mtime));
1892 swap_64(&(p.ctime));
1893 swap_32(&(p.owner));
1894 swap_32(&(p.group));
1895 swap_32(&(p.attributes));
1896
1897#ifdef OLD_BUG
1898 swap_short(&(p.mark));
1899#else
1900 p.mark = *(swap_short(&(p.mark)));
1901#endif
1902 }
1903
1904 /* write the start marker
1905 */
1906 if (pushdata_isfirst == 1)
1907 {
1908 if (sh.flag.update == S_FALSE)
1909 {
1910 if (sh_db_version_string != NULL)
1911 {
1912 if (pushdata_stdout == S_FALSE)
1913 {
1914 sl_write (pushdata_fd, _("\n#Host "), 7);
1915 sl_write (pushdata_fd, sh.host.name,
1916 sl_strlen(sh.host.name));
1917 sl_write (pushdata_fd, _(" Version "), 9);
1918 sl_write (pushdata_fd, sh_db_version_string,
1919 sl_strlen(sh_db_version_string));
1920 sl_write (pushdata_fd, _(" Date "), 6);
1921 (void) sh_unix_time(0, timestring, sizeof(timestring));
1922 sl_write (pushdata_fd, timestring, strlen(timestring));
1923 sl_write (pushdata_fd, "\n", 1);
1924 } else {
1925 printf ("%s",_("\n#Host "));
1926 printf ("%s", sh.host.name);
1927 printf ("%s",_(" Version "));
1928 printf ("%s", sh_db_version_string);
1929 printf ("%s",_(" Date "));
1930 (void) sh_unix_time(0, timestring, sizeof(timestring));
1931 printf ("%s\n", timestring);
1932 }
1933 }
1934
1935 if (pushdata_stdout == S_FALSE)
1936 {
1937#if defined(SH_STEALTH)
1938 sl_write (pushdata_fd, "\n", 1);
1939 sl_write_line (pushdata_fd, N_("[SOF]"), 5);
1940#else
1941 sl_write_line (pushdata_fd, _("\n[SOF]"), 6);
1942#endif
1943 }
1944 else
1945 {
1946#if defined(SH_STEALTH)
1947 printf ("\n%s\n", N_("[SOF]"));
1948#else
1949 printf ("%s\n", _("\n[SOF]"));
1950#endif
1951 }
1952 }
1953 pushdata_isfirst = 0;
1954 }
1955
1956 if (pushdata_stdout == S_FALSE)
1957 {
1958 sl_write (pushdata_fd, &p, sizeof(sh_filestore_t));
1959 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1960 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
1961 if (attr_string)
1962 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
1963 } else {
1964 if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
1965 {
1966 printf ("%s\n", fullpath);
1967 printf ("%s\n", linkpath);
1968 if (attr_string)
1969 printf ("%s\n", attr_string);
1970 }
1971 else
1972 {
1973 perror(_("Error writing database"));
1974 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1975 }
1976 }
1977
1978 ++p_count;
1979
1980 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1981 {
1982 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1983 {
1984 sl_close (pushdata_fd);
1985 pushdata_fd = -1;
1986 }
1987 }
1988
1989 SH_FREE(fullpath);
1990 SH_FREE(linkpath);
1991 if (attr_string)
1992 SH_FREE(attr_string);
1993
1994 SL_RET0(_("sh_hash_pushdata_int"));
1995}
1996
1997SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1998
1999void sh_hash_pushdata (file_type * buf, char * fileHash)
2000{
2001 SH_MUTEX_LOCK(mutex_writeout);
2002 sh_hash_pushdata_int (buf, fileHash);
2003 SH_MUTEX_UNLOCK(mutex_writeout);
2004 return;
2005}
2006
2007
2008int sh_hash_writeout()
2009{
2010 sh_file_t * p;
2011 int i;
2012 file_type * f;
2013 char fileHash[KEY_LEN + 1];
2014
2015 SL_ENTER(_("sh_hash_writeout"));
2016
2017 if (S_TRUE == file_is_remote())
2018 {
2019 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
2020 _("Baseline database is remote"), _("sh_hash_writeout"));
2021 SL_RETURN (1, _("sh_hash_writeout"));
2022 }
2023
2024 SH_MUTEX_LOCK(mutex_writeout);
2025 if (!SL_ISERROR(pushdata_fd))
2026 {
2027 sl_close(pushdata_fd);
2028 pushdata_fd = -1;
2029 }
2030 pushdata_isfirst = 1;
2031
2032
2033 SH_MUTEX_LOCK(mutex_hash);
2034 for (i = 0; i < TABSIZE; ++i)
2035 {
2036 for (p = tab[i]; p; p = p->next)
2037 {
2038 f = sh_hash_create_ft (p, fileHash);
2039 sh_hash_pushdata_int (f, fileHash);
2040 if (f->attr_string) SH_FREE(f->attr_string);
2041 if (f->link_path) SH_FREE(f->link_path);
2042 SH_FREE(f);
2043 }
2044 }
2045 SH_MUTEX_UNLOCK(mutex_hash);
2046
2047 if (!SL_ISERROR(pushdata_fd))
2048 {
2049 sl_close(pushdata_fd);
2050 pushdata_fd = -1;
2051 }
2052 pushdata_isfirst = 1;
2053 SH_MUTEX_UNLOCK(mutex_writeout);
2054
2055 SL_RETURN (0, _("sh_hash_writeout"));
2056}
2057
2058
2059/*********************************************************************
2060 *
2061 * Check whether a file is present in the database.
2062 *
2063 *********************************************************************/
2064static sh_file_t * sh_hash_have_it_int (const char * newname)
2065{
2066 sh_file_t * p;
2067 char hashbuf[KEYBUF_SIZE];
2068
2069 SL_ENTER(_("sh_hash_have_it_int"));
2070
2071 if (newname == NULL)
2072 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
2073
2074 if (sl_strlen(newname) <= MAX_PATH_STORE)
2075 p = hashsearch(newname);
2076 else
2077 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2078 hashbuf, sizeof(hashbuf)) );
2079 if (p == NULL)
2080 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
2081
2082 SL_RETURN( (p), _("sh_hash_have_it_int"));
2083}
2084
2085int sh_hash_have_it (const char * newname)
2086{
2087 sh_file_t * p;
2088 int retval;
2089
2090 if (IsInit != 1)
2091 sh_hash_init();
2092
2093 SH_MUTEX_LOCK(mutex_hash);
2094
2095 retval = 0;
2096
2097 p = sh_hash_have_it_int (newname);
2098
2099 if (!p)
2100 retval = (-1);
2101 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
2102 (p->modi_mask & MODI_CHK) != 0 &&
2103 (p->modi_mask & MODI_MOD) != 0)
2104 retval = 1;
2105 SH_MUTEX_UNLOCK(mutex_hash);
2106
2107 return retval;
2108}
2109
2110int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash)
2111{
2112 sh_file_t * p;
2113 int retval;
2114
2115 if (IsInit != 1)
2116 sh_hash_init();
2117
2118 tmpFile->link_path = NULL;
2119 tmpFile->attr_string = NULL;
2120
2121 SH_MUTEX_LOCK(mutex_hash);
2122
2123 retval = (-1);
2124
2125 p = sh_hash_have_it_int (newname);
2126 if (p)
2127 {
2128 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
2129 if (p->linkpath)
2130 tmpFile->link_path = sh_util_strdup (p->linkpath);
2131 tmpFile->size = p->theFile.size;
2132 tmpFile->mtime = p->theFile.mtime;
2133 tmpFile->ctime = p->theFile.ctime;
2134 tmpFile->atime = p->theFile.atime;
2135
2136 if (NULL != fileHash)
2137 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
2138
2139 tmpFile->attr_string = NULL;
2140 retval = 0;
2141 }
2142 SH_MUTEX_UNLOCK(mutex_hash);
2143
2144 return retval;
2145}
2146
2147int sh_hash_getflags (char * filename)
2148{
2149 sh_file_t * p;
2150 int retval;
2151
2152 if (IsInit != 1)
2153 sh_hash_init();
2154
2155 SH_MUTEX_LOCK(mutex_hash);
2156 p = sh_hash_have_it_int (filename);
2157 if (p)
2158 retval = p->fflags;
2159 else
2160 retval = -1;
2161 SH_MUTEX_UNLOCK(mutex_hash);
2162 return retval;
2163}
2164
2165int sh_hash_setflags (char * filename, int flags)
2166{
2167 sh_file_t * p;
2168 int retval;
2169
2170 if (IsInit != 1)
2171 sh_hash_init();
2172
2173 SH_MUTEX_LOCK(mutex_hash);
2174 p = sh_hash_have_it_int (filename);
2175 if (p)
2176 {
2177 p->fflags = flags;
2178 retval = 0;
2179 }
2180 else
2181 retval = -1;
2182 SH_MUTEX_UNLOCK(mutex_hash);
2183 return retval;
2184}
2185
2186/* needs lock to be threadsafe
2187 */
2188void sh_hash_addflag (char * filename, int flag_to_set)
2189{
2190 sh_file_t * p;
2191
2192 if (IsInit != 1)
2193 sh_hash_init();
2194
2195 SH_MUTEX_LOCK(mutex_hash);
2196 p = sh_hash_have_it_int (filename);
2197 if (p)
2198 {
2199 p->fflags |= flag_to_set;
2200 }
2201 SH_MUTEX_UNLOCK(mutex_hash);
2202 return;
2203}
2204
2205/*****************************************************************
2206 *
2207 * Set a file's status to 'visited'. This is required for
2208 * files that should be ignored, and may be present in the
2209 * database, but not on disk.
2210 *
2211 *****************************************************************/
2212static int sh_hash_set_visited_int (char * newname, int flag)
2213{
2214 sh_file_t * p;
2215 char hashbuf[KEYBUF_SIZE];
2216 int retval;
2217
2218 SL_ENTER(_("sh_hash_set_visited_int"));
2219
2220 if (newname == NULL)
2221 SL_RETURN((-1), _("sh_hash_set_visited_int"));
2222
2223 if (IsInit != 1)
2224 sh_hash_init();
2225
2226 SH_MUTEX_LOCK(mutex_hash);
2227
2228 if (sl_strlen(newname) <= MAX_PATH_STORE)
2229 p = hashsearch(newname);
2230 else
2231 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2232 hashbuf, sizeof(hashbuf)));
2233
2234 if (p)
2235 {
2236 if (flag == SH_FFLAG_CHECKED)
2237 {
2238 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2239 CLEAR_SH_FFLAG_VISITED(p->fflags);
2240 SET_SH_FFLAG_CHECKED(p->fflags);
2241 }
2242 else
2243 {
2244 SET_SH_FFLAG_VISITED(p->fflags);
2245 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2246 if (flag == SH_FFLAG_REPORTED)
2247 SET_SH_FFLAG_REPORTED(p->fflags);
2248 else
2249 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2250 }
2251 retval = 0;
2252 }
2253 else
2254 retval = -1;
2255
2256 SH_MUTEX_UNLOCK(mutex_hash);
2257 SL_RETURN((retval), _("sh_hash_set_visited_int"));
2258}
2259
2260
2261/* cause the record to be deleted without a 'missing' message
2262 */
2263int sh_hash_set_missing (char * newname)
2264{
2265 int i;
2266 SL_ENTER(_("sh_hash_set_missing"));
2267
2268 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
2269
2270 if (sh.flag.checkSum != SH_CHECK_INIT) {
2271 sh_hash_remove(newname);
2272 }
2273
2274 SL_RETURN(i, _("sh_hash_set_missing"));
2275}
2276
2277/* mark the file as visited and reported
2278 */
2279int sh_hash_set_visited (char * newname)
2280{
2281 int i;
2282 SL_ENTER(_("sh_hash_set_visited"));
2283 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
2284 SL_RETURN(i, _("sh_hash_set_visited"));
2285}
2286
2287/* mark the file as visited and NOT reported
2288 * used to avoid deletion of file from internal database
2289 */
2290int sh_hash_set_visited_true (char * newname)
2291{
2292 int i;
2293 SL_ENTER(_("sh_hash_set_visited_true"));
2294 i = sh_hash_set_visited_int(newname, 0);
2295 SL_RETURN(i, _("sh_hash_set_visited_true"));
2296}
2297
2298
2299/******************************************************************
2300 *
2301 * Data entry for arbitrary data into database
2302 *
2303 ******************************************************************/
2304
2305void sh_hash_push2db (const char * key, struct store2db * save)
2306{
2307 int i = 0;
2308 char * p;
2309 char i2h[2];
2310 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2311
2312 int size = save->size;
2313 unsigned char * str = save->str;
2314
2315
2316 tmpFile->attr_string = NULL;
2317 tmpFile->link_path = NULL;
2318
2319 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
2320 tmpFile->size = save->val0;
2321 tmpFile->mtime = save->val1;
2322 tmpFile->ctime = save->val2;
2323 tmpFile->atime = save->val3;
2324
2325 tmpFile->mode = 0;
2326 tmpFile->owner = 0;
2327 tmpFile->group = 0;
2328 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
2329 sl_strlcpy(tmpFile->c_group, _("root"), 5);
2330
2331 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2332 {
2333 tmpFile->c_mode[0] = 'l';
2334 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
2335 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
2336 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
2337 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
2338 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
2339 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
2340 for (i = 0; i < size; ++i)
2341 {
2342 p = sh_util_charhex (str[i],i2h);
2343 tmpFile->link_path[2*i] = p[0];
2344 tmpFile->link_path[2*i+1] = p[1];
2345 tmpFile->link_path[2*i+2] = '\0';
2346 }
2347 }
2348 else
2349 {
2350 for (i = 0; i < 10; ++i)
2351 tmpFile->c_mode[i] = '-';
2352 tmpFile->c_mode[10] = '\0';
2353 tmpFile->link_path = sh_util_strdup("-");
2354 }
2355
2356 if (sh.flag.checkSum == SH_CHECK_INIT)
2357 sh_hash_pushdata (tmpFile,
2358 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
2359 else
2360 sh_hash_pushdata_memory (tmpFile,
2361 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
2362
2363 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2364 SH_FREE(tmpFile);
2365 return;
2366}
2367
2368extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2369
2370char * sh_hash_db2pop (const char * key, struct store2db * save)
2371{
2372 size_t len;
2373 char * p;
2374 int i;
2375 char * retval = NULL;
2376 char fileHash[KEY_LEN+1];
2377 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
2378
2379 save->size = 0;
2380
2381 if (0 == sh_hash_get_it (key, tmpFile, fileHash))
2382 {
2383 save->val0 = tmpFile->size;
2384 save->val1 = tmpFile->mtime;
2385 save->val2 = tmpFile->ctime;
2386 save->val3 = tmpFile->atime;
2387
2388 sl_strlcpy(save->checksum, fileHash, KEY_LEN+1);
2389
2390 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
2391 {
2392 len = strlen(tmpFile->link_path);
2393
2394 p = SH_ALLOC((len/2)+1);
2395 i = sh_util_hextobinary (p, tmpFile->link_path, len);
2396
2397 if (i == 0)
2398 {
2399 save->size = (len/2);
2400 p[save->size] = '\0';
2401 retval = p;
2402 }
2403 else
2404 {
2405 SH_FREE(p);
2406 save->size = 0;
2407 }
2408 }
2409 else
2410 {
2411 save->size = 0;
2412 }
2413 }
2414 else
2415 {
2416 save->size = -1;
2417 save->val0 = 0;
2418 save->val1 = 0;
2419 save->val2 = 0;
2420 save->val3 = 0;
2421 }
2422 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2423 SH_FREE(tmpFile);
2424 return retval;
2425}
2426
2427
2428
2429
2430/******************************************************************
2431 *
2432 * Data entry in hash table
2433 *
2434 ******************************************************************/
2435sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2436{
2437 sh_file_t * fp;
2438 sh_filestore_t p;
2439
2440 size_t len;
2441 char * fullpath;
2442 char * linkpath;
2443 char * attr_string = NULL;
2444 char hashbuf[KEYBUF_SIZE];
2445
2446 SL_ENTER(_("sh_hash_push_int"));
2447
2448 fp = SH_ALLOC(sizeof(sh_file_t));
2449
2450 p.mark = REC_MAGIC;
2451 if (buf->attr_string)
2452 p.mark |= REC_FLAGS_ATTR;
2453 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2454 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2455 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2456 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
2457#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2458 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2459#endif
2460
2461#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2462 p.attributes = (UINT32) buf->attributes;
2463#endif
2464 p.linkmode = (UINT32) buf->linkmode;
2465 p.hardlinks = (UINT32) buf->hardlinks;
2466 p.dev = (UINT64) buf->dev;
2467 p.rdev = (UINT64) buf->rdev;
2468 p.mode = (UINT32) buf->mode;
2469 p.ino = (UINT32) buf->ino;
2470 p.size = (UINT64) buf->size;
2471 p.mtime = (UINT64) buf->mtime;
2472 p.atime = (UINT64) buf->atime;
2473 p.ctime = (UINT64) buf->ctime;
2474 p.owner = (UINT32) buf->owner;
2475 p.group = (UINT32) buf->group;
2476
2477 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
2478 fp->fflags = 0; /* init fflags */
2479 fp->modi_mask = 0L;
2480
2481 if (buf->attr_string)
2482 attr_string = sh_util_strdup(buf->attr_string);
2483 fp->attr_string = attr_string;
2484
2485 len = sl_strlen(buf->fullpath);
2486 if (len <= MAX_PATH_STORE)
2487 {
2488 fullpath = SH_ALLOC(len+1);
2489 sl_strlcpy(fullpath, buf->fullpath, len+1);
2490 }
2491 else
2492 {
2493 fullpath = SH_ALLOC(KEY_LEN + 1);
2494 sl_strlcpy(fullpath,
2495 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2496 hashbuf, sizeof(hashbuf)),
2497 KEY_LEN+1);
2498 }
2499 fp->fullpath = fullpath;
2500
2501 if (buf->link_path)
2502 {
2503 len = sl_strlen(buf->link_path);
2504 if (len <= MAX_PATH_STORE)
2505 {
2506 linkpath = SH_ALLOC(len+1);
2507 sl_strlcpy(linkpath, buf->link_path, len+1);
2508 }
2509 else
2510 {
2511 linkpath = SH_ALLOC(KEY_LEN + 1);
2512 sl_strlcpy(linkpath,
2513 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
2514 hashbuf, sizeof(hashbuf)),
2515 KEY_LEN+1);
2516 }
2517 fp->linkpath = linkpath;
2518 }
2519 else
2520 fp->linkpath = NULL;
2521
2522 SL_RETURN( fp, _("sh_hash_push_int"));
2523}
2524
2525#ifdef HAVE_INTTYPES_H
2526#include <inttypes.h>
2527#else
2528#ifdef HAVE_STDINT_H
2529#include <stdint.h>
2530#endif
2531#endif
2532
2533#ifndef PRIu64
2534#ifdef HAVE_LONG_32
2535#define PRIu64 "llu"
2536#else
2537#define PRIu64 "lu"
2538#endif
2539#endif
2540
2541char * sh_hash_size_format()
2542{
2543 static char form_rval[81];
2544
2545 SL_ENTER(_("sh_hash_size_format"));
2546
2547
2548#ifdef SH_USE_XML
2549 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2550 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
2551#else
2552 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
2553 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
2554#endif
2555
2556 SL_RETURN( form_rval, _("sh_hash_size_format"));
2557}
2558
2559
2560#ifdef SH_USE_XML
2561static char * all_items (file_type * theFile, char * fileHash, int is_new)
2562{
2563 char timstr1c[32];
2564 char timstr1a[32];
2565 char timstr1m[32];
2566
2567 char * tmp_lnk;
2568 char * format;
2569
2570 char * tmp = SH_ALLOC(SH_MSG_BUF);
2571 char * msg = SH_ALLOC(SH_MSG_BUF);
2572
2573 tmp[0] = '\0';
2574 msg[0] = '\0';
2575
2576
2577#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2578 if (is_new)
2579 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2580 else
2581 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
2582 sl_snprintf(tmp, SH_MSG_BUF, format,
2583 theFile->c_mode,
2584 theFile->c_attributes,
2585 (long) theFile->mode,
2586 (long) theFile->attributes
2587 );
2588#else
2589 if (is_new)
2590 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2591 else
2592 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2593
2594 sl_snprintf(tmp, SH_MSG_BUF, format,
2595 theFile->c_mode,
2596 (long) theFile->mode
2597 );
2598#endif
2599 sl_strlcat(msg, tmp, SH_MSG_BUF);
2600
2601 if (is_new)
2602 format = _("hardlinks_new=\"%lu\" ");
2603 else
2604 format = _("hardlinks_old=\"%lu\" ");
2605 sl_snprintf(tmp, SH_MSG_BUF, format,
2606 (unsigned long) theFile->hardlinks);
2607 sl_strlcat(msg, tmp, SH_MSG_BUF);
2608
2609
2610 if (is_new)
2611 format = _("idevice_new=\"%lu\" ");
2612 else
2613 format = _("idevice_old=\"%lu\" ");
2614 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2615 sl_strlcat(msg, tmp, SH_MSG_BUF);
2616
2617
2618 if (is_new)
2619 format = _("inode_new=\"%lu\" ");
2620 else
2621 format = _("inode_old=\"%lu\" ");
2622 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2623 sl_strlcat(msg, tmp, SH_MSG_BUF);
2624
2625 /*
2626 * also report device for prelude
2627 */
2628#if defined(HAVE_LIBPRELUDE)
2629 if (is_new)
2630 format = _("dev_new=\"%lu,%lu\" ");
2631 else
2632 format = _("dev_old=\"%lu,%lu\" ");
2633 sl_snprintf(tmp, SH_MSG_BUF, format,
2634 (unsigned long) major(theFile->dev),
2635 (unsigned long) minor(theFile->dev));
2636 sl_strlcat(msg, tmp, SH_MSG_BUF);
2637#endif
2638
2639
2640 if (is_new)
2641 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2642 else
2643 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
2644 sl_snprintf(tmp, SH_MSG_BUF, format,
2645 theFile->c_owner, (long) theFile->owner);
2646 sl_strlcat(msg, tmp, SH_MSG_BUF);
2647
2648
2649 if (is_new)
2650 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2651 else
2652 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
2653 sl_snprintf(tmp, SH_MSG_BUF, format,
2654 theFile->c_group, (long) theFile->group);
2655 sl_strlcat(msg, tmp, SH_MSG_BUF);
2656
2657
2658 if (is_new)
2659 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2660 (UINT64) 0, (UINT64) theFile->size);
2661 else
2662 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2663 (UINT64) theFile->size, (UINT64) 0);
2664 sl_strlcat(msg, tmp, SH_MSG_BUF);
2665
2666
2667 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2668 if (is_new)
2669 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
2670 else
2671 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2672 sl_strlcat(msg, tmp, SH_MSG_BUF);
2673
2674 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2675 if (is_new)
2676 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
2677 else
2678 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2679 sl_strlcat(msg, tmp, SH_MSG_BUF);
2680
2681 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2682 if (is_new)
2683 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
2684 else
2685 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2686 sl_strlcat(msg, tmp, SH_MSG_BUF);
2687
2688 if (is_new)
2689 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
2690 else
2691 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2692 sl_strlcat(msg, tmp, SH_MSG_BUF);
2693
2694 if (theFile->c_mode[0] == 'l' ||
2695 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2696 {
2697 tmp_lnk = sh_util_safe_name(theFile->link_path);
2698 if (tmp_lnk)
2699 {
2700 if (is_new)
2701 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
2702 else
2703 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
2704 SH_FREE(tmp_lnk);
2705 sl_strlcat(msg, tmp, SH_MSG_BUF);
2706 }
2707 }
2708
2709 if (theFile->attr_string)
2710 {
2711 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2712 if (tmp_lnk)
2713 {
2714 if (is_new)
2715 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
2716 else
2717 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
2718 SH_FREE(tmp_lnk);
2719 sl_strlcat(msg, tmp, SH_MSG_BUF);
2720 }
2721 }
2722
2723
2724 SH_FREE(tmp);
2725 return (msg);
2726}
2727#else
2728static char * all_items (file_type * theFile, char * fileHash, int is_new)
2729{
2730 char timstr1c[32];
2731 char timstr1a[32];
2732 char timstr1m[32];
2733
2734 char * tmp_lnk;
2735 char * format;
2736
2737 char * tmp = SH_ALLOC(SH_MSG_BUF);
2738 char * msg = SH_ALLOC(SH_MSG_BUF);
2739
2740 tmp[0] = '\0';
2741 msg[0] = '\0';
2742
2743
2744#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
2745 if (is_new)
2746 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2747 else
2748 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
2749 sl_snprintf(tmp, SH_MSG_BUF, format,
2750 theFile->c_mode,
2751 theFile->c_attributes,
2752 (long) theFile->mode,
2753 (long) theFile->attributes
2754 );
2755#else
2756 if (is_new)
2757 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2758 else
2759 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2760
2761 sl_snprintf(tmp, SH_MSG_BUF, format,
2762 theFile->c_mode,
2763 (long) theFile->mode
2764 );
2765#endif
2766 sl_strlcat(msg, tmp, SH_MSG_BUF);
2767
2768 if (is_new)
2769 format = _("hardlinks_new=<%lu>, ");
2770 else
2771 format = _("hardlinks_old=<%lu>, ");
2772 sl_snprintf(tmp, SH_MSG_BUF, format,
2773 (unsigned long) theFile->hardlinks);
2774 sl_strlcat(msg, tmp, SH_MSG_BUF);
2775
2776
2777 if (is_new)
2778 format = _("idevice_new=<%lu>, ");
2779 else
2780 format = _("idevice_old=<%lu>, ");
2781 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2782 sl_strlcat(msg, tmp, SH_MSG_BUF);
2783
2784
2785 if (is_new)
2786 format = _("inode_new=<%lu>, ");
2787 else
2788 format = _("inode_old=<%lu>, ");
2789 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2790 sl_strlcat(msg, tmp, SH_MSG_BUF);
2791
2792
2793 /*
2794 * also report device for prelude
2795 */
2796#if defined(HAVE_LIBPRELUDE)
2797 if (is_new)
2798 format = _("dev_new=<%lu,%lu>, ");
2799 else
2800 format = _("dev_old=<%lu,%lu>, ");
2801 sl_snprintf(tmp, SH_MSG_BUF, format,
2802 (unsigned long) major(theFile->dev),
2803 (unsigned long) minor(theFile->dev));
2804 sl_strlcat(msg, tmp, SH_MSG_BUF);
2805#endif
2806
2807 if (is_new)
2808 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2809 else
2810 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
2811 sl_snprintf(tmp, SH_MSG_BUF, format,
2812 theFile->c_owner, (long) theFile->owner);
2813 sl_strlcat(msg, tmp, SH_MSG_BUF);
2814
2815
2816 if (is_new)
2817 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2818 else
2819 format = _("group_old=<%s>, igroup_old=<%ld>, ");
2820 sl_snprintf(tmp, SH_MSG_BUF, format,
2821 theFile->c_group, (long) theFile->group);
2822 sl_strlcat(msg, tmp, SH_MSG_BUF);
2823
2824
2825 if (is_new)
2826 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2827 (UINT64) 0, (UINT64) theFile->size);
2828 else
2829 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
2830 (UINT64) theFile->size, (UINT64) 0);
2831 sl_strlcat(msg, tmp, SH_MSG_BUF);
2832
2833
2834 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
2835 if (is_new)
2836 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
2837 else
2838 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2839 sl_strlcat(msg, tmp, SH_MSG_BUF);
2840
2841 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
2842 if (is_new)
2843 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
2844 else
2845 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2846 sl_strlcat(msg, tmp, SH_MSG_BUF);
2847
2848 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
2849 if (is_new)
2850 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
2851 else
2852 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2853 sl_strlcat(msg, tmp, SH_MSG_BUF);
2854
2855 if (is_new)
2856 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
2857 else
2858 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2859 sl_strlcat(msg, tmp, SH_MSG_BUF);
2860
2861 if (theFile->c_mode[0] == 'l' ||
2862 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
2863 {
2864 tmp_lnk = sh_util_safe_name(theFile->link_path);
2865 if (tmp_lnk)
2866 {
2867 if (is_new)
2868 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
2869 else
2870 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
2871 SH_FREE(tmp_lnk);
2872 sl_strlcat(msg, tmp, SH_MSG_BUF);
2873 }
2874 }
2875
2876 if (theFile->attr_string)
2877 {
2878 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2879 if (tmp_lnk)
2880 {
2881 if (is_new)
2882 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
2883 else
2884 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
2885 SH_FREE(tmp_lnk);
2886 sl_strlcat(msg, tmp, SH_MSG_BUF);
2887 }
2888 }
2889
2890 SH_FREE(tmp);
2891 return (msg);
2892}
2893#endif
2894
2895void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2896{
2897 sh_file_t * p;
2898
2899 SL_ENTER(_("sh_hash_pushdata_memory"));
2900
2901 p = sh_hash_push_int(theFile, fileHash);
2902 if (p)
2903 {
2904 SH_MUTEX_LOCK(mutex_hash);
2905 hashinsert (p);
2906 p->modi_mask = theFile->check_mask;
2907 SH_MUTEX_UNLOCK(mutex_hash);
2908 }
2909
2910 SL_RET0(_("sh_hash_pushdata_memory"));
2911}
2912
2913
2914/*****************************************************************
2915 *
2916 * Compare a file with the database status.
2917 *
2918 *****************************************************************/
2919int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2920 char * policy_override, int severity_override)
2921{
2922 char * msg;
2923 sh_file_t * p;
2924 char * tmp;
2925 char * tmp_path;
2926 char * tmp_lnk;
2927 char * tmp_lnk_old;
2928
2929 char * str;
2930
2931 char timstr1c[32];
2932 char timstr2c[32];
2933 char timstr1a[32];
2934 char timstr2a[32];
2935 char timstr1m[32];
2936 char timstr2m[32];
2937 char linkHash[KEY_LEN+1];
2938 char * linkComp;
2939 int maxcomp;
2940
2941 char change_code[16];
2942 int i;
2943
2944 unsigned long modi_mask;
2945
2946 char log_policy[32];
2947 volatile int log_severity;
2948 char hashbuf[KEYBUF_SIZE];
2949
2950 int retval;
2951
2952 SL_ENTER(_("sh_hash_compdata"));
2953
2954 if (IsInit != 1) sh_hash_init();
2955
2956 if (severity_override < 0)
2957 log_severity = ShDFLevel[class];
2958 else
2959 log_severity = severity_override;
2960
2961 if (policy_override != NULL)
2962 sl_strlcpy (log_policy, policy_override, 32);
2963
2964 /* -------- find the entry for the file ---------------- */
2965
2966 SH_MUTEX_LOCK(mutex_hash);
2967
2968 modi_mask = 0;
2969 retval = 0;
2970
2971 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2972 p = hashsearch(theFile->fullpath);
2973 else
2974 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2975 TIGER_DATA,
2976 sl_strlen(theFile->fullpath),
2977 hashbuf, sizeof(hashbuf))
2978 );
2979
2980
2981 /* --------- Not found in database. ------------
2982 */
2983
2984 if (p == NULL)
2985 {
2986 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2987 {
2988 tmp = sh_util_safe_name(theFile->fullpath);
2989
2990 str = all_items (theFile, fileHash, 1);
2991 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2992 MSG_FI_ADD2,
2993 tmp, str);
2994 SH_FREE(str);
2995
2996 SH_FREE(tmp);
2997 }
2998
2999 if (sh.flag.reportonce == S_TRUE)
3000 SET_SH_FFLAG_REPORTED(theFile->file_reported);
3001
3002 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3003 {
3004 p = sh_hash_push_int(theFile, fileHash);
3005 if (p)
3006 {
3007 hashinsert (p);
3008 p->modi_mask = theFile->check_mask;
3009 }
3010 }
3011
3012 else if (S_TRUE == sh.flag.update)
3013 {
3014 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
3015 {
3016 p = sh_hash_push_int(theFile, fileHash);
3017 if (p)
3018 {
3019 hashinsert (p);
3020 p->modi_mask = theFile->check_mask;
3021 }
3022 }
3023 else
3024 {
3025 retval = 1;
3026 goto unlock_and_return;
3027 }
3028 }
3029
3030 goto unlock_and_return;
3031 }
3032
3033 p->modi_mask = theFile->check_mask;
3034
3035 /* initialize change_code */
3036 for (i = 0; i < 15; ++i)
3037 change_code[i] = '-';
3038 change_code[15] = '\0';
3039
3040 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
3041 theFile->fullpath, fileHash, p->theFile.checksum));
3042
3043 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
3044 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
3045 (theFile->check_mask & MODI_CHK) != 0)
3046 {
3047 if ((theFile->check_mask & MODI_SGROW) == 0)
3048 {
3049 modi_mask |= MODI_CHK;
3050 change_code[0] = 'C';
3051 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
3052 }
3053 else
3054 {
3055 if (0 != strncmp (&fileHash[KEY_LEN + 1],
3056 p->theFile.checksum, KEY_LEN))
3057 {
3058 modi_mask |= MODI_CHK;
3059 change_code[0] = 'C';
3060 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
3061 }
3062 else
3063 {
3064 p->theFile.size = theFile->size;
3065 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3066 }
3067 }
3068 }
3069
3070 if (p->theFile.c_mode[0] == 'l')
3071 {
3072 if (!(theFile->link_path) &&
3073 (theFile->check_mask & MODI_LNK) != 0)
3074 {
3075 linkComp = NULL;
3076 modi_mask |= MODI_LNK;
3077 change_code[1] = 'L';
3078 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3079 }
3080 else
3081 {
3082 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
3083 {
3084 sl_strlcpy(linkHash,
3085 sh_tiger_hash(theFile->link_path,
3086 TIGER_DATA,
3087 sl_strlen(theFile->link_path),
3088 hashbuf, sizeof(hashbuf)),
3089 MAX_PATH_STORE+1);
3090 linkComp = linkHash;
3091 maxcomp = KEY_LEN;
3092 }
3093 else
3094 {
3095 linkComp = theFile->link_path;
3096 maxcomp = MAX_PATH_STORE;
3097 }
3098
3099 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
3100 (theFile->check_mask & MODI_LNK) != 0)
3101 {
3102 modi_mask |= MODI_LNK;
3103 change_code[1] = 'L';
3104 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3105 }
3106 }
3107 }
3108
3109 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
3110 {
3111 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
3112 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
3113 (theFile->check_mask & MODI_RDEV) != 0)
3114 {
3115 modi_mask |= MODI_RDEV;
3116 change_code[2] = 'D';
3117 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
3118 }
3119 }
3120
3121 /* cast to UINT32 in case ino_t is not 32bit
3122 */
3123 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
3124 (theFile->check_mask & MODI_INO) != 0)
3125 {
3126 modi_mask |= MODI_INO;
3127 change_code[3] = 'I';
3128 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
3129 }
3130
3131 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
3132 (theFile->check_mask & MODI_HLN) != 0)
3133 {
3134 modi_mask |= MODI_HLN;
3135 change_code[4] = 'H';
3136 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
3137 }
3138
3139
3140 if ( ( (theFile->mode != p->theFile.mode)
3141#if defined(USE_ACL) || defined(USE_XATTR)
3142 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
3143 (
3144 (theFile->attr_string == NULL && p->attr_string != NULL) ||
3145 (theFile->attr_string != NULL && p->attr_string == NULL) ||
3146 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
3147 )
3148 )
3149#endif
3150#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3151 || (theFile->attributes != p->theFile.attributes)
3152#endif
3153 )
3154 && (theFile->check_mask & MODI_MOD) != 0)
3155 {
3156 modi_mask |= MODI_MOD;
3157 change_code[5] = 'M';
3158 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
3159 /*
3160 * report link path if switch link/no link
3161 */
3162 if ((theFile->check_mask & MODI_LNK) != 0 &&
3163 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
3164 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
3165 {
3166 modi_mask |= MODI_LNK;
3167 change_code[1] = 'L';
3168 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3169 }
3170 }
3171
3172 if ( theFile->owner != (uid_t) p->theFile.owner &&
3173 (theFile->check_mask & MODI_USR) != 0)
3174 {
3175 modi_mask |= MODI_USR;
3176 change_code[6] = 'U';
3177 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
3178 }
3179
3180 if ( theFile->group != (gid_t) p->theFile.group &&
3181 (theFile->check_mask & MODI_GRP) != 0)
3182 {
3183 modi_mask |= MODI_GRP;
3184 change_code[7] = 'G';
3185 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
3186 }
3187
3188
3189 if ( theFile->mtime != (time_t) p->theFile.mtime &&
3190 (theFile->check_mask & MODI_MTM) != 0)
3191 {
3192 modi_mask |= MODI_MTM;
3193 change_code[8] = 'T';
3194 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
3195 }
3196
3197 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3198 theFile->atime != (time_t) p->theFile.atime)
3199 {
3200 modi_mask |= MODI_ATM;
3201 change_code[8] = 'T';
3202 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
3203 }
3204
3205
3206 /* Resetting the access time will set a new ctime. Thus, either we ignore
3207 * the access time or the ctime for NOIGNORE
3208 */
3209 if ( theFile->ctime != (time_t) p->theFile.ctime &&
3210 (theFile->check_mask & MODI_CTM) != 0)
3211 {
3212 modi_mask |= MODI_CTM;
3213 change_code[8] = 'T';
3214 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
3215 }
3216
3217 if ( theFile->size != (off_t) p->theFile.size &&
3218 (theFile->check_mask & MODI_SIZ) != 0)
3219 {
3220 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3221 theFile->size < (off_t) p->theFile.size)
3222 {
3223 modi_mask |= MODI_SIZ;
3224 change_code[9] = 'S';
3225 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
3226 }
3227 }
3228 change_code[10] = '\0';
3229
3230 /* --- Directories special case ---
3231 */
3232 if (p->theFile.c_mode[0] == 'd' &&
3233 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
3234 sh_loosedircheck == S_TRUE)
3235 {
3236 modi_mask = 0;
3237 }
3238
3239 /* --- Report full details. ---
3240 */
3241 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
3242 {
3243 if ((theFile->check_mask & MODI_ATM) == 0)
3244 modi_mask = MASK_READONLY_;
3245 else
3246 modi_mask = MASK_NOIGNORE_;
3247 }
3248
3249 /* --- Report on modified files. ---
3250 */
3251 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
3252 {
3253 tmp = SH_ALLOC(SH_MSG_BUF);
3254 msg = SH_ALLOC(SH_MSG_BUF);
3255 msg[0] = '\0';
3256
3257 if ( ((modi_mask & MODI_MOD) != 0)
3258#if defined(HAVE_LIBPRELUDE)
3259 || ((modi_mask & MODI_USR) != 0)
3260 || ((modi_mask & MODI_GRP) != 0)
3261#endif
3262 )
3263 {
3264#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3265 sl_snprintf(tmp, SH_MSG_BUF,
3266#ifdef SH_USE_XML
3267 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
3268#else
3269 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
3270#endif
3271 p->theFile.c_mode, theFile->c_mode,
3272 p->theFile.c_attributes, theFile->c_attributes
3273#ifdef SH_USE_XML
3274 , (long) p->theFile.mode, (long) theFile->mode,
3275 (long) p->theFile.attributes,
3276 (long) theFile->attributes
3277#endif
3278 );
3279#else
3280#ifdef SH_USE_XML
3281 sl_snprintf(tmp, SH_MSG_BUF,
3282 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
3283 p->theFile.c_mode, theFile->c_mode,
3284 (long) p->theFile.mode, (long) theFile->mode);
3285#else
3286 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
3287 p->theFile.c_mode, theFile->c_mode);
3288#endif
3289#endif
3290 sl_strlcat(msg, tmp, SH_MSG_BUF);
3291
3292#if defined(USE_ACL) || defined(USE_XATTR)
3293 if (theFile->attr_string != NULL || p->attr_string != NULL)
3294 {
3295 sl_snprintf(tmp, SH_MSG_BUF,
3296#ifdef SH_USE_XML
3297 _("acl_old=\"%s\" acl_new=\"%s\" "),
3298#else
3299 _("acl_old=<%s>, acl_new=<%s>, "),
3300#endif
3301 (p->attr_string) ? p->attr_string : _("none"),
3302 (theFile->attr_string) ? theFile->attr_string : _("none"));
3303
3304 sl_strlcat(msg, tmp, SH_MSG_BUF);
3305 }
3306#endif
3307
3308#ifdef REPLACE_OLD
3309 if ((modi_mask & MODI_MOD) != 0)
3310 {
3311 /*
3312 * We postpone update if sh.flag.update == S_TRUE because
3313 * in interactive mode the user may not accept the change.
3314 */
3315 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3316 {
3317 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3318 p->theFile.mode = theFile->mode;
3319#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3320 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3321 p->theFile.attributes = theFile->attributes;
3322#endif
3323#if defined(USE_ACL) || defined(USE_XATTR)
3324 if (p->attr_string == NULL && theFile->attr_string != NULL)
3325 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3326 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3327 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3328 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3329 {
3330 if (0 != strcmp(theFile->attr_string, p->attr_string))
3331 {
3332 SH_FREE(p->attr_string);
3333 p->attr_string = sh_util_strdup (theFile->attr_string);
3334 }
3335 }
3336#endif
3337 }
3338 }
3339#endif
3340 }
3341
3342 if ((modi_mask & MODI_HLN) != 0)
3343 {
3344 sl_snprintf(tmp, SH_MSG_BUF,
3345#ifdef SH_USE_XML
3346 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
3347#else
3348 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
3349#endif
3350 (unsigned long) p->theFile.hardlinks,
3351 (unsigned long) theFile->hardlinks);
3352 sl_strlcat(msg, tmp, SH_MSG_BUF);
3353#ifdef REPLACE_OLD
3354 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3355 p->theFile.hardlinks = theFile->hardlinks;
3356#endif
3357 }
3358
3359 if ((modi_mask & MODI_RDEV) != 0)
3360 {
3361 sl_snprintf(tmp, SH_MSG_BUF,
3362#ifdef SH_USE_XML
3363 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
3364#else
3365 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
3366#endif
3367 (unsigned long) major(p->theFile.rdev),
3368 (unsigned long) minor(p->theFile.rdev),
3369 (unsigned long) major(theFile->rdev),
3370 (unsigned long) minor(theFile->rdev)
3371#ifdef SH_USE_XML
3372 , (unsigned long) p->theFile.rdev,
3373 (unsigned long) theFile->rdev
3374#endif
3375 );
3376 sl_strlcat(msg, tmp, SH_MSG_BUF);
3377#ifdef REPLACE_OLD
3378 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3379 p->theFile.rdev = theFile->rdev;
3380#endif
3381 }
3382
3383 if ((modi_mask & MODI_INO) != 0)
3384 {
3385 sl_snprintf(tmp, SH_MSG_BUF,
3386#ifdef SH_USE_XML
3387 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
3388#else
3389 _("inode_old=<%lu>, inode_new=<%lu>, "),
3390#endif
3391 (unsigned long) p->theFile.ino,
3392 (unsigned long) theFile->ino);
3393 sl_strlcat(msg, tmp, SH_MSG_BUF);
3394#ifdef REPLACE_OLD
3395 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3396 {
3397 p->theFile.ino = theFile->ino;
3398 p->theFile.dev = theFile->dev;
3399 }
3400#endif
3401 }
3402
3403
3404 /*
3405 * also report device for prelude
3406 */
3407#if defined(HAVE_LIBPRELUDE)
3408 if ((modi_mask & MODI_INO) != 0)
3409 {
3410 sl_snprintf(tmp, SH_MSG_BUF,
3411#ifdef SH_USE_XML
3412 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3413#else
3414 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3415#endif
3416 (unsigned long) major(p->theFile.dev),
3417 (unsigned long) minor(p->theFile.dev),
3418 (unsigned long) major(theFile->dev),
3419 (unsigned long) minor(theFile->dev)
3420 );
3421 sl_strlcat(msg, tmp, SH_MSG_BUF);
3422#ifdef REPLACE_OLD
3423 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3424 p->theFile.dev = theFile->dev;
3425#endif
3426 }
3427#endif
3428
3429 if ( ((modi_mask & MODI_USR) != 0)
3430#if defined(HAVE_LIBPRELUDE)
3431 || ((modi_mask & MODI_MOD) != 0)
3432#endif
3433 )
3434 {
3435#ifdef SH_USE_XML
3436 sl_snprintf(tmp, SH_MSG_BUF,
3437 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
3438#else
3439 sl_snprintf(tmp, SH_MSG_BUF,
3440 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
3441#endif
3442 p->theFile.c_owner, theFile->c_owner,
3443 (long) p->theFile.owner, (long) theFile->owner
3444 );
3445 sl_strlcat(msg, tmp, SH_MSG_BUF);
3446#ifdef REPLACE_OLD
3447 if ((modi_mask & MODI_USR) != 0) {
3448 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3449 {
3450 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3451 p->theFile.owner = theFile->owner;
3452 }
3453 }
3454#endif
3455 }
3456
3457 if ( ((modi_mask & MODI_GRP) != 0)
3458#if defined(HAVE_LIBPRELUDE)
3459 || ((modi_mask & MODI_MOD) != 0)
3460#endif
3461 )
3462 {
3463#ifdef SH_USE_XML
3464 sl_snprintf(tmp, SH_MSG_BUF,
3465 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
3466 p->theFile.c_group, theFile->c_group,
3467 (long) p->theFile.group, (long) theFile->group);
3468#else
3469 sl_snprintf(tmp, SH_MSG_BUF,
3470 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3471 p->theFile.c_group, theFile->c_group,
3472 (long) p->theFile.group, (long) theFile->group);
3473#endif
3474
3475 sl_strlcat(msg, tmp, SH_MSG_BUF);
3476#ifdef REPLACE_OLD
3477 if ((modi_mask & MODI_GRP) != 0) {
3478 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3479 {
3480 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3481 p->theFile.group = theFile->group;
3482 }
3483 }
3484#endif
3485 }
3486
3487 if ((modi_mask & MODI_SIZ) != 0)
3488 {
3489 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
3490 (UINT64) p->theFile.size,
3491 (UINT64) theFile->size);
3492 sl_strlcat(msg, tmp, SH_MSG_BUF);
3493#ifdef REPLACE_OLD
3494 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3495 p->theFile.size = theFile->size;
3496#endif
3497 }
3498
3499 if ((modi_mask & MODI_CTM) != 0)
3500 {
3501 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3502 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
3503#ifdef SH_USE_XML
3504 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
3505 timstr1c, timstr2c);
3506#else
3507 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
3508 timstr1c, timstr2c);
3509#endif
3510 sl_strlcat(msg, tmp, SH_MSG_BUF);
3511#ifdef REPLACE_OLD
3512 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3513 p->theFile.ctime = theFile->ctime;
3514#endif
3515 }
3516
3517 if ((modi_mask & MODI_ATM) != 0)
3518 {
3519 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3520 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
3521#ifdef SH_USE_XML
3522 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
3523 timstr1a, timstr2a);
3524#else
3525 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
3526 timstr1a, timstr2a);
3527#endif
3528 sl_strlcat(msg, tmp, SH_MSG_BUF);
3529#ifdef REPLACE_OLD
3530 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3531 p->theFile.atime = theFile->atime;
3532#endif
3533 }
3534
3535 if ((modi_mask & MODI_MTM) != 0)
3536 {
3537 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3538 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
3539#ifdef SH_USE_XML
3540 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
3541 timstr1m, timstr2m);
3542#else
3543 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
3544 timstr1m, timstr2m);
3545#endif
3546 sl_strlcat(msg, tmp, SH_MSG_BUF);
3547#ifdef REPLACE_OLD
3548 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3549 p->theFile.mtime = theFile->mtime;
3550#endif
3551 }
3552
3553
3554 if ((modi_mask & MODI_CHK) != 0)
3555 {
3556 sl_snprintf(tmp, SH_MSG_BUF,
3557#ifdef SH_USE_XML
3558 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3559#else
3560 _("chksum_old=<%s>, chksum_new=<%s>, "),
3561#endif
3562 p->theFile.checksum, fileHash);
3563 sl_strlcat(msg, tmp, SH_MSG_BUF);
3564#ifdef REPLACE_OLD
3565 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3566 {
3567 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3568 if ((theFile->check_mask & MODI_SGROW) != 0)
3569 p->theFile.size = theFile->size;
3570 }
3571#endif
3572 /* FIXME is this correct? */
3573 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
3574 strlen(theFile->link_path) > 2)
3575 modi_mask |= MODI_LNK;
3576 }
3577
3578
3579 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
3580 {
3581 if (theFile->link_path)
3582 tmp_lnk = sh_util_safe_name(theFile->link_path);
3583 else
3584 tmp_lnk = sh_util_strdup("-");
3585 if (p->linkpath)
3586 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3587 else
3588 tmp_lnk_old = sh_util_strdup("-");
3589#ifdef SH_USE_XML
3590 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
3591 tmp_lnk_old, tmp_lnk);
3592#else
3593 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "),
3594 tmp_lnk_old, tmp_lnk);
3595#endif
3596 SH_FREE(tmp_lnk);
3597 SH_FREE(tmp_lnk_old);
3598 sl_strlcat(msg, tmp, SH_MSG_BUF);
3599#ifdef REPLACE_OLD
3600 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3601 {
3602 if (p->linkpath != NULL && p->linkpath != notalink)
3603 SH_FREE(p->linkpath);
3604 if (!(theFile->link_path) ||
3605 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
3606 p->linkpath = (char *)notalink;
3607 else
3608 p->linkpath = sh_util_strdup(theFile->link_path);
3609 }
3610#endif
3611 }
3612
3613 if (MODI_AUDIT_ENABLED(theFile->check_mask))
3614 {
3615 char result[256];
3616
3617 if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, result, sizeof(result)))
3618 {
3619#ifdef SH_USE_XML
3620 sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
3621#else
3622 sl_strlcat(msg, _("obj=<"), SH_MSG_BUF);
3623#endif
3624
3625 sl_strlcat(msg, result, SH_MSG_BUF);
3626
3627#ifdef SH_USE_XML
3628 sl_strlcat(msg, _("\" "), SH_MSG_BUF);
3629#else
3630 sl_strlcat(msg, _(">"), SH_MSG_BUF);
3631#endif
3632 }
3633 }
3634
3635 tmp_path = sh_util_safe_name(theFile->fullpath);
3636 sh_error_handle(log_severity, FIL__, __LINE__,
3637 (long) modi_mask, MSG_FI_CHAN,
3638 (policy_override == NULL) ? _(policy[class]):log_policy,
3639 change_code, tmp_path, msg);
3640
3641 SH_FREE(tmp_path);
3642 SH_FREE(tmp);
3643 SH_FREE(msg);
3644
3645#ifndef REPLACE_OLD
3646 SET_SH_FFLAG_REPORTED(p->fflags);
3647#endif
3648
3649 if (S_TRUE == sh.flag.update)
3650 {
3651 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3652 {
3653 /* user does not want to update, thus we replace
3654 * with data from the baseline database
3655 */
3656 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3657 theFile->mode = p->theFile.mode;
3658#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3659 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3660 theFile->attributes = p->theFile.attributes;
3661#endif
3662#if defined(USE_ACL) || defined(USE_XATTR)
3663 if (theFile->attr_string == NULL && p->attr_string != NULL)
3664 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3665 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3666 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3667 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3668 {
3669 if (0 != strcmp(theFile->attr_string, p->attr_string))
3670 {
3671 SH_FREE(theFile->attr_string);
3672 theFile->attr_string = sh_util_strdup (p->attr_string);
3673 }
3674 }
3675#endif
3676
3677 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3678 {
3679 if (theFile->link_path)
3680 SH_FREE(theFile->link_path);
3681 if (p->linkpath)
3682 theFile->link_path = sh_util_strdup(p->linkpath);
3683 else
3684 theFile->link_path = sh_util_strdup("-");
3685 }
3686 else
3687 {
3688 if (theFile->link_path)
3689 SH_FREE(theFile->link_path);
3690 if (p->linkpath && p->linkpath != notalink)
3691 theFile->link_path = sh_util_strdup(p->linkpath);
3692 else
3693 theFile->link_path = NULL;
3694 }
3695
3696 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3697
3698 theFile->mtime = p->theFile.mtime;
3699 theFile->ctime = p->theFile.ctime;
3700 theFile->atime = p->theFile.atime;
3701
3702 theFile->size = p->theFile.size;
3703
3704 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3705 theFile->group = p->theFile.group;
3706 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3707 theFile->owner = p->theFile.owner;
3708
3709 theFile->ino = p->theFile.ino;
3710 theFile->rdev = p->theFile.rdev;
3711 theFile->dev = p->theFile.dev;
3712 theFile->hardlinks = p->theFile.hardlinks;
3713
3714 SET_SH_FFLAG_VISITED(p->fflags);
3715 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3716 retval = 1;
3717 goto unlock_and_return;
3718 }
3719 else /* if (sh.flag.reportonce == S_TRUE) */
3720 {
3721 /* we replace the data in the in-memory copy of the
3722 * baseline database, because otherwise we would get
3723 * another warning if the suidcheck runs
3724 */
3725 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3726 p->theFile.mode = theFile->mode;
3727#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3728 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3729 p->theFile.attributes = theFile->attributes;
3730#endif
3731#if defined(USE_ACL) || defined(USE_XATTR)
3732 if (p->attr_string == NULL && theFile->attr_string != NULL)
3733 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3734 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3735 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3736 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3737 {
3738 if (0 != strcmp(theFile->attr_string, p->attr_string))
3739 {
3740 SH_FREE(p->attr_string);
3741 p->attr_string = sh_util_strdup (theFile->attr_string);
3742 }
3743 }
3744#endif
3745
3746 if (theFile->c_mode[0] == 'l' || theFile->link_path)
3747 {
3748 if (p->linkpath != NULL && p->linkpath != notalink)
3749 SH_FREE(p->linkpath);
3750 p->linkpath = sh_util_strdup(theFile->link_path);
3751 }
3752 else
3753 {
3754 if (p->linkpath != NULL && p->linkpath != notalink) {
3755 SH_FREE(p->linkpath);
3756 }
3757 p->linkpath = (char *)notalink;
3758 }
3759
3760 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3761
3762 p->theFile.mtime = theFile->mtime;
3763 p->theFile.ctime = theFile->ctime;
3764 p->theFile.atime = theFile->atime;
3765
3766 p->theFile.size = theFile->size;
3767
3768 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3769 p->theFile.group = theFile->group;
3770 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3771 p->theFile.owner = theFile->owner;
3772
3773 p->theFile.ino = theFile->ino;
3774 p->theFile.rdev = theFile->rdev;
3775 p->theFile.dev = theFile->dev;
3776 p->theFile.hardlinks = theFile->hardlinks;
3777 }
3778 }
3779 }
3780
3781 SET_SH_FFLAG_VISITED(p->fflags);
3782 CLEAR_SH_FFLAG_CHECKED(p->fflags);
3783
3784 unlock_and_return:
3785 ; /* 'label at end of compound statement */
3786 SH_MUTEX_UNLOCK(mutex_hash);
3787 SL_RETURN(retval, _("sh_hash_compdata"));
3788}
3789
3790int hash_full_tree ()
3791{
3792 sh_file_t * p;
3793 int i;
3794
3795 SL_ENTER(_("sh_hash_compdata"));
3796
3797 if (IsInit != 1)
3798 SL_RETURN(0, _("sh_hash_compdata"));
3799
3800 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3801 for (i = 0; i < TABSIZE; ++i)
3802 {
3803 for (p = tab[i]; p; p = p->next)
3804 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
3805 }
3806 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3807 SL_RETURN (0, _("sh_hash_compdata"));
3808}
3809
3810
3811int hash_remove_tree (char * s)
3812{
3813 sh_file_t * p;
3814 size_t len;
3815 unsigned int i;
3816
3817 SL_ENTER(_("hash_remove_tree"));
3818
3819 if (!s || *s == '\0')
3820 SL_RETURN ((-1), _("hash_remove_tree"));
3821
3822 len = sl_strlen(s);
3823
3824 if (IsInit != 1)
3825 sh_hash_init();
3826
3827 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
3828 for (i = 0; i < TABSIZE; ++i)
3829 {
3830 for (p = tab[i]; p; p = p->next)
3831 {
3832 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
3833 {
3834 SET_SH_FFLAG_ALLIGNORE(p->fflags);
3835 }
3836 }
3837 }
3838 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
3839 SL_RETURN ((0), _("hash_remove_tree"));
3840}
3841
3842#if TIME_WITH_SYS_TIME
3843#include <sys/time.h>
3844#include <time.h>
3845#else
3846#if HAVE_SYS_TIME_H
3847#include <sys/time.h>
3848#else
3849#include <time.h>
3850#endif
3851#endif
3852
3853static int ListFullDetail = S_FALSE;
3854static int ListWithDelimiter = S_FALSE;
3855static char * ListFile = NULL;
3856
3857int set_list_file (const char * c)
3858{
3859 ListFile = sh_util_strdup(c);
3860 return 0;
3861}
3862
3863int set_full_detail (const char * c)
3864{
3865 (void) c;
3866 ListFullDetail = S_TRUE;
3867 return 0;
3868}
3869
3870int set_list_delimited (const char * c)
3871{
3872 (void) c;
3873 ListFullDetail = S_TRUE;
3874 ListWithDelimiter = S_TRUE;
3875 return 0;
3876}
3877
3878/* Always quote the string, except if it is empty. Quote quotes by
3879 * doubling them.
3880 */
3881char * csv_escape(const char * str)
3882{
3883 const char * p = str;
3884 const char * q;
3885
3886 size_t size = 0;
3887 size_t flag_quote = 0;
3888
3889 char * new;
3890 char * pnew;
3891
3892 if (p)
3893 {
3894
3895 while (*p)
3896 {
3897 if (*p == '"')
3898 ++flag_quote;
3899
3900 ++size; ++p;
3901 }
3902
3903 if (sl_ok_adds(size, flag_quote))
3904 size += flag_quote; /* double each quote */
3905 else
3906 return NULL;
3907
3908 if (sl_ok_adds(size, 3))
3909 size += 3; /* two quotes and terminating null */
3910 else
3911 return NULL;
3912
3913 new = SH_ALLOC(size);
3914
3915 if (flag_quote != 0)
3916 {
3917 new[0] = '"';
3918 pnew = &new[1];
3919 q = str;
3920 while (*q)
3921 {
3922 *pnew = *q;
3923 if (*pnew == '"')
3924 {
3925 ++pnew; *pnew = '"';
3926 }
3927 ++pnew; ++q;
3928 }
3929 *pnew = '"'; ++pnew;
3930 *pnew = '\0';
3931 }
3932 else
3933 {
3934 if (size > 3)
3935 {
3936 new[0] = '"';
3937 sl_strlcpy (&new[1], str, size-1);
3938 new[size-2] = '"';
3939 new[size-1] = '\0';
3940 }
3941 else
3942 {
3943 new[0] = '\0';
3944 }
3945 }
3946
3947 return new;
3948 }
3949 return NULL;
3950}
3951
3952
3953
3954void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3955{
3956 char * tmp;
3957 char * esc;
3958 char str[81];
3959
3960 if (ListWithDelimiter == S_TRUE)
3961 {
3962 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3963 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3964 p->theFile.c_mode, (int) p->theFile.mode,
3965 p->theFile.c_attributes, (int) p->theFile.attributes,
3966 (int) p->theFile.hardlinks,
3967 p->theFile.c_owner, (int) p->theFile.owner,
3968 p->theFile.c_group, (int) p->theFile.group);
3969 }
3970 else
3971 {
3972 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3973 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
3974 p->theFile.c_mode, (int) p->theFile.mode,
3975 p->theFile.c_attributes, (int) p->theFile.attributes,
3976 (int) p->theFile.hardlinks,
3977 p->theFile.c_owner, (int) p->theFile.owner,
3978 p->theFile.c_group, (int) p->theFile.group);
3979 }
3980
3981 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3982 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
3983 else
3984 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
3985
3986 printf( _(" %8s"), str);
3987 if (ListWithDelimiter == S_TRUE)
3988 putchar(',');
3989
3990 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
3991 if (ListWithDelimiter == S_TRUE)
3992 putchar(',');
3993 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
3994 if (ListWithDelimiter == S_TRUE)
3995 putchar(',');
3996 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
3997 if (ListWithDelimiter == S_TRUE)
3998 putchar(',');
3999 printf( _(" %s"), p->theFile.checksum);
4000 if (ListWithDelimiter == S_TRUE)
4001 putchar(',');
4002
4003 tmp = sh_util_safe_name(p->fullpath);
4004 if (ListWithDelimiter != S_TRUE)
4005 {
4006 printf( _(" %s"), tmp);
4007 }
4008 else
4009 {
4010 esc = csv_escape(tmp);
4011 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
4012 if (esc)
4013 SH_FREE(esc);
4014 }
4015 SH_FREE(tmp);
4016
4017 if ('l' == p->theFile.c_mode[0])
4018 {
4019 tmp = sh_util_safe_name(p->linkpath);
4020 if (ListWithDelimiter != S_TRUE)
4021 {
4022 printf(_(" -> %s"), tmp);
4023 }
4024 else
4025 {
4026 esc = csv_escape(tmp);
4027 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
4028 if (esc)
4029 SH_FREE(esc);
4030 }
4031 SH_FREE(tmp);
4032 }
4033
4034 if (p->attr_string)
4035 {
4036 tmp = sh_util_safe_name(p->attr_string);
4037 if (ListWithDelimiter != S_TRUE)
4038 {
4039 printf(_(" %s"), tmp);
4040 }
4041 else
4042 {
4043 esc = csv_escape(tmp);
4044 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
4045 if (esc)
4046 SH_FREE(esc);
4047 }
4048 SH_FREE(tmp);
4049 }
4050 else
4051 {
4052 if (ListWithDelimiter == S_TRUE)
4053 printf("%s",_(" no_attr"));
4054 }
4055 putchar('\n');
4056
4057 return;
4058}
4059
4060void sh_hash_list_db_entry (sh_file_t * p)
4061{
4062 char nowtime[128];
4063 char thetime[128];
4064 char * tmp;
4065 time_t now = time(NULL);
4066 time_t then = (time_t) p->theFile.mtime;
4067
4068#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
4069 struct tm * time_ptr;
4070 struct tm time_tm;
4071
4072 time_ptr = gmtime_r(&then, &time_tm);
4073 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
4074 time_ptr = gmtime_r(&now, &time_tm);
4075 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
4076 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
4077 {
4078 time_ptr = gmtime_r(&then, &time_tm);
4079 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
4080 }
4081#else
4082 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
4083 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
4084 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
4085 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
4086#endif
4087
4088 tmp = sh_util_safe_name(p->fullpath);
4089 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
4090 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
4091 p->theFile.c_mode, (int) p->theFile.hardlinks,
4092 p->theFile.c_owner, p->theFile.c_group,
4093 (int) major((dev_t)p->theFile.rdev),
4094 (int) minor((dev_t)p->theFile.rdev),
4095 thetime,
4096 tmp);
4097 else
4098 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
4099 p->theFile.c_mode, (int) p->theFile.hardlinks,
4100 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
4101 thetime,
4102 tmp);
4103 SH_FREE(tmp);
4104
4105 if ('l' == p->theFile.c_mode[0])
4106 {
4107 tmp = sh_util_safe_name(p->linkpath);
4108 printf(_(" -> %s\n"), tmp);
4109 SH_FREE(tmp);
4110 }
4111 else
4112 printf("\n");
4113
4114 return;
4115}
4116
4117#ifdef HAVE_LIBZ
4118#include <zlib.h>
4119#endif
4120
4121int sh_hash_printcontent(char * linkpath)
4122{
4123#ifdef HAVE_LIBZ
4124 unsigned char * decoded;
4125 unsigned char * decompressed = NULL;
4126 size_t dlen;
4127 unsigned long clen;
4128 unsigned long clen_o;
4129 int res;
4130
4131 if (linkpath && *linkpath != '-')
4132 {
4133 dlen = sh_util_base64_dec_alloc (&decoded,
4134 (unsigned char *)linkpath,
4135 strlen(linkpath));
4136
4137 clen = dlen * 2 + 1;
4138
4139 do {
4140 if (decompressed)
4141 SH_FREE(decompressed);
4142 clen += dlen; clen_o = clen;
4143 decompressed = SH_ALLOC(clen);
4144 res = uncompress(decompressed, &clen, decoded, dlen);
4145 if (res == Z_MEM_ERROR)
4146 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
4147 if (res == Z_DATA_ERROR)
4148 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
4149 } while (res == Z_BUF_ERROR || clen == clen_o);
4150
4151 decompressed[clen] = '\0';
4152 fputs( (char*) decompressed, stdout);
4153 SH_FREE(decompressed);
4154 return 0;
4155 }
4156#else
4157 (void) linkpath;
4158#endif
4159 fprintf(stderr, "%s",_("Error: No data available\n"));
4160 return -1;
4161}
4162
4163int sh_hash_list_db (const char * db_file)
4164{
4165 sh_file_t * p;
4166 SL_TICKET fd;
4167 char * line;
4168 int flag = 0;
4169
4170 if (!db_file)
4171 {
4172 _exit(EXIT_FAILURE);
4173 return -1;
4174 }
4175 if (sl_is_suid())
4176 {
4177 fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
4178 _exit (EXIT_FAILURE);
4179 return -1; /* for Mac OSX compiler */
4180 }
4181 if (0 == strcmp(db_file, _("default")))
4182 db_file = file_path('D', 'W');
4183 if (!db_file)
4184 {
4185 _exit(EXIT_FAILURE);
4186 return -1;
4187 }
4188
4189 line = SH_ALLOC(MAX_PATH_STORE+2);
4190
4191 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV)))
4192 {
4193 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
4194 db_file, fd);
4195 _exit(EXIT_FAILURE);
4196 return -1;
4197 }
4198
4199 /* fast forward to start of data
4200 */
4201 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
4202
4203 while (1)
4204 {
4205 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
4206 if ((p != NULL) && (p->fullpath[0] == '/'))
4207 {
4208 if (!ListFile)
4209 {
4210 flag = 1;
4211 if (ListFullDetail == S_FALSE)
4212 sh_hash_list_db_entry (p);
4213 else
4214 sh_hash_list_db_entry_full_detail (p);
4215 }
4216 else
4217 {
4218 if (0 != sl_strcmp(ListFile, p->fullpath))
4219 {
4220 continue;
4221 }
4222 flag = 1;
4223 if ('l' != p->theFile.c_mode[0])
4224 {
4225 if (sh_hash_printcontent(p->linkpath) < 0)
4226 {
4227 _exit(EXIT_FAILURE);
4228 return -1;
4229 }
4230 }
4231 else
4232 {
4233 fprintf(stderr, "%s",_("File is a link\n"));
4234 _exit(EXIT_FAILURE);
4235 return -1;
4236 }
4237 break;
4238 }
4239 }
4240 else if (p == NULL)
4241 {
4242 break;
4243 }
4244 }
4245
4246 if (line != NULL)
4247 SH_FREE(line);
4248 sl_close (fd);
4249
4250 fflush(NULL);
4251
4252 if (flag == 0)
4253 {
4254 fprintf(stderr, "%s",_("File not found\n"));
4255 _exit(EXIT_FAILURE);
4256 }
4257 _exit(EXIT_SUCCESS);
4258 return 0;
4259}
4260
4261/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
4262#endif
Note: See TracBrowser for help on using the repository browser.