1
2
3
4
5
6
7 package unix_test
8
9 import (
10 "os"
11 "path/filepath"
12 "runtime"
13 "strings"
14 "testing"
15
16 "golang.org/x/sys/unix"
17 )
18
19 func TestXattr(t *testing.T) {
20 chtmpdir(t)
21
22 f := "xattr1"
23 touch(t, f)
24
25 xattrName := "user.test"
26 xattrDataSet := "gopher"
27
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)
33 }
34
35 err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
36 if err != nil {
37 t.Fatalf("Setxattr: %v", err)
38 }
39
40
41 size, err := unix.Listxattr(f, nil)
42 if err != nil {
43 t.Fatalf("Listxattr: %v", err)
44 }
45
46 if size <= 0 {
47 t.Fatalf("Listxattr returned an empty list of attributes")
48 }
49
50 buf := make([]byte, size)
51 read, err := unix.Listxattr(f, buf)
52 if err != nil {
53 t.Fatalf("Listxattr: %v", err)
54 }
55
56 xattrs := stringsFromByteSlice(buf[:read])
57
58 xattrWant := xattrName
59 if runtime.GOOS == "freebsd" {
60
61
62 xattrWant = strings.TrimPrefix(xattrWant, "user.")
63 }
64 found := false
65 for _, name := range xattrs {
66 if name == xattrWant {
67 found = true
68 }
69 }
70
71 if !found {
72 t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName)
73 }
74
75
76 size, err = unix.Getxattr(f, xattrName, nil)
77 if err != nil {
78 t.Fatalf("Getxattr: %v", err)
79 }
80
81 if size <= 0 {
82 t.Fatalf("Getxattr returned an empty attribute")
83 }
84
85 xattrDataGet := make([]byte, size)
86 _, err = unix.Getxattr(f, xattrName, xattrDataGet)
87 if err != nil {
88 t.Fatalf("Getxattr: %v", err)
89 }
90
91 got := string(xattrDataGet)
92 if got != xattrDataSet {
93 t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
94 }
95
96 err = unix.Removexattr(f, xattrName)
97 if err != nil {
98 t.Fatalf("Removexattr: %v", err)
99 }
100
101 n := "nonexistent"
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)
105 }
106
107 _, err = unix.Lgetxattr(n, xattrName, nil)
108 if err != unix.ENOENT {
109 t.Errorf("Lgetxattr: %v", err)
110 }
111
112 s := "symlink1"
113 err = os.Symlink(n, s)
114 if err != nil {
115 t.Fatal(err)
116 }
117
118 err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
119 if err != nil {
120
121
122 if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
123 t.Fatalf("Lsetxattr: %v", err)
124 }
125 }
126 }
127
128 func TestFdXattr(t *testing.T) {
129 file, err := os.Create(filepath.Join(t.TempDir(), "TestFdXattr"))
130 if err != nil {
131 t.Fatal(err)
132 }
133 defer file.Close()
134
135 fd := int(file.Fd())
136 xattrName := "user.test"
137 xattrDataSet := "gopher"
138
139 err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
140 if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
141 t.Skip("filesystem does not support extended attributes, skipping test")
142 } else if err != nil {
143 t.Fatalf("Fsetxattr: %v", err)
144 }
145
146
147 size, err := unix.Flistxattr(fd, nil)
148 if err != nil {
149 t.Fatalf("Flistxattr: %v", err)
150 }
151
152 if size <= 0 {
153 t.Fatalf("Flistxattr returned an empty list of attributes")
154 }
155
156 buf := make([]byte, size)
157 read, err := unix.Flistxattr(fd, buf)
158 if err != nil {
159 t.Fatalf("Flistxattr: %v", err)
160 }
161
162 xattrs := stringsFromByteSlice(buf[:read])
163
164 xattrWant := xattrName
165 if runtime.GOOS == "freebsd" {
166
167
168 xattrWant = strings.TrimPrefix(xattrWant, "user.")
169 }
170 found := false
171 for _, name := range xattrs {
172 if name == xattrWant {
173 found = true
174 }
175 }
176
177 if !found {
178 t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName)
179 }
180
181
182 size, err = unix.Fgetxattr(fd, xattrName, nil)
183 if err != nil {
184 t.Fatalf("Fgetxattr: %v", err)
185 }
186
187 if size <= 0 {
188 t.Fatalf("Fgetxattr returned an empty attribute")
189 }
190
191 xattrDataGet := make([]byte, size)
192 _, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
193 if err != nil {
194 t.Fatalf("Fgetxattr: %v", err)
195 }
196
197 got := string(xattrDataGet)
198 if got != xattrDataSet {
199 t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
200 }
201
202 err = unix.Fremovexattr(fd, xattrName)
203 if err != nil {
204 t.Fatalf("Fremovexattr: %v", err)
205 }
206 }
207
View as plain text