#!/usr/bin/perl use strict; use warnings; use File::Find; use YAML qw/LoadFile/; use Data::Dumper; use Digest::SHA1 qw/sha1_hex/; use DBI; use DateTime; my $dbh = DBI->connect("dbi:SQLite:dbname=checksum_db.sqlite","",""); my $config_path = 'config.yml'; my $config = LoadFile($config_path); sub add_to_db { my ($checksum,$last_modif_time,$size,$name)=@_; #maybe calculating is_* should be done in process_file my $is_dir = (-d $name)?'Y':'N'; my $is_file = (-f $name)?'Y':'N'; my $is_link = (-l $name)?'Y':'N'; $dbh->do( sprintf "INSERT INTO checksums (checksum,size,last_date_modified,name,is_dir,is_file,is_link) VALUES (\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\");", $checksum, $size, $last_modif_time->ymd, $name, $is_dir, $is_file, $is_link ); } sub update { my ($name,$checksum,$last_modif_time)=@_; $dbh->do(sprintf "UPDATE checksums SET checksum=\"%s\",last_date_modified=\"%s\" WHERE name=\"%s\";",$checksum,$name,$last_modif_time->ymd); } sub find_or_update { my ($name,$last_modif_time)=@_; my $s=$dbh->prepare(sprintf "SELECT last_date_modified FROM checksums WHERE name=\"%s\" ;",$name); $s->execute; my $results = $s->fetchall_arrayref; if($results) { #found it in the db; return 2 if $last_modif_time->ymd eq $results->[0]->[0] ; #return 2 if the entry is up to date update($name,file2sha1($name),$last_modif_time); return 1;# the entry is not up to date } return 0; #the entry has not be found- should be updated }; sub file2sha1 { my $file=$_[0]; return '' if -d $file; #have to find out if to prune when a directory is found that doesn't match the regex open my $f,"<$file"; my $sha1 = Digest::SHA1->new; $sha1->addfile(*$f); return $sha1->hexdigest; } sub process_file { my $dir_configs=$_[0]; return if -d $File::Find::name && ! $dir_configs->{dir}; return if -l $File::Find::name && ! $dir_configs->{link}; return if -f $File::Find::name && ! $dir_configs->{file}; return if -s $File::Find::name < $config->{minsize}; unless($File::Find::name =~ /$dir_configs->{regex}/) { if(-d $File::Find::name) { $File::Find::prune=1; } return; } my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($File::Find::name); my $last_modif_time=DateTime->from_epoch(epoch=>$mtime); #find out if entry needs update and update it if necesary #find_or_update returns 0 only if it hasnt found the file in the checksum db unless(find_or_update($File::Find::name,$last_modif_time)) { add_to_db(file2sha1($File::Find::name),$last_modif_time,-s $File::Find::name,$File::Find::name); #add it to db }; }; for my $searched_dir_hash (@{ $config->{directories} }) { next unless (-e $searched_dir_hash->{path} && -d $searched_dir_hash->{path}); find( { wanted=> sub { process_file($searched_dir_hash);} }, $searched_dir_hash->{path} ); }