# sysdeps common # # Written in 2020 by Francesco Palumbo phranz@subfc.net # # To the extent possible under law, the author(s) have dedicated # all copyright and related and neighboring rights to this software # to the public domain worldwide. # This software is distributed without any warranty. # You should have received a copy of the CC0 Public Domain Dedication # along with this software. # If not, see . LDCONFPATH = '/etc/ld.so.conf' DEPMARK = 'NEEDED'.freeze ELF = 'ELF'.freeze SYM = 'symbolic'.freeze LINK = 'link'.freeze EMPTY = ''.freeze readlink_absolute = ->(path) { curdir = Dir.getwd Dir.chdir(File.dirname path) abs = File.absolute_path(File.readlink(File.basename path)) Dir.chdir curdir abs } get_syslibs = ->(paths) { ldpaths = (File.read(LDCONFPATH).split + paths).uniq.join ' ' sopat = /\.so\.?/ %x(find #{ldpaths} \\( -type f -o -type l \\) 2>/dev/null) .split .select { |l| l[sopat] } .map { |l| File.ftype(l) == LINK ? [l, readlink_absolute(l)] : l } .flatten } get_program_dependencies = ->(prg) { return prg if not prg prgpath = nil prgpath = File.exist?(prg) ? prg : %x(which #{prg} 2>/dev/null).chomp return nil unless File.exist?(prgpath) prgpath = readlink_absolute(prgpath) if File.ftype(prgpath) == LINK return nil if %x(file #{prgpath}).split[1] != ELF deppat = /\s+#{DEPMARK}\s+/ %x(objdump -p #{prgpath}) .split("\n") .select { |r| r.include? DEPMARK } .map { |r| r.gsub(deppat, EMPTY) }} get_programs_dependencies = ->() { prog_deps = {} deppat = /\s+#{DEPMARK}\s+/ paths = ENV['PATH'].split(':').join(' ') IO.popen("find #{paths} -type f -executable") { |find_io| find_io.each_with_object({}) { |l, o| next if %x{file #{l}}.split[1] != ELF o[l.chomp] = %x{objdump -p #{l}} .split("\n") .select { |r| r.include? DEPMARK } .map { |r| r.gsub(deppat, EMPTY) }}}} get_libraries_dependencies = ->(syslibs) { deppat = /\s+#{DEPMARK}\s+/ syslibs.each_with_object({}) { |sl, o| sl = readlink_absolute(sl) if File.ftype(sl) == LINK next if %x{file #{sl}}.split[1] != ELF o[sl.chomp] = %x{objdump -p #{sl}} .split("\n") .select { |r| r.include? DEPMARK } .map { |r| r.gsub(deppat, EMPTY) }}} get_programs_by_deps = ->(prog_deps, pattern) { rex = Regexp.new pattern, Regexp::IGNORECASE prog_deps.each_with_object({}) { |(prog, deps), o| deps.each { |d| if d[rex] lms = $~.string o[lms] ? o[lms] << prog : o[lms] = [prog] end }}} get_total_deps = ->(deps) { deps.values.flatten.uniq } get_missing_libs = ->(syslibs, libs) { syslibs = syslibs.map { |l| File.basename l } libs.select { |l| !syslibs.include? l }} group_failed_by_lib = ->(deps, missing) { missing.each_with_object({}) { |l, o| o[l] = [] deps.each { |prg, libs| o[l] << prg if libs.include? l }}} SysDeps = Module.new { local_variables.each { |f| define_method(f, eval(f.to_s)) }}