partedit.c revision 273831
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: stable/10/usr.sbin/bsdinstall/partedit/partedit.c 273831 2014-10-29 16:48:18Z 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;
44244858Snwhitehornstatic int sade_mode = 0;
45218799Snwhitehorn
46218799Snwhitehornstatic int apply_changes(struct gmesh *mesh);
47218799Snwhitehornstatic struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems);
48218799Snwhitehornstatic void add_geom_children(struct ggeom *gp, int recurse,
49218799Snwhitehorn    struct partedit_item **items, int *nitems);
50218799Snwhitehornstatic void init_fstab_metadata(void);
51218799Snwhitehornstatic void get_mount_points(struct partedit_item *items, int nitems);
52218799Snwhitehornstatic int validate_setup(void);
53218799Snwhitehorn
54225066Snwhitehornstatic void
55225066Snwhitehornsigint_handler(int sig)
56225066Snwhitehorn{
57225066Snwhitehorn	struct gmesh mesh;
58225066Snwhitehorn
59225066Snwhitehorn	/* Revert all changes and exit dialog-mode cleanly on SIGINT */
60225066Snwhitehorn	geom_gettree(&mesh);
61225066Snwhitehorn	gpart_revert_all(&mesh);
62225066Snwhitehorn	geom_deletetree(&mesh);
63225066Snwhitehorn
64225066Snwhitehorn	end_dialog();
65225066Snwhitehorn
66225066Snwhitehorn	exit(1);
67225066Snwhitehorn}
68225066Snwhitehorn
69218799Snwhitehornint
70225066Snwhitehornmain(int argc, const char **argv)
71225066Snwhitehorn{
72218799Snwhitehorn	struct partition_metadata *md;
73218799Snwhitehorn	const char *prompt;
74226739Snwhitehorn	struct partedit_item *items = NULL;
75218799Snwhitehorn	struct gmesh mesh;
76218799Snwhitehorn	int i, op, nitems, nscroll;
77218799Snwhitehorn	int error;
78218799Snwhitehorn
79244858Snwhitehorn	if (strcmp(basename(argv[0]), "sade") == 0)
80244858Snwhitehorn		sade_mode = 1;
81244858Snwhitehorn
82218799Snwhitehorn	TAILQ_INIT(&part_metadata);
83218799Snwhitehorn
84218799Snwhitehorn	init_fstab_metadata();
85218799Snwhitehorn
86218799Snwhitehorn	init_dialog(stdin, stdout);
87244858Snwhitehorn	if (!sade_mode)
88218799Snwhitehorn		dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
89218799Snwhitehorn	dialog_vars.item_help = TRUE;
90218799Snwhitehorn	nscroll = i = 0;
91218799Snwhitehorn
92225066Snwhitehorn	/* Revert changes on SIGINT */
93225066Snwhitehorn	signal(SIGINT, sigint_handler);
94225066Snwhitehorn
95218799Snwhitehorn	if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */
96218799Snwhitehorn		prompt = "Please review the disk setup. When complete, press "
97225066Snwhitehorn		    "the Finish button.";
98273831Snwhitehorn		/* Experimental ZFS autopartition support */
99273831Snwhitehorn		if (argc > 1 && strcmp(argv[1], "zfs") == 0) {
100273831Snwhitehorn			part_wizard("zfs");
101273831Snwhitehorn		} else {
102273831Snwhitehorn			part_wizard("ufs");
103273831Snwhitehorn		}
104245700Snwhitehorn	} else if (strcmp(basename(argv[0]), "scriptedpart") == 0) {
105245796Snwhitehorn		error = scripted_editor(argc, argv);
106245700Snwhitehorn		prompt = NULL;
107245796Snwhitehorn		if (error != 0) {
108245796Snwhitehorn			end_dialog();
109245796Snwhitehorn			return (error);
110245796Snwhitehorn		}
111218799Snwhitehorn	} else {
112218799Snwhitehorn		prompt = "Create partitions for FreeBSD. No changes will be "
113225066Snwhitehorn		    "made until you select Finish.";
114218799Snwhitehorn	}
115218799Snwhitehorn
116218799Snwhitehorn	/* Show the part editor either immediately, or to confirm wizard */
117245700Snwhitehorn	while (prompt != NULL) {
118218799Snwhitehorn		dlg_clear();
119218799Snwhitehorn		dlg_put_backtitle();
120218799Snwhitehorn
121226739Snwhitehorn		error = geom_gettree(&mesh);
122226739Snwhitehorn		if (error == 0)
123226739Snwhitehorn			items = read_geom_mesh(&mesh, &nitems);
124226739Snwhitehorn		if (error || items == NULL) {
125226739Snwhitehorn			dialog_msgbox("Error", "No disks found. If you need to "
126226739Snwhitehorn			    "install a kernel driver, choose Shell at the "
127226739Snwhitehorn			    "installation menu.", 0, 0, TRUE);
128226739Snwhitehorn			break;
129226739Snwhitehorn		}
130226739Snwhitehorn
131226739Snwhitehorn		get_mount_points(items, nitems);
132226739Snwhitehorn
133218799Snwhitehorn		if (i >= nitems)
134218799Snwhitehorn			i = nitems - 1;
135218799Snwhitehorn		op = diskeditor_show("Partition Editor", prompt,
136218799Snwhitehorn		    items, nitems, &i, &nscroll);
137218799Snwhitehorn
138218799Snwhitehorn		switch (op) {
139218799Snwhitehorn		case 0: /* Create */
140218799Snwhitehorn			gpart_create((struct gprovider *)(items[i].cookie),
141218799Snwhitehorn			    NULL, NULL, NULL, NULL, 1);
142218799Snwhitehorn			break;
143218799Snwhitehorn		case 1: /* Delete */
144218799Snwhitehorn			gpart_delete((struct gprovider *)(items[i].cookie));
145218799Snwhitehorn			break;
146218799Snwhitehorn		case 2: /* Modify */
147218799Snwhitehorn			gpart_edit((struct gprovider *)(items[i].cookie));
148218799Snwhitehorn			break;
149218799Snwhitehorn		case 3: /* Revert */
150218799Snwhitehorn			gpart_revert_all(&mesh);
151218799Snwhitehorn			while ((md = TAILQ_FIRST(&part_metadata)) != NULL) {
152218799Snwhitehorn				if (md->fstab != NULL) {
153218799Snwhitehorn					free(md->fstab->fs_spec);
154218799Snwhitehorn					free(md->fstab->fs_file);
155218799Snwhitehorn					free(md->fstab->fs_vfstype);
156218799Snwhitehorn					free(md->fstab->fs_mntops);
157218799Snwhitehorn					free(md->fstab->fs_type);
158218799Snwhitehorn					free(md->fstab);
159218799Snwhitehorn				}
160218799Snwhitehorn				if (md->newfs != NULL)
161218799Snwhitehorn					free(md->newfs);
162218799Snwhitehorn				free(md->name);
163218799Snwhitehorn
164218799Snwhitehorn				TAILQ_REMOVE(&part_metadata, md, metadata);
165218799Snwhitehorn				free(md);
166218799Snwhitehorn			}
167218799Snwhitehorn			init_fstab_metadata();
168218799Snwhitehorn			break;
169218799Snwhitehorn		case 4: /* Auto */
170273831Snwhitehorn			part_wizard("ufs");
171218799Snwhitehorn			break;
172218799Snwhitehorn		}
173218799Snwhitehorn
174218799Snwhitehorn		error = 0;
175219391Snwhitehorn		if (op == 5) { /* Finished */
176225066Snwhitehorn			dialog_vars.ok_label = __DECONST(char *, "Commit");
177225066Snwhitehorn			dialog_vars.extra_label =
178225066Snwhitehorn			    __DECONST(char *, "Revert & Exit");
179218799Snwhitehorn			dialog_vars.extra_button = TRUE;
180225066Snwhitehorn			dialog_vars.cancel_label = __DECONST(char *, "Back");
181218799Snwhitehorn			op = dialog_yesno("Confirmation", "Your changes will "
182218799Snwhitehorn			    "now be written to disk. If you have chosen to "
183218799Snwhitehorn			    "overwrite existing data, it will be PERMANENTLY "
184225066Snwhitehorn			    "ERASED. Are you sure you want to commit your "
185225066Snwhitehorn			    "changes?", 0, 0);
186225066Snwhitehorn			dialog_vars.ok_label = NULL;
187218799Snwhitehorn			dialog_vars.extra_button = FALSE;
188225066Snwhitehorn			dialog_vars.cancel_label = NULL;
189218799Snwhitehorn
190219391Snwhitehorn			if (op == 0 && validate_setup()) { /* Save */
191218799Snwhitehorn				error = apply_changes(&mesh);
192218799Snwhitehorn				break;
193225066Snwhitehorn			} else if (op == 3) { /* Quit */
194218799Snwhitehorn				gpart_revert_all(&mesh);
195218799Snwhitehorn				error =	-1;
196218799Snwhitehorn				break;
197218799Snwhitehorn			}
198218799Snwhitehorn		}
199218799Snwhitehorn
200218799Snwhitehorn		geom_deletetree(&mesh);
201218799Snwhitehorn		free(items);
202218799Snwhitehorn	}
203218799Snwhitehorn
204245700Snwhitehorn	if (prompt == NULL) {
205245700Snwhitehorn		error = geom_gettree(&mesh);
206245700Snwhitehorn		if (validate_setup()) {
207245700Snwhitehorn			error = apply_changes(&mesh);
208245700Snwhitehorn		} else {
209245700Snwhitehorn			gpart_revert_all(&mesh);
210245700Snwhitehorn			error = -1;
211245700Snwhitehorn		}
212245700Snwhitehorn	}
213218799Snwhitehorn
214218799Snwhitehorn	geom_deletetree(&mesh);
215218799Snwhitehorn	free(items);
216218799Snwhitehorn	end_dialog();
217218799Snwhitehorn
218218799Snwhitehorn	return (error);
219218799Snwhitehorn}
220218799Snwhitehorn
221218799Snwhitehornstruct partition_metadata *
222218799Snwhitehornget_part_metadata(const char *name, int create)
223218799Snwhitehorn{
224218799Snwhitehorn	struct partition_metadata *md;
225218799Snwhitehorn
226218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata)
227218799Snwhitehorn		if (md->name != NULL && strcmp(md->name, name) == 0)
228218799Snwhitehorn			break;
229218799Snwhitehorn
230218799Snwhitehorn	if (md == NULL && create) {
231218799Snwhitehorn		md = calloc(1, sizeof(*md));
232218799Snwhitehorn		md->name = strdup(name);
233218799Snwhitehorn		TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
234218799Snwhitehorn	}
235218799Snwhitehorn
236218799Snwhitehorn	return (md);
237218799Snwhitehorn}
238218799Snwhitehorn
239218799Snwhitehornvoid
240225066Snwhitehorndelete_part_metadata(const char *name)
241225066Snwhitehorn{
242218799Snwhitehorn	struct partition_metadata *md;
243218799Snwhitehorn
244218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
245218799Snwhitehorn		if (md->name != NULL && strcmp(md->name, name) == 0) {
246218799Snwhitehorn			if (md->fstab != NULL) {
247218799Snwhitehorn				free(md->fstab->fs_spec);
248218799Snwhitehorn				free(md->fstab->fs_file);
249218799Snwhitehorn				free(md->fstab->fs_vfstype);
250218799Snwhitehorn				free(md->fstab->fs_mntops);
251218799Snwhitehorn				free(md->fstab->fs_type);
252218799Snwhitehorn				free(md->fstab);
253218799Snwhitehorn			}
254218799Snwhitehorn			if (md->newfs != NULL)
255218799Snwhitehorn				free(md->newfs);
256218799Snwhitehorn			free(md->name);
257218799Snwhitehorn
258218799Snwhitehorn			TAILQ_REMOVE(&part_metadata, md, metadata);
259218799Snwhitehorn			free(md);
260218799Snwhitehorn			break;
261218799Snwhitehorn		}
262218799Snwhitehorn	}
263218799Snwhitehorn}
264218799Snwhitehorn
265218799Snwhitehornstatic int
266218799Snwhitehornvalidate_setup(void)
267218799Snwhitehorn{
268230309Snwhitehorn	struct partition_metadata *md, *root = NULL;
269230309Snwhitehorn	int cancel;
270218799Snwhitehorn
271218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
272218799Snwhitehorn		if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0)
273230309Snwhitehorn			root = md;
274218799Snwhitehorn
275218799Snwhitehorn		/* XXX: Check for duplicate mountpoints */
276218799Snwhitehorn	}
277218799Snwhitehorn
278230309Snwhitehorn	if (root == NULL) {
279218799Snwhitehorn		dialog_msgbox("Error", "No root partition was found. "
280218799Snwhitehorn		    "The root FreeBSD partition must have a mountpoint of '/'.",
281218799Snwhitehorn		0, 0, TRUE);
282218799Snwhitehorn		return (FALSE);
283218799Snwhitehorn	}
284218799Snwhitehorn
285230309Snwhitehorn	/*
286230309Snwhitehorn	 * Check for root partitions that we aren't formatting, which is
287230309Snwhitehorn	 * usually a mistake
288230309Snwhitehorn	 */
289244858Snwhitehorn	if (root->newfs == NULL && !sade_mode) {
290230309Snwhitehorn		dialog_vars.defaultno = TRUE;
291230309Snwhitehorn		cancel = dialog_yesno("Warning", "The chosen root partition "
292230309Snwhitehorn		    "has a preexisting filesystem. If it contains an existing "
293230309Snwhitehorn		    "FreeBSD system, please update it with freebsd-update "
294230309Snwhitehorn		    "instead of installing a new system on it. The partition "
295230309Snwhitehorn		    "can also be erased by pressing \"No\" and then deleting "
296230309Snwhitehorn		    "and recreating it. Are you sure you want to proceed?",
297230309Snwhitehorn		    0, 0);
298230309Snwhitehorn		dialog_vars.defaultno = FALSE;
299230309Snwhitehorn		if (cancel)
300230309Snwhitehorn			return (FALSE);
301230309Snwhitehorn	}
302230309Snwhitehorn
303218799Snwhitehorn	return (TRUE);
304218799Snwhitehorn}
305218799Snwhitehorn
306218799Snwhitehornstatic int
307218799Snwhitehornapply_changes(struct gmesh *mesh)
308218799Snwhitehorn{
309218799Snwhitehorn	struct partition_metadata *md;
310218799Snwhitehorn	char message[512];
311218799Snwhitehorn	int i, nitems, error;
312218799Snwhitehorn	const char **items;
313218799Snwhitehorn	const char *fstab_path;
314218799Snwhitehorn	FILE *fstab;
315218799Snwhitehorn
316218799Snwhitehorn	nitems = 1; /* Partition table changes */
317218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
318218799Snwhitehorn		if (md->newfs != NULL)
319218799Snwhitehorn			nitems++;
320218799Snwhitehorn	}
321218799Snwhitehorn	items = calloc(nitems * 2, sizeof(const char *));
322218799Snwhitehorn	items[0] = "Writing partition tables";
323218799Snwhitehorn	items[1] = "7"; /* In progress */
324218799Snwhitehorn	i = 1;
325218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
326218799Snwhitehorn		if (md->newfs != NULL) {
327218799Snwhitehorn			char *item;
328218799Snwhitehorn			item = malloc(255);
329218799Snwhitehorn			sprintf(item, "Initializing %s", md->name);
330218799Snwhitehorn			items[i*2] = item;
331218799Snwhitehorn			items[i*2 + 1] = "Pending";
332218799Snwhitehorn			i++;
333218799Snwhitehorn		}
334218799Snwhitehorn	}
335218799Snwhitehorn
336218799Snwhitehorn	i = 0;
337218799Snwhitehorn	dialog_mixedgauge("Initializing",
338218799Snwhitehorn	    "Initializing file systems. Please wait.", 0, 0, i*100/nitems,
339218799Snwhitehorn	    nitems, __DECONST(char **, items));
340218799Snwhitehorn	gpart_commit(mesh);
341218799Snwhitehorn	items[i*2 + 1] = "3";
342218799Snwhitehorn	i++;
343218799Snwhitehorn
344218799Snwhitehorn	if (getenv("BSDINSTALL_LOG") == NULL)
345218799Snwhitehorn		setenv("BSDINSTALL_LOG", "/dev/null", 1);
346218799Snwhitehorn
347218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
348218799Snwhitehorn		if (md->newfs != NULL) {
349218799Snwhitehorn			items[i*2 + 1] = "7"; /* In progress */
350218799Snwhitehorn			dialog_mixedgauge("Initializing",
351218799Snwhitehorn			    "Initializing file systems. Please wait.", 0, 0,
352218799Snwhitehorn			    i*100/nitems, nitems, __DECONST(char **, items));
353218799Snwhitehorn			sprintf(message, "(echo %s; %s) >>%s 2>>%s",
354218799Snwhitehorn			    md->newfs, md->newfs, getenv("BSDINSTALL_LOG"),
355218799Snwhitehorn			    getenv("BSDINSTALL_LOG"));
356218799Snwhitehorn			error = system(message);
357218799Snwhitehorn			items[i*2 + 1] = (error == 0) ? "3" : "1";
358218799Snwhitehorn			i++;
359218799Snwhitehorn		}
360218799Snwhitehorn	}
361218799Snwhitehorn	dialog_mixedgauge("Initializing",
362218799Snwhitehorn	    "Initializing file systems. Please wait.", 0, 0,
363218799Snwhitehorn	    i*100/nitems, nitems, __DECONST(char **, items));
364218799Snwhitehorn
365218799Snwhitehorn	for (i = 1; i < nitems; i++)
366218799Snwhitehorn		free(__DECONST(char *, items[i*2]));
367218799Snwhitehorn	free(items);
368218799Snwhitehorn
369218799Snwhitehorn	if (getenv("PATH_FSTAB") != NULL)
370218799Snwhitehorn		fstab_path = getenv("PATH_FSTAB");
371218799Snwhitehorn	else
372218799Snwhitehorn		fstab_path = "/etc/fstab";
373218799Snwhitehorn	fstab = fopen(fstab_path, "w+");
374218799Snwhitehorn	if (fstab == NULL) {
375218799Snwhitehorn		sprintf(message, "Cannot open fstab file %s for writing (%s)\n",
376218799Snwhitehorn		    getenv("PATH_FSTAB"), strerror(errno));
377218799Snwhitehorn		dialog_msgbox("Error", message, 0, 0, TRUE);
378218799Snwhitehorn		return (-1);
379218799Snwhitehorn	}
380218799Snwhitehorn	fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n");
381218799Snwhitehorn	TAILQ_FOREACH(md, &part_metadata, metadata) {
382218799Snwhitehorn		if (md->fstab != NULL)
383223832Skevlo			fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n",
384218799Snwhitehorn			    md->fstab->fs_spec, md->fstab->fs_file,
385218799Snwhitehorn			    md->fstab->fs_vfstype, md->fstab->fs_mntops,
386218799Snwhitehorn			    md->fstab->fs_freq, md->fstab->fs_passno);
387218799Snwhitehorn	}
388218799Snwhitehorn	fclose(fstab);
389218799Snwhitehorn
390218799Snwhitehorn	return (0);
391218799Snwhitehorn}
392218799Snwhitehorn
393218799Snwhitehornstatic struct partedit_item *
394225066Snwhitehornread_geom_mesh(struct gmesh *mesh, int *nitems)
395225066Snwhitehorn{
396218799Snwhitehorn	struct gclass *classp;
397218799Snwhitehorn	struct ggeom *gp;
398218799Snwhitehorn	struct partedit_item *items;
399218799Snwhitehorn
400218799Snwhitehorn	*nitems = 0;
401218799Snwhitehorn	items = NULL;
402218799Snwhitehorn
403218799Snwhitehorn	/*
404218799Snwhitehorn	 * Build the device table. First add all disks (and CDs).
405218799Snwhitehorn	 */
406218799Snwhitehorn
407218799Snwhitehorn	LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
408218799Snwhitehorn		if (strcmp(classp->lg_name, "DISK") != 0 &&
409225066Snwhitehorn		    strcmp(classp->lg_name, "MD") != 0)
410218799Snwhitehorn			continue;
411218799Snwhitehorn
412218799Snwhitehorn		/* Now recurse into all children */
413218799Snwhitehorn		LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
414218799Snwhitehorn			add_geom_children(gp, 0, &items, nitems);
415218799Snwhitehorn	}
416218799Snwhitehorn
417218799Snwhitehorn	return (items);
418218799Snwhitehorn}
419218799Snwhitehorn
420218799Snwhitehornstatic void
421218799Snwhitehornadd_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items,
422225066Snwhitehorn    int *nitems)
423225066Snwhitehorn{
424218799Snwhitehorn	struct gconsumer *cp;
425218799Snwhitehorn	struct gprovider *pp;
426218799Snwhitehorn	struct gconfig *gc;
427218799Snwhitehorn
428218799Snwhitehorn	if (strcmp(gp->lg_class->lg_name, "PART") == 0 &&
429218799Snwhitehorn	    !LIST_EMPTY(&gp->lg_config)) {
430218799Snwhitehorn		LIST_FOREACH(gc, &gp->lg_config, lg_config) {
431218799Snwhitehorn			if (strcmp(gc->lg_name, "scheme") == 0)
432218799Snwhitehorn				(*items)[*nitems-1].type = gc->lg_val;
433218799Snwhitehorn		}
434218799Snwhitehorn	}
435218799Snwhitehorn
436218799Snwhitehorn	if (LIST_EMPTY(&gp->lg_provider))
437218799Snwhitehorn		return;
438218799Snwhitehorn
439218799Snwhitehorn	LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
440218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "LABEL") == 0)
441218799Snwhitehorn			continue;
442218799Snwhitehorn
443218799Snwhitehorn		/* Skip WORM media */
444218799Snwhitehorn		if (strncmp(pp->lg_name, "cd", 2) == 0)
445218799Snwhitehorn			continue;
446218799Snwhitehorn
447218799Snwhitehorn		*items = realloc(*items,
448218799Snwhitehorn		    (*nitems+1)*sizeof(struct partedit_item));
449218799Snwhitehorn		(*items)[*nitems].indentation = recurse;
450218799Snwhitehorn		(*items)[*nitems].name = pp->lg_name;
451218799Snwhitehorn		(*items)[*nitems].size = pp->lg_mediasize;
452218799Snwhitehorn		(*items)[*nitems].mountpoint = NULL;
453218799Snwhitehorn		(*items)[*nitems].type = "";
454218799Snwhitehorn		(*items)[*nitems].cookie = pp;
455218799Snwhitehorn
456218799Snwhitehorn		LIST_FOREACH(gc, &pp->lg_config, lg_config) {
457218799Snwhitehorn			if (strcmp(gc->lg_name, "type") == 0)
458218799Snwhitehorn				(*items)[*nitems].type = gc->lg_val;
459218799Snwhitehorn		}
460218799Snwhitehorn
461218799Snwhitehorn		/* Skip swap-backed MD devices */
462218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "MD") == 0 &&
463218799Snwhitehorn		    strcmp((*items)[*nitems].type, "swap") == 0)
464218799Snwhitehorn			continue;
465218799Snwhitehorn
466218799Snwhitehorn		(*nitems)++;
467218799Snwhitehorn
468218799Snwhitehorn		LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
469218799Snwhitehorn			add_geom_children(cp->lg_geom, recurse+1, items,
470218799Snwhitehorn			    nitems);
471218799Snwhitehorn
472218799Snwhitehorn		/* Only use first provider for acd */
473218799Snwhitehorn		if (strcmp(gp->lg_class->lg_name, "ACD") == 0)
474218799Snwhitehorn			break;
475218799Snwhitehorn	}
476218799Snwhitehorn}
477218799Snwhitehorn
478218799Snwhitehornstatic void
479218799Snwhitehorninit_fstab_metadata(void)
480218799Snwhitehorn{
481218799Snwhitehorn	struct fstab *fstab;
482218799Snwhitehorn	struct partition_metadata *md;
483218799Snwhitehorn
484218799Snwhitehorn	setfsent();
485218799Snwhitehorn	while ((fstab = getfsent()) != NULL) {
486218799Snwhitehorn		md = calloc(1, sizeof(struct partition_metadata));
487218799Snwhitehorn
488218799Snwhitehorn		md->name = NULL;
489218799Snwhitehorn		if (strncmp(fstab->fs_spec, "/dev/", 5) == 0)
490218799Snwhitehorn			md->name = strdup(&fstab->fs_spec[5]);
491218799Snwhitehorn
492218799Snwhitehorn		md->fstab = malloc(sizeof(struct fstab));
493218799Snwhitehorn		md->fstab->fs_spec = strdup(fstab->fs_spec);
494218799Snwhitehorn		md->fstab->fs_file = strdup(fstab->fs_file);
495218799Snwhitehorn		md->fstab->fs_vfstype = strdup(fstab->fs_vfstype);
496218799Snwhitehorn		md->fstab->fs_mntops = strdup(fstab->fs_mntops);
497218799Snwhitehorn		md->fstab->fs_type = strdup(fstab->fs_type);
498218799Snwhitehorn		md->fstab->fs_freq = fstab->fs_freq;
499218799Snwhitehorn		md->fstab->fs_passno = fstab->fs_passno;
500218799Snwhitehorn
501218799Snwhitehorn		md->newfs = NULL;
502218799Snwhitehorn
503218799Snwhitehorn		TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
504218799Snwhitehorn	}
505218799Snwhitehorn}
506218799Snwhitehorn
507218799Snwhitehornstatic void
508218799Snwhitehornget_mount_points(struct partedit_item *items, int nitems)
509218799Snwhitehorn{
510218799Snwhitehorn	struct partition_metadata *md;
511218799Snwhitehorn	int i;
512218799Snwhitehorn
513218799Snwhitehorn	for (i = 0; i < nitems; i++) {
514218799Snwhitehorn		TAILQ_FOREACH(md, &part_metadata, metadata) {
515218799Snwhitehorn			if (md->name != NULL && md->fstab != NULL &&
516218799Snwhitehorn			    strcmp(md->name, items[i].name) == 0) {
517218799Snwhitehorn				items[i].mountpoint = md->fstab->fs_file;
518218799Snwhitehorn				break;
519218799Snwhitehorn			}
520218799Snwhitehorn		}
521218799Snwhitehorn	}
522218799Snwhitehorn}
523