Example #1
0
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)
}
Example #2
0
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
}
Example #3
0
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
}
Example #4
0
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)
}
Example #5
0
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)
}
Example #6
0
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)
}
Example #7
0
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)
}
Example #8
0
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
}
Example #9
0
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
}
Example #10
0
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
}