Class: Omnizip::Formats::Rar::Rar5::MultiVolume::VolumeWriter
- Inherits:
-
Object
- Object
- Omnizip::Formats::Rar::Rar5::MultiVolume::VolumeWriter
- Defined in:
- lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb
Overview
Volume writer for multi-volume archives
This class writes individual .rar volume files with proper RAR5 headers and volume-specific flags.
Constant Summary collapse
- VOLUME_ARCHIVE_FLAG =
Main header flags for volume archives NOTE: Bits 0-1 are reserved for common flags (EXTRA_AREA, DATA_AREA) Use bits 2+ for format-specific flags
0x0004- VOLUME_NUMBER_FLAG =
Bit 2: This is a volume archive
0x0008- VOLUME_END_FLAG =
End header flags
0x0001
Instance Attribute Summary collapse
-
#io ⇒ IO
readonly
File handle.
-
#is_last ⇒ Boolean
readonly
Is this the last volume?.
-
#path ⇒ String
readonly
Volume file path.
-
#volume_number ⇒ Integer
readonly
Volume number (1-based).
Class Method Summary collapse
-
.volume_filename(base_path, volume_number, naming: "part") ⇒ String
Generate volume filename from base name.
Instance Method Summary collapse
-
#close ⇒ void
Close volume file.
-
#initialize(path, volume_number:, is_last: false) ⇒ VolumeWriter
constructor
Initialize volume writer.
-
#open ⇒ void
Open volume file for writing.
-
#write {|writer| ... } ⇒ void
Write with automatic open/close.
-
#write_end_header ⇒ void
Write End header with volume flags.
-
#write_file_data(file_header, compressed_data) ⇒ void
Write file data (header + compressed data).
-
#write_main_header ⇒ void
Write Main header with volume flags.
-
#write_signature ⇒ void
Write RAR5 signature.
Constructor Details
#initialize(path, volume_number:, is_last: false) ⇒ VolumeWriter
Initialize volume writer
47 48 49 50 51 52 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 47 def initialize(path, volume_number:, is_last: false) @path = path @volume_number = volume_number @is_last = is_last @io = nil end |
Instance Attribute Details
#io ⇒ IO (readonly)
Returns File handle.
40 41 42 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 40 def io @io end |
#is_last ⇒ Boolean (readonly)
Returns Is this the last volume?.
37 38 39 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 37 def is_last @is_last end |
#path ⇒ String (readonly)
Returns Volume file path.
31 32 33 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 31 def path @path end |
#volume_number ⇒ Integer (readonly)
Returns Volume number (1-based).
34 35 36 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 34 def volume_number @volume_number end |
Class Method Details
.volume_filename(base_path, volume_number, naming: "part") ⇒ String
Generate volume filename from base name
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 157 def self.volume_filename(base_path, volume_number, naming: "part") dir = File.dirname(base_path) basename = File.basename(base_path, ".*") ext = File.extname(base_path) volume_name = case naming when "part" "#{basename}.part#{volume_number}#{ext}" when "volume" "#{basename}.vol#{volume_number}#{ext}" when "numeric" # Simple numeric suffix: archive.rar, archive.r00, archive.r01, etc. if volume_number == 1 "#{basename}#{ext}" else # Volume 2 => r00, Volume 3 => r01, etc. "#{basename}.r#{format('%02d', volume_number - 2)}" end else "#{basename}.part#{volume_number}#{ext}" end # Handle relative vs absolute paths if dir == "." volume_name else File.join(dir, volume_name) end end |
Instance Method Details
#close ⇒ void
This method returns an undefined value.
Close volume file
64 65 66 67 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 64 def close @io&.close @io = nil end |
#open ⇒ void
This method returns an undefined value.
Open volume file for writing
57 58 59 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 57 def open @io = File.open(@path, "wb") end |
#write {|writer| ... } ⇒ void
This method returns an undefined value.
Write with automatic open/close
73 74 75 76 77 78 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 73 def write open yield self ensure close end |
#write_end_header ⇒ void
This method returns an undefined value.
Write End header with volume flags
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 136 def write_end_header raise "Volume not open" unless @io # Set END_OF_ARCHIVE flags flags = 0 flags | VOLUME_END_FLAG unless @is_last header = EndHeader.new # Note: EndHeader doesn't support custom flags yet # For v0.5.0, we'll use basic end header # TODO: Enhance EndHeader to support volume flags @io.write(header.encode) end |
#write_file_data(file_header, compressed_data) ⇒ void
This method returns an undefined value.
Write file data (header + compressed data)
126 127 128 129 130 131 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 126 def write_file_data(file_header, compressed_data) raise "Volume not open" unless @io @io.write(file_header.encode) @io.write(compressed_data) end |
#write_main_header ⇒ void
This method returns an undefined value.
Write Main header with volume flags
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 95 def write_main_header raise "Volume not open" unless @io # Set volume-specific flags flags = VOLUME_ARCHIVE_FLAG # Add volume number in extra area for volumes 2+ extra_area = nil if @volume_number > 1 flags |= VOLUME_NUMBER_FLAG # Volume number as VINT in extra area extra_area = VINT.encode(@volume_number).pack("C*") end header = MainHeader.new(flags: flags) # Manually add extra area if needed if extra_area # We need to modify the header to include extra area # For now, use basic header without extra area (simplified) # TODO: Enhance MainHeader to support extra_area parameter end @io.write(header.encode) end |
#write_signature ⇒ void
This method returns an undefined value.
Write RAR5 signature
83 84 85 86 87 88 89 90 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 83 def write_signature raise "Volume not open" unless @io # RAR5 signature: "Rar!\x1A\x07\x01\x00" signature = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00].pack("C*") @io.write(signature) end |