class_docstr: OLE container object
  
  This class encapsulates the interface to an OLE 2 structured
  storage file.  Use the listdir and openstream methods to
  access the contents of this file.
  
  Object names are given as a list of strings, one for each subentry
  level.  The root entry should be omitted.  For example, the following
  code extracts all image streams from a Microsoft Image Composer file::
  
      ole = OleFileIO("fan.mic")
  
      for entry in ole.listdir():
          if entry[1:2] == "Image":
              fin = ole.openstream(entry)
              fout = open(entry[0:1], "wb")
              while True:
                  s = fin.read(8192)
                  if not s:
                      break
                  fout.write(s)
  
  You can use the viewer application provided with the Python Imaging
  Library to view the resulting files (which happens to be standard
  TIFF files).
class_docstr_tok: ["OLE","container","object","This","class","encapsulates","the","interface","to","an","OLE","2","structured","storage","file",".","Use","the","listdir","and","openstream","methods","to","access","the","contents","of","this","file",".","Object","names","are","given","as","a","list","of","strings",",","one","for","each","subentry","level",".","The","root","entry","should","be","omitted",".","For","example",",","the","following","code","extracts","all","image","streams","from","a","Microsoft","Image","Composer","file",":",":","ole","=","OleFileIO","(","``","fan.mic","''",")","for","entry","in","ole.listdir","(",")",":","if","entry","[","1:2","]","==","``","Image","''",":","fin","=","ole.openstream","(","entry",")","fout","=","open","(","entry","[","0:1","]",",","``","wb","''",")","while","True",":","s","=","fin.read","(","8192",")","if","not","s",":","break","fout.write","(","s",")","You","can","use","the","viewer","application","provided","with","the","Python","Imaging","Library","to","view","the","resulting","files","(","which","happens","to","be","standard","TIFF","files",")","."]
docstr: Load the FAT table.
docstr_tok: ["Load","the","FAT","table","."]
code: def loadfat(self, header):
      """
      Load the FAT table.
      """
      # The 1st sector of the file contains sector numbers for the first 109
      # FAT sectors, right after the header which is 76 bytes long.
      # (always 109, whatever the sector size: 512 bytes = 76+4*109)
      # Additional sectors are described by DIF blocks
  
      log.debug(
          "Loading the FAT table, starting with the 1st sector after the header"
      )
      sect = header[76:512]
      log.debug(
          "len(sect)=%d, so %d integers" % (len(sect), len(sect) // 4)
      )
      # fat    = []
      # [PL] FAT is an array of 32 bits unsigned ints, it's more effective
      # to use an array than a list in Python.
      # It's initialized as empty first:
      self.fat = array.array(UINT32)
      self.loadfat_sect(sect)
      # self.dumpfat(self.fat)
      ##      for i in range(0, len(sect), 4):
      ##          ix = i32(sect, i)
      ##          #[PL] if ix == -2 or ix == -1: # ix == 0xFFFFFFFE or ix == 0xFFFFFFFF:
      ##          if ix == 0xFFFFFFFE or ix == 0xFFFFFFFF:
      ##              break
      ##          s = self.getsect(ix)
      ##          #fat    = fat + [i32(s, i) for i in range(0, len(s), 4)]
      ##          fat = fat + array.array(UINT32, s)
      if self.num_difat_sectors != 0:
          log.debug("DIFAT is used, because file size > 6.8MB.")
          # [PL] There's a DIFAT because file is larger than 6.8MB
          # some checks just in case:
          if self.num_fat_sectors <= 109:
              # there must be at least 109 blocks in header and the rest in
              # DIFAT, so number of sectors must be >109.
              self._raise_defect(
                  DEFECT_INCORRECT,
                  "incorrect DIFAT, not enough sectors",
              )
          if self.first_difat_sector >= self.nb_sect:
              # initial DIFAT block index must be valid
              self._raise_defect(
                  DEFECT_FATAL,
                  "incorrect DIFAT, first index out of range",
              )
          log.debug("DIFAT analysis...")
          # We compute the necessary number of DIFAT sectors :
          # Number of pointers per DIFAT sector = (sectorsize/4)-1
          # (-1 because the last pointer is the next DIFAT sector number)
          nb_difat_sectors = (self.sectorsize // 4) - 1
          # (if 512 bytes: each DIFAT sector = 127 pointers + 1 towards next DIFAT sector)
          nb_difat = (
              self.num_fat_sectors - 109 + nb_difat_sectors - 1
          ) // nb_difat_sectors
          log.debug("nb_difat = %d" % nb_difat)
          if self.num_difat_sectors != nb_difat:
              raise IOError("incorrect DIFAT")
          isect_difat = self.first_difat_sector
          for i in iterrange(nb_difat):
              log.debug("DIFAT block %d, sector %X" % (i, isect_difat))
              # TODO: check if corresponding FAT SID = DIFSECT
              sector_difat = self.getsect(isect_difat)
              difat = self.sect2array(sector_difat)
              # Display the sector contents only if the logging level is debug:
              if log.isEnabledFor(logging.DEBUG):
                  self.dumpsect(sector_difat)
              self.loadfat_sect(difat[:nb_difat_sectors])
              # last DIFAT pointer is next DIFAT sector:
              isect_difat = difat[nb_difat_sectors]
              log.debug("next DIFAT sector: %X" % isect_difat)
          # checks:
          if isect_difat not in [ENDOFCHAIN, FREESECT]:
              # last DIFAT pointer value must be ENDOFCHAIN or FREESECT
              raise IOError("incorrect end of DIFAT")
      ##          if len(self.fat) != self.num_fat_sectors:
      ##              # FAT should contain num_fat_sectors blocks
      ##              print("FAT length: %d instead of %d" % (len(self.fat), self.num_fat_sectors))
      ##              raise IOError('incorrect DIFAT')
      else:
          log.debug("No DIFAT, because file size < 6.8MB.")
      # since FAT is read from fixed-size sectors, it may contain more values
      # than the actual number of sectors in the file.
      # Keep only the relevant sector indexes:
      if len(self.fat) > self.nb_sect:
          log.debug(
              "len(fat)=%d, shrunk to nb_sect=%d"
              % (len(self.fat), self.nb_sect)
          )
          self.fat = self.fat[: self.nb_sect]
      log.debug(
          "FAT references %d sectors / Maximum %d sectors in file"
          % (len(self.fat), self.nb_sect)
      )
      # Display the FAT contents only if the logging level is debug:
      if log.isEnabledFor(logging.DEBUG):
          log.debug("\nFAT:")
          self.dumpfat(self.fat)
  
imports: from __future__ import print_function
  import io
  import sys
  import struct, array, os.path, datetime, logging
label_desc: Use image node_id 13 for calling the OleFileIO obj's underlying member method code with example usage: obj.loadfat(header) without return types