github.com/dennwc/btrfs@v0.0.0-20221026161108-3097362dc072/xattr.go (about)

     1  package btrfs
     2  
     3  import (
     4  	"bytes"
     5  	"os"
     6  	"syscall"
     7  )
     8  
     9  const (
    10  	xattrPrefix      = "btrfs."
    11  	xattrCompression = xattrPrefix + "compression"
    12  )
    13  
    14  type Compression string
    15  
    16  const (
    17  	CompressionNone = Compression("")
    18  	LZO             = Compression("lzo")
    19  	ZLIB            = Compression("zlib")
    20  )
    21  
    22  func SetCompression(path string, v Compression) error {
    23  	var value []byte
    24  	if v != CompressionNone {
    25  		var err error
    26  		value, err = syscall.ByteSliceFromString(string(v))
    27  		if err != nil {
    28  			return err
    29  		}
    30  	}
    31  	err := syscall.Setxattr(path, xattrCompression, value, 0)
    32  	if err != nil {
    33  		return &os.PathError{Op: "setxattr", Path: path, Err: err}
    34  	}
    35  	return nil
    36  }
    37  
    38  func GetCompression(path string) (Compression, error) {
    39  	var buf []byte
    40  	for {
    41  		sz, err := syscall.Getxattr(path, xattrCompression, nil)
    42  		if err == syscall.ENODATA || sz == 0 {
    43  			return CompressionNone, nil
    44  		} else if err != nil {
    45  			return CompressionNone, &os.PathError{Op: "getxattr", Path: path, Err: err}
    46  		}
    47  		if cap(buf) < sz {
    48  			buf = make([]byte, sz)
    49  		} else {
    50  			buf = buf[:sz]
    51  		}
    52  		sz, err = syscall.Getxattr(path, xattrCompression, buf)
    53  		if err == syscall.ENODATA {
    54  			return CompressionNone, nil
    55  		} else if err == syscall.ERANGE {
    56  			// xattr changed by someone else, and is larger than our current buffer
    57  			continue
    58  		} else if err != nil {
    59  			return CompressionNone, &os.PathError{Op: "getxattr", Path: path, Err: err}
    60  		}
    61  		buf = buf[:sz]
    62  		break
    63  	}
    64  	buf = bytes.TrimSuffix(buf, []byte{0})
    65  	return Compression(buf), nil
    66  }