source: trunk/src/sh_dbIO.c

Last change on this file was 564, checked in by katerina, 5 months ago

Fix for ticket #452 (reproducible database generation).

File size: 44.2 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2015 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#include <stdio.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27
28#include "samhain.h"
29#include "sh_utils.h"
30#include "sh_dbIO_int.h"
31#include "sh_hash.h"
32#include "sh_dbIO.h"
33#include "sh_sig.h"
34#include "sh_tiger.h"
35#include "sh_xfer.h"
36#include "sh_pthread.h"
37#include "sh_socket.h"
38#include "sh_files.h"
39
40#undef  FIL__
41#define FIL__  _("sh_dbIO.c")
42
43#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
44
45/* external prototypes                                                     */
46
47extern int get_the_fd (SL_TICKET ticket);
48
49SH_MUTEX_EXTERN(mutex_hash);
50
51/******************************************************************
52 *
53 * Get a single line
54 *
55 ******************************************************************/
56static FILE * sh_fin_fd = NULL;
57
58int sh_dbIO_getline (FILE * fd, char * line, const size_t sizeofline)
59{
60  size_t  n = 0;
61
62  SL_REQUIRE(sizeofline >= SH_MINIBUF, _("sizeofline >= SH_MINIBUF"));
63
64  if (NULL != fgets(line, sizeofline, fd))
65    {
66      n = strlen(line);
67      if (n > 0 && line[n-1] == '\n') {
68        n--; line[n] = '\0';
69      }
70    } 
71  else {
72    line[0] = '\0';
73    return -1;
74  }
75
76  return n;
77}
78
79/******************************************************************
80 *
81 * Fast forward to start of data
82 *
83 ******************************************************************/
84
85static void reopen_fin_fd(SL_TICKET fd)
86{
87  if (sh_fin_fd != NULL)
88    {
89      sl_fclose (FIL__, __LINE__, sh_fin_fd);
90      sh_fin_fd = NULL;
91    }
92
93  sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
94  return;
95}
96
97
98static int seek_sof(FILE * fd, char * line, int size, const char * file)
99{
100  long i;
101
102  while (1) 
103    {
104      i =  sh_dbIO_getline (fd, line, size);
105      if (i < 0 ) 
106        {
107          SH_FREE(line);
108          dlog(1, FIL__, __LINE__, 
109               _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
110               (NULL == file) ? _("(null)") : file);
111               
112          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
113                           ( (NULL == file) ? _("(null)") : file)
114                           );
115          return -1;
116        }
117
118#if defined(SH_STEALTH)
119      if (0 == sl_strncmp (line, N_("[SOF]"), 5)) 
120#else
121      if (0 == sl_strncmp (line, _("[SOF]"),  5)) 
122#endif
123        break;
124    }
125  fflush(fd);
126  return 0;
127}
128
129static int sh_dbIO_setdataent (SL_TICKET fd, char * line, int size, 
130                               const char * file)
131{
132  int retval;
133
134  SL_ENTER(_("sh_dbIO_setdataent"));
135
136  sl_rewind (fd);
137  reopen_fin_fd(fd);
138
139  if (!sh_fin_fd)
140    {
141      dlog(1, FIL__, __LINE__, 
142           _("The file signature database: %s is not readable.\n"),
143           (NULL == file) ? _("(null)") : file);
144      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
145                       ( (NULL == file) ? _("(null)") : file)
146                       );
147      SL_RETURN( -1, _("sh_dbIO_setdataent"));
148    }
149
150  retval = seek_sof(sh_fin_fd, line, size, file);
151  SL_RETURN( retval, _("sh_dbIO_setdataent"));
152}
153
154/* Seek to [SOF] and truncate remainder of file
155 */
156static int sh_dbIO_setdataent_old (SL_TICKET fd, char * line, int size, 
157                                   const char * file)
158{
159  FILE * fdp;
160 
161  SL_ENTER(_("sh_dbIO_setdataent_old"));
162
163  sl_rewind (fd);
164  fdp = sl_stream(fd, "r+");
165  if (0 != seek_sof(fdp, line, size, file))
166    SL_RETURN( SL_EREAD, _("sh_dbIO_setdataent_old"));
167
168  lseek(fileno(fdp), ftello(fdp), SEEK_SET);
169
170  if (0 != ftruncate(fileno(fdp), ftello(fdp)))
171    {
172      char ebuf[SH_ERRBUF_SIZE];
173      int errnum = errno;
174      sh_error_message(errnum, ebuf, sizeof(ebuf));
175      sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
176                       ebuf, _("sh_dbIO_setdataent_old") );
177      SL_RETURN( SL_EWRITE, _("sh_dbIO_setdataent_old"));
178    }
179  SL_RETURN( 0, _("sh_dbIO_setdataent_old"));
180}
181
182/******************************************************************
183 *
184 * IO helper functions
185 *
186 ******************************************************************/
187
188
189static UINT32 * swap_32 (UINT32 * iptr)
190{
191#ifdef WORDS_BIGENDIAN
192  unsigned char swap;
193  unsigned char * ii = (unsigned char *) iptr;
194  swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
195  swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
196  return iptr;
197#else
198  return iptr;
199#endif
200}
201
202static UINT64 *  swap_64 (UINT64 * iptr)
203{
204#ifdef WORDS_BIGENDIAN
205#ifdef UINT64_IS_32
206  swap_32 ((UINT32*) iptr);
207#else
208  unsigned char swap;
209  unsigned char * ii = (unsigned char *) iptr;
210  swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
211  swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
212  swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
213  swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
214#endif
215  return iptr;
216#else
217  return iptr;
218#endif
219}
220
221static unsigned short *  swap_short (unsigned short * iptr)
222{
223#ifdef WORDS_BIGENDIAN
224  if (sizeof(short) == 4)
225    swap_32 ((UINT32*) iptr);
226  else
227    {
228      /* alignment problem */
229      static unsigned short ooop = *iptr;
230      unsigned short hi   = (ooop & 0xff00);
231      unsigned short lo   = (ooop & 0xff);
232      ooop = (lo << 8) | (hi >> 8);
233      return &ooop;
234    }
235  return iptr;
236#else
237  return iptr;
238#endif
239}
240
241static void swap_data(sh_filestore_t * ft)
242{
243  swap_32(&(ft->mode));
244  swap_32(&(ft->linkmode));
245  swap_64(&(ft->dev));
246  swap_64(&(ft->rdev));
247  swap_32(&(ft->hardlinks));
248  swap_32(&(ft->ino));
249  swap_64(&(ft->size));
250  swap_64(&(ft->atime));
251  swap_64(&(ft->mtime));
252  swap_64(&(ft->ctime));
253  swap_32(&(ft->owner));
254  swap_32(&(ft->group));
255  swap_32(&(ft->checkflags));
256#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
257  swap_32(&(ft->attributes));
258#endif
259  ft->mark = *(swap_short(&(ft->mark)));
260  return;
261}
262
263#define QUOTE_CHAR '='
264
265char * unquote_string (const char * str, size_t len)
266{
267  int    i = 0, t1, t2;
268  char * tmp = NULL;
269  size_t l2, j, k = 0;
270
271  SL_ENTER(_("unquote_string"));
272
273  if (str != NULL)
274    {
275      l2  = len - 2;
276      tmp = SH_ALLOC(len + 1);
277
278      for (j = 0; j <= len; ++j)
279        {
280          if (str[j] != QUOTE_CHAR)
281            {
282              tmp[k] = str[j];
283            }
284          else if (str[j] == QUOTE_CHAR && j < l2)
285            {
286              t1 = sh_util_hexchar(str[j+1]);
287              t2 = sh_util_hexchar(str[j+2]);
288              if ((t1|t2) >= 0)
289                {
290                  i = 16 * t1 + t2;
291                  tmp[k] = i; 
292                  j += 2;
293                }
294              else
295                {
296                  tmp[k] = str[j];
297                }
298            }
299          else
300            tmp[k] = str[j];
301          ++k;
302        }
303    }
304  SL_RETURN(tmp, _("unquote_string"));
305}
306
307static char * int2hex (unsigned char i, char * i2h)
308{
309  static char hexchars[] = "0123456789ABCDEF";
310
311  i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
312  i2h[1] = hexchars[((i) & 0x0F)];        /* low  */
313
314  return i2h;
315}
316
317char * quote_string (const char * str, size_t len)
318{
319  char * tmp;
320  char * tmp2;
321  size_t l2, j, i = 0, k = 0;
322  char   i2h[2];
323
324  SL_ENTER(_("quote_string"));
325
326  if (str == NULL)
327    {
328      SL_RETURN(NULL, _("quote_string"));
329    }
330
331  for (j = 0; j < len; ++j)
332    if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
333
334  l2 = len + 1;
335  if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
336    {
337      tmp = SH_ALLOC(len + 1 + 3*i);
338    }
339  else
340    {
341      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
342                      _("integer overflow"), 
343                      _("quote_string"));
344      SL_RETURN(NULL, _("quote_string"));
345    }
346
347  for (j = 0; j <= len; ++j)
348    {
349      if (str[j] == '\n')
350        {
351          tmp2 = int2hex((unsigned char) '\n', i2h);
352          tmp[k] = QUOTE_CHAR; ++k;
353          tmp[k] = tmp2[0];    ++k;
354          tmp[k] = tmp2[1];
355        }
356      else if (str[j] == QUOTE_CHAR)
357        {
358          tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
359          tmp[k] = QUOTE_CHAR; ++k;
360          tmp[k] = tmp2[0];    ++k;
361          tmp[k] = tmp2[1];
362        }
363      else
364        {
365          tmp[k] = str[j];
366        }
367      ++k;
368    }
369  SL_RETURN(tmp, _("quote_string"));
370}
371
372static char * unquote_path(char * line, long i)
373{
374  char * tmp  = unquote_string (line, i);
375  size_t len  = sl_strlen(tmp)+1;
376  char * path = SH_ALLOC(len);
377
378  (void) sl_strlcpy (path, tmp, len);
379  if (tmp)
380    SH_FREE(tmp);
381  if (len > 1) {
382    if (path[len-2] == '\n')
383      path[len-2] = '\0';
384  }
385  return path;
386}
387
388/******************************************************************
389 *
390 * Use different init rootfs (patch by Kemal H.)
391 *
392 ******************************************************************/
393
394static char * sh_dbIO_rootfs = NULL;
395static size_t sh_dbIO_rootfs_len = 0;
396
397int sh_dbIO_init_rootfs (const char * rootfs)
398{
399  if (NULL == sh_dbIO_rootfs)
400    {
401      sh_dbIO_rootfs     = sh_util_strdup (rootfs);
402      sh_dbIO_rootfs_len = sl_strlen(sh_dbIO_rootfs);
403      return 0;
404    }
405  return -1;
406}
407
408size_t sh_dbIO_get_rootfs_len()
409{
410  return sh_dbIO_rootfs_len;
411}
412
413/* Prepend rootfs when reading from config file ('path' must be allocated with sufficient space).
414 */
415char * sh_dbIO_rootfs_prepend(char * path)
416{
417  if (0 == sh_dbIO_rootfs_len)
418    return path;
419 
420  memmove (path + sh_dbIO_rootfs_len, path, sl_strlen(path) + 1);
421  memcpy  (path, sh_dbIO_rootfs, sh_dbIO_rootfs_len);
422
423  return path;
424}
425
426
427/* Strip rootfs when writing to database file.
428 */
429char * sh_dbIO_rootfs_strip(char * path)
430{
431  if (sh_dbIO_rootfs_len == 0)
432    {
433      return path;
434    }
435  else
436    {
437      size_t len = sl_strlen(path);
438
439      memmove (path, path + sh_dbIO_rootfs_len, len + 1 - sh_dbIO_rootfs_len);
440      if(path[0] != '/')
441        {
442          path[0]='/';
443          path[1]='\0';
444        }
445    }
446
447  return path;
448}
449
450char * sh_dbIO_rootfs_strip_link(char * path)
451{
452  if (sh_dbIO_rootfs_len == 0)
453    return path;
454  if (strstr(path, sh_dbIO_rootfs) == path)
455    {
456      size_t len = sl_strlen(path);
457
458      memmove (path, path + sh_dbIO_rootfs_len, len + 1 - sh_dbIO_rootfs_len);
459    }
460  return path;
461}
462
463/******************************************************************
464 *
465 * Read next record and return it
466 *
467 ******************************************************************/
468
469static void corrupt_record(char * file, int line, const char * filepath)
470{
471  dlog(1, file, line, 
472       _("There is a corrupt record in the file signature database: %s\n"),
473       (NULL == filepath)? _("(null)") : filepath);
474  sh_error_handle ((-1), file, line, 0, MSG_E_SUBGPATH,
475                   _("Corrupt record in file signature database"), 
476                   _("sh_dbIO_getdataent"),
477                   ( (NULL == filepath) ? _("(null)") : filepath) );
478  return;
479}
480
481static void wrong_version(char * file, int line, const char * filepath)
482{
483  dlog(1, file, line, 
484       _("There is a record with a bad version number in the file signature database: %s\nThis may be caused by using '-t init' repeatedly to initialise the database, without (re)moving the database file.\n"),
485       (NULL == filepath) ? _("(null)") : filepath);
486  sh_error_handle((-1), file, line, 0, MSG_E_SUBGPATH,
487                  _("Record with bad version number in file signature database"), 
488                  _("sh_dbIO_getdataent"),
489                  (NULL == filepath) ? _("(null)") : filepath);
490  return;
491}
492
493static void hexdump(unsigned char * data, size_t size)
494{
495  unsigned int count =0;
496  char ith[3];
497
498  do {
499    int2hex(data[count], ith); ith[2] = '\0';
500    printf("%2s", ith);
501    ++count;
502    if (count % 40 == 0) putc('\n', stdout);
503  } while (count < size);
504}
505
506static size_t dbIO_fread_struct (sh_filestore_t * ptr, FILE *stream, 
507                                 const char * path, int * errflag)
508{
509  sh_filestore_old_t old_struct;
510  fpos_t position;
511  static int oldflag = -1;
512
513 start:
514  if (oldflag != -1) /* 'initialized' case first */
515    {
516      if (oldflag == 0)
517        return fread (ptr, sizeof(sh_filestore_t), 1, stream);
518
519      else
520        {
521          unsigned short mark;
522          if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
523            return 0;
524
525          /* set mark to current version */
526          mark = old_struct.mark;
527          mark = *(swap_short(&(mark)));
528          if ((mark & ~REC_FLAGS_MASK) != OLD_REC_MAGIC)
529            {
530              sh_filestore_old_t try_struct;
531              char try[5];
532
533              if (1 == 0)
534                hexdump((unsigned char *)&old_struct, sizeof(old_struct));
535              memset(&try_struct, 0, sizeof(try_struct));
536              if (!memcmp(&old_struct, &try_struct, sizeof(try_struct)))
537                return 0; /* NULL read */
538              if (1 != fread (try, sizeof(try), 1, stream))
539                return 0;
540              if (feof(stream))
541                return 0;
542
543              wrong_version(FIL__, __LINE__, path);
544              *errflag = -1;
545              return 0;
546            }
547          if ((mark & REC_FLAGS_ATTR) != 0)
548            mark = REC_MAGIC|REC_FLAGS_ATTR;
549          else
550            mark = REC_MAGIC;
551          mark = *(swap_short(&(mark)));
552          old_struct.mark = mark;
553
554          /* copy into current struct version */
555          memcpy(ptr, &old_struct, sizeof(old_struct));
556          ptr->checkflags = 0;
557          return 1;
558        }
559    }
560  else /* not initialized yet, test DB version */
561    {
562      if (0 == fgetpos(stream, &position))
563        {
564          unsigned short mark;
565
566          if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
567            return 0;
568
569          mark = old_struct.mark;
570          mark = *(swap_short(&(mark)));
571          if ((mark & ~REC_FLAGS_MASK) == REC_MAGIC)
572            oldflag = 0;
573          else if ((mark & ~REC_FLAGS_MASK) == OLD_REC_MAGIC)
574            oldflag = 1;
575          else
576            {
577              wrong_version(FIL__, __LINE__, path);
578              *errflag = -1;
579              return 0;
580            }
581
582          /* return to previous position and read data */
583          if (0 != fsetpos(stream, &position))
584            return 0;
585          goto start;
586        }
587      return 0;
588    }
589}
590
591int sig_end_detected (void * ft)
592{
593  char * str = (char *) ft;
594  char cmp[SH_MINIBUF];
595
596  sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp));
597
598  if ( 0 == memcmp(str, cmp, strlen(cmp)) ) 
599    return S_TRUE;
600  return S_FALSE;
601}
602
603static sh_file_t *  sh_dbIO_getdataent (char * line, int size, 
604                                        const char * filepath, int * errflag)
605{
606  sh_file_t * p;
607  sh_filestore_t ft;
608  long i;
609  char * fullpath;
610  char * linkpath;
611  char * attr_string = NULL;
612
613  SL_ENTER(_("sh_dbIO_getdataent"));
614
615  *errflag = 0;
616
617  p = SH_ALLOC(sizeof(sh_file_t));
618
619  /* Read next record -- Part One
620   */
621  if (1 != dbIO_fread_struct (&ft, sh_fin_fd, filepath, errflag))
622    {
623      SH_FREE(p);
624      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
625    }
626
627  ft.mark = *(swap_short(&(ft.mark)));
628
629  if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
630    {
631      if (sig_end_detected(&ft))
632        {
633          SH_FREE(p);
634          SL_RETURN( NULL, _("sh_dbIO_getdataent"));
635        }
636      SH_FREE(p);
637      wrong_version(FIL__, __LINE__, filepath);
638      *errflag = -1;
639      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
640    }
641
642  ft.mark = *(swap_short(&(ft.mark)));
643  swap_data(&ft);
644
645  /* Read next record -- Part Two -- Fullpath
646   */
647  i = sh_dbIO_getline (sh_fin_fd, line, size);
648
649  if (i <= 0 ) 
650    {
651      SH_FREE(p);
652      corrupt_record(FIL__, __LINE__, filepath);
653      *errflag = -1;
654      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
655    }
656
657  fullpath = unquote_path(line, i);
658
659  /* Read next record -- Part Three -- Linkpath
660   */
661  i =  sh_dbIO_getline (sh_fin_fd, line, size);
662
663  if (i <= 0 ) 
664    {
665      SH_FREE(fullpath); SH_FREE(p);
666      corrupt_record(FIL__, __LINE__, filepath);
667      *errflag = -1;
668      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
669    }
670
671  linkpath = unquote_path(line, i);
672
673  /* Read next record -- Part Four -- attr_string
674   */
675  if ((ft.mark & REC_FLAGS_ATTR) != 0)
676    {
677      i =  sh_dbIO_getline (sh_fin_fd, line, size);
678      if (i <= 0 ) 
679        {
680          SH_FREE(fullpath); SH_FREE(linkpath); SH_FREE(p);
681          corrupt_record(FIL__, __LINE__, filepath);
682          *errflag = -1;
683          SL_RETURN( NULL, _("sh_dbIO_getdataent"));
684        }
685
686      attr_string = unquote_path(line, i);
687    }
688
689  /* Read next record -- Part Four -- Decode
690   */
691#if defined(SH_STEALTH)
692  sh_do_decode(fullpath,    sl_strlen(fullpath));
693#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
694  sh_do_decode(ft.c_attributes,   sl_strlen(ft.c_attributes));
695#endif
696  sh_do_decode(ft.c_mode,   sl_strlen(ft.c_mode));
697  sh_do_decode(ft.c_owner,  sl_strlen(ft.c_owner));
698  sh_do_decode(ft.c_group,  sl_strlen(ft.c_group));
699  sh_do_decode(ft.checksum, sl_strlen(ft.checksum)); 
700  /*
701   * TXT entries are c_mode[0] != 'l' and do not get decoded
702   */
703  if (ft.c_mode[0] == 'l' && linkpath[0] != '-')
704    { 
705      sh_do_decode(linkpath, sl_strlen(linkpath));
706    }
707  if ((ft.mark & REC_FLAGS_ATTR) != 0)
708    { 
709      sh_do_decode(attr_string, sl_strlen(attr_string));
710    }
711#endif
712
713  memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
714
715  /* init fflags, such that suid files in
716   * database are recognized as such
717   */
718  {
719    mode_t mode = (mode_t) ft.mode;
720
721    if (S_ISREG(mode) &&
722        (0 !=(S_ISUID & mode) ||
723#if defined(HOST_IS_LINUX)
724         (0 !=(S_ISGID & mode) && 
725          0 !=(S_IXGRP & mode)) 
726#else 
727         0 !=(S_ISGID & mode)
728#endif
729         )
730        )
731      p->fflags = SH_FFLAG_SUIDCHK;
732
733    else
734      p->fflags = 0;
735  }
736
737  p->modi_mask   = ft.checkflags;
738  if (MODI_ISSET(ft.checkflags, MODI_ALLIGNORE))
739    SET_SH_FFLAG_ALLIGNORE(p->fflags);
740  p->fullpath    = fullpath;
741  p->linkpath    = linkpath;
742  p->attr_string = attr_string;
743
744  /* set to an invalid value
745   */
746  ft.mark = (REC_MAGIC + 5);
747
748  SL_REQUIRE((*errflag == 0), _("errflag not set correctly"));
749  SL_RETURN( p, _("sh_dbIO_getdataent"));
750}
751
752/******************************************************************
753 *
754 * Data loading routines
755 *
756 ******************************************************************/
757static SL_TICKET load_data_from_server(const char * uuid)
758{
759  SL_TICKET fd = -1;
760
761#if defined(SH_WITH_CLIENT)
762  char hashbuf[KEYBUF_SIZE];
763
764  /* Data file from Server
765   */
766  if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
767    return -1;
768
769  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
770  fd = sh_xfer_request_file((!uuid) ? _("DATA") : uuid);
771
772  if (SL_ISERROR(fd))
773    {
774      if (!uuid)
775        {
776          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
777          dlog(1, FIL__, __LINE__, 
778               _("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); 
779        }
780      else
781        sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_TCP_FBAD);
782      return fd;
783    }
784  sl_rewind (fd);
785
786  if (!uuid)
787    {
788      sl_strlcpy (sh.data.hash, 
789                  sh_tiger_hash (file_path('D', 'R'), 
790                                 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
791                  KEY_LEN+1);
792      sl_rewind (fd);
793    }
794#else
795  (void) uuid;
796#endif
797  return fd;
798}
799
800static SL_TICKET load_data_from_disk(const char * filepath)
801{
802  char hashbuf[KEYBUF_SIZE];
803  SL_TICKET fd = -1;
804
805  /* Local data file
806   */
807  if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, filepath, SL_YESPRIV)) )
808    {
809      TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"), filepath));
810      dlog(1, FIL__, __LINE__, 
811    _("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"), 
812           sl_get_errmsg(), fd, (int) sl_ret_euid());
813      sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
814                       sh.prg_name);
815      return -1;
816    }
817 
818  TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"), 
819        filepath));
820
821  if (sh.data.hash[0] == '\0')
822    {
823      char hashbuf[KEYBUF_SIZE];
824      sl_strlcpy(sh.data.hash, 
825                 sh_tiger_hash (filepath, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), 
826                 KEY_LEN+1);
827    }
828  else
829    {
830      if (0 != sl_strncmp(sh.data.hash, 
831                          sh_tiger_hash (filepath, fd, TIGER_NOLIM, 
832                                         hashbuf, sizeof(hashbuf)),
833                          KEY_LEN)
834          && sh.flag.checkSum != SH_CHECK_INIT) 
835        {
836          dlog(1, FIL__, __LINE__, 
837               _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
838               sh.data.hash, sh_tiger_hash (filepath, fd, TIGER_NOLIM, 
839                                            hashbuf, sizeof(hashbuf)));
840          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
841                           ( (NULL == filepath) ? _("(null)") :
842                             filepath )
843                           );
844        }
845    }
846  sl_rewind (fd);
847  return fd;
848}
849
850static SL_TICKET verify_data (SL_TICKET fd)
851{
852#if defined(WITH_SIG)
853  SL_TICKET fdTmp;
854
855  /* extract the data and copy to temporary file
856   */
857  fdTmp = sh_sig_extract_signed(fd);
858
859  if (sig_termfast == 1)  /* SIGTERM */
860    {
861      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
862      --sig_raised; --sig_urgent;
863      return -1;
864    }
865
866  sl_close(fd);
867  fd = fdTmp;
868
869  /* Validate signature of open file.
870   */
871  if (0 != sh_sig_check_signature (fd, SIG_DATA))
872    {
873      sl_close(fd);
874      return -1;
875    }
876  sl_rewind (fd);
877
878  fdTmp = sh_sig_extract_signed_data(fd);
879  sl_close(fd);
880  fd = fdTmp; 
881#endif
882
883  return fd;
884}
885
886static int read_data(SL_TICKET fd, sh_file_t * tab[TABSIZE], 
887                     const char * filepath)
888{
889  sh_file_t * p;
890  int count = 0;
891  int errflag = 0;
892  char * line = SH_ALLOC(MAX_PATH_STORE+2);
893
894  /* fast forward to start of data
895   */
896  if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, filepath))
897    return -1;
898
899  while (1) 
900    {
901      if (sig_termfast == 1)  /* SIGTERM */
902        {
903          TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
904          --sig_raised; --sig_urgent;
905          SH_FREE(line);
906          return -1;
907        }
908
909      p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, filepath, &errflag);
910      if (p != NULL)
911        {
912          if (!sh_hash_is_null_record(&(p->theFile)))
913            hashinsert (tab, p);
914          else
915            sh_hash_remove_unconditional (p->fullpath);
916          ++count;
917        }
918      else
919        break;
920    }
921
922  if (line != NULL)
923    SH_FREE(line);
924
925  /* Always keep db in memory, so we have no open file
926   */
927  sl_close (fd);
928
929  sl_fclose (FIL__, __LINE__, sh_fin_fd);
930  sh_fin_fd = NULL;
931
932  return errflag;
933}
934
935
936static int sh_dbIO_load_db_int(sh_file_t * tab[TABSIZE], 
937                               const char * filepath, const char * uuid)
938{
939#define FGETS_BUF 16384
940
941  SL_TICKET fd = -1;
942
943  if (uuid)
944    {
945      fd = load_data_from_server(uuid);
946      if (SL_ISERROR(fd))
947        return -1;
948    }
949  else if (!filepath)
950    {
951      char * dbpath = file_path('D', 'R');
952
953      fd = load_data_from_server(NULL);
954
955      if (SL_ISERROR(fd))
956        {
957          if (*dbpath == '/')
958            fd = load_data_from_disk(dbpath);
959        }
960    }
961  else
962    {
963      fd = load_data_from_disk(filepath);
964    }
965
966  if (SL_ISERROR(fd))
967    return -1;
968
969  if (sig_termfast == 1)  /* SIGTERM */
970    {
971      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
972      --sig_raised; --sig_urgent;
973      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
974    }
975
976  fd = verify_data(fd);
977  if (SL_ISERROR(fd))
978    return -1;
979
980  if (!uuid) { int i; for (i = 0; i < TABSIZE; ++i) tab[i] = NULL; }
981
982  return read_data (fd, tab, filepath);
983}
984
985
986int sh_dbIO_load_db(sh_file_t * tab[TABSIZE])
987{
988  return sh_dbIO_load_db_int(tab, NULL, NULL);
989}
990int sh_dbIO_load_db_file(sh_file_t * tab[TABSIZE], const char * filepath)
991{
992  return sh_dbIO_load_db_int(tab, filepath, NULL);
993}
994
995int sh_dbIO_load_delta()
996{
997  int    status = 0;
998#if defined(SH_WITH_CLIENT)
999  sh_file_t ** mtab = get_default_data_table();
1000  int errflag = 0;
1001  unsigned int count;
1002  time_t last;
1003
1004  if ( sh.flag.checkSum != SH_CHECK_INIT )
1005    {
1006      if (sh_hash_get_initialized() != 0)
1007        {
1008          char * uuid = sh_socket_get_uuid(&errflag, &count, &last);
1009
1010          if (!uuid) 
1011            return errflag;
1012
1013          if (count > 0)
1014            sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, count, MSG_E_SUBGEN,
1015                          _("Retrying download of delta DB"), 
1016                          _("sh_dbIO_load_delta"));
1017
1018          status = sh_dbIO_load_db_int(mtab, NULL, uuid);
1019          if (status < 0)
1020            {
1021              /* Return status < 0 indicates that max_try is exceeded
1022               */
1023              if (sh_socket_return_uuid(uuid, count, last) < 0)
1024                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAFAIL, uuid);
1025            }
1026          else
1027            {
1028              sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAOK, uuid);
1029            }
1030          SH_FREE(uuid);
1031        }
1032      else
1033        {
1034          /* not initialized yet */
1035          sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, -1, MSG_E_SUBGEN,
1036                          _("Download of delta DB skipped, not initialized yet"), 
1037                          _("sh_dbIO_load_delta"));
1038          return -1;
1039        }
1040    }
1041#endif
1042  return status;
1043}
1044
1045/******************************************************************
1046 *
1047 * Writing out a file to the database.
1048 *
1049 ******************************************************************/ 
1050static int       pushdata_isfirst =  1;
1051static SL_TICKET pushdata_fd      = -1;
1052
1053static int       pushdata_stdout  =  S_FALSE;
1054
1055static char * sh_db_version_string = NULL;
1056
1057int sh_dbIO_writeout_stdout (const char * str)
1058{
1059  if (!str)
1060    { pushdata_stdout  =  S_TRUE; return 0; }
1061  return -1;
1062}
1063
1064int sh_dbIO_version_string(const char * str)
1065{
1066  if (str)
1067    {
1068      if (sh_db_version_string != NULL) {
1069        SH_FREE(sh_db_version_string);
1070      }
1071      if (0 == sl_strncmp(str, _("NULL"), 4))
1072        {
1073          sh_db_version_string = NULL;
1074          return 0;
1075        }
1076      sh_db_version_string = sh_util_strdup(str);
1077      return 0;
1078    }
1079  return -1;
1080}
1081
1082void do_writeout_checks(const char * outpath)
1083{
1084  if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
1085    {
1086      dlog(1, FIL__, __LINE__, 
1087           _("You cannot write the database to stdout when you use update rather than init.\n"));
1088      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1089                      _("Writing database to stdout with update"), 
1090                      sh.prg_name, 
1091                      _("sh_dbIO_data_write_int"));
1092      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1093    }
1094
1095  if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
1096    {
1097      dlog(1, FIL__, __LINE__, 
1098           _("You cannot write the database to stdout when running with suid privileges.\n"));
1099      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1100                      _("Writing database to stdout when suid"), 
1101                      sh.prg_name, 
1102                      _("sh_dbIO_data_write_int"));
1103      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1104    }
1105
1106
1107  if ( (pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) && 
1108       ( (NULL == outpath) || (0 == sl_strcmp(outpath, _("REQ_FROM_SERVER"))) ) )
1109    {
1110      dlog(1, FIL__, __LINE__, 
1111           _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
1112      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
1113                      _("No local path for database specified"), 
1114                      sh.prg_name, 
1115                      _("sh_dbIO_data_write_int"));
1116      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1117    }
1118
1119  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE)) 
1120    {
1121      /* Warn that file already exists; file_path != NULL here because
1122       * checked above
1123       */
1124      struct stat sbuf;
1125
1126      if (0 == retry_lstat(FIL__, __LINE__, outpath, &sbuf))
1127        {
1128          if (sh.flag.update == S_FALSE)
1129            {
1130              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
1131                              file_path('D', 'W'));
1132            }
1133        }
1134    }
1135
1136  return;
1137}
1138
1139static SL_TICKET open_writeout_data_truncate(const char * path)
1140{
1141  int status;
1142  SL_TICKET fd;
1143
1144  if ( SL_ISERROR(fd = sl_open_rdwr_trunc(FIL__, __LINE__, path, SL_YESPRIV))) 
1145    {
1146      sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
1147                      geteuid(), path);
1148      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1149    }
1150
1151  if (SL_ISERROR(status = sl_lock (fd)))
1152    {
1153      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1154                      _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
1155                      path);
1156      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1157    }
1158  return fd;
1159}
1160
1161static SL_TICKET open_writeout_data(const char * path)
1162{
1163  int status;
1164  SL_TICKET fd;
1165
1166  if ( SL_ISERROR(fd = sl_open_rdwr(FIL__, __LINE__, path, SL_YESPRIV))) 
1167    {
1168      sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
1169                      geteuid(), path);
1170      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1171    }
1172
1173  if (SL_ISERROR(status = sl_lock (fd)))
1174    {
1175      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1176                      _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
1177                      path);
1178      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1179    }
1180  return fd;
1181}
1182
1183static void seek_writeout_data(SL_TICKET fd, const char * path)
1184{
1185  int status;
1186
1187  if ( SL_ISERROR(status = sl_forward(fd))) 
1188    {
1189      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
1190                      _("Failed to seek to end of baseline database"),
1191                      _("seek_writeout_data"),
1192                      path);
1193      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1194    }
1195  return;
1196}
1197
1198/* Seek to [SOF] and truncate remainder
1199 */
1200static int seek_writeout_data_old(SL_TICKET fd, const char * path)
1201{
1202  char * line = SH_ALLOC(MAX_PATH_STORE+1);
1203
1204  /* This will do an ftruncate() after the sof marker
1205   */
1206  if (SL_ISERROR(sh_dbIO_setdataent_old (fd, line, MAX_PATH_STORE, path)))
1207    {
1208      SH_FREE(line);
1209      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1210                      _("Failed to seek to start of baseline database"),
1211                      _("seek_writeout_data_old"),
1212                      path);
1213      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1214    }
1215  SH_FREE(line);
1216  return 0;
1217}
1218
1219char * prep_path(char * path, int flag)
1220{
1221  size_t old_len = sl_strlen(path);
1222  char * tmp;
1223  size_t tmp_len;
1224  size_t path_len;
1225  char * outpath = NULL;
1226#if !defined(SH_STEALTH)
1227  (void) flag;
1228#endif
1229
1230#if defined(SH_STEALTH)
1231  if (flag == S_TRUE)
1232    sh_do_encode(path, old_len);
1233#endif
1234  tmp = quote_string(path, old_len);
1235  tmp_len = sl_strlen(tmp);
1236#if defined(SH_STEALTH)
1237  if (flag == S_TRUE)
1238    sh_do_decode(path, old_len);
1239#endif
1240
1241  if (tmp && tmp_len <= MAX_PATH_STORE) 
1242    {
1243      outpath = sh_util_strdup(path);
1244    } 
1245  else 
1246    {
1247      char hashbuf[KEYBUF_SIZE];
1248     
1249      outpath = sh_util_strdup(sh_tiger_hash (path,
1250                                              TIGER_DATA, old_len, 
1251                                              hashbuf, sizeof(hashbuf)));
1252    }
1253  if (tmp) 
1254    SH_FREE(tmp);
1255
1256  path_len = sl_strlen(outpath);
1257#if defined(SH_STEALTH)
1258  if (flag == S_TRUE)
1259    sh_do_encode(outpath, path_len);
1260#endif
1261 
1262  tmp = quote_string(outpath, path_len);
1263  if (tmp) {
1264    SH_FREE(outpath);
1265    outpath = tmp;
1266  }
1267  return outpath;
1268}
1269
1270static char * prep_attr(char * attr_str)
1271{
1272  char * tmp;
1273  char * outstr = NULL;
1274  size_t old_len = sl_strlen(attr_str);
1275
1276#if defined(SH_STEALTH)
1277  sh_do_encode(attr_str, old_len);
1278#endif
1279
1280  tmp = quote_string(attr_str, old_len);
1281  if (tmp)
1282    {
1283      outstr = tmp;
1284    }
1285
1286#if defined(SH_STEALTH)
1287  sh_do_decode(attr_str, old_len);
1288#endif
1289  return outstr;
1290}
1291
1292static void prep_encode(sh_filestore_t * p)
1293{
1294#if defined(SH_STEALTH)
1295  sh_do_encode(p->c_mode,   sl_strlen(p->c_mode));
1296  sh_do_encode(p->c_owner,  sl_strlen(p->c_owner));
1297  sh_do_encode(p->c_group,  sl_strlen(p->c_group));
1298  sh_do_encode(p->checksum, sl_strlen(p->checksum));
1299  sh_do_encode(p->c_attributes,   sl_strlen(p->c_attributes));
1300#else
1301  (void) p;
1302#endif
1303  return;
1304}
1305
1306static void prep_struct(sh_filestore_t * p, file_type * buf, char * fileHash)
1307{
1308#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
1309  int    i;
1310#endif
1311  p->mark = REC_MAGIC;
1312  sl_strlcpy(p->c_mode,   buf->c_mode,   CMODE_SIZE);
1313  sl_strlcpy(p->c_group,  buf->c_group,  GROUP_MAX+1);
1314  sl_strlcpy(p->c_owner,  buf->c_owner,  USER_MAX+1);
1315  if (fileHash) {
1316    sl_strlcpy(p->checksum, fileHash,      KEY_LEN+1);
1317  }
1318#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1319  sl_strlcpy(p->c_attributes, buf->c_attributes, ATTRBUF_SIZE);
1320#else
1321  for (i = 0; i < ATTRBUF_USED; ++i) p->c_attributes[i] = '-';
1322  p->c_attributes[ATTRBUF_USED] = '\0';
1323#endif
1324 
1325  prep_encode(p);
1326 
1327#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1328  p->attributes  = (UINT32) buf->attributes;
1329#else
1330  p->attributes  = 0;
1331#endif
1332  p->linkmode    = (UINT32) buf->linkmode;
1333  p->hardlinks   = (UINT32) buf->hardlinks;
1334  p->dev   = (UINT64) buf->dev;
1335  p->rdev  = (UINT64) buf->rdev;
1336  p->mode  = (UINT32) buf->mode;
1337  p->ino   = (UINT32) buf->ino;
1338  p->size  = (UINT64) buf->size;
1339  p->mtime = (UINT64) buf->mtime;
1340  p->atime = (UINT64) buf->atime;
1341  p->ctime = (UINT64) buf->ctime;
1342  p->owner = (UINT32) buf->owner;
1343  p->group = (UINT32) buf->group;
1344
1345  p->checkflags = (UINT32) buf->check_flags; 
1346 
1347  return;
1348}
1349
1350
1351static void write_start_header(SL_TICKET fd)
1352{
1353  char   timestring[81];
1354
1355  if (pushdata_stdout == S_FALSE)
1356    {
1357      sl_write (fd, _("\n#Host "), 7);
1358      sl_write (fd, sh.host.name, 
1359                sl_strlen(sh.host.name));
1360      sl_write (fd, _(" Version "), 9);
1361      sl_write (fd, sh_db_version_string, 
1362                sl_strlen(sh_db_version_string));
1363      sl_write (fd, _(" Date "), 6);
1364      (void) sh_unix_time(0, timestring, sizeof(timestring));
1365      sl_write (fd, timestring, strlen(timestring));
1366      sl_write (fd,        "\n", 1);
1367    } 
1368  else 
1369    {
1370      printf ("%s",_("\n#Host "));
1371      printf ("%s", sh.host.name);
1372      printf ("%s",_(" Version "));
1373      printf ("%s", sh_db_version_string);
1374      printf ("%s",_(" Date "));
1375      (void) sh_unix_time(0, timestring, sizeof(timestring));
1376      printf ("%s\n", timestring);
1377    }
1378}
1379
1380static void write_start_marker(SL_TICKET fd)
1381{
1382  if (sh_db_version_string != NULL)
1383    {
1384      write_start_header(fd);
1385    }
1386 
1387  if (pushdata_stdout == S_FALSE)
1388    {
1389#if defined(SH_STEALTH)
1390      sl_write      (fd,        "\n", 1);
1391      sl_write_line (fd, N_("[SOF]"), 5);
1392#else
1393      sl_write_line (fd, _("\n[SOF]"),  6);
1394#endif
1395    }
1396  else 
1397    {
1398#if defined(SH_STEALTH)
1399      puts (N_("[SOF]"));
1400#else
1401      puts (_("\n[SOF]"));
1402#endif
1403    }
1404}
1405
1406static void   write_record(SL_TICKET fd, sh_filestore_t * p, 
1407                           char * fullpath, char * linkpath, char * attr_string)
1408{
1409  static char ll[2] = { '-', '\0' };
1410  char * lpath;
1411
1412  if (!linkpath || 0 == sl_strlen(linkpath))
1413    lpath = ll;
1414  else
1415    lpath = linkpath;
1416
1417  if (pushdata_stdout == S_FALSE)
1418    {
1419      if (SL_ENONE != sl_write (fd,        p, sizeof(sh_filestore_t)))
1420        {
1421          char * tmp = sh_util_safe_name(fullpath);
1422          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1423                          _("Failed to write record to baseline database"),
1424                          _("write_record"),
1425                          tmp);
1426          SH_FREE(tmp);
1427          aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
1428        }
1429      if (SL_ENONE != sl_write_line_fast (fd, fullpath, sl_strlen(fullpath)))
1430        {
1431          char * tmp = sh_util_safe_name(fullpath);
1432          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1433                          _("Failed to write path to baseline database"),
1434                          _("write_record"),
1435                          tmp);
1436          SH_FREE(tmp);
1437          aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
1438        }
1439      if (SL_ENONE != sl_write_line_fast (fd,    lpath, sl_strlen(lpath)))
1440        {
1441          char * tmp = sh_util_safe_name(fullpath);
1442          sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1443                          _("Failed to write lpath to baseline database"),
1444                          _("write_record"),
1445                          tmp);
1446          SH_FREE(tmp);
1447          aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
1448        }
1449      if (attr_string)
1450        sl_write_line_fast (fd, attr_string, sl_strlen(attr_string));
1451    } 
1452  else 
1453    {
1454      if (fwrite (p, sizeof(sh_filestore_t), 1, stdout))
1455        {
1456          puts (fullpath);
1457          puts (lpath);
1458          if (attr_string)
1459            puts (attr_string);
1460        }
1461      else
1462        {
1463          perror(_("Error writing database"));
1464          aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1465        }
1466    }
1467
1468  SH_FREE(fullpath);
1469  if (linkpath)
1470    SH_FREE(linkpath);
1471  if (attr_string)
1472    SH_FREE(attr_string);
1473
1474  return;
1475}
1476
1477static void sh_dbIO_data_write_int (file_type * buf, char * fileHash, 
1478                                    const char * outpath, int truncate)
1479{
1480  static long p_count = 0;
1481  sh_filestore_t p;
1482  char *  fullpath = NULL;
1483  char *  linkpath = NULL;
1484  char *  attr_string = NULL;
1485
1486  SL_ENTER(_("sh_dbIO_data_write_int"));
1487
1488  do_writeout_checks(outpath);
1489
1490  if (sh.flag.update == S_FALSE)
1491    {
1492      if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
1493        {
1494          if (truncate == S_TRUE)
1495            pushdata_fd = open_writeout_data_truncate(outpath);
1496          else
1497            {
1498              pushdata_fd = open_writeout_data(outpath);
1499              /* Seek to eof */
1500              seek_writeout_data(pushdata_fd, outpath);
1501            }
1502        }
1503    }
1504  else /* update == TRUE */
1505    {
1506      if (pushdata_isfirst == 1)
1507        {
1508          TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")));
1509          pushdata_fd = open_writeout_data(outpath);
1510          /* Seek to sof and truncate */
1511          seek_writeout_data_old(pushdata_fd, outpath);
1512        }
1513    }
1514
1515  /* unconditionally initialize the structure */
1516  memset(&p, 0, sizeof(sh_filestore_t));
1517
1518  if (buf != NULL) 
1519    {
1520      fullpath = prep_path(buf->fullpath, S_TRUE);
1521    }
1522
1523  /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded
1524   */
1525  if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL) 
1526    { 
1527      if (buf->c_mode[0] == 'l')
1528        linkpath = prep_path(buf->link_path, S_TRUE);
1529      else
1530        linkpath = prep_path(buf->link_path, S_FALSE);
1531    }
1532
1533  if (buf != NULL && buf->attr_string != NULL) 
1534    {
1535      attr_string = prep_attr(buf->attr_string);
1536    }
1537
1538  if (buf != NULL) 
1539    {
1540      prep_struct(&p, buf, fileHash);
1541      if (attr_string)
1542        p.mark |= REC_FLAGS_ATTR;
1543      swap_data(&p);
1544    }
1545
1546  /* write the start marker
1547   */
1548  if (pushdata_isfirst == 1) 
1549    {
1550      if (sh.flag.update == S_FALSE)
1551        write_start_marker(pushdata_fd);
1552      pushdata_isfirst = 0;
1553    }
1554
1555  if (buf && fullpath)
1556    {
1557      write_record(pushdata_fd, &p, fullpath, linkpath, attr_string);
1558      ++p_count;
1559    }
1560
1561  if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
1562    {
1563      if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
1564        {
1565          if (SL_ISERROR(sl_close (pushdata_fd))) 
1566            {
1567              char * tmp = sh_util_safe_name(outpath);
1568              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
1569                              _("Failed to close baseline database"),
1570                              _("sh_dbIO_data_write_int"),
1571                              tmp);
1572              SH_FREE(tmp);
1573            }
1574          else {
1575            if (sh.flag.checkSum == SH_CHECK_INIT)
1576              sh_error_handle((-1), FIL__, __LINE__, 0, MSG_DCLOSE);
1577          }
1578          pushdata_fd = -1;
1579        }
1580    }
1581
1582  SL_RET0(_("sh_dbIO_data_write_int"));
1583}
1584
1585SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
1586
1587void sh_dbIO_data_write (file_type * buf, char * fileHash)
1588{
1589  SH_MUTEX_LOCK(mutex_writeout); 
1590  sh_dbIO_data_write_int (buf, fileHash, file_path('D', 'W'), S_FALSE);
1591  SH_MUTEX_UNLOCK(mutex_writeout); 
1592  return;
1593}
1594
1595
1596static int dbIO_writeout(sh_file_t * mtab[TABSIZE], const char * outpath, int truncate)
1597{
1598  sh_file_t * p;
1599  int         i;
1600  file_type * f;
1601  char   fileHash[KEY_LEN + 1];
1602
1603  SL_ENTER(_("dbIO_writeout"));
1604
1605  SH_MUTEX_LOCK(mutex_writeout); 
1606  if (!SL_ISERROR(pushdata_fd))
1607    {
1608      sl_close(pushdata_fd);
1609      pushdata_fd = -1;
1610    }
1611  pushdata_isfirst =  1;
1612
1613
1614  SH_MUTEX_LOCK(mutex_hash);
1615  for (i = 0; i < TABSIZE; ++i)
1616    {
1617      for (p = mtab[i]; p; p = p->next)
1618        {
1619          f = sh_hash_create_ft (p, fileHash);
1620          sh_dbIO_data_write_int (f, fileHash, outpath, (i == 0) ? truncate : S_FALSE);
1621          if (f->attr_string) SH_FREE(f->attr_string);
1622          if (f->link_path)   SH_FREE(f->link_path);
1623          SH_FREE(f);
1624        }
1625    }
1626  SH_MUTEX_UNLOCK(mutex_hash);
1627
1628  if (!SL_ISERROR(pushdata_fd))
1629    {
1630      sl_close(pushdata_fd);
1631      pushdata_fd = -1;
1632    }
1633  pushdata_isfirst =  1;
1634  SH_MUTEX_UNLOCK(mutex_writeout); 
1635
1636  SL_RETURN (0, _("dbIO_writeout"));
1637}
1638
1639int sh_dbIO_writeout_update()
1640{
1641  sh_file_t ** mtab = get_default_data_table();
1642
1643  if (S_TRUE == file_is_remote())
1644    {
1645      sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN, 
1646                      _("Baseline database is remote"), _("sh_dbIO_writeout"));
1647      SL_RETURN (1, _("sh_dbIO_writeout_update"));
1648    }
1649
1650  return dbIO_writeout(mtab, file_path('D', 'W'), S_FALSE);
1651}
1652
1653int sh_dbIO_writeout_to_path(const char * path)
1654{
1655  sh_file_t ** mtab = get_default_data_table();
1656  return dbIO_writeout(mtab, path, S_TRUE);
1657}
1658
1659static void dbIO_write_record(sh_file_t * record, SL_TICKET fd)
1660{
1661  sh_filestore_t * p = &(record->theFile);
1662  char * fullpath    = NULL;
1663  char * linkpath    = NULL;
1664  char * attr_string = NULL;
1665
1666  fullpath = prep_path(record->fullpath, S_TRUE);
1667
1668  /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded
1669   */
1670  if (record->linkpath != NULL && 0 != strcmp("-", record->linkpath)) 
1671    { 
1672      if (p->c_mode[0] == 'l')
1673        linkpath = prep_path(record->linkpath, S_TRUE);
1674      else
1675        linkpath = prep_path(record->linkpath, S_FALSE);
1676    }
1677
1678  if (record->attr_string != NULL) 
1679    attr_string = prep_attr(record->attr_string);
1680
1681  prep_encode(p);
1682  swap_data(p);
1683
1684  write_record(fd, p, fullpath, linkpath, attr_string);
1685  return;
1686}
1687
1688static void dbIO_write_entry(sh_file_t * p)
1689{
1690  static int is_first = 1;
1691
1692  if (is_first)
1693    {
1694      pushdata_isfirst =  1;
1695      if (!sh.outpath || sh.outpath[0] == '\0') 
1696        pushdata_stdout  =  S_TRUE;
1697      else
1698        pushdata_fd = open_writeout_data_truncate(sh.outpath);
1699      write_start_marker(pushdata_fd);
1700      pushdata_isfirst = 0;
1701      is_first = 0;
1702    }
1703
1704  dbIO_write_record(p, pushdata_fd);
1705
1706}
1707
1708
1709/******************************************************************
1710 *
1711 * Listing the database.
1712 *
1713 ******************************************************************/ 
1714
1715static int ListBinary = S_FALSE;
1716static char * ListFilter = NULL;
1717
1718int sh_dbIO_list_binary (const char * c)
1719{
1720  (void) c;
1721  ListBinary = S_TRUE;
1722  return 0;
1723}
1724int sh_dbIO_list_filter (const char * c)
1725{
1726  ListFilter = sh_util_strdup(c);
1727  return 0;
1728}
1729
1730#include "zAVLTree.h"
1731
1732static zAVLTree * filter_list = NULL;
1733extern char * rtrim (char * str);
1734
1735#include <ctype.h>
1736static void read_filter()
1737{
1738  int    i, n = 0;
1739  size_t len;
1740  char * key;
1741  char * str;
1742  char * line = SH_ALLOC(SH_MAXBUF);
1743  FILE * fd   = fopen(ListFilter, "r");
1744 
1745  if (!fd)
1746    {
1747      perror(_("read_filter: fopen:"));
1748      _exit(EXIT_FAILURE);
1749    }
1750  do {
1751    i = sh_dbIO_getline (fd, line, SH_MAXBUF);
1752    str = rtrim(line);
1753    while (isspace((int)*str)) ++str;
1754
1755    key = sh_files_parse_input(str, &len);
1756
1757    if (key && *key == '/')
1758      {
1759        zAVL_string_set(&filter_list, key);
1760        ++n;
1761      }
1762  } while (i >= 0);
1763
1764  fclose(fd);
1765  SH_FREE(line);
1766
1767  if (n == 0)
1768    {
1769      fprintf(stderr, _("read_filter: empty file <%s>\n"), ListFilter);
1770      _exit (EXIT_FAILURE);
1771    }
1772  return;
1773}
1774
1775static int check_filter(char * path)
1776{
1777  if (NULL == zAVL_string_get(filter_list, path))
1778    return S_FALSE;
1779  return S_TRUE;
1780}
1781
1782int sh_dbIO_list_db (const char * db_file)
1783{
1784  sh_file_t * p;
1785  SL_TICKET fd;
1786  char * line;
1787  int  errflag = 0;
1788  int  flag = 0;
1789  char * ListFile = get_list_file();
1790
1791  if (!db_file)
1792    {
1793      fputs(_("ERROR: no database file given\n"), stderr);
1794      _exit(EXIT_FAILURE);
1795      return -1; 
1796    }
1797  if (sl_is_suid())
1798    {
1799      fputs(_("ERROR: insufficient privilege\n"), stderr);
1800      _exit (EXIT_FAILURE);
1801      return -1; /* for Mac OSX compiler */
1802    }
1803  if (0 == strcmp(db_file, _("default")))
1804    db_file = file_path('D', 'W');
1805  if (!db_file)
1806    {
1807      fputs(_("ERROR: no filename\n"), stderr);
1808      _exit(EXIT_FAILURE);
1809      return -1; 
1810    }
1811
1812  if (ListFilter) 
1813    read_filter();
1814
1815  line = SH_ALLOC(MAX_PATH_STORE+2);
1816
1817  if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV))) 
1818    {
1819      fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"), 
1820              db_file, fd);
1821      _exit(EXIT_FAILURE);
1822      return -1; 
1823    }
1824
1825  /* fast forward to start of data
1826   */
1827  if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, db_file))
1828    {
1829      fprintf(stderr, _("ERROR: can't find start marker in %s\n"), 
1830              db_file);
1831      _exit(EXIT_FAILURE);
1832      return -1; 
1833    }
1834
1835  while (1) 
1836    {
1837      p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, db_file, &errflag);
1838      if ((p != NULL) && (p->fullpath[0] == '/'))
1839        {
1840          if (!ListFile)
1841            {
1842              flag = 1;
1843              if (ListFilter && S_FALSE == check_filter(p->fullpath))
1844                continue;
1845              if (ListBinary)
1846                dbIO_write_entry (p);
1847              else
1848                sh_hash_list_db_entry (p); 
1849            }
1850          else
1851            {
1852              if (0 != sl_strcmp(ListFile, p->fullpath))
1853                {
1854                  continue;
1855                }
1856              flag = 1;
1857              if ('l' != p->theFile.c_mode[0])
1858                {
1859                  if (sh_hash_printcontent(p->linkpath) < 0)
1860                    {
1861                      fputs(_("Error listing file content\n"), stderr);
1862                      _exit(EXIT_FAILURE);
1863                      return -1;
1864                    }
1865                }
1866              else
1867                {
1868                  fputs(_("File is a link\n"), stderr);
1869                  _exit(EXIT_FAILURE);
1870                  return -1;
1871                }
1872              break;
1873            }
1874        }
1875      else if (p == NULL)
1876        {
1877          break;
1878        }
1879    }
1880
1881  if (line != NULL)
1882    SH_FREE(line);
1883  sl_close (fd);
1884
1885  fflush(NULL);
1886
1887  if (flag == 0)
1888    {
1889      fputs(_("File not found.\n"), stderr);
1890      _exit(EXIT_FAILURE);
1891    }
1892  else if (errflag < 0)
1893    {
1894      fputs(_("Error while reading file.\n"), stderr);
1895      _exit(EXIT_FAILURE);
1896    }
1897     
1898  _exit(EXIT_SUCCESS);
1899  return 0; 
1900}
1901
1902/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
1903#endif
Note: See TracBrowser for help on using the repository browser.