xref: /freebsd/lib/libbe/be_info.c (revision c3a34c08e09c24c9cadf309c393e019063e52616)
128f16a0fSKyle Evans /*
228f16a0fSKyle Evans  * be_info.c
328f16a0fSKyle Evans  *
428f16a0fSKyle Evans  * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
528f16a0fSKyle Evans  * All rights reserved.
628f16a0fSKyle Evans  *
728f16a0fSKyle Evans  * Redistribution and use in source and binary forms, with or without
828f16a0fSKyle Evans  * modification, are permitted provided that the following conditions
928f16a0fSKyle Evans  * are met:
1028f16a0fSKyle Evans  * 1. Redistributions of source code must retain the above copyright
1128f16a0fSKyle Evans  *    notice, this list of conditions and the following disclaimer.
1228f16a0fSKyle Evans  * 2. Redistributions in binary form must reproduce the above copyright
1328f16a0fSKyle Evans  *    notice, this list of conditions and the following disclaimer in the
1428f16a0fSKyle Evans  *    documentation and/or other materials provided with the distribution.
1528f16a0fSKyle Evans  *
1628f16a0fSKyle Evans  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1728f16a0fSKyle Evans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1828f16a0fSKyle Evans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1928f16a0fSKyle Evans  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2028f16a0fSKyle Evans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2128f16a0fSKyle Evans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2228f16a0fSKyle Evans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2328f16a0fSKyle Evans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2428f16a0fSKyle Evans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2528f16a0fSKyle Evans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2628f16a0fSKyle Evans  * SUCH DAMAGE.
2728f16a0fSKyle Evans  */
2828f16a0fSKyle Evans 
2928f16a0fSKyle Evans #include "be.h"
3028f16a0fSKyle Evans #include "be_impl.h"
3128f16a0fSKyle Evans 
3228f16a0fSKyle Evans typedef struct prop_data {
3328f16a0fSKyle Evans 	nvlist_t *list;
3428f16a0fSKyle Evans 	libbe_handle_t *lbh;
3528f16a0fSKyle Evans } prop_data_t;
3628f16a0fSKyle Evans 
3728f16a0fSKyle Evans static int prop_list_builder_cb(zfs_handle_t *, void *);
3828f16a0fSKyle Evans static int prop_list_builder(prop_data_t *);
3928f16a0fSKyle Evans 
4028f16a0fSKyle Evans /*
4128f16a0fSKyle Evans  * Returns the name of the active boot environment
4228f16a0fSKyle Evans  */
4328f16a0fSKyle Evans const char *
4428f16a0fSKyle Evans be_active_name(libbe_handle_t *lbh)
4528f16a0fSKyle Evans {
46*c3a34c08SKyle Evans 	return (strrchr(lbh->rootfs, '/') + sizeof(char));
4728f16a0fSKyle Evans }
4828f16a0fSKyle Evans 
4928f16a0fSKyle Evans 
5028f16a0fSKyle Evans /*
5128f16a0fSKyle Evans  * Returns full path of the active boot environment
5228f16a0fSKyle Evans  */
5328f16a0fSKyle Evans const char *
5428f16a0fSKyle Evans be_active_path(libbe_handle_t *lbh)
5528f16a0fSKyle Evans {
56*c3a34c08SKyle Evans 	return (lbh->rootfs);
5728f16a0fSKyle Evans }
5828f16a0fSKyle Evans 
5928f16a0fSKyle Evans 
6028f16a0fSKyle Evans /*
6128f16a0fSKyle Evans  * Returns the path of the boot environment root dataset
6228f16a0fSKyle Evans  */
6328f16a0fSKyle Evans const char *
6428f16a0fSKyle Evans be_root_path(libbe_handle_t *lbh)
6528f16a0fSKyle Evans {
6628f16a0fSKyle Evans 	return (lbh->root);
6728f16a0fSKyle Evans }
6828f16a0fSKyle Evans 
6928f16a0fSKyle Evans 
7028f16a0fSKyle Evans /*
7128f16a0fSKyle Evans  * Returns an nvlist of the bootenv's properties
7228f16a0fSKyle Evans  * TODO: the nvlist should be passed as a param and ints should return status
7328f16a0fSKyle Evans  */
7428f16a0fSKyle Evans nvlist_t *
7528f16a0fSKyle Evans be_get_bootenv_props(libbe_handle_t *lbh)
7628f16a0fSKyle Evans {
7728f16a0fSKyle Evans 	prop_data_t data;
7828f16a0fSKyle Evans 
7928f16a0fSKyle Evans 	data.lbh = lbh;
8028f16a0fSKyle Evans 	prop_list_builder(&data);
8128f16a0fSKyle Evans 
8228f16a0fSKyle Evans 	return (data.list);
8328f16a0fSKyle Evans }
8428f16a0fSKyle Evans 
8528f16a0fSKyle Evans 
8628f16a0fSKyle Evans /*
8728f16a0fSKyle Evans  * Internal callback function used by zfs_iter_filesystems. For each dataset in
8828f16a0fSKyle Evans  * the bootenv root, populate an nvlist_t of its relevant properties.
8928f16a0fSKyle Evans  * TODO: should any other properties be included?
9028f16a0fSKyle Evans  */
9128f16a0fSKyle Evans static int
9228f16a0fSKyle Evans prop_list_builder_cb(zfs_handle_t *zfs_hdl, void *data_p)
9328f16a0fSKyle Evans {
9428f16a0fSKyle Evans 	/*
9528f16a0fSKyle Evans 	 * TODO:
9628f16a0fSKyle Evans 	 *      some system for defining constants for the nvlist keys
9728f16a0fSKyle Evans 	 *      error checking
9828f16a0fSKyle Evans 	 */
9928f16a0fSKyle Evans 
10028f16a0fSKyle Evans 	char buf[512];
10128f16a0fSKyle Evans 	prop_data_t *data;
10228f16a0fSKyle Evans 	boolean_t mounted, active, nextboot;
10328f16a0fSKyle Evans 
10428f16a0fSKyle Evans 
10528f16a0fSKyle Evans 	data = (prop_data_t *)data_p;
10628f16a0fSKyle Evans 
10728f16a0fSKyle Evans 
10828f16a0fSKyle Evans 	nvlist_t *props;
10928f16a0fSKyle Evans 
11028f16a0fSKyle Evans 	libbe_handle_t *lbh = data->lbh;
11128f16a0fSKyle Evans 
11228f16a0fSKyle Evans 
11328f16a0fSKyle Evans 	nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
11428f16a0fSKyle Evans 
11528f16a0fSKyle Evans 	const char *dataset = zfs_get_name(zfs_hdl);
11628f16a0fSKyle Evans 	nvlist_add_string(props, "dataset", dataset);
11728f16a0fSKyle Evans 
11828f16a0fSKyle Evans 	const char *name = strrchr(dataset, '/') + 1;
11928f16a0fSKyle Evans 	nvlist_add_string(props, "name", name);
12028f16a0fSKyle Evans 
12128f16a0fSKyle Evans 
12228f16a0fSKyle Evans 	mounted = zfs_prop_get_int(zfs_hdl, ZFS_PROP_MOUNTED);
12328f16a0fSKyle Evans 	nvlist_add_boolean_value(props, "mounted", mounted);
12428f16a0fSKyle Evans 
12528f16a0fSKyle Evans 	// TODO: NOT CORRECT! Must use is_mounted
12628f16a0fSKyle Evans 	if (mounted) {
12728f16a0fSKyle Evans 		zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512,
12828f16a0fSKyle Evans 		    NULL, NULL, 0, 1);
12928f16a0fSKyle Evans 		nvlist_add_string(props, "mountpoint", buf);
13028f16a0fSKyle Evans 	}
13128f16a0fSKyle Evans 
13228f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512,
13328f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
13428f16a0fSKyle Evans 		nvlist_add_string(props, "origin", buf);
13528f16a0fSKyle Evans 	}
13628f16a0fSKyle Evans 
13728f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512,
13828f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
13928f16a0fSKyle Evans 		nvlist_add_string(props, "creation", buf);
14028f16a0fSKyle Evans 	}
14128f16a0fSKyle Evans 
14228f16a0fSKyle Evans 	nvlist_add_boolean_value(props, "active",
14328f16a0fSKyle Evans 	    (strcmp(be_active_path(lbh), dataset) == 0));
14428f16a0fSKyle Evans 
14528f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512,
14628f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
14728f16a0fSKyle Evans 		nvlist_add_string(props, "used", buf);
14828f16a0fSKyle Evans 	}
14928f16a0fSKyle Evans 
15028f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512,
15128f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
15228f16a0fSKyle Evans 		nvlist_add_string(props, "usedds", buf);
15328f16a0fSKyle Evans 	}
15428f16a0fSKyle Evans 
15528f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512,
15628f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
15728f16a0fSKyle Evans 		nvlist_add_string(props, "usedsnap", buf);
15828f16a0fSKyle Evans 	}
15928f16a0fSKyle Evans 
16028f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512,
16128f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
16228f16a0fSKyle Evans 		nvlist_add_string(props, "usedrefreserv", buf);
16328f16a0fSKyle Evans 	}
16428f16a0fSKyle Evans 
16528f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512,
16628f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
16728f16a0fSKyle Evans 		nvlist_add_string(props, "referenced", buf);
16828f16a0fSKyle Evans 	}
16928f16a0fSKyle Evans 
17028f16a0fSKyle Evans 	/* TODO figure out how to read nextboot (set in libzfs_pool.c) */
17128f16a0fSKyle Evans 
17228f16a0fSKyle Evans 	nvlist_add_nvlist(data->list, name, props);
17328f16a0fSKyle Evans 
17428f16a0fSKyle Evans 	return (0);
17528f16a0fSKyle Evans }
17628f16a0fSKyle Evans 
17728f16a0fSKyle Evans 
17828f16a0fSKyle Evans /*
17928f16a0fSKyle Evans  * Updates the properties of each bootenv in the libbe handle
18028f16a0fSKyle Evans  * TODO: rename to be_proplist_update
18128f16a0fSKyle Evans  * TODO: ensure that this is always consistent (run after adds, deletes,
18228f16a0fSKyle Evans  *       renames,etc
18328f16a0fSKyle Evans  */
18428f16a0fSKyle Evans static int
18528f16a0fSKyle Evans prop_list_builder(prop_data_t *data)
18628f16a0fSKyle Evans {
18728f16a0fSKyle Evans 	zfs_handle_t *root_hdl;
18828f16a0fSKyle Evans 
18928f16a0fSKyle Evans 	if (nvlist_alloc(&(data->list), NV_UNIQUE_NAME, KM_SLEEP) != 0) {
19028f16a0fSKyle Evans 		/* TODO: actually handle error */
19128f16a0fSKyle Evans 		return (1);
19228f16a0fSKyle Evans 	}
19328f16a0fSKyle Evans 
19428f16a0fSKyle Evans 
19528f16a0fSKyle Evans 	if ((root_hdl =
19628f16a0fSKyle Evans 	    zfs_open(data->lbh->lzh, data->lbh->root,
19728f16a0fSKyle Evans 	    ZFS_TYPE_FILESYSTEM)) == NULL) {
19828f16a0fSKyle Evans 		return (BE_ERR_ZFSOPEN);
19928f16a0fSKyle Evans 	}
20028f16a0fSKyle Evans 
20128f16a0fSKyle Evans 	// TODO: some error checking here
20228f16a0fSKyle Evans 	zfs_iter_filesystems(root_hdl, prop_list_builder_cb, data);
20328f16a0fSKyle Evans 
20428f16a0fSKyle Evans 	zfs_close(root_hdl);
20528f16a0fSKyle Evans 
20628f16a0fSKyle Evans 	return (0);
20728f16a0fSKyle Evans }
20828f16a0fSKyle Evans 
20928f16a0fSKyle Evans 
21028f16a0fSKyle Evans /*
21128f16a0fSKyle Evans  * frees property list and its children
21228f16a0fSKyle Evans  */
21328f16a0fSKyle Evans void
21428f16a0fSKyle Evans be_prop_list_free(nvlist_t *be_list)
21528f16a0fSKyle Evans {
21628f16a0fSKyle Evans 	nvlist_t *prop_list;
21728f16a0fSKyle Evans 
21828f16a0fSKyle Evans 	nvpair_t *be_pair = nvlist_next_nvpair(be_list, NULL);
21928f16a0fSKyle Evans 
22028f16a0fSKyle Evans 	if (nvpair_value_nvlist(be_pair, &prop_list) == 0) {
22128f16a0fSKyle Evans 		nvlist_free(prop_list);
22228f16a0fSKyle Evans 	}
22328f16a0fSKyle Evans 
22428f16a0fSKyle Evans 	while ((be_pair = nvlist_next_nvpair(be_list, be_pair)) != NULL) {
22528f16a0fSKyle Evans 		if (nvpair_value_nvlist(be_pair, &prop_list) == 0) {
22628f16a0fSKyle Evans 			nvlist_free(prop_list);
22728f16a0fSKyle Evans 		}
22828f16a0fSKyle Evans 	}
22928f16a0fSKyle Evans }
23028f16a0fSKyle Evans 
23128f16a0fSKyle Evans 
23228f16a0fSKyle Evans /*
23328f16a0fSKyle Evans  * Usage
23428f16a0fSKyle Evans  */
23528f16a0fSKyle Evans bool
23628f16a0fSKyle Evans be_exists(libbe_handle_t *lbh, char *be)
23728f16a0fSKyle Evans {
23828f16a0fSKyle Evans 	char buf[BE_MAXPATHLEN];
23928f16a0fSKyle Evans 
24028f16a0fSKyle Evans 	be_root_concat(lbh, be, buf);
24128f16a0fSKyle Evans 
24228f16a0fSKyle Evans 	// TODO: check mountpoint prop and see if its /, AND that result with below
24328f16a0fSKyle Evans 	// expression
24428f16a0fSKyle Evans 	return (zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET));
24528f16a0fSKyle Evans }
246