[Forensics-changes] [hashrat] 01/02: Imported Upstream version 1.8.0

Giovani Augusto Ferreira giovani-guest at moszumanska.debian.org
Thu Mar 24 13:46:43 UTC 2016


This is an automated email from the git hooks/post-receive script.

giovani-guest pushed a commit to branch debian
in repository hashrat.

commit 2f71ac50791d56a0692868803e4539274e244501
Author: Giovani Augusto Ferreira <giovani at riseup.net>
Date:   Thu Mar 24 10:45:51 2016 -0300

    Imported Upstream version 1.8.0
---
 README                           |  20 ++++--
 check-hash.c                     |  39 +++++++----
 check-hash.h                     |   2 +-
 check.sh                         |   2 +-
 command-line-args.c              |  21 +++++-
 common.c                         |   2 +-
 common.h                         |  13 +++-
 files.c                          |  71 ++++++++++++++++---
 find.c                           | 118 ++++++++++++++++++++++++++++---
 find.h                           |   1 +
 hashrat.1                        |  16 ++++-
 libUseful-2.1/GeneralFunctions.c |   1 -
 libUseful-2.1/Log.c              |   2 +-
 libUseful-2.1/configure          | 147 +++++++++++++++++++++++++++------------
 libUseful-2.1/configure.ac       |  10 +++
 libUseful-2.1/proctitle.c        |  10 ++-
 libUseful-2.1/pty.c              |   4 ++
 main.c                           |  57 +++++++--------
 18 files changed, 408 insertions(+), 128 deletions(-)

diff --git a/README b/README
index b8c7bd1..d69c925 100644
--- a/README
+++ b/README
@@ -77,6 +77,8 @@ Options:
   -n <length>     Truncate hashes to <length> bytes
   -c              CHECK hashes against list from file (or stdin)
   -cf             CHECK hashes but only show failures
+  -C              CHECK files against list from file (or stdin) can spot new files
+  -Cf             CHECK files but only show failures
   -m              MATCH files from a list read from stdin.
   -lm             Read hashes from stdin, upload them to a memcached server (requires the -memcached option).
   -X              In CHECK or MATCH mode only examine executable files.
@@ -235,11 +237,21 @@ USES FOR HASHRAT
 
 	Similarly these can then be used to check files later
 
-		cat /tmp/files.sha256 | hashrat -sha256 
-		hashrat -c -sha256 -r . -xattr
-		hashrat -c -sha256 -r . -memcached
+		cat /tmp/files.sha256 | hashrat -c -sha256 
+		cat /tmp/files.sha256 | hashrat -sha256 -C /tmp
+		hashrat -C -sha256 -xattr
+		hashrat -C -sha256 -memcached
+
+	Hashrat has four 'check' options:
+
+	-c   check from list
+	-cf  check from list and only show failures
+	-C   check directory
+	-Cf  check directory and only show failures
+
+	the -c forms only check the files listed on stdin. The -C forms read a list of files on stdin, but they expect to be given a directory to check, and they check every file in that directory, outputing any that weren't in the list, or that are in the list but not on disk, as well as any that have changed. Thus the -C forms allow one to detect new files, changed files, and deleted files, where the -c form only detects changed and deleted files. The -c and -C forms both work as -C if the ha [...]
 
-	There is a slight difference between xattr/memcached checks and checks where a list is read from stdin. Currently when reading from stdin hashrat will ONLY check the files in the list. However, in -xattr and -memcached mode, it will check all files, outputting and error for those where no stored hash can be found. This is likely to change in the a future release, with the stdin method being brought into line with the others.
+	Note that -C implies -r, so you don't need to supply -r
 
 
 	3) Finding files that match hashes.
diff --git a/check-hash.c b/check-hash.c
index 4ac965c..a82b4d9 100644
--- a/check-hash.c
+++ b/check-hash.c
@@ -63,12 +63,14 @@ int CheckStat(char *Path, struct stat *ExpectedStat, struct stat *Stat)
 }
 
 
