1245700Snwhitehorn/*-
2245700Snwhitehorn * Copyright (c) 2013 Nathan Whitehorn
3245700Snwhitehorn * All rights reserved.
4245700Snwhitehorn *
5245700Snwhitehorn * Redistribution and use in source and binary forms, with or without
6245700Snwhitehorn * modification, are permitted provided that the following conditions
7245700Snwhitehorn * are met:
8245700Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9245700Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10245700Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11245700Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12245700Snwhitehorn *    documentation and/or other materials provided with the distribution.
13245700Snwhitehorn *
14245700Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15245700Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16245700Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17245700Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18245700Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19245700Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20245700Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21245700Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22245700Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23245700Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24245700Snwhitehorn * SUCH DAMAGE.
25245700Snwhitehorn *
26245700Snwhitehorn * $FreeBSD$
27245700Snwhitehorn */
28245700Snwhitehorn
29245700Snwhitehorn#include <sys/param.h>
30245700Snwhitehorn#include <errno.h>
31245700Snwhitehorn#include <libutil.h>
32245700Snwhitehorn#include <inttypes.h>
33245700Snwhitehorn
34245700Snwhitehorn#include <libgeom.h>
35245700Snwhitehorn#include <dialog.h>
36245700Snwhitehorn#include <dlg_keys.h>
37245700Snwhitehorn
38245700Snwhitehorn#include "partedit.h"
39245700Snwhitehorn
40245700Snwhitehornstatic struct gprovider *
41245700Snwhitehornprovider_for_name(struct gmesh *mesh, const char *name)
42245700Snwhitehorn{
43245700Snwhitehorn	struct gclass *classp;
44245700Snwhitehorn	struct gprovider *pp = NULL;
45245700Snwhitehorn	struct ggeom *gp;
46245700Snwhitehorn
47245700Snwhitehorn	LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
48245700Snwhitehorn		LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
49245700Snwhitehorn			if (LIST_EMPTY(&gp->lg_provider))
50245700Snwhitehorn				continue;
51245700Snwhitehorn
52245700Snwhitehorn			LIST_FOREACH(pp, &gp->lg_provider, lg_provider)
53245700Snwhitehorn				if (strcmp(pp->lg_name, name) == 0)
54245700Snwhitehorn					break;
55245700Snwhitehorn
56245700Snwhitehorn			if (pp != NULL) break;
57245700Snwhitehorn		}
58245700Snwhitehorn
59245700Snwhitehorn		if (pp != NULL) break;
60245700Snwhitehorn	}
61245700Snwhitehorn
62245700Snwhitehorn	return (pp);
63245700Snwhitehorn}
64245700Snwhitehorn
65245700Snwhitehornstatic int
66245700Snwhitehornpart_config(char *disk, const char *scheme, char *config)
67245700Snwhitehorn{
68245700Snwhitehorn	char *partition, *ap, *size = NULL, *type = NULL, *mount = NULL;
69245700Snwhitehorn	struct gclass *classp;
70245700Snwhitehorn	struct gmesh mesh;
71245700Snwhitehorn	struct ggeom *gpart = NULL;
72245700Snwhitehorn	int error;
73245700Snwhitehorn
74245700Snwhitehorn	if (scheme == NULL)
75245700Snwhitehorn		scheme = default_scheme();
76245700Snwhitehorn
77245700Snwhitehorn	error = geom_gettree(&mesh);
78245796Snwhitehorn	if (provider_for_name(&mesh, disk) == NULL) {
79245796Snwhitehorn		fprintf(stderr, "GEOM provider %s not found\n", disk);
80245796Snwhitehorn		geom_deletetree(&mesh);
81245796Snwhitehorn		return (-1);
82245796Snwhitehorn	}
83245700Snwhitehorn
84245700Snwhitehorn	/* Remove any existing partitioning and create new scheme */
85245700Snwhitehorn	LIST_FOREACH(classp, &mesh.lg_class, lg_class)
86245700Snwhitehorn		if (strcmp(classp->lg_name, "PART") == 0)
87245700Snwhitehorn			break;
88245700Snwhitehorn        if (classp != NULL) {
89245700Snwhitehorn		LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
90245700Snwhitehorn		if (strcmp(gpart->lg_name, disk) == 0)
91245700Snwhitehorn			break;
92245700Snwhitehorn	}
93245700Snwhitehorn	if (gpart != NULL)
94245700Snwhitehorn		gpart_destroy(gpart);
95245700Snwhitehorn	gpart_partition(disk, scheme);
96245700Snwhitehorn
97245700Snwhitehorn	if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) {
98245700Snwhitehorn		struct gmesh submesh;
99245700Snwhitehorn		geom_gettree(&submesh);
100245700Snwhitehorn		gpart_create(provider_for_name(&submesh, disk),
101245700Snwhitehorn		    "freebsd", NULL, NULL, &disk, 0);
102245700Snwhitehorn		geom_deletetree(&submesh);
103245700Snwhitehorn	} else {
104245700Snwhitehorn		disk= strdup(disk);
105245700Snwhitehorn	}
106245700Snwhitehorn
107245700Snwhitehorn	geom_deletetree(&mesh);
108245700Snwhitehorn	error = geom_gettree(&mesh);
109245700Snwhitehorn
110245700Snwhitehorn	/* Create partitions */
111245701Snwhitehorn	if (config == NULL) {
112273831Snwhitehorn		wizard_makeparts(&mesh, disk, "ufs", 0);
113245701Snwhitehorn		goto finished;
114245701Snwhitehorn	}
115245701Snwhitehorn
116245700Snwhitehorn	while ((partition = strsep(&config, ",")) != NULL) {
117245700Snwhitehorn		while ((ap = strsep(&partition, " \t\n")) != NULL) {
118245700Snwhitehorn			if (*ap == '\0')
119245700Snwhitehorn				continue;
120245700Snwhitehorn			if (size == NULL)
121245700Snwhitehorn				size = ap;
122245700Snwhitehorn			else if (type == NULL)
123245700Snwhitehorn				type = ap;
124245700Snwhitehorn			else if (mount == NULL)
125245700Snwhitehorn				mount = ap;
126245700Snwhitehorn		}
127245700Snwhitehorn		if (size == NULL)
128245700Snwhitehorn			continue;
129245700Snwhitehorn		if (strcmp(size, "auto") == 0)
130245700Snwhitehorn			size = NULL;
131245700Snwhitehorn		gpart_create(provider_for_name(&mesh, disk), type, size, mount,
132245700Snwhitehorn		    NULL, 0);
133245700Snwhitehorn		geom_deletetree(&mesh);
134245700Snwhitehorn		error = geom_gettree(&mesh);
135245700Snwhitehorn		size = type = mount = NULL;
136245700Snwhitehorn	}
137245700Snwhitehorn
138245701Snwhitehornfinished:
139245700Snwhitehorn	geom_deletetree(&mesh);
140245700Snwhitehorn	free(disk);
141245700Snwhitehorn
142245700Snwhitehorn	return (0);
143245700Snwhitehorn}
144245700Snwhitehorn
145245700Snwhitehornstatic
146245700Snwhitehornint parse_disk_config(char *input)
147245700Snwhitehorn{
148245700Snwhitehorn	char *ap;
149245700Snwhitehorn	char *disk = NULL, *scheme = NULL, *partconfig = NULL;
150245700Snwhitehorn
151245700Snwhitehorn	while (input != NULL && *input != 0) {
152245700Snwhitehorn		if (isspace(*input)) {
153245700Snwhitehorn			input++;
154245700Snwhitehorn			continue;
155245700Snwhitehorn		}
156245700Snwhitehorn
157245700Snwhitehorn		switch(*input) {
158245700Snwhitehorn		case '{':
159245700Snwhitehorn			input++;
160245700Snwhitehorn			partconfig = strchr(input, '}');
161245700Snwhitehorn			if (partconfig == NULL) {
162245700Snwhitehorn				fprintf(stderr, "Malformed partition setup "
163245700Snwhitehorn				    "string: %s\n", input);
164245700Snwhitehorn				return (1);
165245700Snwhitehorn			}
166245700Snwhitehorn			*partconfig = '\0';
167245700Snwhitehorn			ap = partconfig+1;
168245700Snwhitehorn			partconfig = input;
169245700Snwhitehorn			input = ap;
170245700Snwhitehorn			break;
171245700Snwhitehorn		default:
172245700Snwhitehorn			if (disk == NULL)
173245700Snwhitehorn				disk = strsep(&input, " \t\n");
174245700Snwhitehorn			else if (scheme == NULL)
175245700Snwhitehorn				scheme = strsep(&input, " \t\n");
176245700Snwhitehorn			else {
177245700Snwhitehorn				fprintf(stderr, "Unknown directive: %s\n",
178245700Snwhitehorn				    strsep(&input, " \t\n"));
179245700Snwhitehorn				return (1);
180245700Snwhitehorn			}
181245700Snwhitehorn		}
182245700Snwhitehorn	} while (input != NULL && *input != 0);
183245700Snwhitehorn
184245700Snwhitehorn	if (disk != NULL)
185245796Snwhitehorn		return (part_config(disk, scheme, partconfig));
186245700Snwhitehorn
187245700Snwhitehorn	return (0);
188245700Snwhitehorn}
189245700Snwhitehorn
190245700Snwhitehornint
191245700Snwhitehornscripted_editor(int argc, const char **argv)
192245700Snwhitehorn{
193245700Snwhitehorn	char *token;
194245796Snwhitehorn	int i, error = 0, len = 0;
195245700Snwhitehorn
196245700Snwhitehorn	for (i = 1; i < argc; i++)
197245700Snwhitehorn		len += strlen(argv[i]) + 1;
198245700Snwhitehorn	char inputbuf[len], *input = inputbuf;
199245700Snwhitehorn	strcpy(input, argv[1]);
200245700Snwhitehorn	for (i = 2; i < argc; i++) {
201245700Snwhitehorn		strcat(input, " ");
202245700Snwhitehorn		strcat(input, argv[i]);
203245700Snwhitehorn	}
204245700Snwhitehorn
205245796Snwhitehorn	while ((token = strsep(&input, ";")) != NULL) {
206245796Snwhitehorn		error = parse_disk_config(token);
207245796Snwhitehorn		if (error != 0)
208245796Snwhitehorn			return (error);
209245796Snwhitehorn	}
210245700Snwhitehorn
211245700Snwhitehorn	return (0);
212245700Snwhitehorn}
213245700Snwhitehorn
214