source: trunk/src/sh_hash.c@ 590

Last change on this file since 590 was 590, checked in by katerina, 27 hours ago

Fix for ticket #478 (cppcheck warnings).

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