Class: Yast::SharedLibInfo

Inherits:
Object
  • Object
show all
Defined in:
library/system/src/lib/yast2/shared_lib_info.rb

Overview

Class to get information about shared libraries used by a process (by default the current process) from its /proc/self/maps file.

You can also get information for a different process by specifying its /proc/$pid/maps file.

For testing, a fixed file can be used.

The information stored in this class is only a snapshot in the life time of the process. As new shared libs are loaded (e.g. plug-ins are loaded with dlopen()), this information may become outdated. In that case, simply let the old instance go out of scope and create a new one.

More information: https://github.com/yast/yast-yast2/pull/1194

Direct Known Subclasses

UIPluginInfo

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(maps_file = "/proc/self/maps") ⇒ SharedLibInfo

Constructor.

Parameters:

  • maps_file (String) (defaults to: "/proc/self/maps")

    name of the maps file to use



39
40
41
42
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 39

def initialize(maps_file = "/proc/self/maps")
  clear
  read(maps_file)
end

Instance Attribute Details

#shared_libsArray<String> (readonly)

Returns Complete paths of the shared libs.

Returns:

  • (Array<String>)

    Complete paths of the shared libs



34
35
36
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 34

def shared_libs
  @shared_libs
end

Class Method Details

.build_lib_name(basename, so_number) ⇒ String

Counterpart to split_lib_name: Build a library name from its base name and its SO number.

Example: "libscr", "3.0.0" -> "libscr.so.3.0.0" "libc-2.33", nil -> "libc-2.33.so"

Parameters:

  • basename (String)

    lib base name without path and SO number

  • so_number (String)

    lib SO number or nil or empty

Returns:



119
120
121
122
123
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 119

def self.build_lib_name(basename, so_number)
  lib_name = basename + ".so"
  lib_name += "." + so_number unless so_number.nil? || so_number.empty?
  lib_name
end

.lib_basename(lib) ⇒ String

Return the library basename of a shared lib. Unlike File.basename(), this also cuts off the SO number.

Example: "/usr/lib64/libscr.so.3.0.0" -> "libscr" "/usr/lib64/libc-2.33.so" -> "libc-2.33"

Parameters:

  • lib (String)

    full name (with or without path) of a shared lib

Returns:

  • (String)

    the name of the lib without path and without .so number



54
55
56
57
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 54

def self.lib_basename(lib)
  (name, _so_number) = split_lib_name(lib)
  name
end

.so_major(lib) ⇒ String?

Return the SO major number of a shared lib (with or without a full path)

Example: "/usr/lib64/libscr.so.3.0.0" -> "3" "/usr/lib64/libc-2.33.so" -> nil

Parameters:

  • lib (String)

    full name (with or without path) of a shared lib

Returns:

  • (String, nil)

    the major .so of the lib ("3")



84
85
86
87
88
89
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 84

def self.so_major(lib)
  so = so_number(lib)
  return nil if so.nil?

  so.split(".").first
end

.so_number(lib) ⇒ String?

Return the so number of a shared lib (with or without a full path).

Example: "/usr/lib64/libscr.so.3.0.0" -> "3.0.0" "/usr/lib64/libc-2.33.so" -> nil

Parameters:

  • lib (String)

    full name (with or without path) of a shared lib

Returns:

  • (String, nil)

    the .so number part of the lib ("3.0.0")



68
69
70
71
72
73
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 68

def self.so_number(lib)
  # There might be only one component if there is no SO number,
  # so we can't simply use .last: We want to return nil in that case
  (_name, so_number) = split_lib_name(lib)
  so_number
end

.split_lib_name(lib) ⇒ Array<String>?

Split a library name (with or without a full path) up into its base name and its SO number and return both.

Example: "/usr/lib64/libscr.so.3.0.0" -> ["libscr", "3.0.0"] "/usr/lib64/libc-2.33.so" -> ["libc-2.33", nil]

Parameters:

  • lib (String)

    full name (with or without path) of a shared lib

Returns:

  • (Array<String>, nil)

    lib name split into name and so number



101
102
103
104
105
106
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 101

def self.split_lib_name(lib)
  return nil if lib.nil?

  full_name = File.basename(lib) # "libscr.so.3.0.0"
  full_name.split(/\.so\.?/) # ["libscr", "3.0.0"]
end

Instance Method Details

#clearObject (protected)

Clear all previous content.



128
129
130
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 128

def clear
  @shared_libs = []
end

#parse_maps_line(line) ⇒ String? (protected)

Parse one entry of /proc/self/maps and add an entry to @shared_libs if applicable.

Parameters:

  • line (String)

    one line of /proc/self/maps

Returns:

  • (String, nil)

    the shared lib with path on this line



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 149

def parse_maps_line(line)
  # Sample lines:
  #
  # 7fb22485f000-7fb22486f000 r--p 000f0000 08:02 132839    /usr/lib64/yui/libyui-qt.so.15.0.0
  # 7fb22486f000-7fb224872000 rw-p 00100000 08:02 132839    /usr/lib64/yui/libyui-qt.so.15.0.0
  # 7fb2248a2000-7fb2248d8000 r--p 00000000 08:02 1054948   /usr/lib64/libyui.so.15.0.0
  # 7f8cadbc5000-7f8cadbc9000 rw-p 00000000 00:00 0
  # 7fffe6181000-7fffe6183000 r-xp 00000000 00:00 0         [vdso]
  #
  # See also
  # https://www.kernel.org/doc/html/latest/filesystems/proc.html
  #
  line.strip!
  return nil if line.empty? || line.start_with?("#")

  path = line.split[5]
  return nil if path.nil?

  @shared_libs << path if shared_lib?(path)
  path
end

#read(maps_file = "/proc/self/maps") ⇒ Object (protected)

Read a maps file formatted like /proc/self/maps.

Parameters:

  • maps_file (String) (defaults to: "/proc/self/maps")

    name of the maps file to use



136
137
138
139
140
141
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 136

def read(maps_file = "/proc/self/maps")
  return if maps_file.nil? || maps_file.empty?

  File.open(maps_file).each { |line| parse_maps_line(line) }
  @shared_libs.sort!.uniq!
end

#shared_lib?(path) ⇒ Boolean (protected)

Check if a path is a shared lib.

Parameters:

  • lib (String)

    full name (with path) of a shared lib

Returns:

  • (Boolean)

    true if it is a shared lib, false if not



176
177
178
# File 'library/system/src/lib/yast2/shared_lib_info.rb', line 176

def shared_lib?(path)
  path =~ /\.so/
end