func SetProp(name string, props map[string]interface{}, source PropSource) error {
	cmd := &Cmd{
		Cookie: uint64(source),
	}
	errList := make(map[string]int64)
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_SET_PROP, name, cmd, props, errList, nil)
}
SetProp sets one or more props on a ZFS dataset.
package ioctl
import (
	"errors"
	"fmt"
	"io"
	"os"
	"syscall"
	"golang.org/x/sys/unix"
)
type PropWithSource struct {
	Value  interface{} `nvlist:"value"`
	Source string      `nvlist:"source"`
}
type DatasetPropsWithSource map[string]PropWithSource
type DatasetProps map[string]interface{}
type ACLInheritancePolicy uint64
type DNodeSize uint64
type CanMount uint64
type FilesystemProps struct {
	SnapshotDirectoryEnabled bool                 `nvlist:"snapdir,asuint64"`
	ACLInheritancePolicy     ACLInheritancePolicy `nvlist:"aclinherit,omitempty,default=4"`
	DNodeSize                DNodeSize            `nvlist:"dnodesize,omitempty"`
	Atime                    bool                 `nvlist:"atime,default=true"`
	RelativeAtime            bool                 `nvlist:"relatime"`
	Zoned     bool     `nvlist:"zoned"`
	VirusScan bool     `nvlist:"vscan"`
	Overlay   bool     `nvlist:"overlay"`
	CanMount  CanMount `nvlist:"canmount,default=true"`
	Mounted   bool     `nvlist:"mounted"`
	Mountpoint string `nvlist:"mountpoint"`
}
type VolumeProps struct {
}
type PoolProps struct {
	Name    string `nvlist:"name,omitempty"`
	Version uint64 `nvlist:"version,omitempty"`
	Comment string `nvlist:"comment,omitempty"`
	AlternativeRoot string   `nvlist:"altroot,omitempty"`
	TemporaryName   string   `nvlist:"tname,omitempty"`
	BootFS          string   `nvlist:"bootfs,omitempty"`
	CacheFile       string   `nvlist:"cachefile,omitempty"`
	ReadOnly        bool     `nvlist:"readonly,omitempty"`
	Multihost       bool     `nvlist:"multihost,omitempty"`
	Failmode        FailMode `nvlist:"failmode,omitempty"`
	DedupDitto      uint64   `nvlist:"dedupditto,omitempty"`
	AlignmentShift  uint64   `nvlist:"ashift,omitempty"`
	Delegation      bool     `nvlist:"delegation,omitempty"`
	Autoreplace     bool     `nvlist:"autoreplace,omitempty"`
	ListSnapshots   bool     `nvlist:"listsnapshots,omitempty"`
	Autoexpand      bool     `nvlist:"autoexpand,omitempty"`
	MaxBlockSize    uint64   `nvlist:"maxblocksize,omitempty"`
	MaxDnodeSize    uint64   `nvlist:"maxdnodesize,omitempty"`
	RootProps *DatasetProps `nvlist:"root-props-nvl,omitempty"`
	User map[string]string `nvlist:"-,extra,omitempty"`
	Size          uint64 `nvlist:"size,ro"`
	Free          uint64 `nvlist:"free,ro"`
	Freeing       uint64 `nvlist:"freeing,ro"`
	Leaked        uint64 `nvlist:"leaked,ro"`
	Allocated     uint64 `nvlist:"allocated,ro"`
	ExpandSize    uint64 `nvlist:"expandsize,ro"`
	Fragmentation uint64 `nvlist:"fragmentation,ro"`
	Capacity      uint64 `nvlist:"capacity,ro"`
	GUID          uint64 `nvlist:"guid,ro"`
	Health        State  `nvlist:"health,ro"`
	DedupRatio    uint64 `nvlist:"dedupratio,ro"`
}
var zfsHandle *os.File
func Init(nodePath string) error {
	if nodePath == "" {
		nodePath = "/dev/zfs"
	}
	var err error
	zfsHandle, err = os.Open(nodePath)
	if os.IsNotExist(err) {
		unix.Mknod(nodePath, 666, int(unix.Mkdev(10, 54)))
	}
	zfsHandle, err = os.Open(nodePath)
	if err != nil {
		return fmt.Errorf("Failed to open or create ZFS device node: %v", err)
	}
	return nil
}
type VDev struct {
	IsLog               uint64 `nvlist:"is_log"`
	DTL                 uint64 `nvlist:"DTL,omitempty"`
	AlignmentShift      uint64 `nvlist:"ashift,omitempty"`
	AllocatableCapacity uint64 `nvlist:"asize,omitempty"`
	GUID                uint64 `nvlist:"guid,omitempty"`
	ID                  uint64 `nvlist:"id,omitempty"`
	Path                string `nvlist:"path"`
	Type                string `nvlist:"type"`
	Children            []VDev `nvlist:"children,omitempty"`
	L2CacheChildren     []VDev `nvlist:"l2cache,omitempty"`
	SparesChildren      []VDev `nvlist:"spares,omitempty"`
}
type PoolConfig struct {
	Version          uint64 `nvlist:"version,omitempty"`
	Name             string `nvlist:"name,omitempty"`
	State            uint64 `nvlist:"state,omitempty"`
	TXG              uint64 `nvlist:"txg,omitempty"`
	GUID             uint64 `nvlist:"pool_guid,omitempty"`
	Errata           uint64 `nvlist:"errata,omitempty"`
	Hostname         string `nvlist:"hostname,omitempty"`
	NumberOfChildren uint64 `nvlist:"vdev_children"`
	VDevTree         *VDev  `nvlist:"vdev_tree"`
	HostID           uint64 `nvlist:"hostid,omitempty"`
	FeaturesForRead map[string]bool `nvlist:"features_for_read"`
}
func delimitedBufToString(buf []byte) string {
	i := 0
	for ; i < len(buf); i++ {
		if buf[i] == 0x00 {
			break
		}
	}
	return string(buf[:i])
}
func stringToDelimitedBuf(str string, buf []byte) error {
	if len(str) > len(buf)-1 {
		return fmt.Errorf("String longer than target buffer (%v > %v)", len(str), len(buf)-1)
	}
	for i := 0; i < len(str); i++ {
		if str[i] == 0x00 {
			return errors.New("String contains null byte, this is unsupported by ZFS")
		}
		buf[i] = str[i]
	}
	return nil
}
func DatasetListNext(name string, cursor uint64) (string, uint64, DMUObjectSetStats, DatasetPropsWithSource, error) {
	cmd := &Cmd{
		Cookie: cursor,
	}
	props := make(DatasetPropsWithSource)
	if err := NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_DATASET_LIST_NEXT, name, cmd, nil, props, nil); err != nil {
		return "", 0, DMUObjectSetStats{}, props, err
	}
	return delimitedBufToString(cmd.Name[:]), cmd.Cookie, cmd.Objset_stats, props, nil
}
func SnapshotListNext(name string, cursor uint64, props interface{}) (string, uint64, DMUObjectSetStats, error) {
	cmd := &Cmd{
		Cookie: cursor,
	}
	if err := NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_SNAPSHOT_LIST_NEXT, name, cmd, nil, props, nil); err != nil {
		return "", 0, DMUObjectSetStats{}, err
	}
	return delimitedBufToString(cmd.Name[:]), cmd.Cookie, cmd.Objset_stats, nil
}
func PoolCreate(name string, features map[string]uint64, config VDev) error {
	cmd := &Cmd{}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_CREATE, name, cmd, features, nil, config)
}
func PoolDestroy(name string) error {
	cmd := &Cmd{}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_DESTROY, name, cmd, nil, nil, nil)
}
func PoolConfigs() (map[string]interface{}, error) {
	cmd := &Cmd{}
	res := make(map[string]interface{})
	err := NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_CONFIGS, "", cmd, nil, res, nil)
	return res, err
}
func PoolStats(name string) (map[string]interface{}, error) {
	cmd := &Cmd{}
	res := make(map[string]interface{})
	err := NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_STATS, name, cmd, nil, res, nil)
	if err != nil {
		return nil, err
	}
	if cmd.Cookie != 0 {
		return nil, syscall.Errno(cmd.Cookie)
	}
	return res, nil
}
func PoolImport(name string, config map[string]interface{}, props map[string]interface{}) (map[string]interface{}, error) {
	cmd := &Cmd{}
	cmd.Guid = config["pool_guid"].(uint64)
	outConfig := make(map[string]interface{})
	err := NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_IMPORT, name, cmd, props, outConfig, config)
	if cmd.Cookie != 0 {
		return nil, unix.Errno(cmd.Cookie)
	}
	return outConfig, err
}
func PoolExport(name string, force, hardForce bool) error {
	cmd := &Cmd{}
	if force {
		cmd.Cookie = 1
	}
	if hardForce {
		cmd.Guid = 1
	}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_POOL_EXPORT, name, cmd, nil, nil, nil)
}
func Promote(name string) (conflictingSnapshot string, err error) {
	cmd := &Cmd{}
	err = NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_PROMOTE, name, cmd, nil, nil, nil)
	conflictingSnapshot = delimitedBufToString(cmd.String[:])
	return
}
func Clone(origin string, name string, props *DatasetProps) error {
	var cloneReq struct {
		Origin string        `nvlist:"origin"`
		Props  *DatasetProps `nvlist:"props"`
	}
	cloneReq.Origin = origin
	cloneReq.Props = props
	errList := make(map[string]int32)
	cmd := &Cmd{}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_CLONE, name, cmd, cloneReq, errList, nil)
}
func Create(name string, t ObjectType, props *DatasetProps) error {
	var createReq struct {
		Type  ObjectType    `nvlist:"type"`
		Props *DatasetProps `nvlist:"props"`
	}
	createReq.Type = t
	createReq.Props = props
	cmd := &Cmd{}
	createRes := make(map[string]int32)
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_CREATE, name, cmd, createReq, createRes, nil)
}
func Snapshot(names []string, pool string, props *DatasetProps) error {
	var snapReq struct {
		Snaps map[string]bool `nvlist:"snaps"`
		Props *DatasetProps   `nvlist:"props"`
	}
	snapReq.Snaps = make(map[string]bool)
	for _, name := range names {
		if _, ok := snapReq.Snaps[name]; ok {
			return errors.New("duplicate snapshot name")
		}
		snapReq.Snaps[name] = true
	}
	snapReq.Props = props
	cmd := &Cmd{}
	snapRes := make(map[string]int32)
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_SNAPSHOT, pool, cmd, snapReq, snapRes, nil)
}
func DestroySnapshots(names []string, pool string, defer_ bool) error {
	var destroySnapReq struct {
		Snaps map[string]bool `nvlist:"snaps"`
		Defer bool            `nvlist:"defer"`
	}
	destroySnapReq.Snaps = make(map[string]bool)
	for _, name := range names {
		if _, ok := destroySnapReq.Snaps[name]; ok {
			return errors.New("duplicate snapshot name")
		}
		destroySnapReq.Snaps[name] = true
	}
	destroySnapReq.Defer = defer_
	errList := make(map[string]int32)
	cmd := &Cmd{}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_CLONE, pool, cmd, destroySnapReq, errList, nil)
}
func Bookmark(snapshotsToBookmarks map[string]string) error {
	errList := make(map[string]int32)
	cmd := &Cmd{}
	return NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_BOOKMARK, "", cmd, snapshotsToBookmarks, errList, nil)
}
func Rollback(name string, target string) (actualTarget string, err error) {
	var req struct {
		Target string `nvlist:"target,omitempty"`
	}
	req.Target = target
	var res struct {
		Target string `nvlist:"target"`
	}
	cmd := &Cmd{}
	err = NvlistIoctl(zfsHandle.Fd(), ZFS_IOC_ROLLBACK, name, cmd, req, res, nil)
	actualTarget = res.Target
	return
}
type PropSource uint64
const (
	PropSourceNone PropSource = 1 << iota
	PropSourceDefault
	PropSourceTemporary
	PropSourceLocal
	PropSourceInherited
	PropSourceReceived
)