source: trunk/src/sh_hash.c@ 215

Last change on this file since 215 was 212, checked in by katerina, 16 years ago

Lock baseline database (ticket #139) and allow list as input for PortCheckInterface (ticket #140).

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