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