1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin freebsd linux netbsd
16 "golang.org/x/sys/unix"
19 func TestXattr(t *testing.T) {
25 xattrName := "user.test"
26 xattrDataSet := "gopher"
28 err := unix.Setxattr(f, xattrName, []byte{}, 0)
29 if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
30 t.Skip("filesystem does not support extended attributes, skipping test")
31 } else if err != nil {
32 t.Fatalf("Setxattr: %v", err)
35 err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
37 t.Fatalf("Setxattr: %v", err)
41 size, err := unix.Listxattr(f, nil)
43 t.Fatalf("Listxattr: %v", err)
47 t.Fatalf("Listxattr returned an empty list of attributes")
50 buf := make([]byte, size)
51 read, err := unix.Listxattr(f, buf)
53 t.Fatalf("Listxattr: %v", err)
56 xattrs := stringsFromByteSlice(buf[:read])
58 xattrWant := xattrName
59 if runtime.GOOS == "freebsd" {
60 // On FreeBSD, the namespace is stored separately from the xattr
61 // name and Listxattr doesn't return the namespace prefix.
62 xattrWant = strings.TrimPrefix(xattrWant, "user.")
65 for _, name := range xattrs {
66 if name == xattrWant {
72 t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName)
76 size, err = unix.Getxattr(f, xattrName, nil)
78 t.Fatalf("Getxattr: %v", err)
82 t.Fatalf("Getxattr returned an empty attribute")
85 xattrDataGet := make([]byte, size)
86 _, err = unix.Getxattr(f, xattrName, xattrDataGet)
88 t.Fatalf("Getxattr: %v", err)
91 got := string(xattrDataGet)
92 if got != xattrDataSet {
93 t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
96 err = unix.Removexattr(f, xattrName)
98 t.Fatalf("Removexattr: %v", err)
102 err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
103 if err != unix.ENOENT {
104 t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
107 _, err = unix.Lgetxattr(n, xattrName, nil)
108 if err != unix.ENOENT {
109 t.Errorf("Lgetxattr: %v", err)
113 err = os.Symlink(n, s)
118 err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
120 // Linux and Android doen't support xattrs on symlinks according
121 // to xattr(7), so just test that we get the proper error.
122 if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
123 t.Fatalf("Lsetxattr: %v", err)
128 func TestFdXattr(t *testing.T) {
129 file, err := ioutil.TempFile("", "TestFdXattr")
133 defer os.Remove(file.Name())
137 xattrName := "user.test"
138 xattrDataSet := "gopher"
140 err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
141 if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
142 t.Skip("filesystem does not support extended attributes, skipping test")
143 } else if err != nil {
144 t.Fatalf("Fsetxattr: %v", err)
148 size, err := unix.Flistxattr(fd, nil)
150 t.Fatalf("Flistxattr: %v", err)
154 t.Fatalf("Flistxattr returned an empty list of attributes")
157 buf := make([]byte, size)
158 read, err := unix.Flistxattr(fd, buf)
160 t.Fatalf("Flistxattr: %v", err)
163 xattrs := stringsFromByteSlice(buf[:read])
165 xattrWant := xattrName
166 if runtime.GOOS == "freebsd" {
167 // On FreeBSD, the namespace is stored separately from the xattr
168 // name and Listxattr doesn't return the namespace prefix.
169 xattrWant = strings.TrimPrefix(xattrWant, "user.")
172 for _, name := range xattrs {
173 if name == xattrWant {
179 t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName)
183 size, err = unix.Fgetxattr(fd, xattrName, nil)
185 t.Fatalf("Fgetxattr: %v", err)
189 t.Fatalf("Fgetxattr returned an empty attribute")
192 xattrDataGet := make([]byte, size)
193 _, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
195 t.Fatalf("Fgetxattr: %v", err)
198 got := string(xattrDataGet)
199 if got != xattrDataSet {
200 t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
203 err = unix.Fremovexattr(fd, xattrName)
205 t.Fatalf("Fremovexattr: %v", err)