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