-int CheckFileHash(HashratCtx *Ctx, char *Path, struct stat *Stat, char *ExpectedHash, char *ActualHash) 
+//FP here is the expected fingerprint of the file, ActualHash and Path are
+// its actual path and hash value
+
+int CheckFileHash(HashratCtx *Ctx, char *Path, struct stat *Stat, char *ActualHash, TFingerprint *FP) 
 {
 int result=FALSE;
 
-	if (strcasecmp(ExpectedHash,ActualHash)!=0) HandleCheckFail(Path, "Hash mismatch");
-	else
+	if (strcasecmp(FP->Hash,ActualHash) != 0) HandleCheckFail(Path, "Hash mismatch");
 	{
 		if (! (Flags & FLAG_OUTPUT_FAILS))
 		{
@@ -84,22 +86,34 @@ return(result);
 }
 
 
-int HashratCheckFile(HashratCtx *Ctx, char *Path, struct stat *ExpectedStat, struct stat *ActualStat, char *ExpectedHash,  char *ActualHash)
+int HashratCheckFile(HashratCtx *Ctx, char *Path, struct stat *ActualStat, char *ActualHash, TFingerprint *FP)
 {
 int result=FALSE;
+char *Tempstr=NULL;
 
 
-		if (access(Path,F_OK)!=0) fprintf(stderr,"\rERROR: No such file '%s'\n",Path);
+		if (access(Path,F_OK)!=0) 
+		{
+			//fprintf(stderr,"\rERROR: No such file '%s'\n",Path);
+			Tempstr=MCopyStr(Tempstr,"No such file [",Path,"]",NULL);
+			HandleCheckFail(Path, Tempstr);
+		}
+		else if (strcasecmp(FP->Path, Path) != 0) 
+		{
+				Tempstr=MCopyStr(Tempstr,"Moved [",FP->Path,"] to [",Path,"]",NULL);
+				HandleCheckFail(Path, Tempstr);
+		}
 		else
 		{
-			if (ExpectedStat)
+			if (FP->Flags & FP_HASSTAT) 
 			{
-				result=CheckStat(Path, ExpectedStat, ActualStat);
-				if (result) result=CheckFileHash(Ctx, Path, ActualStat, ExpectedHash, ActualHash); 
+				result=CheckStat(Path, &FP->FStat, ActualStat);
+				if (result) result=CheckFileHash(Ctx, Path, ActualStat, ActualHash, FP); 
 			}
-			else result=CheckFileHash(Ctx, Path, ActualStat, ExpectedHash, ActualHash); 
+			else result=CheckFileHash(Ctx, Path, ActualStat, ActualHash, FP); 
 		}
 
+DestroyString(Tempstr);
 return(result);
 }
 
@@ -110,7 +124,7 @@ char *HashStr=NULL, *ptr;
 int Checked=0, Errors=0;
 STREAM *ListStream;
 TFingerprint *FP;
-struct stat Stat, *ExpectedStat;
+struct stat Stat;
 
 
 ptr=GetVar(Ctx->Vars,"Path");
@@ -127,10 +141,7 @@ while (FP)
   if (StrLen(FP->HashType)) Ctx->HashType=CopyStr(Ctx->HashType, FP->HashType);
 	if (StatFile(Ctx,FP->Path,&Stat)==0) HashItem(Ctx, Ctx->HashType, FP->Path, &Stat, &HashStr);
 
-	if (FP->Flags & FP_HASSTAT) ExpectedStat=&FP->FStat;
-	else ExpectedStat=NULL;
-
-  if (! HashratCheckFile(Ctx, FP->Path, ExpectedStat, &Stat, FP->Hash, HashStr)) Errors++;
+  if (! HashratCheckFile(Ctx, FP->Path, &Stat, HashStr, FP)) Errors++;
   TFingerprintDestroy(FP);
   FP=FingerprintRead(ListStream);
   Checked++;
diff --git a/check-hash.h b/check-hash.h
index 89dabf6..bfef470 100644
--- a/check-hash.h
+++ b/check-hash.h
@@ -6,6 +6,6 @@
 
 int CheckHashesFromList(HashratCtx *Ctx);
 void HandleCheckFail(char *Path, char *ErrorMessage);
-int HashratCheckFile(HashratCtx *Ctx, char *Path, struct stat *ExpectedStat, struct stat *ActualStat, char *ExpectedHash, char *ActualHash);
+int HashratCheckFile(HashratCtx *Ctx, char *Path, struct stat *ActualStat, char *ActualHash, TFingerprint *FP);
 
 #endif
diff --git a/check.sh b/check.sh
index 9125ebc..6fa4585 100755
--- a/check.sh
+++ b/check.sh
@@ -114,7 +114,7 @@ TestHash z85 "ZEROMQ85 encoding" "wX%ElWFTQ9+Z=X4h"
 Title "Testing Misc. Features"
 
 HR_OUT=`./hashrat -version`
-if [ "$HR_OUT" = "version: 1.6.1" ]
+if [ "$HR_OUT" = "version: 1.8" ]
 then
 	OkayMessage "Version (-version) works"
 else
diff --git a/command-line-args.c b/command-line-args.c
index fc97d55..78d4088 100644
--- a/command-line-args.c
+++ b/command-line-args.c
@@ -206,14 +206,26 @@ else if (
 	Ctx->Action=ACT_PRINTUSAGE;
 	return(Ctx);
 }
-else if (strcmp(argv[i],"-c")==0)
+else if (strcmp(argv[i],"-C")==0)
 {
 	Ctx->Action = ACT_CHECK;
+	ParseFlags |= CommandLineHandleArg(argc, argv, i, 0, FLAG_RECURSE, "", "",Ctx->Vars);
 	strcpy(argv[i],"");
 }
-else if (strcmp(argv[i],"-cf")==0)
+else if (strcmp(argv[i],"-Cf")==0)
 {
 	Ctx->Action = ACT_CHECK;
+	ParseFlags |= CommandLineHandleArg(argc, argv, i, 0, FLAG_RECURSE | FLAG_OUTPUT_FAILS, "", "",Ctx->Vars);
+	strcpy(argv[i],"");
+}
+else if (strcmp(argv[i],"-c")==0)
+{
+	Ctx->Action = ACT_CHECK_LIST;
+	strcpy(argv[i],"");
+}
+else if (strcmp(argv[i],"-cf")==0)
+{
+	Ctx->Action = ACT_CHECK_LIST;
 	ParseFlags |= CommandLineHandleArg(argc, argv, i, 0, FLAG_OUTPUT_FAILS, "", "",Ctx->Vars);
 }
 else if (strcmp(argv[i],"-s")==0)
@@ -401,6 +413,7 @@ else Ctx->HashType=CopyStr(Ctx->HashType,GetVar(Ctx->Vars,"HashType"));
 switch (Ctx->Action)
 {
 case ACT_CHECK:
+case ACT_CHECK_LIST:
 	if (ParseFlags & CMDLINE_XATTR) Ctx->Action=ACT_CHECK_XATTR;
 	if (ParseFlags & CMDLINE_MEMCACHED) Ctx->Action=ACT_CHECK_MEMCACHED;
 break;
@@ -490,7 +503,9 @@ printf("  %-15s %s\n","-i <pattern>", "Only hash items matching <pattern>");
 printf("  %-15s %s\n","-x <pattern>", "Exclude items matching <pattern>");
 printf("  %-15s %s\n","-n <length>", "Truncate hashes to <length> bytes");
 printf("  %-15s %s\n","-c", "CHECK hashes against list from file (or stdin)");
-printf("  %-15s %s\n","-cf", "CHECK hashes but only show failures");
+printf("  %-15s %s\n","-cf", "CHECK hashes against list but only show failures");
+printf("  %-15s %s\n","-C <dir>", "Recursively CHECK directory against list of files on stdin ");
+printf("  %-15s %s\n","-Cf <dir>", "Recursively CHECK directory against list but only show failures");
 printf("  %-15s %s\n","-m", "MATCH files from a list read from stdin.");
 printf("  %-15s %s\n","-lm", "Read hashes from stdin, upload them to a memcached server (requires the -memcached option).");
 printf("  %-15s %s\n","-X", "In CHECK or MATCH mode only examine executable files.");
diff --git a/common.c b/common.c
index 4c41968..c3b9520 100644
--- a/common.c
+++ b/common.c
@@ -7,7 +7,7 @@ char *DiffHook=NULL;
 char *Key=NULL;
 char *LocalHost=NULL;
 ListNode *IncludeExclude=NULL;
-
+int MatchCount=0, DiffCount=0;
 
 char *HashratHashTypes[]={"md5","sha1","sha256","sha512","whirl","whirlpool","jh-224","jh-256","jh-384","jh-512",NULL};
 
diff --git a/common.h b/common.h
index 3ca6465..de5116d 100644
--- a/common.h
+++ b/common.h
@@ -14,8 +14,9 @@
 #define ACT_SIGN 7
 #define ACT_CHECKSIGN 8
 #define ACT_CHECK       10
-#define ACT_CHECK_XATTR 11
+#define ACT_CHECK_LIST  11
 #define ACT_CHECK_MEMCACHED 12
+#define ACT_CHECK_XATTR 13
 #define ACT_LOADMATCHES 20
 #define ACT_FINDMATCHES 21
 #define ACT_FINDMATCHES_MEMCACHED 22
@@ -57,6 +58,11 @@
 #define CTX_XATTR_CACHE 4096
 #define CTX_EXES 8192
 
+#define INEX_INCLUDE 1
+#define INEX_EXCLUDE 2
+#define INEX_INCLUDE_DIR 3
+#define INEX_EXCLUDE_DIR 4
+
 #define RESULT_PASS 1
 #define RESULT_FAIL 2
 #define RESULT_WARN 4
@@ -68,7 +74,7 @@
 
 #define BLOCKSIZE 4096
 
-#define VERSION "1.6.1"
+#define VERSION "1.8"
 
 
 typedef struct
@@ -79,6 +85,7 @@ char *Hash;
 char *HashType;
 char *Data;
 struct stat FStat;
+void *Next;
 } TFingerprint;
 
 
@@ -104,7 +111,7 @@ extern char *Key;
 extern char *LocalHost;
 extern char *HashratHashTypes[];
 extern ListNode *IncludeExclude;
-
+extern int MatchCount, DiffCount;
 
 TFingerprint *TFingerprintCreate(const char *Hash, const char *HashType, const char *Data, const char *Path);
 void HashratCtxDestroy(void *p_Ctx);
diff --git a/files.c b/files.c
index 6b8d756..d2adfe6 100644
--- a/files.c
+++ b/files.c
@@ -18,7 +18,6 @@ dev_t StartingFS=0;
 int FileType(char *Path, int FTFlags, struct stat *Stat)
 {
 
-
 	if ((FTFlags & FLAG_NET))
 	{
 		if (strncasecmp(Path,"ssh:",4)==0) return(FT_SSH);
@@ -67,12 +66,25 @@ while (Curr)
 		dptr=GetBasename(Path);
 	}
 	
-	if (fnmatch(mptr,dptr,0)==0) 
+	switch (Curr->ItemType)
 	{
-		if (Curr->ItemType==FLAG_INCLUDE) result=TRUE;
-		else result=FALSE;
+	case INEX_INCLUDE:
+	if (fnmatch(mptr,dptr,0)==0) result=TRUE;
+	break;
+
+	case INEX_EXCLUDE:
+	if (fnmatch(mptr,dptr,0)==0) result=FALSE;
+	break;
+
+	case INEX_INCLUDE_DIR:
+	if (strncmp(mptr,dptr,StrLen(mptr))==0) result=TRUE;
+	break;
+
+	case INEX_EXCLUDE_DIR:
+	if (strncmp(mptr,dptr,StrLen(mptr))==0) result=FALSE;
+	break;
 	}
-	
+
 	Curr=ListGetNext(Curr);
 }
 
@@ -311,6 +323,8 @@ int ConsiderItem(HashratCtx *Ctx, char *Path, struct stat *FStat)
 		break;
 	}
 
+	if (FStat)
+	{
 	if (Flags & FLAG_ONE_FS)
 	{
 		if (StartingFS==0) StartingFS=FStat->st_dev;
@@ -318,7 +332,7 @@ int ConsiderItem(HashratCtx *Ctx, char *Path, struct stat *FStat)
 	}
 	if ((Ctx->Flags & CTX_EXES) && (! (FStat->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) return(FLAG_EXCLUDE);
 	if (! IsIncluded(Path, FStat)) return(FLAG_EXCLUDE);
-
+	}
 
 	return(0);
 }
@@ -366,7 +380,8 @@ char *Tempstr=NULL;
 		break;
 
 		case FT_LNK:
-			fprintf(stderr,"WARN: Not following symbolic link %s\n",Path);
+		if (Ctx->Flags & CTX_DEREFERENCE)
+		{
 			Tempstr=SetStrLen(Tempstr,PATH_MAX);
 			val=readlink(Path, Tempstr,PATH_MAX);
 			if (val > 0)
@@ -374,6 +389,8 @@ char *Tempstr=NULL;
 				Tempstr[val]='\0';
 				ProcessData(HashStr, Ctx, Tempstr, val);
 			}
+		}
+		else fprintf(stderr,"WARN: Not following symbolic link %s\n",Path);
 		break;
 
 		default:
@@ -384,6 +401,13 @@ char *Tempstr=NULL;
 		break;
 	}
 
