Class: Cfruby::Checksum::Checksum

Inherits:
Object
  • Object
show all
Defined in:
lib/libcfruby/checksum.rb

Overview

The Checksum class ties to a database file and has methods for adding files to the database, and checking existing files against their previously added checkums. In addition get_checksums may be called on files or IO streams without instantiating an instance of Checksum for quick checks.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(databasefile = nil, user = Process.euid, group = Process.egid, mode = 0600) ⇒ Checksum

Takes an optional databasefile to use and a user, group, and mode to enforce for that file. Most functions cannot be used without an actual database file.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/libcfruby/checksum.rb', line 77

def initialize(databasefile=nil, user=Process.euid, group=Process.egid, mode=0600)
	@mode = mode
	@user = user
	@group = group

	# convert mode to internal representation
	modefile = Tempfile.new('checksum')
	modefilepath = modefile.path
	modefile.close(true)
	Cfruby::FileOps.create(modefilepath, Process.euid, Process.egid, mode)
	@statmode = File.stat(modefilepath).mode
	Cfruby::FileOps.delete(modefilepath)

	@database = Hash.new()
	
	if(databasefile != nil)
		self.databasefile=(databasefile)
	end
end

Instance Attribute Details

#databaseObject (readonly)

Returns the value of attribute database.



72
73
74
# File 'lib/libcfruby/checksum.rb', line 72

def database
  @database
end

#databasefileObject

Returns the value of attribute databasefile.



72
73
74
# File 'lib/libcfruby/checksum.rb', line 72

def databasefile
  @databasefile
end

Class Method Details

.get_checksums(object) ⇒ Object

returns the checksum of object (may be a filename or an IO object). The checksum contains the following fields:

uid

User id of the file’s owner

gid

Group id of the file’s group

permissions

Integer representation of the file’s permissions

md5

MD5 hash of the file’s contents

sha1

SHA1 hash of the file’s contents

timestamp

The modification time of the file



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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/libcfruby/checksum.rb', line 119

def Checksum.get_checksums(object)
	checksums = ChecksumValues.new()
	
	md5digest = Digest::MD5.new()
	shadigest = Digest::SHA1.new()
	buffer = String.new()
	opened = false
	
	fp = object
	
	# handle Pathname objects as strings
	if(object.kind_of?(Pathname))
		object = object.realpath.to_s()
	end
	
	if(!object.respond_to?(:read))
		filename = object.to_s()
		fp = File.open(filename, File::RDONLY)
		opened = true
		stats = File.stat(filename)
		checksums.uid = stats.uid
		checksums.gid = stats.gid
		checksums.permissions = stats.mode.to_s(8)
	else
		checksums.uid = nil
		checksums.gid = nil
		checksums.permissions = nil
	end

	begin
		while(fp.read(2048, buffer) != nil)
			md5digest << buffer
			shadigest << buffer
		end
	ensure
		# close it if we opened it
		if(opened)
			fp.close()
		end
	end

	checksums.md5 = md5digest.hexdigest()
	checksums.sha1 = shadigest.hexdigest()
	checksums.timestamp = Time.now()
	
	return(checksums)
end

Instance Method Details

#check(basedir, options = {}) ⇒ Object

If the files found by calling Cfruby::FileFind.find on basedir are in the database, and matches the listed checksums then nothing is done. If they are not in the database they are added. If a file is in the database and the checksum is different an appropriate Exception (ChecksumMatchError, ChecksumPermissionError, or ChecksumOwnershipError) is raised.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/libcfruby/checksum.rb', line 186

def check(basedir, options = {})
	Cfruby.controller.attempt("Checking checksums of \"#{basedir}\" against checksum database \"#{databasefile}\"") {
		FileFind.find(basedir, options) { |filename|
			filename = filename.realpath()
		
			# get the current checksums
			checksums = Checksum.get_checksums(filename)
		
			if(@database.has_key?(filename))
				if(@database[filename].md5 != checksums.md5 or @database[filename].sha1 != checksums.sha1)
					raise(ChecksumMatchError, "Checksums do not match previously recorded value for #{filename}")
				elsif(@database[filename].permissions != checksums.permissions)
					raise(ChecksumPermissionError, "Permsisions to not match previously recorded permissions for #{filename}")
				elsif(@database[filename].uid != checksums.uid or @database[filename].gid != checksums.gid)
					raise(ChecksumOwnershipError, "user and/or group do not match previosuly recorded values for #{filename}")
				end
			else
				Cfruby.controller.attempt("adding \"#{filename}\" to checksum database", 'destructive', 'nonreversible') {
					@database[filename] = checksums
					save_database()
				}
			end
		}
	}
end

#check?(basedir, options = {}) ⇒ Boolean

Calls check and returns true or false (instead of throwing an Exception) if a checksum fails

Returns:

  • (Boolean)


169
170
171
172
173
174
175
176
177
178
# File 'lib/libcfruby/checksum.rb', line 169

def check?(basedir, options={})
	begin
		check(basedir, options)
	rescue ChecksumError
		Cfruby.controller.inform('warn', $!.to_s())
		return(false)
	end
	
	return(true)
end

#check_allObject

Checks every file currently in the database



214
215
216
217
218
# File 'lib/libcfruby/checksum.rb', line 214

def check_all()
	@database.each_key() { |filename|
		check(filename)
	}
end

#check_all?Boolean

Calls check_all and returns true or false instead of throwing an Exception if a checksum fails

Returns:

  • (Boolean)


222
223
224
225
226
227
228
229
230
# File 'lib/libcfruby/checksum.rb', line 222

def check_all?()
	begin
		check_all()
	rescue ChecksumError
		return(false)
	end

	return(true)
end

#update(basedir, options = {}) ⇒ Object

Updates the database checksums for a given set of files



242
243
244
245
246
247
248
249
250
251
252
# File 'lib/libcfruby/checksum.rb', line 242

def update(basedir, options = {})
	Cfruby.controller.attempt("Updating checksum database \"#{@databasefile}\" with \"#{basedir}\"", 'nonreversible', 'destructive') {
		FileFind.find(basedir, options) { |filename|
			filename = filename.realpath()
			Cfruby.controller.inform('info', "updating checksum for \"#{filename}\"")
			@database[filename] = Checksum.get_checksums(filename)
		}
	
		save_database()
	}
end

#update_allObject

Updates the checksums of every file in the database



234
235
236
237
238
# File 'lib/libcfruby/checksum.rb', line 234

def update_all()
	@database.each_key() { |filename|
		update(filename)
	}
end