1131476Spjd/*-
2142727Spjd * Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3131476Spjd * All rights reserved.
4131476Spjd *
5131476Spjd * Redistribution and use in source and binary forms, with or without
6131476Spjd * modification, are permitted provided that the following conditions
7131476Spjd * are met:
8131476Spjd * 1. Redistributions of source code must retain the above copyright
9131476Spjd *    notice, this list of conditions and the following disclaimer.
10131476Spjd * 2. Redistributions in binary form must reproduce the above copyright
11131476Spjd *    notice, this list of conditions and the following disclaimer in the
12131476Spjd *    documentation and/or other materials provided with the distribution.
13155175Spjd *
14131476Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15131476Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16131476Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17131476Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18131476Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19131476Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20131476Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21131476Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22131476Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23131476Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24131476Spjd * SUCH DAMAGE.
25131476Spjd */
26131476Spjd
27131476Spjd#include <sys/cdefs.h>
28131476Spjd__FBSDID("$FreeBSD: stable/10/sbin/geom/class/label/geom_label.c 330737 2018-03-10 04:17:01Z asomers $");
29131476Spjd
30131476Spjd#include <sys/param.h>
31131476Spjd#include <errno.h>
32131476Spjd#include <stdio.h>
33131476Spjd#include <stdlib.h>
34131476Spjd#include <string.h>
35131476Spjd#include <strings.h>
36131476Spjd#include <assert.h>
37131476Spjd#include <libgeom.h>
38131476Spjd#include <geom/label/g_label.h>
39131476Spjd
40131476Spjd#include "core/geom.h"
41131476Spjd#include "misc/subr.h"
42131476Spjd
43179550Smarcel#ifdef STATIC_GEOM_CLASSES
44176852Sdelphij#define PUBSYM(x)	glabel_##x
45176852Sdelphij#else
46176852Sdelphij#define PUBSYM(x)	x
47176852Sdelphij#endif
48131476Spjd
49176852Sdelphijuint32_t PUBSYM(lib_version) = G_LIB_VERSION;
50176852Sdelphijuint32_t PUBSYM(version) = G_LABEL_VERSION;
51131476Spjd
52131476Spjdstatic void label_main(struct gctl_req *req, unsigned flags);
53132344Spjdstatic void label_clear(struct gctl_req *req);
54132344Spjdstatic void label_dump(struct gctl_req *req);
55131476Spjdstatic void label_label(struct gctl_req *req);
56131476Spjd
57176852Sdelphijstruct g_command PUBSYM(class_commands)[] = {
58212554Spjd	{ "clear", G_FLAG_VERBOSE, label_main, G_NULL_OPTS,
59143586Spjd	    "[-v] dev ..."
60143586Spjd	},
61143586Spjd	{ "create", G_FLAG_VERBOSE | G_FLAG_LOADKLD, NULL, G_NULL_OPTS,
62212554Spjd	    "[-v] name dev"
63143586Spjd	},
64131476Spjd	{ "destroy", G_FLAG_VERBOSE, NULL,
65131476Spjd	    {
66162868Spjd		{ 'f', "force", NULL, G_TYPE_BOOL },
67131476Spjd		G_OPT_SENTINEL
68143586Spjd	    },
69212554Spjd	    "[-fv] name ..."
70131476Spjd	},
71212554Spjd	{ "dump", 0, label_main, G_NULL_OPTS,
72143586Spjd	    "dev ..."
73143586Spjd	},
74143586Spjd	{ "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, label_main, G_NULL_OPTS,
75212554Spjd	    "[-v] name dev"
76143586Spjd	},
77131649Spjd	{ "stop", G_FLAG_VERBOSE, NULL,
78131649Spjd	    {
79162868Spjd		{ 'f', "force", NULL, G_TYPE_BOOL },
80131649Spjd		G_OPT_SENTINEL
81143586Spjd	    },
82212554Spjd	    "[-fv] name ..."
83131649Spjd	},
84131476Spjd	G_CMD_SENTINEL
85131476Spjd};
86131476Spjd
87131476Spjdstatic int verbose = 0;
88131476Spjd
89131476Spjdstatic void
90131476Spjdlabel_main(struct gctl_req *req, unsigned flags)
91131476Spjd{
92131476Spjd	const char *name;
93131476Spjd
94131476Spjd	if ((flags & G_FLAG_VERBOSE) != 0)
95131476Spjd		verbose = 1;
96131476Spjd
97153190Spjd	name = gctl_get_ascii(req, "verb");
98131476Spjd	if (name == NULL) {
99131476Spjd		gctl_error(req, "No '%s' argument.", "verb");
100131476Spjd		return;
101131476Spjd	}
102131476Spjd	if (strcmp(name, "label") == 0)
103131476Spjd		label_label(req);
104131476Spjd	else if (strcmp(name, "clear") == 0)
105131476Spjd		label_clear(req);
106132344Spjd	else if (strcmp(name, "dump") == 0)
107132344Spjd		label_dump(req);
108131476Spjd	else
109131476Spjd		gctl_error(req, "Unknown command: %s.", name);
110131476Spjd}
111131476Spjd
112131476Spjdstatic void
113131476Spjdlabel_label(struct gctl_req *req)
114131476Spjd{
115131476Spjd	struct g_label_metadata md;
116131476Spjd	const char *name, *label;
117131476Spjd	u_char sector[512];
118153190Spjd	int error, nargs;
119131476Spjd
120330737Sasomers	bzero(sector, sizeof(sector));
121153190Spjd	nargs = gctl_get_int(req, "nargs");
122153190Spjd	if (nargs != 2) {
123131476Spjd		gctl_error(req, "Invalid number of arguments.");
124131476Spjd		return;
125131476Spjd	}
126131476Spjd
127131476Spjd	/*
128131476Spjd	 * Clear last sector first to spoil all components if device exists.
129131476Spjd	 */
130153190Spjd	name = gctl_get_ascii(req, "arg1");
131131476Spjd	error = g_metadata_clear(name, NULL);
132131476Spjd	if (error != 0) {
133131476Spjd		gctl_error(req, "Can't store metadata on %s: %s.", name,
134131476Spjd		    strerror(error));
135131476Spjd		return;
136131476Spjd	}
137131476Spjd
138131476Spjd	strlcpy(md.md_magic, G_LABEL_MAGIC, sizeof(md.md_magic));
139131476Spjd	md.md_version = G_LABEL_VERSION;
140153190Spjd	label = gctl_get_ascii(req, "arg0");
141330737Sasomers	bzero(md.md_label, sizeof(md.md_label));
142131476Spjd	strlcpy(md.md_label, label, sizeof(md.md_label));
143142727Spjd	md.md_provsize = g_get_mediasize(name);
144142727Spjd	if (md.md_provsize == 0) {
145142727Spjd		gctl_error(req, "Can't get mediasize of %s: %s.", name,
146142727Spjd		    strerror(errno));
147142727Spjd		return;
148142727Spjd	}
149131476Spjd
150131476Spjd	/*
151131476Spjd	 * Ok, store metadata.
152131476Spjd	 */
153131476Spjd	label_metadata_encode(&md, sector);
154131476Spjd	error = g_metadata_store(name, sector, sizeof(sector));
155131476Spjd	if (error != 0) {
156131476Spjd		fprintf(stderr, "Can't store metadata on %s: %s.\n", name,
157131476Spjd		    strerror(error));
158131476Spjd		gctl_error(req, "Not done.");
159131476Spjd	}
160131476Spjd	if (verbose)
161131476Spjd		printf("Metadata value stored on %s.\n", name);
162131476Spjd}
163131476Spjd
164131476Spjdstatic void
165131476Spjdlabel_clear(struct gctl_req *req)
166131476Spjd{
167131476Spjd	const char *name;
168153190Spjd	int error, i, nargs;
169131476Spjd
170153190Spjd	nargs = gctl_get_int(req, "nargs");
171153190Spjd	if (nargs < 1) {
172131476Spjd		gctl_error(req, "Too few arguments.");
173131476Spjd		return;
174131476Spjd	}
175131476Spjd
176153190Spjd	for (i = 0; i < nargs; i++) {
177153190Spjd		name = gctl_get_ascii(req, "arg%d", i);
178131476Spjd		error = g_metadata_clear(name, G_LABEL_MAGIC);
179131476Spjd		if (error != 0) {
180131476Spjd			fprintf(stderr, "Can't clear metadata on %s: %s.\n",
181131476Spjd			    name, strerror(error));
182131476Spjd			gctl_error(req, "Not fully done.");
183131476Spjd			continue;
184131476Spjd		}
185131476Spjd		if (verbose)
186155175Spjd			printf("Metadata cleared on %s.\n", name);
187131476Spjd	}
188131476Spjd}
189132344Spjd
190155175Spjdstatic void
191132344Spjdlabel_metadata_dump(const struct g_label_metadata *md)
192132344Spjd{
193132344Spjd
194155175Spjd	printf("    Magic string: %s\n", md->md_magic);
195132344Spjd	printf("Metadata version: %u\n", (u_int)md->md_version);
196132344Spjd	printf("           Label: %s\n", md->md_label);
197132344Spjd}
198132344Spjd
199132344Spjdstatic void
200132344Spjdlabel_dump(struct gctl_req *req)
201132344Spjd{
202132344Spjd	struct g_label_metadata md, tmpmd;
203132344Spjd	const char *name;
204153190Spjd	int error, i, nargs;
205132344Spjd
206153190Spjd	nargs = gctl_get_int(req, "nargs");
207153190Spjd	if (nargs < 1) {
208132344Spjd		gctl_error(req, "Too few arguments.");
209132344Spjd		return;
210132344Spjd	}
211132344Spjd
212153190Spjd	for (i = 0; i < nargs; i++) {
213153190Spjd		name = gctl_get_ascii(req, "arg%d", i);
214132344Spjd		error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd),
215132344Spjd		    G_LABEL_MAGIC);
216132344Spjd		if (error != 0) {
217132344Spjd			fprintf(stderr, "Can't read metadata from %s: %s.\n",
218132344Spjd			    name, strerror(error));
219132344Spjd			gctl_error(req, "Not fully done.");
220132344Spjd			continue;
221132344Spjd		}
222132344Spjd		label_metadata_decode((u_char *)&tmpmd, &md);
223132344Spjd		printf("Metadata on %s:\n", name);
224132344Spjd		label_metadata_dump(&md);
225132344Spjd		printf("\n");
226132344Spjd	}
227132344Spjd}
228