xref: /freebsd/lib/libbe/be_info.c (revision 28f16a0f1985b32a97075a540236e8abebaeadf1)
1*28f16a0fSKyle Evans /*
2*28f16a0fSKyle Evans  * be_info.c
3*28f16a0fSKyle Evans  *
4*28f16a0fSKyle Evans  * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
5*28f16a0fSKyle Evans  * All rights reserved.
6*28f16a0fSKyle Evans  *
7*28f16a0fSKyle Evans  * Redistribution and use in source and binary forms, with or without
8*28f16a0fSKyle Evans  * modification, are permitted provided that the following conditions
9*28f16a0fSKyle Evans  * are met:
10*28f16a0fSKyle Evans  * 1. Redistributions of source code must retain the above copyright
11*28f16a0fSKyle Evans  *    notice, this list of conditions and the following disclaimer.
12*28f16a0fSKyle Evans  * 2. Redistributions in binary form must reproduce the above copyright
13*28f16a0fSKyle Evans  *    notice, this list of conditions and the following disclaimer in the
14*28f16a0fSKyle Evans  *    documentation and/or other materials provided with the distribution.
15*28f16a0fSKyle Evans  *
16*28f16a0fSKyle Evans  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17*28f16a0fSKyle Evans  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*28f16a0fSKyle Evans  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*28f16a0fSKyle Evans  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20*28f16a0fSKyle Evans  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*28f16a0fSKyle Evans  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*28f16a0fSKyle Evans  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*28f16a0fSKyle Evans  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*28f16a0fSKyle Evans  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*28f16a0fSKyle Evans  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*28f16a0fSKyle Evans  * SUCH DAMAGE.
27*28f16a0fSKyle Evans  */
28*28f16a0fSKyle Evans 
29*28f16a0fSKyle Evans #include "be.h"
30*28f16a0fSKyle Evans #include "be_impl.h"
31*28f16a0fSKyle Evans 
32*28f16a0fSKyle Evans typedef struct prop_data {
33*28f16a0fSKyle Evans 	nvlist_t *list;
34*28f16a0fSKyle Evans 	libbe_handle_t *lbh;
35*28f16a0fSKyle Evans } prop_data_t;
36*28f16a0fSKyle Evans 
37*28f16a0fSKyle Evans static int prop_list_builder_cb(zfs_handle_t *, void *);
38*28f16a0fSKyle Evans static int prop_list_builder(prop_data_t *);
39*28f16a0fSKyle Evans 
40*28f16a0fSKyle Evans /*
41*28f16a0fSKyle Evans  * Returns the name of the active boot environment
42*28f16a0fSKyle Evans  */
43*28f16a0fSKyle Evans const char *
44*28f16a0fSKyle Evans be_active_name(libbe_handle_t *lbh)
45*28f16a0fSKyle Evans {
46*28f16a0fSKyle Evans 	return (strrchr(lbh->active, '/') + sizeof(char));
47*28f16a0fSKyle Evans }
48*28f16a0fSKyle Evans 
49*28f16a0fSKyle Evans 
50*28f16a0fSKyle Evans /*
51*28f16a0fSKyle Evans  * Returns full path of the active boot environment
52*28f16a0fSKyle Evans  */
53*28f16a0fSKyle Evans const char *
54*28f16a0fSKyle Evans be_active_path(libbe_handle_t *lbh)
55*28f16a0fSKyle Evans {
56*28f16a0fSKyle Evans 	return (lbh->active);
57*28f16a0fSKyle Evans }
58*28f16a0fSKyle Evans 
59*28f16a0fSKyle Evans 
60*28f16a0fSKyle Evans /*
61*28f16a0fSKyle Evans  * Returns the path of the boot environment root dataset
62*28f16a0fSKyle Evans  */
63*28f16a0fSKyle Evans const char *
64*28f16a0fSKyle Evans be_root_path(libbe_handle_t *lbh)
65*28f16a0fSKyle Evans {
66*28f16a0fSKyle Evans 	return (lbh->root);
67*28f16a0fSKyle Evans }
68*28f16a0fSKyle Evans 
69*28f16a0fSKyle Evans 
70*28f16a0fSKyle Evans /*
71*28f16a0fSKyle Evans  * Returns an nvlist of the bootenv's properties
72*28f16a0fSKyle Evans  * TODO: the nvlist should be passed as a param and ints should return status
73*28f16a0fSKyle Evans  */
74*28f16a0fSKyle Evans nvlist_t *
75*28f16a0fSKyle Evans be_get_bootenv_props(libbe_handle_t *lbh)
76*28f16a0fSKyle Evans {
77*28f16a0fSKyle Evans 	prop_data_t data;
78*28f16a0fSKyle Evans 
79*28f16a0fSKyle Evans 	data.lbh = lbh;
80*28f16a0fSKyle Evans 	prop_list_builder(&data);
81*28f16a0fSKyle Evans 
82*28f16a0fSKyle Evans 	return (data.list);
83*28f16a0fSKyle Evans }
84*28f16a0fSKyle Evans 
85*28f16a0fSKyle Evans 
86*28f16a0fSKyle Evans /*
87*28f16a0fSKyle Evans  * Internal callback function used by zfs_iter_filesystems. For each dataset in
88*28f16a0fSKyle Evans  * the bootenv root, populate an nvlist_t of its relevant properties.
89*28f16a0fSKyle Evans  * TODO: should any other properties be included?
90*28f16a0fSKyle Evans  */
91*28f16a0fSKyle Evans static int
92*28f16a0fSKyle Evans prop_list_builder_cb(zfs_handle_t *zfs_hdl, void *data_p)
93*28f16a0fSKyle Evans {
94*28f16a0fSKyle Evans 	/*
95*28f16a0fSKyle Evans 	 * TODO:
96*28f16a0fSKyle Evans 	 *      some system for defining constants for the nvlist keys
97*28f16a0fSKyle Evans 	 *      error checking
98*28f16a0fSKyle Evans 	 */
99*28f16a0fSKyle Evans 
100*28f16a0fSKyle Evans 	char buf[512];
101*28f16a0fSKyle Evans 	prop_data_t *data;
102*28f16a0fSKyle Evans 	boolean_t mounted, active, nextboot;
103*28f16a0fSKyle Evans 
104*28f16a0fSKyle Evans 
105*28f16a0fSKyle Evans 	data = (prop_data_t *)data_p;
106*28f16a0fSKyle Evans 
107*28f16a0fSKyle Evans 
108*28f16a0fSKyle Evans 	nvlist_t *props;
109*28f16a0fSKyle Evans 
110*28f16a0fSKyle Evans 	libbe_handle_t *lbh = data->lbh;
111*28f16a0fSKyle Evans 
112*28f16a0fSKyle Evans 
113*28f16a0fSKyle Evans 	nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
114*28f16a0fSKyle Evans 
115*28f16a0fSKyle Evans 	const char *dataset = zfs_get_name(zfs_hdl);
116*28f16a0fSKyle Evans 	nvlist_add_string(props, "dataset", dataset);
117*28f16a0fSKyle Evans 
118*28f16a0fSKyle Evans 	const char *name = strrchr(dataset, '/') + 1;
119*28f16a0fSKyle Evans 	nvlist_add_string(props, "name", name);
120*28f16a0fSKyle Evans 
121*28f16a0fSKyle Evans 
122*28f16a0fSKyle Evans 	mounted = zfs_prop_get_int(zfs_hdl, ZFS_PROP_MOUNTED);
123*28f16a0fSKyle Evans 	nvlist_add_boolean_value(props, "mounted", mounted);
124*28f16a0fSKyle Evans 
125*28f16a0fSKyle Evans 	// TODO: NOT CORRECT! Must use is_mounted
126*28f16a0fSKyle Evans 	if (mounted) {
127*28f16a0fSKyle Evans 		zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512,
128*28f16a0fSKyle Evans 		    NULL, NULL, 0, 1);
129*28f16a0fSKyle Evans 		nvlist_add_string(props, "mountpoint", buf);
130*28f16a0fSKyle Evans 	}
131*28f16a0fSKyle Evans 
132*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512,
133*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
134*28f16a0fSKyle Evans 		nvlist_add_string(props, "origin", buf);
135*28f16a0fSKyle Evans 	}
136*28f16a0fSKyle Evans 
137*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512,
138*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
139*28f16a0fSKyle Evans 		nvlist_add_string(props, "creation", buf);
140*28f16a0fSKyle Evans 	}
141*28f16a0fSKyle Evans 
142*28f16a0fSKyle Evans 	nvlist_add_boolean_value(props, "active",
143*28f16a0fSKyle Evans 	    (strcmp(be_active_path(lbh), dataset) == 0));
144*28f16a0fSKyle Evans 
145*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512,
146*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
147*28f16a0fSKyle Evans 		nvlist_add_string(props, "used", buf);
148*28f16a0fSKyle Evans 	}
149*28f16a0fSKyle Evans 
150*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512,
151*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
152*28f16a0fSKyle Evans 		nvlist_add_string(props, "usedds", buf);
153*28f16a0fSKyle Evans 	}
154*28f16a0fSKyle Evans 
155*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512,
156*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
157*28f16a0fSKyle Evans 		nvlist_add_string(props, "usedsnap", buf);
158*28f16a0fSKyle Evans 	}
159*28f16a0fSKyle Evans 
160*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512,
161*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
162*28f16a0fSKyle Evans 		nvlist_add_string(props, "usedrefreserv", buf);
163*28f16a0fSKyle Evans 	}
164*28f16a0fSKyle Evans 
165*28f16a0fSKyle Evans 	if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512,
166*28f16a0fSKyle Evans 	    NULL, NULL, 0, 1)) {
167*28f16a0fSKyle Evans 		nvlist_add_string(props, "referenced", buf);
168*28f16a0fSKyle Evans 	}
169*28f16a0fSKyle Evans 
170*28f16a0fSKyle Evans 	/* TODO figure out how to read nextboot (set in libzfs_pool.c) */
171*28f16a0fSKyle Evans 
172*28f16a0fSKyle Evans 	nvlist_add_nvlist(data->list, name, props);
173*28f16a0fSKyle Evans 
174*28f16a0fSKyle Evans 	return (0);
175*28f16a0fSKyle Evans }
176*28f16a0fSKyle Evans 
177*28f16a0fSKyle Evans 
178*28f16a0fSKyle Evans /*
179*28f16a0fSKyle Evans  * Updates the properties of each bootenv in the libbe handle
180*28f16a0fSKyle Evans  * TODO: rename to be_proplist_update
181*28f16a0fSKyle Evans  * TODO: ensure that this is always consistent (run after adds, deletes,
182*28f16a0fSKyle Evans  *       renames,etc
183*28f16a0fSKyle Evans  */
184*28f16a0fSKyle Evans static int
185*28f16a0fSKyle Evans prop_list_builder(prop_data_t *data)
186*28f16a0fSKyle Evans {
187*28f16a0fSKyle Evans 	zfs_handle_t *root_hdl;
188*28f16a0fSKyle Evans 
189*28f16a0fSKyle Evans 	if (nvlist_alloc(&(data->list), NV_UNIQUE_NAME, KM_SLEEP) != 0) {
190*28f16a0fSKyle Evans 		/* TODO: actually handle error */
191*28f16a0fSKyle Evans 		return (1);
192*28f16a0fSKyle Evans 	}
193*28f16a0fSKyle Evans 
194*28f16a0fSKyle Evans 
195*28f16a0fSKyle Evans 	if ((root_hdl =
196*28f16a0fSKyle Evans 	    zfs_open(data->lbh->lzh, data->lbh->root,
197*28f16a0fSKyle Evans 	    ZFS_TYPE_FILESYSTEM)) == NULL) {
198*28f16a0fSKyle Evans 		return (BE_ERR_ZFSOPEN);
199*28f16a0fSKyle Evans 	}
200*28f16a0fSKyle Evans 
201*28f16a0fSKyle Evans 	// TODO: some error checking here
202*28f16a0fSKyle Evans 	zfs_iter_filesystems(root_hdl, prop_list_builder_cb, data);
203*28f16a0fSKyle Evans 
204*28f16a0fSKyle Evans 	zfs_close(root_hdl);
205*28f16a0fSKyle Evans 
206*28f16a0fSKyle Evans 	return (0);
207*28f16a0fSKyle Evans }
208*28f16a0fSKyle Evans 
209*28f16a0fSKyle Evans 
210*28f16a0fSKyle Evans /*
211*28f16a0fSKyle Evans  * frees property list and its children
212*28f16a0fSKyle Evans  */
213*28f16a0fSKyle Evans void
214*28f16a0fSKyle Evans be_prop_list_free(nvlist_t *be_list)
215*28f16a0fSKyle Evans {
216*28f16a0fSKyle Evans 	nvlist_t *prop_list;
217*28f16a0fSKyle Evans 
218*28f16a0fSKyle Evans 	nvpair_t *be_pair = nvlist_next_nvpair(be_list, NULL);
219*28f16a0fSKyle Evans 
220*28f16a0fSKyle Evans 	if (nvpair_value_nvlist(be_pair, &prop_list) == 0) {
221*28f16a0fSKyle Evans 		nvlist_free(prop_list);
222*28f16a0fSKyle Evans 	}
223*28f16a0fSKyle Evans 
224*28f16a0fSKyle Evans 	while ((be_pair = nvlist_next_nvpair(be_list, be_pair)) != NULL) {
225*28f16a0fSKyle Evans 		if (nvpair_value_nvlist(be_pair, &prop_list) == 0) {
226*28f16a0fSKyle Evans 			nvlist_free(prop_list);
227*28f16a0fSKyle Evans 		}
228*28f16a0fSKyle Evans 	}
229*28f16a0fSKyle Evans }
230*28f16a0fSKyle Evans 
231*28f16a0fSKyle Evans 
232*28f16a0fSKyle Evans /*
233*28f16a0fSKyle Evans  * Usage
234*28f16a0fSKyle Evans  */
235*28f16a0fSKyle Evans bool
236*28f16a0fSKyle Evans be_exists(libbe_handle_t *lbh, char *be)
237*28f16a0fSKyle Evans {
238*28f16a0fSKyle Evans 	char buf[BE_MAXPATHLEN];
239*28f16a0fSKyle Evans 
240*28f16a0fSKyle Evans 	be_root_concat(lbh, be, buf);
241*28f16a0fSKyle Evans 
242*28f16a0fSKyle Evans 	// TODO: check mountpoint prop and see if its /, AND that result with below
243*28f16a0fSKyle Evans 	// expression
244*28f16a0fSKyle Evans 	return (zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET));
245*28f16a0fSKyle Evans }
246