#!/usr/bin/perl -w

use strict;

use Digest::MD5 qw(md5_hex);

die "$0 disk blocksize\n" unless @ARGV == 2;

my $bs = $ARGV[1];

my %h;

my $blocks = 0;
my $zeroes = 0;
open DISK, $ARGV[0] or die "open: $!";
my $size = (stat ($ARGV[0]))[7];
print "disk size = $size\n";
print "\n";

for (my $i = 0; $i < $size; $i += $bs) {
    my $buf;
    read DISK, $buf, $bs;
    die (length $buf, " != ", $bs) unless length $buf == $bs;
    if ($buf eq ("\0" x $bs)) {
        $zeroes++;
    }
    else {
        my $digest = md5_hex ($buf);
        $h{$digest} = 0 unless exists $h{$digest};
        $h{$digest}++;
    }
    $blocks++;
}

my %hist;
my $lonely = 0;
foreach (keys %h) {
    my $n = $h{$_};
    if ($n > 1) {
        $hist{$n} = 0 unless exists $hist{$n};
        $hist{$n}++;
    } else {
        $lonely++;
    }
}

printf ("blocks of zeros:                       %s / %s\t%.1f%%\n", $zeroes, $blocks, 100 * $zeroes / $blocks);
printf ("blocks that could not be deduplicated: %s / %s\t%.1f%%\n", $lonely, $blocks, 100 * $lonely / $blocks);
print "\n";
foreach (sort { $b <=> $a }  keys %hist) {
    printf ("number of duplicates: %d\tcount: %d\t%.1f%%\n", $_, $hist{$_}, 100 * $hist{$_} / $blocks);
}
