Advertisement
Guest User

tripwire.pl

a guest
Apr 15th, 2012
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 3.26 KB | None | 0 0
  1. use strict;
  2. use warnings;
  3. use Any::Daemon;
  4. use Digest::SHA1;
  5. use Getopt::Long;
  6. use Array::Utils qw(array_minus intersect);
  7.  
  8. my $dir=".";
  9. my $check_freq=10; #number of seconds between checks.
  10. my $username=$ENV{LOGNAME};
  11. my $max_iterations=0; #max number of iterations, 0 means there is no maximum.
  12. my $background=0; #flag to determine whether or not the daemon runs in the background.
  13.  
  14. GetOptions('d|dir=s'=>\$dir,
  15.     'c|check_freq=i'=>\$check_freq,
  16.     'u|username=s'=>\$username,
  17.     'm|max_iterations=i'=>\$max_iterations,
  18.     'b|background'=>\$background);
  19.  
  20. die "Check frequency must be positive" unless $check_freq>0;
  21.  
  22. die "No directory given" unless $dir;
  23.  
  24. die "The maximum number of iterations must be nonnegative" unless $max_iterations>=0;
  25.  
  26.  
  27. my $daemon=Any::Daemon->new(user=>$username,workdir=>$dir);
  28. $daemon->run(
  29.     background=>$background,
  30.     child_task=>\&check_dir,
  31.     max_childs=>1,
  32.     kill_childs=>sub{exit;}
  33.     );
  34.  
  35. sub check_dir
  36. {                      
  37.     opendir(my $dh,$dir) or die $!;
  38.     my @files=sort grep{(-f $_) and (-r $_)}readdir($dh);
  39.     closedir($dh);
  40.    
  41.     unless(@files)
  42.     {
  43.         print "No readable files found in directory $dir.\n";
  44.         exit 0;
  45.     }
  46.    
  47.     my %data=();
  48.    
  49.     #file_data returns a hash ref of the form
  50.     #{sha1=>$sha_digest,size=>$file_size}
  51.     $data{$_}=file_data($_) foreach(@files);
  52.    
  53.     my $counter=1;
  54.    
  55.     while(1)
  56.     {
  57.         sleep $check_freq;
  58.                                            
  59.         opendir(my $dh,$dir) or die $!;
  60.         my @updated_files=sort grep{(-f $_) and (-r $_)}readdir($dh);
  61.         closedir($dh);
  62.        
  63.         my @deleted_files=array_minus(@files,@updated_files);
  64.        
  65.         foreach my $file(@deleted_files)
  66.         {
  67.             print "$file has been deleted or moved from directory $dir.\n\n";
  68.            
  69.             print "Was:\n";
  70.             print "Size: " . $data{$file}->{size} . " bytes\n";
  71.             print "SHA1: " . $data{$file}->{sha1} . "\n\n";
  72.         }
  73.        
  74.         my %updated_data=();
  75.         $updated_data{$_}=file_data($_) foreach (@updated_files);
  76.        
  77.         my @new_files=array_minus(@updated_files,@files);
  78.        
  79.         foreach my $file(@new_files)
  80.         {
  81.             print "New file: $file\n\n";
  82.             print "Is now:\nSize: " . $updated_data{$file}->{size} . " bytes\n";
  83.             print "SHA1: " . $updated_data{$file}->{sha1} . "\n\n";
  84.         }
  85.        
  86.         my @intersection=intersect(@updated_files,@files);
  87.        
  88.         foreach my $file(@intersection)
  89.         {
  90.             unless(
  91.                     ($data{$file}->{size} == $updated_data{$file}->{size})
  92.                     and
  93.                     ($data{$file}->{sha1} eq $updated_data{$file}->{sha1})
  94.                 )
  95.             {
  96.                 print "$file changed.\n\n";
  97.                 print "Was:\n";
  98.                 print "Size: " . $data{$file}->{size} . " bytes\n";
  99.                 print "SHA1: " . $data{$file}->{sha1} . "\n\n";
  100.                
  101.                 print "Is now:\n";
  102.                 print "Size: " . $updated_data{$file}->{size} . " bytes\n";
  103.                 print "SHA1: " . $updated_data{$file}->{sha1} . "\n\n";
  104.             }
  105.         }
  106.        
  107.         #updating old files and old data with new stuff
  108.         @files=@updated_files;
  109.         %data=%updated_data;
  110.        
  111.         if($max_iterations)
  112.         {
  113.             print "Iteration $counter complete.\n";
  114.             if($counter==$max_iterations)
  115.             {
  116.                 kill 'INT',getppid or die "Cannot signal " . getppid . " with SIGINT: $!";
  117.                 exit 0;
  118.             }
  119.             $counter++;
  120.         }
  121.     }
  122.    
  123.    
  124. }
  125.  
  126. sub file_data
  127. {
  128.     my $file=shift;
  129.     die "No argument given to file_data" unless defined $file;
  130.    
  131.     open(my $fh,"<",$file) or die $!;
  132.     my $sha1=Digest::SHA1->new;
  133.     $sha1->addfile($fh);
  134.     my $digest=$sha1->hexdigest;
  135.     close($fh);
  136.     my $size = -s $file;
  137.     return {sha1=>$digest,size=>$size};
  138.    
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement