source: trunk/src/sh_dbIO.c@ 486

Last change on this file since 486 was 483, checked in by katerina, 9 years ago

Fix for ticket #381 (BSD suid check compile failure).

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