source: trunk/src/sh_dbIO.c@ 533

Last change on this file since 533 was 525, checked in by katerina, 7 years ago

Log error if the close() on the baseline database fails (ticket #420).

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