1*b2d2f356SSara Hartse--
2*b2d2f356SSara Hartse-- This file and its contents are supplied under the terms of the
3*b2d2f356SSara Hartse-- Common Development and Distribution License ("CDDL"), version 1.0.
4*b2d2f356SSara Hartse-- You may only use this file in accordance with the terms of version
5*b2d2f356SSara Hartse-- 1.0 of the CDDL.
6*b2d2f356SSara Hartse--
7*b2d2f356SSara Hartse-- A full copy of the text of the CDDL should have accompanied this
8*b2d2f356SSara Hartse-- source.  A copy of the CDDL is also available via the Internet at
9*b2d2f356SSara Hartse-- http://www.illumos.org/license/CDDL.
10*b2d2f356SSara Hartse--
11*b2d2f356SSara Hartse
12*b2d2f356SSara Hartse--
13*b2d2f356SSara Hartse-- Copyright (c) 2017 by Delphix. All rights reserved.
14*b2d2f356SSara Hartse-- Copyright 2020 Joyent, Inc.
15*b2d2f356SSara Hartse--
16*b2d2f356SSara Hartse
17*b2d2f356SSara Hartsearg = ...
18*b2d2f356SSara Hartsefs = arg["argv"][1]
19*b2d2f356SSara Hartse
20*b2d2f356SSara Hartse-- values from zfs.h
21*b2d2f356SSara Hartsemaxname = 256       -- ZAP_MAXNAMELEN
22*b2d2f356SSara Hartsemaxvalue = 8192     -- ZAP_MAXVALUELEN
23*b2d2f356SSara Hartse
24*b2d2f356SSara Hartsepos_props = {}
25*b2d2f356SSara Hartseneg_props = {}
26*b2d2f356SSara Hartse
27*b2d2f356SSara Hartse-- In lua, strings are immutable, so to avoid a bunch of copies, we
28*b2d2f356SSara Hartse-- build the value in a table and use concat (which appears to be the
29*b2d2f356SSara Hartse-- recommended method for such things).
30*b2d2f356SSara Hartselargeprop = {}
31*b2d2f356SSara Hartsefor i = 0,maxvalue,8
32*b2d2f356SSara Hartsedo
33*b2d2f356SSara Hartse    table.insert(largeprop, "aaaaaaaa")
34*b2d2f356SSara Hartseend
35*b2d2f356SSara Hartse-- add an extra character so we spill over the limit
36*b2d2f356SSara Hartsetable.insert(largeprop, "b")
37*b2d2f356SSara Hartse
38*b2d2f356SSara Hartselargepropv = table.concat(largeprop)
39*b2d2f356SSara Hartse
40*b2d2f356SSara Hartselargepropname = { "b:" }
41*b2d2f356SSara Hartsefor i = 0,maxname,8
42*b2d2f356SSara Hartsedo
43*b2d2f356SSara Hartse    table.insert(largepropname, "aaaaaaaa")
44*b2d2f356SSara Hartseend
45*b2d2f356SSara Hartselargepropnamev = table.concat(largepropname)
46*b2d2f356SSara Hartse
47*b2d2f356SSara Hartsepos_props["a:prop"] = {"hello"}
48*b2d2f356SSara Hartse
49*b2d2f356SSara Hartse-- For neg_props, an optional expected error value can be added after the
50*b2d2f356SSara Hartse-- property value as seen below.
51*b2d2f356SSara Hartseneg_props["notaproperty"] = {"hello", EINVAL}
52*b2d2f356SSara Hartseneg_props["a:very.long.property.value"] = { largepropv, E2BIG }
53*b2d2f356SSara Hartseneg_props[largepropnamev] = {"greetings", ENAMETOOLONG }
54*b2d2f356SSara Hartse
55*b2d2f356SSara Hartse-- non-user properties aren't currently supported
56*b2d2f356SSara Hartse-- Even if they were, the argument must be a string due to requirements of
57*b2d2f356SSara Hartse-- the ZCP api.
58*b2d2f356SSara Hartseneg_props["mountpoint"] = {"/foo/bar"}
59*b2d2f356SSara Hartseneg_props["copies"] = { "2" }
60*b2d2f356SSara Hartse
61*b2d2f356SSara Hartse-- read-only properties should never succeed
62*b2d2f356SSara Hartseneg_props["guid"] = { "12345" }
63*b2d2f356SSara Hartse
64*b2d2f356SSara Hartseset_fail = {}
65*b2d2f356SSara Hartseval_fail = {}
66*b2d2f356SSara Hartse
67*b2d2f356SSara Hartse-- Test properties that should work
68*b2d2f356SSara Hartsefor prop, values in pairs(pos_props) do
69*b2d2f356SSara Hartse    for i, val in ipairs(values) do
70*b2d2f356SSara Hartse        old_val, src = zfs.get_prop(fs, prop)
71*b2d2f356SSara Hartse
72*b2d2f356SSara Hartse        -- Attempt to set the property to the specified value
73*b2d2f356SSara Hartse        err = zfs.sync.set_prop(fs, prop, val)
74*b2d2f356SSara Hartse
75*b2d2f356SSara Hartse        if (err ~= 0) then
76*b2d2f356SSara Hartse            set_fail[prop] = err -- tuple of prop, val that resulted in error
77*b2d2f356SSara Hartse        else
78*b2d2f356SSara Hartse            -- use get_prop to check that the set took effect
79*b2d2f356SSara Hartse            new_val, src = zfs.get_prop(fs, prop)
80*b2d2f356SSara Hartse            if (tostring(new_val) ~= tostring(val)) then
81*b2d2f356SSara Hartse                val_fail[prop] = new_val
82*b2d2f356SSara Hartse            end
83*b2d2f356SSara Hartse
84*b2d2f356SSara Hartse            -- We modified the prop, restore old value (if one existed)
85*b2d2f356SSara Hartse            if (old_val ~= nil) then
86*b2d2f356SSara Hartse                err = zfs.sync.set_prop(fs, prop, old_val)
87*b2d2f356SSara Hartse                if (err ~= 0) then return err end
88*b2d2f356SSara Hartse            else
89*b2d2f356SSara Hartse                -- Didn't have an old value, delete (inherit) instead
90*b2d2f356SSara Hartse                err = zfs.sync.inherit(fs, prop)
91*b2d2f356SSara Hartse                if (err ~= 0) then return err end
92*b2d2f356SSara Hartse            end
93*b2d2f356SSara Hartse        end
94*b2d2f356SSara Hartse    end
95*b2d2f356SSara Hartseend
96*b2d2f356SSara Hartse
97*b2d2f356SSara Hartse-- Test properties that should fail
98*b2d2f356SSara Hartsefor prop, expected in pairs(neg_props) do
99*b2d2f356SSara Hartse    exp_val = expected[1]
100*b2d2f356SSara Hartse    exp_err = expected[2]
101*b2d2f356SSara Hartse
102*b2d2f356SSara Hartse    -- Attempt to set the property to the specified value
103*b2d2f356SSara Hartse    err = zfs.sync.set_prop(fs, prop, exp_val)
104*b2d2f356SSara Hartse    if (err == 0 or (exp_err ~= nil and err ~= exp_err)) then
105*b2d2f356SSara Hartse        set_fail[prop] = err -- tuple of prop, val that resulted in error
106*b2d2f356SSara Hartse    end
107*b2d2f356SSara Hartseend
108*b2d2f356SSara Hartse
109*b2d2f356SSara Hartsereturn {set_fail, val_fail}
110