geom_shsec.c revision 213662
1177633Sdfr/*-
2177633Sdfr * Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3177633Sdfr * All rights reserved.
4177633Sdfr *
5177633Sdfr * Redistribution and use in source and binary forms, with or without
6177633Sdfr * modification, are permitted provided that the following conditions
7177633Sdfr * are met:
8177633Sdfr * 1. Redistributions of source code must retain the above copyright
9177633Sdfr *    notice, this list of conditions and the following disclaimer.
10177633Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11177633Sdfr *    notice, this list of conditions and the following disclaimer in the
12177633Sdfr *    documentation and/or other materials provided with the distribution.
13177633Sdfr *
14177633Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15177633Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16177633Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17177633Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18177633Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19177633Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20177633Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21177633Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22177633Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23177633Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24177633Sdfr * SUCH DAMAGE.
25177633Sdfr */
26177633Sdfr
27177633Sdfr#include <sys/cdefs.h>
28177633Sdfr__FBSDID("$FreeBSD: head/sbin/geom/class/shsec/geom_shsec.c 213662 2010-10-09 20:20:27Z ae $");
29177633Sdfr
30177633Sdfr#include <sys/param.h>
31177633Sdfr#include <errno.h>
32177633Sdfr#include <paths.h>
33177633Sdfr#include <stdio.h>
34177633Sdfr#include <stdlib.h>
35177633Sdfr#include <stdint.h>
36177633Sdfr#include <string.h>
37177633Sdfr#include <strings.h>
38177633Sdfr#include <assert.h>
39177685Sdfr#include <libgeom.h>
40177633Sdfr#include <geom/shsec/g_shsec.h>
41177685Sdfr
42177633Sdfr#include "core/geom.h"
43177633Sdfr#include "misc/subr.h"
44177633Sdfr
45177633Sdfr
46177633Sdfruint32_t lib_version = G_LIB_VERSION;
47177633Sdfruint32_t version = G_SHSEC_VERSION;
48177633Sdfr
49177633Sdfrstatic void shsec_main(struct gctl_req *req, unsigned flags);
50177633Sdfrstatic void shsec_clear(struct gctl_req *req);
51177633Sdfrstatic void shsec_dump(struct gctl_req *req);
52177633Sdfrstatic void shsec_label(struct gctl_req *req);
53177633Sdfr
54177685Sdfrstruct g_command class_commands[] = {
55177685Sdfr	{ "clear", G_FLAG_VERBOSE, shsec_main, G_NULL_OPTS,
56177685Sdfr	    "[-v] prov ..."
57177633Sdfr	},
58177633Sdfr	{ "dump", 0, shsec_main, G_NULL_OPTS,
59177633Sdfr	    "prov ..."
60177633Sdfr	},
61177633Sdfr	{ "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, shsec_main,
62177633Sdfr	    {
63177633Sdfr		{ 'h', "hardcode", NULL, G_TYPE_BOOL },
64177633Sdfr		G_OPT_SENTINEL
65177633Sdfr	    },
66177633Sdfr	    "[-hv] name prov prov ..."
67177633Sdfr	},
68177633Sdfr	{ "stop", G_FLAG_VERBOSE, NULL,
69177633Sdfr	    {
70177633Sdfr		{ 'f', "force", NULL, G_TYPE_BOOL },
71177633Sdfr		G_OPT_SENTINEL
72177633Sdfr	    },
73177633Sdfr	    "[-fv] name ..."
74177633Sdfr	},
75177633Sdfr	G_CMD_SENTINEL
76177633Sdfr};
77177633Sdfr
78177633Sdfrstatic int verbose = 0;
79177633Sdfr
80177633Sdfrstatic void
81177633Sdfrshsec_main(struct gctl_req *req, unsigned flags)
82177633Sdfr{
83177633Sdfr	const char *name;
84177685Sdfr
85177685Sdfr	if ((flags & G_FLAG_VERBOSE) != 0)
86177685Sdfr		verbose = 1;
87177685Sdfr
88177685Sdfr	name = gctl_get_ascii(req, "verb");
89177685Sdfr	if (name == NULL) {
90177633Sdfr		gctl_error(req, "No '%s' argument.", "verb");
91177685Sdfr		return;
92177633Sdfr	}
93177633Sdfr	if (strcmp(name, "label") == 0)
94177633Sdfr		shsec_label(req);
95177633Sdfr	else if (strcmp(name, "clear") == 0)
96177633Sdfr		shsec_clear(req);
97177633Sdfr	else if (strcmp(name, "dump") == 0)
98177633Sdfr		shsec_dump(req);
99177633Sdfr	else
100177633Sdfr		gctl_error(req, "Unknown command: %s.", name);
101177633Sdfr}
102177633Sdfr
103177633Sdfrstatic void
104177633Sdfrshsec_label(struct gctl_req *req)
105177633Sdfr{
106177633Sdfr	struct g_shsec_metadata md;
107177633Sdfr	off_t compsize, msize;
108177633Sdfr	u_char sector[512];
109177633Sdfr	unsigned ssize, secsize;
110177633Sdfr	const char *name;
111177633Sdfr	int error, i, nargs, hardcode;
112177633Sdfr
113177633Sdfr	nargs = gctl_get_int(req, "nargs");
114177633Sdfr	if (nargs <= 2) {
115177633Sdfr		gctl_error(req, "Too few arguments.");
116177633Sdfr		return;
117177633Sdfr	}
118177633Sdfr	hardcode = gctl_get_int(req, "hardcode");
119177633Sdfr
120177633Sdfr	/*
121177633Sdfr	 * Clear last sector first to spoil all components if device exists.
122177633Sdfr	 */
123177633Sdfr	compsize = 0;
124177633Sdfr	secsize = 0;
125177633Sdfr	for (i = 1; i < nargs; i++) {
126177633Sdfr		name = gctl_get_ascii(req, "arg%d", i);
127177633Sdfr		msize = g_get_mediasize(name);
128177633Sdfr		ssize = g_get_sectorsize(name);
129177633Sdfr		if (msize == 0 || ssize == 0) {
130177633Sdfr			gctl_error(req, "Can't get informations about %s: %s.",
131177633Sdfr			    name, strerror(errno));
132177633Sdfr			return;
133177633Sdfr		}
134177633Sdfr		msize -= ssize;
135177633Sdfr		if (compsize == 0 || (compsize > 0 && msize < compsize))
136177633Sdfr			compsize = msize;
137177633Sdfr		if (secsize == 0)
138177633Sdfr			secsize = ssize;
139177633Sdfr		else
140177633Sdfr			secsize = g_lcm(secsize, ssize);
141177633Sdfr
142177633Sdfr		error = g_metadata_clear(name, NULL);
143177633Sdfr		if (error != 0) {
144177633Sdfr			gctl_error(req, "Can't store metadata on %s: %s.", name,
145177633Sdfr			    strerror(error));
146177633Sdfr			return;
147178241Sdfr		}
148177633Sdfr	}
149177633Sdfr
150177633Sdfr	strlcpy(md.md_magic, G_SHSEC_MAGIC, sizeof(md.md_magic));
151177633Sdfr	md.md_version = G_SHSEC_VERSION;
152177633Sdfr	name = gctl_get_ascii(req, "arg0");
153177633Sdfr	strlcpy(md.md_name, name, sizeof(md.md_name));
154177633Sdfr	md.md_id = arc4random();
155177633Sdfr	md.md_all = nargs - 1;
156177633Sdfr
157177633Sdfr	/*
158177633Sdfr	 * Ok, store metadata.
159177633Sdfr	 */
160177633Sdfr	for (i = 1; i < nargs; i++) {
161177633Sdfr		name = gctl_get_ascii(req, "arg%d", i);
162177633Sdfr		msize = g_get_mediasize(name);
163177633Sdfr		ssize = g_get_sectorsize(name);
164178112Sdfr		if (compsize < msize - ssize) {
165178112Sdfr			fprintf(stderr,
166178112Sdfr			    "warning: %s: only %jd bytes from %jd bytes used.\n",
167178112Sdfr			    name, (intmax_t)compsize, (intmax_t)(msize - ssize));
168178112Sdfr		}
169177633Sdfr
170177633Sdfr		md.md_no = i - 1;
171177633Sdfr		md.md_provsize = msize;
172177633Sdfr		if (!hardcode)
173177633Sdfr			bzero(md.md_provider, sizeof(md.md_provider));
174177633Sdfr		else {
175177633Sdfr			if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
176177633Sdfr				name += sizeof(_PATH_DEV) - 1;
177177633Sdfr			strlcpy(md.md_provider, name, sizeof(md.md_provider));
178177633Sdfr		}
179178112Sdfr		shsec_metadata_encode(&md, sector);
180177633Sdfr		error = g_metadata_store(name, sector, sizeof(sector));
181177633Sdfr		if (error != 0) {
182177633Sdfr			fprintf(stderr, "Can't store metadata on %s: %s.\n",
183177633Sdfr			    name, strerror(error));
184177633Sdfr			gctl_error(req, "Not fully done.");
185177633Sdfr			continue;
186177633Sdfr		}
187177633Sdfr		if (verbose)
188177633Sdfr			printf("Metadata value stored on %s.\n", name);
189177633Sdfr	}
190177633Sdfr}
191177633Sdfr
192177633Sdfrstatic void
193177633Sdfrshsec_clear(struct gctl_req *req)
194177633Sdfr{
195177633Sdfr	const char *name;
196177633Sdfr	int error, i, nargs;
197177633Sdfr
198177633Sdfr	nargs = gctl_get_int(req, "nargs");
199177633Sdfr	if (nargs < 1) {
200177633Sdfr		gctl_error(req, "Too few arguments.");
201177633Sdfr		return;
202177633Sdfr	}
203177633Sdfr
204177633Sdfr	for (i = 0; i < nargs; i++) {
205177633Sdfr		name = gctl_get_ascii(req, "arg%d", i);
206177633Sdfr		error = g_metadata_clear(name, G_SHSEC_MAGIC);
207177633Sdfr		if (error != 0) {
208177633Sdfr			fprintf(stderr, "Can't clear metadata on %s: %s.\n",
209177633Sdfr			    name, strerror(error));
210177633Sdfr			gctl_error(req, "Not fully done.");
211177633Sdfr			continue;
212177633Sdfr		}
213177633Sdfr		if (verbose)
214177633Sdfr			printf("Metadata cleared on %s.\n", name);
215177633Sdfr	}
216177633Sdfr}
217177633Sdfr
218177633Sdfrstatic void
219177633Sdfrshsec_metadata_dump(const struct g_shsec_metadata *md)
220177633Sdfr{
221177633Sdfr
222177633Sdfr	printf("         Magic string: %s\n", md->md_magic);
223177633Sdfr	printf("     Metadata version: %u\n", (u_int)md->md_version);
224177633Sdfr	printf("          Device name: %s\n", md->md_name);
225177633Sdfr	printf("            Device ID: %u\n", (u_int)md->md_id);
226177633Sdfr	printf("          Disk number: %u\n", (u_int)md->md_no);
227177633Sdfr	printf("Total number of disks: %u\n", (u_int)md->md_all);
228177633Sdfr	printf("   Hardcoded provider: %s\n", md->md_provider);
229177633Sdfr}
230177633Sdfr
231177633Sdfrstatic void
232177633Sdfrshsec_dump(struct gctl_req *req)
233177633Sdfr{
234177633Sdfr	struct g_shsec_metadata md, tmpmd;
235177633Sdfr	const char *name;
236177633Sdfr	int error, i, nargs;
237177633Sdfr
238177633Sdfr	nargs = gctl_get_int(req, "nargs");
239177633Sdfr	if (nargs < 1) {
240177633Sdfr		gctl_error(req, "Too few arguments.");
241177633Sdfr		return;
242177633Sdfr	}
243177633Sdfr
244177633Sdfr	for (i = 0; i < nargs; i++) {
245177633Sdfr		name = gctl_get_ascii(req, "arg%d", i);
246177633Sdfr		error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd),
247177633Sdfr		    G_SHSEC_MAGIC);
248177633Sdfr		if (error != 0) {
249177633Sdfr			fprintf(stderr, "Can't read metadata from %s: %s.\n",
250177633Sdfr			    name, strerror(error));
251177633Sdfr			gctl_error(req, "Not fully done.");
252177633Sdfr			continue;
253177633Sdfr		}
254177633Sdfr		shsec_metadata_decode((u_char *)&tmpmd, &md);
255177633Sdfr		printf("Metadata on %s:\n", name);
256177633Sdfr		shsec_metadata_dump(&md);
257177633Sdfr		printf("\n");
258177633Sdfr	}
259177633Sdfr}
260177633Sdfr