File Coverage

blib/lib/File/Fingerprint/Huge.pm
Criterion Covered Total %
statement 34 47 72.3
branch 4 12 33.3
condition n/a
subroutine 8 10 80.0
pod 6 6 100.0
total 52 75 69.3


line stmt bran cond sub pod time code
1             package File::Fingerprint::Huge;
2              
3 4     4   89673 use Math::Random::MT qw[ rand srand ];
  4         5933  
  4         26  
4 4     4   4114 use Digest::CRC qw[ crc64 ];
  4         35487  
  4         906  
5 4     4   44 use strict;
  4         13  
  4         153  
6 4     4   25 use vars qw ($VERSION);
  4         9  
  4         5252  
7              
8             $VERSION = $1 if('$Id: Huge.pm,v 1.4 2012/02/14 16:02:36 cfaber Exp $' =~ /,v ([\d.]+) /);
9              
10             =head1 NAME
11              
12             File::Fingerprint::Huge
13              
14             =head1 DESCRIPTION
15              
16             The File::Fingerprint::Huge library is designed to quickly finger print very large files which a very high probability of uniqueness. However absolute uniqueness cannot be guaranteed.
17              
18             =head1 SYNOPSIS
19              
20             use File::Fingerprint::Huge;
21             my $fp = File::Fingerprint::Huge->new("/largefile");
22              
23             my $crc64 = $fp->fp_crc64;
24              
25             print $crc64 . "\n";
26              
27             exit;
28              
29              
30             =head1 METHODS
31              
32              
33             =head2 new(file)
34              
35             Create a new File::Fingerprint::Huge object based on B which is a large file to scan.
36              
37             =cut
38              
39             sub new {
40 3     3 1 39 my ($class, $file) = @_;
41 3 50       494 return bless { file => $file, crc64 => (eval "Digest::CRC::crc64(1234)" ? 1 : 0)}, $class;
42             }
43              
44             =head2 fp_file(filename)
45              
46             Change the file to checksum by assigning B as the new file.
47              
48             =cut
49              
50             sub fp_file {
51 0     0 1 0 my ($self, $file) = @_;
52 0         0 $self->{file} = $file;
53 0         0 return 1;
54             }
55              
56             =head2 fp_chunks()
57              
58             Fetch data chunks for checksum processing and return them
59              
60             =cut
61              
62             sub fp_chunks {
63 2     2 1 5 my ($self) = @_;
64              
65 2         52 my $size = (stat($self->{file}))[7];
66              
67 2         12 srand($size);
68              
69 2 50       176 if(open(my $fh, "<", $self->{file})){
70 2         8 my $chunks = int( $size / 8 ) - 1;
71              
72             ## Added sort per RichardK's suggestion below.
73 2         16 my @posns = sort { $a <=> $b } map 8 * int( rand $chunks ), 1 .. 100;
  1098         1916  
74              
75 2         11 my $sample = join '', map { seek $fh, $_, 0; read( $fh, my $chunk, 8 ); $chunk } @posns;
  200         1644  
  200         1551  
  200         2078  
76 2         49 close $fh;
77              
78 2         27 return $sample;
79             } else {
80 0         0 return;
81             }
82             }
83              
84              
85             =head2 fp_crc64()
86              
87             Return a CRC64 number based on large file scan
88              
89             =cut
90              
91             sub fp_crc64 {
92 0     0 1 0 my ($self) = @_;
93 0 0       0 if($self->{use_crc32}){
94 0         0 $! = "ERROR: crc64() does not appear functional. Use fp_crc32.";
95 0         0 return;
96             }
97              
98 0 0       0 if(my $sample = $self->fp_chunks){
99 0         0 return Digest::CRC::crc64( $sample );
100             } else {
101 0         0 return;
102             }
103             }
104              
105             =head2 fp_crc32()
106              
107             Return a CRC32 number based on the large file scan
108              
109             =cut
110              
111             sub fp_crc32 {
112 1     1 1 7659 my ($self) = @_;
113 1 50       4 if(my $sample = $self->fp_chunks){
114 1         9 return Digest::CRC::crc32( $sample );
115             } else {
116 0         0 return;
117             }
118             }
119              
120             =head2 fp_md5hex()
121              
122             Return an MD5 checksum hash based on the large file scan
123              
124             =cut
125              
126             sub fp_md5hex {
127 1     1 1 88 my ($self) = @_;
128 1 50       5 if(my $sample = $self->fp_chunks){
129 1         10 require Digest::MD5;
130 1         14 return Digest::MD5::md5_hex( $sample );
131             } else {
132 0           return;
133             }
134             }
135              
136             1;
137              
138             __END__