source: trunk/src/sh_hash.c @ 132

Last change on this file since 132 was 132, checked in by rainer, 12 years ago

Make utility functions thread-safe.

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