summaryrefslogtreecommitdiffstats
path: root/lib/puppet/util/checksums.rb
blob: e129301e645767b7bc732295471735533a151618 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# A stand-alone module for calculating checksums
# in a generic way.
module Puppet::Util::Checksums
  class FakeChecksum
    def <<(*args)
      self
    end
  end

  # Is the provided string a checksum?
  def checksum?(string)
    string =~ /^\{(\w{3,5})\}\S+/
  end

  # Strip the checksum type from an existing checksum
  def sumdata(checksum)
    checksum =~ /^\{(\w+)\}(.+)/ ? $2 : nil
  end

  # Strip the checksum type from an existing checksum
  def sumtype(checksum)
    checksum =~ /^\{(\w+)\}/ ? $1 : nil
  end

  # Calculate a checksum using Digest::MD5.
  def md5(content)
    require 'digest/md5'
    Digest::MD5.hexdigest(content)
  end

  # Calculate a checksum of the first 500 chars of the content using Digest::MD5.
  def md5lite(content)
    md5(content[0..511])
  end

  # Calculate a checksum of a file's content using Digest::MD5.
  def md5_file(filename, lite = false)
    require 'digest/md5'

    digest = Digest::MD5.new
    checksum_file(digest, filename,  lite)
  end

  # Calculate a checksum of the first 500 chars of a file's content using Digest::MD5.
  def md5lite_file(filename)
    md5_file(filename, true)
  end

  def md5_stream(&block)
    require 'digest/md5'
    digest = Digest::MD5.new
    yield digest
    digest.hexdigest
  end

  alias :md5lite_stream :md5_stream

  # Return the :mtime timestamp of a file.
  def mtime_file(filename)
    File.stat(filename).send(:mtime)
  end

  # by definition this doesn't exist
  # but we still need to execute the block given
  def mtime_stream
    noop_digest = FakeChecksum.new
    yield noop_digest
    nil
  end

  def mtime(content)
    ""
  end

  # Calculate a checksum using Digest::SHA1.
  def sha1(content)
    require 'digest/sha1'
    Digest::SHA1.hexdigest(content)
  end

  # Calculate a checksum of the first 500 chars of the content using Digest::SHA1.
  def sha1lite(content)
    sha1(content[0..511])
  end

  # Calculate a checksum of a file's content using Digest::SHA1.
  def sha1_file(filename, lite = false)
    require 'digest/sha1'

    digest = Digest::SHA1.new
    checksum_file(digest, filename, lite)
  end

  # Calculate a checksum of the first 500 chars of a file's content using Digest::SHA1.
  def sha1lite_file(filename)
    sha1_file(filename, true)
  end

  def sha1_stream
    require 'digest/sha1'
    digest = Digest::SHA1.new
    yield digest
    digest.hexdigest
  end

  alias :sha1lite_stream :sha1_stream

  # Return the :ctime of a file.
  def ctime_file(filename)
    File.stat(filename).send(:ctime)
  end

  alias :ctime_stream :mtime_stream

  def ctime(content)
    ""
  end

  # Return a "no checksum"
  def none_file(filename)
    ""
  end

  def none_stream
    noop_digest = FakeChecksum.new
    yield noop_digest
    ""
  end

  def none(content)
    ""
  end

  private

  # Perform an incremental checksum on a file.
  def checksum_file(digest, filename, lite = false)
    buffer = lite ? 512 : 4096
    File.open(filename, 'r') do |file|
      while content = file.read(buffer)
        digest << content
        break if lite
      end
    end

    digest.hexdigest
  end
end