Class: Omnizip::Formats::Cpio::Writer

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

Overview

CPIO archive writer

Creates CPIO archives in newc, CRC, or ODC format. Ported from libarchive's archive_write_set_format_cpio_newc.c

Examples:

Create CPIO archive

writer = Cpio::Writer.new('archive.cpio')
writer.add_file('file.txt')
writer.add_directory('dir/')
writer.write

With CRC format

writer = Cpio::Writer.new('archive.cpio', format: :crc)
writer.add_directory('initramfs/')
writer.write

Constant Summary

Constants included from Constants

Constants::MAGIC_BINARY, Constants::MAGIC_CRC, Constants::MAGIC_NEWC, Constants::MAGIC_ODC, Constants::NEWC_ALIGNMENT, Constants::NEWC_HEADER_SIZE, Constants::S_IFBLK, Constants::S_IFCHR, Constants::S_IFDIR, Constants::S_IFIFO, Constants::S_IFLNK, Constants::S_IFMT, Constants::S_IFREG, Constants::S_IFSOCK, Constants::S_IRGRP, Constants::S_IROTH, Constants::S_IRUSR, Constants::S_IRWXG, Constants::S_IRWXO, Constants::S_IRWXU, Constants::S_ISGID, Constants::S_ISUID, Constants::S_ISVTX, Constants::S_IWGRP, Constants::S_IWOTH, Constants::S_IWUSR, Constants::S_IXGRP, Constants::S_IXOTH, Constants::S_IXUSR, Constants::TRAILER_NAME

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output_path, format: :newc) ⇒ Writer

Initialize CPIO writer

Parameters:

  • output_path (String)

    Output CPIO file path

  • format (Symbol) (defaults to: :newc)

    CPIO format (:newc, :crc, :odc)



39
40
41
42
43
44
# File 'lib/omnizip/formats/cpio/writer.rb', line 39

def initialize(output_path, format: :newc)
  @output_path = output_path
  @format = validate_format(format)
  @entries = []
  @inode_counter = 1
end

Instance Attribute Details

#entriesArray<Entry> (readonly)

Returns Entries to write.

Returns:

  • (Array<Entry>)

    Entries to write



33
34
35
# File 'lib/omnizip/formats/cpio/writer.rb', line 33

def entries
  @entries
end

#formatSymbol (readonly)

Returns CPIO format (:newc, :crc, :odc).

Returns:

  • (Symbol)

    CPIO format (:newc, :crc, :odc)



30
31
32
# File 'lib/omnizip/formats/cpio/writer.rb', line 30

def format
  @format
end

#output_pathString (readonly)

Returns Output archive path.

Returns:

  • (String)

    Output archive path



27
28
29
# File 'lib/omnizip/formats/cpio/writer.rb', line 27

def output_path
  @output_path
end

Instance Method Details

#add_directory(dir_path, recursive: true, cpio_path: nil) ⇒ Object

Add directory to archive

Parameters:

  • dir_path (String)

    Source directory path

  • recursive (Boolean) (defaults to: true)

    Include subdirectories

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

    Path in archive

Raises:

  • (ArgumentError)

    if directory doesn't exist



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/omnizip/formats/cpio/writer.rb', line 83

def add_directory(dir_path, recursive: true, cpio_path: nil)
  raise ArgumentError, "Directory not found: #{dir_path}" unless
    Dir.exist?(dir_path)

  # Default to basename if no cpio_path specified
  cpio_path = File.basename(dir_path) if cpio_path.nil?
  # Normalize path: remove leading slashes to make relative
  cpio_path = cpio_path.sub(%r{^/+}, "")
  stat = File.lstat(dir_path)

  # Add directory entry
  entry = create_entry_from_stat(cpio_path, stat, "")
  @entries << entry
  @inode_counter += 1

  # Add contents if recursive
  if recursive
    Dir.foreach(dir_path) do |item|
      next if [".", ".."].include?(item)

      item_path = File.join(dir_path, item)
      item_cpio_path = "#{cpio_path}/#{item}"

      if File.directory?(item_path)
        add_directory(item_path, recursive: true,
                                 cpio_path: item_cpio_path)
      else
        add_file(item_path, item_cpio_path)
      end
    end
  end
end

#add_file(file_path, cpio_path = nil) ⇒ Object

Add file to archive

Parameters:

  • file_path (String)

    Source file path

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

    Path in archive (defaults to file_path)

Raises:

  • (ArgumentError)

    if file doesn't exist



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/omnizip/formats/cpio/writer.rb', line 51

def add_file(file_path, cpio_path = nil)
  raise ArgumentError, "File not found: #{file_path}" unless
    File.exist?(file_path) || File.symlink?(file_path)

  # Default to basename if no cpio_path specified
  cpio_path = File.basename(file_path) if cpio_path.nil?
  # Use lstat to not follow symlinks
  stat = File.lstat(file_path)

  # Normalize path: remove leading slashes to make relative
  cpio_path = cpio_path.sub(%r{^/+}, "")

  # Read file data unless it's a symlink
  data = if File.symlink?(file_path)
           File.readlink(file_path)
         elsif stat.file?
           File.binread(file_path)
         else
           ""
         end

  entry = create_entry_from_stat(cpio_path, stat, data)
  @entries << entry
  @inode_counter += 1
end

#writeObject

Write CPIO archive

Raises:



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/omnizip/formats/cpio/writer.rb', line 119

def write
  File.open(@output_path, "wb") do |io|
    # Write all entries
    @entries.each do |entry|
      write_entry(io, entry)
    end

    # Write trailer
    write_trailer(io)
  end

  @output_path
end