Class: Omnizip::Formats::Rar::ParityHandler
- Inherits:
-
Object
- Object
- Omnizip::Formats::Rar::ParityHandler
- Defined in:
- lib/omnizip/formats/rar/parity_handler.rb
Overview
RAR parity operations handler Reads parity data and performs recovery calculations
Instance Attribute Summary collapse
-
#parity_blocks ⇒ Object
readonly
Returns the value of attribute parity_blocks.
-
#recovery_record ⇒ Object
readonly
Returns the value of attribute recovery_record.
Instance Method Summary collapse
-
#calculate_parity(data, block_index) ⇒ String
Calculate parity for a block.
-
#can_recover?(block_index) ⇒ Boolean
Check if block can be recovered.
-
#initialize(recovery_record) ⇒ ParityHandler
constructor
Initialize parity handler.
-
#load_parity_data(rev_files) ⇒ Boolean
Load parity data from .rev files.
-
#parity_block(index) ⇒ Hash?
Get parity block by index.
-
#recover_block(archive_path, block_index) ⇒ String?
Recover corrupted block.
-
#total_blocks ⇒ Integer
Get total number of blocks.
-
#verify_blocks(archive_path, block_indices = nil) ⇒ Hash
Verify archive blocks using parity.
Constructor Details
#initialize(recovery_record) ⇒ ParityHandler
Initialize parity handler
14 15 16 17 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 14 def initialize(recovery_record) @recovery_record = recovery_record @parity_blocks = [] end |
Instance Attribute Details
#parity_blocks ⇒ Object (readonly)
Returns the value of attribute parity_blocks.
9 10 11 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 9 def parity_blocks @parity_blocks end |
#recovery_record ⇒ Object (readonly)
Returns the value of attribute recovery_record.
9 10 11 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 9 def recovery_record @recovery_record end |
Instance Method Details
#calculate_parity(data, block_index) ⇒ String
Calculate parity for a block
65 66 67 68 69 70 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 65 def calculate_parity(data, block_index) # Basic XOR parity for simple recovery # In production, would use Reed-Solomon parity = data.bytes.reduce(0) { |acc, byte| acc ^ byte } [parity, block_index].pack("CN") end |
#can_recover?(block_index) ⇒ Boolean
Check if block can be recovered
91 92 93 94 95 96 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 91 def can_recover?(block_index) return false if @parity_blocks.empty? # Can recover if we have parity data for this block @parity_blocks.any? { |p| p[:index] == block_index } end |
#load_parity_data(rev_files) ⇒ Boolean
Load parity data from .rev files
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 23 def load_parity_data(rev_files) @parity_blocks = [] rev_files.each do |rev_file| blocks = parse_rev_file(rev_file) @parity_blocks.concat(blocks) if blocks end @parity_blocks.any? end |
#parity_block(index) ⇒ Hash?
Get parity block by index
111 112 113 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 111 def parity_block(index) @parity_blocks.find { |p| p[:index] == index } end |
#recover_block(archive_path, block_index) ⇒ String?
Recover corrupted block
77 78 79 80 81 82 83 84 85 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 77 def recover_block(archive_path, block_index) return nil unless can_recover?(block_index) if @recovery_record.version == 5 recover_rar5_block(archive_path, block_index) else recover_rar4_block(archive_path, block_index) end end |
#total_blocks ⇒ Integer
Get total number of blocks
101 102 103 104 105 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 101 def total_blocks return 0 if @recovery_record.block_size.zero? (@recovery_record.protected_size / @recovery_record.block_size.to_f).ceil end |
#verify_blocks(archive_path, block_indices = nil) ⇒ Hash
Verify archive blocks using parity
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/omnizip/formats/rar/parity_handler.rb', line 39 def verify_blocks(archive_path, block_indices = nil) if @parity_blocks.empty? return { verified: false, error: "No parity data" } end blocks_to_check = block_indices || (0...total_blocks).to_a corrupted_blocks = [] blocks_to_check.each do |index| corrupted_blocks << index unless verify_block(archive_path, index) end { verified: corrupted_blocks.empty?, total: blocks_to_check.size, ok: blocks_to_check.size - corrupted_blocks.size, corrupted: corrupted_blocks, } end |