partedit.c revision 225066
1218799Snwhitehorn/*-
2218799Snwhitehorn * Copyright (c) 2011 Nathan Whitehorn
3218799Snwhitehorn * All rights reserved.
4218799Snwhitehorn *
5218799Snwhitehorn * Redistribution and use in source and binary forms, with or without
6218799Snwhitehorn * modification, are permitted provided that the following conditions
7218799Snwhitehorn * are met:
8218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9218799Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11218799Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12218799Snwhitehorn *    documentation and/or other materials provided with the distribution.
13218799Snwhitehorn *
14218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17218799Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24218799Snwhitehorn * SUCH DAMAGE.
25218799Snwhitehorn *
26218799Snwhitehorn * $FreeBSD: head/usr.sbin/bsdinstall/partedit/partedit.c 225066 2011-08-21 18:50:30Z nwhitehorn $
27218799Snwhitehorn */
28218799Snwhitehorn
29218799Snwhitehorn#include <sys/param.h>
30218799Snwhitehorn#include <libgen.h>
31218799Snwhitehorn#include <libutil.h>
32218799Snwhitehorn#include <inttypes.h>
33218799Snwhitehorn#include <errno.h>
34218799Snwhitehorn
35218799Snwhitehorn#include <fstab.h>
36218799Snwhitehorn#include <libgeom.h>
37218799Snwhitehorn#include <dialog.h>
38218799Snwhitehorn#include <dlg_keys.h>
39218799Snwhitehorn
40218799Snwhitehorn#include "diskeditor.h"
41218799Snwhitehorn#include "partedit.h"
42218799Snwhitehorn
43218799Snwhitehornstruct pmetadata_head part_metadata;
44218799Snwhitehorn
45218799Snwhitehornstatic int apply_changes(struct gmesh *mesh);
46218799Snwhitehornstatic struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems);
47218799Snwhitehornstatic void add_geom_children(struct ggeom *gp, int recurse,
48218799Snwhitehorn    struct partedit_item **items, int *nitems);
49218799Snwhitehornstatic void init_fstab_metadata(void);
50218799Snwhitehornstatic void get_mount_points(struct partedit_item *items, int nitems);
51218799Snwhitehornstatic int validate_setup(void);
52218799Snwhitehorn
53225066Snwhitehornstatic void
54225066Snwhitehornsigint_handler(int sig)
55225066Snwhitehorn{
56225066Snwhitehorn	struct gmesh mesh;
57225066Snwhitehorn
58225066Snwhitehorn	/* Revert all changes and exit dialog-mode cleanly on SIGINT */
59225066Snwhitehorn	geom_gettree(&mesh);
60225066Snwhitehorn	gpart_revert_all(&mesh);
61225066Snwhitehorn	geom_deletetree(&mesh);
62225066Snwhitehorn
63225066Snwhitehorn	end_dialog();
64225066Snwhitehorn
65225066Snwhitehorn	exit(1);
66225066Snwhitehorn}
67225066Snwhitehorn
68218799Snwhitehornint
69225066Snwhitehornmain(int argc, const char **argv)
70225066Snwhitehorn{
71218799Snwhitehorn	struct partition_metadata *md;
72218799Snwhitehorn	const char *prompt;
73218799Snwhitehorn	struct partedit_item *items;
74218799Snwhitehorn	struct gmesh mesh;
75218799Snwhitehorn	int i, op, nitems, nscroll;
76218799Snwhitehorn	int error;
77218799Snwhitehorn
78218799Snwhitehorn	TAILQ_INIT(&part_metadata);
79218799Snwhitehorn
80218799Snwhitehorn	init_fstab_metadata();
81218799Snwhitehorn
82218799Snwhitehorn	init_dialog(stdin, stdout);
83218799Snwhitehorn	if (strcmp(basename(argv[0]), "sade") != 0)
84218799Snwhitehorn		dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
85218799Snwhitehorn	dialog_vars.item_help = TRUE;
86218799Snwhitehorn	nscroll = i = 0;
87218799Snwhitehorn
88225066Snwhitehorn	/* Revert changes on SIGINT */
89225066Snwhitehorn	signal(SIGINT, sigint_handler);
90225066Snwhitehorn
91218799Snwhitehorn	if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */
92218799Snwhitehorn		prompt = "Please review the disk setup. When complete, press "
93225066Snwhitehorn		    "the Finish button.";
94218799Snwhitehorn		part_wizard();
95218799Snwhitehorn	} else {
96218799Snwhitehorn		prompt = "Create partitions for FreeBSD. No changes will be "
97225066Snwhitehorn		    "made until you select Finish.";
98218799Snwhitehorn	}
99218799Snwhitehorn
100218799Snwhitehorn	/* Show the part editor either immediately, or to confirm wizard */
101218799Snwhitehorn	while (1) {
102218799Snwhitehorn		error = geom_gettree(&mesh);
103218799Snwhitehorn		items = read_geom_mesh(&mesh, &nitems);
104218799Snwhitehorn		get_mount_points(items, nitems);
105218799Snwhitehorn		dlg_clear();
106218799Snwhitehorn		dlg_put_backtitle();
107218799Snwhitehorn
108218799Snwhitehorn		if (i >= nitems)
109218799Snwhitehorn			i = nitems - 1;
110218799Snwhitehorn		op = diskeditor_show("Partition Editor", prompt,
111218799Snwhitehorn		    items, nitems, &i, &nscroll);
112218799Snwhitehorn
113218799Snwhitehorn		switch (op) {
114218799Snwhitehorn		case 0: /* Create */
115218799Snwhitehorn			gpart_create((struct gprovider *)(items[i].cookie),
116218799Snwhitehorn			    NULL, NULL, NULL, NULL, 1);
117218799Snwhitehorn			break;
118218799Snwhitehorn		case 1: /* Delete */
119218799Snwhitehorn			gpart_delete((struct gprovider *)(items[i].cookie));
120218799Snwhitehorn			break;
121218799Snwhitehorn		case 2: /* Modify */
122218799Snwhitehorn			gpart_edit((struct gprovider *)(items[i].cookie));
123218799Snwhitehorn			break;
124218799Snwhitehorn		case 3: /* Revert */
125218799Snwhitehorn			gpart_revert_all(&mesh);
126218799Snwhitehorn			while ((md = TAILQ_FIRST(&part_metadata)) != NULL) {
127218799Snwhitehorn				if (md->fstab != NULL) {
128218799Snwhitehorn					free(md->fstab->fs_spec);
129218799Snwhitehorn					free(md->fstab->fs_file);
130218799Snwhitehorn					free(md->fstab->fs_vfstype);
131218799Snwhitehorn					free(md->fstab->fs_mntops);
132218799Snwhitehorn					free(md->fstab->fs_type);
133218799Snwhitehorn					free(md->fstab);
134218799Snwhitehorn				}
135218799Snwhitehorn				if (md->newfs != NULL)
136218799Snwhitehorn					free(md->newfs);
137218799Snwhitehorn				free(md->name);
138218799Snwhitehorn
139218799Snwhitehorn				TAILQ_REMOVE(&part_metadata, md, metadata);
140218799Snwhitehorn				free(md);
141218799Snwhitehorn			}
142218799Snwhitehorn			init_fstab_metadata();
143218799Snwhitehorn			break;
144218799Snwhitehorn		case 4: /* Auto */
145218799Snwhitehorn			part_wizard();
146218799Snwhitehorn			break;
147218799Snwhitehorn		}
148218799Snwhitehorn
149218799Snwhitehorn		error = 0;
150219391Snwhitehorn		if (op == 5) { /* Finished */
151225066Snwhitehorn			dialog_vars.ok_label = __DECONST(char *, "Commit");
152225066Snwhitehorn			dialog_vars.extra_label =
153225066Snwhitehorn			    __DECONST(char *, "Revert & Exit");
154218799Snwhitehorn			dialog_vars.extra_button = TRUE;
155225066Snwhitehorn			dialog_vars.cancel_label = __DECONST(char *, "Back");
156218799Snwhitehorn			op = dialog_yesno("Confirmation", "Your changes will "
157218799Snwhitehorn			    "now be written to disk. If you have chosen to "
158218799Snwhitehorn			    "overwrite existing data, it will be PERMANENTLY "
159225066Snwhitehorn			    "ERASED. Are you sure you want to commit your "
160225066Snwhitehorn			    "changes?", 0, 0);
161225066Snwhitehorn			dialog_vars.ok_label = NULL;
162218799Snwhitehorn			dialog_vars.extra_button = FALSE;
163225066Snwhitehorn			dialog_vars.cancel_label = NULL;
164218799Snwhitehorn
165219391Snwhitehorn			if (op == 0 && validate_setup()) { /* Save */
166218799Snwhitehorn				error = apply_changes(&mesh);
167218799Snwhitehorn				break;
168225066Snwhitehorn			} else if (op == 3) { /* Quit */
169218799Snwhitehorn				gpart_revert_all(&mesh);
170218799Snwhitehorn				error =	-1;
171218799Snwhitehorn				break;
172218799Snwhitehorn			}
173218799Snwhitehorn		}
174218799Snwhitehorn
175218799Snwhitehorn		geom_deletetree(&mesh);
176218799Snwhitehorn		free(items);
177218799Snwhitehorn	}
178218799Snwhitehorn
179218799Snwhitehorn
180218799Snwhitehorn	geom_deletetree(&mesh);
181218799Snwhitehorn	free(items);
182218799Snwhitehorn	end_dialog();
183218799Snwhitehorn
184218799Snwhitehorn	return (error);
185218799Snwhitehorn}
186218799Snwhitehorn
187218799Snwhitehornstruct partition_metadata *
188218799Snwhitehornget_part_metadata(const char *name, int create)
189218799Snwhitehorn{
190218799Snwhitehorn	struct partition_metadata *md;
191218799Snwhitehorn
192218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata)
193218799Snwhitehorn		if (md->name != NULL && strcmp(md->name, name) == 0)
194218799Snwhitehorn			break;
195218799Snwhitehorn
196218799Snwhitehorn	if (md == NULL && create) {
197218799Snwhitehorn		md = calloc(1, sizeof(*md));
198218799Snwhitehorn		md->name = strdup(name);
199218799Snwhitehorn		TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
200218799Snwhitehorn	}
201218799Snwhitehorn
202218799Snwhitehorn	return (md);
203218799Snwhitehorn}
204218799Snwhitehorn
205218799Snwhitehornvoid
206225066Snwhitehorndelete_part_metadata(const char *name)
207225066Snwhitehorn{
208218799Snwhitehorn	struct partition_metadata *md;
209218799Snwhitehorn
210218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
211218799Snwhitehorn		if (md->name != NULL && strcmp(md->name, name) == 0) {
212218799Snwhitehorn			if (md->fstab != NULL) {
213218799Snwhitehorn				free(md->fstab->fs_spec);
214218799Snwhitehorn				free(md->fstab->fs_file);
215218799Snwhitehorn				free(md->fstab->fs_vfstype);
216218799Snwhitehorn				free(md->fstab->fs_mntops);
217218799Snwhitehorn				free(md->fstab->fs_type);
218218799Snwhitehorn				free(md->fstab);
219218799Snwhitehorn			}
220218799Snwhitehorn			if (md->newfs != NULL)
221218799Snwhitehorn				free(md->newfs);
222218799Snwhitehorn			free(md->name);
223218799Snwhitehorn
224218799Snwhitehorn			TAILQ_REMOVE(&part_metadata, md, metadata);
225218799Snwhitehorn			free(md);
226218799Snwhitehorn			break;
227218799Snwhitehorn		}
228218799Snwhitehorn	}
229218799Snwhitehorn}
230218799Snwhitehorn
231218799Snwhitehornstatic int
232218799Snwhitehornvalidate_setup(void)
233218799Snwhitehorn{
234218799Snwhitehorn	struct partition_metadata *md;
235218799Snwhitehorn	int root_found = FALSE;
236218799Snwhitehorn
237218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
238218799Snwhitehorn		if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0)
239218799Snwhitehorn			root_found = TRUE;
240218799Snwhitehorn
241218799Snwhitehorn		/* XXX: Check for duplicate mountpoints */
242218799Snwhitehorn	}
243218799Snwhitehorn
244218799Snwhitehorn	if (!root_found) {
245218799Snwhitehorn		dialog_msgbox("Error", "No root partition was found. "
246218799Snwhitehorn		    "The root FreeBSD partition must have a mountpoint of '/'.",
247218799Snwhitehorn		0, 0, TRUE);
248218799Snwhitehorn		return (FALSE);
249218799Snwhitehorn	}
250218799Snwhitehorn
251218799Snwhitehorn	return (TRUE);
252218799Snwhitehorn}
253218799Snwhitehorn
254218799Snwhitehornstatic int
255218799Snwhitehornapply_changes(struct gmesh *mesh)
256218799Snwhitehorn{
257218799Snwhitehorn	struct partition_metadata *md;
258218799Snwhitehorn	char message[512];
259218799Snwhitehorn	int i, nitems, error;
260218799Snwhitehorn	const char **items;
261218799Snwhitehorn	const char *fstab_path;
262218799Snwhitehorn	FILE *fstab;
263218799Snwhitehorn
264218799Snwhitehorn	nitems = 1; /* Partition table changes */
265218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
266218799Snwhitehorn		if (md->newfs != NULL)
267218799Snwhitehorn			nitems++;
268218799Snwhitehorn	}
269218799Snwhitehorn	items = calloc(nitems * 2, sizeof(const char *));
270218799Snwhitehorn	items[0] = "Writing partition tables";
271218799Snwhitehorn	items[1] = "7"; /* In progress */
272218799Snwhitehorn	i = 1;
273218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
274218799Snwhitehorn		if (md->newfs != NULL) {
275218799Snwhitehorn			char *item;
276218799Snwhitehorn			item = malloc(255);
277218799Snwhitehorn			sprintf(item, "Initializing %s", md->name);
278218799Snwhitehorn			items[i*2] = item;
279218799Snwhitehorn			items[i*2 + 1] = "Pending";
280218799Snwhitehorn			i++;
281218799Snwhitehorn		}
282218799Snwhitehorn	}
283218799Snwhitehorn
284218799Snwhitehorn	i = 0;
285218799Snwhitehorn	dialog_mixedgauge("Initializing",
286218799Snwhitehorn	    "Initializing file systems. Please wait.", 0, 0, i*100/nitems,
287218799Snwhitehorn	    nitems, __DECONST(char **, items));
288218799Snwhitehorn	gpart_commit(mesh);
289218799Snwhitehorn	items[i*2 + 1] = "3";
290218799Snwhitehorn	i++;
291218799Snwhitehorn
292218799Snwhitehorn	if (getenv("BSDINSTALL_LOG") == NULL)
293218799Snwhitehorn		setenv("BSDINSTALL_LOG", "/dev/null", 1);
294218799Snwhitehorn
295218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
296218799Snwhitehorn		if (md->newfs != NULL) {
297218799Snwhitehorn			items[i*2 + 1] = "7"; /* In progress */
298218799Snwhitehorn			dialog_mixedgauge("Initializing",
299218799Snwhitehorn			    "Initializing file systems. Please wait.", 0, 0,
300218799Snwhitehorn			    i*100/nitems, nitems, __DECONST(char **, items));
301218799Snwhitehorn			sprintf(message, "(echo %s; %s) >>%s 2>>%s",
302218799Snwhitehorn			    md->newfs, md->newfs, getenv("BSDINSTALL_LOG"),
303218799Snwhitehorn			    getenv("BSDINSTALL_LOG"));
304218799Snwhitehorn			error = system(message);
305218799Snwhitehorn			items[i*2 + 1] = (error == 0) ? "3" : "1";
306218799Snwhitehorn			i++;
307218799Snwhitehorn		}
308218799Snwhitehorn	}
309218799Snwhitehorn	dialog_mixedgauge("Initializing",
310218799Snwhitehorn	    "Initializing file systems. Please wait.", 0, 0,
311218799Snwhitehorn	    i*100/nitems, nitems, __DECONST(char **, items));
312218799Snwhitehorn
313218799Snwhitehorn	for (i = 1; i < nitems; i++)
314218799Snwhitehorn		free(__DECONST(char *, items[i*2]));
315218799Snwhitehorn	free(items);
316218799Snwhitehorn
317218799Snwhitehorn	if (getenv("PATH_FSTAB") != NULL)
318218799Snwhitehorn		fstab_path = getenv("PATH_FSTAB");
319218799Snwhitehorn	else
320218799Snwhitehorn		fstab_path = "/etc/fstab";
321218799Snwhitehorn	fstab = fopen(fstab_path, "w+");
322218799Snwhitehorn	if (fstab == NULL) {
323218799Snwhitehorn		sprintf(message, "Cannot open fstab file %s for writing (%s)\n",
324218799Snwhitehorn		    getenv("PATH_FSTAB"), strerror(errno));
325218799Snwhitehorn		dialog_msgbox("Error", message, 0, 0, TRUE);
326218799Snwhitehorn		return (-1);
327218799Snwhitehorn	}
328218799Snwhitehorn	fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n");
329218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
330218799Snwhitehorn		if (md->fstab != NULL)
331223832Skevlo			fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n",
332218799Snwhitehorn			    md->fstab->fs_spec, md->fstab->fs_file,
333218799Snwhitehorn			    md->fstab->fs_vfstype, md->fstab->fs_mntops,
334218799Snwhitehorn			    md->fstab->fs_freq, md->fstab->fs_passno);
335218799Snwhitehorn	}
336218799Snwhitehorn	fclose(fstab);
337218799Snwhitehorn
338218799Snwhitehorn	return (0);
339218799Snwhitehorn}
340218799Snwhitehorn
341218799Snwhitehornstatic struct partedit_item *
342225066Snwhitehornread_geom_mesh(struct gmesh *mesh, int *nitems)
343225066Snwhitehorn{
344218799Snwhitehorn	struct gclass *classp;
345218799Snwhitehorn	struct ggeom *gp;
346218799Snwhitehorn	struct partedit_item *items;
347218799Snwhitehorn
348218799Snwhitehorn	*nitems = 0;
349218799Snwhitehorn	items = NULL;
350218799Snwhitehorn
351218799Snwhitehorn	/*
352218799Snwhitehorn	 * Build the device table. First add all disks (and CDs).
353218799Snwhitehorn	 */
354218799Snwhitehorn
355218799Snwhitehorn	LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
356218799Snwhitehorn		if (strcmp(classp->lg_name, "DISK") != 0 &&
357225066Snwhitehorn		    strcmp(classp->lg_name, "MD") != 0)
358218799Snwhitehorn			continue;
359218799Snwhitehorn
360218799Snwhitehorn		/* Now recurse into all children */
361218799Snwhitehorn		LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
362218799Snwhitehorn			add_geom_children(gp, 0, &items, nitems);
363218799Snwhitehorn	}
364218799Snwhitehorn
365218799Snwhitehorn	return (items);
366218799Snwhitehorn}
367218799Snwhitehorn
368218799Snwhitehornstatic void
369218799Snwhitehornadd_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items,
370225066Snwhitehorn    int *nitems)
371225066Snwhitehorn{
372218799Snwhitehorn	struct gconsumer *cp;
373218799Snwhitehorn	struct gprovider *pp;
374218799Snwhitehorn	struct gconfig *gc;
375218799Snwhitehorn
376218799Snwhitehorn	if (strcmp(gp->lg_class->lg_name, "PART") == 0 &&
377218799Snwhitehorn	    !LIST_EMPTY(&gp->lg_config)) {
378218799Snwhitehorn		LIST_FOREACH(gc, &gp->lg_config, lg_config) {
379218799Snwhitehorn			if (strcmp(gc->lg_name, "scheme") == 0)
380218799Snwhitehorn				(*items)[*nitems-1].type = gc->lg_val;
381218799Snwhitehorn		}
382218799Snwhitehorn	}
383218799Snwhitehorn
384218799Snwhitehorn	if (LIST_EMPTY(&gp->lg_provider))
385218799Snwhitehorn		return;
386218799Snwhitehorn
387218799Snwhitehorn	LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
388218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "LABEL") == 0)
389218799Snwhitehorn			continue;
390218799Snwhitehorn
391218799Snwhitehorn		/* Skip WORM media */
392218799Snwhitehorn		if (strncmp(pp->lg_name, "cd", 2) == 0)
393218799Snwhitehorn			continue;
394218799Snwhitehorn
395218799Snwhitehorn		*items = realloc(*items,
396218799Snwhitehorn		    (*nitems+1)*sizeof(struct partedit_item));
397218799Snwhitehorn		(*items)[*nitems].indentation = recurse;
398218799Snwhitehorn		(*items)[*nitems].name = pp->lg_name;
399218799Snwhitehorn		(*items)[*nitems].size = pp->lg_mediasize;
400218799Snwhitehorn		(*items)[*nitems].mountpoint = NULL;
401218799Snwhitehorn		(*items)[*nitems].type = "";
402218799Snwhitehorn		(*items)[*nitems].cookie = pp;
403218799Snwhitehorn
404218799Snwhitehorn		LIST_FOREACH(gc, &pp->lg_config, lg_config) {
405218799Snwhitehorn			if (strcmp(gc->lg_name, "type") == 0)
406218799Snwhitehorn				(*items)[*nitems].type = gc->lg_val;
407218799Snwhitehorn		}
408218799Snwhitehorn
409218799Snwhitehorn		/* Skip swap-backed MD devices */
410218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "MD") == 0 &&
411218799Snwhitehorn		    strcmp((*items)[*nitems].type, "swap") == 0)
412218799Snwhitehorn			continue;
413218799Snwhitehorn
414218799Snwhitehorn		(*nitems)++;
415218799Snwhitehorn
416218799Snwhitehorn		LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
417218799Snwhitehorn			add_geom_children(cp->lg_geom, recurse+1, items,
418218799Snwhitehorn			    nitems);
419218799Snwhitehorn
420218799Snwhitehorn		/* Only use first provider for acd */
421218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "ACD") == 0)
422218799Snwhitehorn			break;
423218799Snwhitehorn	}
424218799Snwhitehorn}
425218799Snwhitehorn
426218799Snwhitehornstatic void
427218799Snwhitehorninit_fstab_metadata(void)
428218799Snwhitehorn{
429218799Snwhitehorn	struct fstab *fstab;
430218799Snwhitehorn	struct partition_metadata *md;
431218799Snwhitehorn
432218799Snwhitehorn	setfsent();
433218799Snwhitehorn	while ((fstab = getfsent()) != NULL) {
434218799Snwhitehorn		md = calloc(1, sizeof(struct partition_metadata));
435218799Snwhitehorn
436218799Snwhitehorn		md->name = NULL;
437218799Snwhitehorn		if (strncmp(fstab->fs_spec, "/dev/", 5) == 0)
438218799Snwhitehorn			md->name = strdup(&fstab->fs_spec[5]);
439218799Snwhitehorn
440218799Snwhitehorn		md->fstab = malloc(sizeof(struct fstab));
441218799Snwhitehorn		md->fstab->fs_spec = strdup(fstab->fs_spec);
442218799Snwhitehorn		md->fstab->fs_file = strdup(fstab->fs_file);
443218799Snwhitehorn		md->fstab->fs_vfstype = strdup(fstab->fs_vfstype);
444218799Snwhitehorn		md->fstab->fs_mntops = strdup(fstab->fs_mntops);
445218799Snwhitehorn		md->fstab->fs_type = strdup(fstab->fs_type);
446218799Snwhitehorn		md->fstab->fs_freq = fstab->fs_freq;
447218799Snwhitehorn		md->fstab->fs_passno = fstab->fs_passno;
448218799Snwhitehorn
449218799Snwhitehorn		md->newfs = NULL;
450218799Snwhitehorn
451218799Snwhitehorn		TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
452218799Snwhitehorn	}
453218799Snwhitehorn}
454218799Snwhitehorn
455218799Snwhitehornstatic void
456218799Snwhitehornget_mount_points(struct partedit_item *items, int nitems)
457218799Snwhitehorn{
458218799Snwhitehorn	struct partition_metadata *md;
459218799Snwhitehorn	int i;
460218799Snwhitehorn
461218799Snwhitehorn	for (i = 0; i < nitems; i++) {
462218799Snwhitehorn		TAILQ_FOREACH(md, &part_metadata, metadata) {
463218799Snwhitehorn			if (md->name != NULL && md->fstab != NULL &&
464218799Snwhitehorn			    strcmp(md->name, items[i].name) == 0) {
465218799Snwhitehorn				items[i].mountpoint = md->fstab->fs_file;
466218799Snwhitehorn				break;
467218799Snwhitehorn			}
468218799Snwhitehorn		}
469218799Snwhitehorn	}
470218799Snwhitehorn}
471