github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/system/xattrs_linux.go (about)

     1  package system
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  )
     7  
     8  var _zero uintptr
     9  
    10  // Returns the size of xattrs and nil error
    11  // Requires path, takes allocated []byte or nil as last argument
    12  func Llistxattr(path string, dest []byte) (size int, err error) {
    13  	pathBytes, err := syscall.BytePtrFromString(path)
    14  	if err != nil {
    15  		return -1, err
    16  	}
    17  	var newpathBytes unsafe.Pointer
    18  	if len(dest) > 0 {
    19  		newpathBytes = unsafe.Pointer(&dest[0])
    20  	} else {
    21  		newpathBytes = unsafe.Pointer(&_zero)
    22  	}
    23  
    24  	_size, _, errno := syscall.Syscall6(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(newpathBytes), uintptr(len(dest)), 0, 0, 0)
    25  	size = int(_size)
    26  	if errno != 0 {
    27  		return -1, errno
    28  	}
    29  
    30  	return size, nil
    31  }
    32  
    33  // Returns a []byte slice if the xattr is set and nil otherwise
    34  // Requires path and its attribute as arguments
    35  func Lgetxattr(path string, attr string) ([]byte, error) {
    36  	var sz int
    37  	pathBytes, err := syscall.BytePtrFromString(path)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	attrBytes, err := syscall.BytePtrFromString(attr)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	// Start with a 128 length byte array
    47  	sz = 128
    48  	dest := make([]byte, sz)
    49  	destBytes := unsafe.Pointer(&dest[0])
    50  	_sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
    51  
    52  	switch {
    53  	case errno == syscall.ENODATA:
    54  		return nil, errno
    55  	case errno == syscall.ENOTSUP:
    56  		return nil, errno
    57  	case errno == syscall.ERANGE:
    58  		// 128 byte array might just not be good enough,
    59  		// A dummy buffer is used ``uintptr(0)`` to get real size
    60  		// of the xattrs on disk
    61  		_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0)
    62  		sz = int(_sz)
    63  		if sz < 0 {
    64  			return nil, errno
    65  		}
    66  		dest = make([]byte, sz)
    67  		destBytes := unsafe.Pointer(&dest[0])
    68  		_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
    69  		if errno != 0 {
    70  			return nil, errno
    71  		}
    72  	case errno != 0:
    73  		return nil, errno
    74  	}
    75  	sz = int(_sz)
    76  	return dest[:sz], nil
    77  }
    78  
    79  func Lsetxattr(path string, attr string, data []byte, flags int) error {
    80  	pathBytes, err := syscall.BytePtrFromString(path)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	attrBytes, err := syscall.BytePtrFromString(attr)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	var dataBytes unsafe.Pointer
    89  	if len(data) > 0 {
    90  		dataBytes = unsafe.Pointer(&data[0])
    91  	} else {
    92  		dataBytes = unsafe.Pointer(&_zero)
    93  	}
    94  	_, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
    95  	if errno != 0 {
    96  		return errno
    97  	}
    98  	return nil
    99  }