stack.go
func (s *Stack) IterateForward(handler func(depth int, header io.Reader, body io.Reader) bool) error {
	// This operation does not relies on depth counter, so can be used for repare
	s.guard.Lock()
	defer s.guard.Unlock()
	s.lastAccess = time.Now()
	file, err := s.getFile()
	if err != nil {
		return err
	}
	//Get file size
	fileSize, err := file.Seek(0, os.SEEK_END)
	if err != nil {
		return err
	}
	_, err = file.Seek(0, os.SEEK_SET)
	if err != nil {
		return err
	}
	defer file.Seek(0, os.SEEK_END)
	var (
		currentBlock       fileBlock // Current block description
		currentBlockOffset uint64    // Current block offset from begining of file
	)
	var depth int
	for currentBlock.NextBlockPoint() < fileSize {
		newPos := currentBlock.NextBlockPoint()
		if newPos > fileSize {
			log.Println("Bad reference to next block at", currentBlockOffset, "!trunc!")
			file.Truncate(int64(currentBlockOffset))
			break
		}
		block, err := readBlockAt(file, newPos)
		// Non-full meta-info?
		if err == io.EOF {
			log.Println("Broken meta info at", newPos, "!trunc!")
			file.Truncate(newPos)
			break
		}
		// I/O error
		if err != nil {
			log.Println("Can't read block at", newPos)
			return err
		}
		// Check back-ref
		if block.PrevBlock != currentBlockOffset {
			log.Println("Bad back reference", block.PrevBlock, "!=", currentBlockOffset, "!upd!")
			block.PrevBlock = currentBlockOffset
			block.writeTo(file, newPos)
		}
		// Update current state
		currentBlockOffset = uint64(newPos)
		currentBlock = block
		body := io.NewSectionReader(file, int64(currentBlock.DataPoint), int64(currentBlock.DataSize))
		header := io.NewSectionReader(file, int64(currentBlock.HeaderPoint), int64(currentBlock.HeaderSize))
		// invoke block processor
		if handler != nil && !handler(depth, header, body) {
			return nil
		}
		depth++
	}
	s.depth = depth
	s.currentBlock = currentBlock
	s.currentBlockPos = int64(currentBlockOffset)
	return nil
}
func (s *Stack) IterateForward(handler func(depth int, header io.Reader, body io.Reader) bool) error {
	// This operation does not relies on depth counter, so can be used for repare
	s.guard.Lock()
	defer s.guard.Unlock()
	s.lastAccess = time.Now()
	file, err := s.getFile()
	if err != nil {
		return err
	}
	//Get file size
	fileSize, err := file.Seek(0, os.SEEK_END)
	if err != nil {
		return err
	}
	_, err = file.Seek(0, os.SEEK_SET)
	if err != nil {
		return err
	}
	defer file.Seek(0, os.SEEK_END)
	var (
		currentBlock       fileBlock // Current block description
		currentBlockOffset uint64    // Current block offset from begining of file
	)
	var depth int
	for currentBlock.NextBlockPoint() < fileSize {
		newPos := currentBlock.NextBlockPoint()
		if newPos > fileSize {
			log.Println("Bad reference to next block at", currentBlockOffset, "!trunc!")
			file.Truncate(int64(currentBlockOffset))
			break
		}
		block, err := readBlockAt(file, newPos)
		// Non-full meta-info?
		if err == io.EOF {
			log.Println("Broken meta info at", newPos, "!trunc!")
			file.Truncate(newPos)
			break
		}
		// I/O error
		if err != nil {
			log.Println("Can't read block at", newPos)
			return err
		}
		// Check back-ref
		if block.PrevBlock != currentBlockOffset {
			log.Println("Bad back reference", block.PrevBlock, "!=", currentBlockOffset, "!upd!")
			block.PrevBlock = currentBlockOffset
			block.writeTo(file, newPos)
		}
		// Update current state
		currentBlockOffset = uint64(newPos)
		currentBlock = block
		body := io.NewSectionReader(file, int64(currentBlock.DataPoint), int64(currentBlock.DataSize))
		header := io.NewSectionReader(file, int64(currentBlock.HeaderPoint), int64(currentBlock.HeaderSize))
		// invoke block processor
		if handler != nil && !handler(depth, header, body) {
			return nil
		}
		depth++
	}
	s.depth = depth
	s.currentBlock = currentBlock
	s.currentBlockPos = int64(currentBlockOffset)
	return nil
}
// IterateForward - iterate over hole stack segment-by-segment from begining to end. If all segments
// iterated stack may be repaired