From 8d841b605aa29add72575853ff5d7a2fe792ef92 Mon Sep 17 00:00:00 2001 From: franz Date: Sun, 4 Oct 2009 16:35:41 +0200 Subject: [PATCH] add some safety checks to gdbm conversion, plus initial yaml conversion (not working yet) --- lib/rbot/dbhash.rb | 10 ++--- lib/rbot/registry.rb | 98 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/lib/rbot/dbhash.rb b/lib/rbot/dbhash.rb index b7c8e23e..2da64f6c 100644 --- a/lib/rbot/dbhash.rb +++ b/lib/rbot/dbhash.rb @@ -58,24 +58,24 @@ module Irc end def [](key) - @db[key.downcase] + @db[key.to_s.downcase] end def []=(key, val) - @db[key.downcase] = val + @db[key.to_s.downcase] = val end alias :store :[]= def delete(key) - @db.delete(key.downcase) + @db.delete(key.to_s.downcase) end def fetch(key, *args) - @db.fetch(key.downcase, *args) + @db.fetch(key.to_s.downcase, *args) end def has_key?(key) - @db.has_key?(key.downcase) + @db.has_key?(key.to_s.downcase) end alias :key? :has_key? diff --git a/lib/rbot/registry.rb b/lib/rbot/registry.rb index bf842ef1..5093e5d9 100644 --- a/lib/rbot/registry.rb +++ b/lib/rbot/registry.rb @@ -13,6 +13,9 @@ class Bot 0x00042253,0x53220400, #BDB_Queue 0x00040988,0x88090400] #BDB_Log + GDBM_MAGIC_NUMBERS = + [0x13579ace, 0xce9a5713, "GDBM"] + def is_bdb?(file) f = File.open(file, 'r') magic = f.read(4).unpack('L')[0] @@ -21,7 +24,9 @@ class Bot magic = f.read(4).unpack('L')[0] end f.close - BDB_MAGIC_NUMBERS.include?(magic) ? true : false + result = BDB_MAGIC_NUMBERS.include?(magic) ? true : false + debug "File #{file} is bdb: #{result}" + result end def require_bdb @@ -29,16 +34,17 @@ class Bot log 'Trying to load bdb, since some of your config files are in bdb format.' begin require 'bdb' - require 'rbot/bdb_cibtree' + require 'rbot/bdb_cibtree' rescue LoadError fatal "rbot couldn't load the bdb module, perhaps you need to install it? try: http://www.ruby-lang.org/en/raa-list.rhtml?name=bdb" - exit 1 + exit 1 rescue Exception => e fatal "rbot couldn't load the bdb module: #{e.pretty_inspect}" - exit 1 + exit 1 end end + def initialize(bot) @bot = bot upgrade_data @@ -104,23 +110,91 @@ class Bot end def upgrade_data3 - #move away from bdb - newdir = @bot.path 'registry' - Dir.glob("#{newdir}/**/*").each { |file| - if File.file? file and is_bdb? file + #move away from bdb to gdbm + regdir = @bot.path 'registry' + Dir.glob("#{regdir}/**/*.db").each { |file| + unless File.file? file and File.readable? file + warning "File #{file} is not a regular file or is not readable, skipping" + next + end + unless is_bdb? file + debug "File #{file} is not bdb, skipping" + next + end + begin require_bdb - File.rename file, file+'_old' - old = BDB::CIBtree.open(file+'_old', nil, 'r+', 0600) + save_file = file+'_bdb_saved' + debug "renaming #{file} to #{save_file}" + File.rename file, save_file + raise IOError, "#{file} still exists" if File.exists? file + old = BDB::CIBtree.open(save_file, nil, 'r+', 0600) new = DBHash.create_db file old.each {|k,v| new[k] = v } - old.close - new.close + rescue IOError, SystemCallError => e + fatal "Fatal error: #{e}, exiting" + exit 1 + rescue => e + fatal "Other error: #{e}" + exit 1 + ensure + old.close rescue nil + new.close rescue nil end } end + def try_unmarshaling(file) + db = DBHash.open_db file + return if db.empty? + key = db.keys[0] + val = db[key] + db.close + begin + ruby_val = Marshal.restore(val) + rescue ArgumentError => e + fatal "This ruby interpreter cannot read values stored in registry dbs. Please start it the ruby which created the files." + exit 1 + rescue => e + fatal "Other error: #{e}" + exit 1 + end + end + + def upgrade_data4 + #move away from Marshal to YAML + require 'yaml' + regdir = @bot.path 'registry' + Dir.glob("#{regdir}/**/*.db").each { |file| + unless File.file? file and File.readable? file + warning "File #{file} is not a regular file or is not readable, skipping" + next + end + try_unmarshaling(file) + begin + save_file = file+'_gdbm_saved' + debug "renaming #{file} to #{save_file}" + File.rename file, save_file + raise IOError, "#{file} still exists" if File.exists? file + old = DBHash.open_db save_file + new = DBHash.create_db file + old.each {|k,v| + ruby_val = Marshal.restore(v) + new[k] = ruby_val.to_yaml + } + rescue IOError, SystemCallError => e + fatal "Fatal error: #{e}, exiting" + exit 1 + rescue => e + fatal "Other error: #{e}" + exit 1 + ensure + old.close rescue nil + new.close rescue nil + end + } + end # This class provides persistent storage for plugins via a hash interface. # The default mode is an object store, so you can store ruby objects and -- 2.32.0.93.g670b81a890