source: trunk/src/sh_dbIO.c@ 482

Last change on this file since 482 was 481, checked in by katerina, 9 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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