source: trunk/src/sh_dbIO.c@ 572

Last change on this file since 572 was 564, checked in by katerina, 3 years 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.