Class: Hackmac::Kext

Inherits:
Object
  • Object
show all
Includes:
Plist, Tins::StringVersion
Defined in:
lib/hackmac/kext.rb

Overview

A class that represents a kernel extension (kext) and provides access to its metadata and remote version information

The Kext class encapsulates the functionality for working with macOS kernel extensions, including loading their Info.plist files, extracting metadata such as identifiers and versions, and determining whether newer versions are available from remote sources

Examples:

kext = Hackmac::Kext.new(path: '/path/to/MyKext.kext')
# Provides access to kext metadata through method calls

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Plist

#as_hash, #each, #method_missing, #plist, #to_json

Constructor Details

#initialize(path:, config: nil) ⇒ Kext

The initialize method sets up a Kext instance by loading and parsing its Info.plist file

This method takes a path to a kext directory and optionally a configuration object, then reads the Info.plist file within the kext’s Contents directory to extract metadata about the kernel extension. The plist data is parsed and stored for later access through dynamic method calls.

Parameters:

  • path (String)

    the filesystem path to the kext directory

  • config (Object, nil) (defaults to: nil)

    optional configuration object that may provide source information



33
34
35
36
37
38
# File 'lib/hackmac/kext.rb', line 33

def initialize(path:, config: nil)
  @path   = path
  info    = Pathname.new(@path) + 'Contents/Info.plist'
  @plist  = File.open(info, encoding: 'UTF-8') { |f| ::Plist.parse_xml(f) }
  @config = config
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Hackmac::Plist

Instance Attribute Details

#pathString (readonly)

The path reader method provides access to the path attribute that was set during object initialization.

This method returns the value of the path instance variable, which typically represents the filesystem path associated with the object.

Returns:

  • (String)

    the path value stored in the instance variable



47
48
49
# File 'lib/hackmac/kext.rb', line 47

def path
  @path
end

Instance Method Details

#identifierString?

The identifier method retrieves the bundle identifier from the kext’s Info.plist file

This method accesses the CFBundleIdentifier key from the parsed plist data of a kernel extension, providing the unique identifier that distinguishes this particular kext within the system

Returns:

  • (String)

    the bundle identifier of the kernel extension

  • (nil)

    returns nil if the CFBundleIdentifier key is not present in the plist



58
59
60
# File 'lib/hackmac/kext.rb', line 58

def identifier
  CFBundleIdentifier()
end

#inspectString

The inspect method returns a string representation of the object that includes its class name and string value

Returns:

  • (String)

    a formatted string containing the object’s class name and its string representation



149
150
151
# File 'lib/hackmac/kext.rb', line 149

def inspect
  "#<#{self.class}: #{to_s}>"
end

#nameString?

The name method retrieves the display name for the kernel extension

This method attempts to return the CFBundleName value from the kext’s Info.plist file and falls back to using the basename of the bundle identifier if that value is not present

Returns:

  • (String)

    the human-readable name of the kernel extension

  • (nil)

    returns nil if neither CFBundleName nor identifier is available



70
71
72
# File 'lib/hackmac/kext.rb', line 70

def name
  CFBundleName() || File.basename(identifier)
end

#remote_kextHackmac::GithubSource, ...

The remote_kext method retrieves or creates a remote source object for a kext

This method attempts to return an existing cached remote kext source or constructs a new one based on the configuration source for this kext. It supports both GitHub-based sources and direct URL downloads, determining the appropriate source type from the configuration and creating the corresponding source object.

Returns:



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/hackmac/kext.rb', line 108

def remote_kext
  return @remote_kext if @remote_kext
  if @config
    source = @config.kext.sources[name] or return
    case
    when github = source&.github?
      auth = [ @config.github.user, @config.github.access_token ].compact
      auth.empty? and auth = nil
      suffix =
        case debug = source.debug?
        when true       then 'DEBUG'
        when false      then 'RELEASE'
        when nil        then nil
        end
      @remote_kext = Hackmac::GithubSource.new(github, auth: auth, suffix: suffix)
    when download = source&.download
      @remote_kext = Hackmac::URLDownload.new(download.name, download.version, download.url)
    end
  end
end

#remote_versionTins::StringVersion, ...

The remote_version method retrieves the version identifier from the remote kext source

This method accesses the cached remote kext source object and returns its version information if available. It uses the safe navigation operator to avoid errors when the remote kext source has not been initialized or does not have version data

Returns:

  • (Tins::StringVersion, String, nil)

    the version object or string from the remote source, or nil if no remote source is available or has no version information



140
141
142
# File 'lib/hackmac/kext.rb', line 140

def remote_version
  remote_kext&.version
end

#to_sString

The to_s method returns a string representation of the object by combining its name and version attributes into a single space-separated string.

Returns:

  • (String)

    a formatted string containing the name and version separated by a space



158
159
160
# File 'lib/hackmac/kext.rb', line 158

def to_s
  "#{name} #{version}"
end

#versionTins::StringVersion, ...

The version method retrieves and caches the version identifier from the kext’s Info.plist file

This method attempts to extract the CFBundleShortVersionString value from the parsed plist data and convert it into a Version object for proper semantic versioning comparison. If the version string is not a valid semantic version, it stores the raw string instead.

Returns:

  • (Tins::StringVersion, String, nil)

    the version object or string if found, nil otherwise



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/hackmac/kext.rb', line 83

def version
  unless @version
    if version = CFBundleShortVersionString()
      begin
        @version = Version.new(version)
      rescue ArgumentError
        @version = version
      end
    end
  end
  @version
end