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