Class: Omnizip::Formats::Rpm::Writer

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/formats/rpm/writer.rb

Overview

RPM package writer

Creates RPM packages with binary payload (CPIO archive). Supports multiple compression algorithms: gzip, bzip2, xz, zstd.

Examples:

Create an RPM package with gzip compression (default)

writer = Rpm::Writer.new(
  name: "myapp",
  version: "1.0.0",
  release: "1",
  arch: "x86_64"
)
writer.add_file("/usr/bin/myapp", content, mode: 0755)
writer.write("myapp-1.0.0-1.x86_64.rpm")

Create an RPM with xz compression

writer = Rpm::Writer.new(
  name: "myapp",
  version: "1.0.0",
  release: "1",
  compression: :xz
)

Constant Summary collapse

COMPRESSION_INFO =

Supported compression types and their properties

{
  gzip: { name: "gzip", flags: "9" },
  bzip2: { name: "bzip2", flags: "9" },
  xz: { name: "xz", flags: "9" },
  zstd: { name: "zstd", flags: "19" },
  none: { name: nil, flags: nil },
}.freeze
ARCHITECTURES =

Architecture mapping

{
  "noarch" => 0,
  "i386" => 1,
  "i486" => 2,
  "i586" => 3,
  "i686" => 4,
  "x86_64" => 9,
  "amd64" => 9,
  "ia64" => 11,
  "ppc" => 5,
  "ppc64" => 16,
  "sparc" => 6,
  "sparc64" => 7,
  "alpha" => 8,
  "s390" => 14,
  "s390x" => 15,
  "arm" => 12,
  "aarch64" => 19,
}.freeze
TAG_NAMES =

Tag ID mapping (reverse of Tag::TAG_IDS)

{
  # Header tags
  name: 1000,
  version: 1001,
  release: 1002,
  epoch: 1003,
  summary: 1004,
  description: 1005,
  buildtime: 1006,
  buildhost: 1007,
  size: 1009,
  distribution: 1010,
  vendor: 1011,
  license: 1014,
  packager: 1015,
  group: 1016,
  url: 1020,
  os: 1021,
  arch: 1022,
  prein: 1023,
  postin: 1024,
  preun: 1025,
  postun: 1026,
  filesizes: 1028,
  filemodes: 1030,
  fileuids: 1031,
  filegids: 1032,
  filemtimes: 1034,
  filedigests: 1035,
  filelinktos: 1036,
  fileflags: 1037,
  fileusername: 1039,
  filegroupname: 1040,
  archivesize: 1046,
  rpmversion: 1064,
  dirindexes: 1116,
  basenames: 1117,
  dirnames: 1118,
  payloadformat: 1124,
  payloadcompressor: 1125,
  payloadflags: 1126,

  # Signature tags
  sigsize: 257,
  sha1header: 269,
}.freeze

Constants included from Constants

Constants::FILE_CONFIG, Constants::FILE_DOC, Constants::FILE_LICENSE, Constants::FILE_README, Constants::FLAG_EQUAL, Constants::FLAG_GREATER, Constants::FLAG_LESS, Constants::HEADER_HEADER_SIZE, Constants::HEADER_MAGIC, Constants::HEADER_SIGNED_TYPE, Constants::LEAD_MAGIC, Constants::LEAD_SIZE, Constants::PACKAGE_BINARY, Constants::PACKAGE_SOURCE, Constants::TAG_ENTRY_SIZE, Constants::TYPE_BINARY, Constants::TYPE_CHAR, Constants::TYPE_I18NSTRING, Constants::TYPE_INT16, Constants::TYPE_INT32, Constants::TYPE_INT64, Constants::TYPE_INT8, Constants::TYPE_NULL, Constants::TYPE_STRING, Constants::TYPE_STRING_ARRAY

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, version:, release:, arch: "noarch", epoch: nil, compression: :gzip, **metadata) ⇒ Writer

Initialize RPM writer

Parameters:

  • name (String)

    Package name

  • version (String)

    Package version

  • release (String)

    Package release

  • arch (String) (defaults to: "noarch")

    Architecture (default: "noarch")

  • epoch (String, nil) (defaults to: nil)

    Optional epoch

  • compression (Symbol) (defaults to: :gzip)

    Compression type (:gzip, :bzip2, :xz, :zstd, :none)

  • metadata (Hash)

    Additional metadata



148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/omnizip/formats/rpm/writer.rb', line 148

def initialize(name:, version:, release:, arch: "noarch", epoch: nil,
               compression: :gzip, **)
  @name = name
  @version = version
  @release = release
  @arch = arch
  @epoch = epoch
  @compression = validate_compression(compression)
  @metadata = 
  @files = []
  @directories = []
end

Instance Attribute Details

#archString (readonly)

Returns Architecture.

Returns:

  • (String)

    Architecture



128
129
130
# File 'lib/omnizip/formats/rpm/writer.rb', line 128

def arch
  @arch
end

#compressionSymbol (readonly)

Returns Compression type.

