// function that lists all the xattrs for an object, since xattrs are // a k-v pair, this function returns a map of k-v pairs on // success, error code on failure func (ioctx *IOContext) ListXattrs(oid string) (map[string][]byte, error) { c_oid := C.CString(oid) defer C.free(unsafe.Pointer(c_oid)) var it C.rados_xattrs_iter_t ret := C.rados_getxattrs(ioctx.ioctx, c_oid, &it) if ret < 0 { return nil, GetRadosError(ret) } defer func() { C.rados_getxattrs_end(it) }() m := make(map[string][]byte) for { var c_name, c_val *C.char var c_len C.size_t defer C.free(unsafe.Pointer(c_name)) defer C.free(unsafe.Pointer(c_val)) ret := C.rados_getxattrs_next(it, &c_name, &c_val, &c_len) if ret < 0 { return nil, GetRadosError(ret) } // rados api returns a null name,val & 0-length upon // end of iteration if c_name == nil { return m, nil // stop iteration } m[C.GoString(c_name)] = C.GoBytes(unsafe.Pointer(c_val), (C.int)(c_len)) } }
// Next returns the next extended attribute. This returns an error when there are no more attributes. func (i *AttributeList) Next() (name string, value io.Reader, err error) { var n *C.char var v *C.char var length C.size_t ret := C.rados_getxattrs_next(i.iterator, &n, &v, &length) if errs := toRadosError(ret); errs != nil { errs.Message = "Unable to get next attribute" err = errs } else if length == 0 { errs := toRadosError(-1) errs.Message = "End of attribute list reached" err = errs } else { name = C.GoString(n) value = bufToReader(v, C.int(length)) } return }
func (ioctx *IOContext) ReadTaggedFull(oid string, tagName string, data []byte, offset int) (n int, tag []byte, err error) { if len(data) == 0 { return 0, nil, nil } c_oid := C.CString(oid) c_tagName := C.CString(tagName) defer C.free(unsafe.Pointer(c_oid)) defer C.free(unsafe.Pointer(c_tagName)) var size C.size_t var rval_read C.int var rval_attr C.int var it C.rados_xattrs_iter_t op := C.rados_create_read_op() defer func() { C.rados_release_read_op(op) }() C.rados_read_op_read( op, (C.uint64_t)(offset), (C.size_t)(len(data)), (*C.char)(unsafe.Pointer(&data[0])), &size, &rval_read) C.rados_read_op_getxattrs( op, &it, &rval_attr) ret := C.rados_read_op_operate(op, ioctx.ioctx, c_oid, 0) if ret < 0 { return 0, nil, GetRadosError(ret) } if rval_read < 0 { return 0, nil, GetRadosError(rval_read) } if rval_attr < 0 { return 0, nil, GetRadosError(ret) } defer func() { C.rados_getxattrs_end(it) }() for { var c_name, c_val *C.char var c_len C.size_t defer C.free(unsafe.Pointer(c_name)) defer C.free(unsafe.Pointer(c_val)) ret := C.rados_getxattrs_next(it, &c_name, &c_val, &c_len) if ret < 0 { return int(size), nil, GetRadosError(ret) } // rados api returns a null name,val & 0-length upon // end of iteration if c_name == nil { return int(size), nil, GetRadosError(ret) } if tagName == C.GoString(c_name) { tag = C.GoBytes(unsafe.Pointer(c_val), (C.int)(c_len)) break } } return int(size), tag, nil }