module OCI8::Util
def self.check_load_error(exc)
def self.check_load_error(exc) check_os_specific_load_error(exc) case exc.message when /^OCI Library Initialization Error/ # TODO end end
def self.check_os_specific_load_error(exc)
def self.check_os_specific_load_error(exc) case exc.message when /^OCI\.DLL: 193\(/, /^193: / # "OCI.DLL: 193(%1 is not a valid Win32 application.)" in English check_win32_pe_arch(exc.message.split(' - ')[1], "ruby-oci8") dll_load_path_list.each do |path| check_win32_pe_arch(File.join(path, '\OCI.DLL'), "Oracle client") end when /^OCI.DLL: 126\(/, /^126: / # "OCI.DLL: 126(The specified module could not be found.)" in English oci_dll_files = dll_load_path_list.inject([]) do |files, path| file = File.join(path, '\OCI.DLL') files << file if File.exist?(file) files end if oci_dll_files.empty? raise LoadError, "Cannot find OCI.DLL in PATH." end if oci_dll_files.none? {|file| open(file, 'rb') {true} rescue false} raise LoadError, "OCI.DLL in PATH isn't readable." end first_error = nil oci_dll_files.each do |file| begin check_win32_pe_arch(file, "Oracle client") valid_arch = true rescue LoadError first_error ||= $! valid_arch = false end if valid_arch handle = LoadLibraryExA(file, nil, DONT_RESOLVE_DLL_REFERENCES) unless handle.null? FreeLibrary(handle) raise LoadError, <<EOS find DLLs depended by #{file}. tp://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-instant-client.md#Windows end break end end raise first_error if first_error end end # self.check_os_specific_load_error
def self.check_os_specific_load_error(exc)
def self.check_os_specific_load_error(exc) case exc.message when /^libaio\.so\.1:/ # "libaio.so.1: cannot open shared object file: No such file or directory" in English install_cmd = if File.executable? '/usr/bin/apt-get' 'apt-get install libaio1' elsif File.executable? '/usr/bin/yum' 'yum install libaio' end if install_cmd raise LoadError, "You need to install libaio.so.1. Run '#{install_cmd}'." else raise LoadError, "You need to install libaio.so.1." end end end # self.check_os_specific_load_error
def self.check_os_specific_load_error(exc)
def self.check_os_specific_load_error(exc) end
def self.check_win32_pe_arch(filename, package)
def self.check_win32_pe_arch(filename, package) open(filename, 'rb') do |f| # DOS header. if f.read(2) == 'MZ' f.seek(60, IO::SEEK_SET) pe_offset = f.read(4).unpack('V')[0] f.seek(pe_offset) # PE header. if f.read(4) == "PE\000\000" case f.read(2).unpack('v')[0] when 0x8664 if [nil].pack('P').size == 4 raise LoadError, "\"#{filename}\" is x64 DLL. Use 32-bit #{package} instead." end return true when 0x014c if [nil].pack('P').size == 8 raise LoadError, "\"#{filename}\" is 32-bit DLL. Use x64 #{package} instead." end return true end end end raise LoadError, "\"#{filename}\" is not a valid Win32 application." end nil rescue nil end # self.check_win32_pe_arch
def self.dll_load_path_list
def self.dll_load_path_list buf = "\0" * MAX_PATH paths = [] paths << buf[0, GetModuleFileNameA(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '') paths << buf[0, GetSystemDirectoryA(buf, MAX_PATH)].force_encoding("locale") paths << buf[0, GetWindowsDirectoryA(buf, MAX_PATH)].force_encoding("locale") paths << "." paths + (ENV['PATH'].split(';').reject {|path| path.empty?}) end # self.dll_load_path_list