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
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.
12 * Copyright 2020 Toomas Soome <tsoome@me.com>
15 #include <sys/types.h>
18 #include <libzfsbootenv.h>
19 #include <sys/zfs_bootenv.h>
20 #include <sys/vdev_impl.h>
23 * Store device name to zpool label bootenv area.
24 * This call will set bootenv version to VB_NVLIST, if bootenv currently
25 * does contain other version, then old data will be replaced.
28 lzbe_set_boot_device(const char *pool
, lzbe_flags_t flag
, const char *device
)
31 zpool_handle_t
*zphdl
;
37 if (pool
== NULL
|| *pool
== '\0')
40 if ((hdl
= libzfs_init()) == NULL
)
43 zphdl
= zpool_open(hdl
, pool
);
51 rv
= zpool_get_bootenv(zphdl
, &nv
);
54 * We got the nvlist, check for version.
55 * if version is missing or is not VB_NVLIST,
58 rv
= nvlist_lookup_uint64(nv
, BOOTENV_VERSION
,
60 if (rv
== 0 && version
== VB_NVLIST
)
63 /* Drop this nvlist */
74 /* version is mandatory */
75 fnvlist_add_uint64(nv
, BOOTENV_VERSION
, VB_NVLIST
);
79 * If device name is empty, remove boot device configuration.
81 if ((device
== NULL
|| *device
== '\0')) {
82 if (nvlist_exists(nv
, OS_BOOTONCE
))
83 fnvlist_remove(nv
, OS_BOOTONCE
);
86 * Use device name directly if it does start with
87 * prefix "zfs:". Otherwise, add prefix and suffix.
89 if (strncmp(device
, "zfs:", 4) == 0) {
90 fnvlist_add_string(nv
, OS_BOOTONCE
, device
);
92 if (asprintf(&descriptor
, "zfs:%s:", device
) > 0) {
93 fnvlist_add_string(nv
, OS_BOOTONCE
, descriptor
);
100 rv
= zpool_set_bootenv(zphdl
, nv
);
102 fprintf(stderr
, "%s\n", libzfs_error_description(hdl
));
111 * Return boot device name from bootenv, if set.
114 lzbe_get_boot_device(const char *pool
, char **device
)
116 libzfs_handle_t
*hdl
;
117 zpool_handle_t
*zphdl
;
122 if (pool
== NULL
|| *pool
== '\0' || device
== NULL
)
125 if ((hdl
= libzfs_init()) == NULL
)
128 zphdl
= zpool_open(hdl
, pool
);
134 rv
= zpool_get_bootenv(zphdl
, &nv
);
136 rv
= nvlist_lookup_string(nv
, OS_BOOTONCE
, &val
);
139 * zfs device descriptor is in form of "zfs:dataset:",
140 * we only do need dataset name.
142 if (strncmp(val
, "zfs:", 4) == 0) {
143 char *tmp
= strdup(val
+ 4);
145 size_t len
= strlen(tmp
);
147 if (tmp
[len
- 1] == ':')