...

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

View as plain text