]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/geom/shsec/geom_shsec.c
Normalize the g(eom,cache,part,...) build.
[FreeBSD/FreeBSD.git] / lib / geom / shsec / geom_shsec.c
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$");
31
32 #include <sys/param.h>
33 #include <errno.h>
34 #include <paths.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <strings.h>
40 #include <assert.h>
41 #include <libgeom.h>
42 #include <geom/shsec/g_shsec.h>
43
44 #include "core/geom.h"
45 #include "misc/subr.h"
46
47
48 uint32_t lib_version = G_LIB_VERSION;
49 uint32_t version = G_SHSEC_VERSION;
50
51 static void shsec_main(struct gctl_req *req, unsigned flags);
52 static void shsec_clear(struct gctl_req *req);
53 static void shsec_dump(struct gctl_req *req);
54 static void shsec_label(struct gctl_req *req);
55
56 struct g_command class_commands[] = {
57         { "clear", G_FLAG_VERBOSE, shsec_main, G_NULL_OPTS,
58             "[-v] prov ..."
59         },
60         { "dump", 0, shsec_main, G_NULL_OPTS,
61             "prov ..."
62         },
63         { "label", G_FLAG_VERBOSE | G_FLAG_LOADKLD, shsec_main,
64             {
65                 { 'h', "hardcode", NULL, G_TYPE_BOOL },
66                 G_OPT_SENTINEL
67             },
68             "[-hv] name prov prov ..."
69         },
70         { "stop", G_FLAG_VERBOSE, NULL,
71             {
72                 { 'f', "force", NULL, G_TYPE_BOOL },
73                 G_OPT_SENTINEL
74             },
75             "[-fv] name ..."
76         },
77         G_CMD_SENTINEL
78 };
79
80 static int verbose = 0;
81
82 static void
83 shsec_main(struct gctl_req *req, unsigned flags)
84 {
85         const char *name;
86
87         if ((flags & G_FLAG_VERBOSE) != 0)
88                 verbose = 1;
89
90         name = gctl_get_ascii(req, "verb");
91         if (name == NULL) {
92                 gctl_error(req, "No '%s' argument.", "verb");
93                 return;
94         }
95         if (strcmp(name, "label") == 0)
96                 shsec_label(req);
97         else if (strcmp(name, "clear") == 0)
98                 shsec_clear(req);
99         else if (strcmp(name, "dump") == 0)
100                 shsec_dump(req);
101         else
102                 gctl_error(req, "Unknown command: %s.", name);
103 }
104
105 static void
106 shsec_label(struct gctl_req *req)
107 {
108         struct g_shsec_metadata md;
109         off_t compsize, msize;
110         u_char sector[512];
111         unsigned ssize, secsize;
112         const char *name;
113         int error, i, nargs, hardcode;
114
115         bzero(sector, sizeof(sector));
116         nargs = gctl_get_int(req, "nargs");
117         if (nargs <= 2) {
118                 gctl_error(req, "Too few arguments.");
119                 return;
120         }
121         hardcode = gctl_get_int(req, "hardcode");
122
123         /*
124          * Clear last sector first to spoil all components if device exists.
125          */
126         compsize = 0;
127         secsize = 0;
128         for (i = 1; i < nargs; i++) {
129                 name = gctl_get_ascii(req, "arg%d", i);
130                 msize = g_get_mediasize(name);
131                 ssize = g_get_sectorsize(name);
132                 if (msize == 0 || ssize == 0) {
133                         gctl_error(req, "Can't get informations about %s: %s.",
134                             name, strerror(errno));
135                         return;
136                 }
137                 msize -= ssize;
138                 if (compsize == 0 || (compsize > 0 && msize < compsize))
139                         compsize = msize;
140                 if (secsize == 0)
141                         secsize = ssize;
142                 else
143                         secsize = g_lcm(secsize, ssize);
144
145                 error = g_metadata_clear(name, NULL);
146                 if (error != 0) {
147                         gctl_error(req, "Can't store metadata on %s: %s.", name,
148                             strerror(error));
149                         return;
150                 }
151         }
152
153         strlcpy(md.md_magic, G_SHSEC_MAGIC, sizeof(md.md_magic));
154         md.md_version = G_SHSEC_VERSION;
155         name = gctl_get_ascii(req, "arg0");
156         strlcpy(md.md_name, name, sizeof(md.md_name));
157         md.md_id = arc4random();
158         md.md_all = nargs - 1;
159
160         /*
161          * Ok, store metadata.
162          */
163         for (i = 1; i < nargs; i++) {
164                 name = gctl_get_ascii(req, "arg%d", i);
165                 msize = g_get_mediasize(name);
166                 ssize = g_get_sectorsize(name);
167                 if (compsize < msize - ssize) {
168                         fprintf(stderr,
169                             "warning: %s: only %jd bytes from %jd bytes used.\n",
170                             name, (intmax_t)compsize, (intmax_t)(msize - ssize));
171                 }
172
173                 md.md_no = i - 1;
174                 md.md_provsize = msize;
175                 if (!hardcode)
176                         bzero(md.md_provider, sizeof(md.md_provider));
177                 else {
178                         if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
179                                 name += sizeof(_PATH_DEV) - 1;
180                         strlcpy(md.md_provider, name, sizeof(md.md_provider));
181                 }
182                 shsec_metadata_encode(&md, sector);
183                 error = g_metadata_store(name, sector, sizeof(sector));
184                 if (error != 0) {
185                         fprintf(stderr, "Can't store metadata on %s: %s.\n",
186                             name, strerror(error));
187                         gctl_error(req, "Not fully done.");
188                         continue;
189                 }
190                 if (verbose)
191                         printf("Metadata value stored on %s.\n", name);
192         }
193 }
194
195 static void
196 shsec_clear(struct gctl_req *req)
197 {
198         const char *name;
199         int error, i, nargs;
200
201         nargs = gctl_get_int(req, "nargs");
202         if (nargs < 1) {
203                 gctl_error(req, "Too few arguments.");
204                 return;
205         }
206
207         for (i = 0; i < nargs; i++) {
208                 name = gctl_get_ascii(req, "arg%d", i);
209                 error = g_metadata_clear(name, G_SHSEC_MAGIC);
210                 if (error != 0) {
211                         fprintf(stderr, "Can't clear metadata on %s: %s.\n",
212                             name, strerror(error));
213                         gctl_error(req, "Not fully done.");
214                         continue;
215                 }
216                 if (verbose)
217                         printf("Metadata cleared on %s.\n", name);
218         }
219 }
220
221 static void
222 shsec_metadata_dump(const struct g_shsec_metadata *md)
223 {
224
225         printf("         Magic string: %s\n", md->md_magic);
226         printf("     Metadata version: %u\n", (u_int)md->md_version);
227         printf("          Device name: %s\n", md->md_name);
228         printf("            Device ID: %u\n", (u_int)md->md_id);
229         printf("          Disk number: %u\n", (u_int)md->md_no);
230         printf("Total number of disks: %u\n", (u_int)md->md_all);
231         printf("   Hardcoded provider: %s\n", md->md_provider);
232 }
233
234 static void
235 shsec_dump(struct gctl_req *req)
236 {
237         struct g_shsec_metadata md, tmpmd;
238         const char *name;
239         int error, i, nargs;
240
241         nargs = gctl_get_int(req, "nargs");
242         if (nargs < 1) {
243                 gctl_error(req, "Too few arguments.");
244                 return;
245         }
246
247         for (i = 0; i < nargs; i++) {
248                 name = gctl_get_ascii(req, "arg%d", i);
249                 error = g_metadata_read(name, (u_char *)&tmpmd, sizeof(tmpmd),
250                     G_SHSEC_MAGIC);
251                 if (error != 0) {
252                         fprintf(stderr, "Can't read metadata from %s: %s.\n",
253                             name, strerror(error));
254                         gctl_error(req, "Not fully done.");
255                         continue;
256                 }
257                 shsec_metadata_decode((u_char *)&tmpmd, &md);
258                 printf("Metadata on %s:\n", name);
259                 shsec_metadata_dump(&md);
260                 printf("\n");
261         }
262 }