source: trunk/src/sh_hash.c@ 351

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

Fix for ticket #255 (improve protection against 'intruder on server' scenario).

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