def load
@io.rewind
header_block = @io.read 512
@header = Header.new header_block
@bbat = AllocationTable::Big.new self
bbat_chain = header_block[Header::SIZE..-1].unpack 'V*'
mbat_block = @header.mbat_start
@header.num_mbat.times do
blocks = @bbat.read([mbat_block]).unpack 'V*'
mbat_block = blocks.pop
bbat_chain += blocks
end
@bbat.load @bbat.read(bbat_chain[0, @header.num_bat])
@dirents = @bbat.read(@header.dirent_start).to_enum(:each_chunk, Dirent::SIZE).
map { |str| Dirent.new self, str }.reject { |d| d.type_id == 0 }
class << @dirents
def to_tree idx=0
return [] if idx == Dirent::EOT
d = self[idx]
d.children = to_tree d.child
raise FormatError, "directory #{d.inspect} used twice" if d.idx
d.idx = idx
to_tree(d.prev) + [d] + to_tree(d.next)
end
end
@root = @dirents.to_tree.first
Log.warn "root name was #{@root.name.inspect}" unless @root.name == 'Root Entry'
unused = @dirents.reject(&:idx).length
Log.warn "#{unused} unused directories" if unused > 0
@sb_file = RangesIOResizeable.new @bbat, :first_block => @root.first_block, :size => @root.size
@sbat = AllocationTable::Small.new self
@sbat.load @bbat.read(@header.sbat_start)
end