+  if (StrLen(DiffHook))
+  {
+    Tempstr=MCopyStr(Tempstr,DiffHook," '",Path,"'",NULL);
+    system(Tempstr);
+  }
+
+
 DestroyString(Tempstr);
 
 return(0);
@@ -405,6 +429,24 @@ case ACT_HASH:
 	HashratStoreHash(Ctx, Path, Stat, HashStr);
 break;
 
+case ACT_CHECK:
+	if (S_ISREG(Stat->st_mode))
+	{
+		if (Stat->st_size > 0)
+		{
+			HashItem(Ctx, Ctx->HashType, Path, Stat, &HashStr);
+			FP=CheckForMatch(Ctx, Path, Stat, HashStr);
+			if (FP)
+			{
+				if (HashratCheckFile(Ctx, Path, Stat, HashStr, FP)) MatchCount++;
+			}
+	   	else HandleCheckFail(Path, "Changed or new");
+			TFingerprintDestroy(FP);	
+			}
+		else if (Flags & FLAG_VERBOSE) fprintf(stderr,"ZERO LENGTH FILE: %s\n",Path);
+	}
+break;
+
 case ACT_CHECK_XATTR:
 	if (S_ISREG(Stat->st_mode))
 	{
@@ -412,8 +454,8 @@ case ACT_CHECK_XATTR:
 		if (FP) 
 		{
 			HashItem(Ctx, FP->HashType, Path, Stat, &HashStr);
-			if (FP->Flags & FP_HASSTAT) HashratCheckFile(Ctx, Path, &FP->FStat, Stat, FP->Hash, HashStr);
-			else HashratCheckFile(Ctx, Path, NULL, Stat, FP->Hash, HashStr);
+			if (FP->Flags & FP_HASSTAT) HashratCheckFile(Ctx, Path, Stat, HashStr, FP);
+			else HashratCheckFile(Ctx, Path, Stat, HashStr, FP);
 		}
 		else fprintf(stderr,"ERROR: No stored hash for '%s'\n",Path);
 	}
