gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

xattr_bsd.go (5818B)


      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 
      8 package unix
      9 
     10 import (
     11 	"strings"
     12 	"unsafe"
     13 )
     14 
     15 // Derive extattr namespace and attribute name
     16 
     17 func 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 
     36 func initxattrdest(dest []byte, idx int) (d unsafe.Pointer) {
     37 	if len(dest) > idx {
     38 		return unsafe.Pointer(&dest[idx])
     39 	}
     40 	if dest != nil {
     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)
     45 	}
     46 	return nil
     47 }
     48 
     49 // FreeBSD and NetBSD implement their own syscalls to handle extended attributes
     50 
     51 func Getxattr(file string, attr string, dest []byte) (sz int, err error) {
     52 	d := initxattrdest(dest, 0)
     53 	destsize := len(dest)
     54 
     55 	nsid, a, err := xattrnamespace(attr)
     56 	if err != nil {
     57 		return -1, err
     58 	}
     59 
     60 	return ExtattrGetFile(file, nsid, a, uintptr(d), destsize)
     61 }
     62 
     63 func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
     64 	d := initxattrdest(dest, 0)
     65 	destsize := len(dest)
     66 
     67 	nsid, a, err := xattrnamespace(attr)
     68 	if err != nil {
     69 		return -1, err
     70 	}
     71 
     72 	return ExtattrGetFd(fd, nsid, a, uintptr(d), destsize)
     73 }
     74 
     75 func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
     76 	d := initxattrdest(dest, 0)
     77 	destsize := len(dest)
     78 
     79 	nsid, a, err := xattrnamespace(attr)
     80 	if err != nil {
     81 		return -1, err
     82 	}
     83 
     84 	return ExtattrGetLink(link, nsid, a, uintptr(d), destsize)
     85 }
     86 
     87 // flags are unused on FreeBSD
     88 
     89 func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
     90 	var d unsafe.Pointer
     91 	if len(data) > 0 {
     92 		d = unsafe.Pointer(&data[0])
     93 	}
     94 	datasiz := len(data)
     95 
     96 	nsid, a, err := xattrnamespace(attr)
     97 	if err != nil {
     98 		return
     99 	}
    100 
    101 	_, err = ExtattrSetFd(fd, nsid, a, uintptr(d), datasiz)
    102 	return
    103 }
    104 
    105 func Setxattr(file string, attr string, data []byte, flags int) (err error) {
    106 	var d unsafe.Pointer
    107 	if len(data) > 0 {
    108 		d = unsafe.Pointer(&data[0])
    109 	}
    110 	datasiz := len(data)
    111 
    112 	nsid, a, err := xattrnamespace(attr)
    113 	if err != nil {
    114 		return
    115 	}
    116 
    117 	_, err = ExtattrSetFile(file, nsid, a, uintptr(d), datasiz)
    118 	return
    119 }
    120 
    121 func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
    122 	var d unsafe.Pointer
    123 	if len(data) > 0 {
    124 		d = unsafe.Pointer(&data[0])
    125 	}
    126 	datasiz := len(data)
    127 
    128 	nsid, a, err := xattrnamespace(attr)
    129 	if err != nil {
    130 		return
    131 	}
    132 
    133 	_, err = ExtattrSetLink(link, nsid, a, uintptr(d), datasiz)
    134 	return
    135 }
    136 
    137 func Removexattr(file string, attr string) (err error) {
    138 	nsid, a, err := xattrnamespace(attr)
    139 	if err != nil {
    140 		return
    141 	}
    142 
    143 	err = ExtattrDeleteFile(file, nsid, a)
    144 	return
    145 }
    146 
    147 func Fremovexattr(fd int, attr string) (err error) {
    148 	nsid, a, err := xattrnamespace(attr)
    149 	if err != nil {
    150 		return
    151 	}
    152 
    153 	err = ExtattrDeleteFd(fd, nsid, a)
    154 	return
    155 }
    156 
    157 func Lremovexattr(link string, attr string) (err error) {
    158 	nsid, a, err := xattrnamespace(attr)
    159 	if err != nil {
    160 		return
    161 	}
    162 
    163 	err = ExtattrDeleteLink(link, nsid, a)
    164 	return
    165 }
    166 
    167 func Listxattr(file string, dest []byte) (sz int, err error) {
    168 	destsiz := len(dest)
    169 
    170 	// FreeBSD won't allow you to list xattrs from multiple namespaces
    171 	s, pos := 0, 0
    172 	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
    173 		stmp, e := ListxattrNS(file, nsid, dest[pos:])
    174 
    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
    178 		 *
    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
    181 		 */
    182 		if e != nil {
    183 			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
    184 				continue
    185 			}
    186 			return s, e
    187 		}
    188 
    189 		s += stmp
    190 		pos = s
    191 		if pos > destsiz {
    192 			pos = destsiz
    193 		}
    194 	}
    195 
    196 	return s, nil
    197 }
    198 
    199 func ListxattrNS(file string, nsid int, dest []byte) (sz int, err error) {
    200 	d := initxattrdest(dest, 0)
    201 	destsiz := len(dest)
    202 
    203 	s, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
    204 	if e != nil {
    205 		return 0, err
    206 	}
    207 
    208 	return s, nil
    209 }
    210 
    211 func Flistxattr(fd int, dest []byte) (sz int, err error) {
    212 	destsiz := len(dest)
    213 
    214 	s, pos := 0, 0
    215 	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
    216 		stmp, e := FlistxattrNS(fd, nsid, dest[pos:])
    217 
    218 		if e != nil {
    219 			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
    220 				continue
    221 			}
    222 			return s, e
    223 		}
    224 
    225 		s += stmp
    226 		pos = s
    227 		if pos > destsiz {
    228 			pos = destsiz
    229 		}
    230 	}
    231 
    232 	return s, nil
    233 }
    234 
    235 func FlistxattrNS(fd int, nsid int, dest []byte) (sz int, err error) {
    236 	d := initxattrdest(dest, 0)
    237 	destsiz := len(dest)
    238 
    239 	s, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
    240 	if e != nil {
    241 		return 0, err
    242 	}
    243 
    244 	return s, nil
    245 }
    246 
    247 func Llistxattr(link string, dest []byte) (sz int, err error) {
    248 	destsiz := len(dest)
    249 
    250 	s, pos := 0, 0
    251 	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
    252 		stmp, e := LlistxattrNS(link, nsid, dest[pos:])
    253 
    254 		if e != nil {
    255 			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
    256 				continue
    257 			}
    258 			return s, e
    259 		}
    260 
    261 		s += stmp
    262 		pos = s
    263 		if pos > destsiz {
    264 			pos = destsiz
    265 		}
    266 	}
    267 
    268 	return s, nil
    269 }
    270 
    271 func LlistxattrNS(link string, nsid int, dest []byte) (sz int, err error) {
    272 	d := initxattrdest(dest, 0)
    273 	destsiz := len(dest)
    274 
    275 	s, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
    276 	if e != nil {
    277 		return 0, err
    278 	}
    279 
    280 	return s, nil
    281 }