github.com/bir3/gocompiler@v0.3.205/src/xvendor/golang.org/x/sys/unix/xattr_bsd.go (about)

     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  	destsiz := len(dest)
   164  
   165  	// FreeBSD won't allow you to list xattrs from multiple namespaces
   166  	s, pos := 0, 0
   167  	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
   168  		stmp, e := ListxattrNS(file, nsid, dest[pos:])
   169  
   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
   173  		 *
   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
   176  		 */
   177  		if e != nil {
   178  			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
   179  				continue
   180  			}
   181  			return s, e
   182  		}
   183  
   184  		s += stmp
   185  		pos = s
   186  		if pos > destsiz {
   187  			pos = destsiz
   188  		}
   189  	}
   190  
   191  	return s, nil
   192  }
   193  
   194  func ListxattrNS(file string, nsid int, dest []byte) (sz int, err error) {
   195  	d := initxattrdest(dest, 0)
   196  	destsiz := len(dest)
   197  
   198  	s, e := ExtattrListFile(file, nsid, uintptr(d), destsiz)
   199  	if e != nil {
   200  		return 0, err
   201  	}
   202  
   203  	return s, nil
   204  }
   205  
   206  func Flistxattr(fd int, dest []byte) (sz int, err error) {
   207  	destsiz := len(dest)
   208  
   209  	s, pos := 0, 0
   210  	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
   211  		stmp, e := FlistxattrNS(fd, nsid, dest[pos:])
   212  
   213  		if e != nil {
   214  			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
   215  				continue
   216  			}
   217  			return s, e
   218  		}
   219  
   220  		s += stmp
   221  		pos = s
   222  		if pos > destsiz {
   223  			pos = destsiz
   224  		}
   225  	}
   226  
   227  	return s, nil
   228  }
   229  
   230  func FlistxattrNS(fd int, nsid int, dest []byte) (sz int, err error) {
   231  	d := initxattrdest(dest, 0)
   232  	destsiz := len(dest)
   233  
   234  	s, e := ExtattrListFd(fd, nsid, uintptr(d), destsiz)
   235  	if e != nil {
   236  		return 0, err
   237  	}
   238  
   239  	return s, nil
   240  }
   241  
   242  func Llistxattr(link string, dest []byte) (sz int, err error) {
   243  	destsiz := len(dest)
   244  
   245  	s, pos := 0, 0
   246  	for _, nsid := range [...]int{EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM} {
   247  		stmp, e := LlistxattrNS(link, nsid, dest[pos:])
   248  
   249  		if e != nil {
   250  			if e == EPERM && nsid != EXTATTR_NAMESPACE_USER {
   251  				continue
   252  			}
   253  			return s, e
   254  		}
   255  
   256  		s += stmp
   257  		pos = s
   258  		if pos > destsiz {
   259  			pos = destsiz
   260  		}
   261  	}
   262  
   263  	return s, nil
   264  }
   265  
   266  func LlistxattrNS(link string, nsid int, dest []byte) (sz int, err error) {
   267  	d := initxattrdest(dest, 0)
   268  	destsiz := len(dest)
   269  
   270  	s, e := ExtattrListLink(link, nsid, uintptr(d), destsiz)
   271  	if e != nil {
   272  		return 0, err
   273  	}
   274  
   275  	return s, nil
   276  }