- Set and get user property

This commit is contained in:
Faruk Kasumovic 2017-01-16 14:07:17 +01:00
parent 5411c35d4b
commit fe36016d7e
5 changed files with 97 additions and 2 deletions

41
zfs.c
View File

@ -82,6 +82,47 @@ int read_dataset_property(zfs_handle_t *zh, property_list_t *list, int prop) {
return r; return r;
} }
int read_user_property(zfs_handle_t *zh, property_list_t *list, const char *prop) {
nvlist_t *user_props = zfs_get_user_props(zh);
nvlist_t *propval;
zprop_source_t sourcetype;
char *strval;
char *sourceval;
// char source[ZFS_MAX_DATASET_NAME_LEN];
if (nvlist_lookup_nvlist(user_props,
prop, &propval) != 0) {
sourcetype = ZPROP_SRC_NONE;
(void) strncpy(list->source,
"none", sizeof (list->source));
strval = "-";
} else {
verify(nvlist_lookup_string(propval,
ZPROP_VALUE, &strval) == 0);
verify(nvlist_lookup_string(propval,
ZPROP_SOURCE, &sourceval) == 0);
if (strcmp(sourceval,
zfs_get_name(zh)) == 0) {
sourcetype = ZPROP_SRC_LOCAL;
(void) strncpy(list->source,
"local", sizeof (list->source));
} else if (strcmp(sourceval,
ZPROP_SOURCE_VAL_RECVD) == 0) {
sourcetype = ZPROP_SRC_RECEIVED;
(void) strncpy(list->source,
"received", sizeof (list->source));
} else {
sourcetype = ZPROP_SRC_INHERITED;
(void) strncpy(list->source,
sourceval, sizeof (list->source));
}
}
(void) strncpy(list->value,
strval, sizeof (list->value));
return 0;
}
int clear_last_error(libzfs_handle_t *hdl) { int clear_last_error(libzfs_handle_t *hdl) {
zfs_standard_error(hdl, EZFS_SUCCESS, "success"); zfs_standard_error(hdl, EZFS_SUCCESS, "success");
return 0; return 0;

36
zfs.go
View File

@ -278,6 +278,26 @@ func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
return return
} }
func (d *Dataset) GetUserProperty(p string) (prop Property, err error) {
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
}
var plist *C.property_list_t
plist = C.new_property_list()
defer C.free_properties(plist)
csp := C.CString(p)
defer C.free(unsafe.Pointer(csp))
errcode := C.read_user_property(d.list.zh, plist, csp)
if errcode != 0 {
err = LastError()
return
}
prop = Property{Value: C.GoString(&(*plist).value[0]),
Source: C.GoString(&(*plist).source[0])}
return
}
// SetProperty set ZFS dataset property to value. Not all properties can be set, // SetProperty set ZFS dataset property to value. Not all properties can be set,
// some can be set only at creation time and some are read only. // some can be set only at creation time and some are read only.
// Always check if returned error and its description. // Always check if returned error and its description.
@ -300,6 +320,22 @@ func (d *Dataset) SetProperty(p Prop, value string) (err error) {
return return
} }
func (d *Dataset) SetUserProperty(prop, value string) (err error) {
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
}
csValue := C.CString(value)
csProp := C.CString(prop)
errcode := C.zfs_prop_set(d.list.zh, csProp, csValue)
C.free(unsafe.Pointer(csValue))
C.free(unsafe.Pointer(csProp))
if errcode != 0 {
err = LastError()
}
return
}
// Clone - clones the dataset. The target must be of the same type as // Clone - clones the dataset. The target must be of the same type as
// the source. // the source.
func (d *Dataset) Clone(target string, props map[Prop]Property) (rd Dataset, err error) { func (d *Dataset) Clone(target string, props map[Prop]Property) (rd Dataset, err error) {

1
zfs.h
View File

@ -21,6 +21,7 @@ int dataset_list_children(zfs_handle_t *zfs, dataset_list_t **first);
dataset_list_t *dataset_next(dataset_list_t *dataset); dataset_list_t *dataset_next(dataset_list_t *dataset);
int read_dataset_property(zfs_handle_t *zh, property_list_t *list, int prop); int read_dataset_property(zfs_handle_t *zh, property_list_t *list, int prop);
int read_user_property(zfs_handle_t *zh, property_list_t *list, const char* prop);
int clear_last_error(libzfs_handle_t *libzfs); int clear_last_error(libzfs_handle_t *libzfs);

View File

@ -74,7 +74,22 @@ func zfsTestDatasetOpen(t *testing.T) {
t.Error(err) t.Error(err)
return return
} }
d.Close() defer d.Close()
print("PASS\n\n")
println("TEST Set/GetUserProperty(prop, value string) ... ")
var p zfs.Property
// Test set/get user property
if err = d.SetUserProperty("go-libzfs:test", "yes"); err != nil {
t.Error(err)
return
}
if p, err = d.GetUserProperty("go-libzfs:test"); err != nil {
t.Error(err)
return
}
println("go-libzfs:test", " = ",
p.Value)
print("PASS\n\n") print("PASS\n\n")
} }

View File

@ -7,6 +7,8 @@
#define INT_MAX_NAME 256 #define INT_MAX_NAME 256
#define INT_MAX_VALUE 1024 #define INT_MAX_VALUE 1024
#define ZAP_OLDMAXVALUELEN 1024
#define ZFS_MAX_DATASET_NAME_LEN 256
struct zpool_list { struct zpool_list {
zpool_handle_t *zph; zpool_handle_t *zph;
@ -15,7 +17,7 @@ struct zpool_list {
typedef struct property_list { typedef struct property_list {
char value[INT_MAX_VALUE]; char value[INT_MAX_VALUE];
char source[INT_MAX_NAME]; char source[ZFS_MAX_DATASET_NAME_LEN];
int property; int property;
void *pnext; void *pnext;
} property_list_t; } property_list_t;