# File lib/ole/storage/base.rb, line 105
    def load
      # we always read 512 for the header block. if the block size ends up being different,
      # what happens to the 109 fat entries. are there more/less entries?
      @io.rewind
      header_block = @io.read 512
      @header = Header.new header_block

      # create an empty bbat.
      @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
      # am i using num_bat in the right way?
      @bbat.load @bbat.read(bbat_chain[0, @header.num_bat])
  
      # get block chain for directories, read it, then split it into chunks and load the
      # directory entries. semantics changed - used to cut at first dir where dir.type == 0
      @dirents = @bbat.read(@header.dirent_start).to_enum(:each_chunk, Dirent::SIZE).
        map { |str| Dirent.new self, str }

      # now reorder from flat into a tree
      # links are stored in some kind of balanced binary tree
      # check that everything is visited at least, and at most once
      # similarly with the blocks of the file.
      # was thinking of moving this to Dirent.to_tree instead.
      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
      @dirents.reject! { |d| d.type_id == 0 }
      # silence this warning by default, its not really important (issue #5).
      # fairly common one appears to be "R" (from office OS X?) which smells
      # like some kind of UTF16 snafu, but scottwillson also has had some kanji...
      #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

      # FIXME i don't currently use @header.num_sbat which i should
      # hmm. nor do i write it. it means what exactly again?
      # which mode to use here?
      @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