source: trunk/src/sh_hash.c@ 436

Last change on this file since 436 was 425, checked in by katerina, 12 years ago

Fix for tickets #329, #330, #331, #332

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