@@ -430,7 +472,7 @@ case ACT_CHECK_MEMCACHED:
     else FP->Path=MCopyStr(FP->Path,"hashrat://",LocalHost,Path,NULL);
     FP->Hash=MemcachedGet(FP->Hash, FP->Path);
 
-		if (FP) HashratCheckFile(Ctx, Path, NULL, NULL, FP->Hash, HashStr);
+		if (FP) HashratCheckFile(Ctx, Path, NULL, HashStr, FP);
 		else fprintf(stderr,"ERROR: No stored hash for '%s'\n",Path);
 		TFingerprintDestroy(FP);
 		}
@@ -446,7 +488,12 @@ case ACT_FINDMATCHES_MEMCACHED:
 		{
 		HashItem(Ctx, Ctx->HashType, Path, Stat, &HashStr);
 		FP=CheckForMatch(Ctx, Path, Stat, HashStr);
-		if (FP) printf("LOCATED: %s '%s %s' at %s\n",FP->Hash,FP->Path,FP->Data,Path);
+		if (FP)
+		{
+			printf("LOCATED: %s '%s %s' at %s\n",FP->Hash,FP->Path,FP->Data,Path);
+			MatchCount++;
+		}
+		else DiffCount++;
 		TFingerprintDestroy(FP);	
 		}
 		else if (Flags & FLAG_VERBOSE) fprintf(stderr,"ZERO LENGTH FILE: %s\n",Path);
