source: trunk/src/sh_hash.c@ 376

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

Patch for ticket #265 (inotify support).

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