Description
File extended attributes on FreeBSD (and NetBSD) have a namespace which is either user
or system
. This is represented by an enum in the syscall API. In the Go package, it's represented by prefixing the name with user.
or system.
, like how it works in Linux. When listing extended attributes (at the syscall level) you need to specify the namespace. The Go package lists both the system and user namespaces and merges the results, but doesn't add any prefix so the returned list of attribute names isn't usable -- we don't know the namespace each came from.
A test case:
package fs_test
import (
"golang.org/x/sys/unix"
"os"
"testing"
)
func TestFreeBSDXattr(t *testing.T) {
fd, err := os.Create("testfile")
if err != nil {
t.Fatal(err)
}
fd.Close()
if err := unix.Lsetxattr("testfile", "user.foo", []byte("value 1"), 0); err != nil {
t.Fatal(err)
}
if err := unix.Lsetxattr("testfile", "system.bar", []byte("value 2"), 0); err != nil {
t.Fatal(err)
}
buf := make([]byte, 1024)
size, err := unix.Llistxattr("testfile", buf)
if err != nil {
t.Fatal(err)
}
buf = buf[:size]
t.Logf("%q", buf)
}
which returns the following list of attributes (when run as a superuser who can set system
namespace attributes):
=== RUN TestFreeBSDXattr
freebsd_xattr_test.go:30: "\x03foo\x03bar"
--- PASS: TestFreeBSDXattr (0.00s)
(that's length, name, length, name
so "foo", "bar"
)
Actually trying to unix.Lgetxattr
"foo"
or "bar"
returns ENOATTR
, as these do not exist without a namespace.
Probably Llistxattr
(and Listxattr
) should synthesize the namespace prefix in the listing.