@@ -464,11 +511,13 @@ case ACT_FINDDUPLICATES:
 			if (FP)
 			{
 				printf("DUPLICATE: %s of %s %s\n",Path,FP->Path,FP->Data);
+				MatchCount++;
 				TFingerprintDestroy(FP);	
 			}
 			else 
 			{
 				FP=TFingerprintCreate(HashStr, Ctx->HashType, Path, "");
+				DiffCount++;
 				MatchAdd(FP, Path, 0);
 			}
 		}
diff --git a/find.c b/find.c
index 8b8e245..5bbcb9a 100644
--- a/find.c
+++ b/find.c
@@ -5,7 +5,30 @@
 #include <search.h>
 
 
-void *Tree;
+/****************************************************
+
+This file contains the implementation of an in-memory storage/search
+system for hashes->paths. It's used in finding duplicate files, files
+matching a hash, and changed files.
+
+The libc 'tree' implementation is used for speed, but it can only
+store one item per key, so the node items (TFingerprint) have 
+a 'next' pointer, so that the system is a tree with linked lists 
+hanging off each node.
+
+In 'check' mode items are deleted from this list, so that we can detect
+items that have been deleted from the filesystem (as they are still 
+left in the tree at the end of a check)
+
+Because the head node is a real data node, and the head of the list
+it cannot be deleted if there are other items hanging off it, and so
+its path is set to 'blank' instead
+
+****************************************************/
+
+
+
+void *Tree=NULL;
 
 
 
@@ -25,6 +48,7 @@ int MatchAdd(TFingerprint *FP, const char *Path, int Flags)
 TFingerprint *Item;
 int result=FALSE;
 char *ptr;
+void *vptr;
 
 	if (Flags & FLAG_MEMCACHED)
 	{
@@ -35,7 +59,13 @@ char *ptr;
 	}
 	else
 	{
-		tsearch(FP, &Tree, MatchCompareFunc);
+			vptr=tsearch(FP, &Tree, MatchCompareFunc);
+			Item=*(TFingerprint **) vptr;
+		if (strcmp(Item->Path, FP->Path) !=0)
+		{
+			while (Item->Next !=NULL) Item=(TFingerprint *) Item->Next;
+			Item->Next=(void *) FP;
+		}
 		result=TRUE;
 	}
 
@@ -43,13 +73,39 @@ char *ptr;
 }
 
 
+TFingerprint *FindInMatches(HashratCtx *Ctx, TFingerprint *Head, const char *Path)
+{
+TFingerprint *Item=NULL, *Prev=NULL;
+
+Item=Head;
+Prev=Head;
+while (Item->Next && (strcmp(Path,Item->Path) !=0)) 
+{
+	Prev=Item;
+	Item=Item->Next;
+}
+
+if (strcmp(Path, Item->Path)==0) 
+{
+	if (Ctx->Action==ACT_CHECK) 
+	{
+		//unclip item from list
+		if (Item != Head) Prev->Next=Item->Next;
+	}
+	return(Item);
+}
+
+return(NULL);
+}
+
 
 
 TFingerprint *CheckForMatch(HashratCtx *Ctx, const char *Path, struct stat *FStat, const char *HashStr)
 {
-TFingerprint *Lookup, *Found, *Result=NULL;
+TFingerprint *Lookup, *Head=NULL, *Prev=NULL, *Item=NULL, *Result=NULL;
 void *ptr;
 
+if (! StrLen(Path)) return(NULL);
 
 Lookup=TFingerprintCreate(HashStr,"","",Path);
 if (Ctx->Action==ACT_FINDMATCHES_MEMCACHED)
@@ -60,11 +116,31 @@ if (Ctx->Action==ACT_FINDMATCHES_MEMCACHED)
 else
 {
 		ptr=tfind(Lookup, &Tree, MatchCompareFunc);
-		if (ptr)
+		if (ptr) 
 		{
-			Found=*(TFingerprint **) ptr;
-			Result=TFingerprintCreate(Found->Hash, Found->HashType, Found->Data, Found->Path);
-		}
+			Item=FindInMatches(Ctx, *(TFingerprint **) ptr, Path);
+
+      if (Item) 
+			{
+			Result=TFingerprintCreate(Item->Hash, Item->HashType, Item->Data, Item->Path);
+      if (Ctx->Action==ACT_CHECK)
+      {
+        if (Item==Head) 
+				{
+					if (Item->Next==NULL) 
+					{
+						// tree functions take a copy of the 'head' item, so we cannot
+						// destroy it. No idea how they do this, it's magic
+						// however we can destroy non-head items that we hang off
+						// the tree
+						tdelete(Lookup, &Tree, MatchCompareFunc);
+					}
+					else Item->Path=CopyStr(Item->Path, "");
+				}
+				//else TFingerprintDestroy(Item);
+      }
+      }
+    }
 }
 
 TFingerprintDestroy(Lookup);
