func (r *Reader) findNext(sn uint32, mini bool) (uint32, error) {
	entries := r.sectorSize / 4
	index := int(sn / entries)  
	var sect uint32
	if mini {
		if index < 0 || index >= len(r.header.miniFatLocs) {
			return 0, Error{ErrRead, "minisector index is outside miniFAT range", int64(index)}
		}
		sect = r.header.miniFatLocs[index]
	} else {
		if index < 0 || index >= len(r.header.difats) {
			return 0, Error{ErrRead, "FAT index is outside DIFAT range", int64(index)}
		}
		sect = r.header.difats[index]
	}
	fatIndex := sn % entries  
	offset := fileOffset(r.sectorSize, sect) + int64(fatIndex*4)
	buf, err := r.readAt(offset, 4)
	if err != nil {
		return 0, Error{ErrRead, "bad read finding next sector (" + err.Error() + ")", offset}
	}
	return binary.LittleEndian.Uint32(buf), nil
}
check the FAT sector for the next sector in a chain
package mscfb
import (
	"encoding/binary"
	"io"
	"strconv"
	"time"
)
func fileOffset(ss, sn uint32) int64 {
	return int64((sn + 1) * ss)
}
const (
	signature            uint64 = 0xE11AB1A1E011CFD0
	miniStreamSectorSize uint32 = 64
	miniStreamCutoffSize int64  = 4096
	dirEntrySize         uint32 = 128  
)
const (
	maxRegSect     uint32 = 0xFFFFFFFA  
	difatSect      uint32 = 0xFFFFFFFC  
	fatSect        uint32 = 0xFFFFFFFD  
	endOfChain     uint32 = 0xFFFFFFFE  
	freeSect       uint32 = 0xFFFFFFFF  
	maxRegStreamID uint32 = 0xFFFFFFFA  
	noStream       uint32 = 0xFFFFFFFF  
)
const lenHeader int = 8 + 16 + 10 + 6 + 12 + 8 + 16 + 109*4
type headerFields struct {
	signature           uint64
	_                   [16]byte     
	minorVersion        uint16       
	majorVersion        uint16       
	_                   [2]byte      
	sectorSize          uint16       
	_                   [2]byte      
	_                   [6]byte      
	numDirectorySectors uint32       
	numFatSectors       uint32       
	directorySectorLoc  uint32       
	_                   [4]byte      
	_                   [4]byte      
	miniFatSectorLoc    uint32       
	numMiniFatSectors   uint32       
	difatSectorLoc      uint32       
	numDifatSectors     uint32       
	initialDifats       [109]uint32  
}
func makeHeader(b []byte) *headerFields {
	h := &headerFields{}
	h.signature = binary.LittleEndian.Uint64(b[:8])
	h.minorVersion = binary.LittleEndian.Uint16(b[24:26])
	h.majorVersion = binary.LittleEndian.Uint16(b[26:28])
	h.sectorSize = binary.LittleEndian.Uint16(b[30:32])
	h.numDirectorySectors = binary.LittleEndian.Uint32(b[40:44])
	h.numFatSectors = binary.LittleEndian.Uint32(b[44:48])
	h.directorySectorLoc = binary.LittleEndian.Uint32(b[48:52])
	h.miniFatSectorLoc = binary.LittleEndian.Uint32(b[60:64])
	h.numMiniFatSectors = binary.LittleEndian.Uint32(b[64:68])
	h.difatSectorLoc = binary.LittleEndian.Uint32(b[68:72])
	h.numDifatSectors = binary.LittleEndian.Uint32(b[72:76])
	var idx int
	for i := 76; i < 512; i = i + 4 {
		h.initialDifats[idx] = binary.LittleEndian.Uint32(b[i : i+4])
		idx++
	}
	return h
}
type header struct {
	*headerFields
	difats         []uint32
	miniFatLocs    []uint32
	miniStreamLocs []uint32  
}
func (r *Reader) setHeader() error {
	buf, err := r.readAt(0, lenHeader)
	if err != nil {
		return err
	}
	r.header = &header{headerFields: makeHeader(buf)}
	if r.header.signature != signature {
		return Error{ErrFormat, "bad signature", int64(r.header.signature)}
	}
	if r.header.sectorSize == 0x0009 || r.header.sectorSize == 0x000c {
		r.sectorSize = uint32(1 << r.header.sectorSize)
	} else {
		return Error{ErrFormat, "illegal sector size", int64(r.header.sectorSize)}
	}
	if r.header.numDifatSectors > 0 {
		sz := (r.sectorSize / 4) - 1
		if int(r.header.numDifatSectors*sz+109) < 0 {
			return Error{ErrFormat, "DIFAT int overflow", int64(r.header.numDifatSectors)}
		}
		if r.header.numDifatSectors*sz+109 > r.header.numFatSectors+sz {
			return Error{ErrFormat, "num DIFATs exceeds FAT sectors", int64(r.header.numDifatSectors)}
		}
	}
	if r.header.numMiniFatSectors > 0 {
		if int(r.sectorSize/4*r.header.numMiniFatSectors) < 0 {
			return Error{ErrFormat, "mini FAT int overflow", int64(r.header.numMiniFatSectors)}
		}
		if r.header.numMiniFatSectors > r.header.numFatSectors*(r.sectorSize/miniStreamSectorSize) {
			return Error{ErrFormat, "num mini FATs exceeds FAT sectors", int64(r.header.numFatSectors)}
		}
	}
	return nil
}
func (r *Reader) setDifats() error {
	r.header.difats = r.header.initialDifats[:]
	if r.header.numDifatSectors == 0 {
		return nil
	}
	sz := (r.sectorSize / 4) - 1
	n := make([]uint32, 109, r.header.numDifatSectors*sz+109)
	copy(n, r.header.difats)
	r.header.difats = n
	off := r.header.difatSectorLoc
	for i := 0; i < int(r.header.numDifatSectors); i++ {
		buf, err := r.readAt(fileOffset(r.sectorSize, off), int(r.sectorSize))
		if err != nil {
			return Error{ErrFormat, "error setting DIFAT(" + err.Error() + ")", int64(off)}
		}
		for j := 0; j < int(sz); j++ {
			r.header.difats = append(r.header.difats, binary.LittleEndian.Uint32(buf[j*4:j*4+4]))
		}
		off = binary.LittleEndian.Uint32(buf[len(buf)-4:])
	}
	return nil
}
func (r *Reader) setMiniStream() error {
	if r.direntries[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 {
		return nil
	}
	c := int(r.header.numMiniFatSectors)
	r.header.miniFatLocs = make([]uint32, c)
	r.header.miniFatLocs[0] = r.header.miniFatSectorLoc
	for i := 1; i < c; i++ {
		loc, err := r.findNext(r.header.miniFatLocs[i-1], false)
		if err != nil {
			return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(r.header.miniFatLocs[i-1])}
		}
		r.header.miniFatLocs[i] = loc
	}
	c = int(r.sectorSize / 4 * r.header.numMiniFatSectors)
	r.header.miniStreamLocs = make([]uint32, 0, c)
	sn := r.direntries[0].startingSectorLoc
	var err error
	for sn != endOfChain {
		r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn)
		sn, err = r.findNext(sn, false)
		if err != nil {
			return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(sn)}
		}
	}
	return nil
}
func (r *Reader) readAt(offset int64, length int) ([]byte, error) {
	if r.slicer {
		b, err := r.ra.(slicer).Slice(offset, length)
		if err != nil {
			return nil, Error{ErrRead, "slicer read error (" + err.Error() + ")", offset}
		}
		return b, nil
	}
	if length > len(r.buf) {
		return nil, Error{ErrRead, "read length greater than read buffer", int64(length)}
	}
	if _, err := r.ra.ReadAt(r.buf[:length], offset); err != nil {
		return nil, Error{ErrRead, err.Error(), offset}
	}
	return r.buf[:length], nil
}
func (r *Reader) getOffset(sn uint32, mini bool) (int64, error) {
	if mini {
		num := r.sectorSize / 64
		sec := int(sn / num)
		if sec >= len(r.header.miniStreamLocs) {
			return 0, Error{ErrRead, "minisector number is outside minisector range", int64(sec)}
		}
		dif := sn % num
		return int64((r.header.miniStreamLocs[sec]+1)*r.sectorSize + dif*64), nil
	}
	return fileOffset(r.sectorSize, sn), nil
}