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 freebsd netbsd
14 // Derive extattr namespace and attribute name
16 func xattrnamespace(fullattr string) (ns int, attr string, err error) {
17 s := strings.IndexByte(fullattr, '.')
19 return -1, "", ENOATTR
22 namespace := fullattr[0:s]
27 return EXTATTR_NAMESPACE_USER, attr, nil
29 return EXTATTR_NAMESPACE_SYSTEM, attr, nil
31 return -1, "", ENOATTR
35 func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
37 return unsafe.Pointer(&dest[idx])
39 return unsafe.Pointer(_zero)
43 // FreeBSD and NetBSD implement their own syscalls to handle extended attributes
45 func Getxattr(file string, attr string, dest []byte) (sz int, err error) {
46 d := initxattrdest(dest, 0)
49 nsid, a, err := xattrnamespace(attr)
54 return ExtattrGetFile(file, nsid, a, uintptr(d), destsize)
57 func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
58 d := initxattrdest(dest, 0)
61 nsid, a, err := xattrnamespace(attr)
66 return ExtattrGetFd(fd, nsid, a, uintptr(d), destsize)
69 func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
70 d := initxattrdest(dest, 0)
73 nsid, a, err := xattrnamespace(attr)
78 return ExtattrGetLink(link, nsid, a, uintptr(d), destsize)
81 // flags are unused on FreeBSD
83 func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
86 d = unsafe.Pointer(&data[0])
90 nsid, a, err := xattrnamespace(attr)
95 _, err = ExtattrSetFd(fd, nsid, a, uintptr(d), datasiz)
99 func Setxattr(file string, attr string, data []byte, flags int) (err error) {
102 d = unsafe.Pointer(&data[0])
106 nsid, a, err := xattrnamespace(attr)
111 _, err = ExtattrSetFile(file, nsid, a, uintptr(d), datasiz)
115 func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
118 d = unsafe.Pointer(&data[0])
122 nsid, a, err := xattrnamespace(attr)
127 _, err = ExtattrSetLink(link, nsid, a, uintptr(d), datasiz)
131 func Removexattr(file string, attr string) (err error) {
132 nsid, a, err := xattrnamespace(attr)
137 err = ExtattrDeleteFile(file, nsid, a)
141 func Fremovexattr(fd int, attr string) (err error) {
142 nsid, a, err := xattrnamespace(attr)
147 err = ExtattrDeleteFd(fd, nsid, a)
151 func Lremovexattr(link string, attr string) (err error) {
152 nsid, a, err := xattrnamespace(attr)
157 err = ExtattrDeleteLink(link, nsid, a)
161 func Listxattr(file string, dest []byte) (sz int, err error) {
162 d := initxattrdest(dest, 0)
165 // FreeBSD won't allow you to list xattrs from multiple namespaces
167 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
168 stmp, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
170 /* Errors accessing system attrs are ignored so that
171 * we can implement the Linux-like behavior of omitting errors that
172 * we don't have read permissions on
174 * Linux will still error if we ask for user attributes on a file that
175 * we don't have read permissions on, so don't ignore those errors
177 if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
188 d = initxattrdest(dest, s)
194 func Flistxattr(fd int, dest []byte) (sz int, err error) {
195 d := initxattrdest(dest, 0)
199 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
200 stmp, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
201 if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
212 d = initxattrdest(dest, s)
218 func Llistxattr(link string, dest []byte) (sz int, err error) {
219 d := initxattrdest(dest, 0)
223 for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
224 stmp, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
225 if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
236 d = initxattrdest(dest, s)