func send(name string, outputFD uintptr, fromSnap string, largeBlockOK, embedOK bool) error { innvl := map[string]interface{}{ "fd": int32(outputFD), } // The following properties are optional, but must only be present in innvl // if being used. if fromSnap != "" { innvl["fromsnap"] = fromSnap } if largeBlockOK { innvl["largeblockok"] = true } if embedOK { innvl["embedok"] = true } m := map[string]interface{}{ "cmd": "zfs_send", "version": uint64(0), "innvl": innvl, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return err } return ioctl(zfs, name, encoded.Bytes(), nil) }
func holds(name string) ([]string, error) { m := map[string]interface{}{ "cmd": "zfs_get_holds", "version": uint64(0), } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return nil, err } out := make([]byte, 1024) copy(out, emptyList) err = ioctl(zfs, name, encoded.Bytes(), out) if err != nil { return nil, err } m = map[string]interface{}{} if err = nv.NewNativeDecoder(bytes.NewReader(out)).Decode(&m); err != nil { return nil, err } names := make([]string, 0, len(m)) for name := range m { names = append(names, name) } return names, nil }
func rename(name, newName string, recursive bool) (string, error) { m := map[string]interface{}{ "cmd": "zfs_rename", "version": uint64(0), "innvl": map[string]interface{}{ "newname": newName, "recursive": recursive, }, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return "", err } out := make([]byte, 1024) err = ioctl(zfs, name, encoded.Bytes(), out) var failedName string if err != nil && recursive { _ = nv.NewNativeDecoder(bytes.NewReader(out)).Decode(&failedName) } return failedName, err }
func exists(name string) error { m := map[string]interface{}{ "cmd": "zfs_exists", "version": uint64(0), } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return err } return ioctl(zfs, name, encoded.Bytes(), nil) }
func destroy(name string, deferFlag bool) error { m := map[string]interface{}{ "cmd": "zfs_destroy", "version": uint64(0), "defer": deferFlag, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return err } return ioctl(zfs, name, encoded.Bytes(), nil) }
func clone(name, origin string, props map[string]interface{}) error { m := map[string]interface{}{ "cmd": "zfs_clone", "version": uint64(0), "innvl": map[string]interface{}{ "origin": origin, "props": props, }, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return err } return ioctl(zfs, name, encoded.Bytes(), nil) }
func create(name string, createType dmuType, props map[string]interface{}) error { m := map[string]interface{}{ "cmd": "zfs_create", "version": uint64(0), "innvl": map[string]interface{}{ "type": createType, "props": props, }, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return err } return ioctl(zfs, name, encoded.Bytes(), nil) }
func snapshot(pool string, snapNames []string, props map[string]string) (map[string]syscall.Errno, error) { // snaps needs to be a map with the snap name as the key and an arbitrary value snaps := make(map[string]string) for _, snapName := range snapNames { snaps[snapName] = "" } m := map[string]interface{}{ "cmd": "zfs_snapshot", "version": uint64(0), "innvl": map[string]interface{}{ "snaps": snaps, "props": props, }, } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return nil, err } out := make([]byte, 1024) err = ioctl(zfs, pool, encoded.Bytes(), out) var errlist map[string]syscall.Errno if errno, ok := err.(syscall.Errno); ok && errno == syscall.EEXIST { // Try to get errlist info, but ignore any errors in the attempt errs := map[string]int32{} if nv.NewNativeDecoder(bytes.NewReader(out)).Decode(&errs) == nil { errlist = make(map[string]syscall.Errno, len(errs)) for snap, errno := range errs { errlist[snap] = syscall.Errno(errno) } } } return errlist, err }
func rollback(name string) (string, error) { m := map[string]interface{}{ "cmd": "zfs_rollback", "version": uint64(0), } encoded := &bytes.Buffer{} err := nv.NewNativeEncoder(encoded).Encode(m) if err != nil { return "", err } out := make([]byte, 1024) err = ioctl(zfs, name, encoded.Bytes(), out) var snapName string if err == nil { var results map[string]string if err = nv.NewNativeDecoder(bytes.NewReader(out)).Decode(&results); err == nil { snapName = results["target"] } } return snapName, err }
func list(name string, types map[string]bool, recurse bool, depth uint64) ([]*dataset, error) { var reader io.Reader reader, writer, err := os.Pipe() if err != nil { return nil, err } defer reader.(*os.File).Close() defer writer.Close() opts := map[string]interface{}{ "fd": int32(writer.Fd()), } if types != nil { opts["type"] = types } if recurse != false { if depth != 0 { opts["recurse"] = depth } else { opts["recurse"] = true } } args := map[string]interface{}{ "cmd": "zfs_list", "innvl": map[string]interface{}{}, "opts": opts, "version": uint64(0), } encoded := &bytes.Buffer{} err = nv.NewNativeEncoder(encoded).Encode(args) if err != nil { return nil, err } err = ioctl(zfs, name, encoded.Bytes(), nil) if err != nil { return nil, err } var buf []byte reader = bufio.NewReader(reader) ret := []*dataset{} for { var size int64 size, err = getSize(reader) if err != nil { break } if size == 0 { break } if len(buf) < int(size) { l := (size + 1023) & ^1023 buf = make([]byte, l) } buf = buf[:size] _, err = io.ReadFull(reader, buf) if err != nil { break } m := &dataset{} err = nv.NewXDRDecoder(bytes.NewReader(buf)).Decode(&m) if err != nil { break } if m.Properties.Clones.Value == nil { m.Properties.Clones.Value = make(map[string]nv.Boolean) } ret = append(ret, m) } return ret, err }