]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libzfsbootenv/lzbe_pair.c
missed three fcntl.h header files
[FreeBSD/FreeBSD.git] / lib / libzfsbootenv / lzbe_pair.c
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 /*
12  * Copyright 2020 Toomas Soome <tsoome@me.com>
13  */
14
15 #include <sys/types.h>
16 #include <string.h>
17 #include <libzfs.h>
18 #include <libzfsbootenv.h>
19 #include <sys/zfs_bootenv.h>
20 #include <sys/vdev_impl.h>
21
22 /*
23  * Get or create nvlist. If key is not NULL, get nvlist from bootenv,
24  * otherwise return bootenv.
25  */
26 int
27 lzbe_nvlist_get(const char *pool, const char *key, void **ptr)
28 {
29         libzfs_handle_t *hdl;
30         zpool_handle_t *zphdl;
31         nvlist_t *nv;
32         int rv = -1;
33
34         if (pool == NULL || *pool == '\0')
35                 return (rv);
36
37         if ((hdl = libzfs_init()) == NULL) {
38                 return (rv);
39         }
40
41         zphdl = zpool_open(hdl, pool);
42         if (zphdl == NULL) {
43                 libzfs_fini(hdl);
44                 return (rv);
45         }
46
47         rv = zpool_get_bootenv(zphdl, &nv);
48         if (rv == 0) {
49                 nvlist_t *nvl, *dup;
50
51                 if (key != NULL) {
52                         rv = nvlist_lookup_nvlist(nv, key, &nvl);
53                         if (rv == 0) {
54                                 rv = nvlist_dup(nvl, &dup, 0);
55                                 nvlist_free(nv);
56                                 if (rv == 0)
57                                         nv = dup;
58                                 else
59                                         nv = NULL;
60                         } else {
61                                 nvlist_free(nv);
62                                 rv = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
63                         }
64                 }
65                 *ptr = nv;
66         }
67
68         zpool_close(zphdl);
69         libzfs_fini(hdl);
70         return (rv);
71 }
72
73 int
74 lzbe_nvlist_set(const char *pool, const char *key, void *ptr)
75 {
76         libzfs_handle_t *hdl;
77         zpool_handle_t *zphdl;
78         nvlist_t *nv;
79         uint64_t version;
80         int rv = -1;
81
82         if (pool == NULL || *pool == '\0')
83                 return (rv);
84
85         if ((hdl = libzfs_init()) == NULL) {
86                 return (rv);
87         }
88
89         zphdl = zpool_open(hdl, pool);
90         if (zphdl == NULL) {
91                 libzfs_fini(hdl);
92                 return (rv);
93         }
94
95         if (key != NULL) {
96                 rv = zpool_get_bootenv(zphdl, &nv);
97                 if (rv == 0) {
98                         /*
99                          * We got the nvlist, check for version.
100                          * if version is missing or is not VB_NVLIST,
101                          * create new list.
102                          */
103                         rv = nvlist_lookup_uint64(nv, BOOTENV_VERSION,
104                             &version);
105                         if (rv != 0 || version != VB_NVLIST) {
106                                 /* Drop this nvlist */
107                                 fnvlist_free(nv);
108                                 /* Create and prepare new nvlist */
109                                 nv = fnvlist_alloc();
110                                 fnvlist_add_uint64(nv, BOOTENV_VERSION,
111                                     VB_NVLIST);
112                         }
113                         rv = nvlist_add_nvlist(nv, key, ptr);
114                         if (rv == 0)
115                                 rv = zpool_set_bootenv(zphdl, nv);
116                         nvlist_free(nv);
117                 }
118         } else {
119                 rv = zpool_set_bootenv(zphdl, ptr);
120         }
121
122         zpool_close(zphdl);
123         libzfs_fini(hdl);
124         return (rv);
125 }
126
127 /*
128  * free nvlist we got via lzbe_nvlist_get()
129  */
130 void
131 lzbe_nvlist_free(void *ptr)
132 {
133         nvlist_free(ptr);
134 }
135
136 static const char *typenames[] = {
137         "DATA_TYPE_UNKNOWN",
138         "DATA_TYPE_BOOLEAN",
139         "DATA_TYPE_BYTE",
140         "DATA_TYPE_INT16",
141         "DATA_TYPE_UINT16",
142         "DATA_TYPE_INT32",
143         "DATA_TYPE_UINT32",
144         "DATA_TYPE_INT64",
145         "DATA_TYPE_UINT64",
146         "DATA_TYPE_STRING",
147         "DATA_TYPE_BYTE_ARRAY",
148         "DATA_TYPE_INT16_ARRAY",
149         "DATA_TYPE_UINT16_ARRAY",
150         "DATA_TYPE_INT32_ARRAY",
151         "DATA_TYPE_UINT32_ARRAY",
152         "DATA_TYPE_INT64_ARRAY",
153         "DATA_TYPE_UINT64_ARRAY",
154         "DATA_TYPE_STRING_ARRAY",
155         "DATA_TYPE_HRTIME",
156         "DATA_TYPE_NVLIST",
157         "DATA_TYPE_NVLIST_ARRAY",
158         "DATA_TYPE_BOOLEAN_VALUE",
159         "DATA_TYPE_INT8",
160         "DATA_TYPE_UINT8",
161         "DATA_TYPE_BOOLEAN_ARRAY",
162         "DATA_TYPE_INT8_ARRAY",
163         "DATA_TYPE_UINT8_ARRAY"
164 };
165
166 static int
167 nvpair_type_from_name(const char *name)
168 {
169         unsigned i;
170
171         for (i = 0; i < ARRAY_SIZE(typenames); i++) {
172                 if (strcmp(name, typenames[i]) == 0)
173                         return (i);
174         }
175         return (0);
176 }
177
178 /*
179  * Add pair defined by key, type and value into nvlist.
180  */
181 int
182 lzbe_add_pair(void *ptr, const char *key, const char *type, void *value,
183     size_t size)
184 {
185         nvlist_t *nv = ptr;
186         data_type_t dt;
187         int rv = 0;
188
189         if (ptr == NULL || key == NULL || value == NULL)
190                 return (rv);
191
192         if (type == NULL)
193                 type = "DATA_TYPE_STRING";
194         dt = nvpair_type_from_name(type);
195         if (dt == DATA_TYPE_UNKNOWN)
196                 return (EINVAL);
197
198         switch (dt) {
199         case DATA_TYPE_BYTE:
200                 if (size != sizeof (uint8_t)) {
201                         rv = EINVAL;
202                         break;
203                 }
204                 rv = nvlist_add_byte(nv, key, *(uint8_t *)value);
205                 break;
206
207         case DATA_TYPE_INT16:
208                 if (size != sizeof (int16_t)) {
209                         rv = EINVAL;
210                         break;
211                 }
212                 rv = nvlist_add_int16(nv, key, *(int16_t *)value);
213                 break;
214
215         case DATA_TYPE_UINT16:
216                 if (size != sizeof (uint16_t)) {
217                         rv = EINVAL;
218                         break;
219                 }
220                 rv = nvlist_add_uint16(nv, key, *(uint16_t *)value);
221                 break;
222
223         case DATA_TYPE_INT32:
224                 if (size != sizeof (int32_t)) {
225                         rv = EINVAL;
226                         break;
227                 }
228                 rv = nvlist_add_int32(nv, key, *(int32_t *)value);
229                 break;
230
231         case DATA_TYPE_UINT32:
232                 if (size != sizeof (uint32_t)) {
233                         rv = EINVAL;
234                         break;
235                 }
236                 rv = nvlist_add_uint32(nv, key, *(uint32_t *)value);
237                 break;
238
239         case DATA_TYPE_INT64:
240                 if (size != sizeof (int64_t)) {
241                         rv = EINVAL;
242                         break;
243                 }
244                 rv = nvlist_add_int64(nv, key, *(int64_t *)value);
245                 break;
246
247         case DATA_TYPE_UINT64:
248                 if (size != sizeof (uint64_t)) {
249                         rv = EINVAL;
250                         break;
251                 }
252                 rv = nvlist_add_uint64(nv, key, *(uint64_t *)value);
253                 break;
254
255         case DATA_TYPE_STRING:
256                 rv = nvlist_add_string(nv, key, value);
257                 break;
258
259         case DATA_TYPE_BYTE_ARRAY:
260                 rv = nvlist_add_byte_array(nv, key, value, size);
261                 break;
262
263         case DATA_TYPE_INT16_ARRAY:
264                 rv = nvlist_add_int16_array(nv, key, value, size);
265                 break;
266
267         case DATA_TYPE_UINT16_ARRAY:
268                 rv = nvlist_add_uint16_array(nv, key, value, size);
269                 break;
270
271         case DATA_TYPE_INT32_ARRAY:
272                 rv = nvlist_add_int32_array(nv, key, value, size);
273                 break;
274
275         case DATA_TYPE_UINT32_ARRAY:
276                 rv = nvlist_add_uint32_array(nv, key, value, size);
277                 break;
278
279         case DATA_TYPE_INT64_ARRAY:
280                 rv = nvlist_add_int64_array(nv, key, value, size);
281                 break;
282
283         case DATA_TYPE_UINT64_ARRAY:
284                 rv = nvlist_add_uint64_array(nv, key, value, size);
285                 break;
286
287         case DATA_TYPE_STRING_ARRAY:
288                 rv = nvlist_add_string_array(nv, key, value, size);
289                 break;
290
291         case DATA_TYPE_NVLIST:
292                 rv = nvlist_add_nvlist(nv, key, (nvlist_t *)value);
293                 break;
294
295         case DATA_TYPE_NVLIST_ARRAY:
296                 rv = nvlist_add_nvlist_array(nv, key, value, size);
297                 break;
298
299         case DATA_TYPE_BOOLEAN_VALUE:
300                 if (size != sizeof (boolean_t)) {
301                         rv = EINVAL;
302                         break;
303                 }
304                 rv = nvlist_add_boolean_value(nv, key, *(boolean_t *)value);
305                 break;
306
307         case DATA_TYPE_INT8:
308                 if (size != sizeof (int8_t)) {
309                         rv = EINVAL;
310                         break;
311                 }
312                 rv = nvlist_add_int8(nv, key, *(int8_t *)value);
313                 break;
314
315         case DATA_TYPE_UINT8:
316                 if (size != sizeof (uint8_t)) {
317                         rv = EINVAL;
318                         break;
319                 }
320                 rv = nvlist_add_uint8(nv, key, *(uint8_t *)value);
321                 break;
322
323         case DATA_TYPE_BOOLEAN_ARRAY:
324                 rv = nvlist_add_boolean_array(nv, key, value, size);
325                 break;
326
327         case DATA_TYPE_INT8_ARRAY:
328                 rv = nvlist_add_int8_array(nv, key, value, size);
329                 break;
330
331         case DATA_TYPE_UINT8_ARRAY:
332                 rv = nvlist_add_uint8_array(nv, key, value, size);
333                 break;
334
335         default:
336                 return (ENOTSUP);
337         }
338
339         return (rv);
340 }
341
342 int
343 lzbe_remove_pair(void *ptr, const char *key)
344 {
345
346         return (nvlist_remove_all(ptr, key));
347 }