Returns:

  • (Symbol)

    Compression type



131
132
133
# File 'lib/omnizip/formats/rpm/writer.rb', line 131

def compression
  @compression
end

#epochString? (readonly)

Returns Package epoch.

Returns:

  • (String, nil)

    Package epoch



125
126
127
# File 'lib/omnizip/formats/rpm/writer.rb', line 125

def epoch
  @epoch
end

#filesHash<String, String> (readonly)

Returns File contents.

Returns:

  • (Hash<String, String>)

    File contents



134
135
136
# File 'lib/omnizip/formats/rpm/writer.rb', line 134

def files
  @files
end

#metadataHash (readonly)

Returns Additional metadata.

Returns:

  • (Hash)

    Additional metadata



137
138
139
# File 'lib/omnizip/formats/rpm/writer.rb', line 137

def 
  @metadata
end

#nameString (readonly)

Returns Package name.

Returns:

  • (String)

    Package name



116
117
118
# File 'lib/omnizip/formats/rpm/writer.rb', line 116

def name
  @name
end

#releaseString (readonly)

Returns Package release.

Returns:

  • (String)

    Package release



122
123
124
# File 'lib/omnizip/formats/rpm/writer.rb', line 122

def release
  @release
end

#versionString (readonly)

Returns Package version.

Returns:

  • (String)

    Package version



119
120
121
# File 'lib/omnizip/formats/rpm/writer.rb', line 119

def version
  @version
end

Instance Method Details

#add_directory(path, mode: 0o755, owner: "root", group: "root") ⇒ Object

Add directory to package

Parameters:

  • path (String)

    Directory path in package (absolute path)

  • mode (Integer) (defaults to: 0o755)

    Directory permissions (default: 0755)

  • owner (String) (defaults to: "root")

    Directory owner (default: "root")

  • group (String) (defaults to: "root")

    Directory group (default: "root")



209
210
211
212
213
214
215
216
# File 'lib/omnizip/formats/rpm/writer.rb', line 209

def add_directory(path, mode: 0o755, owner: "root", group: "root")
  @directories << {
    path: path,
    mode: mode,
    owner: owner,
    group: group,
  }
end

#add_file(path, content, mode: 0o644, owner: "root", group: "root", mtime: nil) ⇒ Object

Add file to package

Parameters:

  • path (String)

    File path in package (absolute path)

  • content (String)

    File content

  • mode (Integer) (defaults to: 0o644)

    File permissions (default: 0644)

  • owner (String) (defaults to: "root")

    File owner (default: "root")

  • group (String) (defaults to: "root")

    File group (default: "root")

  • mtime (Integer) (defaults to: nil)

    Modification time (default: now)



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/omnizip/formats/rpm/writer.rb', line 191

def add_file(path, content, mode: 0o644, owner: "root", group: "root",
mtime: nil)
  @files << {
    path: path,
    content: content,
    mode: mode,
    owner: owner,
    group: group,
    mtime: mtime || Time.now.to_i,
  }
end

#compression_infoHash

Get compression info

Returns:

  • (Hash)

    Compression info with :name and :flags



179
180
181
# File 'lib/omnizip/formats/rpm/writer.rb', line 179

def compression_info
  COMPRESSION_INFO[@compression]
end

#validate_compression(comp) ⇒ Symbol

Validate compression type

Parameters:

  • comp (Symbol)

    Compression type

Returns:

  • (Symbol)

    Validated compression type

Raises:

  • (ArgumentError)

    If compression type is invalid



166
167
168
169
170
171
172
173
174
# File 'lib/omnizip/formats/rpm/writer.rb', line 166

def validate_compression(comp)
  return :gzip unless comp

  unless COMPRESSION_INFO.key?(comp)
    raise ArgumentError, "Unsupported compression: #{comp}. " \
                         "Supported: #{COMPRESSION_INFO.keys.join(', ')}"
  end
  comp
end

#write(output_path) ⇒ String

Write RPM package to file

Parameters:

  • output_path (String)

    Output file path

Returns:

  • (String)

    Output path



222
223
224
225
226
227
# File 'lib/omnizip/formats/rpm/writer.rb', line 222

def write(output_path)
  File.open(output_path, "wb") do |io|
    write_to_io(io)
  end
  output_path
end

#write_to_io(io) ⇒ Object

Write RPM package to IO

Parameters:

  • io (IO)

    Output IO



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/omnizip/formats/rpm/writer.rb', line 232

def write_to_io(io)
  # Build payload (compressed CPIO)
  payload_io = StringIO.new("".b)
  cpio_data = build_cpio_payload
  compress_payload(cpio_data, payload_io)
  payload_io.rewind
  payload_data = payload_io.read

  # Build headers
  main_header = build_main_header(payload_data.bytesize)
  sig_header = build_signature_header(main_header.bytesize,
                                      payload_data.bytesize)

  # Build lead
  lead = build_lead

  # Write RPM in order
  io.write(lead)
  io.write(sig_header)
  io.write(main_header)
  io.write(payload_data)
end