@@ -72,7 +148,33 @@ TFingerprintDestroy(Lookup);
 return(Result);
 }
 
+void OutputUnmatchedItem(const void *p_Item, const VISIT which, const int depth)
+{
+	TFingerprint *Item;
+
+	if ((which==preorder) || (which==leaf))
+	{
+		Item=*(TFingerprint **) p_Item;
+	
+		while (Item)
+		{
+			//if a root node of the linked list has been deleted, its path is
+			//set blank, rather than actually deleting it, as we need it to 
+			//continue acting as the head node
+			if (StrLen(Item->Path))
+			{
+			if (access(Item->Path, F_OK) !=0) HandleCheckFail(Item->Path, "Missing");
+			}
+			Item=Item->Next;
+		}
+	}
+}
+
 
+void OutputUnmatched(HashratCtx *Ctx)
+{
+twalk (Tree, OutputUnmatchedItem);
+}
 
 
 int LoadFromIOC(const char *XML, int Flags)
@@ -117,7 +219,7 @@ int count=0;
 
 
 S=STREAMFromFD(0);
-STREAMSetTimeout(S,1);
+STREAMSetTimeout(S,100);
 Line=STREAMReadLine(Line,S);
 if (! StrLen(Line)) return(NULL);
 
diff --git a/find.h b/find.h
index d44fce0..782608f 100644
--- a/find.h
+++ b/find.h
@@ -7,6 +7,7 @@
 
 void *MatchesLoad();
 void LoadMatchesToMemcache();
+void OutputUnmatched(HashratCtx *Ctx);
 int MatchAdd(TFingerprint *FP, const char *Path, int Flags);
 TFingerprint *CheckForMatch(HashratCtx *Ctx, const char *Path, struct stat *FStat, const char *HashStr);
 
diff --git a/hashrat.1 b/hashrat.1
index 540ed31..0abaa1e 100644
--- a/hashrat.1
+++ b/hashrat.1
@@ -155,6 +155,14 @@ CHECK \fIhashes\fP against list from \fIfile\fP (or stdin).
 CHECK \fIhashes\fP but only show failures.
 .TP
 .B
+\fB-C <dir>\fP
+CHECK \fIfiles\fP under dir recursively against a list from \fIfile\fP (or stdin). This can detect 'new' files
+.TP
+.B
+\fB-Cf <dir>\fP
+CHECK \fIfiles\fP under dir recursively against a list from \fIfile\fP (or stdin). This can detect 'new' files. Only show failures.
+.TP
+.B
 \fB-m\fP
 MATCH files from a list read from stdin.
 .TP
@@ -446,14 +454,16 @@ Similarly these can then be used \fIto\fP check files later:
 .PP
 .nf
 .fam C
-    $ cat /tmp/files.sha256 | hashrat \-sha256
+    $ cat /tmp/files.sha256 | hashrat -c \-sha256
 
-    $ hashrat \-c \-sha256 \-r . \-xattr
+    $ hashrat \-C . \-sha256  \-xattr
 
-    $ hashrat \-c \-sha256 \-r . \-memcached
+    $ hashrat \-C /tmp \-sha256  \-memcached
 
 .fam T
 .fi
+Note that -c checks only check the files in the supplied list. The -C flag instead checks all files in a directory (supplied on command line) and expects to find those in the list. This means that -C can find new files that aren't in the list, whereas -c can't.
+.fi
 There is a slight difference between xattr/memcached checks and checks where a list is read from stdin. Currently when reading from stdin \fBhashrat\fP will ONLY check the
 files in the list. However, in \fB-xattr\fP and \fB-memcached\fP mode, it will check all files, outputting and error for those where no stored \fIhash\fP can be found. This is likely
 \fIto\fP change in the a future release, with the stdin method being brought into line with the others.
