func (k *KStat) CopyTo(ptr interface{}) error {
	if err := k.prep(); err != nil {
		return err
	}
	if k.Type != RawStat {
		return errors.New("KStat is not a RawStat")
	}
	if ptr == nil {
		panic("CopyTo given nil pointer")
	}
	vp := reflect.ValueOf(ptr)
	if vp.Kind() != reflect.Ptr {
		panic("CopyTo not given a pointer")
	}
	if vp.IsNil() {
		panic("CopyTo given nil pointer")
	}
	dst := vp.Elem()
	if dst.Kind() != reflect.Struct {
		panic("CopyTo: not pointer to struct")
	}
	if !safeThing(dst.Type()) {
		panic("CopyTo: not a safe structure, contains unsupported fields")
	}
	if !dst.CanSet() {
		panic("CopyTo: struct cannot be set for some reason")
	}
	if uintptr(k.ksp.ks_data_size) != dst.Type().Size() {
		return errors.New("struct size does not match KStat size")
	}
	src := reflect.NewAt(dst.Type(), unsafe.Pointer(k.ksp.ks_data))
	dst.Set(reflect.Indirect(src))
	return nil
}
TODO: add floats to the supported list? It's unlikely to be needed
but it should just work.
CopyTo copies a RawStat KStat into a struct that you supply a
pointer to. The size of the struct must exactly match the size of
the RawStat's data.

CopyStat imposes conditions on the struct that you are copying to:
it must be composed entirely of primitive integer types with defined
sizes (intN and uintN), or arrays and structs that ultimately only
contain them. All fields should be exported.

If you give CopyStat a bad argument, it generally panics.

This API is provisional and may be changed or deleted.
package kstat
import "C"
import (
	"errors"
	"fmt"
	"reflect"
	"unsafe"
)
type Raw struct {
	Data     []byte
	Ndata    uint64
	Snaptime int64
	KStat    *KStat
}
func (k *KStat) prep() error {
	if k.invalid() {
		return errors.New("invalid KStat or closed token")
	}
	if k.ksp.ks_data == nil {
		if err := k.Refresh(); err != nil {
			return err
		}
	}
	return nil
}
func (k *KStat) Raw() (*Raw, error) {
	if err := k.prep(); err != nil {
		return nil, err
	}
	r := Raw{}
	r.KStat = k
	r.Snaptime = k.Snaptime
	r.Ndata = uint64(k.ksp.ks_ndata)
	r.Data = C.GoBytes(unsafe.Pointer(k.ksp.ks_data), C.int(k.ksp.ks_data_size))
	return &r, nil
}
func (tok *Token) prepunix(name string, size uintptr) (*KStat, error) {
	k, err := tok.Lookup("unix", 0, name)
	if err != nil {
		return nil, err
	}
	if k.ksp.ks_type != C.KSTAT_TYPE_RAW {
		return nil, fmt.Errorf("%s is wrong type %s", k, k.Type)
	}
	if uintptr(k.ksp.ks_data_size) != size {
		return nil, fmt.Errorf("%s is wrong size %d (should be %d)", k, k.ksp.ks_data_size, size)
	}
	return k, nil
}
func (tok *Token) Sysinfo() (*KStat, *Sysinfo, error) {
	var si Sysinfo
	k, err := tok.prepunix("sysinfo", unsafe.Sizeof(si))
	if err != nil {
		return nil, nil, err
	}
	si = *((*Sysinfo)(k.ksp.ks_data))
	return k, &si, nil
}
func (tok *Token) Vminfo() (*KStat, *Vminfo, error) {
	var vi Vminfo
	k, err := tok.prepunix("vminfo", unsafe.Sizeof(vi))
	if err != nil {
		return nil, nil, err
	}
	vi = *((*Vminfo)(k.ksp.ks_data))
	return k, &vi, nil
}
func (tok *Token) Var() (*KStat, *Var, error) {
	var vi Var
	k, err := tok.prepunix("var", unsafe.Sizeof(vi))
	if err != nil {
		return nil, nil, err
	}
	vi = *((*Var)(k.ksp.ks_data))
	return k, &vi, nil
}
func (k *KStat) GetMntinfo() (*Mntinfo, error) {
	var mi Mntinfo
	if err := k.prep(); err != nil {
		return nil, err
	}
	if k.Type != RawStat || k.Module != "nfs" || k.Name != "mntinfo" {
		return nil, errors.New("KStat is not a Mntinfo kstat")
	}
	if uintptr(k.ksp.ks_data_size) != unsafe.Sizeof(mi) {
		return nil, fmt.Errorf("KStat is wrong size %d (should be %d)", k.ksp.ks_data_size, unsafe.Sizeof(mi))
	}
	mi = *((*Mntinfo)(k.ksp.ks_data))
	return &mi, nil
}
func safeThing(t reflect.Type) bool {
	switch t.Kind() {
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return true
	case reflect.Array:
		return safeThing(t.Elem())
	case reflect.Struct:
		for i := 0; i < t.NumField(); i++ {
			if !safeThing(t.Field(i).Type) {
				return false
			}
		}
		return true
	default:
		return false
	}
}