source: trunk/src/sh_hash.c@ 272

Last change on this file since 272 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

File size: 99.8 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{
[252]788 sl_fclose (FIL__, __LINE__, sh_fin_fd);
[1]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 {
[252]818 sl_fclose (FIL__, __LINE__, sh_fin_fd);
[1]819 sh_fin_fd = NULL;
820 }
821
[247]822 sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
[1]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);
[247]1130 FILE * fin_cp = NULL;
[1]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 {
[248]1193 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__,
1194 file_path('D', 'R'), SL_YESPRIV)))
[1]1195 {
1196 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"),
1197 file_path('D', 'R')));
1198 dlog(1, FIL__, __LINE__,
1199 _("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"),
1200 sl_get_errmsg(), fd, (int) sl_ret_euid());
1201 sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1,
1202 sh.prg_name);
[185]1203 retval = 1; exitval = EXIT_FAILURE;
1204 goto unlock_and_return;
[1]1205 }
1206
1207 TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"),
1208 file_path('D', 'R')));
1209
1210 if (0 != sl_strncmp(sh.data.hash,
[160]1211 sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
[133]1212 hashbuf, sizeof(hashbuf)),
[1]1213 KEY_LEN)
1214 && sh.flag.checkSum != SH_CHECK_INIT)
1215 {
1216 dlog(1, FIL__, __LINE__,
[162]1217 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
1218 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM,
1219 hashbuf, sizeof(hashbuf)));
[1]1220 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
1221 ( (NULL == file_path('D', 'R')) ? _("(null)") :
1222 file_path('D', 'R') )
1223 );
[185]1224 retval = 1; exitval = EXIT_FAILURE;
1225 goto unlock_and_return;
[1]1226 }
1227 sl_rewind (fd);
1228
1229 } /* new 1.4.8 */
1230
1231 if (sig_termfast == 1) /* SIGTERM */
1232 {
1233 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1234 --sig_raised; --sig_urgent;
[185]1235 retval = 1; exitval = EXIT_SUCCESS;
1236 goto unlock_and_return;
[1]1237 }
1238
1239#if defined(WITH_GPG) || defined(WITH_PGP)
1240 /* new 1.4.8: also checked for server data */
1241
1242 /* extract the data and copy to temporary file
1243 */
1244 fdTmp = open_tmp();
1245
[247]1246 fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
[34]1247 buf = SH_ALLOC(FGETS_BUF);
[1]1248
[34]1249 while (NULL != fgets(buf, FGETS_BUF, fin_cp))
[1]1250 {
1251 bufc = 0;
[34]1252 while (bufc < FGETS_BUF) {
[1]1253 if (buf[bufc] == '\n') { ++bufc; break; }
1254 ++bufc;
1255 }
1256
1257 if (sig_termfast == 1) /* SIGTERM */
1258 {
1259 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1260 --sig_raised; --sig_urgent;
[185]1261 retval = 1; exitval = EXIT_SUCCESS;
1262 goto unlock_and_return;
[1]1263 }
1264
1265 if (flag_pgp == S_FALSE &&
1266 (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
1267 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
1268 )
1269 {
1270 flag_pgp = S_TRUE;
1271 sl_write(fdTmp, buf, bufc);
1272 continue;
1273 }
1274
1275 if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
1276 {
1277 if (buf[0] == '\n')
1278 {
1279 flag_nohead = S_TRUE;
1280 sl_write(fdTmp, buf, 1);
1281 continue;
1282 }
1283 else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
1284 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
1285 {
1286 sl_write(fdTmp, buf, bufc);
1287 continue;
1288 }
1289 else
1290 continue;
1291 }
1292
1293 if (flag_pgp == S_TRUE && buf[0] == '\n')
1294 {
1295 sl_write(fdTmp, buf, 1);
1296 }
1297 else if (flag_pgp == S_TRUE)
1298 {
1299 /* sl_write_line(fdTmp, buf, bufc); */
1300 sl_write(fdTmp, buf, bufc);
1301 }
1302
1303 if (flag_pgp == S_TRUE &&
1304 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
1305 break;
1306 }
1307 SH_FREE(buf);
1308 sl_close(fd);
[252]1309 sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
[1]1310
1311 fd = fdTmp;
1312 sl_rewind (fd);
1313
1314 /* Validate signature of open file.
1315 */
1316 if (0 != sh_gpg_check_sign (0, fd, 2))
1317 {
[185]1318 retval = 1; exitval = EXIT_FAILURE;
1319 goto unlock_and_return;
[1]1320 }
1321 sl_rewind (fd);
1322#endif
1323 /* } new 1.4.8 check sig also for files downloaded from server */
1324
[170]1325 line = SH_ALLOC(MAX_PATH_STORE+2);
[1]1326
1327 /* fast forward to start of data
1328 */
[170]1329 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
[1]1330
[149]1331 for (i = 0; i < TABSIZE; ++i)
1332 tab[i] = NULL;
1333
[1]1334 while (1)
1335 {
1336 if (sig_termfast == 1) /* SIGTERM */
1337 {
1338 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1339 --sig_raised; --sig_urgent;
[185]1340 retval = 1; exitval = EXIT_SUCCESS;
[227]1341 SH_FREE(line);
1342 line = NULL;
[185]1343 goto unlock_and_return;
[1]1344 }
1345
[170]1346 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
[1]1347 if (p != NULL)
1348 {
1349 hashinsert (p);
1350 ++count;
1351 }
1352 else
1353 break;
1354 }
1355
[149]1356 /* Initialization completed.
1357 */
1358 IsInit = 1;
1359
[1]1360 if (line != NULL)
1361 SH_FREE(line);
1362
1363 /* Always keep db in memory, so we have no open file
1364 */
1365 sl_close (fd);
1366 sh_hash_getline_end();
1367 fd = -1;
1368
[149]1369 unlock_and_return:
[153]1370 ; /* 'label at end of compound statement */
[149]1371 SH_MUTEX_UNLOCK(mutex_hash);
[185]1372 if (retval == 0)
1373 {
1374 SL_RET0(_("sh_hash_init"));
1375 }
1376 aud_exit (FIL__, __LINE__, exitval);
[1]1377}
1378
1379/*****************************************************************
1380 *
1381 * delete hash array
1382 *
1383 *****************************************************************/
1384void sh_hash_hashdelete ()
1385{
1386 int i;
1387
1388 SL_ENTER(_("sh_hash_hashdelete"));
[149]1389 SH_MUTEX_LOCK(mutex_hash);
[1]1390
1391 if (IsInit == 0)
[149]1392 goto unlock_and_exit;
1393
[1]1394 for (i = 0; i < TABSIZE; ++i)
1395 if (tab[i] != NULL)
1396 {
1397 hash_kill (tab[i]);
1398 tab[i] = NULL;
1399 }
1400 IsInit = 0;
[149]1401
1402 unlock_and_exit:
[153]1403 ; /* 'label at end of compound statement */
[149]1404 SH_MUTEX_UNLOCK(mutex_hash);
[1]1405 SL_RET0(_("sh_hash_hashdelete"));
1406}
1407
1408/******************************************************************
1409 *
1410 * Insert a file into the database.
1411 *
1412 ******************************************************************/
1413static int pushdata_isfirst = 1;
1414static SL_TICKET pushdata_fd = -1;
1415
1416static int pushdata_stdout = S_FALSE;
1417
1418static char * sh_db_version_string = NULL;
1419
[20]1420int sh_hash_pushdata_stdout (const char * str)
[1]1421{
1422 if (!str)
1423 { pushdata_stdout = S_TRUE; return 0; }
1424 return -1;
1425}
1426
[22]1427int sh_hash_version_string(const char * str)
[1]1428{
1429 if (str)
1430 {
1431 if (sh_db_version_string != NULL) {
1432 SH_FREE(sh_db_version_string);
1433 }
1434 if (0 == sl_strncmp(str, _("NULL"), 4))
1435 {
1436 sh_db_version_string = NULL;
1437 return 0;
1438 }
[34]1439 sh_db_version_string = sh_util_strdup(str);
[1]1440 return 0;
1441 }
1442 return -1;
1443}
1444
[205]1445static int sh_loosedircheck = S_FALSE;
[1]1446
[205]1447int sh_hash_loosedircheck(const char * str)
1448{
1449 return sh_util_flagval(str, &sh_loosedircheck);
1450}
1451
1452
[149]1453static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
[1]1454{
1455 static long p_count = 0;
1456
1457 int status = 0;
1458
1459 char * tmp;
1460 size_t tmp_len = 0;
1461 size_t old_len = 0;
[149]1462 size_t path_len = 0;
[1]1463
1464 sh_filestore_t p;
1465
1466 struct stat sbuf;
1467
1468 char * fullpath = NULL;
1469 char * linkpath = NULL;
[68]1470 char * attr_string = NULL;
[1]1471
1472 char * line = NULL;
1473
1474 char timestring[81];
1475
[10]1476#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
[1]1477 int i;
1478#endif
1479
[149]1480 SL_ENTER(_("sh_hash_pushdata_int"));
[1]1481
1482 fullpath = SH_ALLOC(MAX_PATH_STORE+1);
1483 linkpath = SH_ALLOC(MAX_PATH_STORE+1);
1484
1485 linkpath[0] = '-';
1486 linkpath[1] = '\0';
1487 fullpath[0] = '-';
1488 fullpath[1] = '\0';
1489
1490 if (!buf) {
1491 memset(&p, '\0', sizeof(sh_filestore_t));
1492 }
1493
1494 if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1495 {
1496 dlog(1, FIL__, __LINE__,
1497 _("You cannot write the database to stdout when you use update rather than init.\n"));
1498 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1499 _("Writing database to stdout with update"),
1500 sh.prg_name,
[149]1501 _("sh_hash_pushdata_int"));
[1]1502 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1503 }
1504
1505 if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1506 {
1507 dlog(1, FIL__, __LINE__,
1508 _("You cannot write the database to stdout when running with suid privileges.\n"));
1509 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1510 _("Writing database to stdout when suid"),
1511 sh.prg_name,
[149]1512 _("sh_hash_pushdata_int"));
[1]1513 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1514 }
1515
1516
[149]1517 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) &&
[1]1518 ( (NULL == file_path('D', 'W')) ||
1519 (0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
1520 {
1521 dlog(1, FIL__, __LINE__,
1522 _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1523 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1524 _("No local path for database specified"),
1525 sh.prg_name,
[149]1526 _("sh_hash_pushdata_int"));
[1]1527 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1528 }
1529
1530
[149]1531 if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))
[1]1532 {
1533 /* Warn that file already exists; file_path != NULL here because
1534 * checked above
1535 */
1536 if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
1537 {
1538 if (sh.flag.update == S_FALSE)
1539 {
1540 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1541 file_path('D', 'W'));
1542 }
1543 }
1544 }
1545
1546
1547 if (sh.flag.update == S_FALSE)
1548 {
[76]1549 if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
[1]1550 {
[248]1551 if ( SL_ISERROR(pushdata_fd = sl_open_write(FIL__, __LINE__,
1552 file_path('D', 'W'),
1553 SL_YESPRIV)))
[76]1554 {
1555 SH_FREE(fullpath);
1556 SH_FREE(linkpath);
1557 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1558 geteuid(), file_path('D', 'W'));
[212]1559 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
[76]1560 }
[212]1561
1562 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1563 {
1564 SH_FREE(fullpath);
1565 SH_FREE(linkpath);
1566 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1567 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1568 file_path('D', 'W'));
1569 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1570 }
1571
[76]1572 if ( SL_ISERROR(status = sl_forward(pushdata_fd)))
1573 {
1574 SH_FREE(fullpath);
1575 SH_FREE(linkpath);
1576 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
[248]1577 _("Failed to seek to end of baseline database"),
1578 _("sh_hash_pushdata_int"),
[76]1579 file_path('D', 'W'));
[212]1580 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
[76]1581 }
[1]1582 }
1583 }
1584 else /* update == TRUE */
1585 {
1586 if (pushdata_isfirst == 1)
1587 {
1588 TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
[248]1589 if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(FIL__, __LINE__,
1590 file_path('D', 'W'),
1591 SL_YESPRIV))){
[212]1592 SH_FREE(fullpath);
1593 SH_FREE(linkpath);
1594 sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
1595 geteuid(), file_path('D', 'W'));
1596 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1597 }
1598
1599 if (SL_ISERROR(status = sl_lock (pushdata_fd)))
1600 {
1601 SH_FREE(fullpath);
1602 SH_FREE(linkpath);
1603 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1604 _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
1605 file_path('D', 'W'));
1606 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1607 }
1608
[1]1609 line = SH_ALLOC(MAX_PATH_STORE+1);
1610 if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line,
1611 MAX_PATH_STORE,
1612 file_path('D', 'W'))))
1613 {
1614 SH_FREE(fullpath);
1615 SH_FREE(linkpath);
1616 SH_FREE(line);
[212]1617 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
[1]1618 }
1619 SH_FREE(line);
1620 }
1621 }
1622
1623 if (buf != NULL && buf->fullpath != NULL) {
1624
1625 old_len = sl_strlen(buf->fullpath);
1626#if defined(SH_STEALTH)
1627 sh_do_encode(buf->fullpath, old_len);
1628#endif
[149]1629 tmp = quote_string(buf->fullpath, old_len);
[1]1630 tmp_len = sl_strlen(tmp);
1631#if defined(SH_STEALTH)
1632 sh_do_decode(buf->fullpath, old_len);
1633#endif
1634
[34]1635 if (tmp && tmp_len <= MAX_PATH_STORE)
[1]1636 {
1637 sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
1638 }
1639 else
1640 {
[133]1641 char hashbuf[KEYBUF_SIZE];
1642
[1]1643 sl_strlcpy(fullpath,
1644 sh_tiger_hash (buf->fullpath,
[133]1645 TIGER_DATA, old_len,
1646 hashbuf, sizeof(hashbuf)),
[1]1647 KEY_LEN+1);
1648 }
[34]1649 if (tmp) SH_FREE(tmp);
[1]1650 }
1651
[149]1652 path_len = sl_strlen(fullpath);
[1]1653#if defined(SH_STEALTH)
[149]1654 sh_do_encode(fullpath, path_len);
[1]1655#endif
1656
[149]1657 tmp = quote_string(fullpath, path_len);
[34]1658 if (tmp) {
1659 sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
1660 SH_FREE(tmp);
1661 }
[1]1662
[167]1663 if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL)
[1]1664 {
1665
[167]1666 old_len = sl_strlen(buf->link_path);
[1]1667#if defined(SH_STEALTH)
[167]1668 if (buf->c_mode[0] == 'l')
1669 sh_do_encode(buf->link_path, old_len);
[1]1670#endif
[167]1671 tmp = quote_string(buf->link_path, old_len);
[1]1672 tmp_len = sl_strlen(tmp);
1673#if defined(SH_STEALTH)
[167]1674 if (buf->c_mode[0] == 'l')
1675 sh_do_decode(buf->link_path, old_len);
[1]1676#endif
1677
[34]1678 if (tmp && tmp_len <= MAX_PATH_STORE)
[1]1679 {
[167]1680 sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);
[1]1681 }
1682 else
1683 {
[133]1684 char hashbuf[KEYBUF_SIZE];
[1]1685 sl_strlcpy(linkpath,
[167]1686 sh_tiger_hash (buf->link_path,
[133]1687 TIGER_DATA, old_len,
1688 hashbuf, sizeof(hashbuf)),
[1]1689 KEY_LEN+1);
1690 }
[34]1691 if (tmp) SH_FREE(tmp);
[1]1692
[149]1693 path_len = sl_strlen(linkpath);
[1]1694#if defined(SH_STEALTH)
[167]1695 if (buf->c_mode[0] == 'l')
1696 sh_do_encode(linkpath, path_len);
[1]1697#endif
[149]1698 tmp = quote_string(linkpath, path_len);
[34]1699 if (tmp)
1700 {
1701 sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
1702 SH_FREE(tmp);
1703 }
[1]1704 }
1705
[68]1706 if (buf != NULL && buf->attr_string != NULL)
1707 {
1708 old_len = sl_strlen(buf->attr_string);
1709#if defined(SH_STEALTH)
1710 sh_do_encode(buf->attr_string, old_len);
1711#endif
[149]1712 tmp = quote_string(buf->attr_string, old_len);
[68]1713 if (tmp)
1714 {
1715 attr_string = tmp;
1716 tmp = NULL;
1717 }
1718#if defined(SH_STEALTH)
1719 sh_do_decode(buf->attr_string, old_len);
1720#endif
1721 }
1722
1723
[1]1724 if (buf != NULL) {
1725 p.mark = REC_MAGIC;
[68]1726 if (attr_string)
1727 p.mark |= REC_FLAGS_ATTR;
[149]1728 sl_strlcpy(p.c_mode, buf->c_mode, CMODE_SIZE);
[1]1729 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1730 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1731 if (fileHash) {
1732 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
1733 }
[10]1734#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[149]1735 sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
[1]1736#else
[149]1737 for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
1738 p.c_attributes[ATTRBUF_USED] = '\0';
[1]1739#endif
1740
1741#if defined(SH_STEALTH)
1742 sh_do_encode(p.c_mode, sl_strlen(p.c_mode));
1743 sh_do_encode(p.c_owner, sl_strlen(p.c_owner));
1744 sh_do_encode(p.c_group, sl_strlen(p.c_group));
1745 sh_do_encode(p.checksum, sl_strlen(p.checksum));
1746
1747 sh_do_encode(p.c_attributes, sl_strlen(p.c_attributes));
1748#endif
1749
[10]1750#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1751 p.attributes = (UINT32) buf->attributes;
1752#else
1753 p.attributes = 0;
1754#endif
1755 p.linkmode = (UINT32) buf->linkmode;
1756 p.hardlinks = (UINT32) buf->hardlinks;
1757 p.dev = (UINT64) buf->dev;
1758 p.rdev = (UINT64) buf->rdev;
1759 p.mode = (UINT32) buf->mode;
1760 p.ino = (UINT32) buf->ino;
1761 p.size = (UINT64) buf->size;
1762 p.mtime = (UINT64) buf->mtime;
1763 p.atime = (UINT64) buf->atime;
1764 p.ctime = (UINT64) buf->ctime;
1765 p.owner = (UINT32) buf->owner;
1766 p.group = (UINT32) buf->group;
1767
1768 swap_32(&(p.mode));
1769 swap_32(&(p.linkmode));
1770 swap_64(&(p.dev));
1771 swap_64(&(p.rdev));
1772 swap_32(&(p.hardlinks));
1773 swap_32(&(p.ino));
1774 swap_64(&(p.size));
1775 swap_64(&(p.atime));
1776 swap_64(&(p.mtime));
1777 swap_64(&(p.ctime));
1778 swap_32(&(p.owner));
1779 swap_32(&(p.group));
1780 swap_32(&(p.attributes));
1781
1782#ifdef OLD_BUG
1783 swap_short(&(p.mark));
1784#else
1785 p.mark = *(swap_short(&(p.mark)));
1786#endif
1787 }
1788
1789 /* write the start marker
1790 */
1791 if (pushdata_isfirst == 1)
1792 {
1793 if (sh.flag.update == S_FALSE)
1794 {
1795 if (sh_db_version_string != NULL)
1796 {
1797 if (pushdata_stdout == S_FALSE)
1798 {
1799 sl_write (pushdata_fd, _("\n#Host "), 7);
1800 sl_write (pushdata_fd, sh.host.name,
1801 sl_strlen(sh.host.name));
1802 sl_write (pushdata_fd, _(" Version "), 9);
1803 sl_write (pushdata_fd, sh_db_version_string,
1804 sl_strlen(sh_db_version_string));
1805 sl_write (pushdata_fd, _(" Date "), 6);
[132]1806 (void) sh_unix_time(0, timestring, sizeof(timestring));
[1]1807 sl_write (pushdata_fd, timestring, sl_strlen(timestring));
1808 sl_write (pushdata_fd, "\n", 1);
1809 } else {
[210]1810 printf ("%s",_("\n#Host "));
[1]1811 printf ("%s", sh.host.name);
[210]1812 printf ("%s",_(" Version "));
[1]1813 printf ("%s", sh_db_version_string);
[210]1814 printf ("%s",_(" Date "));
[132]1815 (void) sh_unix_time(0, timestring, sizeof(timestring));
[1]1816 printf ("%s\n", timestring);
1817 }
1818 }
1819
1820 if (pushdata_stdout == S_FALSE)
1821 {
1822#if defined(SH_STEALTH)
1823 sl_write (pushdata_fd, "\n", 1);
1824 sl_write_line (pushdata_fd, N_("[SOF]"), 5);
1825#else
1826 sl_write_line (pushdata_fd, _("\n[SOF]"), 6);
1827#endif
1828 }
1829 else
1830 {
1831#if defined(SH_STEALTH)
1832 printf ("\n%s\n", N_("[SOF]"));
1833#else
1834 printf ("%s\n", _("\n[SOF]"));
1835#endif
1836 }
1837 }
1838 pushdata_isfirst = 0;
1839 }
1840
1841 if (pushdata_stdout == S_FALSE)
1842 {
1843 sl_write (pushdata_fd, &p, sizeof(sh_filestore_t));
[76]1844 sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
1845 sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
[68]1846 if (attr_string)
[76]1847 sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
[1]1848 } else {
[153]1849 if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
1850 {
1851 printf ("%s\n", fullpath);
1852 printf ("%s\n", linkpath);
1853 if (attr_string)
1854 printf ("%s\n", attr_string);
1855 }
1856 else
1857 {
1858 perror(_("Error writing database"));
1859 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1860 }
[1]1861 }
1862
1863 ++p_count;
1864
1865 if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1866 {
[76]1867 if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1868 {
1869 sl_close (pushdata_fd);
1870 pushdata_fd = -1;
1871 }
[1]1872 }
1873
1874 SH_FREE(fullpath);
1875 SH_FREE(linkpath);
[68]1876 if (attr_string)
1877 SH_FREE(attr_string);
[1]1878
[149]1879 SL_RET0(_("sh_hash_pushdata_int"));
[1]1880}
1881
[149]1882SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1883
1884void sh_hash_pushdata (file_type * buf, char * fileHash)
1885{
1886 SH_MUTEX_LOCK(mutex_writeout);
1887 sh_hash_pushdata_int (buf, fileHash);
1888 SH_MUTEX_UNLOCK(mutex_writeout);
1889 return;
1890}
1891
1892
[1]1893int sh_hash_writeout()
1894{
1895 sh_file_t * p;
1896 int i;
1897 file_type * f;
1898 char fileHash[KEY_LEN + 1];
1899
1900 SL_ENTER(_("sh_hash_writeout"));
1901
1902 if (S_TRUE == file_is_remote())
1903 {
1904 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
1905 _("Baseline database is remote"), _("sh_hash_writeout"));
1906 SL_RETURN (1, _("sh_hash_writeout"));
1907 }
1908
[149]1909 SH_MUTEX_LOCK(mutex_writeout);
[1]1910 if (!SL_ISERROR(pushdata_fd))
1911 {
1912 sl_close(pushdata_fd);
1913 pushdata_fd = -1;
1914 }
1915 pushdata_isfirst = 1;
1916
[149]1917
1918 SH_MUTEX_LOCK(mutex_hash);
[1]1919 for (i = 0; i < TABSIZE; ++i)
1920 {
1921 for (p = tab[i]; p; p = p->next)
1922 {
1923 f = sh_hash_create_ft (p, fileHash);
[149]1924 sh_hash_pushdata_int (f, fileHash);
[167]1925 if (f->attr_string) SH_FREE(f->attr_string);
1926 if (f->link_path) SH_FREE(f->link_path);
[1]1927 SH_FREE(f);
1928 }
1929 }
[149]1930 SH_MUTEX_UNLOCK(mutex_hash);
[1]1931
1932 if (!SL_ISERROR(pushdata_fd))
1933 {
1934 sl_close(pushdata_fd);
1935 pushdata_fd = -1;
1936 }
1937 pushdata_isfirst = 1;
[149]1938 SH_MUTEX_UNLOCK(mutex_writeout);
[1]1939
1940 SL_RETURN (0, _("sh_hash_writeout"));
1941}
1942
1943
1944/*********************************************************************
1945 *
1946 * Check whether a file is present in the database.
1947 *
1948 *********************************************************************/
1949static sh_file_t * sh_hash_have_it_int (char * newname)
1950{
1951 sh_file_t * p;
[133]1952 char hashbuf[KEYBUF_SIZE];
[1]1953
[115]1954 SL_ENTER(_("sh_hash_have_it_int"));
[1]1955
1956 if (newname == NULL)
[115]1957 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[1]1958
1959 if (sl_strlen(newname) <= MAX_PATH_STORE)
1960 p = hashsearch(newname);
1961 else
[133]1962 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1963 hashbuf, sizeof(hashbuf)) );
[1]1964 if (p == NULL)
[115]1965 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[149]1966
[115]1967 SL_RETURN( (p), _("sh_hash_have_it_int"));
[1]1968}
1969
1970int sh_hash_have_it (char * newname)
1971{
[149]1972 sh_file_t * p;
[170]1973 int retval;
[1]1974
[149]1975 if (IsInit != 1)
1976 sh_hash_init();
1977
1978 SH_MUTEX_LOCK(mutex_hash);
[170]1979
1980 retval = 0;
1981
[149]1982 p = sh_hash_have_it_int (newname);
1983
1984 if (!p)
1985 retval = (-1);
1986 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
1987 (p->modi_mask & MODI_CHK) != 0 &&
1988 (p->modi_mask & MODI_MOD) != 0)
1989 retval = 1;
1990 SH_MUTEX_UNLOCK(mutex_hash);
1991
1992 return retval;
[1]1993}
1994
1995int sh_hash_get_it (char * newname, file_type * tmpFile)
1996{
[149]1997 sh_file_t * p;
[170]1998 int retval;
[68]1999
[149]2000 if (IsInit != 1)
2001 sh_hash_init();
2002
[167]2003 tmpFile->link_path = NULL;
2004 tmpFile->attr_string = NULL;
2005
[149]2006 SH_MUTEX_LOCK(mutex_hash);
[170]2007
2008 retval = (-1);
2009
[149]2010 p = sh_hash_have_it_int (newname);
2011 if (p)
2012 {
[167]2013 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
2014 if (p->linkpath)
2015 tmpFile->link_path = sh_util_strdup (p->linkpath);
[149]2016 tmpFile->size = p->theFile.size;
2017 tmpFile->mtime = p->theFile.mtime;
2018 tmpFile->ctime = p->theFile.ctime;
2019 tmpFile->attr_string = NULL;
2020 retval = 0;
2021 }
2022 SH_MUTEX_UNLOCK(mutex_hash);
2023
2024 return retval;
[1]2025}
2026
[115]2027int sh_hash_getflags (char * filename)
2028{
[149]2029 sh_file_t * p;
[170]2030 int retval;
[149]2031
2032 if (IsInit != 1)
2033 sh_hash_init();
2034
2035 SH_MUTEX_LOCK(mutex_hash);
2036 p = sh_hash_have_it_int (filename);
2037 if (p)
2038 retval = p->fflags;
[170]2039 else
2040 retval = -1;
[149]2041 SH_MUTEX_UNLOCK(mutex_hash);
2042 return retval;
[115]2043}
2044
2045int sh_hash_setflags (char * filename, int flags)
2046{
[149]2047 sh_file_t * p;
[170]2048 int retval;
[149]2049
2050 if (IsInit != 1)
2051 sh_hash_init();
2052
2053 SH_MUTEX_LOCK(mutex_hash);
2054 p = sh_hash_have_it_int (filename);
2055 if (p)
2056 {
2057 p->fflags = flags;
2058 retval = 0;
2059 }
[170]2060 else
2061 retval = -1;
[149]2062 SH_MUTEX_UNLOCK(mutex_hash);
2063 return retval;
[115]2064}
2065
2066/* needs lock to be threadsafe
2067 */
2068void sh_hash_addflag (char * filename, int flag_to_set)
2069{
[149]2070 sh_file_t * p;
[115]2071
[149]2072 if (IsInit != 1)
2073 sh_hash_init();
2074
2075 SH_MUTEX_LOCK(mutex_hash);
2076 p = sh_hash_have_it_int (filename);
2077 if (p)
[115]2078 {
[149]2079 p->fflags |= flag_to_set;
[115]2080 }
[149]2081 SH_MUTEX_UNLOCK(mutex_hash);
[115]2082 return;
2083}
2084
[1]2085/*****************************************************************
2086 *
2087 * Set a file's status to 'visited'. This is required for
2088 * files that should be ignored, and may be present in the
2089 * database, but not on disk.
2090 *
2091 *****************************************************************/
2092static int sh_hash_set_visited_int (char * newname, int flag)
2093{
2094 sh_file_t * p;
[133]2095 char hashbuf[KEYBUF_SIZE];
[170]2096 int retval;
[1]2097
2098 SL_ENTER(_("sh_hash_set_visited_int"));
2099
2100 if (newname == NULL)
2101 SL_RETURN((-1), _("sh_hash_set_visited_int"));
[149]2102
[1]2103 if (IsInit != 1)
2104 sh_hash_init();
2105
[149]2106 SH_MUTEX_LOCK(mutex_hash);
2107
[1]2108 if (sl_strlen(newname) <= MAX_PATH_STORE)
2109 p = hashsearch(newname);
2110 else
[133]2111 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
2112 hashbuf, sizeof(hashbuf)));
[1]2113
[149]2114 if (p)
[1]2115 {
[149]2116 if (flag == SH_FFLAG_CHECKED)
2117 {
2118 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2119 CLEAR_SH_FFLAG_VISITED(p->fflags);
2120 SET_SH_FFLAG_CHECKED(p->fflags);
2121 }
[114]2122 else
[149]2123 {
2124 SET_SH_FFLAG_VISITED(p->fflags);
2125 CLEAR_SH_FFLAG_CHECKED(p->fflags);
2126 if (flag == SH_FFLAG_REPORTED)
2127 SET_SH_FFLAG_REPORTED(p->fflags);
2128 else
2129 CLEAR_SH_FFLAG_REPORTED(p->fflags);
2130 }
2131 retval = 0;
[1]2132 }
[170]2133 else
2134 retval = -1;
[149]2135
2136 SH_MUTEX_UNLOCK(mutex_hash);
2137 SL_RETURN((retval), _("sh_hash_set_visited_int"));
[1]2138}
2139
2140
2141/* cause the record to be deleted without a 'missing' message
2142 */
2143int sh_hash_set_missing (char * newname)
2144{
2145 int i;
2146 SL_ENTER(_("sh_hash_set_visited"));
[114]2147 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
[1]2148 SL_RETURN(i, _("sh_hash_set_visited"));
2149}
2150
[114]2151/* mark the file as visited and reported
2152 */
[1]2153int sh_hash_set_visited (char * newname)
2154{
2155 int i;
2156 SL_ENTER(_("sh_hash_set_visited"));
[114]2157 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
[1]2158 SL_RETURN(i, _("sh_hash_set_visited"));
2159}
2160
[114]2161/* mark the file as visited and NOT reported
2162 * used to avoid deletion of file from internal database
2163 */
[1]2164int sh_hash_set_visited_true (char * newname)
2165{
2166 int i;
2167 SL_ENTER(_("sh_hash_set_visited_true"));
[114]2168 i = sh_hash_set_visited_int(newname, 0);
[1]2169 SL_RETURN(i, _("sh_hash_set_visited_true"));
2170}
2171
2172
2173/******************************************************************
2174 *
2175 * Data entry for arbitrary data into database
2176 *
2177 ******************************************************************/
2178
2179void sh_hash_push2db (char * key, unsigned long val1,
2180 unsigned long val2, unsigned long val3,
2181 unsigned char * str, int size)
2182{
2183 int i = 0;
2184 char * p;
[137]2185 char i2h[2];
[227]2186 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[1]2187
[227]2188 tmpFile->attr_string = NULL;
2189 tmpFile->link_path = NULL;
[68]2190
[227]2191 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
2192 tmpFile->size = val1;
2193 tmpFile->mtime = val2;
2194 tmpFile->ctime = val3;
[1]2195
[227]2196 tmpFile->atime = 0;
2197 tmpFile->mode = 0;
2198 tmpFile->owner = 0;
2199 tmpFile->group = 0;
2200 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
2201 sl_strlcpy(tmpFile->c_group, _("root"), 5);
[1]2202
2203 if ((str != NULL) && (size < (PATH_MAX/2)-1))
2204 {
[227]2205 tmpFile->c_mode[0] = 'l';
2206 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
2207 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
2208 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
2209 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
2210 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
2211 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
[1]2212 for (i = 0; i < size; ++i)
2213 {
[137]2214 p = sh_util_charhex (str[i],i2h);
[227]2215 tmpFile->link_path[2*i] = p[0];
2216 tmpFile->link_path[2*i+1] = p[1];
2217 tmpFile->link_path[2*i+2] = '\0';
[1]2218 }
2219 }
2220 else
2221 {
[93]2222 for (i = 0; i < 10; ++i)
[227]2223 tmpFile->c_mode[i] = '-';
2224 tmpFile->c_mode[10] = '\0';
2225 tmpFile->link_path = sh_util_strdup("-");
[1]2226 }
2227
2228 if (sh.flag.checkSum == SH_CHECK_CHECK &&
2229 sh.flag.update == S_TRUE)
[227]2230 sh_hash_pushdata_memory (tmpFile, SH_KEY_NULL);
[1]2231 else
[227]2232 sh_hash_pushdata (tmpFile, SH_KEY_NULL);
[1]2233
[227]2234 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2235 SH_FREE(tmpFile);
[1]2236 return;
2237}
2238
2239extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
2240
2241char * sh_hash_db2pop (char * key, unsigned long * val1,
2242 unsigned long * val2, unsigned long * val3,
2243 int * size)
2244{
2245 size_t len;
2246 char * p;
2247 int i;
[167]2248 char * retval = NULL;
[227]2249 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[167]2250
[1]2251 *size = 0;
2252
[227]2253 if (0 == sh_hash_get_it (key, tmpFile))
[1]2254 {
[227]2255 *val1 = tmpFile->size;
2256 *val2 = tmpFile->mtime;
2257 *val3 = tmpFile->ctime;
[1]2258
[227]2259 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
[1]2260 {
[227]2261 len = strlen(tmpFile->link_path);
[1]2262
2263 p = SH_ALLOC((len/2)+1);
[227]2264 i = sh_util_hextobinary (p, tmpFile->link_path, len);
[1]2265
2266 if (i == 0)
2267 {
2268 *size = (len/2);
2269 p[*size] = '\0';
[167]2270 retval = p;
[1]2271 }
2272 else
2273 {
2274 SH_FREE(p);
2275 *size = 0;
2276 }
2277 }
2278 else
2279 {
2280 *size = 0;
2281 }
2282 }
2283 else
2284 {
2285 *size = -1;
2286 *val1 = 0;
2287 *val2 = 0;
2288 *val3 = 0;
2289 }
[227]2290 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
2291 SH_FREE(tmpFile);
[167]2292 return retval;
[1]2293}
2294
2295
2296
2297
2298/******************************************************************
2299 *
2300 * Data entry in hash table
2301 *
2302 ******************************************************************/
2303sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
2304{
2305 sh_file_t * fp;
2306 sh_filestore_t p;
[34]2307
2308 size_t len;
[1]2309 char * fullpath;
2310 char * linkpath;
[68]2311 char * attr_string = NULL;
[133]2312 char hashbuf[KEYBUF_SIZE];
[1]2313
2314 SL_ENTER(_("sh_hash_push_int"));
2315
2316 fp = SH_ALLOC(sizeof(sh_file_t));
2317
2318 p.mark = REC_MAGIC;
[68]2319 if (buf->attr_string)
2320 p.mark |= REC_FLAGS_ATTR;
[1]2321 sl_strlcpy(p.c_mode, buf->c_mode, 11);
2322 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
2323 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
2324 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
[10]2325#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2326 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
2327#endif
2328
[10]2329#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2330 p.attributes = (UINT32) buf->attributes;
2331#endif
2332 p.linkmode = (UINT32) buf->linkmode;
2333 p.hardlinks = (UINT32) buf->hardlinks;
[40]2334 p.dev = (UINT64) buf->dev;
2335 p.rdev = (UINT64) buf->rdev;
[1]2336 p.mode = (UINT32) buf->mode;
2337 p.ino = (UINT32) buf->ino;
2338 p.size = (UINT64) buf->size;
2339 p.mtime = (UINT64) buf->mtime;
2340 p.atime = (UINT64) buf->atime;
2341 p.ctime = (UINT64) buf->ctime;
2342 p.owner = (UINT32) buf->owner;
2343 p.group = (UINT32) buf->group;
2344
2345 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
[115]2346 fp->fflags = 0; /* init fflags */
[1]2347 fp->modi_mask = 0L;
2348
[68]2349 if (buf->attr_string)
2350 attr_string = sh_util_strdup(buf->attr_string);
2351 fp->attr_string = attr_string;
2352
[34]2353 len = sl_strlen(buf->fullpath);
2354 if (len <= MAX_PATH_STORE)
[1]2355 {
[34]2356 fullpath = SH_ALLOC(len+1);
2357 sl_strlcpy(fullpath, buf->fullpath, len+1);
[1]2358 }
2359 else
2360 {
2361 fullpath = SH_ALLOC(KEY_LEN + 1);
2362 sl_strlcpy(fullpath,
[133]2363 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
2364 hashbuf, sizeof(hashbuf)),
[1]2365 KEY_LEN+1);
2366 }
2367 fp->fullpath = fullpath;
2368
[167]2369 if (buf->link_path)
[1]2370 {
[167]2371 len = sl_strlen(buf->link_path);
[34]2372 if (len <= MAX_PATH_STORE)
[1]2373 {
[34]2374 linkpath = SH_ALLOC(len+1);
[167]2375 sl_strlcpy(linkpath, buf->link_path, len+1);
[1]2376 }
2377 else
2378 {
2379 linkpath = SH_ALLOC(KEY_LEN + 1);
2380 sl_strlcpy(linkpath,
[167]2381 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
[133]2382 hashbuf, sizeof(hashbuf)),
[1]2383 KEY_LEN+1);
2384 }
2385 fp->linkpath = linkpath;
2386 }
2387 else
2388 fp->linkpath = NULL;
2389
2390 SL_RETURN( fp, _("sh_hash_push_int"));
2391}
2392
2393#ifdef HAVE_INTTYPES_H
2394#include <inttypes.h>
2395#else
2396#ifdef HAVE_STDINT_H
2397#include <stdint.h>
2398#endif
2399#endif
2400
[40]2401#ifndef PRIu64
2402#ifdef HAVE_LONG_32
2403#define PRIu64 "llu"
2404#else
2405#define PRIu64 "lu"
[1]2406#endif
[40]2407#endif
[1]2408
2409char * sh_hash_size_format()
2410{
2411 static char form_rval[81];
2412
2413 SL_ENTER(_("sh_hash_size_format"));
2414
2415
2416#ifdef SH_USE_XML
2417 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]2418 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
[1]2419#else
2420 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]2421 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
[1]2422#endif
2423
2424 SL_RETURN( form_rval, _("sh_hash_size_format"));
2425}
2426
2427
2428#ifdef SH_USE_XML
2429static char * all_items (file_type * theFile, char * fileHash, int is_new)
2430{
2431 char timstr1c[32];
2432 char timstr1a[32];
2433 char timstr1m[32];
2434
2435 char * tmp_lnk;
2436 char * format;
2437
[170]2438 char * tmp = SH_ALLOC(SH_MSG_BUF);
2439 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]2440
2441 tmp[0] = '\0';
2442 msg[0] = '\0';
2443
2444
[10]2445#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2446 if (is_new)
2447 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
2448 else
2449 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
[170]2450 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2451 theFile->c_mode,
2452 theFile->c_attributes,
2453 (long) theFile->mode,
2454 (long) theFile->attributes
2455 );
2456#else
2457 if (is_new)
2458 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
2459 else
2460 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
2461
[170]2462 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2463 theFile->c_mode,
2464 (long) theFile->mode
2465 );
2466#endif
[170]2467 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2468
2469 if (is_new)
[40]2470 format = _("hardlinks_new=\"%lu\" ");
[1]2471 else
[40]2472 format = _("hardlinks_old=\"%lu\" ");
[170]2473 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2474 (unsigned long) theFile->hardlinks);
[170]2475 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2476
2477
2478 if (is_new)
[40]2479 format = _("idevice_new=\"%lu\" ");
[1]2480 else
[40]2481 format = _("idevice_old=\"%lu\" ");
[170]2482 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2483 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2484
2485
2486 if (is_new)
[40]2487 format = _("inode_new=\"%lu\" ");
[1]2488 else
[40]2489 format = _("inode_old=\"%lu\" ");
[170]2490 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2491 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2492
[40]2493 /*
2494 * also report device for prelude
2495 */
[181]2496#if defined(HAVE_LIBPRELUDE)
[40]2497 if (is_new)
2498 format = _("dev_new=\"%lu,%lu\" ");
2499 else
2500 format = _("dev_old=\"%lu,%lu\" ");
[170]2501 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]2502 (unsigned long) major(theFile->dev),
2503 (unsigned long) minor(theFile->dev));
[170]2504 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]2505#endif
[1]2506
[40]2507
[1]2508 if (is_new)
2509 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
2510 else
2511 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
[170]2512 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2513 theFile->c_owner, (long) theFile->owner);
[170]2514 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2515
2516
2517 if (is_new)
2518 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
2519 else
2520 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
[170]2521 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2522 theFile->c_group, (long) theFile->group);
[170]2523 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2524
2525
2526 if (is_new)
[170]2527 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2528 (UINT64) 0, (UINT64) theFile->size);
2529 else
[170]2530 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2531 (UINT64) theFile->size, (UINT64) 0);
[170]2532 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2533
2534
[132]2535 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]2536 if (is_new)
[170]2537 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
[1]2538 else
[170]2539 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
2540 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2541
[132]2542 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]2543 if (is_new)
[170]2544 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
[1]2545 else
[170]2546 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
2547 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2548
[132]2549 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]2550 if (is_new)
[170]2551 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
[1]2552 else
[170]2553 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
2554 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2555
2556 if (is_new)
[170]2557 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
[1]2558 else
[170]2559 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
2560 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2561
[169]2562 if (theFile->c_mode[0] == 'l' ||
2563 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]2564 {
[167]2565 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]2566 if (tmp_lnk)
2567 {
2568 if (is_new)
[170]2569 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
[1]2570 else
[170]2571 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
[1]2572 SH_FREE(tmp_lnk);
[170]2573 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2574 }
2575 }
[68]2576
2577 if (theFile->attr_string)
2578 {
2579 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2580 if (tmp_lnk)
2581 {
2582 if (is_new)
[170]2583 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
[68]2584 else
[170]2585 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
[68]2586 SH_FREE(tmp_lnk);
[170]2587 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2588 }
2589 }
2590
[1]2591
2592 SH_FREE(tmp);
2593 return (msg);
2594}
2595#else
2596static char * all_items (file_type * theFile, char * fileHash, int is_new)
2597{
2598 char timstr1c[32];
2599 char timstr1a[32];
2600 char timstr1m[32];
2601
2602 char * tmp_lnk;
2603 char * format;
2604
[170]2605 char * tmp = SH_ALLOC(SH_MSG_BUF);
2606 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]2607
2608 tmp[0] = '\0';
2609 msg[0] = '\0';
2610
2611
[10]2612#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2613 if (is_new)
2614 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
2615 else
2616 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
[170]2617 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2618 theFile->c_mode,
2619 theFile->c_attributes,
2620 (long) theFile->mode,
2621 (long) theFile->attributes
2622 );
2623#else
2624 if (is_new)
2625 format = _("mode_new=<%s>, imode_new=<%ld>, ");
2626 else
2627 format = _("mode_old=<%s>, imode_old=<%ld>, ");
2628
[170]2629 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2630 theFile->c_mode,
2631 (long) theFile->mode
2632 );
2633#endif
[170]2634 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2635
2636 if (is_new)
[40]2637 format = _("hardlinks_new=<%lu>, ");
[1]2638 else
[40]2639 format = _("hardlinks_old=<%lu>, ");
[170]2640 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2641 (unsigned long) theFile->hardlinks);
[170]2642 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2643
2644
2645 if (is_new)
[40]2646 format = _("idevice_new=<%lu>, ");
[1]2647 else
[40]2648 format = _("idevice_old=<%lu>, ");
[170]2649 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
2650 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2651
2652
2653 if (is_new)
[40]2654 format = _("inode_new=<%lu>, ");
[1]2655 else
[40]2656 format = _("inode_old=<%lu>, ");
[170]2657 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
2658 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2659
2660
[40]2661 /*
2662 * also report device for prelude
2663 */
[181]2664#if defined(HAVE_LIBPRELUDE)
[1]2665 if (is_new)
[40]2666 format = _("dev_new=<%lu,%lu>, ");
2667 else
2668 format = _("dev_old=<%lu,%lu>, ");
[170]2669 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]2670 (unsigned long) major(theFile->dev),
2671 (unsigned long) minor(theFile->dev));
[170]2672 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]2673#endif
2674
2675 if (is_new)
[1]2676 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
2677 else
2678 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
[170]2679 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2680 theFile->c_owner, (long) theFile->owner);
[170]2681 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2682
2683
2684 if (is_new)
2685 format = _("group_new=<%s>, igroup_new=<%ld>, ");
2686 else
2687 format = _("group_old=<%s>, igroup_old=<%ld>, ");
[170]2688 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]2689 theFile->c_group, (long) theFile->group);
[170]2690 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2691
2692
2693 if (is_new)
[170]2694 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2695 (UINT64) 0, (UINT64) theFile->size);
2696 else
[170]2697 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2698 (UINT64) theFile->size, (UINT64) 0);
[170]2699 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2700
2701
[132]2702 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]2703 if (is_new)
[170]2704 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
[1]2705 else
[170]2706 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
2707 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2708
[132]2709 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]2710 if (is_new)
[170]2711 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
[1]2712 else
[170]2713 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
2714 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2715
[132]2716 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]2717 if (is_new)
[170]2718 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
[1]2719 else
[170]2720 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
2721 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2722
2723 if (is_new)
[170]2724 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
[1]2725 else
[170]2726 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
2727 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2728
[169]2729 if (theFile->c_mode[0] == 'l' ||
2730 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]2731 {
[167]2732 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]2733 if (tmp_lnk)
2734 {
2735 if (is_new)
[170]2736 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
[1]2737 else
[170]2738 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
[1]2739 SH_FREE(tmp_lnk);
[170]2740 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]2741 }
2742 }
2743
[68]2744 if (theFile->attr_string)
2745 {
2746 tmp_lnk = sh_util_safe_name(theFile->attr_string);
2747 if (tmp_lnk)
2748 {
2749 if (is_new)
[170]2750 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
[68]2751 else
[170]2752 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
[68]2753 SH_FREE(tmp_lnk);
[170]2754 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2755 }
2756 }
2757
[1]2758 SH_FREE(tmp);
2759 return (msg);
2760}
2761#endif
2762
2763void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
2764{
2765 sh_file_t * p;
2766
2767 SL_ENTER(_("sh_hash_pushdata_memory"));
2768
2769 p = sh_hash_push_int(theFile, fileHash);
2770 if (p)
2771 {
[149]2772 SH_MUTEX_LOCK(mutex_hash);
[1]2773 hashinsert (p);
2774 p->modi_mask = theFile->check_mask;
[149]2775 SH_MUTEX_UNLOCK(mutex_hash);
[1]2776 }
2777
2778 SL_RET0(_("sh_hash_pushdata_memory"));
2779}
2780
2781
2782/*****************************************************************
2783 *
2784 * Compare a file with the database status.
2785 *
2786 *****************************************************************/
2787int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
2788 char * policy_override, int severity_override)
2789{
2790 char * msg;
2791 sh_file_t * p;
2792 char * tmp;
2793 char * tmp_path;
2794 char * tmp_lnk;
2795 char * tmp_lnk_old;
2796
2797 char * str;
2798
2799 char timstr1c[32];
2800 char timstr2c[32];
2801 char timstr1a[32];
2802 char timstr2a[32];
2803 char timstr1m[32];
2804 char timstr2m[32];
2805 char linkHash[KEY_LEN+1];
[169]2806 char * linkComp;
[1]2807 int maxcomp;
2808
2809 char change_code[16];
2810 int i;
2811
[170]2812 unsigned long modi_mask;
[1]2813
2814 char log_policy[32];
[153]2815 volatile int log_severity;
[133]2816 char hashbuf[KEYBUF_SIZE];
[1]2817
[170]2818 int retval;
[149]2819
[1]2820 SL_ENTER(_("sh_hash_compdata"));
2821
2822 if (IsInit != 1) sh_hash_init();
2823
2824 if (severity_override < 0)
2825 log_severity = ShDFLevel[class];
2826 else
2827 log_severity = severity_override;
2828
2829 if (policy_override != NULL)
2830 sl_strlcpy (log_policy, policy_override, 32);
2831
2832 /* -------- find the entry for the file ---------------- */
2833
[149]2834 SH_MUTEX_LOCK(mutex_hash);
2835
[170]2836 modi_mask = 0;
2837 retval = 0;
2838
[1]2839 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
2840 p = hashsearch(theFile->fullpath);
2841 else
2842 p = hashsearch( sh_tiger_hash(theFile->fullpath,
2843 TIGER_DATA,
[133]2844 sl_strlen(theFile->fullpath),
2845 hashbuf, sizeof(hashbuf))
[1]2846 );
2847
2848
2849 /* --------- Not found in database. ------------
2850 */
2851
2852 if (p == NULL)
2853 {
2854 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
2855 {
2856 tmp = sh_util_safe_name(theFile->fullpath);
2857
2858 str = all_items (theFile, fileHash, 1);
2859 sh_error_handle (log_severity, FIL__, __LINE__, 0,
2860 MSG_FI_ADD2,
2861 tmp, str);
2862 SH_FREE(str);
2863
2864 SH_FREE(tmp);
2865 }
2866
2867 if (sh.flag.reportonce == S_TRUE)
[114]2868 SET_SH_FFLAG_REPORTED(theFile->file_reported);
[77]2869
2870 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[1]2871 {
[77]2872 p = sh_hash_push_int(theFile, fileHash);
2873 if (p)
[149]2874 {
2875 hashinsert (p);
2876 p->modi_mask = theFile->check_mask;
2877 }
[77]2878 }
2879
2880 else if (S_TRUE == sh.flag.update)
2881 {
2882 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
[1]2883 {
[77]2884 p = sh_hash_push_int(theFile, fileHash);
2885 if (p)
[149]2886 {
2887 hashinsert (p);
2888 p->modi_mask = theFile->check_mask;
2889 }
[77]2890 }
2891 else
2892 {
[149]2893 retval = 1;
2894 goto unlock_and_return;
[77]2895 }
[1]2896 }
[149]2897
2898 goto unlock_and_return;
[1]2899 }
2900
[149]2901 p->modi_mask = theFile->check_mask;
2902
[1]2903 /* initialize change_code */
2904 for (i = 0; i < 15; ++i)
2905 change_code[i] = '-';
2906 change_code[15] = '\0';
2907
2908 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
2909 theFile->fullpath, fileHash, p->theFile.checksum));
2910
2911 if ( (fileHash != NULL) && (p->theFile.checksum != NULL) &&
[19]2912 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
[1]2913 (theFile->check_mask & MODI_CHK) != 0)
2914 {
[19]2915 if ((theFile->check_mask & MODI_SGROW) == 0)
2916 {
2917 modi_mask |= MODI_CHK;
2918 change_code[0] = 'C';
2919 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2920 }
2921 else
2922 {
2923 if (0 != strncmp (&fileHash[KEY_LEN + 1],
2924 p->theFile.checksum, KEY_LEN))
2925 {
2926 modi_mask |= MODI_CHK;
2927 change_code[0] = 'C';
2928 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
2929 }
2930 else
2931 {
2932 p->theFile.size = theFile->size;
2933 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2934 }
2935 }
[1]2936 }
2937
2938 if (p->theFile.c_mode[0] == 'l')
2939 {
[169]2940 if (!(theFile->link_path) &&
2941 (theFile->check_mask & MODI_LNK) != 0)
[1]2942 {
[169]2943 linkComp = NULL;
[93]2944 modi_mask |= MODI_LNK;
2945 change_code[1] = 'L';
2946 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
[169]2947 }
2948 else
2949 {
2950 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2951 {
2952 sl_strlcpy(linkHash,
2953 sh_tiger_hash(theFile->link_path,
2954 TIGER_DATA,
2955 sl_strlen(theFile->link_path),
2956 hashbuf, sizeof(hashbuf)),
2957 MAX_PATH_STORE+1);
2958 linkComp = linkHash;
2959 maxcomp = KEY_LEN;
2960 }
2961 else
2962 {
2963 linkComp = theFile->link_path;
2964 maxcomp = MAX_PATH_STORE;
2965 }
2966
2967 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
2968 (theFile->check_mask & MODI_LNK) != 0)
2969 {
2970 modi_mask |= MODI_LNK;
2971 change_code[1] = 'L';
2972 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2973 }
2974 }
[1]2975 }
2976
2977 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2978 {
2979 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2980 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
2981 (theFile->check_mask & MODI_RDEV) != 0)
2982 {
2983 modi_mask |= MODI_RDEV;
2984 change_code[2] = 'D';
2985 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2986 }
2987 }
2988
2989 /* cast to UINT32 in case ino_t is not 32bit
2990 */
2991 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
2992 (theFile->check_mask & MODI_INO) != 0)
2993 {
2994 modi_mask |= MODI_INO;
2995 change_code[3] = 'I';
2996 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2997 }
2998
2999 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
3000 (theFile->check_mask & MODI_HLN) != 0)
3001 {
3002 modi_mask |= MODI_HLN;
3003 change_code[4] = 'H';
3004 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
3005 }
3006
3007
3008 if ( ( (theFile->mode != p->theFile.mode)
[68]3009#if defined(USE_ACL) || defined(USE_XATTR)
3010 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
3011 (
3012 (theFile->attr_string == NULL && p->attr_string != NULL) ||
3013 (theFile->attr_string != NULL && p->attr_string == NULL) ||
3014 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
3015 )
3016 )
3017#endif
[10]3018#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]3019 || (theFile->attributes != p->theFile.attributes)
3020#endif
[68]3021 )
[1]3022 && (theFile->check_mask & MODI_MOD) != 0)
3023 {
3024 modi_mask |= MODI_MOD;
3025 change_code[5] = 'M';
3026 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
3027 /*
3028 * report link path if switch link/no link
3029 */
3030 if ((theFile->check_mask & MODI_LNK) != 0 &&
3031 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
3032 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
3033 {
3034 modi_mask |= MODI_LNK;
3035 change_code[1] = 'L';
3036 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
3037 }
3038 }
3039
3040 if ( theFile->owner != (uid_t) p->theFile.owner &&
3041 (theFile->check_mask & MODI_USR) != 0)
3042 {
3043 modi_mask |= MODI_USR;
3044 change_code[6] = 'U';
3045 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
3046 }
3047
3048 if ( theFile->group != (gid_t) p->theFile.group &&
3049 (theFile->check_mask & MODI_GRP) != 0)
3050 {
3051 modi_mask |= MODI_GRP;
3052 change_code[7] = 'G';
3053 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
3054 }
3055
3056
3057 if ( theFile->mtime != (time_t) p->theFile.mtime &&
3058 (theFile->check_mask & MODI_MTM) != 0)
3059 {
3060 modi_mask |= MODI_MTM;
3061 change_code[8] = 'T';
3062 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
3063 }
3064
[68]3065 if ( (theFile->check_mask & MODI_ATM) != 0 &&
3066 theFile->atime != (time_t) p->theFile.atime)
[1]3067 {
3068 modi_mask |= MODI_ATM;
3069 change_code[8] = 'T';
3070 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
3071 }
3072
3073
3074 /* Resetting the access time will set a new ctime. Thus, either we ignore
3075 * the access time or the ctime for NOIGNORE
3076 */
3077 if ( theFile->ctime != (time_t) p->theFile.ctime &&
3078 (theFile->check_mask & MODI_CTM) != 0)
3079 {
3080 modi_mask |= MODI_CTM;
3081 change_code[8] = 'T';
3082 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
3083 }
3084
3085 if ( theFile->size != (off_t) p->theFile.size &&
3086 (theFile->check_mask & MODI_SIZ) != 0)
3087 {
[19]3088 if ((theFile->check_mask & MODI_SGROW) == 0 ||
3089 theFile->size < (off_t) p->theFile.size)
[1]3090 {
3091 modi_mask |= MODI_SIZ;
3092 change_code[9] = 'S';
3093 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
[19]3094 }
[1]3095 }
3096 change_code[10] = '\0';
3097
[205]3098 /* --- Directories special case ---
3099 */
3100 if (p->theFile.c_mode[0] == 'd' &&
3101 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
3102 sh_loosedircheck == S_TRUE)
3103 {
3104 modi_mask = 0;
3105 }
3106
[1]3107 /* --- Report full details. ---
3108 */
3109 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
3110 {
3111 if ((theFile->check_mask & MODI_ATM) == 0)
3112 modi_mask = MASK_READONLY_;
3113 else
3114 modi_mask = MASK_NOIGNORE_;
3115 }
3116
3117 /* --- Report on modified files. ---
3118 */
[114]3119 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
[1]3120 {
[170]3121 tmp = SH_ALLOC(SH_MSG_BUF);
3122 msg = SH_ALLOC(SH_MSG_BUF);
[1]3123 msg[0] = '\0';
3124
3125 if ( ((modi_mask & MODI_MOD) != 0)
[181]3126#if defined(HAVE_LIBPRELUDE)
[68]3127 || ((modi_mask & MODI_USR) != 0)
3128 || ((modi_mask & MODI_GRP) != 0)
[1]3129#endif
3130 )
3131 {
[10]3132#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[170]3133 sl_snprintf(tmp, SH_MSG_BUF,
[1]3134#ifdef SH_USE_XML
3135 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
3136#else
3137 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
3138#endif
3139 p->theFile.c_mode, theFile->c_mode,
3140 p->theFile.c_attributes, theFile->c_attributes
3141#ifdef SH_USE_XML
3142 , (long) p->theFile.mode, (long) theFile->mode,
3143 (long) p->theFile.attributes,
3144 (long) theFile->attributes
3145#endif
3146 );
3147#else
3148#ifdef SH_USE_XML
[170]3149 sl_snprintf(tmp, SH_MSG_BUF,
[1]3150 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
[68]3151 p->theFile.c_mode, theFile->c_mode,
3152 (long) p->theFile.mode, (long) theFile->mode);
[1]3153#else
[170]3154 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
[68]3155 p->theFile.c_mode, theFile->c_mode);
[1]3156#endif
[68]3157#endif
[170]3158 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]3159
3160#if defined(USE_ACL) || defined(USE_XATTR)
3161 if (theFile->attr_string != NULL || p->attr_string != NULL)
3162 {
[170]3163 sl_snprintf(tmp, SH_MSG_BUF,
[1]3164#ifdef SH_USE_XML
[68]3165 _("acl_old=\"%s\" acl_new=\"%s\" "),
3166#else
3167 _("acl_old=<%s>, acl_new=<%s>, "),
[1]3168#endif
[68]3169 (p->attr_string) ? p->attr_string : _("none"),
3170 (theFile->attr_string) ? theFile->attr_string : _("none"));
3171
[170]3172 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]3173 }
[1]3174#endif
[68]3175
[1]3176#ifdef REPLACE_OLD
3177 if ((modi_mask & MODI_MOD) != 0)
3178 {
3179 /*
3180 * We postpone update if sh.flag.update == S_TRUE because
3181 * in interactive mode the user may not accept the change.
3182 */
3183 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3184 {
3185 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3186 p->theFile.mode = theFile->mode;
[10]3187#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]3188 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
3189 p->theFile.attributes = theFile->attributes;
3190#endif
[68]3191#if defined(USE_ACL) || defined(USE_XATTR)
3192 if (p->attr_string == NULL && theFile->attr_string != NULL)
3193 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3194 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3195 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3196 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3197 {
3198 if (0 != strcmp(theFile->attr_string, p->attr_string))
3199 {
3200 SH_FREE(p->attr_string);
3201 p->attr_string = sh_util_strdup (theFile->attr_string);
3202 }
3203 }
3204#endif
[1]3205 }
3206 }
3207#endif
3208 }
3209
3210 if ((modi_mask & MODI_HLN) != 0)
3211 {
[170]3212 sl_snprintf(tmp, SH_MSG_BUF,
[1]3213#ifdef SH_USE_XML
[40]3214 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
[1]3215#else
[40]3216 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
[1]3217#endif
3218 (unsigned long) p->theFile.hardlinks,
3219 (unsigned long) theFile->hardlinks);
[170]3220 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3221#ifdef REPLACE_OLD
3222 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3223 p->theFile.hardlinks = theFile->hardlinks;
3224#endif
3225 }
3226
3227 if ((modi_mask & MODI_RDEV) != 0)
3228 {
[170]3229 sl_snprintf(tmp, SH_MSG_BUF,
[1]3230#ifdef SH_USE_XML
[40]3231 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
[1]3232#else
[40]3233 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
[1]3234#endif
3235 (unsigned long) major(p->theFile.rdev),
3236 (unsigned long) minor(p->theFile.rdev),
3237 (unsigned long) major(theFile->rdev),
3238 (unsigned long) minor(theFile->rdev)
3239#ifdef SH_USE_XML
3240 , (unsigned long) p->theFile.rdev,
3241 (unsigned long) theFile->rdev
3242#endif
3243 );
[170]3244 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3245#ifdef REPLACE_OLD
3246 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3247 p->theFile.rdev = theFile->rdev;
3248#endif
3249 }
3250
3251 if ((modi_mask & MODI_INO) != 0)
3252 {
[170]3253 sl_snprintf(tmp, SH_MSG_BUF,
[1]3254#ifdef SH_USE_XML
[40]3255 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
[1]3256#else
[40]3257 _("inode_old=<%lu>, inode_new=<%lu>, "),
[1]3258#endif
3259 (unsigned long) p->theFile.ino,
3260 (unsigned long) theFile->ino);
[170]3261 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3262#ifdef REPLACE_OLD
3263 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[40]3264 {
3265 p->theFile.ino = theFile->ino;
3266 p->theFile.dev = theFile->dev;
3267 }
[1]3268#endif
3269 }
3270
[40]3271
3272 /*
3273 * also report device for prelude
3274 */
[181]3275#if defined(HAVE_LIBPRELUDE)
[40]3276 if ((modi_mask & MODI_INO) != 0)
3277 {
[170]3278 sl_snprintf(tmp, SH_MSG_BUF,
[40]3279#ifdef SH_USE_XML
3280 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
3281#else
3282 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
3283#endif
3284 (unsigned long) major(p->theFile.dev),
3285 (unsigned long) minor(p->theFile.dev),
3286 (unsigned long) major(theFile->dev),
3287 (unsigned long) minor(theFile->dev)
3288 );
[170]3289 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]3290#ifdef REPLACE_OLD
3291 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3292 p->theFile.dev = theFile->dev;
3293#endif
3294 }
3295#endif
3296
[1]3297 if ( ((modi_mask & MODI_USR) != 0)
[181]3298#if defined(HAVE_LIBPRELUDE)
[1]3299 || ((modi_mask & MODI_MOD) != 0)
3300#endif
3301 )
3302 {
3303#ifdef SH_USE_XML
[170]3304 sl_snprintf(tmp, SH_MSG_BUF,
[40]3305 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
[1]3306#else
[170]3307 sl_snprintf(tmp, SH_MSG_BUF,
[40]3308 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
[1]3309#endif
[40]3310 p->theFile.c_owner, theFile->c_owner,
3311 (long) p->theFile.owner, (long) theFile->owner
[1]3312 );
[170]3313 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3314#ifdef REPLACE_OLD
3315 if ((modi_mask & MODI_USR) != 0) {
3316 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3317 {
3318 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3319 p->theFile.owner = theFile->owner;
3320 }
3321 }
3322#endif
3323 }
3324
3325 if ( ((modi_mask & MODI_GRP) != 0)
[181]3326#if defined(HAVE_LIBPRELUDE)
[1]3327 || ((modi_mask & MODI_MOD) != 0)
3328#endif
3329 )
3330 {
3331#ifdef SH_USE_XML
[170]3332 sl_snprintf(tmp, SH_MSG_BUF,
[40]3333 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
[1]3334 p->theFile.c_group, theFile->c_group,
3335 (long) p->theFile.group, (long) theFile->group);
3336#else
[170]3337 sl_snprintf(tmp, SH_MSG_BUF,
[40]3338 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
3339 p->theFile.c_group, theFile->c_group,
3340 (long) p->theFile.group, (long) theFile->group);
[1]3341#endif
3342
[170]3343 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3344#ifdef REPLACE_OLD
3345 if ((modi_mask & MODI_GRP) != 0) {
3346 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3347 {
3348 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3349 p->theFile.group = theFile->group;
3350 }
3351 }
3352#endif
3353 }
3354
3355 if ((modi_mask & MODI_SIZ) != 0)
3356 {
[170]3357 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]3358 (UINT64) p->theFile.size,
3359 (UINT64) theFile->size);
[170]3360 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3361#ifdef REPLACE_OLD
3362 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3363 p->theFile.size = theFile->size;
3364#endif
3365 }
3366
3367 if ((modi_mask & MODI_CTM) != 0)
3368 {
[132]3369 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
3370 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
[1]3371#ifdef SH_USE_XML
[170]3372 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
[1]3373 timstr1c, timstr2c);
3374#else
[170]3375 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
[1]3376 timstr1c, timstr2c);
3377#endif
[170]3378 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3379#ifdef REPLACE_OLD
3380 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3381 p->theFile.ctime = theFile->ctime;
3382#endif
3383 }
3384
3385 if ((modi_mask & MODI_ATM) != 0)
3386 {
[132]3387 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
3388 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
[1]3389#ifdef SH_USE_XML
[170]3390 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
[1]3391 timstr1a, timstr2a);
3392#else
[170]3393 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
[1]3394 timstr1a, timstr2a);
3395#endif
[170]3396 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3397#ifdef REPLACE_OLD
3398 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3399 p->theFile.atime = theFile->atime;
3400#endif
3401 }
3402
3403 if ((modi_mask & MODI_MTM) != 0)
3404 {
[132]3405 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
3406 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
[1]3407#ifdef SH_USE_XML
[170]3408 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
[1]3409 timstr1m, timstr2m);
3410#else
[170]3411 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
[1]3412 timstr1m, timstr2m);
3413#endif
[170]3414 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3415#ifdef REPLACE_OLD
3416 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3417 p->theFile.mtime = theFile->mtime;
3418#endif
3419 }
3420
3421
3422 if ((modi_mask & MODI_CHK) != 0)
3423 {
[170]3424 sl_snprintf(tmp, SH_MSG_BUF,
[1]3425#ifdef SH_USE_XML
3426 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
3427#else
3428 _("chksum_old=<%s>, chksum_new=<%s>, "),
3429#endif
3430 p->theFile.checksum, fileHash);
[170]3431 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3432#ifdef REPLACE_OLD
3433 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[107]3434 {
3435 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3436 if ((theFile->check_mask & MODI_SGROW) != 0)
3437 p->theFile.size = theFile->size;
3438 }
[1]3439#endif
[169]3440 /* FIXME is this correct? */
3441 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
3442 strlen(theFile->link_path) > 2)
3443 modi_mask |= MODI_LNK;
[1]3444 }
3445
3446
[169]3447 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
[1]3448 {
[169]3449 if (theFile->link_path)
3450 tmp_lnk = sh_util_safe_name(theFile->link_path);
3451 else
3452 tmp_lnk = sh_util_strdup("-");
3453 if (p->linkpath)
3454 tmp_lnk_old = sh_util_safe_name(p->linkpath);
3455 else
3456 tmp_lnk_old = sh_util_strdup("-");
[1]3457#ifdef SH_USE_XML
[170]3458 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
[1]3459 tmp_lnk_old, tmp_lnk);
3460#else
[170]3461 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>"),
[1]3462 tmp_lnk_old, tmp_lnk);
3463#endif
3464 SH_FREE(tmp_lnk);
3465 SH_FREE(tmp_lnk_old);
[170]3466 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]3467#ifdef REPLACE_OLD
3468 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
3469 {
[149]3470 if (p->linkpath != NULL && p->linkpath != notalink)
[1]3471 SH_FREE(p->linkpath);
[167]3472 if (!(theFile->link_path) ||
3473 (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
[149]3474 p->linkpath = (char *)notalink;
3475 else
[167]3476 p->linkpath = sh_util_strdup(theFile->link_path);
[1]3477 }
3478#endif
3479 }
3480
3481
3482 tmp_path = sh_util_safe_name(theFile->fullpath);
3483 sh_error_handle(log_severity, FIL__, __LINE__,
3484 (long) modi_mask, MSG_FI_CHAN,
3485 (policy_override == NULL) ? _(policy[class]):log_policy,
3486 change_code, tmp_path, msg);
3487
3488 SH_FREE(tmp_path);
3489 SH_FREE(tmp);
3490 SH_FREE(msg);
3491
3492#ifndef REPLACE_OLD
[114]3493 SET_SH_FFLAG_REPORTED(p->fflags);
[1]3494#endif
3495
3496 if (S_TRUE == sh.flag.update)
3497 {
3498 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
3499 {
3500 /* user does not want to update, thus we replace
3501 * with data from the baseline database
3502 */
3503 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
3504 theFile->mode = p->theFile.mode;
[10]3505#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]3506 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
3507 theFile->attributes = p->theFile.attributes;
3508#endif
[68]3509#if defined(USE_ACL) || defined(USE_XATTR)
3510 if (theFile->attr_string == NULL && p->attr_string != NULL)
3511 { theFile->attr_string = sh_util_strdup (p->attr_string); }
3512 else if (theFile->attr_string != NULL && p->attr_string == NULL)
3513 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
3514 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3515 {
3516 if (0 != strcmp(theFile->attr_string, p->attr_string))
3517 {
3518 SH_FREE(theFile->attr_string);
3519 theFile->attr_string = sh_util_strdup (p->attr_string);
3520 }
3521 }
3522#endif
[1]3523
3524 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
3525 {
[167]3526 if (theFile->link_path)
3527 SH_FREE(theFile->link_path);
3528 if (p->linkpath)
3529 theFile->link_path = sh_util_strdup(p->linkpath);
3530 else
3531 theFile->link_path = sh_util_strdup("-");
[1]3532 }
3533 else
3534 {
[167]3535 if (theFile->link_path)
3536 SH_FREE(theFile->link_path);
3537 if (p->linkpath && p->linkpath != notalink)
3538 theFile->link_path = sh_util_strdup(p->linkpath);
3539 else
3540 theFile->link_path = NULL;
[1]3541 }
3542
3543 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
3544
3545 theFile->mtime = p->theFile.mtime;
3546 theFile->ctime = p->theFile.ctime;
3547 theFile->atime = p->theFile.atime;
3548
3549 theFile->size = p->theFile.size;
3550
3551 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
3552 theFile->group = p->theFile.group;
3553 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
3554 theFile->owner = p->theFile.owner;
3555
3556 theFile->ino = p->theFile.ino;
3557 theFile->rdev = p->theFile.rdev;
3558 theFile->dev = p->theFile.dev;
3559 theFile->hardlinks = p->theFile.hardlinks;
3560
[114]3561 SET_SH_FFLAG_VISITED(p->fflags);
3562 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[149]3563 retval = 1;
3564 goto unlock_and_return;
[1]3565 }
[77]3566 else /* if (sh.flag.reportonce == S_TRUE) */
[1]3567 {
3568 /* we replace the data in the in-memory copy of the
3569 * baseline database, because otherwise we would get
3570 * another warning if the suidcheck runs
3571 */
3572 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
3573 p->theFile.mode = theFile->mode;
[10]3574#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]3575 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
3576 p->theFile.attributes = theFile->attributes;
3577#endif
[68]3578#if defined(USE_ACL) || defined(USE_XATTR)
3579 if (p->attr_string == NULL && theFile->attr_string != NULL)
3580 { p->attr_string = sh_util_strdup (theFile->attr_string); }
3581 else if (p->attr_string != NULL && theFile->attr_string == NULL)
3582 { SH_FREE(p->attr_string); p->attr_string = NULL; }
3583 else if (theFile->attr_string != NULL && p->attr_string != NULL)
3584 {
3585 if (0 != strcmp(theFile->attr_string, p->attr_string))
3586 {
3587 SH_FREE(p->attr_string);
3588 p->attr_string = sh_util_strdup (theFile->attr_string);
3589 }
3590 }
3591#endif
[1]3592
[167]3593 if (theFile->c_mode[0] == 'l' || theFile->link_path)
[1]3594 {
[149]3595 if (p->linkpath != NULL && p->linkpath != notalink)
[1]3596 SH_FREE(p->linkpath);
[167]3597 p->linkpath = sh_util_strdup(theFile->link_path);
[1]3598 }
3599 else
3600 {
[149]3601 if (p->linkpath != NULL && p->linkpath != notalink) {
[167]3602 SH_FREE(p->linkpath);
3603 }
3604 p->linkpath = (char *)notalink;
[1]3605 }
3606
3607 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
3608
3609 p->theFile.mtime = theFile->mtime;
3610 p->theFile.ctime = theFile->ctime;
3611 p->theFile.atime = theFile->atime;
3612
3613 p->theFile.size = theFile->size;
3614
3615 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
3616 p->theFile.group = theFile->group;
3617 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
3618 p->theFile.owner = theFile->owner;
3619
3620 p->theFile.ino = theFile->ino;
3621 p->theFile.rdev = theFile->rdev;
3622 p->theFile.dev = theFile->dev;
3623 p->theFile.hardlinks = theFile->hardlinks;
3624 }
3625 }
3626 }
3627
[114]3628 SET_SH_FFLAG_VISITED(p->fflags);
3629 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[1]3630
[149]3631 unlock_and_return:
[153]3632 ; /* 'label at end of compound statement */
[149]3633 SH_MUTEX_UNLOCK(mutex_hash);
3634 SL_RETURN(retval, _("sh_hash_compdata"));
[1]3635}
3636
3637int hash_full_tree ()
3638{
3639 sh_file_t * p;
3640 int i;
3641
3642 SL_ENTER(_("sh_hash_compdata"));
3643
3644 if (IsInit != 1)
3645 SL_RETURN(0, _("sh_hash_compdata"));
3646
[149]3647 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]3648 for (i = 0; i < TABSIZE; ++i)
3649 {
3650 for (p = tab[i]; p; p = p->next)
[114]3651 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
[1]3652 }
[149]3653 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[1]3654 SL_RETURN (0, _("sh_hash_compdata"));
3655}
3656
3657
3658int hash_remove_tree (char * s)
3659{
[8]3660 sh_file_t * p;
3661 size_t len;
3662 unsigned int i;
[1]3663
3664 SL_ENTER(_("hash_remove_tree"));
3665
[8]3666 if (!s || *s == '\0')
[1]3667 SL_RETURN ((-1), _("hash_remove_tree"));
3668
[8]3669 len = sl_strlen(s);
3670
[1]3671 if (IsInit != 1)
3672 sh_hash_init();
3673
[149]3674 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]3675 for (i = 0; i < TABSIZE; ++i)
3676 {
3677 for (p = tab[i]; p; p = p->next)
3678 {
[8]3679 if (p->fullpath && 0 == strncmp(s, p->fullpath, len))
[1]3680 {
[114]3681 SET_SH_FFLAG_ALLIGNORE(p->fflags);
[1]3682 }
3683 }
3684 }
[149]3685 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[1]3686 SL_RETURN ((0), _("hash_remove_tree"));
3687}
3688
3689#if TIME_WITH_SYS_TIME
3690#include <sys/time.h>
3691#include <time.h>
3692#else
3693#if HAVE_SYS_TIME_H
3694#include <sys/time.h>
3695#else
3696#include <time.h>
3697#endif
3698#endif
3699
[169]3700static int ListFullDetail = S_FALSE;
[1]3701static int ListWithDelimiter = S_FALSE;
[169]3702static char * ListFile = NULL;
[1]3703
[169]3704int set_list_file (const char * c)
3705{
3706 ListFile = sh_util_strdup(c);
3707 return 0;
3708}
3709
[20]3710int set_full_detail (const char * c)
[1]3711{
[149]3712 (void) c;
[1]3713 ListFullDetail = S_TRUE;
[149]3714 return 0;
[1]3715}
3716
[20]3717int set_list_delimited (const char * c)
[1]3718{
[149]3719 (void) c;
[1]3720 ListFullDetail = S_TRUE;
3721 ListWithDelimiter = S_TRUE;
[149]3722 return 0;
[1]3723}
[76]3724
[149]3725/* Always quote the string, except if it is empty. Quote quotes by
[76]3726 * doubling them.
3727 */
3728char * csv_escape(const char * str)
3729{
3730 const char * p = str;
3731 const char * q;
3732
3733 size_t size = 0;
3734 size_t flag_quote = 0;
3735 int flag_comma = 0;
3736 char * new;
3737 char * pnew;
3738
3739 if (p)
3740 {
3741
3742 while (*p)
3743 {
3744 if (*p == ',')
3745 flag_comma = 1;
3746 else if (*p == '"')
3747 ++flag_quote;
3748
3749 ++size; ++p;
3750 }
3751
3752 if (sl_ok_adds(size, flag_quote))
3753 size += flag_quote; /* double each quote */
3754 else
3755 return NULL;
3756
3757 if (sl_ok_adds(size, 3))
3758 size += 3; /* two quotes and terminating null */
3759 else
3760 return NULL;
3761
3762 new = SH_ALLOC(size);
3763
3764 if (flag_quote != 0)
3765 {
3766 new[0] = '"';
3767 pnew = &new[1];
3768 q = str;
3769 while (*q)
3770 {
3771 *pnew = *q;
3772 if (*pnew == '"')
3773 {
3774 ++pnew; *pnew = '"';
3775 }
3776 ++pnew; ++q;
3777 }
3778 *pnew = '"'; ++pnew;
3779 *pnew = '\0';
3780 }
3781 else
3782 {
3783 if (size > 3)
3784 {
3785 new[0] = '"';
3786 sl_strlcpy (&new[1], str, size-1);
3787 new[size-2] = '"';
3788 new[size-1] = '\0';
3789 }
3790 else
3791 {
3792 new[0] = '\0';
3793 }
3794 }
3795
3796 return new;
3797 }
3798 return NULL;
3799}
3800
3801
[1]3802
3803void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3804{
3805 char * tmp;
[76]3806 char * esc;
[1]3807 char str[81];
3808
3809 if (ListWithDelimiter == S_TRUE)
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 else
3820 {
[40]3821 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3822 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
[1]3823 p->theFile.c_mode, (int) p->theFile.mode,
3824 p->theFile.c_attributes, (int) p->theFile.attributes,
3825 (int) p->theFile.hardlinks,
3826 p->theFile.c_owner, (int) p->theFile.owner,
3827 p->theFile.c_group, (int) p->theFile.group);
3828 }
3829
3830 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
[132]3831 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
[1]3832 else
[132]3833 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
[1]3834
3835 printf( _(" %8s"), str);
3836 if (ListWithDelimiter == S_TRUE)
3837 putchar(',');
3838
[132]3839 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
[1]3840 if (ListWithDelimiter == S_TRUE)
3841 putchar(',');
[132]3842 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
[1]3843 if (ListWithDelimiter == S_TRUE)
3844 putchar(',');
[132]3845 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
[1]3846 if (ListWithDelimiter == S_TRUE)
3847 putchar(',');
3848 printf( _(" %s"), p->theFile.checksum);
3849 if (ListWithDelimiter == S_TRUE)
3850 putchar(',');
3851
3852 tmp = sh_util_safe_name(p->fullpath);
[76]3853 if (ListWithDelimiter != S_TRUE)
3854 {
3855 printf( _(" %s"), tmp);
3856 }
3857 else
3858 {
3859 esc = csv_escape(tmp);
3860 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3861 if (esc)
3862 SH_FREE(esc);
3863 }
[1]3864 SH_FREE(tmp);
3865
3866 if ('l' == p->theFile.c_mode[0])
3867 {
3868 tmp = sh_util_safe_name(p->linkpath);
[76]3869 if (ListWithDelimiter != S_TRUE)
3870 {
3871 printf(_(" -> %s"), tmp);
3872 }
[1]3873 else
[76]3874 {
3875 esc = csv_escape(tmp);
3876 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3877 if (esc)
3878 SH_FREE(esc);
3879 }
[1]3880 SH_FREE(tmp);
3881 }
[68]3882
3883 if (p->attr_string)
3884 {
3885 tmp = sh_util_safe_name(p->attr_string);
[76]3886 if (ListWithDelimiter != S_TRUE)
3887 {
3888 printf(_(" %s"), tmp);
3889 }
3890 else
3891 {
3892 esc = csv_escape(tmp);
3893 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3894 if (esc)
3895 SH_FREE(esc);
3896 }
[68]3897 SH_FREE(tmp);
3898 }
[1]3899 else
[68]3900 {
3901 if (ListWithDelimiter == S_TRUE)
[210]3902 printf("%s",_(" no_attr"));
[68]3903 }
3904 putchar('\n');
[1]3905
3906 return;
3907}
3908
3909void sh_hash_list_db_entry (sh_file_t * p)
3910{
3911 char nowtime[128];
3912 char thetime[128];
3913 char * tmp;
3914 time_t now = time(NULL);
3915 time_t then = (time_t) p->theFile.mtime;
3916
[131]3917#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3918 struct tm * time_ptr;
3919 struct tm time_tm;
3920
3921 time_ptr = gmtime_r(&then, &time_tm);
3922 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3923 time_ptr = gmtime_r(&now, &time_tm);
3924 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3925 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3926 {
3927 time_ptr = gmtime_r(&then, &time_tm);
3928 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3929 }
3930#else
[1]3931 strftime(thetime, 127, _("%b %d %Y"), gmtime(&then));
3932 strftime(nowtime, 127, _("%b %d %Y"), gmtime(&now));
3933 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3934 strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
[131]3935#endif
[1]3936
3937 tmp = sh_util_safe_name(p->fullpath);
3938 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3939 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3940 p->theFile.c_mode, (int) p->theFile.hardlinks,
3941 p->theFile.c_owner, p->theFile.c_group,
3942 (int) major((dev_t)p->theFile.rdev),
3943 (int) minor((dev_t)p->theFile.rdev),
3944 thetime,
3945 tmp);
3946 else
3947 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3948 p->theFile.c_mode, (int) p->theFile.hardlinks,
3949 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3950 thetime,
3951 tmp);
3952 SH_FREE(tmp);
3953
3954 if ('l' == p->theFile.c_mode[0])
3955 {
3956 tmp = sh_util_safe_name(p->linkpath);
3957 printf(_(" -> %s\n"), tmp);
3958 SH_FREE(tmp);
3959 }
3960 else
3961 printf("\n");
3962
3963 return;
3964}
3965
[169]3966#ifdef HAVE_LIBZ
3967#include <zlib.h>
3968#endif
3969
3970int sh_hash_printcontent(char * linkpath)
3971{
3972#ifdef HAVE_LIBZ
3973 unsigned char * decoded;
3974 unsigned char * decompressed = NULL;
3975 size_t dlen;
3976 unsigned long clen;
3977 unsigned long clen_o;
3978 int res;
3979
3980 if (linkpath && *linkpath != '-')
3981 {
3982 dlen = sh_util_base64_dec_alloc (&decoded,
3983 (unsigned char *)linkpath,
3984 strlen(linkpath));
[170]3985
[169]3986 clen = dlen * 2 + 1;
[170]3987
[169]3988 do {
3989 if (decompressed)
3990 SH_FREE(decompressed);
3991 clen += dlen; clen_o = clen;
3992 decompressed = SH_ALLOC(clen);
3993 res = uncompress(decompressed, &clen, decoded, dlen);
3994 if (res == Z_MEM_ERROR)
[210]3995 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
[169]3996 if (res == Z_DATA_ERROR)
[210]3997 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
[169]3998 } while (res == Z_BUF_ERROR || clen == clen_o);
[170]3999
[169]4000 decompressed[clen] = '\0';
4001 fputs( (char*) decompressed, stdout);
[227]4002 SH_FREE(decompressed);
[169]4003 return 0;
4004 }
4005#else
4006 (void) linkpath;
4007#endif
[210]4008 fprintf(stderr, "%s",_("Error: No data available\n"));
[169]4009 return -1;
4010}
4011
[20]4012int sh_hash_list_db (const char * db_file)
[1]4013{
4014 sh_file_t * p;
4015 SL_TICKET fd;
4016 char * line;
[169]4017 int flag = 0;
[1]4018
4019 if (!db_file)
4020 {
4021 _exit(EXIT_FAILURE);
4022 return -1;
4023 }
4024 if (sl_is_suid())
4025 {
[210]4026 fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
[1]4027 _exit (EXIT_FAILURE);
4028 return -1; /* for Mac OSX compiler */
4029 }
4030 if (0 == strcmp(db_file, _("default")))
4031 db_file = file_path('D', 'W');
4032 if (!db_file)
4033 {
4034 _exit(EXIT_FAILURE);
4035 return -1;
4036 }
4037
[170]4038 line = SH_ALLOC(MAX_PATH_STORE+2);
[1]4039
[248]4040 if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV)))
[1]4041 {
4042 fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"),
4043 db_file, fd);
4044 _exit(EXIT_FAILURE);
4045 return -1;
4046 }
4047
4048 /* fast forward to start of data
4049 */
[170]4050 sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
[1]4051
4052 while (1)
4053 {
[170]4054 p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
[169]4055 if ((p != NULL) && (p->fullpath[0] == '/'))
[1]4056 {
[169]4057 if (!ListFile)
4058 {
4059 flag = 1;
4060 if (ListFullDetail == S_FALSE)
4061 sh_hash_list_db_entry (p);
4062 else
4063 sh_hash_list_db_entry_full_detail (p);
4064 }
[1]4065 else
[169]4066 {
4067 if (0 != sl_strcmp(ListFile, p->fullpath))
4068 {
4069 continue;
4070 }
4071 flag = 1;
4072 if ('l' != p->theFile.c_mode[0])
4073 {
4074 if (sh_hash_printcontent(p->linkpath) < 0)
4075 {
4076 _exit(EXIT_FAILURE);
4077 return -1;
4078 }
4079 }
4080 else
4081 {
[210]4082 fprintf(stderr, "%s",_("File is a link\n"));
[169]4083 _exit(EXIT_FAILURE);
4084 return -1;
4085 }
4086 break;
4087 }
[1]4088 }
4089 else if (p == NULL)
4090 {
4091 break;
4092 }
4093 }
4094
4095 if (line != NULL)
4096 SH_FREE(line);
4097 sl_close (fd);
4098
4099 fflush(NULL);
4100
[169]4101 if (flag == 0)
4102 {
[210]4103 fprintf(stderr, "%s",_("File not found\n"));
[169]4104 _exit(EXIT_FAILURE);
4105 }
[1]4106 _exit(EXIT_SUCCESS);
4107 return 0;
4108}
4109
4110/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
4111#endif
Note: See TracBrowser for help on using the repository browser.