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