arnaucube
arnaucube/mirror-to-giteaPublic Self-hosted repository
mirror-to-gitea/vendor/golang.org/x/sys/unix/xattr_bsd.go
vendor/golang.org/x/sys/unix/xattr_bsd.goRaw
  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.
  4
  5//go:build freebsd || netbsd
  6// +build freebsd netbsd
  7
  8package unix
  9
 10import (
 11	"strings"
 12	"unsafe"
 13)
 14
 15// Derive extattr namespace and attribute name
 16
 17func xattrnamespace(fullattr string) (ns int, attr string, err error) {
 18	s := strings.IndexByte(fullattr, '.')
 19	if s == -1 {
 20		return -1, "", ENOATTR
 21	}
 22
 23	namespace := fullattr[0:s]
 24	attr = fullattr[s+1:]
 25
 26	switch namespace {
 27	case "user":
 28		return EXTATTR_NAMESPACE_USER, attr, nil
 29	case "system":
 30		return EXTATTR_NAMESPACE_SYSTEM, attr, nil
 31	default:
 32		return -1, "", ENOATTR
 33	}
 34}
 35
 36func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
 37	if len(dest) > idx {
 38		return unsafe.Pointer(&dest[idx])
 39	} else {
 40		return unsafe.Pointer(_zero)
 41	}
 42}
 43
 44// FreeBSD and NetBSD implement their own syscalls to handle extended attributes
 45
 46func Getxattr(file string, attr string, dest []byte) (sz int, err error) {
 47	d := initxattrdest(dest, 0)
 48	destsize := len(dest)
 49
 50	nsid, a, err := xattrnamespace(attr)
 51	if err != nil {
 52		return -1, err
 53	}
 54
 55	return ExtattrGetFile(file, nsid, a, uintptr(d), destsize)
 56}
 57
 58func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
 59	d := initxattrdest(dest, 0)
 60	destsize := len(dest)
 61
 62	nsid, a, err := xattrnamespace(attr)
 63	if err != nil {
 64		return -1, err
 65	}
 66
 67	return ExtattrGetFd(fd, nsid, a, uintptr(d), destsize)
 68}
 69
 70func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
 71	d := initxattrdest(dest, 0)
 72	destsize := len(dest)
 73
 74	nsid, a, err := xattrnamespace(attr)
 75	if err != nil {
 76		return -1, err
 77	}
 78
 79	return ExtattrGetLink(link, nsid, a, uintptr(d), destsize)
 80}
 81
 82// flags are unused on FreeBSD
 83
 84func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
 85	var d unsafe.Pointer
 86	if len(data) > 0 {
 87		d = unsafe.Pointer(&data[0])
 88	}
 89	datasiz := len(data)
 90
 91	nsid, a, err := xattrnamespace(attr)
 92	if err != nil {
 93		return
 94	}
 95
 96	_, err = ExtattrSetFd(fd, nsid, a, uintptr(d), datasiz)
 97	return
 98}
 99
100func Setxattr(file string, attr string, data []byte, flags int) (err error) {
101	var d unsafe.Pointer
102	if len(data) > 0 {
103		d = unsafe.Pointer(&data[0])
104	}
105	datasiz := len(data)
106
107	nsid, a, err := xattrnamespace(attr)
108	if err != nil {
109		return
110	}
111
112	_, err = ExtattrSetFile(file, nsid, a, uintptr(d), datasiz)
113	return
114}
115
116func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
117	var d unsafe.Pointer
118	if len(data) > 0 {
119		d = unsafe.Pointer(&data[0])
120	}
121	datasiz := len(data)
122
123	nsid, a, err := xattrnamespace(attr)
124	if err != nil {
125		return
126	}
127
128	_, err = ExtattrSetLink(link, nsid, a, uintptr(d), datasiz)
129	return
130}
131
132func Removexattr(file string, attr string) (err error) {
133	nsid, a, err := xattrnamespace(attr)
134	if err != nil {
135		return
136	}
137
138	err = ExtattrDeleteFile(file, nsid, a)
139	return
140}
141
142func Fremovexattr(fd int, attr string) (err error) {
143	nsid, a, err := xattrnamespace(attr)
144	if err != nil {
145		return
146	}
147
148	err = ExtattrDeleteFd(fd, nsid, a)
149	return
150}
151
152func Lremovexattr(link string, attr string) (err error) {
153	nsid, a, err := xattrnamespace(attr)
154	if err != nil {
155		return
156	}
157
158	err = ExtattrDeleteLink(link, nsid, a)
159	return
160}
161
162func Listxattr(file string, dest []byte) (sz int, err error) {
163	d := initxattrdest(dest, 0)
164	destsiz := len(dest)
165
166	// FreeBSD won't allow you to list xattrs from multiple namespaces
167	s := 0
168	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
169		stmp, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
170
171		/* Errors accessing system attrs are ignored so that
172		 * we can implement the Linux-like behavior of omitting errors that
173		 * we don't have read permissions on
174		 *
175		 * Linux will still error if we ask for user attributes on a file that
176		 * we don't have read permissions on, so don't ignore those errors
177		 */
178		if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
179			continue
180		} else if e != nil {
181			return s, e
182		}
183
184		s += stmp
185		destsiz -= s
186		if destsiz < 0 {
187			destsiz = 0
188		}
189		d = initxattrdest(dest, s)
190	}
191
192	return s, nil
193}
194
195func Flistxattr(fd int, dest []byte) (sz int, err error) {
196	d := initxattrdest(dest, 0)
197	destsiz := len(dest)
198
199	s := 0
200	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
201		stmp, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
202		if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
203			continue
204		} else if e != nil {
205			return s, e
206		}
207
208		s += stmp
209		destsiz -= s
210		if destsiz < 0 {
211			destsiz = 0
212		}
213		d = initxattrdest(dest, s)
214	}
215
216	return s, nil
217}
218
219func Llistxattr(link string, dest []byte) (sz int, err error) {
220	d := initxattrdest(dest, 0)
221	destsiz := len(dest)
222
223	s := 0
224	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
225		stmp, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
226		if e != nil && e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
227			continue
228		} else if e != nil {
229			return s, e
230		}
231
232		s += stmp
233		destsiz -= s
234		if destsiz < 0 {
235			destsiz = 0
236		}
237		d = initxattrdest(dest, s)
238	}
239
240	return s, nil
241}