source: trunk/src/sh_hash.c@ 526

Last change on this file since 526 was 516, checked in by katerina, 8 years ago

Fix for ticket #409 and #410 (unprivileged suidcheck and gcc 6.2 compiler warnings).

File size: 79.3 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000, 2001, 2002 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 <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
[444]28#include <ctype.h>
[1]29
30#ifdef MAJOR_IN_MKDEV
31#include <sys/mkdev.h>
32#else
33#ifdef MAJOR_IN_SYSMACROS
34#include <sys/sysmacros.h>
35#endif
36#endif
37
38#ifdef HAVE_MEMORY_H
39#include <memory.h>
40#endif
41
[481]42
[1]43#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
44
[481]45#include "samhain.h"
46#include "sh_utils.h"
47#include "sh_unix.h"
48#include "sh_dbIO_int.h"
49#include "sh_dbIO.h"
[1]50#include "sh_hash.h"
51#include "sh_error.h"
52#include "sh_tiger.h"
53#include "sh_gpg.h"
54#include "sh_unix.h"
55#include "sh_files.h"
56#include "sh_ignore.h"
[149]57#include "sh_pthread.h"
[1]58
59#if defined(SH_WITH_CLIENT)
[481]60#include "sh_xfer.h"
[1]61#endif
62
[105]63
64#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
65
66
[1]67#undef FIL__
68#define FIL__ _("sh_hash.c")
69
[481]70SH_MUTEX_INIT(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
[149]71
[1]72static char * all_items (file_type * theFile, char * fileHash, int is_new);
73
[481]74static const char *policy[] = {
75 N_("[]"),
76 N_("[ReadOnly]"),
77 N_("[LogFiles]"),
78 N_("[GrowingLogs]"),
79 N_("[IgnoreNone]"),
80 N_("[IgnoreAll]"),
81 N_("[Attributes]"),
82 N_("[User0]"),
83 N_("[User1]"),
84 N_("[User2]"),
85 N_("[User3]"),
86 N_("[User4]"),
87 N_("[Prelink]"),
88 NULL
89};
[1]90
[481]91static int report_checkflags = S_FALSE;
92int set_report_checkflags(const char * c)
[1]93{
[481]94 return sh_util_flagval(c, &report_checkflags);
[1]95}
[481]96int get_report_checkflags()
[1]97{
[481]98 return report_checkflags;
[1]99}
100
[34]101
[1]102
[356]103const char * sh_hash_getpolicy(int class)
104{
105 if (class > 0 && class < SH_ERR_T_DIR)
106 return _(policy[class]);
107 return _("[indef]");
108}
[1]109
110/**********************************
111 *
112 * hash table functions
113 *
114 **********************************
115 */
116
117#include "sh_hash.h"
118
119
120/**************************************************************
121 *
122 * create a file_type from a sh_file_t
123 *
124 **************************************************************/
[481]125file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
[1]126{
127 file_type * theFile;
128
129 SL_ENTER(_("sh_hash_create_ft"));
130
131 theFile = SH_ALLOC(sizeof(file_type));
132
133 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
134 theFile->mode = p->theFile.mode;
[10]135#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[149]136 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
[1]137 theFile->attributes = p->theFile.attributes;
138#endif
139
140 sl_strlcpy(theFile->fullpath, p->fullpath, PATH_MAX);
[167]141 if (p->linkpath != NULL /* && theFile->c_mode[0] == 'l' */)
[1]142 {
[167]143 theFile->link_path = sh_util_strdup(p->linkpath);
[1]144 }
145 else
146 {
[167]147 theFile->link_path = NULL;
[1]148 }
149 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
150
151 theFile->mtime = p->theFile.mtime;
152 theFile->ctime = p->theFile.ctime;
153 theFile->atime = p->theFile.atime;
154
155 theFile->size = p->theFile.size;
156
157 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
158 theFile->group = p->theFile.group;
159 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
160 theFile->owner = p->theFile.owner;
161
162 theFile->ino = p->theFile.ino;
163 theFile->rdev = p->theFile.rdev;
164 theFile->dev = p->theFile.dev;
165 theFile->hardlinks = p->theFile.hardlinks;
[481]166 theFile->check_flags = p->theFile.checkflags;
[1]167
[68]168 if (p->attr_string)
169 theFile->attr_string = sh_util_strdup(p->attr_string);
170 else
171 theFile->attr_string = NULL;
172
[1]173 SL_RETURN((theFile), _("sh_hash_create_ft"));
174}
175
[305]176struct two_sh_file_t {
177 sh_file_t * prev;
178 sh_file_t * this;
179};
180
[294]181static sh_file_t * hashsearch (const char * s);
[305]182static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index);
[1]183
[481]184
185/**************************************************************
186 *
187 * >>>> The internal database <<<
188 *
189 **************************************************************/
190
[1]191static sh_file_t * tab[TABSIZE];
192
[481]193sh_file_t ** get_default_data_table()
194{
195 return tab;
196}
197
[1]198/**************************************************************
199 *
200 * compute hash function
201 *
202 **************************************************************/
[8]203
[294]204static int hashfunc(const char *s)
[1]205{
[18]206 unsigned int n = 0;
[1]207
208 for ( ; *s; s++)
209 n = 31 * n + *s;
[18]210
211 return n & (TABSIZE - 1); /* % TABSIZE */;
[1]212}
213
[8]214
[1]215int hashreport_missing( char *fullpath, int level)
216{
217 sh_file_t * p;
218 char * tmp;
219 char fileHash[KEY_LEN + 1];
220 file_type * theFile;
221 char * str;
[133]222 char hashbuf[KEYBUF_SIZE];
[367]223 volatile int retval;
[1]224
225 /* -------- find the entry for the file ---------------- */
226
[149]227 SH_MUTEX_LOCK(mutex_hash);
228
[170]229 retval = 0;
230
[1]231 if (sl_strlen(fullpath) <= MAX_PATH_STORE)
232 p = hashsearch(fullpath);
233 else
234 p = hashsearch( sh_tiger_hash(fullpath,
235 TIGER_DATA,
[133]236 sl_strlen(fullpath),
237 hashbuf, sizeof(hashbuf))
[1]238 );
239 if (p == NULL)
[149]240 {
241 retval = -1;
242 goto unlock_and_return;
243 }
[1]244
245 theFile = sh_hash_create_ft (p, fileHash);
246 str = all_items(theFile, fileHash, 0);
247 tmp = sh_util_safe_name(fullpath);
[367]248
249 SH_MUTEX_LOCK(mutex_thread_nolog);
[488]250 if (!sh_global_check_silent)
251 sh_error_handle (level, FIL__, __LINE__, 0,
252 MSG_FI_MISS2, tmp, str);
[367]253 SH_MUTEX_UNLOCK(mutex_thread_nolog);
[405]254 ++sh.statistics.files_report;
[362]255
[1]256 SH_FREE(tmp);
257 SH_FREE(str);
[167]258 if (theFile->attr_string) SH_FREE(theFile->attr_string);
259 if (theFile->link_path) SH_FREE(theFile->link_path);
[1]260 SH_FREE(theFile);
[149]261
262 unlock_and_return:
[153]263 ; /* 'label at end of compound statement */
[149]264 SH_MUTEX_UNLOCK(mutex_hash);
[305]265
[458]266 /* remove here to avoid second message from hash_unvisited */
267 if (retval == 0)
268 sh_hash_remove (fullpath);
269
[149]270 return retval;
[1]271}
272
273
274/**************************************************************
275 *
276 * search for files not visited, and check whether they exist
277 *
278 **************************************************************/
[294]279static sh_file_t * delete_db_entry(sh_file_t *p)
280{
281 if (p->fullpath)
282 {
283 SH_FREE(p->fullpath);
284 p->fullpath = NULL;
285 }
286 if (p->linkpath)
287 {
[481]288 SH_FREE(p->linkpath);
[294]289 p->linkpath = NULL;
290 }
291 if (p->attr_string)
292 {
293 SH_FREE(p->attr_string);
294 p->attr_string = NULL;
295 }
296 SH_FREE(p);
297 return NULL;
298}
299
[1]300static void hash_unvisited (int j,
301 sh_file_t *prev, sh_file_t *p, ShErrLevel level)
302{
303 struct stat buf;
304 int i;
305 char * tmp;
306 char * ptr;
307 char fileHash[KEY_LEN + 1];
308 file_type * theFile;
309 char * str;
310
311 SL_ENTER(_("hash_unvisited"));
312
313 if (p->next != NULL)
314 hash_unvisited (j, p, p->next, level);
315
316 if (p->fullpath == NULL)
317 {
318 SL_RET0(_("hash_unvisited"));
319 }
320
[114]321 /* Not a fully qualified path, i.e. some info stored by some module
[1]322 */
[114]323 if (p->fullpath[0] != '/')
[1]324 {
325 SL_RET0(_("hash_unvisited"));
326 }
[458]327
[114]328 /* visited flag not set: not seen;
329 * checked flag set: not seen (i.e. missing), and already checked
330 * reported flag not set: not reported yet
331 * allignore flag not set: not under IgnoreAll
[1]332 *
333 * Files/directories under IgnoreAll are noticed as missing already
334 * during the file check.
335 */
[114]336 if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags))
337 && (!SH_FFLAG_REPORTED_SET(p->fflags))
[481]338 /* && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)) */)
[1]339 {
340 i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
[458]341
[457]342 /* if file does not exist
[1]343 */
344 if (0 != i)
345 {
[34]346 ptr = sh_util_dirname (p->fullpath);
[1]347 if (ptr)
348 {
349 /* If any of the parent directories is under IgnoreAll
350 */
[481]351 if ((0 != sh_files_is_allignore(ptr)) || SH_FFLAG_ALLIGNORE_SET(p->fflags))
[1]352 level = ShDFLevel[SH_LEVEL_ALLIGNORE];
353 SH_FREE(ptr);
354 }
[114]355
356 /* Only report if !SH_FFLAG_CHECKED_SET
357 */
358 if (!SH_FFLAG_CHECKED_SET(p->fflags))
[1]359 {
360 if (S_FALSE == sh_ignore_chk_del(p->fullpath))
361 {
362 tmp = sh_util_safe_name(p->fullpath);
363
364 theFile = sh_hash_create_ft (p, fileHash);
365 str = all_items(theFile, fileHash, 0);
[488]366 if (!sh_global_check_silent)
367 sh_error_handle (level, FIL__, __LINE__, 0,
368 MSG_FI_MISS2, tmp, str);
[405]369 ++sh.statistics.files_report;
[1]370 SH_FREE(str);
[167]371 if (theFile->attr_string) SH_FREE(theFile->attr_string);
372 if (theFile->link_path) SH_FREE(theFile->link_path);
[1]373 SH_FREE(theFile);
374
375 SH_FREE(tmp);
376 }
377 }
378
[77]379 /* We rewrite the db on update, thus we need to keep this
[1]380 * if the user does not want to purge it from the db.
381 */
382
[77]383 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
384 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
[1]385 {
386 /* Remove the old entry
387 */
388 if (prev == p)
389 tab[j] = p->next;
390 else
391 prev->next = p->next;
[294]392
[383]393 delete_db_entry(p);
[294]394
[1]395 SL_RET0(_("hash_unvisited"));
396 }
397 }
398 }
399
[114]400 else if (SH_FFLAG_VISITED_SET(p->fflags) && SH_FFLAG_REPORTED_SET(p->fflags)
401 && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
[1]402 {
403 if (S_FALSE == sh_ignore_chk_new(p->fullpath))
404 {
405 tmp = sh_util_safe_name(p->fullpath);
406
407 theFile = sh_hash_create_ft (p, fileHash);
408 str = all_items(theFile, fileHash, 0);
[488]409 if (!sh_global_check_silent)
410 sh_error_handle (level, FIL__, __LINE__, 0,
411 MSG_FI_MISS2, tmp, str);
[405]412 ++sh.statistics.files_report;
[1]413 SH_FREE(str);
[68]414 if (theFile->attr_string)
415 SH_FREE(theFile->attr_string);
[1]416 SH_FREE(theFile);
417
418 SH_FREE(tmp);
419 }
420
[114]421 CLEAR_SH_FFLAG_REPORTED(p->fflags);
[1]422 }
423
424 if (sh.flag.reportonce == S_FALSE)
[114]425 CLEAR_SH_FFLAG_REPORTED(p->fflags);
[1]426
[114]427 CLEAR_SH_FFLAG_VISITED(p->fflags);
428 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[458]429 SET_SH_FFLAG_ENOENT(p->fflags);
[114]430
[1]431 SL_RET0(_("hash_unvisited"));
432}
433
434
[305]435
[1]436/*********************************************************************
437 *
438 * Search for files in the database that have been deleted from disk.
439 *
440 *********************************************************************/
441void sh_hash_unvisited (ShErrLevel level)
442{
443 int i;
444
445 SL_ENTER(_("sh_hash_unvisited"));
[149]446
447 SH_MUTEX_LOCK(mutex_hash);
[1]448 for (i = 0; i < TABSIZE; ++i)
449 {
450 if (tab[i] != NULL)
451 hash_unvisited (i, tab[i], tab[i], level);
452 }
[149]453 SH_MUTEX_UNLOCK(mutex_hash);
454
[1]455 SL_RET0(_("hash_unvisited"));
456}
457
[294]458/*********************************************************************
459 *
[305]460 * Remove a single file from the database.
461 *
462 *********************************************************************/
[481]463void sh_hash_remove_unconditional (const char * path)
[305]464{
465 struct two_sh_file_t entries;
466 int index;
467
[481]468 SL_ENTER(_("sh_hash_remove_unconditional"));
[305]469
470 SH_MUTEX_LOCK(mutex_hash);
[481]471 if (0 == hashsearch_prev (path, &entries, &index))
472 {
473 sh_file_t * p = entries.this;
474
475 /* Remove the old entry
476 */
477 if (entries.prev == p)
478 tab[index] = p->next;
479 else
480 entries.prev->next = p->next;
481
482 delete_db_entry(p);
483 }
484 SH_MUTEX_UNLOCK(mutex_hash);
[305]485
[481]486 SL_RET0(_("sh_hash_remove_unconditional"));
487}
488
489void sh_hash_remove (const char * path)
490{
491 SL_ENTER(_("sh_hash_remove"));
492
[305]493 if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) ||
494 (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
495 {
[481]496 sh_hash_remove_unconditional (path);
[305]497 }
498 SL_RET0(_("sh_hash_remove"));
499}
500
501
502/*********************************************************************
503 *
[294]504 * Search for unvisited entries in the database, custom error handler.
505 *
506 *********************************************************************/
507void sh_hash_unvisited_custom (char prefix, void(*handler)(const char * key))
508{
509 int i;
510 sh_file_t *p = NULL;
511 sh_file_t *prev = NULL;
512 sh_file_t *next = NULL;
[1]513
[294]514 SL_ENTER(_("sh_hash_unvisited_custom"));
515
516 SH_MUTEX_LOCK(mutex_hash);
517 for (i = 0; i < TABSIZE; ++i)
518 {
519 if (tab[i] != NULL)
520 {
521 p = tab[i]; prev = p;
522
523 do
524 {
525 next = p->next;
526
527 if (p->fullpath &&
528 prefix == p->fullpath[0])
529 {
530 if ((!SH_FFLAG_VISITED_SET(p->fflags))
531 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
532 {
533 handler(p->fullpath);
534
535 if (!SH_FFLAG_CHECKED_SET(p->fflags))
536 {
537 /* delete */
538 if (tab[i] == p)
539 {
540 tab[i] = p->next;
541 prev = tab[i];
542 next = prev;
543 }
544 else
545 {
546 prev->next = p->next;
547 next = prev->next;
548 }
549
550 p = delete_db_entry(p);
551 }
552 }
553 if (p)
554 {
555 CLEAR_SH_FFLAG_VISITED(p->fflags);
556 CLEAR_SH_FFLAG_CHECKED(p->fflags);
557 }
558 }
559 if (p)
560 prev = p;
561 p = next;
562 }
563 while (p);
564 }
565 }
566 SH_MUTEX_UNLOCK(mutex_hash);
567
568 SL_RET0(_("hash_unvisited_custom"));
569}
570
571
[1]572/**********************************************************************
573 *
574 * delete hash array
575 *
576 **********************************************************************/
577static void hash_kill (sh_file_t *p)
578{
579 SL_ENTER(_("hash_kill"));
580
581 if (p == NULL)
582 SL_RET0(_("hash_kill"));
583
584 if (p->next != NULL)
585 hash_kill (p->next);
586
587 if (p->fullpath)
588 {
589 SH_FREE(p->fullpath);
590 p->fullpath = NULL;
591 }
592 if (p->linkpath)
593 {
[481]594 SH_FREE(p->linkpath);
[1]595 p->linkpath = NULL;
596 }
[68]597 if (p->attr_string)
598 {
599 SH_FREE(p->attr_string);
600 p->attr_string = NULL;
601 }
[1]602 SH_FREE(p);
603 p = NULL;
604 SL_RET0(_("hash_kill"));
605}
606
607
608/***********************************************************************
609 *
610 * get info out of hash array
611 *
612 ***********************************************************************/
[294]613static sh_file_t * hashsearch (const char * s)
[1]614{
615 sh_file_t * p;
616
617 SL_ENTER(_("hashsearch"));
618
[8]619 if (s)
620 {
621 for (p = tab[hashfunc(s)]; p; p = p->next)
622 if ((p->fullpath != NULL) && (0 == strcmp(s, p->fullpath)))
623 SL_RETURN( p, _("hashsearch"));
624 }
[1]625 SL_RETURN( NULL, _("hashsearch"));
626}
627
[305]628static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index)
629{
630 sh_file_t * this;
631 sh_file_t * prev = NULL;
[1]632
[305]633 SL_ENTER(_("hashsearch_prev"));
634
635 if (s)
636 {
637 *index = hashfunc(s);
[481]638 this = tab[*index];
639 prev = this;
[305]640
641 if (this)
642 {
643 do {
644 if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
645 {
646 a->prev = prev;
[481]647 a->this = this;
[305]648 SL_RETURN( 0, _("hashsearch_prev"));
649 }
650 prev = this;
651 this = this->next;
652 } while(this);
653 }
654 }
655 SL_RETURN( -1, _("hashsearch"));
656}
657
658
[1]659/***********************************************************************
660 *
661 * insert into hash array
662 *
663 ***********************************************************************/
[481]664void hashinsert (sh_file_t * mtab[TABSIZE], sh_file_t * s)
[1]665{
666 sh_file_t * p;
[3]667 sh_file_t * q;
[1]668 int key;
669
670 SL_ENTER(_("hashinsert"));
671
672 key = hashfunc(s->fullpath);
673
[481]674 if (mtab[key] == NULL)
[1]675 {
[481]676 mtab[key] = s;
677 mtab[key]->next = NULL;
[1]678 SL_RET0(_("hashinsert"));
679 }
680 else
681 {
[481]682 p = mtab[key];
[1]683 while (1)
684 {
[481]685 if (p && p->fullpath && 0 == strcmp(s->fullpath, p->fullpath))
[1]686 {
[3]687 q = p->next;
688 SH_FREE(p->fullpath);
[481]689 if(p->linkpath) SH_FREE(p->linkpath);
690 if(p->attr_string) SH_FREE(p->attr_string);
[3]691 memcpy(p, s, sizeof(sh_file_t));
692 p->next = q;
[481]693 SH_FREE(s); s = NULL;
[1]694 SL_RET0(_("hashinsert"));
695 }
[383]696 else if (p && p->next == NULL)
697 {
698 p->next = s;
699 p->next->next = NULL;
700 SL_RET0(_("hashinsert"));
701 }
702 if (p)
703 p = p->next;
704 else /* cannot really happen, but llvm/clang does not know */
705 break;
[1]706 }
707 }
708 /* notreached */
709}
710
711
712
713/******************************************************************
714 *
715 * ------- Check functions -------
716 *
717 ******************************************************************/
718
719static int IsInit = 0;
720
[481]721void sh_hash_set_initialized()
[1]722{
[481]723 IsInit = 1;
724 return;
[1]725}
726
[481]727int sh_hash_get_initialized()
[1]728{
[481]729 return IsInit;
[1]730}
731
732
733/******************************************************************
734 *
735 * Initialize
736 *
737 ******************************************************************/
738void sh_hash_init ()
739{
[199]740 volatile int retval = 0;
741 volatile int exitval = EXIT_SUCCESS;
[185]742
[1]743 SL_ENTER(_("sh_hash_init"));
744
[463]745 if ( sh.flag.checkSum == SH_CHECK_INIT )
746 {
747 dlog(1, FIL__, __LINE__,
748 _("Attempt to load the baseline database during initialisation. This is an internal error, please report it to the developer.\n"));
749 SH_ABORT;
750 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
751 }
752
[149]753 SH_MUTEX_LOCK(mutex_hash);
[1]754
[149]755 if (IsInit == 1)
756 {
757 goto unlock_and_return;
758 }
[1]759
[149]760 /* Initialization completed.
761 */
[481]762 retval = sh_dbIO_load_db(tab);
[149]763
[481]764 if (0 == retval)
765 IsInit = 1;
766 else
767 exitval = EXIT_FAILURE;
[1]768
[149]769 unlock_and_return:
[153]770 ; /* 'label at end of compound statement */
[149]771 SH_MUTEX_UNLOCK(mutex_hash);
[185]772 if (retval == 0)
773 {
774 SL_RET0(_("sh_hash_init"));
775 }
[481]776 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
[185]777 aud_exit (FIL__, __LINE__, exitval);
[1]778}
[481]779
780void sh_hash_init_and_checksum()
781{
782 TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
783 if (sh.flag.checkSum == SH_CHECK_CHECK)
784 {
785 if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
786 {
787 char hashbuf[KEYBUF_SIZE];
788 (void) sl_strlcpy(sh.data.hash,
789 sh_tiger_hash (file_path('D', 'R'),
790 TIGER_FILE, TIGER_NOLIM,
791 hashbuf, sizeof(hashbuf)),
792 KEY_LEN+1);
793 }
794
795 /* this eventually fetches the file from server to get checksum
796 */
797 sh_hash_init ();
798 }
799 return;
800}
[1]801
802/*****************************************************************
803 *
804 * delete hash array
805 *
806 *****************************************************************/
807void sh_hash_hashdelete ()
808{
809 int i;
810
811 SL_ENTER(_("sh_hash_hashdelete"));
812
[320]813 /* need deadlock detection here if called from exit handler
814 */
815 SH_MUTEX_TRYLOCK(mutex_hash);
816
[1]817 if (IsInit == 0)
[149]818 goto unlock_and_exit;
819
[1]820 for (i = 0; i < TABSIZE; ++i)
821 if (tab[i] != NULL)
822 {
823 hash_kill (tab[i]);
824 tab[i] = NULL;
825 }
826 IsInit = 0;
[149]827
828 unlock_and_exit:
[153]829 ; /* 'label at end of compound statement */
[371]830 SH_MUTEX_TRYLOCK_UNLOCK(mutex_hash);
[320]831
[1]832 SL_RET0(_("sh_hash_hashdelete"));
833}
834
[205]835static int sh_loosedircheck = S_FALSE;
[1]836
[205]837int sh_hash_loosedircheck(const char * str)
838{
839 return sh_util_flagval(str, &sh_loosedircheck);
840}
841
842
[1]843
844
845/*********************************************************************
846 *
847 * Check whether a file is present in the database.
848 *
849 *********************************************************************/
[294]850static sh_file_t * sh_hash_have_it_int (const char * newname)
[1]851{
852 sh_file_t * p;
[133]853 char hashbuf[KEYBUF_SIZE];
[1]854
[115]855 SL_ENTER(_("sh_hash_have_it_int"));
[1]856
857 if (newname == NULL)
[115]858 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[1]859
860 if (sl_strlen(newname) <= MAX_PATH_STORE)
861 p = hashsearch(newname);
862 else
[133]863 p = hashsearch ( sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
864 hashbuf, sizeof(hashbuf)) );
[1]865 if (p == NULL)
[115]866 SL_RETURN( (NULL), _("sh_hash_have_it_int"));
[149]867
[115]868 SL_RETURN( (p), _("sh_hash_have_it_int"));
[1]869}
870
[294]871int sh_hash_have_it (const char * newname)
[1]872{
[149]873 sh_file_t * p;
[170]874 int retval;
[1]875
[149]876 if (IsInit != 1)
877 sh_hash_init();
878
879 SH_MUTEX_LOCK(mutex_hash);
[170]880
881 retval = 0;
882
[149]883 p = sh_hash_have_it_int (newname);
884
885 if (!p)
886 retval = (-1);
887 else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) &&
888 (p->modi_mask & MODI_CHK) != 0 &&
889 (p->modi_mask & MODI_MOD) != 0)
890 retval = 1;
891 SH_MUTEX_UNLOCK(mutex_hash);
892
893 return retval;
[1]894}
895
[294]896int sh_hash_get_it (const char * newname, file_type * tmpFile, char * fileHash)
[1]897{
[149]898 sh_file_t * p;
[170]899 int retval;
[68]900
[149]901 if (IsInit != 1)
902 sh_hash_init();
903
[167]904 tmpFile->link_path = NULL;
905 tmpFile->attr_string = NULL;
906
[149]907 SH_MUTEX_LOCK(mutex_hash);
[170]908
909 retval = (-1);
910
[149]911 p = sh_hash_have_it_int (newname);
912 if (p)
913 {
[167]914 sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
915 if (p->linkpath)
916 tmpFile->link_path = sh_util_strdup (p->linkpath);
[149]917 tmpFile->size = p->theFile.size;
918 tmpFile->mtime = p->theFile.mtime;
919 tmpFile->ctime = p->theFile.ctime;
[294]920 tmpFile->atime = p->theFile.atime;
921
922 if (NULL != fileHash)
923 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
924
[149]925 tmpFile->attr_string = NULL;
926 retval = 0;
927 }
928 SH_MUTEX_UNLOCK(mutex_hash);
929
930 return retval;
[1]931}
932
[115]933int sh_hash_getflags (char * filename)
934{
[149]935 sh_file_t * p;
[463]936 int retval = 0;
[149]937
[463]938 if ( sh.flag.checkSum != SH_CHECK_INIT )
939 {
940 if (IsInit != 1)
941 sh_hash_init();
942
943 SH_MUTEX_LOCK(mutex_hash);
944 p = sh_hash_have_it_int (filename);
945 if (p)
946 retval = p->fflags;
947 else
948 retval = -1;
949 SH_MUTEX_UNLOCK(mutex_hash);
950 }
[149]951 return retval;
[115]952}
953
954int sh_hash_setflags (char * filename, int flags)
955{
[149]956 sh_file_t * p;
[463]957 int retval = 0;
[149]958
[463]959 if ( sh.flag.checkSum != SH_CHECK_INIT )
[149]960 {
[463]961 if (IsInit != 1)
962 sh_hash_init();
963
964 SH_MUTEX_LOCK(mutex_hash);
965 p = sh_hash_have_it_int (filename);
966 if (p)
967 {
968 p->fflags = flags;
969 retval = 0;
970 }
971 else
972 retval = -1;
973 SH_MUTEX_UNLOCK(mutex_hash);
[149]974 }
975 return retval;
[115]976}
977
978/* needs lock to be threadsafe
979 */
[458]980void sh_hash_set_flag (char * filename, int flag_to_set)
[115]981{
[149]982 sh_file_t * p;
[115]983
[463]984 if ( sh.flag.checkSum != SH_CHECK_INIT )
[115]985 {
[463]986 if (IsInit != 1)
987 sh_hash_init();
988
989 SH_MUTEX_LOCK(mutex_hash);
990 p = sh_hash_have_it_int (filename);
991 if (p)
992 {
993 p->fflags |= flag_to_set;
994 }
995 SH_MUTEX_UNLOCK(mutex_hash);
[115]996 }
997 return;
998}
999
[458]1000/* needs lock to be threadsafe
1001 */
1002void sh_hash_clear_flag (char * filename, int flag_to_clear)
1003{
1004 sh_file_t * p;
1005
[463]1006 if ( sh.flag.checkSum != SH_CHECK_INIT )
[458]1007 {
[463]1008 if (IsInit != 1)
1009 sh_hash_init();
1010
1011 SH_MUTEX_LOCK(mutex_hash);
1012 p = sh_hash_have_it_int (filename);
1013 if (p)
1014 {
1015 p->fflags &= ~flag_to_clear;
1016 }
1017 SH_MUTEX_UNLOCK(mutex_hash);
[458]1018 }
1019 return;
1020}
1021
1022
[1]1023/*****************************************************************
1024 *
1025 * Set a file's status to 'visited'. This is required for
1026 * files that should be ignored, and may be present in the
1027 * database, but not on disk.
1028 *
1029 *****************************************************************/
1030static int sh_hash_set_visited_int (char * newname, int flag)
1031{
1032 sh_file_t * p;
[133]1033 char hashbuf[KEYBUF_SIZE];
[170]1034 int retval;
[1]1035
1036 SL_ENTER(_("sh_hash_set_visited_int"));
1037
1038 if (newname == NULL)
1039 SL_RETURN((-1), _("sh_hash_set_visited_int"));
[149]1040
[1]1041 if (IsInit != 1)
1042 sh_hash_init();
1043
[149]1044 SH_MUTEX_LOCK(mutex_hash);
1045
[1]1046 if (sl_strlen(newname) <= MAX_PATH_STORE)
1047 p = hashsearch(newname);
1048 else
[133]1049 p = hashsearch (sh_tiger_hash(newname, TIGER_DATA, sl_strlen(newname),
1050 hashbuf, sizeof(hashbuf)));
[1]1051
[149]1052 if (p)
[1]1053 {
[149]1054 if (flag == SH_FFLAG_CHECKED)
1055 {
1056 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1057 CLEAR_SH_FFLAG_VISITED(p->fflags);
1058 SET_SH_FFLAG_CHECKED(p->fflags);
1059 }
[114]1060 else
[149]1061 {
1062 SET_SH_FFLAG_VISITED(p->fflags);
1063 CLEAR_SH_FFLAG_CHECKED(p->fflags);
1064 if (flag == SH_FFLAG_REPORTED)
1065 SET_SH_FFLAG_REPORTED(p->fflags);
1066 else
1067 CLEAR_SH_FFLAG_REPORTED(p->fflags);
1068 }
1069 retval = 0;
[1]1070 }
[170]1071 else
1072 retval = -1;
[149]1073
1074 SH_MUTEX_UNLOCK(mutex_hash);
1075 SL_RETURN((retval), _("sh_hash_set_visited_int"));
[1]1076}
1077
1078
1079/* cause the record to be deleted without a 'missing' message
1080 */
1081int sh_hash_set_missing (char * newname)
1082{
1083 int i;
[294]1084 SL_ENTER(_("sh_hash_set_missing"));
[305]1085
[114]1086 i = sh_hash_set_visited_int(newname, SH_FFLAG_CHECKED);
[305]1087
1088 if (sh.flag.checkSum != SH_CHECK_INIT) {
1089 sh_hash_remove(newname);
1090 }
1091
[294]1092 SL_RETURN(i, _("sh_hash_set_missing"));
[1]1093}
1094
[114]1095/* mark the file as visited and reported
1096 */
[1]1097int sh_hash_set_visited (char * newname)
1098{
1099 int i;
1100 SL_ENTER(_("sh_hash_set_visited"));
[114]1101 i = sh_hash_set_visited_int(newname, SH_FFLAG_REPORTED);
[1]1102 SL_RETURN(i, _("sh_hash_set_visited"));
1103}
1104
[114]1105/* mark the file as visited and NOT reported
1106 * used to avoid deletion of file from internal database
1107 */
[1]1108int sh_hash_set_visited_true (char * newname)
1109{
1110 int i;
1111 SL_ENTER(_("sh_hash_set_visited_true"));
[114]1112 i = sh_hash_set_visited_int(newname, 0);
[1]1113 SL_RETURN(i, _("sh_hash_set_visited_true"));
1114}
1115
1116
1117/******************************************************************
1118 *
1119 * Data entry for arbitrary data into database
1120 *
1121 ******************************************************************/
1122
[294]1123void sh_hash_push2db (const char * key, struct store2db * save)
[1]1124{
1125 int i = 0;
1126 char * p;
[137]1127 char i2h[2];
[227]1128 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[1]1129
[294]1130 int size = save->size;
1131 unsigned char * str = save->str;
1132
1133
[227]1134 tmpFile->attr_string = NULL;
1135 tmpFile->link_path = NULL;
[68]1136
[227]1137 sl_strlcpy(tmpFile->fullpath, key, PATH_MAX);
[294]1138 tmpFile->size = save->val0;
1139 tmpFile->mtime = save->val1;
1140 tmpFile->ctime = save->val2;
1141 tmpFile->atime = save->val3;
[1]1142
[227]1143 tmpFile->mode = 0;
1144 tmpFile->owner = 0;
1145 tmpFile->group = 0;
1146 sl_strlcpy(tmpFile->c_owner, _("root"), 5);
1147 sl_strlcpy(tmpFile->c_group, _("root"), 5);
[1]1148
[481]1149 tmpFile->check_flags = 0;
1150
[1]1151 if ((str != NULL) && (size < (PATH_MAX/2)-1))
1152 {
[227]1153 tmpFile->c_mode[0] = 'l';
1154 tmpFile->c_mode[1] = 'r'; tmpFile->c_mode[2] = 'w';
1155 tmpFile->c_mode[3] = 'x'; tmpFile->c_mode[4] = 'r';
1156 tmpFile->c_mode[5] = 'w'; tmpFile->c_mode[6] = 'x';
1157 tmpFile->c_mode[7] = 'r'; tmpFile->c_mode[8] = 'w';
1158 tmpFile->c_mode[9] = 'x'; tmpFile->c_mode[10] = '\0';
1159 tmpFile->link_path = SH_ALLOC((size * 2) + 2);
[1]1160 for (i = 0; i < size; ++i)
1161 {
[137]1162 p = sh_util_charhex (str[i],i2h);
[227]1163 tmpFile->link_path[2*i] = p[0];
1164 tmpFile->link_path[2*i+1] = p[1];
1165 tmpFile->link_path[2*i+2] = '\0';
[1]1166 }
1167 }
1168 else
1169 {
[93]1170 for (i = 0; i < 10; ++i)
[227]1171 tmpFile->c_mode[i] = '-';
1172 tmpFile->c_mode[10] = '\0';
1173 tmpFile->link_path = sh_util_strdup("-");
[1]1174 }
1175
[294]1176 if (sh.flag.checkSum == SH_CHECK_INIT)
[481]1177 sh_dbIO_data_write (tmpFile,
1178 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
[1]1179 else
[294]1180 sh_hash_pushdata_memory (tmpFile,
1181 (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
[1]1182
[227]1183 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1184 SH_FREE(tmpFile);
[1]1185 return;
1186}
1187
1188extern int sh_util_hextobinary (char * binary, char * hex, int bytes);
1189
[294]1190char * sh_hash_db2pop (const char * key, struct store2db * save)
[1]1191{
1192 size_t len;
1193 char * p;
1194 int i;
[167]1195 char * retval = NULL;
[294]1196 char fileHash[KEY_LEN+1];
[227]1197 file_type * tmpFile = SH_ALLOC(sizeof(file_type));
[167]1198
[294]1199 save->size = 0;
[1]1200
[294]1201 if (0 == sh_hash_get_it (key, tmpFile, fileHash))
[1]1202 {
[294]1203 save->val0 = tmpFile->size;
1204 save->val1 = tmpFile->mtime;
1205 save->val2 = tmpFile->ctime;
1206 save->val3 = tmpFile->atime;
[1]1207
[294]1208 sl_strlcpy(save->checksum, fileHash, KEY_LEN+1);
1209
[227]1210 if (tmpFile->link_path && tmpFile->link_path[0] != '-')
[1]1211 {
[227]1212 len = strlen(tmpFile->link_path);
[1]1213
1214 p = SH_ALLOC((len/2)+1);
[227]1215 i = sh_util_hextobinary (p, tmpFile->link_path, len);
[1]1216
1217 if (i == 0)
1218 {
[294]1219 save->size = (len/2);
1220 p[save->size] = '\0';
[167]1221 retval = p;
[1]1222 }
1223 else
1224 {
1225 SH_FREE(p);
[294]1226 save->size = 0;
[1]1227 }
1228 }
1229 else
1230 {
[294]1231 save->size = 0;
[1]1232 }
1233 }
1234 else
1235 {
[294]1236 save->size = -1;
1237 save->val0 = 0;
1238 save->val1 = 0;
1239 save->val2 = 0;
1240 save->val3 = 0;
[1]1241 }
[227]1242 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
1243 SH_FREE(tmpFile);
[167]1244 return retval;
[1]1245}
1246
1247
1248
1249
1250/******************************************************************
1251 *
1252 * Data entry in hash table
1253 *
1254 ******************************************************************/
1255sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
1256{
[516]1257 sh_file_t * fp = NULL;
[1]1258 sh_filestore_t p;
[34]1259
1260 size_t len;
[1]1261 char * fullpath;
1262 char * linkpath;
[68]1263 char * attr_string = NULL;
[133]1264 char hashbuf[KEYBUF_SIZE];
[1]1265
1266 SL_ENTER(_("sh_hash_push_int"));
1267
[516]1268 if (!buf)
1269 SL_RETURN(NULL, _("sh_hash_push_int"));
1270
[1]1271 fp = SH_ALLOC(sizeof(sh_file_t));
1272
1273 p.mark = REC_MAGIC;
[68]1274 if (buf->attr_string)
1275 p.mark |= REC_FLAGS_ATTR;
[1]1276 sl_strlcpy(p.c_mode, buf->c_mode, 11);
1277 sl_strlcpy(p.c_group, buf->c_group, GROUP_MAX+1);
1278 sl_strlcpy(p.c_owner, buf->c_owner, USER_MAX+1);
1279 sl_strlcpy(p.checksum, fileHash, KEY_LEN+1);
[10]1280#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1281 sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
1282#endif
1283
[10]1284#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1285 p.attributes = (UINT32) buf->attributes;
1286#endif
1287 p.linkmode = (UINT32) buf->linkmode;
1288 p.hardlinks = (UINT32) buf->hardlinks;
[40]1289 p.dev = (UINT64) buf->dev;
1290 p.rdev = (UINT64) buf->rdev;
[1]1291 p.mode = (UINT32) buf->mode;
1292 p.ino = (UINT32) buf->ino;
1293 p.size = (UINT64) buf->size;
1294 p.mtime = (UINT64) buf->mtime;
1295 p.atime = (UINT64) buf->atime;
1296 p.ctime = (UINT64) buf->ctime;
1297 p.owner = (UINT32) buf->owner;
1298 p.group = (UINT32) buf->group;
1299
[481]1300 p.checkflags = (UINT32) buf->check_flags;
1301
[1]1302 memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
[115]1303 fp->fflags = 0; /* init fflags */
[1]1304 fp->modi_mask = 0L;
1305
[68]1306 if (buf->attr_string)
1307 attr_string = sh_util_strdup(buf->attr_string);
1308 fp->attr_string = attr_string;
1309
[34]1310 len = sl_strlen(buf->fullpath);
1311 if (len <= MAX_PATH_STORE)
[1]1312 {
[34]1313 fullpath = SH_ALLOC(len+1);
1314 sl_strlcpy(fullpath, buf->fullpath, len+1);
[1]1315 }
1316 else
1317 {
1318 fullpath = SH_ALLOC(KEY_LEN + 1);
1319 sl_strlcpy(fullpath,
[133]1320 sh_tiger_hash (buf->fullpath, TIGER_DATA, len,
1321 hashbuf, sizeof(hashbuf)),
[1]1322 KEY_LEN+1);
1323 }
1324 fp->fullpath = fullpath;
1325
[167]1326 if (buf->link_path)
[1]1327 {
[167]1328 len = sl_strlen(buf->link_path);
[34]1329 if (len <= MAX_PATH_STORE)
[1]1330 {
[34]1331 linkpath = SH_ALLOC(len+1);
[167]1332 sl_strlcpy(linkpath, buf->link_path, len+1);
[1]1333 }
1334 else
1335 {
1336 linkpath = SH_ALLOC(KEY_LEN + 1);
1337 sl_strlcpy(linkpath,
[167]1338 sh_tiger_hash (buf->link_path, TIGER_DATA, len,
[133]1339 hashbuf, sizeof(hashbuf)),
[1]1340 KEY_LEN+1);
1341 }
1342 fp->linkpath = linkpath;
1343 }
1344 else
1345 fp->linkpath = NULL;
1346
1347 SL_RETURN( fp, _("sh_hash_push_int"));
1348}
1349
1350#ifdef HAVE_INTTYPES_H
1351#include <inttypes.h>
1352#else
1353#ifdef HAVE_STDINT_H
1354#include <stdint.h>
1355#endif
1356#endif
1357
[40]1358#ifndef PRIu64
1359#ifdef HAVE_LONG_32
1360#define PRIu64 "llu"
1361#else
1362#define PRIu64 "lu"
[1]1363#endif
[40]1364#endif
[1]1365
1366char * sh_hash_size_format()
1367{
1368 static char form_rval[81];
1369
1370 SL_ENTER(_("sh_hash_size_format"));
1371
1372
1373#ifdef SH_USE_XML
1374 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]1375 _("size_old=\"%"), PRIu64, _("\" size_new=\"%"), PRIu64, "\" ");
[1]1376#else
1377 sl_snprintf(form_rval, 80, _("%s%s%s%s%s"),
[40]1378 _("size_old=<%"), PRIu64, _(">, size_new=<%"), PRIu64, ">, ");
[1]1379#endif
1380
1381 SL_RETURN( form_rval, _("sh_hash_size_format"));
1382}
1383
1384
1385#ifdef SH_USE_XML
1386static char * all_items (file_type * theFile, char * fileHash, int is_new)
1387{
1388 char timstr1c[32];
1389 char timstr1a[32];
1390 char timstr1m[32];
1391
1392 char * tmp_lnk;
1393 char * format;
1394
[170]1395 char * tmp = SH_ALLOC(SH_MSG_BUF);
1396 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]1397
1398 tmp[0] = '\0';
1399 msg[0] = '\0';
1400
[481]1401 if (report_checkflags != S_FALSE)
1402 {
1403 if (is_new)
1404 format = _("checkflags_new=\"0%lo\" ");
1405 else
1406 format = _("checkflags_old=\"0%lo\" ");
1407 sl_snprintf(tmp, SH_MSG_BUF, format,
1408 (unsigned long) theFile->check_flags);
1409 sl_strlcat(msg, tmp, SH_MSG_BUF);
1410 }
[1]1411
[10]1412#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1413 if (is_new)
1414 format = _("mode_new=\"%s\" attr_new=\"%s\" imode_new=\"%ld\" iattr_new=\"%ld\" ");
1415 else
1416 format = _("mode_old=\"%s\" attr_old=\"%s\" imode_old=\"%ld\" iattr_old=\"%ld\" ");
[170]1417 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1418 theFile->c_mode,
1419 theFile->c_attributes,
1420 (long) theFile->mode,
1421 (long) theFile->attributes
1422 );
1423#else
1424 if (is_new)
1425 format = _("mode_new=\"%s\" imode_new=\"%ld\" ");
1426 else
1427 format = _("mode_old=\"%s\" imode_old=\"%ld\" ");
1428
[170]1429 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1430 theFile->c_mode,
1431 (long) theFile->mode
1432 );
1433#endif
[170]1434 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1435
1436 if (is_new)
[40]1437 format = _("hardlinks_new=\"%lu\" ");
[1]1438 else
[40]1439 format = _("hardlinks_old=\"%lu\" ");
[170]1440 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1441 (unsigned long) theFile->hardlinks);
[170]1442 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1443
1444
1445 if (is_new)
[40]1446 format = _("idevice_new=\"%lu\" ");
[1]1447 else
[40]1448 format = _("idevice_old=\"%lu\" ");
[170]1449 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1450 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1451
1452
1453 if (is_new)
[40]1454 format = _("inode_new=\"%lu\" ");
[1]1455 else
[40]1456 format = _("inode_old=\"%lu\" ");
[170]1457 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1458 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1459
[40]1460 /*
1461 * also report device for prelude
1462 */
[181]1463#if defined(HAVE_LIBPRELUDE)
[40]1464 if (is_new)
1465 format = _("dev_new=\"%lu,%lu\" ");
1466 else
1467 format = _("dev_old=\"%lu,%lu\" ");
[170]1468 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]1469 (unsigned long) major(theFile->dev),
1470 (unsigned long) minor(theFile->dev));
[170]1471 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]1472#endif
[1]1473
[40]1474
[1]1475 if (is_new)
1476 format = _("owner_new=\"%s\" iowner_new=\"%ld\" ");
1477 else
1478 format = _("owner_old=\"%s\" iowner_old=\"%ld\" ");
[170]1479 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1480 theFile->c_owner, (long) theFile->owner);
[170]1481 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1482
1483
1484 if (is_new)
1485 format = _("group_new=\"%s\" igroup_new=\"%ld\" ");
1486 else
1487 format = _("group_old=\"%s\" igroup_old=\"%ld\" ");
[170]1488 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1489 theFile->c_group, (long) theFile->group);
[170]1490 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1491
1492
1493 if (is_new)
[170]1494 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1495 (UINT64) 0, (UINT64) theFile->size);
1496 else
[170]1497 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1498 (UINT64) theFile->size, (UINT64) 0);
[170]1499 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1500
1501
[132]1502 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]1503 if (is_new)
[170]1504 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=\"%s\" "), timstr1c);
[1]1505 else
[170]1506 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" "), timstr1c);
1507 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1508
[132]1509 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]1510 if (is_new)
[170]1511 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=\"%s\" "), timstr1a);
[1]1512 else
[170]1513 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" "), timstr1a);
1514 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1515
[132]1516 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]1517 if (is_new)
[170]1518 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=\"%s\" "), timstr1m);
[1]1519 else
[170]1520 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" "), timstr1m);
1521 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1522
1523 if (is_new)
[170]1524 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=\"%s\" "), fileHash);
[1]1525 else
[170]1526 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=\"%s\" "), fileHash);
1527 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1528
[169]1529 if (theFile->c_mode[0] == 'l' ||
1530 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]1531 {
[167]1532 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]1533 if (tmp_lnk)
1534 {
1535 if (is_new)
[170]1536 sl_snprintf(tmp, SH_MSG_BUF, _("link_new=\"%s\" "), tmp_lnk);
[1]1537 else
[170]1538 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" "), tmp_lnk);
[1]1539 SH_FREE(tmp_lnk);
[170]1540 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1541 }
1542 }
[68]1543
1544 if (theFile->attr_string)
1545 {
1546 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1547 if (tmp_lnk)
1548 {
1549 if (is_new)
[170]1550 sl_snprintf(tmp, SH_MSG_BUF, _("acl_new=\"%s\" "), tmp_lnk);
[68]1551 else
[170]1552 sl_snprintf(tmp, SH_MSG_BUF, _("acl_old=\"%s\" "), tmp_lnk);
[68]1553 SH_FREE(tmp_lnk);
[170]1554 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]1555 }
1556 }
1557
[1]1558
1559 SH_FREE(tmp);
1560 return (msg);
1561}
1562#else
1563static char * all_items (file_type * theFile, char * fileHash, int is_new)
1564{
1565 char timstr1c[32];
1566 char timstr1a[32];
1567 char timstr1m[32];
1568
1569 char * tmp_lnk;
1570 char * format;
1571
[170]1572 char * tmp = SH_ALLOC(SH_MSG_BUF);
1573 char * msg = SH_ALLOC(SH_MSG_BUF);
[1]1574
1575 tmp[0] = '\0';
1576 msg[0] = '\0';
1577
[481]1578 if (report_checkflags == S_TRUE)
1579 {
1580 if (is_new)
1581 format = _("checkflags_new=<0%lo> ");
1582 else
1583 format = _("checkflags_old=<0%lo> ");
1584 sl_snprintf(tmp, SH_MSG_BUF, format,
1585 (unsigned long) theFile->check_flags);
1586 sl_strlcat(msg, tmp, SH_MSG_BUF);
1587 }
[1]1588
[481]1589
[10]1590#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]1591 if (is_new)
1592 format = _("mode_new=<%s>, attr_new=<%s>, imode_new=<%ld>, iattr_new=<%ld>, ");
1593 else
1594 format = _("mode_old=<%s>, attr_old=<%s>, imode_old=<%ld>, iattr_old=<%ld>, ");
[170]1595 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1596 theFile->c_mode,
1597 theFile->c_attributes,
1598 (long) theFile->mode,
1599 (long) theFile->attributes
1600 );
1601#else
1602 if (is_new)
1603 format = _("mode_new=<%s>, imode_new=<%ld>, ");
1604 else
1605 format = _("mode_old=<%s>, imode_old=<%ld>, ");
1606
[170]1607 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1608 theFile->c_mode,
1609 (long) theFile->mode
1610 );
1611#endif
[170]1612 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1613
1614 if (is_new)
[40]1615 format = _("hardlinks_new=<%lu>, ");
[1]1616 else
[40]1617 format = _("hardlinks_old=<%lu>, ");
[170]1618 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1619 (unsigned long) theFile->hardlinks);
[170]1620 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1621
1622
1623 if (is_new)
[40]1624 format = _("idevice_new=<%lu>, ");
[1]1625 else
[40]1626 format = _("idevice_old=<%lu>, ");
[170]1627 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->rdev);
1628 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1629
1630
1631 if (is_new)
[40]1632 format = _("inode_new=<%lu>, ");
[1]1633 else
[40]1634 format = _("inode_old=<%lu>, ");
[170]1635 sl_snprintf(tmp, SH_MSG_BUF, format, (unsigned long) theFile->ino);
1636 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1637
1638
[40]1639 /*
1640 * also report device for prelude
1641 */
[181]1642#if defined(HAVE_LIBPRELUDE)
[1]1643 if (is_new)
[40]1644 format = _("dev_new=<%lu,%lu>, ");
1645 else
1646 format = _("dev_old=<%lu,%lu>, ");
[170]1647 sl_snprintf(tmp, SH_MSG_BUF, format,
[40]1648 (unsigned long) major(theFile->dev),
1649 (unsigned long) minor(theFile->dev));
[170]1650 sl_strlcat(msg, tmp, SH_MSG_BUF);
[40]1651#endif
1652
1653 if (is_new)
[1]1654 format = _("owner_new=<%s>, iowner_new=<%ld>, ");
1655 else
1656 format = _("owner_old=<%s>, iowner_old=<%ld>, ");
[170]1657 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1658 theFile->c_owner, (long) theFile->owner);
[170]1659 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1660
1661
1662 if (is_new)
1663 format = _("group_new=<%s>, igroup_new=<%ld>, ");
1664 else
1665 format = _("group_old=<%s>, igroup_old=<%ld>, ");
[170]1666 sl_snprintf(tmp, SH_MSG_BUF, format,
[1]1667 theFile->c_group, (long) theFile->group);
[170]1668 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1669
1670
1671 if (is_new)
[170]1672 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1673 (UINT64) 0, (UINT64) theFile->size);
1674 else
[170]1675 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]1676 (UINT64) theFile->size, (UINT64) 0);
[170]1677 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1678
1679
[132]1680 (void) sh_unix_gmttime (theFile->ctime, timstr1c, sizeof(timstr1c));
[1]1681 if (is_new)
[170]1682 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_new=<%s>, "), timstr1c);
[1]1683 else
[170]1684 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, "), timstr1c);
1685 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1686
[132]1687 (void) sh_unix_gmttime (theFile->atime, timstr1a, sizeof(timstr1a));
[1]1688 if (is_new)
[170]1689 sl_snprintf(tmp, SH_MSG_BUF, _("atime_new=<%s>, "), timstr1a);
[1]1690 else
[170]1691 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, "), timstr1a);
1692 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1693
[132]1694 (void) sh_unix_gmttime (theFile->mtime, timstr1m, sizeof(timstr1m));
[1]1695 if (is_new)
[170]1696 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_new=<%s>, "), timstr1m);
[1]1697 else
[170]1698 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, "), timstr1m);
1699 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1700
1701 if (is_new)
[170]1702 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_new=<%s>"), fileHash);
[1]1703 else
[170]1704 sl_snprintf(tmp, SH_MSG_BUF, _("chksum_old=<%s>"), fileHash);
1705 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1706
[169]1707 if (theFile->c_mode[0] == 'l' ||
1708 (theFile->link_path != NULL && theFile->link_path[0] != '-'))
[1]1709 {
[167]1710 tmp_lnk = sh_util_safe_name(theFile->link_path);
[1]1711 if (tmp_lnk)
1712 {
1713 if (is_new)
[170]1714 sl_snprintf(tmp, SH_MSG_BUF, _(", link_new=<%s> "), tmp_lnk);
[1]1715 else
[170]1716 sl_snprintf(tmp, SH_MSG_BUF, _(", link_old=<%s> "), tmp_lnk);
[1]1717 SH_FREE(tmp_lnk);
[170]1718 sl_strlcat(msg, tmp, SH_MSG_BUF);
[1]1719 }
1720 }
1721
[68]1722 if (theFile->attr_string)
1723 {
1724 tmp_lnk = sh_util_safe_name(theFile->attr_string);
1725 if (tmp_lnk)
1726 {
1727 if (is_new)
[170]1728 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_new=<%s> "), tmp_lnk);
[68]1729 else
[170]1730 sl_snprintf(tmp, SH_MSG_BUF, _(", acl_old=<%s> "), tmp_lnk);
[68]1731 SH_FREE(tmp_lnk);
[170]1732 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]1733 }
1734 }
1735
[1]1736 SH_FREE(tmp);
1737 return (msg);
1738}
1739#endif
1740
1741void sh_hash_pushdata_memory (file_type * theFile, char * fileHash)
1742{
1743 sh_file_t * p;
1744
1745 SL_ENTER(_("sh_hash_pushdata_memory"));
1746
1747 p = sh_hash_push_int(theFile, fileHash);
1748 if (p)
1749 {
[149]1750 SH_MUTEX_LOCK(mutex_hash);
[481]1751 hashinsert (tab, p);
1752 p->modi_mask = theFile->check_flags;
[149]1753 SH_MUTEX_UNLOCK(mutex_hash);
[1]1754 }
1755
1756 SL_RET0(_("sh_hash_pushdata_memory"));
1757}
1758
[481]1759int sh_hash_is_null_file(file_type * theFile)
1760{
1761 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1762 theFile->ino == 0 && theFile->ctime == 0)
1763 {
1764 return S_TRUE;
1765 }
1766 return S_FALSE;
1767}
[1]1768
[481]1769int sh_hash_is_null_record(sh_filestore_t * theFile)
1770{
1771 if (theFile->hardlinks == SH_DEADFILE && theFile->mode == 0 &&
1772 theFile->ino == 0 && theFile->ctime == 0)
1773 {
1774 return S_TRUE;
1775 }
1776 return S_FALSE;
1777}
1778
1779void sh_hash_insert_null(char * str)
1780{
1781 file_type theFile = { 0, 0, {'\0'}, 0, 0, 0, 0, 0,
1782#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
1783 0, {'\0'},
1784#endif
1785 {'\0'}, 0, {'\0'}, 0, {'\0'},
1786 0, 0, 0, 0, 0, 0, 0, NULL, 0, {'\0'}, 0, NULL
1787 }; /* clang compiler bails out on standard conforming init with just {0} */
1788 char fileHash[KEY_LEN+1];
1789 char hashbuf[KEYBUF_SIZE];
1790
1791 sl_strlcpy(fileHash, SH_KEY_NULL, sizeof(fileHash));
1792 theFile.hardlinks = SH_DEADFILE;
1793
1794 if (sl_strlen(str) < PATH_MAX)
1795 sl_strlcpy(theFile.fullpath, str, PATH_MAX);
1796 else
1797 sl_strlcpy(theFile.fullpath,
1798 sh_tiger_hash(str, TIGER_DATA, sl_strlen(str),
1799 hashbuf, sizeof(hashbuf)),
1800 PATH_MAX);
1801
1802 sh_hash_pushdata_memory(&theFile, fileHash);
1803 return;
1804}
1805
1806static int handle_notfound(int log_severity, int class,
1807 file_type * theFile, char * fileHash)
1808{
1809 sh_file_t * p;
1810 int retval = 0;
1811
[516]1812 if (!theFile)
1813 return retval;
1814
[481]1815 if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
1816 {
1817 char * tmp = sh_util_safe_name(theFile->fullpath);
1818 char * str;
1819
1820 sh_files_fixup_mask(class, &(theFile->check_flags));
1821 str = all_items (theFile, fileHash, 1);
1822
[488]1823 if (!sh_global_check_silent)
1824 sh_error_handle (log_severity, FIL__, __LINE__, 0,
1825 MSG_FI_ADD2,
1826 tmp, str);
[481]1827 ++sh.statistics.files_report;
1828 SH_FREE(str);
1829 SH_FREE(tmp);
1830 }
1831
1832 if (sh.flag.reportonce == S_TRUE)
1833 SET_SH_FFLAG_REPORTED(theFile->file_reported);
1834
1835 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
1836 {
1837 p = sh_hash_push_int(theFile, fileHash);
1838 if (p)
1839 {
1840 hashinsert (tab, p);
1841 p->modi_mask = theFile->check_flags;
1842 p->theFile.checkflags = p->modi_mask;
1843 }
1844 }
1845
1846 else if (S_TRUE == sh.flag.update)
1847 {
1848 if (S_TRUE == sh_util_ask_update (theFile->fullpath))
1849 {
1850 p = sh_hash_push_int(theFile, fileHash);
1851 if (p)
1852 {
1853 hashinsert (tab, p);
1854 p->modi_mask = theFile->check_flags;
1855 p->theFile.checkflags = p->modi_mask;
1856 }
1857 }
1858 else
1859 retval = 1;
1860 }
1861 return retval;
1862}
1863
[1]1864/*****************************************************************
1865 *
1866 * Compare a file with the database status.
1867 *
1868 *****************************************************************/
1869int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
1870 char * policy_override, int severity_override)
1871{
1872 char * msg;
1873 sh_file_t * p;
1874 char * tmp;
1875 char * tmp_path;
1876 char * tmp_lnk;
1877 char * tmp_lnk_old;
1878
1879 char timstr1c[32];
1880 char timstr2c[32];
1881 char timstr1a[32];
1882 char timstr2a[32];
1883 char timstr1m[32];
1884 char timstr2m[32];
1885 char linkHash[KEY_LEN+1];
[169]1886 char * linkComp;
[1]1887 int maxcomp;
[492]1888 volatile int checksum_flag = 0;
[1]1889
1890 char change_code[16];
1891 int i;
1892
[170]1893 unsigned long modi_mask;
[1]1894
1895 char log_policy[32];
[153]1896 volatile int log_severity;
[133]1897 char hashbuf[KEYBUF_SIZE];
[481]1898 struct {
1899 unsigned long oldflags;
1900 unsigned long newflags;
1901 } cf_report;
[1]1902
[170]1903 int retval;
[149]1904
[1]1905 SL_ENTER(_("sh_hash_compdata"));
1906
[516]1907 if (!theFile)
1908 SL_RETURN(0, _("sh_hash_compdata"));
[1]1909
[516]1910 if (IsInit != 1) sh_hash_init();
1911
[1]1912 if (severity_override < 0)
1913 log_severity = ShDFLevel[class];
1914 else
1915 log_severity = severity_override;
1916
1917 if (policy_override != NULL)
1918 sl_strlcpy (log_policy, policy_override, 32);
1919
1920 /* -------- find the entry for the file ---------------- */
1921
[149]1922 SH_MUTEX_LOCK(mutex_hash);
1923
[170]1924 modi_mask = 0;
1925 retval = 0;
1926
[1]1927 if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE)
1928 p = hashsearch(theFile->fullpath);
1929 else
1930 p = hashsearch( sh_tiger_hash(theFile->fullpath,
1931 TIGER_DATA,
[133]1932 sl_strlen(theFile->fullpath),
1933 hashbuf, sizeof(hashbuf))
[1]1934 );
1935
1936
1937 /* --------- Not found in database. ------------
1938 */
1939
1940 if (p == NULL)
1941 {
[481]1942 retval = handle_notfound(log_severity, class, theFile, fileHash);
[149]1943 goto unlock_and_return;
[1]1944 }
1945
[425]1946 /* --------- Skip if we don't want to report changes. ------------
1947 */
1948
1949 if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
1950 {
[481]1951 MODI_SET(theFile->check_flags, MODI_NOCHECK);
1952 p->modi_mask = theFile->check_flags;
1953 p->theFile.checkflags = p->modi_mask;
[425]1954 goto unlock_and_return;
1955 }
1956
[481]1957 cf_report.oldflags = p->theFile.checkflags;
1958 cf_report.newflags = theFile->check_flags;
[149]1959
[481]1960 p->modi_mask = theFile->check_flags;
1961 p->theFile.checkflags = p->modi_mask;
1962
[1]1963 /* initialize change_code */
1964 for (i = 0; i < 15; ++i)
1965 change_code[i] = '-';
1966 change_code[15] = '\0';
1967
1968 TPT ((0, FIL__, __LINE__, _("file=<%s>, cs_old=<%s>, cs_new=<%s>\n"),
1969 theFile->fullpath, fileHash, p->theFile.checksum));
1970
[474]1971 if ( (fileHash != NULL) &&
[19]1972 (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) &&
[481]1973 (theFile->check_flags & MODI_CHK) != 0)
[1]1974 {
[492]1975 checksum_flag = 1;
1976
[481]1977 if ((theFile->check_flags & MODI_SGROW) == 0)
[19]1978 {
1979 modi_mask |= MODI_CHK;
1980 change_code[0] = 'C';
1981 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1982 }
1983 else
1984 {
[425]1985 if (0 != strncmp (&fileHash[KEY_LEN + 1], p->theFile.checksum, KEY_LEN))
[19]1986 {
[425]1987 if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size,
[481]1988 (UINT64) p->theFile.ino, p->theFile.checksum,
1989 p->theFile.checkflags))
[425]1990 {
1991 modi_mask |= MODI_CHK;
1992 change_code[0] = 'C';
1993 TPT ((0, FIL__, __LINE__, _("mod=<checksum>")));
1994 }
1995 else
1996 {
1997 /* logfile has been rotated */
1998 p->theFile.size = theFile->size;
1999 p->theFile.ino = theFile->ino;
2000 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2001 }
[19]2002 }
2003 else
2004 {
2005 p->theFile.size = theFile->size;
2006 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2007 }
2008 }
[1]2009 }
2010
2011 if (p->theFile.c_mode[0] == 'l')
2012 {
[169]2013 if (!(theFile->link_path) &&
[481]2014 (theFile->check_flags & MODI_LNK) != 0)
[1]2015 {
[169]2016 linkComp = NULL;
[93]2017 modi_mask |= MODI_LNK;
2018 change_code[1] = 'L';
2019 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
[169]2020 }
2021 else
2022 {
2023 if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE)
2024 {
2025 sl_strlcpy(linkHash,
2026 sh_tiger_hash(theFile->link_path,
2027 TIGER_DATA,
2028 sl_strlen(theFile->link_path),
2029 hashbuf, sizeof(hashbuf)),
2030 MAX_PATH_STORE+1);
2031 linkComp = linkHash;
2032 maxcomp = KEY_LEN;
2033 }
2034 else
2035 {
2036 linkComp = theFile->link_path;
2037 maxcomp = MAX_PATH_STORE;
2038 }
2039
2040 if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
[481]2041 (theFile->check_flags & MODI_LNK) != 0)
[169]2042 {
2043 modi_mask |= MODI_LNK;
2044 change_code[1] = 'L';
2045 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2046 }
2047 }
[1]2048 }
2049
2050 if (p->theFile.c_mode[0] == 'c' || p->theFile.c_mode[0] == 'b')
2051 {
2052 if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) ||
2053 minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
[481]2054 (theFile->check_flags & MODI_RDEV) != 0)
[1]2055 {
2056 modi_mask |= MODI_RDEV;
2057 change_code[2] = 'D';
2058 TPT ((0, FIL__, __LINE__, _("mod=<rdev>")));
2059 }
2060 }
2061
2062 /* cast to UINT32 in case ino_t is not 32bit
2063 */
2064 if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino &&
[481]2065 (theFile->check_flags & MODI_INO) != 0)
[1]2066 {
[492]2067 if ((theFile->check_flags & MODI_SGROW) == 0)
2068 {
2069 modi_mask |= MODI_INO;
2070 change_code[3] = 'I';
2071 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2072 }
2073 else
2074 {
2075 /* growing log, checksum ok but inode changed
2076 */
2077 if (checksum_flag == 0)
2078 {
2079 if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size,
2080 (UINT64) p->theFile.ino, p->theFile.checksum,
2081 p->theFile.checkflags))
2082 {
2083 modi_mask |= MODI_INO;
2084 change_code[3] = 'I';
2085 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2086 }
2087 else
2088 {
2089 /* logfile has been rotated */
2090 p->theFile.size = theFile->size;
2091 p->theFile.ino = theFile->ino;
2092 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2093 }
2094 }
2095 else
2096 {
2097 modi_mask |= MODI_INO;
2098 change_code[3] = 'I';
2099 TPT ((0, FIL__, __LINE__, _("mod=<inode>")));
2100 }
2101 }
[1]2102 }
2103
2104 if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
[481]2105 (theFile->check_flags & MODI_HLN) != 0)
[1]2106 {
2107 modi_mask |= MODI_HLN;
2108 change_code[4] = 'H';
2109 TPT ((0, FIL__, __LINE__, _("mod=<hardlink>")));
2110 }
2111
2112
2113 if ( ( (theFile->mode != p->theFile.mode)
[68]2114#if defined(USE_ACL) || defined(USE_XATTR)
2115 || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
2116 (
2117 (theFile->attr_string == NULL && p->attr_string != NULL) ||
2118 (theFile->attr_string != NULL && p->attr_string == NULL) ||
2119 (theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
2120 )
2121 )
2122#endif
[10]2123#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2124 || (theFile->attributes != p->theFile.attributes)
2125#endif
[68]2126 )
[481]2127 && (theFile->check_flags & MODI_MOD) != 0)
[1]2128 {
2129 modi_mask |= MODI_MOD;
2130 change_code[5] = 'M';
2131 TPT ((0, FIL__, __LINE__, _("mod=<mode>")));
2132 /*
2133 * report link path if switch link/no link
2134 */
[481]2135 if ((theFile->check_flags & MODI_LNK) != 0 &&
[1]2136 (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
2137 (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
2138 {
2139 modi_mask |= MODI_LNK;
2140 change_code[1] = 'L';
2141 TPT ((0, FIL__, __LINE__, _("mod=<link>")));
2142 }
2143 }
2144
2145 if ( theFile->owner != (uid_t) p->theFile.owner &&
[481]2146 (theFile->check_flags & MODI_USR) != 0)
[1]2147 {
2148 modi_mask |= MODI_USR;
2149 change_code[6] = 'U';
2150 TPT ((0, FIL__, __LINE__, _("mod=<user>")));
2151 }
2152
2153 if ( theFile->group != (gid_t) p->theFile.group &&
[481]2154 (theFile->check_flags & MODI_GRP) != 0)
[1]2155 {
2156 modi_mask |= MODI_GRP;
2157 change_code[7] = 'G';
2158 TPT ((0, FIL__, __LINE__, _("mod=<group>")));
2159 }
2160
2161
2162 if ( theFile->mtime != (time_t) p->theFile.mtime &&
[481]2163 (theFile->check_flags & MODI_MTM) != 0)
[1]2164 {
2165 modi_mask |= MODI_MTM;
2166 change_code[8] = 'T';
2167 TPT ((0, FIL__, __LINE__, _("mod=<mtime>")));
2168 }
2169
[481]2170 if ( (theFile->check_flags & MODI_ATM) != 0 &&
[68]2171 theFile->atime != (time_t) p->theFile.atime)
[1]2172 {
2173 modi_mask |= MODI_ATM;
2174 change_code[8] = 'T';
2175 TPT ((0, FIL__, __LINE__, _("mod=<atime>")));
2176 }
2177
2178
2179 /* Resetting the access time will set a new ctime. Thus, either we ignore
2180 * the access time or the ctime for NOIGNORE
2181 */
2182 if ( theFile->ctime != (time_t) p->theFile.ctime &&
[481]2183 (theFile->check_flags & MODI_CTM) != 0)
[1]2184 {
2185 modi_mask |= MODI_CTM;
2186 change_code[8] = 'T';
2187 TPT ((0, FIL__, __LINE__, _("mod=<ctime>")));
2188 }
2189
2190 if ( theFile->size != (off_t) p->theFile.size &&
[481]2191 (theFile->check_flags & MODI_SIZ) != 0)
[1]2192 {
[481]2193 if ((theFile->check_flags & MODI_SGROW) == 0 ||
[19]2194 theFile->size < (off_t) p->theFile.size)
[1]2195 {
2196 modi_mask |= MODI_SIZ;
2197 change_code[9] = 'S';
2198 TPT ((0, FIL__, __LINE__, _("mod=<size>")));
[19]2199 }
[1]2200 }
2201 change_code[10] = '\0';
2202
[205]2203 /* --- Directories special case ---
2204 */
2205 if (p->theFile.c_mode[0] == 'd' &&
2206 0 == (modi_mask & ~(MODI_SIZ|MODI_ATM|MODI_CTM|MODI_MTM)) &&
2207 sh_loosedircheck == S_TRUE)
2208 {
2209 modi_mask = 0;
2210 }
2211
[1]2212 /* --- Report full details. ---
2213 */
2214 if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
2215 {
[481]2216 if ((theFile->check_flags & MODI_ATM) == 0)
[1]2217 modi_mask = MASK_READONLY_;
2218 else
2219 modi_mask = MASK_NOIGNORE_;
2220 }
2221
2222 /* --- Report on modified files. ---
2223 */
[114]2224 if (modi_mask != 0 && (!SH_FFLAG_REPORTED_SET(p->fflags)))
[1]2225 {
[170]2226 tmp = SH_ALLOC(SH_MSG_BUF);
2227 msg = SH_ALLOC(SH_MSG_BUF);
[1]2228 msg[0] = '\0';
2229
[481]2230 sh_files_fixup_mask(class, &(cf_report.newflags));
2231
2232 if ( (report_checkflags != S_FALSE) && (cf_report.oldflags != cf_report.newflags))
2233 {
2234 sl_snprintf(tmp, SH_MSG_BUF,
2235#ifdef SH_USE_XML
2236 _("checkflags_old=\"0%lo\" checkflags_new=\"0%lo\" "),
2237#else
2238 _("checkflags_old=<0%lo>, checkflags_new=<0%lo>, "),
2239#endif
2240 cf_report.oldflags, cf_report.newflags);
2241 sl_strlcat(msg, tmp, SH_MSG_BUF);
2242 }
2243
[1]2244 if ( ((modi_mask & MODI_MOD) != 0)
[181]2245#if defined(HAVE_LIBPRELUDE)
[68]2246 || ((modi_mask & MODI_USR) != 0)
2247 || ((modi_mask & MODI_GRP) != 0)
[1]2248#endif
2249 )
2250 {
[10]2251#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[170]2252 sl_snprintf(tmp, SH_MSG_BUF,
[1]2253#ifdef SH_USE_XML
2254 _("mode_old=\"%s\" mode_new=\"%s\" attr_old=\"%s\" attr_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" iattr_old=\"%ld\" iattr_new=\"%ld\" "),
2255#else
2256 _("mode_old=<%s>, mode_new=<%s>, attr_old=<%s>, attr_new=<%s>, "),
2257#endif
2258 p->theFile.c_mode, theFile->c_mode,
2259 p->theFile.c_attributes, theFile->c_attributes
2260#ifdef SH_USE_XML
2261 , (long) p->theFile.mode, (long) theFile->mode,
2262 (long) p->theFile.attributes,
2263 (long) theFile->attributes
2264#endif
2265 );
2266#else
2267#ifdef SH_USE_XML
[170]2268 sl_snprintf(tmp, SH_MSG_BUF,
[1]2269 _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
[68]2270 p->theFile.c_mode, theFile->c_mode,
2271 (long) p->theFile.mode, (long) theFile->mode);
[1]2272#else
[170]2273 sl_snprintf(tmp, SH_MSG_BUF, _("mode_old=<%s>, mode_new=<%s>, "),
[68]2274 p->theFile.c_mode, theFile->c_mode);
[1]2275#endif
[68]2276#endif
[170]2277 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2278
2279#if defined(USE_ACL) || defined(USE_XATTR)
2280 if (theFile->attr_string != NULL || p->attr_string != NULL)
2281 {
[170]2282 sl_snprintf(tmp, SH_MSG_BUF,
[1]2283#ifdef SH_USE_XML
[68]2284 _("acl_old=\"%s\" acl_new=\"%s\" "),
2285#else
2286 _("acl_old=<%s>, acl_new=<%s>, "),
[1]2287#endif
[68]2288 (p->attr_string) ? p->attr_string : _("none"),
2289 (theFile->attr_string) ? theFile->attr_string : _("none"));
2290
[170]2291 sl_strlcat(msg, tmp, SH_MSG_BUF);
[68]2292 }
[1]2293#endif
[68]2294
[1]2295 if ((modi_mask & MODI_MOD) != 0)
2296 {
2297 /*
2298 * We postpone update if sh.flag.update == S_TRUE because
2299 * in interactive mode the user may not accept the change.
2300 */
2301 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2302 {
2303 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2304 p->theFile.mode = theFile->mode;
[10]2305#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2306 sl_strlcpy(p->theFile.c_attributes,theFile->c_attributes,16);
2307 p->theFile.attributes = theFile->attributes;
2308#endif
[68]2309#if defined(USE_ACL) || defined(USE_XATTR)
2310 if (p->attr_string == NULL && theFile->attr_string != NULL)
2311 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2312 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2313 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2314 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2315 {
2316 if (0 != strcmp(theFile->attr_string, p->attr_string))
2317 {
2318 SH_FREE(p->attr_string);
2319 p->attr_string = sh_util_strdup (theFile->attr_string);
2320 }
2321 }
2322#endif
[1]2323 }
2324 }
[481]2325
[1]2326 }
2327
2328 if ((modi_mask & MODI_HLN) != 0)
2329 {
[170]2330 sl_snprintf(tmp, SH_MSG_BUF,
[1]2331#ifdef SH_USE_XML
[40]2332 _("hardlinks_old=\"%lu\" hardlinks_new=\"%lu\" "),
[1]2333#else
[40]2334 _("hardlinks_old=<%lu>, hardlinks_new=<%lu>, "),
[1]2335#endif
2336 (unsigned long) p->theFile.hardlinks,
2337 (unsigned long) theFile->hardlinks);
[170]2338 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2339
[1]2340 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2341 p->theFile.hardlinks = theFile->hardlinks;
2342 }
2343
2344 if ((modi_mask & MODI_RDEV) != 0)
2345 {
[170]2346 sl_snprintf(tmp, SH_MSG_BUF,
[1]2347#ifdef SH_USE_XML
[40]2348 _("device_old=\"%lu,%lu\" device_new=\"%lu,%lu\" idevice_old=\"%lu\" idevice_new=\"%lu\" "),
[1]2349#else
[40]2350 _("device_old=<%lu,%lu>, device_new=<%lu,%lu>, "),
[1]2351#endif
2352 (unsigned long) major(p->theFile.rdev),
2353 (unsigned long) minor(p->theFile.rdev),
2354 (unsigned long) major(theFile->rdev),
2355 (unsigned long) minor(theFile->rdev)
2356#ifdef SH_USE_XML
2357 , (unsigned long) p->theFile.rdev,
2358 (unsigned long) theFile->rdev
2359#endif
2360 );
[170]2361 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2362
[1]2363 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2364 p->theFile.rdev = theFile->rdev;
2365 }
2366
2367 if ((modi_mask & MODI_INO) != 0)
2368 {
[170]2369 sl_snprintf(tmp, SH_MSG_BUF,
[1]2370#ifdef SH_USE_XML
[40]2371 _("inode_old=\"%lu\" inode_new=\"%lu\" "),
[1]2372#else
[40]2373 _("inode_old=<%lu>, inode_new=<%lu>, "),
[1]2374#endif
2375 (unsigned long) p->theFile.ino,
2376 (unsigned long) theFile->ino);
[170]2377 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2378
[1]2379 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[40]2380 {
2381 p->theFile.ino = theFile->ino;
2382 p->theFile.dev = theFile->dev;
2383 }
[1]2384 }
2385
[40]2386
2387 /*
2388 * also report device for prelude
2389 */
[181]2390#if defined(HAVE_LIBPRELUDE)
[40]2391 if ((modi_mask & MODI_INO) != 0)
2392 {
[170]2393 sl_snprintf(tmp, SH_MSG_BUF,
[40]2394#ifdef SH_USE_XML
2395 _("dev_old=\"%lu,%lu\" dev_new=\"%lu,%lu\" "),
2396#else
2397 _("dev_old=<%lu,%lu>, dev_new=<%lu,%lu>, "),
2398#endif
2399 (unsigned long) major(p->theFile.dev),
2400 (unsigned long) minor(p->theFile.dev),
2401 (unsigned long) major(theFile->dev),
2402 (unsigned long) minor(theFile->dev)
2403 );
[170]2404 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2405
[40]2406 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2407 p->theFile.dev = theFile->dev;
2408 }
2409#endif
2410
[1]2411 if ( ((modi_mask & MODI_USR) != 0)
[181]2412#if defined(HAVE_LIBPRELUDE)
[1]2413 || ((modi_mask & MODI_MOD) != 0)
2414#endif
2415 )
2416 {
2417#ifdef SH_USE_XML
[170]2418 sl_snprintf(tmp, SH_MSG_BUF,
[40]2419 _("owner_old=\"%s\" owner_new=\"%s\" iowner_old=\"%ld\" iowner_new=\"%ld\" "),
[1]2420#else
[170]2421 sl_snprintf(tmp, SH_MSG_BUF,
[40]2422 _("owner_old=<%s>, owner_new=<%s>, iowner_old=<%ld>, iowner_new=<%ld>, "),
[1]2423#endif
[40]2424 p->theFile.c_owner, theFile->c_owner,
2425 (long) p->theFile.owner, (long) theFile->owner
[1]2426 );
[170]2427 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2428
[1]2429 if ((modi_mask & MODI_USR) != 0) {
2430 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2431 {
2432 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2433 p->theFile.owner = theFile->owner;
2434 }
2435 }
2436 }
2437
2438 if ( ((modi_mask & MODI_GRP) != 0)
[181]2439#if defined(HAVE_LIBPRELUDE)
[1]2440 || ((modi_mask & MODI_MOD) != 0)
2441#endif
2442 )
2443 {
2444#ifdef SH_USE_XML
[170]2445 sl_snprintf(tmp, SH_MSG_BUF,
[40]2446 _("group_old=\"%s\" group_new=\"%s\" igroup_old=\"%ld\" igroup_new=\"%ld\" "),
[1]2447 p->theFile.c_group, theFile->c_group,
2448 (long) p->theFile.group, (long) theFile->group);
2449#else
[170]2450 sl_snprintf(tmp, SH_MSG_BUF,
[40]2451 _("group_old=<%s>, group_new=<%s>, igroup_old=<%ld>, igroup_new=<%ld>, "),
2452 p->theFile.c_group, theFile->c_group,
2453 (long) p->theFile.group, (long) theFile->group);
[1]2454#endif
2455
[170]2456 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2457
[1]2458 if ((modi_mask & MODI_GRP) != 0) {
2459 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2460 {
2461 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2462 p->theFile.group = theFile->group;
2463 }
2464 }
2465 }
2466
2467 if ((modi_mask & MODI_SIZ) != 0)
2468 {
[170]2469 sl_snprintf(tmp, SH_MSG_BUF, sh_hash_size_format(),
[1]2470 (UINT64) p->theFile.size,
2471 (UINT64) theFile->size);
[170]2472 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2473
[1]2474 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2475 p->theFile.size = theFile->size;
2476 }
2477
2478 if ((modi_mask & MODI_CTM) != 0)
2479 {
[132]2480 (void) sh_unix_gmttime (p->theFile.ctime, timstr1c, sizeof(timstr1c));
2481 (void) sh_unix_gmttime (theFile->ctime, timstr2c, sizeof(timstr2c));
[1]2482#ifdef SH_USE_XML
[170]2483 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=\"%s\" ctime_new=\"%s\" "),
[1]2484 timstr1c, timstr2c);
2485#else
[170]2486 sl_snprintf(tmp, SH_MSG_BUF, _("ctime_old=<%s>, ctime_new=<%s>, "),
[1]2487 timstr1c, timstr2c);
2488#endif
[170]2489 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2490
[1]2491 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2492 p->theFile.ctime = theFile->ctime;
2493 }
2494
2495 if ((modi_mask & MODI_ATM) != 0)
2496 {
[132]2497 (void) sh_unix_gmttime (p->theFile.atime, timstr1a, sizeof(timstr1a));
2498 (void) sh_unix_gmttime (theFile->atime, timstr2a, sizeof(timstr2a));
[1]2499#ifdef SH_USE_XML
[170]2500 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=\"%s\" atime_new=\"%s\" "),
[1]2501 timstr1a, timstr2a);
2502#else
[170]2503 sl_snprintf(tmp, SH_MSG_BUF, _("atime_old=<%s>, atime_new=<%s>, "),
[1]2504 timstr1a, timstr2a);
2505#endif
[170]2506 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2507
[1]2508 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2509 p->theFile.atime = theFile->atime;
2510 }
2511
2512 if ((modi_mask & MODI_MTM) != 0)
2513 {
[132]2514 (void) sh_unix_gmttime (p->theFile.mtime, timstr1m, sizeof(timstr1m));
2515 (void) sh_unix_gmttime (theFile->mtime, timstr2m, sizeof(timstr2m));
[1]2516#ifdef SH_USE_XML
[170]2517 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=\"%s\" mtime_new=\"%s\" "),
[1]2518 timstr1m, timstr2m);
2519#else
[170]2520 sl_snprintf(tmp, SH_MSG_BUF, _("mtime_old=<%s>, mtime_new=<%s>, "),
[1]2521 timstr1m, timstr2m);
2522#endif
[170]2523 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2524
[1]2525 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2526 p->theFile.mtime = theFile->mtime;
2527 }
2528
2529
2530 if ((modi_mask & MODI_CHK) != 0)
2531 {
[170]2532 sl_snprintf(tmp, SH_MSG_BUF,
[1]2533#ifdef SH_USE_XML
2534 _("chksum_old=\"%s\" chksum_new=\"%s\" "),
2535#else
2536 _("chksum_old=<%s>, chksum_new=<%s>, "),
2537#endif
2538 p->theFile.checksum, fileHash);
[170]2539 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2540
[1]2541 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
[107]2542 {
2543 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
[481]2544 if ((theFile->check_flags & MODI_SGROW) != 0)
[107]2545 p->theFile.size = theFile->size;
2546 }
[481]2547
2548
[169]2549 if (theFile->c_mode[0] != 'l' && theFile->link_path &&
2550 strlen(theFile->link_path) > 2)
2551 modi_mask |= MODI_LNK;
[1]2552 }
2553
2554
[169]2555 if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
[1]2556 {
[169]2557 if (theFile->link_path)
2558 tmp_lnk = sh_util_safe_name(theFile->link_path);
2559 else
2560 tmp_lnk = sh_util_strdup("-");
2561 if (p->linkpath)
2562 tmp_lnk_old = sh_util_safe_name(p->linkpath);
2563 else
2564 tmp_lnk_old = sh_util_strdup("-");
[1]2565#ifdef SH_USE_XML
[170]2566 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=\"%s\" link_new=\"%s\" "),
[1]2567 tmp_lnk_old, tmp_lnk);
2568#else
[294]2569 sl_snprintf(tmp, SH_MSG_BUF, _("link_old=<%s>, link_new=<%s>, "),
[1]2570 tmp_lnk_old, tmp_lnk);
2571#endif
2572 SH_FREE(tmp_lnk);
2573 SH_FREE(tmp_lnk_old);
[170]2574 sl_strlcat(msg, tmp, SH_MSG_BUF);
[481]2575
[1]2576 if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
2577 {
[481]2578 if (p->linkpath != NULL)
[1]2579 SH_FREE(p->linkpath);
[481]2580 if (!(theFile->link_path))
2581 p->linkpath = sh_util_strdup("-");
[149]2582 else
[167]2583 p->linkpath = sh_util_strdup(theFile->link_path);
[1]2584 }
2585 }
2586
[481]2587 if (MODI_AUDIT_ENABLED(theFile->check_flags))
[294]2588 {
2589 char result[256];
[488]2590
2591 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__,
2592 0, MSG_E_SUBGPATH,
2593 _("Fetching audit record"),
2594 _("sh_hash"), theFile->fullpath );
[1]2595
[514]2596 if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, theFile->ctime, theFile->atime,
2597 result, sizeof(result)))
[294]2598 {
2599#ifdef SH_USE_XML
2600 sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
2601#else
2602 sl_strlcat(msg, _("obj=<"), SH_MSG_BUF);
2603#endif
2604
2605 sl_strlcat(msg, result, SH_MSG_BUF);
2606
2607#ifdef SH_USE_XML
2608 sl_strlcat(msg, _("\" "), SH_MSG_BUF);
2609#else
2610 sl_strlcat(msg, _(">"), SH_MSG_BUF);
2611#endif
2612 }
2613 }
2614
[481]2615 /****************************************************
2616 *
2617 * REPORT on file change
2618 *
2619 ****************************************************/
[1]2620 tmp_path = sh_util_safe_name(theFile->fullpath);
[488]2621 if (!sh_global_check_silent)
2622 sh_error_handle(log_severity, FIL__, __LINE__,
2623 (long) modi_mask, MSG_FI_CHAN,
2624 (policy_override == NULL) ? _(policy[class]):log_policy,
2625 change_code, tmp_path, msg);
[405]2626 ++sh.statistics.files_report;
[1]2627
2628 SH_FREE(tmp_path);
2629 SH_FREE(tmp);
2630 SH_FREE(msg);
2631
2632 if (S_TRUE == sh.flag.update)
2633 {
2634 if (S_FALSE == sh_util_ask_update(theFile->fullpath))
2635 {
2636 /* user does not want to update, thus we replace
2637 * with data from the baseline database
2638 */
2639 sl_strlcpy(theFile->c_mode, p->theFile.c_mode, 11);
2640 theFile->mode = p->theFile.mode;
[10]2641#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2642 sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
2643 theFile->attributes = p->theFile.attributes;
2644#endif
[68]2645#if defined(USE_ACL) || defined(USE_XATTR)
2646 if (theFile->attr_string == NULL && p->attr_string != NULL)
2647 { theFile->attr_string = sh_util_strdup (p->attr_string); }
2648 else if (theFile->attr_string != NULL && p->attr_string == NULL)
2649 { SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
2650 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2651 {
2652 if (0 != strcmp(theFile->attr_string, p->attr_string))
2653 {
2654 SH_FREE(theFile->attr_string);
2655 theFile->attr_string = sh_util_strdup (p->attr_string);
2656 }
2657 }
2658#endif
[1]2659
2660 if (theFile->c_mode[0] == 'l') /* c_mode is already copied */
2661 {
[167]2662 if (theFile->link_path)
2663 SH_FREE(theFile->link_path);
2664 if (p->linkpath)
2665 theFile->link_path = sh_util_strdup(p->linkpath);
2666 else
2667 theFile->link_path = sh_util_strdup("-");
[1]2668 }
2669 else
2670 {
[167]2671 if (theFile->link_path)
2672 SH_FREE(theFile->link_path);
[481]2673 if (p->linkpath)
[167]2674 theFile->link_path = sh_util_strdup(p->linkpath);
2675 else
2676 theFile->link_path = NULL;
[1]2677 }
2678
2679 sl_strlcpy(fileHash, p->theFile.checksum, KEY_LEN+1);
2680
2681 theFile->mtime = p->theFile.mtime;
2682 theFile->ctime = p->theFile.ctime;
2683 theFile->atime = p->theFile.atime;
2684
2685 theFile->size = p->theFile.size;
2686
2687 sl_strlcpy(theFile->c_group, p->theFile.c_group, GROUP_MAX+2);
2688 theFile->group = p->theFile.group;
2689 sl_strlcpy(theFile->c_owner, p->theFile.c_owner, USER_MAX+2);
2690 theFile->owner = p->theFile.owner;
2691
2692 theFile->ino = p->theFile.ino;
2693 theFile->rdev = p->theFile.rdev;
2694 theFile->dev = p->theFile.dev;
2695 theFile->hardlinks = p->theFile.hardlinks;
2696
[114]2697 SET_SH_FFLAG_VISITED(p->fflags);
2698 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[149]2699 retval = 1;
2700 goto unlock_and_return;
[1]2701 }
[77]2702 else /* if (sh.flag.reportonce == S_TRUE) */
[1]2703 {
2704 /* we replace the data in the in-memory copy of the
2705 * baseline database, because otherwise we would get
2706 * another warning if the suidcheck runs
2707 */
2708 sl_strlcpy(p->theFile.c_mode, theFile->c_mode, 11);
2709 p->theFile.mode = theFile->mode;
[10]2710#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
[1]2711 sl_strlcpy(p->theFile.c_attributes, theFile->c_attributes, 16);
2712 p->theFile.attributes = theFile->attributes;
2713#endif
[68]2714#if defined(USE_ACL) || defined(USE_XATTR)
2715 if (p->attr_string == NULL && theFile->attr_string != NULL)
2716 { p->attr_string = sh_util_strdup (theFile->attr_string); }
2717 else if (p->attr_string != NULL && theFile->attr_string == NULL)
2718 { SH_FREE(p->attr_string); p->attr_string = NULL; }
2719 else if (theFile->attr_string != NULL && p->attr_string != NULL)
2720 {
2721 if (0 != strcmp(theFile->attr_string, p->attr_string))
2722 {
2723 SH_FREE(p->attr_string);
2724 p->attr_string = sh_util_strdup (theFile->attr_string);
2725 }
2726 }
2727#endif
[1]2728
[167]2729 if (theFile->c_mode[0] == 'l' || theFile->link_path)
[1]2730 {
[481]2731 if (p->linkpath != NULL)
[1]2732 SH_FREE(p->linkpath);
[167]2733 p->linkpath = sh_util_strdup(theFile->link_path);
[1]2734 }
2735 else
2736 {
[481]2737 if (p->linkpath != NULL)
[167]2738 SH_FREE(p->linkpath);
[481]2739 p->linkpath = sh_util_strdup("-");
[1]2740 }
2741
2742 sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
2743
2744 p->theFile.mtime = theFile->mtime;
2745 p->theFile.ctime = theFile->ctime;
2746 p->theFile.atime = theFile->atime;
2747
2748 p->theFile.size = theFile->size;
2749
2750 sl_strlcpy(p->theFile.c_group, theFile->c_group, GROUP_MAX+2);
2751 p->theFile.group = theFile->group;
2752 sl_strlcpy(p->theFile.c_owner, theFile->c_owner, USER_MAX+2);
2753 p->theFile.owner = theFile->owner;
2754
2755 p->theFile.ino = theFile->ino;
2756 p->theFile.rdev = theFile->rdev;
2757 p->theFile.dev = theFile->dev;
2758 p->theFile.hardlinks = theFile->hardlinks;
2759 }
2760 }
2761 }
2762
[114]2763 SET_SH_FFLAG_VISITED(p->fflags);
2764 CLEAR_SH_FFLAG_CHECKED(p->fflags);
[1]2765
[149]2766 unlock_and_return:
[153]2767 ; /* 'label at end of compound statement */
[149]2768 SH_MUTEX_UNLOCK(mutex_hash);
2769 SL_RETURN(retval, _("sh_hash_compdata"));
[1]2770}
2771
2772int hash_full_tree ()
2773{
2774 sh_file_t * p;
2775 int i;
2776
[457]2777 SL_ENTER(_("hash_full_tree"));
[1]2778
2779 if (IsInit != 1)
[457]2780 SL_RETURN(0, _("hash_full_tree"));
[1]2781
[149]2782 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]2783 for (i = 0; i < TABSIZE; ++i)
2784 {
2785 for (p = tab[i]; p; p = p->next)
[114]2786 CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
[1]2787 }
[149]2788 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[457]2789 SL_RETURN (0, _("hash_full_tree"));
[1]2790}
2791
[457]2792#if !defined(SH_CUTEST)
2793static
2794#endif
2795int hash_remove_tree_test(char * s, char * fullpath, size_t len_s)
2796{
2797 size_t len_p;
2798 char * test;
[1]2799
[457]2800 len_p = strlen(fullpath);
2801
2802 if (len_p >= len_s)
2803 {
2804 if (0 == strncmp(s, fullpath, len_s))
2805 {
2806 if (len_p > len_s)
2807 {
2808 /* continue if not inside directory;
2809 * len_s > 1 because everything is inside '/'
2810 */
2811 if ((len_s > 1) && (fullpath[len_s] != '/'))
2812 return S_FALSE;
2813
2814 test = sh_files_find_mostspecific_dir(fullpath);
2815
2816 if (test && 0 != strcmp(test, s)) {
2817 /* There is a more specific directory, continue */
2818 return S_FALSE;
2819 }
2820
2821 if (NULL == sh_files_findfile(fullpath)) {
2822 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2823 return S_TRUE;
2824 }
2825 }
2826 else /* len_p == len */
2827 {
2828 /* it is 's' itself, mark and continue
2829 * unless there is a policy for the inode itself
2830 */
2831 if (NULL == sh_files_findfile(fullpath)) {
2832 /* SET_SH_FFLAG_ALLIGNORE(p->fflags); */
2833 return S_TRUE;
2834 }
2835 else {
2836 return S_FALSE;
2837 }
2838 }
2839
2840 } /* if path is in tree */
2841 } /* if path is possibly in tree */
2842 return S_FALSE;
2843}
2844
2845
[1]2846int hash_remove_tree (char * s)
2847{
[8]2848 sh_file_t * p;
[457]2849 size_t len_s;
[8]2850 unsigned int i;
[1]2851
2852 SL_ENTER(_("hash_remove_tree"));
2853
[8]2854 if (!s || *s == '\0')
[1]2855 SL_RETURN ((-1), _("hash_remove_tree"));
2856
[457]2857 len_s = sl_strlen(s);
[8]2858
[1]2859 if (IsInit != 1)
2860 sh_hash_init();
2861
[149]2862 SH_MUTEX_LOCK_UNSAFE(mutex_hash);
[1]2863 for (i = 0; i < TABSIZE; ++i)
2864 {
2865 for (p = tab[i]; p; p = p->next)
2866 {
[457]2867 if (p->fullpath)
2868 {
2869 /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */
[481]2870 if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) {
[457]2871 SET_SH_FFLAG_ALLIGNORE(p->fflags);
[481]2872 MODI_SET(p->theFile.checkflags, MODI_ALLIGNORE);
2873 }
[457]2874 } /* if path is not null */
2875
[1]2876 }
2877 }
[149]2878 SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
[1]2879 SL_RETURN ((0), _("hash_remove_tree"));
2880}
2881
2882#if TIME_WITH_SYS_TIME
2883#include <sys/time.h>
2884#include <time.h>
2885#else
2886#if HAVE_SYS_TIME_H
2887#include <sys/time.h>
2888#else
2889#include <time.h>
2890#endif
2891#endif
2892
[169]2893static int ListFullDetail = S_FALSE;
[1]2894static int ListWithDelimiter = S_FALSE;
[169]2895static char * ListFile = NULL;
[1]2896
[169]2897int set_list_file (const char * c)
2898{
2899 ListFile = sh_util_strdup(c);
2900 return 0;
2901}
[481]2902char * get_list_file()
2903{
2904 return ListFile;
2905}
[169]2906
[20]2907int set_full_detail (const char * c)
[1]2908{
[149]2909 (void) c;
[1]2910 ListFullDetail = S_TRUE;
[149]2911 return 0;
[1]2912}
2913
[20]2914int set_list_delimited (const char * c)
[1]2915{
[149]2916 (void) c;
[1]2917 ListFullDetail = S_TRUE;
2918 ListWithDelimiter = S_TRUE;
[149]2919 return 0;
[1]2920}
[76]2921
[149]2922/* Always quote the string, except if it is empty. Quote quotes by
[76]2923 * doubling them.
2924 */
2925char * csv_escape(const char * str)
2926{
2927 const char * p = str;
2928 const char * q;
2929
2930 size_t size = 0;
2931 size_t flag_quote = 0;
[362]2932
[76]2933 char * new;
2934 char * pnew;
2935
2936 if (p)
2937 {
2938
2939 while (*p)
2940 {
[362]2941 if (*p == '"')
[76]2942 ++flag_quote;
2943
2944 ++size; ++p;
2945 }
2946
2947 if (sl_ok_adds(size, flag_quote))
2948 size += flag_quote; /* double each quote */
2949 else
2950 return NULL;
2951
2952 if (sl_ok_adds(size, 3))
2953 size += 3; /* two quotes and terminating null */
2954 else
2955 return NULL;
2956
2957 new = SH_ALLOC(size);
2958
2959 if (flag_quote != 0)
2960 {
2961 new[0] = '"';
2962 pnew = &new[1];
2963 q = str;
2964 while (*q)
2965 {
2966 *pnew = *q;
2967 if (*pnew == '"')
2968 {
2969 ++pnew; *pnew = '"';
2970 }
2971 ++pnew; ++q;
2972 }
2973 *pnew = '"'; ++pnew;
2974 *pnew = '\0';
2975 }
2976 else
2977 {
2978 if (size > 3)
2979 {
2980 new[0] = '"';
2981 sl_strlcpy (&new[1], str, size-1);
2982 new[size-2] = '"';
2983 new[size-1] = '\0';
2984 }
2985 else
2986 {
2987 new[0] = '\0';
2988 }
2989 }
2990
2991 return new;
2992 }
2993 return NULL;
2994}
2995
[444]2996int isHexKey(char * s)
2997{
2998 int i;
2999
3000 for (i = 0; i < KEY_LEN; ++i)
3001 {
3002 if (*s)
3003 {
3004 if ((*s >= '0' && *s <= '9') ||
3005 (*s >= 'A' && *s <= 'F') ||
3006 (*s >= 'a' && *s <= 'f'))
3007 {
3008 ++s;
3009 continue;
3010 }
3011 }
3012 return S_FALSE;
3013 }
3014 return S_TRUE;
3015}
3016
3017#include "sh_checksum.h"
[76]3018
[444]3019static char * KEYBUFtolower (char * s, char * result)
3020{
3021 char * r = result;
3022 if (s)
3023 {
3024 for (; *s; ++s)
3025 {
3026 *r = tolower((unsigned char) *s); ++r;
3027 }
3028 *r = '\0';
3029 }
3030 return result;
3031}
3032
[1]3033void sh_hash_list_db_entry_full_detail (sh_file_t * p)
3034{
3035 char * tmp;
[76]3036 char * esc;
[1]3037 char str[81];
[444]3038 char hexdigest[SHA256_DIGEST_STRING_LENGTH];
3039 char keybuffer[KEYBUF_SIZE];
[1]3040
3041 if (ListWithDelimiter == S_TRUE)
3042 {
[40]3043 printf(_("%7ld, %7ld, %10s, %5d, %12s, %5d, %3d, %-8s, %5d, %-8s, %5d, "),
3044 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
[1]3045 p->theFile.c_mode, (int) p->theFile.mode,
3046 p->theFile.c_attributes, (int) p->theFile.attributes,
3047 (int) p->theFile.hardlinks,
3048 p->theFile.c_owner, (int) p->theFile.owner,
3049 p->theFile.c_group, (int) p->theFile.group);
3050 }
3051 else
3052 {
[40]3053 printf(_("%7ld %7ld %10s %5d %12s %5d %3d %-8s %5d %-8s %5d "),
3054 (unsigned long) p->theFile.ino, (unsigned long) p->theFile.dev,
[1]3055 p->theFile.c_mode, (int) p->theFile.mode,
3056 p->theFile.c_attributes, (int) p->theFile.attributes,
3057 (int) p->theFile.hardlinks,
3058 p->theFile.c_owner, (int) p->theFile.owner,
3059 p->theFile.c_group, (int) p->theFile.group);
3060 }
3061
3062 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
[132]3063 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.rdev);
[1]3064 else
[132]3065 sl_snprintf(str, sizeof(str), "%"PRIu64, p->theFile.size);
[1]3066
3067 printf( _(" %8s"), str);
3068 if (ListWithDelimiter == S_TRUE)
3069 putchar(',');
3070
[132]3071 printf( _(" %s"), sh_unix_gmttime (p->theFile.ctime, str, sizeof(str)));
[1]3072 if (ListWithDelimiter == S_TRUE)
3073 putchar(',');
[132]3074 printf( _(" %s"), sh_unix_gmttime (p->theFile.mtime, str, sizeof(str)));
[1]3075 if (ListWithDelimiter == S_TRUE)
3076 putchar(',');
[132]3077 printf( _(" %s"), sh_unix_gmttime (p->theFile.atime, str, sizeof(str)));
[1]3078 if (ListWithDelimiter == S_TRUE)
3079 putchar(',');
[444]3080
3081 if (isHexKey(p->theFile.checksum))
3082 printf( _(" %s"), KEYBUFtolower(p->theFile.checksum, keybuffer));
3083 else
3084 printf( _(" %s"), SHA256_Base2Hex(p->theFile.checksum, hexdigest));
[1]3085 if (ListWithDelimiter == S_TRUE)
3086 putchar(',');
3087
3088 tmp = sh_util_safe_name(p->fullpath);
[76]3089 if (ListWithDelimiter != S_TRUE)
3090 {
3091 printf( _(" %s"), tmp);
3092 }
3093 else
3094 {
3095 esc = csv_escape(tmp);
3096 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3097 if (esc)
3098 SH_FREE(esc);
3099 }
[1]3100 SH_FREE(tmp);
3101
3102 if ('l' == p->theFile.c_mode[0])
3103 {
3104 tmp = sh_util_safe_name(p->linkpath);
[76]3105 if (ListWithDelimiter != S_TRUE)
3106 {
3107 printf(_(" -> %s"), tmp);
3108 }
[1]3109 else
[76]3110 {
3111 esc = csv_escape(tmp);
3112 printf( _(" %s,"), (esc != NULL) ? esc : _("(null)"));
3113 if (esc)
3114 SH_FREE(esc);
3115 }
[1]3116 SH_FREE(tmp);
3117 }
[68]3118
3119 if (p->attr_string)
3120 {
3121 tmp = sh_util_safe_name(p->attr_string);
[76]3122 if (ListWithDelimiter != S_TRUE)
3123 {
3124 printf(_(" %s"), tmp);
3125 }
3126 else
3127 {
3128 esc = csv_escape(tmp);
3129 printf( _(" %s"), (esc != NULL) ? esc : _("(null)"));
3130 if (esc)
3131 SH_FREE(esc);
3132 }
[68]3133 SH_FREE(tmp);
3134 }
[1]3135 else
[68]3136 {
3137 if (ListWithDelimiter == S_TRUE)
[210]3138 printf("%s",_(" no_attr"));
[68]3139 }
3140 putchar('\n');
[1]3141
3142 return;
3143}
3144
3145void sh_hash_list_db_entry (sh_file_t * p)
3146{
3147 char nowtime[128];
3148 char thetime[128];
3149 char * tmp;
3150 time_t now = time(NULL);
3151 time_t then = (time_t) p->theFile.mtime;
[481]3152 struct tm * time_ptr;
[1]3153
[131]3154#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
3155 struct tm time_tm;
[481]3156#endif
[131]3157
[481]3158 if (ListFullDetail != S_FALSE)
3159 {
3160 sh_hash_list_db_entry_full_detail (p);
3161 return;
3162 }
3163
3164#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
[131]3165 time_ptr = gmtime_r(&then, &time_tm);
[481]3166 if (!time_ptr)
3167 return;
[131]3168 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3169 time_ptr = gmtime_r(&now, &time_tm);
[481]3170 if (!time_ptr)
3171 return;
[131]3172 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
3173 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
3174 {
3175 time_ptr = gmtime_r(&then, &time_tm);
[481]3176 if (!time_ptr)
3177 return;
[131]3178 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3179 }
3180#else
[481]3181 time_ptr = gmtime(&then);
3182 if (!time_ptr)
3183 return;
3184 strftime(thetime, 127, _("%b %d %Y"), time_ptr);
3185 time_ptr = gmtime(&now);
3186 if (!time_ptr)
3187 return;
3188 strftime(nowtime, 127, _("%b %d %Y"), time_ptr);
[1]3189 if (0 == strncmp(&nowtime[7], &thetime[7], 4))
[481]3190 {
3191 time_ptr = gmtime(&then);
3192 if (!time_ptr)
3193 return;
3194 strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
3195 }
[131]3196#endif
[1]3197
3198 tmp = sh_util_safe_name(p->fullpath);
3199 if ('c' == p->theFile.c_mode[0] || 'b' == p->theFile.c_mode[0])
3200 printf(_("%10s %3d %-8s %-8s %3d,%4d %s %s"),
3201 p->theFile.c_mode, (int) p->theFile.hardlinks,
3202 p->theFile.c_owner, p->theFile.c_group,
3203 (int) major((dev_t)p->theFile.rdev),
3204 (int) minor((dev_t)p->theFile.rdev),
3205 thetime,
3206 tmp);
3207 else
3208 printf(_("%10s %3d %-8s %-8s %8ld %s %s"),
3209 p->theFile.c_mode, (int) p->theFile.hardlinks,
3210 p->theFile.c_owner, p->theFile.c_group, (long) p->theFile.size,
3211 thetime,
3212 tmp);
3213 SH_FREE(tmp);
3214
3215 if ('l' == p->theFile.c_mode[0])
3216 {
3217 tmp = sh_util_safe_name(p->linkpath);
3218 printf(_(" -> %s\n"), tmp);
3219 SH_FREE(tmp);
3220 }
3221 else
3222 printf("\n");
3223
3224 return;
3225}
3226
[169]3227#ifdef HAVE_LIBZ
3228#include <zlib.h>
3229#endif
3230
3231int sh_hash_printcontent(char * linkpath)
3232{
3233#ifdef HAVE_LIBZ
3234 unsigned char * decoded;
3235 unsigned char * decompressed = NULL;
3236 size_t dlen;
3237 unsigned long clen;
3238 unsigned long clen_o;
3239 int res;
3240
3241 if (linkpath && *linkpath != '-')
3242 {
3243 dlen = sh_util_base64_dec_alloc (&decoded,
3244 (unsigned char *)linkpath,
3245 strlen(linkpath));
[170]3246
[169]3247 clen = dlen * 2 + 1;
[170]3248
[169]3249 do {
3250 if (decompressed)
3251 SH_FREE(decompressed);
3252 clen += dlen; clen_o = clen;
3253 decompressed = SH_ALLOC(clen);
3254 res = uncompress(decompressed, &clen, decoded, dlen);
3255 if (res == Z_MEM_ERROR)
[210]3256 { fprintf(stderr, "%s",_("Error: Not enough memory\n")); return -1; }
[169]3257 if (res == Z_DATA_ERROR)
[210]3258 { fprintf(stderr, "%s",_("Error: Data corrupt or incomplete\n")); return -1; }
[169]3259 } while (res == Z_BUF_ERROR || clen == clen_o);
[170]3260
[169]3261 decompressed[clen] = '\0';
3262 fputs( (char*) decompressed, stdout);
[227]3263 SH_FREE(decompressed);
[169]3264 return 0;
3265 }
3266#else
3267 (void) linkpath;
3268#endif
[210]3269 fprintf(stderr, "%s",_("Error: No data available\n"));
[169]3270 return -1;
3271}
3272
[1]3273/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
3274#endif
Note: See TracBrowser for help on using the repository browser.