geom_label.c revision 142727
1/*-
2 * Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sbin/geom/class/label/geom_label.c 142727 2005-02-27 23:07:47Z pjd $");
29
30#include <sys/param.h>
31#include <errno.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <strings.h>
36#include <assert.h>
37#include <libgeom.h>
38#include <geom/label/g_label.h>
39
40#include "core/geom.h"
41#include "misc/subr.h"
42
43
44uint32_t lib_version = G_LIB_VERSION;
45uint32_t version = G_LABEL_VERSION;
46
47static void label_main(struct gctl_req *req, unsigned flags);
48static void label_clear(struct gctl_req *req);
49static void label_dump(struct gctl_req *req);
50static void label_label(struct gctl_req *req);
51
52struct g_command class_commands[] = {
53	{ "clear", G_FLAG_VERBOSE, label_main, G_NULL_OPTS },
54	{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, G_NULL_OPTS },
55	{ "destroy", G_FLAG_VERBOSE, NULL,
56	    {
57		{ 'f', "force", NULL, G_TYPE_NONE },
58		G_OPT_SENTINEL
59	    }
60	},
61	{ "dump", 0, label_main, G_NULL_OPTS },
62	{ "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, label_main, G_NULL_OPTS },
63	{ "stop", G_FLAG_VERBOSE, NULL,
64	    {
65		{ 'f', "force", NULL, G_TYPE_NONE },
66		G_OPT_SENTINEL
67	    }
68	},
69	G_CMD_SENTINEL
70};
71
72static int verbose = 0;
73
74
75void usage(const char *name);
76void
77usage(const char *name)
78{
79
80	fprintf(stderr, "usage: %s create [-v] name dev\n", name);
81	fprintf(stderr, "       %s destroy [-fv] name ...\n", name);
82	fprintf(stderr, "       %s label [-v] name dev\n", name);
83	fprintf(stderr, "       %s stop [-fv] name ...\n", name);
84	fprintf(stderr, "       %s clear [-v] dev ...\n", name);
85	fprintf(stderr, "       %s dump dev ...\n", name);
86}
87
88static void
89label_main(struct gctl_req *req, unsigned flags)
90{
91	const char *name;
92
93	if ((flags & G_FLAG_VERBOSE) != 0)
94		verbose = 1;
95
96	name = gctl_get_asciiparam(req, "verb");
97	if (name == NULL) {
98		gctl_error(req, "No '%s' argument.", "verb");
99		return;
100	}
101	if (strcmp(name, "label") == 0)
102		label_label(req);
103	else if (strcmp(name, "clear") == 0)
104		label_clear(req);
105	else if (strcmp(name, "dump") == 0)
106		label_dump(req);
107	else
108		gctl_error(req, "Unknown command: %s.", name);
109}
110
111static void
112label_label(struct gctl_req *req)
113{
114	struct g_label_metadata md;
115	const char *name, *label;
116	u_char sector[512];
117	int *nargs, error;
118
119	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
120	if (nargs == NULL) {
121		gctl_error(req, "No '%s' argument.", "nargs");
122		return;
123	}
124	if (*nargs != 2) {
125		gctl_error(req, "Invalid number of arguments.");
126		return;
127	}
128
129	/*
130	 * Clear last sector first to spoil all components if device exists.
131	 */
132	name = gctl_get_asciiparam(req, "arg1");
133	if (name == NULL) {
134		gctl_error(req, "No 'arg%u' argument.", 1);
135		return;
136	}
137	error = g_metadata_clear(name, NULL);
138	if (error != 0) {
139		gctl_error(req, "Can't store metadata on %s: %s.", name,
140		    strerror(error));
141		return;
142	}
143
144	strlcpy(md.md_magic, G_LABEL_MAGIC, sizeof(md.md_magic));
145	md.md_version = G_LABEL_VERSION;
146	label = gctl_get_asciiparam(req, "arg0");
147	if (label == NULL) {
148		gctl_error(req, "No 'arg%u' argument.", 0);
149		return;
150	}
151	strlcpy(md.md_label, label, sizeof(md.md_label));
152	md.md_provsize = g_get_mediasize(name);
153	if (md.md_provsize == 0) {
154		gctl_error(req, "Can't get mediasize of %s: %s.", name,
155		    strerror(errno));
156		return;
157	}
158
159	/*
160	 * Ok, store metadata.
161	 */
162	label_metadata_encode(&md, sector);
163	error = g_metadata_store(name, sector, sizeof(sector));
164	if (error != 0) {
165		fprintf(stderr, "Can't store metadata on %s: %s.\n", name,
166		    strerror(error));
167		gctl_error(req, "Not done.");
168	}
169	if (verbose)
170		printf("Metadata value stored on %s.\n", name);
171}
172
173static void
174label_clear(struct gctl_req *req)
175{
176	const char *name;
177	char param[16];
178	unsigned i;
179	int *nargs, error;
180
181	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
182	if (nargs == NULL) {
183		gctl_error(req, "No '%s' argument.", "nargs");
184		return;
185	}
186	if (*nargs < 1) {
187		gctl_error(req, "Too few arguments.");
188		return;
189	}
190
191	for (i = 0; i < (unsigned)*nargs; i++) {
192		snprintf(param, sizeof(param), "arg%u", i);
193		name = gctl_get_asciiparam(req, param);
194
195		error = g_metadata_clear(name, G_LABEL_MAGIC);
196		if (error != 0) {
197			fprintf(stderr, "Can't clear metadata on %s: %s.\n",
198			    name, strerror(error));
199			gctl_error(req, "Not fully done.");
200			continue;
201		}
202		if (verbose)
203			printf("Metadata cleared on %s.\n", name);
204	}
205}
206
207static void
208label_metadata_dump(const struct g_label_metadata *md)
209{
210
211	printf("    Magic string: %s\n", md->md_magic);
212	printf("Metadata version: %u\n", (u_int)md->md_version);
213	printf("           Label: %s\n", md->md_label);
214}
215
216static void
217label_dump(struct gctl_req *req)
218{
219	struct g_label_metadata md, tmpmd;
220	const char *name;
221	char param[16];
222	int *nargs, error, i;
223
224	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
225	if (nargs == NULL) {
226		gctl_error(req, "No '%s' argument.", "nargs");
227		return;
228	}
229	if (*nargs < 1) {
230		gctl_error(req, "Too few arguments.");
231		return;
232	}
233
234	for (i = 0; i < *nargs; i++) {
235		snprintf(param, sizeof(param), "arg%u", i);
236		name = gctl_get_asciiparam(req, param);
237
238		error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd),
239		    G_LABEL_MAGIC);
240		if (error != 0) {
241			fprintf(stderr, "Can't read metadata from %s: %s.\n",
242			    name, strerror(error));
243			gctl_error(req, "Not fully done.");
244			continue;
245		}
246		label_metadata_decode((u_char *)&tmpmd, &md);
247		printf("Metadata on %s:\n", name);
248		label_metadata_dump(&md);
249		printf("\n");
250	}
251}
252