package cephfs /* #cgo LDFLAGS: -lcephfs #cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64 #define _GNU_SOURCE #include #include */ import "C" import ( "unsafe" "github.com/ceph/go-ceph/internal/cutil" "github.com/ceph/go-ceph/internal/retry" ) // SetXattr sets an extended attribute on the file at the supplied path. // // NOTE: Attempting to set an xattr value with an empty value may cause // the xattr to be unset. Please refer to https://tracker.ceph.com/issues/46084 // // Implements: // int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, // const void *value, size_t size, int flags); func (mount *MountInfo) SetXattr(path, name string, value []byte, flags XattrFlags) error { if err := mount.validate(); err != nil { return err } if name == "" { return errInvalid } var vptr unsafe.Pointer if len(value) > 0 { vptr = unsafe.Pointer(&value[0]) } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.ceph_setxattr( mount.mount, cPath, cName, vptr, C.size_t(len(value)), C.int(flags)) return getError(ret) } // GetXattr gets an extended attribute from the file at the supplied path. // // Implements: // int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, // void *value, size_t size); func (mount *MountInfo) GetXattr(path, name string) ([]byte, error) { if err := mount.validate(); err != nil { return nil, err } if name == "" { return nil, errInvalid } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) var ( ret C.int err error buf []byte ) // range from 1k to 64KiB retry.WithSizes(1024, 1<<16, func(size int) retry.Hint { buf = make([]byte, size) ret = C.ceph_getxattr( mount.mount, cPath, cName, unsafe.Pointer(&buf[0]), C.size_t(size)) err = getErrorIfNegative(ret) return retry.DoubleSize.If(err == errRange) }) if err != nil { return nil, err } return buf[:ret], nil } // ListXattr returns a slice containing strings for the name of each xattr set // on the file at the supplied path. // // Implements: // int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size); func (mount *MountInfo) ListXattr(path string) ([]string, error) { if err := mount.validate(); err != nil { return nil, err } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) var ( ret C.int err error buf []byte ) // range from 1k to 64KiB retry.WithSizes(1024, 1<<16, func(size int) retry.Hint { buf = make([]byte, size) ret = C.ceph_listxattr( mount.mount, cPath, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(size)) err = getErrorIfNegative(ret) return retry.DoubleSize.If(err == errRange) }) if err != nil { return nil, err } names := cutil.SplitSparseBuffer(buf[:ret]) return names, nil } // RemoveXattr removes the named xattr from the open file. // // Implements: // int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name); func (mount *MountInfo) RemoveXattr(path, name string) error { if err := mount.validate(); err != nil { return err } if name == "" { return errInvalid } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.ceph_removexattr( mount.mount, cPath, cName) return getError(ret) } // LsetXattr sets an extended attribute on the file at the supplied path. // // NOTE: Attempting to set an xattr value with an empty value may cause // the xattr to be unset. Please refer to https://tracker.ceph.com/issues/46084 // // Implements: // int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, // const void *value, size_t size, int flags); func (mount *MountInfo) LsetXattr(path, name string, value []byte, flags XattrFlags) error { if err := mount.validate(); err != nil { return err } if name == "" { return errInvalid } var vptr unsafe.Pointer if len(value) > 0 { vptr = unsafe.Pointer(&value[0]) } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.ceph_lsetxattr( mount.mount, cPath, cName, vptr, C.size_t(len(value)), C.int(flags)) return getError(ret) } // LgetXattr gets an extended attribute from the file at the supplied path. // // Implements: // int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, // void *value, size_t size); func (mount *MountInfo) LgetXattr(path, name string) ([]byte, error) { if err := mount.validate(); err != nil { return nil, err } if name == "" { return nil, errInvalid } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) var ( ret C.int err error buf []byte ) // range from 1k to 64KiB retry.WithSizes(1024, 1<<16, func(size int) retry.Hint { buf = make([]byte, size) ret = C.ceph_lgetxattr( mount.mount, cPath, cName, unsafe.Pointer(&buf[0]), C.size_t(size)) err = getErrorIfNegative(ret) return retry.DoubleSize.If(err == errRange) }) if err != nil { return nil, err } return buf[:ret], nil } // LlistXattr returns a slice containing strings for the name of each xattr set // on the file at the supplied path. // // Implements: // int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size); func (mount *MountInfo) LlistXattr(path string) ([]string, error) { if err := mount.validate(); err != nil { return nil, err } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) var ( ret C.int err error buf []byte ) // range from 1k to 64KiB retry.WithSizes(1024, 1<<16, func(size int) retry.Hint { buf = make([]byte, size) ret = C.ceph_llistxattr( mount.mount, cPath, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(size)) err = getErrorIfNegative(ret) return retry.DoubleSize.If(err == errRange) }) if err != nil { return nil, err } names := cutil.SplitSparseBuffer(buf[:ret]) return names, nil } // LremoveXattr removes the named xattr from the open file. // // Implements: // int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name); func (mount *MountInfo) LremoveXattr(path, name string) error { if err := mount.validate(); err != nil { return err } if name == "" { return errInvalid } cPath := C.CString(path) defer C.free(unsafe.Pointer(cPath)) cName := C.CString(name) defer C.free(unsafe.Pointer(cName)) ret := C.ceph_lremovexattr( mount.mount, cPath, cName) return getError(ret) }