...

Source file src/github.com/containerd/continuity/sysx/xattr.go

Documentation: github.com/containerd/continuity/sysx

     1  //go:build linux || darwin
     2  // +build linux darwin
     3  
     4  /*
     5     Copyright The containerd Authors.
     6  
     7     Licensed under the Apache License, Version 2.0 (the "License");
     8     you may not use this file except in compliance with the License.
     9     You may obtain a copy of the License at
    10  
    11         http://www.apache.org/licenses/LICENSE-2.0
    12  
    13     Unless required by applicable law or agreed to in writing, software
    14     distributed under the License is distributed on an "AS IS" BASIS,
    15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16     See the License for the specific language governing permissions and
    17     limitations under the License.
    18  */
    19  
    20  package sysx
    21  
    22  import (
    23  	"bytes"
    24  
    25  	"golang.org/x/sys/unix"
    26  )
    27  
    28  // Listxattr calls syscall listxattr and reads all content
    29  // and returns a string array
    30  func Listxattr(path string) ([]string, error) {
    31  	return listxattrAll(path, unix.Listxattr)
    32  }
    33  
    34  // Removexattr calls syscall removexattr
    35  func Removexattr(path string, attr string) (err error) {
    36  	return unix.Removexattr(path, attr)
    37  }
    38  
    39  // Setxattr calls syscall setxattr
    40  func Setxattr(path string, attr string, data []byte, flags int) (err error) {
    41  	return unix.Setxattr(path, attr, data, flags)
    42  }
    43  
    44  // Getxattr calls syscall getxattr
    45  func Getxattr(path, attr string) ([]byte, error) {
    46  	return getxattrAll(path, attr, unix.Getxattr)
    47  }
    48  
    49  // LListxattr lists xattrs, not following symlinks
    50  func LListxattr(path string) ([]string, error) {
    51  	return listxattrAll(path, unix.Llistxattr)
    52  }
    53  
    54  // LRemovexattr removes an xattr, not following symlinks
    55  func LRemovexattr(path string, attr string) (err error) {
    56  	return unix.Lremovexattr(path, attr)
    57  }
    58  
    59  // LSetxattr sets an xattr, not following symlinks
    60  func LSetxattr(path string, attr string, data []byte, flags int) (err error) {
    61  	return unix.Lsetxattr(path, attr, data, flags)
    62  }
    63  
    64  // LGetxattr gets an xattr, not following symlinks
    65  func LGetxattr(path, attr string) ([]byte, error) {
    66  	return getxattrAll(path, attr, unix.Lgetxattr)
    67  }
    68  
    69  const defaultXattrBufferSize = 128
    70  
    71  type listxattrFunc func(path string, dest []byte) (int, error)
    72  
    73  func listxattrAll(path string, listFunc listxattrFunc) ([]string, error) {
    74  	buf := make([]byte, defaultXattrBufferSize)
    75  	n, err := listFunc(path, buf)
    76  	for err == unix.ERANGE {
    77  		// Buffer too small, use zero-sized buffer to get the actual size
    78  		n, err = listFunc(path, []byte{})
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		buf = make([]byte, n)
    83  		n, err = listFunc(path, buf)
    84  	}
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	ps := bytes.Split(bytes.TrimSuffix(buf[:n], []byte{0}), []byte{0})
    90  	var entries []string
    91  	for _, p := range ps {
    92  		if len(p) > 0 {
    93  			entries = append(entries, string(p))
    94  		}
    95  	}
    96  
    97  	return entries, nil
    98  }
    99  
   100  type getxattrFunc func(string, string, []byte) (int, error)
   101  
   102  func getxattrAll(path, attr string, getFunc getxattrFunc) ([]byte, error) {
   103  	buf := make([]byte, defaultXattrBufferSize)
   104  	n, err := getFunc(path, attr, buf)
   105  	for err == unix.ERANGE {
   106  		// Buffer too small, use zero-sized buffer to get the actual size
   107  		n, err = getFunc(path, attr, []byte{})
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		buf = make([]byte, n)
   112  		n, err = getFunc(path, attr, buf)
   113  	}
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	return buf[:n], nil
   118  }
   119  

View as plain text