source: trunk/src/sh_hash.c@ 362

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

Fix for ticket #267 (Multiple compiler warnings with gcc 4.6.1).

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