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 switch runtime.GOOS {
60 case "freebsd", "netbsd":
61
62
63 xattrWant = strings.TrimPrefix(xattrWant, "user.")
64 }
65 found := false
66 for _, name := range xattrs {
67 if name == xattrWant {
68 found = true
69 break
70 }
71 }
72
73 if !found {
74 t.Errorf("Listxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
75 }
76
77
78 size, err = unix.Getxattr(f, xattrName, nil)
79 if err != nil {
80 t.Fatalf("Getxattr: %v", err)
81 }
82
83 if size <= 0 {
84 t.Fatalf("Getxattr returned an empty attribute")
85 }
86
87 xattrDataGet := make([]byte, size)
88 _, err = unix.Getxattr(f, xattrName, xattrDataGet)
89 if err != nil {
90 t.Fatalf("Getxattr: %v", err)
91 }
92
93 got := string(xattrDataGet)
94 if got != xattrDataSet {
95 t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
96 }
97
98 err = unix.Removexattr(f, xattrName)
99 if err != nil {
100 t.Fatalf("Removexattr: %v", err)
101 }
102
103 n := "nonexistent"
104 err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
105 if err != unix.ENOENT {
106 t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
107 }
108
109 _, err = unix.Lgetxattr(n, xattrName, nil)
110 if err != unix.ENOENT {
111 t.Errorf("Lgetxattr: %v", err)
112 }
113
114 s := "symlink1"
115 err = os.Symlink(n, s)
116 if err != nil {
117 t.Fatal(err)
118 }
119
120 err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
121 if err != nil {
122
123
124 if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
125 t.Fatalf("Lsetxattr: %v", err)
126 }
127 }
128 }
129
130 func TestFdXattr(t *testing.T) {
131 file, err := os.Create(filepath.Join(t.TempDir(), "TestFdXattr"))
132 if err != nil {
133 t.Fatal(err)
134 }
135 defer file.Close()
136
137 fd := int(file.Fd())
138 xattrName := "user.test"
139 xattrDataSet := "gopher"
140
141 err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
142 if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
143 t.Skip("filesystem does not support extended attributes, skipping test")
144 } else if err != nil {
145 t.Fatalf("Fsetxattr: %v", err)
146 }
147
148
149 size, err := unix.Flistxattr(fd, nil)
150 if err != nil {
151 t.Fatalf("Flistxattr: %v", err)
152 }
153
154 if size <= 0 {
155 t.Fatalf("Flistxattr returned an empty list of attributes")
156 }
157
158 buf := make([]byte, size)
159 read, err := unix.Flistxattr(fd, buf)
160 if err != nil {
161 t.Fatalf("Flistxattr: %v", err)
162 }
163
164 xattrs := stringsFromByteSlice(buf[:read])
165
166 xattrWant := xattrName
167 switch runtime.GOOS {
168 case "freebsd", "netbsd":
169
170
171 xattrWant = strings.TrimPrefix(xattrWant, "user.")
172 }
173 found := false
174 for _, name := range xattrs {
175 if name == xattrWant {
176 found = true
177 break
178 }
179 }
180
181 if !found {
182 t.Errorf("Flistxattr did not return previously set attribute %q in attributes %v", xattrName, xattrs)
183 }
184
185
186 size, err = unix.Fgetxattr(fd, xattrName, nil)
187 if err != nil {
188 t.Fatalf("Fgetxattr: %v", err)
189 }
190
191 if size <= 0 {
192 t.Fatalf("Fgetxattr returned an empty attribute")
193 }
194
195 xattrDataGet := make([]byte, size)
196 _, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
197 if err != nil {
198 t.Fatalf("Fgetxattr: %v", err)
199 }
200
201 got := string(xattrDataGet)
202 if got != xattrDataSet {
203 t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
204 }
205
206 err = unix.Fremovexattr(fd, xattrName)
207 if err != nil {
208 t.Fatalf("Fremovexattr: %v", err)
209 }
210 }
211
View as plain text