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 }