fingerprint 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/fingerprint +59 -0
- data/lib/fingerprint.rb +19 -0
- data/lib/fingerprint/checker.rb +82 -0
- data/lib/fingerprint/scanner.rb +86 -0
- data/lib/fingerprint/version.rb +24 -0
- metadata +71 -0
data/bin/fingerprint
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
require 'optparse'
|
18
|
+
require 'fingerprint'
|
19
|
+
|
20
|
+
OPTIONS = {
|
21
|
+
:root => "./",
|
22
|
+
:mode => :scan,
|
23
|
+
:output => nil
|
24
|
+
}
|
25
|
+
|
26
|
+
ARGV.options do |o|
|
27
|
+
script_name = File.basename($0)
|
28
|
+
|
29
|
+
o.banner = "Usage: #{script_name} [options]"
|
30
|
+
o.define_head "This script is used to calculate and compare a basic file system fingerprint."
|
31
|
+
|
32
|
+
o.on("-c", "Compare the given fingerprints. Check that the second fingerprint is a superset of the first.") do
|
33
|
+
OPTIONS[:mode] = :check
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on("-o [output-path]", String, "Write the fingerprint output to the given file.") do |path|
|
37
|
+
OPTIONS[:output] = File.open(path, "w")
|
38
|
+
end
|
39
|
+
|
40
|
+
o.separator ""
|
41
|
+
o.separator "Help and Copyright information"
|
42
|
+
|
43
|
+
o.on_tail("--copy", "Display copyright information") {
|
44
|
+
puts "#{script_name} v#{Fingerprint::VERSION::STRING}. Copyright (c) 2010 Samuel Williams. Released under the GPLv3."
|
45
|
+
puts "See http://www.oriontransfer.co.nz/ for more information."
|
46
|
+
|
47
|
+
exit
|
48
|
+
}
|
49
|
+
|
50
|
+
o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
|
51
|
+
end.parse!
|
52
|
+
|
53
|
+
case (OPTIONS[:mode])
|
54
|
+
when :scan
|
55
|
+
Fingerprint::Scanner.scan_dirs(ARGV, OPTIONS[:output] || $stdout)
|
56
|
+
when :check
|
57
|
+
error_count = Fingerprint::Checker.check_files(ARGV[0], ARGV[1])
|
58
|
+
exit(error_count > 0 ? 1 : 0)
|
59
|
+
end
|
data/lib/fingerprint.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'fingerprint/version'
|
17
|
+
require 'fingerprint/scanner'
|
18
|
+
require 'fingerprint/checker'
|
19
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'set'
|
17
|
+
|
18
|
+
module Fingerprint
|
19
|
+
# Check that every file specified in fp2 exists in fp1 correctly,
|
20
|
+
# i.e. ensure that the fingerprint fp2 accurately is a superset of
|
21
|
+
# fp1
|
22
|
+
class Checker
|
23
|
+
def initialize(fp1, fp2)
|
24
|
+
@fp1 = fp1
|
25
|
+
@fp2 = fp2
|
26
|
+
@mismatches = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def check (&block)
|
30
|
+
@fp1.seek(0)
|
31
|
+
@fp2.seek(0)
|
32
|
+
|
33
|
+
@dst = Set.new
|
34
|
+
@dst_paths = {}
|
35
|
+
@dst_hashes = {}
|
36
|
+
|
37
|
+
# Parse original fingerprint
|
38
|
+
@fp2.each_line do |line|
|
39
|
+
if line.chomp.match(/^([a-fA-F0-9]{32}): (.*)$/)
|
40
|
+
@dst.add([$1, $2])
|
41
|
+
|
42
|
+
@dst_paths[$2] = $1
|
43
|
+
@dst_hashes[$1] ||= Set.new
|
44
|
+
@dst_hashes[$1].add($2)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# For every file in the src, we check that it exists
|
49
|
+
# in the destination:
|
50
|
+
@fp1.each_line do |line|
|
51
|
+
if line.chomp.match(/^([a-fA-F0-9]{32}): (.*)$/)
|
52
|
+
yield($1, $2, self) unless dst.include?([$1, $2])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr :dst
|
58
|
+
attr :dst_paths
|
59
|
+
attr :dst_hashes
|
60
|
+
|
61
|
+
def self.check_files(p1, p2)
|
62
|
+
puts "Comparing src: #{p1.dump} with dst: #{p2.dump}..."
|
63
|
+
error_count = 0
|
64
|
+
checker = Checker.new(File.open(p1), File.open(p2))
|
65
|
+
|
66
|
+
checker.check do |hash, path|
|
67
|
+
error_count += 1
|
68
|
+
|
69
|
+
if !checker.dst_paths[path]
|
70
|
+
puts "Source file: #{path.dump} does not exist in destination!"
|
71
|
+
elsif checker.dst_paths[path] != hash
|
72
|
+
puts "Destination file: #{path.dump} is different!"
|
73
|
+
else
|
74
|
+
puts "Unknown error for path: #{path.dump}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
return error_count
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
require 'stringio'
|
17
|
+
require 'find'
|
18
|
+
require 'digest'
|
19
|
+
|
20
|
+
module Fingerprint
|
21
|
+
|
22
|
+
class Scanner
|
23
|
+
def initialize(dirs)
|
24
|
+
@dirs = dirs
|
25
|
+
@dirs << Dir.pwd if dirs.size == 0
|
26
|
+
|
27
|
+
@excludes = [/^\._/]
|
28
|
+
|
29
|
+
@output = StringIO.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def output_dir(path)
|
33
|
+
@output.puts ""
|
34
|
+
@output.puts((" " * 32) + " #{path}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def output_file(path)
|
38
|
+
d = Digest::MD5.new
|
39
|
+
|
40
|
+
File.open(path) do |f|
|
41
|
+
while buf = f.read(1024*1024*10)
|
42
|
+
d << buf
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
@output.puts "#{d.hexdigest}: #{path}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def excluded?(path)
|
50
|
+
@excludes.each do |exclusion|
|
51
|
+
if exclusion.match(path)
|
52
|
+
return true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
def process
|
60
|
+
for dir in @dirs
|
61
|
+
Dir.chdir(dir) do
|
62
|
+
Find.find("./") do |path|
|
63
|
+
if FileTest.directory?(path)
|
64
|
+
if excluded?(path)
|
65
|
+
Find.prune # Ignore this directory
|
66
|
+
else
|
67
|
+
output_dir(path)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
output_file(path) unless excluded?(path)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end # Dir.chdir
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
attr :output, true
|
78
|
+
|
79
|
+
def self.scan_dirs(dirs, output = $stdout)
|
80
|
+
scanner = Scanner.new(dirs)
|
81
|
+
scanner.output = output
|
82
|
+
|
83
|
+
scanner.process
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3.
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
module Fingerprint
|
17
|
+
module VERSION #:nodoc:
|
18
|
+
MAJOR = 1
|
19
|
+
MINOR = 0
|
20
|
+
TINY = 0
|
21
|
+
|
22
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fingerprint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Samuel Williams
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-20 00:00:00 +13:00
|
19
|
+
default_executable: fingerprint
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description:
|
23
|
+
email: samuel@oriontransfer.org
|
24
|
+
executables:
|
25
|
+
- fingerprint
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- bin/fingerprint
|
32
|
+
- lib/fingerprint/checker.rb
|
33
|
+
- lib/fingerprint/scanner.rb
|
34
|
+
- lib/fingerprint/version.rb
|
35
|
+
- lib/fingerprint.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://www.oriontransfer.co.nz/software/admin-toolbox/fingerprint
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.7
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Fingerprint is a tool for creating checksums of entire directory structures, and comparing them for inconsistencies.
|
70
|
+
test_files: []
|
71
|
+
|