diff --git a/libUseful-2.1/GeneralFunctions.c b/libUseful-2.1/GeneralFunctions.c
index 5497863..ca7f64c 100644
--- a/libUseful-2.1/GeneralFunctions.c
+++ b/libUseful-2.1/GeneralFunctions.c
@@ -131,7 +131,6 @@ for (ptr=Bytes; ptr < end; )
 	//so for the last chracter
 	RetStr=CatStrLen(RetStr,Buff,ptr-block);
 } 
-printf("\n");
 
 return(RetStr);
 }
diff --git a/libUseful-2.1/Log.c b/libUseful-2.1/Log.c
index ab81035..3264065 100644
--- a/libUseful-2.1/Log.c
+++ b/libUseful-2.1/Log.c
@@ -184,7 +184,7 @@ int LogFileInternalWrite(TLogFile *LF, STREAM *S, int Flags, const char *Str)
 
 		if (ParentPID==0) ParentPID=getpid();
 		if (LF) S=LogFileInternalDoRotate(LF);
-		if (! S) return;
+		if (! S) return(result);
 
 		gettimeofday(&Now,NULL);
 		if (Flags & LOGFILE_TIMESTAMP)
diff --git a/libUseful-2.1/configure b/libUseful-2.1/configure
index 4908d44..375cc42 100755
--- a/libUseful-2.1/configure
+++ b/libUseful-2.1/configure
@@ -1511,6 +1511,52 @@ fi
 
 } # ac_fn_c_try_run
 
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
 # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
 # -------------------------------------------------------
 # Tests whether HEADER exists, giving a warning if it cannot be compiled using
