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
//go:build freebsd || netbsd
6
// +build freebsd netbsd
15
// Derive extattr namespace and attribute name
17
func xattrnamespace(fullattr string) (ns int, attr string, err error) {
18
s := strings.IndexByte(fullattr, '.')
20
return -1, "", ENOATTR
23
namespace := fullattr[0:s]
28
return EXTATTR_NAMESPACE_USER, attr, nil
30
return EXTATTR_NAMESPACE_SYSTEM, attr, nil
32
return -1, "", ENOATTR
36
func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
38
return unsafe.Pointer(&dest[idx])
41
// extattr_get_file and extattr_list_file treat NULL differently from
42
// a non-NULL pointer of length zero. Preserve the property of nilness,
43
// even if we can't use dest directly.
44
return unsafe.Pointer(&_zero)
49
// FreeBSD and NetBSD implement their own syscalls to handle extended attributes
51
func Getxattr(file string, attr string, dest []byte) (sz int, err error) {
52
d := initxattrdest(dest, 0)
55
nsid, a, err := xattrnamespace(attr)
60
return ExtattrGetFile(file, nsid, a, uintptr(d), destsize)
63
func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
64
d := initxattrdest(dest, 0)
67
nsid, a, err := xattrnamespace(attr)
72
return ExtattrGetFd(fd, nsid, a, uintptr(d), destsize)
75
func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
76
d := initxattrdest(dest, 0)
79
nsid, a, err := xattrnamespace(attr)
84
return ExtattrGetLink(link, nsid, a, uintptr(d), destsize)
87
// flags are unused on FreeBSD
89
func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
92
d = unsafe.Pointer(&data[0])
96
nsid, a, err := xattrnamespace(attr)
101
_, err = ExtattrSetFd(fd, nsid, a, uintptr(d), datasiz)
105
func Setxattr(file string, attr string, data []byte, flags int) (err error) {
108
d = unsafe.Pointer(&data[0])
112
nsid, a, err := xattrnamespace(attr)
117
_, err = ExtattrSetFile(file, nsid, a, uintptr(d), datasiz)
121
func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
124
d = unsafe.Pointer(&data[0])
128
nsid, a, err := xattrnamespace(attr)
133
_, err = ExtattrSetLink(link, nsid, a, uintptr(d), datasiz)
137
func Removexattr(file string, attr string) (err error) {
138
nsid, a, err := xattrnamespace(attr)
143
err = ExtattrDeleteFile(file, nsid, a)
147
func Fremovexattr(fd int, attr string) (err error) {
148
nsid, a, err := xattrnamespace(attr)
153
err = ExtattrDeleteFd(fd, nsid, a)
157
func Lremovexattr(link string, attr string) (err error) {
158
nsid, a, err := xattrnamespace(attr)
163
err = ExtattrDeleteLink(link, nsid, a)
167
func Listxattr(file string, dest []byte) (sz int, err error) {
170
// FreeBSD won't allow you to list xattrs from multiple namespaces
172
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
173
stmp, e := ListxattrNS(file, nsid, dest[pos:])
175
/* Errors accessing system attrs are ignored so that
176
* we can implement the Linux-like behavior of omitting errors that
177
* we don't have read permissions on
179
* Linux will still error if we ask for user attributes on a file that
180
* we don't have read permissions on, so don't ignore those errors
183
if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
199
func ListxattrNS(file string, nsid int, dest []byte) (sz int, err error) {
200
d := initxattrdest(dest, 0)
203
s, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
211
func Flistxattr(fd int, dest []byte) (sz int, err error) {
215
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
216
stmp, e := FlistxattrNS(fd, nsid, dest[pos:])
219
if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
235
func FlistxattrNS(fd int, nsid int, dest []byte) (sz int, err error) {
236
d := initxattrdest(dest, 0)
239
s, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
247
func Llistxattr(link string, dest []byte) (sz int, err error) {
251
for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
252
stmp, e := LlistxattrNS(link, nsid, dest[pos:])
255
if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
271
func LlistxattrNS(link string, nsid int, dest []byte) (sz int, err error) {
272
d := initxattrdest(dest, 0)
275
s, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)