mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-31 14:26:40 -04:00
On NetBSD the namespace of an xattr is stored separately from the name and isn't returned by Listxattr and Flistxattr. Like on FreeBSD, strip the namespace before checking the returned xattrs. Fixes golang/go#69313 Fixes golang/go#69314 Change-Id: I7f2393cc63f9860332c0e07a51f3b9d32911e892 Cq-Include-Trybots: luci.golang.try:x_sys-gotip-netbsd-arm64 Reviewed-on: https://go-review.googlesource.com/c/sys/+/611695 Auto-Submit: Tobias Klauser <tobias.klauser@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Benny Siegert <bsiegert@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
211 lines
4.7 KiB
Go
211 lines
4.7 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build darwin || freebsd || linux || netbsd
|
|
|
|
package unix_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func TestXattr(t *testing.T) {
|
|
chtmpdir(t)
|
|
|
|
f := "xattr1"
|
|
touch(t, f)
|
|
|
|
xattrName := "user.test"
|
|
xattrDataSet := "gopher"
|
|
|
|
err := unix.Setxattr(f, xattrName, []byte{}, 0)
|
|
if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
|
|
t.Skip("filesystem does not support extended attributes, skipping test")
|
|
} else if err != nil {
|
|
t.Fatalf("Setxattr: %v", err)
|
|
}
|
|
|
|
err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
|
|
if err != nil {
|
|
t.Fatalf("Setxattr: %v", err)
|
|
}
|
|
|
|
// find size
|
|
size, err := unix.Listxattr(f, nil)
|
|
if err != nil {
|
|
t.Fatalf("Listxattr: %v", err)
|
|
}
|
|
|
|
if size <= 0 {
|
|
t.Fatalf("Listxattr returned an empty list of attributes")
|
|
}
|
|
|
|
buf := make([]byte, size)
|
|
read, err := unix.Listxattr(f, buf)
|
|
if err != nil {
|
|
t.Fatalf("Listxattr: %v", err)
|
|
}
|
|
|
|
xattrs := stringsFromByteSlice(buf[:read])
|
|
|
|
xattrWant := xattrName
|
|
switch runtime.GOOS {
|
|
case "freebsd", "netbsd":
|
|
// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
|
|
// name and Listxattr doesn't return the namespace prefix.
|
|
xattrWant = strings.TrimPrefix(xattrWant, "user.")
|
|
}
|
|
found := false
|
|
for _, name := range xattrs {
|
|
if name == xattrWant {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Errorf("Listxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
|
|
}
|
|
|
|
// find size
|
|
size, err = unix.Getxattr(f, xattrName, nil)
|
|
if err != nil {
|
|
t.Fatalf("Getxattr: %v", err)
|
|
}
|
|
|
|
if size <= 0 {
|
|
t.Fatalf("Getxattr returned an empty attribute")
|
|
}
|
|
|
|
xattrDataGet := make([]byte, size)
|
|
_, err = unix.Getxattr(f, xattrName, xattrDataGet)
|
|
if err != nil {
|
|
t.Fatalf("Getxattr: %v", err)
|
|
}
|
|
|
|
got := string(xattrDataGet)
|
|
if got != xattrDataSet {
|
|
t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
|
|
}
|
|
|
|
err = unix.Removexattr(f, xattrName)
|
|
if err != nil {
|
|
t.Fatalf("Removexattr: %v", err)
|
|
}
|
|
|
|
n := "nonexistent"
|
|
err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
|
|
if err != unix.ENOENT {
|
|
t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
|
|
}
|
|
|
|
_, err = unix.Lgetxattr(n, xattrName, nil)
|
|
if err != unix.ENOENT {
|
|
t.Errorf("Lgetxattr: %v", err)
|
|
}
|
|
|
|
s := "symlink1"
|
|
err = os.Symlink(n, s)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
|
|
if err != nil {
|
|
// Linux and Android doen't support xattrs on symlinks according
|
|
// to xattr(7), so just test that we get the proper error.
|
|
if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
|
|
t.Fatalf("Lsetxattr: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFdXattr(t *testing.T) {
|
|
file, err := os.Create(filepath.Join(t.TempDir(), "TestFdXattr"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
fd := int(file.Fd())
|
|
xattrName := "user.test"
|
|
xattrDataSet := "gopher"
|
|
|
|
err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
|
|
if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
|
|
t.Skip("filesystem does not support extended attributes, skipping test")
|
|
} else if err != nil {
|
|
t.Fatalf("Fsetxattr: %v", err)
|
|
}
|
|
|
|
// find size
|
|
size, err := unix.Flistxattr(fd, nil)
|
|
if err != nil {
|
|
t.Fatalf("Flistxattr: %v", err)
|
|
}
|
|
|
|
if size <= 0 {
|
|
t.Fatalf("Flistxattr returned an empty list of attributes")
|
|
}
|
|
|
|
buf := make([]byte, size)
|
|
read, err := unix.Flistxattr(fd, buf)
|
|
if err != nil {
|
|
t.Fatalf("Flistxattr: %v", err)
|
|
}
|
|
|
|
xattrs := stringsFromByteSlice(buf[:read])
|
|
|
|
xattrWant := xattrName
|
|
switch runtime.GOOS {
|
|
case "freebsd", "netbsd":
|
|
// On FreeBSD and NetBSD, the namespace is stored separately from the xattr
|
|
// name and Listxattr doesn't return the namespace prefix.
|
|
xattrWant = strings.TrimPrefix(xattrWant, "user.")
|
|
}
|
|
found := false
|
|
for _, name := range xattrs {
|
|
if name == xattrWant {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Errorf("Flistxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
|
|
}
|
|
|
|
// find size
|
|
size, err = unix.Fgetxattr(fd, xattrName, nil)
|
|
if err != nil {
|
|
t.Fatalf("Fgetxattr: %v", err)
|
|
}
|
|
|
|
if size <= 0 {
|
|
t.Fatalf("Fgetxattr returned an empty attribute")
|
|
}
|
|
|
|
xattrDataGet := make([]byte, size)
|
|
_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
|
|
if err != nil {
|
|
t.Fatalf("Fgetxattr: %v", err)
|
|
}
|
|
|
|
got := string(xattrDataGet)
|
|
if got != xattrDataSet {
|
|
t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
|
|
}
|
|
|
|
err = unix.Fremovexattr(fd, xattrName)
|
|
if err != nil {
|
|
t.Fatalf("Fremovexattr: %v", err)
|
|
}
|
|
}
|