@@ -1629,52 +1675,6 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_header_compile
 
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  rm -f conftest.$ac_objext conftest$ac_exeext
-  if { { ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    grep -v '^ *+' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-    mv -f conftest.er1 conftest.err
-  fi
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && {
-	 test -z "$ac_c_werror_flag" ||
-	 test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-	 test "$cross_compiling" = yes ||
-	 test -x conftest$ac_exeext
-       }; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-	ac_retval=1
-fi
-  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
-  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
-  # interfere with the next link command; also delete a directory that is
-  # left behind by Apple's compiler.  We do this before executing the actions.
-  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
 # ac_fn_c_check_func LINENO FUNC VAR
 # ----------------------------------
 # Tests whether FUNC exists, setting the cache variable VAR accordingly
@@ -3511,6 +3511,61 @@ cf_have_libz=yes
 cf_have_oss=no
 cf_have_libesd=no
 cf_have_sendfile=no
+cf_have_ptsname_r=no
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ptsname_r in -lc" >&5
+$as_echo_n "checking for ptsname_r in -lc... " >&6; }
+if ${ac_cv_lib_c_ptsname_r+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ptsname_r ();
+int
+main ()
+{
+return ptsname_r ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_c_ptsname_r=yes
+else
+  ac_cv_lib_c_ptsname_r=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_ptsname_r" >&5
+$as_echo "$ac_cv_lib_c_ptsname_r" >&6; }
+if test "x$ac_cv_lib_c_ptsname_r" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC 1
+_ACEOF
+
+  LIBS="-lc $LIBS"
+
+fi
+
+cf_have_ptsname_r=$ac_cv_lib_c_ptsname_r
+if test "$cf_have_ptsname_r"
+then
+$as_echo "#define HAVE_PTSNAME_R 1" >>confdefs.h
+
+fi
+
 
 # Check whether --enable-sendfile was given.
 if test "${enable_sendfile+set}" = set; then :
diff --git a/libUseful-2.1/configure.ac b/libUseful-2.1/configure.ac
index a09bb1b..8a744c0 100644
--- a/libUseful-2.1/configure.ac
+++ b/libUseful-2.1/configure.ac
@@ -16,6 +16,16 @@ cf_have_libz=yes
 cf_have_oss=no
 cf_have_libesd=no
 cf_have_sendfile=no
+cf_have_ptsname_r=no
+
+
+AC_CHECK_LIB(c,ptsname_r,,)
+cf_have_ptsname_r=$ac_cv_lib_c_ptsname_r
+if test "$cf_have_ptsname_r"
+then
+AC_DEFINE([HAVE_PTSNAME_R])
+fi
+
 
 AC_ARG_ENABLE(sendfile, [  --enable-sendfile       enable sendfile support], cf_use_sendfile=$enableval )
 
diff --git a/libUseful-2.1/proctitle.c b/libUseful-2.1/proctitle.c
index b4e61d0..3b1bca8 100644
--- a/libUseful-2.1/proctitle.c
+++ b/libUseful-2.1/proctitle.c
@@ -5,8 +5,6 @@
 /*This is code to change the command-line of a program as visible in ps */
 
 extern char **environ;
-extern char *program_invocation_name;
-extern char *program_invocation_short_name;
 char *TitleBuffer=NULL;
 int TitleLen=0;
 
@@ -39,8 +37,13 @@ void ProcessTitleCaptureBuffer(char **argv)
 {
 char **arg, *end=NULL, *tmp;
 
+#ifdef __GNU_LIBRARY__
+extern char *program_invocation_name;
+extern char *program_invocation_short_name;
+
 program_invocation_name=strdup(program_invocation_name);
 program_invocation_short_name=strdup(program_invocation_short_name);
+#endif
 
 TitleBuffer=argv[0];
 arg=argv;
@@ -52,7 +55,8 @@ arg++;
 }
 
 arg=environ;
-clearenv();
+//clearenv();  //clearenv is not portable
+environ[0]=NULL;
 while (*arg)
 {
 	for (end=*arg; *end != '\0'; end++);
diff --git a/libUseful-2.1/pty.c b/libUseful-2.1/pty.c
index 88eec35..d997efa 100644
--- a/libUseful-2.1/pty.c
+++ b/libUseful-2.1/pty.c
@@ -197,6 +197,8 @@ int GrabPseudoTTY(int *pty, int *tty, int TermFlags)
 char c1,c2;
 char *Tempstr=NULL;
 
+#ifdef __GNU_LIBRARY__
+#ifdef HAVE_PTSNAME_R
 //first try unix98 style
 *pty=open("/dev/ptmx",O_RDWR);
 if (*pty > -1)
@@ -215,6 +217,8 @@ if (*pty > -1)
 	}
 	close(*pty);
 }
+#endif
+#endif
 
 //if unix98 fails, try old BSD style
 
diff --git a/main.c b/main.c
index 783d5f8..0027c9f 100644
--- a/main.c
+++ b/main.c
@@ -9,7 +9,6 @@
 #include "filesigning.h"
 #include "cgi.h"
 
-
 void HashFromListFile(HashratCtx *Ctx)
 {
 char *Tempstr=NULL, *HashStr=NULL;
@@ -134,10 +133,37 @@ switch (Ctx->Action)
 	if (count==0) HashStdIn(Ctx);
 	break;
 
-	case ACT_CHECK:
+	case ACT_CHECK_LIST:
 		result=CheckHashesFromList(Ctx);
 	break;
 
+	case ACT_HASH_LISTFILE:
+		HashFromListFile(Ctx);
+	break;
+
+	case ACT_CHECK:
+	case ACT_FINDMATCHES:
+	if (! MatchesLoad(0))
+	{
+		printf("No hashes supplied on stdin.\n");
+		exit(1);
+	}
+	ProcessCommandLine(Ctx, argc, argv);
+	if (Ctx->Action==ACT_CHECK) OutputUnmatched(Ctx);
+	break;
+
+	//Load matches to an mcached server
+	case ACT_LOADMATCHES:
+	ptr=GetVar(Ctx->Vars, "Memcached:Server");
+	if (StrLen(ptr) ==0) printf("ERROR: No memcached server specified. Use the -memcached <server> command-line argument to specify one\n");
+	else MatchesLoad(FLAG_MEMCACHED);
+	break;
+
+	case ACT_FINDMATCHES_MEMCACHED:
+	case ACT_FINDDUPLICATES:
+	ProcessCommandLine(Ctx, argc, argv);
+	break;
+
 	case ACT_CHECK_XATTR:
 		ProcessCommandLine(Ctx, argc, argv);
 	break;
@@ -146,6 +172,7 @@ switch (Ctx->Action)
 		ProcessCommandLine(Ctx, argc, argv);
 	break;
 
+
 	case ACT_CGI:
 		CGIDisplayPage();
 	break;
@@ -154,10 +181,6 @@ switch (Ctx->Action)
 		CommandLinePrintUsage();
 	break;
 
-	case ACT_HASH_LISTFILE:
-		HashFromListFile(Ctx);
-	break;
-
 	case ACT_SIGN:
 	Ctx->Encoding = ENCODE_BASE64;
 	for (i=1; i < argc; i++)
@@ -191,28 +214,6 @@ switch (Ctx->Action)
 	}
 	}
 	break;
-
-	case ACT_LOADMATCHES:
-	ptr=GetVar(Ctx->Vars, "Memcached:Server");
-	if (StrLen(ptr) ==0) printf("ERROR: No memcached server specified. Use the -memcached <server> command-line argument to specify one\n");
-	else MatchesLoad(FLAG_MEMCACHED);
-	break;
-
-	case ACT_FINDMATCHES:
-	if (! MatchesLoad(0))
-	{
-		printf("No hashes supplied on stdin.\n");
-		exit(1);
-	}
-	ProcessCommandLine(Ctx, argc, argv);
-	break;
-
-	case ACT_FINDMATCHES_MEMCACHED:
-	case ACT_FINDDUPLICATES:
-	ProcessCommandLine(Ctx, argc, argv);
-	break;
-
-
 }
 
 fflush(NULL);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/hashrat.git



More information about the forensics-changes mailing list