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