source: trunk/src/sh_dbIO.c@ 583

Last change on this file since 583 was 579, checked in by katerina, 18 months ago

Fix for ticket #467 (memleak).

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