#!/usr/bin/perl die "fs-diff 1.1, check for new/changed/deleted files.\n fs-diff Save current state to /var/fs-diff/.snapshot fs-diff --snapshot Print current state fs-diff appname [snap1 [snap2]] Save difference between current state and /var/fs-diff/.snapshot to /var/fs-diff/appname With snap1 - diff current state and snap1 With snap1 and snap2 - diff snap1 and snap2\n" if grep {/^-h|--help$/} @ARGV; $stdout = shift if $ARGV[0] eq "--snapshot"; ($app_name, $snap1, $snap2) = @ARGV; if (not defined $app_name) { open DUMP,">/var/fs-diff/.snapshot" and select DUMP or die $! if ! $stdout; dir_snapshot("/"); } else { die "bad appname\n" unless $app_name=~/^\w[\w\d-.+]*$/; open(DIFF,">/var/fs-diff/$app_name") and select DIFF or die $!; open(OLD,(defined $snap1 ? $snap1 : "/var/fs-diff/.snapshot")) or die $!; open(NEW,(defined $snap2 ? $snap2 : "$0 --snapshot |")) or die $!; diff_snapshots(\*OLD, \*NEW); } sub dir_snapshot { my $cwd = $_[0]; my $file; my %EXCL = map {$_,1} qw(/dev /home /mnt /proc /root /tmp /usr/src /var/fs-diff /var/log /var/run /var/www); # /var/qmail /var/oops local ($,, $\) = (",","\n"); local *CWD; opendir(CWD, $cwd) or die "can't opendir `$cwd': $!"; while ($file = readdir(CWD)) { next if $file eq ".." or $file eq "." or $EXCL{$file = $cwd.$file}; print((lstat $file)[2,4,5,7,9], $file . (-d $file && "/"). (-l $file && " -> ".readlink($file))); dir_snapshot($file."/") if -d _ and not -l _; } } sub diff_snapshots { my ($OLD, $NEW) = @_; local ($,, $\) = (",","\n"); my ($file, %F); while (<$OLD>) { /^(?:[^,]*,){5}(.*)$/; ($file = $1) =~ s/ -> .*//; $F{$file} = $_; } while (<$NEW>) { /^(?:[^,]*,){5}(.*)$/; ($file = $1) =~ s/ -> .*//; if (not exists $F{$file}) { print(" $file") } elsif ($_ ne $F{$file} and $file !~ m{/$}) { print("? $file") } delete $F{$file}; } print "- $_" for keys %F; }