fingerprint 1.0.0 → 1.1.3
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/README.md +40 -0
- data/bin/fingerprint +44 -16
- data/lib/fingerprint.rb +35 -12
- data/lib/fingerprint/checker.rb +105 -74
- data/lib/fingerprint/scanner.rb +125 -73
- data/lib/fingerprint/version.rb +21 -15
- metadata +8 -12
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Fingerprint
|
2
|
+
===========
|
3
|
+
|
4
|
+
* Author: Samuel G. D. Williams (<http://www.oriontransfer.co.nz>)
|
5
|
+
* Copyright (C) 2010, 2011 Samuel G. D. Williams.
|
6
|
+
* Released under the MIT license.
|
7
|
+
|
8
|
+
Fingerprint is primarily a command line tool to compare directory structures on
|
9
|
+
disk. It also provides a programmatic interface for this procedure.
|
10
|
+
|
11
|
+
Because Fingerprint produces output to `IO` like structures, it is easy to transmit
|
12
|
+
this data across a network, or store it for later use. As an example, it could be
|
13
|
+
used to check the integrity of a backup.
|
14
|
+
|
15
|
+
For examples please see the main [project page][1].
|
16
|
+
|
17
|
+
[1]: http://www.oriontransfer.co.nz/projects/admin-toolbox/fingerprint
|
18
|
+
|
19
|
+
License
|
20
|
+
-------
|
21
|
+
|
22
|
+
Copyright (c) 2010, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
23
|
+
|
24
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
25
|
+
of this software and associated documentation files (the "Software"), to deal
|
26
|
+
in the Software without restriction, including without limitation the rights
|
27
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
28
|
+
copies of the Software, and to permit persons to whom the Software is
|
29
|
+
furnished to do so, subject to the following conditions:
|
30
|
+
|
31
|
+
The above copyright notice and this permission notice shall be included in
|
32
|
+
all copies or substantial portions of the Software.
|
33
|
+
|
34
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
35
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
36
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
37
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
38
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
39
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
40
|
+
THE SOFTWARE.
|
data/bin/fingerprint
CHANGED
@@ -1,18 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
2
|
+
|
3
|
+
# Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
8
11
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
13
14
|
#
|
14
|
-
#
|
15
|
-
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
16
22
|
|
17
23
|
require 'optparse'
|
18
24
|
require 'fingerprint'
|
@@ -20,13 +26,14 @@ require 'fingerprint'
|
|
20
26
|
OPTIONS = {
|
21
27
|
:root => "./",
|
22
28
|
:mode => :scan,
|
23
|
-
:output => nil
|
29
|
+
:output => nil,
|
30
|
+
:verbose => false
|
24
31
|
}
|
25
32
|
|
26
33
|
ARGV.options do |o|
|
27
34
|
script_name = File.basename($0)
|
28
35
|
|
29
|
-
o.banner = "Usage: #{script_name} [options]"
|
36
|
+
o.banner = "Usage: #{script_name} [options] [path]"
|
30
37
|
o.define_head "This script is used to calculate and compare a basic file system fingerprint."
|
31
38
|
|
32
39
|
o.on("-c", "Compare the given fingerprints. Check that the second fingerprint is a superset of the first.") do
|
@@ -36,6 +43,10 @@ ARGV.options do |o|
|
|
36
43
|
o.on("-o [output-path]", String, "Write the fingerprint output to the given file.") do |path|
|
37
44
|
OPTIONS[:output] = File.open(path, "w")
|
38
45
|
end
|
46
|
+
|
47
|
+
o.on("--verbose", "Verbose output, include additional details in the file transcript.") do
|
48
|
+
OPTIONS[:verbose] = true
|
49
|
+
end
|
39
50
|
|
40
51
|
o.separator ""
|
41
52
|
o.separator "Help and Copyright information"
|
@@ -52,8 +63,25 @@ end.parse!
|
|
52
63
|
|
53
64
|
case (OPTIONS[:mode])
|
54
65
|
when :scan
|
55
|
-
|
66
|
+
roots = ARGV
|
67
|
+
roots << Dir.pwd if roots.size == 0
|
68
|
+
|
69
|
+
# Check that all supplied paths exist
|
70
|
+
roots.delete_if do |root|
|
71
|
+
if File.exist? root
|
72
|
+
false
|
73
|
+
else
|
74
|
+
$stderr.puts "Path #{root} doesn't exist, skipping!"
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
options = {}
|
80
|
+
options[:verbose] = true if OPTIONS[:verbose]
|
81
|
+
options[:output] = OPTIONS[:output] || $stdout
|
82
|
+
|
83
|
+
Fingerprint::Scanner.scan_paths(roots, options)
|
56
84
|
when :check
|
57
85
|
error_count = Fingerprint::Checker.check_files(ARGV[0], ARGV[1])
|
58
86
|
exit(error_count > 0 ? 1 : 0)
|
59
|
-
end
|
87
|
+
end
|
data/lib/fingerprint.rb
CHANGED
@@ -1,19 +1,42 @@
|
|
1
|
-
# Copyright (c)
|
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.
|
1
|
+
# Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'fingerprint/version'
|
17
22
|
require 'fingerprint/scanner'
|
18
23
|
require 'fingerprint/checker'
|
19
24
|
|
25
|
+
module Fingerprint
|
26
|
+
# A helper function to check two paths for consistency. Provides callback from +Fingerprint::Checker+.
|
27
|
+
def self.check_paths(master_path, copy_path, &block)
|
28
|
+
master = Scanner.new([master_path])
|
29
|
+
copy = Scanner.new([copy_path])
|
30
|
+
|
31
|
+
master.scan
|
32
|
+
copy.scan
|
33
|
+
|
34
|
+
master.output.seek(0)
|
35
|
+
copy.output.seek(0)
|
36
|
+
|
37
|
+
checker = Checker.new(master.output, copy.output)
|
38
|
+
checker.check(&block)
|
39
|
+
|
40
|
+
return checker
|
41
|
+
end
|
42
|
+
end
|
data/lib/fingerprint/checker.rb
CHANGED
@@ -1,82 +1,113 @@
|
|
1
|
-
# Copyright (c)
|
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.
|
1
|
+
# Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'set'
|
17
22
|
|
18
23
|
module Fingerprint
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
24
|
+
# Given two fingerprints (master and copy) ensures that the copy has at least everything contained
|
25
|
+
# in master: For every file in the master, a corresponding file must exist in the copy. This means that
|
26
|
+
# there may be extraneous files in the copy, but ensures that every file in the master has been replicated
|
27
|
+
# accurately.
|
28
|
+
#
|
29
|
+
# At this time, this implementation may require a large amount of memory, proportional to the number of
|
30
|
+
# files being checked.
|
31
|
+
#
|
32
|
+
# Master and copy are +IO+ objects corresponding to the output produced by +Fingerprint::Scanner+.
|
33
|
+
class Checker
|
34
|
+
def initialize(master, copy, options = {})
|
35
|
+
@master = master
|
36
|
+
@copy = copy
|
37
|
+
|
38
|
+
@mismatches = []
|
39
|
+
|
40
|
+
@options = options
|
41
|
+
|
42
|
+
@failures = []
|
43
|
+
end
|
44
|
+
|
45
|
+
# Run the checking process.
|
46
|
+
def check (options = {}, &block)
|
47
|
+
@files = Set.new
|
48
|
+
@file_paths = {}
|
49
|
+
@file_hashes = {}
|
50
|
+
|
51
|
+
# Parse original fingerprint
|
52
|
+
@copy.each_line do |line|
|
53
|
+
# Skip comments
|
54
|
+
next if line.match(/^\s+#/)
|
55
|
+
|
56
|
+
if line.chomp.match(/^([a-fA-F0-9]{32}): (.*)$/)
|
57
|
+
@files.add([$1, $2])
|
58
|
+
|
59
|
+
@file_paths[$2] = $1
|
60
|
+
@file_hashes[$1] ||= Set.new
|
61
|
+
@file_hashes[$1].add($2)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# For every file in the src, we check that it exists
|
66
|
+
# in the destination:
|
67
|
+
@master.each_line do |line|
|
68
|
+
# Skip comments
|
69
|
+
next if line.match(/^\s+#/)
|
70
|
+
|
71
|
+
if line.chomp.match(/^([a-fA-F0-9]{32}): (.*)$/)
|
72
|
+
unless @files.include?([$1, $2])
|
73
|
+
yield($1, $2) if block_given?
|
74
|
+
@failures << [$1, $2]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# A list of files which either did not exist in the copy, or had the wrong checksum.
|
81
|
+
attr :failures
|
82
|
+
|
83
|
+
# An array of all files in the copy
|
84
|
+
attr :files
|
85
|
+
|
86
|
+
# A hash of all files in copy +path => file hash+
|
87
|
+
attr :file_paths
|
88
|
+
|
89
|
+
# A hash of all files in copy +file hash => [file1, file2, ...]+
|
90
|
+
attr :file_hashes
|
91
|
+
|
92
|
+
# Helper function to check two fingerprint files.
|
93
|
+
def self.check_files(master, copy, &block)
|
94
|
+
error_count = 0
|
95
|
+
checker = Checker.new(File.open(master), File.open(copy))
|
96
|
+
|
97
|
+
checker.check do |hash, path|
|
98
|
+
error_count += 1
|
99
|
+
|
100
|
+
if !checker.file_paths[path]
|
101
|
+
$stderr.puts "Source file: #{path.dump} does not exist in destination!"
|
102
|
+
elsif checker.file_paths[path] != hash
|
103
|
+
$stderr.puts "Destination file: #{path.dump} is different!"
|
104
|
+
else
|
105
|
+
$stderr.puts "Unknown error for path: #{path.dump}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
return error_count
|
110
|
+
end
|
41
111
|
|
42
|
-
|
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
|
112
|
+
end
|
82
113
|
end
|
data/lib/fingerprint/scanner.rb
CHANGED
@@ -1,86 +1,138 @@
|
|
1
|
-
# Copyright (c)
|
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.
|
1
|
+
# Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
15
20
|
|
16
21
|
require 'stringio'
|
17
22
|
require 'find'
|
18
23
|
require 'digest'
|
19
24
|
|
20
25
|
module Fingerprint
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
|
27
|
+
# The default pattern for excluding files.
|
28
|
+
DEFAULT_EXCLUDES = [/\/\.[^\/]+$/, /\~$/]
|
29
|
+
|
30
|
+
# The scanner class can scan a set of directories and produce an index.
|
31
|
+
class Scanner
|
32
|
+
# Initialize the scanner to scan a given set of directories in order.
|
33
|
+
# [+options[:excludes]+] An array of regular expressions of files to avoid indexing.
|
34
|
+
# [+options[:output]+] An +IO+ where the results will be written.
|
35
|
+
def initialize(roots, options = {})
|
36
|
+
@roots = roots
|
37
|
+
|
38
|
+
@excludes = options[:excludes] || DEFAULT_EXCLUDES
|
39
|
+
@output = options[:output] || StringIO.new
|
40
|
+
|
41
|
+
@options = options
|
42
|
+
end
|
43
|
+
|
44
|
+
attr :output
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
# Adds a header for a given path which is mainly version information.
|
49
|
+
def output_header(root)
|
50
|
+
@output.puts "\# Checksum generated by Fingerprint (#{Fingerprint::VERSION::STRING}) at #{Time.now.to_s}"
|
51
|
+
@output.puts "\# Root: #{root}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Output a directory header.
|
55
|
+
def output_dir(path)
|
56
|
+
@output.puts ""
|
57
|
+
@output.puts((" " * 32) + " #{path}")
|
58
|
+
end
|
59
|
+
|
60
|
+
# Output a file and associated metadata.
|
61
|
+
def output_file(path)
|
62
|
+
d = Digest::MD5.new
|
31
63
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
64
|
+
File.open(path) do |f|
|
65
|
+
while buf = f.read(1024*1024*10)
|
66
|
+
d << buf
|
67
|
+
end
|
68
|
+
end
|
36
69
|
|
37
|
-
|
38
|
-
|
70
|
+
@output.puts "#{d.hexdigest}: #{path}"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Add information about excluded paths.
|
74
|
+
def output_excluded(path)
|
75
|
+
if @options[:verbose]
|
76
|
+
@output.puts '#'.ljust(32) + ": #{path}"
|
77
|
+
end
|
78
|
+
end
|
39
79
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
80
|
+
public
|
81
|
+
|
82
|
+
# Returns true if the given path should be excluded.
|
83
|
+
def excluded?(path)
|
84
|
+
@excludes.each do |exclusion|
|
85
|
+
if exclusion.match(path)
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
45
89
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
90
|
+
return false
|
91
|
+
end
|
92
|
+
|
93
|
+
# Run the scanning process.
|
94
|
+
def scan
|
95
|
+
excluded_count = 0
|
96
|
+
checksummed_count = 0
|
97
|
+
directory_count = 0
|
98
|
+
|
99
|
+
@roots.each do |root|
|
100
|
+
Dir.chdir(root) do
|
101
|
+
output_header(root)
|
102
|
+
Find.find("./") do |path|
|
103
|
+
if File.directory?(path)
|
104
|
+
if excluded?(path)
|
105
|
+
excluded_count += 1
|
106
|
+
output_excluded(path)
|
107
|
+
Find.prune # Ignore this directory
|
108
|
+
else
|
109
|
+
directory_count += 1
|
110
|
+
output_dir(path)
|
111
|
+
end
|
112
|
+
else
|
113
|
+
unless excluded?(path)
|
114
|
+
checksummed_count += 1
|
115
|
+
output_file(path)
|
116
|
+
else
|
117
|
+
excluded_count += 1
|
118
|
+
output_excluded(path)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Output summary
|
126
|
+
@output.puts "\# Directories: #{directory_count} Files: #{checksummed_count} Excluded: #{excluded_count}"
|
127
|
+
end
|
58
128
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
129
|
+
# A helper function to scan a set of directories.
|
130
|
+
def self.scan_paths(paths, options = {})
|
131
|
+
scanner = Scanner.new(paths, options)
|
132
|
+
|
133
|
+
scanner.scan
|
134
|
+
|
135
|
+
return scanner
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/fingerprint/version.rb
CHANGED
@@ -1,23 +1,29 @@
|
|
1
|
-
# Copyright (c)
|
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.
|
1
|
+
# Copyright (c) 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
|
7
2
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
15
21
|
|
16
22
|
module Fingerprint
|
17
|
-
module VERSION
|
23
|
+
module VERSION
|
18
24
|
MAJOR = 1
|
19
|
-
MINOR =
|
20
|
-
TINY =
|
25
|
+
MINOR = 1
|
26
|
+
TINY = 3
|
21
27
|
|
22
28
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
23
29
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fingerprint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
7
|
+
- 1
|
8
|
+
- 3
|
9
|
+
version: 1.1.3
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Samuel Williams
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2011-07-17 00:00:00 +12:00
|
19
18
|
default_executable: fingerprint
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -33,8 +32,9 @@ files:
|
|
33
32
|
- lib/fingerprint/scanner.rb
|
34
33
|
- lib/fingerprint/version.rb
|
35
34
|
- lib/fingerprint.rb
|
36
|
-
|
37
|
-
|
35
|
+
- README.md
|
36
|
+
has_rdoc: yard
|
37
|
+
homepage: http://www.oriontransfer.co.nz/projects/admin-toolbox/fingerprint
|
38
38
|
licenses: []
|
39
39
|
|
40
40
|
post_install_message:
|
@@ -43,27 +43,23 @@ rdoc_options: []
|
|
43
43
|
require_paths:
|
44
44
|
- lib
|
45
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
-
none: false
|
47
46
|
requirements:
|
48
47
|
- - ">="
|
49
48
|
- !ruby/object:Gem::Version
|
50
|
-
hash: 3
|
51
49
|
segments:
|
52
50
|
- 0
|
53
51
|
version: "0"
|
54
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
53
|
requirements:
|
57
54
|
- - ">="
|
58
55
|
- !ruby/object:Gem::Version
|
59
|
-
hash: 3
|
60
56
|
segments:
|
61
57
|
- 0
|
62
58
|
version: "0"
|
63
59
|
requirements: []
|
64
60
|
|
65
61
|
rubyforge_project:
|
66
|
-
rubygems_version: 1.3.
|
62
|
+
rubygems_version: 1.3.6
|
67
63
|
signing_key:
|
68
64
|
specification_version: 3
|
69
65
|
summary: Fingerprint is a tool for creating checksums of entire directory structures, and comparing them for inconsistencies.
|