cephfs: add file method ListXattr implementing ceph_flistxattr

Add ListXattr implementing ceph_flistxattr. Add a test for the function.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
John Mulligan 2020-06-18 15:19:06 -04:00 committed by John Mulligan
parent a9738e7d45
commit 04bf7a4d0e
2 changed files with 84 additions and 1 deletions

View File

@ -12,6 +12,7 @@ package cephfs
import "C"
import (
"bytes"
"unsafe"
"github.com/ceph/go-ceph/internal/retry"
@ -97,3 +98,43 @@ func (f *File) GetXattr(name string) ([]byte, error) {
}
return buf[:ret], nil
}
// ListXattr returns a slice containing strings for the name of each xattr set
// on the fie.
//
// Implements:
// int ceph_flistxattr(struct ceph_mount_info *cmount, int fd, char *list, size_t size);
func (f *File) ListXattr() ([]string, error) {
if err := f.validate(); err != nil {
return nil, err
}
var (
ret C.int
err error
buf []byte
)
// range from 1k to 64KiB
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
buf = make([]byte, size)
ret = C.ceph_flistxattr(
f.mount.mount,
f.fd,
(*C.char)(unsafe.Pointer(&buf[0])),
C.size_t(size))
err = getErrorIfNegative(ret)
return retry.DoubleSize.If(err == errRange)
})
if err != nil {
return nil, err
}
names := make([]string, 0)
for _, s := range bytes.Split(buf[:ret], []byte{0}) {
if len(s) > 0 {
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
names = append(names, name)
}
}
return names, nil
}

View File

@ -74,5 +74,47 @@ func TestGetSetXattr(t *testing.T) {
_, err = f1.GetXattr(samples[0].name)
assert.Error(t, err)
})
}
func TestListXattr(t *testing.T) {
mount := fsConnect(t)
defer fsDisconnect(t, mount)
fname := "TestListXattr.txt"
f, err := mount.Open(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
require.NoError(t, err)
defer func() {
assert.NoError(t, f.Close())
assert.NoError(t, mount.Unlink(fname))
}()
t.Run("listXattrs1", func(t *testing.T) {
for _, s := range samples[:1] {
err := f.SetXattr(s.name, s.value, XattrDefault)
assert.NoError(t, err)
}
xl, err := f.ListXattr()
assert.NoError(t, err)
assert.Len(t, xl, 1)
assert.Contains(t, xl, samples[0].name)
})
t.Run("listXattrs2", func(t *testing.T) {
for _, s := range samples[:3] {
err := f.SetXattr(s.name, s.value, XattrDefault)
assert.NoError(t, err)
}
xl, err := f.ListXattr()
assert.NoError(t, err)
assert.Len(t, xl, 3)
assert.Contains(t, xl, samples[0].name)
assert.Contains(t, xl, samples[1].name)
assert.Contains(t, xl, samples[2].name)
})
t.Run("invalidFile", func(t *testing.T) {
f1 := &File{}
_, err := f1.ListXattr()
assert.Error(t, err)
})
}