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 ARCHIVE flags (spec): 0x0001 volume, 0x0002 volume number field present
MainHeader::ARCHIVE_FLAG_VOLUME
- VOLUME_NUMBER_FLAG =
MainHeader::ARCHIVE_FLAG_VOLUME_NUMBER
- 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
46 47 48 49 50 51 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 46 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.
39 40 41 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 39 def io @io end |
#is_last ⇒ Boolean (readonly)
Returns Is this the last volume?.
36 37 38 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 36 def is_last @is_last end |
#path ⇒ String (readonly)
Returns Volume file path.
30 31 32 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 30 def path @path end |
#volume_number ⇒ Integer (readonly)
Returns Volume number (1-based).
33 34 35 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 33 def volume_number @volume_number end |
Class Method Details
.volume_filename(base_path, volume_number, naming: "part") ⇒ String
Generate volume filename from base name
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 141 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
63 64 65 66 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 63 def close @io&.close @io = nil end |
#open ⇒ void
This method returns an undefined value.
Open volume file for writing
56 57 58 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 56 def open @io = File.open(@path, "wb") end |
#write {|writer| ... } ⇒ void
This method returns an undefined value.
Write with automatic open/close
72 73 74 75 76 77 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 72 def write open yield self ensure close end |
#write_end_header ⇒ void
This method returns an undefined value.
Write End header with volume flags
126 127 128 129 130 131 132 133 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 126 def write_end_header raise "Volume not open" unless @io # End-of-archive flags: 0x0001 marks a volume with more # volumes following; the last volume ends with 0. end_flags = @is_last ? 0 : VOLUME_END_FLAG @io.write(EndHeader.new(end_flags: end_flags).encode) end |
#write_file_data(file_header, compressed_data) ⇒ void
This method returns an undefined value.
Write file data (header + compressed data)
116 117 118 119 120 121 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 116 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
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 94 def write_main_header raise "Volume not open" unless @io # Archive flags: every volume declares 0x0001; volumes # after the first also carry the volume number field # (spec: number is N-1, absent on the first volume). archive_flags = VOLUME_ARCHIVE_FLAG volume_number = nil if @volume_number > 1 archive_flags |= VOLUME_NUMBER_FLAG volume_number = @volume_number - 1 end @io.write(MainHeader.new(archive_flags: archive_flags, volume_number: volume_number).encode) end |
#write_signature ⇒ void
This method returns an undefined value.
Write RAR5 signature
82 83 84 85 86 87 88 89 |
# File 'lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb', line 82 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 |