]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libbe/be_info.c
libbe(3)/be(8): Drop WARNS overrides, fix all fallout
[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
47         return (strrchr(lbh->rootfs, '/') + sizeof(char));
48 }
49
50
51 /*
52  * Returns full path of the active boot environment
53  */
54 const char *
55 be_active_path(libbe_handle_t *lbh)
56 {
57
58         return (lbh->rootfs);
59 }
60
61 /*
62  * Returns the name of the next active boot environment
63  */
64 const char *
65 be_nextboot_name(libbe_handle_t *lbh)
66 {
67
68         return (strrchr(lbh->bootfs, '/') + sizeof(char));
69 }
70
71
72 /*
73  * Returns full path of the active boot environment
74  */
75 const char *
76 be_nextboot_path(libbe_handle_t *lbh)
77 {
78
79         return (lbh->bootfs);
80 }
81
82
83 /*
84  * Returns the path of the boot environment root dataset
85  */
86 const char *
87 be_root_path(libbe_handle_t *lbh)
88 {
89
90         return (lbh->root);
91 }
92
93
94 /*
95  * Populates dsnvl with one nvlist per bootenv dataset describing the properties
96  * of that dataset that we've declared ourselves to care about.
97  */
98 int
99 be_get_bootenv_props(libbe_handle_t *lbh, nvlist_t *dsnvl)
100 {
101         prop_data_t data;
102
103         data.lbh = lbh;
104         data.list = dsnvl;
105         return (prop_list_builder(&data));
106 }
107
108
109 /*
110  * Internal callback function used by zfs_iter_filesystems. For each dataset in
111  * the bootenv root, populate an nvlist_t of its relevant properties.
112  * TODO: should any other properties be included?
113  */
114 static int
115 prop_list_builder_cb(zfs_handle_t *zfs_hdl, void *data_p)
116 {
117         char buf[512];
118         prop_data_t *data;
119         libbe_handle_t *lbh;
120         nvlist_t *props;
121         const char *dataset, *name;
122         boolean_t mounted;
123
124         /*
125          * XXX TODO:
126          *      some system for defining constants for the nvlist keys
127          *      error checking
128          */
129         data = (prop_data_t *)data_p;
130         lbh = data->lbh;
131
132         nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
133
134         dataset = zfs_get_name(zfs_hdl);
135         nvlist_add_string(props, "dataset", dataset);
136
137         name = strrchr(dataset, '/') + 1;
138         nvlist_add_string(props, "name", name);
139
140         mounted = zfs_prop_get_int(zfs_hdl, ZFS_PROP_MOUNTED);
141         nvlist_add_boolean_value(props, "mounted", mounted);
142
143         /* XXX TODO: NOT CORRECT! Must use is_mounted */
144         if (mounted) {
145                 zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512,
146                     NULL, NULL, 0, 1);
147                 nvlist_add_string(props, "mountpoint", buf);
148         }
149
150         if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512,
151             NULL, NULL, 0, 1))
152                 nvlist_add_string(props, "origin", buf);
153
154         if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512,
155             NULL, NULL, 0, 1))
156                 nvlist_add_string(props, "creation", buf);
157
158         nvlist_add_boolean_value(props, "active",
159             (strcmp(be_active_path(lbh), dataset) == 0));
160
161         if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512,
162             NULL, NULL, 0, 1))
163                 nvlist_add_string(props, "used", buf);
164
165         if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512,
166             NULL, NULL, 0, 1))
167                 nvlist_add_string(props, "usedds", buf);
168
169         if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512,
170             NULL, NULL, 0, 1))
171                 nvlist_add_string(props, "usedsnap", buf);
172
173         if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512,
174             NULL, NULL, 0, 1))
175                 nvlist_add_string(props, "usedrefreserv", buf);
176
177         if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512,
178             NULL, NULL, 0, 1))
179                 nvlist_add_string(props, "referenced", buf);
180
181         nvlist_add_boolean_value(props, "nextboot",
182             (strcmp(be_nextboot_path(lbh), dataset) == 0));
183
184         nvlist_add_nvlist(data->list, name, props);
185
186         return (0);
187 }
188
189
190 /*
191  * Updates the properties of each bootenv in the libbe handle
192  * XXX TODO: rename to be_proplist_update
193  * XXX TODO: ensure that this is always consistent (run after adds, deletes,
194  *       renames,etc
195  */
196 static int
197 prop_list_builder(prop_data_t *data)
198 {
199         zfs_handle_t *root_hdl;
200
201         if ((root_hdl = zfs_open(data->lbh->lzh, data->lbh->root,
202             ZFS_TYPE_FILESYSTEM)) == NULL)
203                 return (BE_ERR_ZFSOPEN);
204
205         /* XXX TODO: some error checking here */
206         zfs_iter_filesystems(root_hdl, prop_list_builder_cb, data);
207
208         zfs_close(root_hdl);
209
210         return (0);
211 }
212
213
214 /*
215  * frees property list and its children
216  */
217 void
218 be_prop_list_free(nvlist_t *be_list)
219 {
220         nvlist_t *prop_list;
221         nvpair_t *be_pair;
222
223         be_pair = nvlist_next_nvpair(be_list, NULL);
224         if (nvpair_value_nvlist(be_pair, &prop_list) == 0)
225                 nvlist_free(prop_list);
226
227         while ((be_pair = nvlist_next_nvpair(be_list, be_pair)) != NULL) {
228                 if (nvpair_value_nvlist(be_pair, &prop_list) == 0)
229                         nvlist_free(prop_list);
230         }
231 }
232
233
234 /*
235  * Usage
236  */
237 bool
238 be_exists(libbe_handle_t *lbh, char *be)
239 {
240         char buf[BE_MAXPATHLEN];
241
242         be_root_concat(lbh, be, buf);
243
244         /*
245          * XXX TODO: check mountpoint prop and see if its /, AND that result
246          * with below expression.
247          */
248         return (zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET));
249 }