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