code: func HashFile(ctx context.Context, fs fs.Filesystem, path string, blockSize int, counter Counter, useWeakHashes bool) ([]protocol.BlockInfo, error) {
  	fd, err := fs.Open(path)
  	if err != nil {
  		l.Debugln("open:", err)
  		return nil, err
  	}
  	defer fd.Close()
  
  	// Get the size and modtime of the file before we start hashing it.
  
  	fi, err := fd.Stat()
  	if err != nil {
  		l.Debugln("stat before:", err)
  		return nil, err
  	}
  	size := fi.Size()
  	modTime := fi.ModTime()
  
  	// Hash the file. This may take a while for large files.
  
  	blocks, err := Blocks(ctx, fd, blockSize, size, counter, useWeakHashes)
  	if err != nil {
  		l.Debugln("blocks:", err)
  		return nil, err
  	}
  
  	// Recheck the size and modtime again. If they differ, the file changed
  	// while we were reading it and our hash results are invalid.
  
  	fi, err = fd.Stat()
  	if err != nil {
  		l.Debugln("stat after:", err)
  		return nil, err
  	}
  	if size != fi.Size() || !modTime.Equal(fi.ModTime()) {
  		return nil, errors.New("file changed during hashing")
  	}
  
  	return blocks, nil
  }
docs: // HashFile hashes the files and returns a list of blocks representing the file.