Source file src/cmd/vendor/golang.org/x/sys/unix/xattr_bsd.go

     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  }
   242  

View as plain text