usb-ks

USB Killswitch
git clone git://git.laack.co/usb-ks.git
Log | Files | Refs | README | LICENSE

xattr_bsd.go (5122B)


      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 	} else {
     40 		return unsafe.Pointer(_zero)
     41 	}
     42 }
     43 
     44 // FreeBSD and NetBSD implement their own syscalls to handle extended attributes
     45 
     46 func 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 
     58 func 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 
     70 func 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 
     84 func 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 
    100 func 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 
    116 func 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 
    132 func 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 
    142 func 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 
    152 func 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 
    162 func 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 
    195 func 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 
    219 func 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 }