subr.c revision 129470
1129470Spjd/*- 2129470Spjd * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3129470Spjd * All rights reserved. 4129470Spjd * 5129470Spjd * Redistribution and use in source and binary forms, with or without 6129470Spjd * modification, are permitted provided that the following conditions 7129470Spjd * are met: 8129470Spjd * 1. Redistributions of source code must retain the above copyright 9129470Spjd * notice, this list of conditions and the following disclaimer. 10129470Spjd * 2. Redistributions in binary form must reproduce the above copyright 11129470Spjd * notice, this list of conditions and the following disclaimer in the 12129470Spjd * documentation and/or other materials provided with the distribution. 13129470Spjd * 14129470Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15129470Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16129470Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17129470Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18129470Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19129470Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20129470Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21129470Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22129470Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23129470Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24129470Spjd * SUCH DAMAGE. 25129470Spjd */ 26129470Spjd 27129470Spjd#include <sys/cdefs.h> 28129470Spjd__FBSDID("$FreeBSD: head/sbin/geom/misc/subr.c 129470 2004-05-20 10:09:56Z pjd $"); 29129470Spjd 30129470Spjd#include <sys/param.h> 31129470Spjd#include <sys/disk.h> 32129470Spjd#include <sys/endian.h> 33129470Spjd#include <sys/uio.h> 34129470Spjd#include <errno.h> 35129470Spjd#include <fcntl.h> 36129470Spjd#include <paths.h> 37129470Spjd#include <stdio.h> 38129470Spjd#include <stdlib.h> 39129470Spjd#include <stdarg.h> 40129470Spjd#include <string.h> 41129470Spjd#include <strings.h> 42129470Spjd#include <unistd.h> 43129470Spjd#include <assert.h> 44129470Spjd#include <libgeom.h> 45129470Spjd 46129470Spjd#include "misc/subr.h" 47129470Spjd 48129470Spjd 49129470Spjdstruct std_metadata { 50129470Spjd char md_magic[16]; 51129470Spjd uint32_t md_version; 52129470Spjd}; 53129470Spjd 54129470Spjdstatic void 55129470Spjdstd_metadata_decode(const u_char *data, struct std_metadata *md) 56129470Spjd{ 57129470Spjd 58129470Spjd bcopy(data, md->md_magic, sizeof(md->md_magic)); 59129470Spjd md->md_version = le32dec(data + 16); 60129470Spjd} 61129470Spjd 62129470Spjdstatic void 63129470Spjdpathgen(const char *name, char *path, size_t size) 64129470Spjd{ 65129470Spjd 66129470Spjd if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) != 0) 67129470Spjd snprintf(path, size, "%s%s", _PATH_DEV, name); 68129470Spjd else 69129470Spjd strlcpy(path, name, size); 70129470Spjd} 71129470Spjd 72129470Spjdint 73129470Spjdg_metadata_store(const char *name, u_char *md, size_t size) 74129470Spjd{ 75129470Spjd char path[MAXPATHLEN]; 76129470Spjd unsigned sectorsize; 77129470Spjd off_t mediasize; 78129470Spjd u_char *sector; 79129470Spjd int error, fd; 80129470Spjd 81129470Spjd pathgen(name, path, sizeof(path)); 82129470Spjd sector = NULL; 83129470Spjd error = 0; 84129470Spjd 85129470Spjd fd = open(path, O_WRONLY); 86129470Spjd if (fd == -1) 87129470Spjd return (errno); 88129470Spjd if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) { 89129470Spjd error = errno; 90129470Spjd goto out; 91129470Spjd } 92129470Spjd if (ioctl(fd, DIOCGSECTORSIZE, §orsize) < 0) { 93129470Spjd error = errno; 94129470Spjd goto out; 95129470Spjd } 96129470Spjd assert(sectorsize >= size); 97129470Spjd sector = malloc(sectorsize); 98129470Spjd if (sector == NULL) { 99129470Spjd error = ENOMEM; 100129470Spjd goto out; 101129470Spjd } 102129470Spjd bcopy(md, sector, size); 103129470Spjd if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) != 104129470Spjd (ssize_t)sectorsize) { 105129470Spjd error = errno; 106129470Spjd goto out; 107129470Spjd } 108129470Spjdout: 109129470Spjd if (sector != NULL) 110129470Spjd free(sector); 111129470Spjd close(fd); 112129470Spjd return (error); 113129470Spjd} 114129470Spjd 115129470Spjdint 116129470Spjdg_metadata_clear(const char *name, const char *magic) 117129470Spjd{ 118129470Spjd struct std_metadata md; 119129470Spjd char path[MAXPATHLEN]; 120129470Spjd unsigned sectorsize; 121129470Spjd off_t mediasize; 122129470Spjd u_char *sector; 123129470Spjd int error, fd; 124129470Spjd 125129470Spjd pathgen(name, path, sizeof(path)); 126129470Spjd sector = NULL; 127129470Spjd error = 0; 128129470Spjd 129129470Spjd fd = open(path, O_RDWR); 130129470Spjd if (fd == -1) 131129470Spjd return (errno); 132129470Spjd if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) { 133129470Spjd error = errno; 134129470Spjd goto out; 135129470Spjd } 136129470Spjd if (ioctl(fd, DIOCGSECTORSIZE, §orsize) < 0) { 137129470Spjd error = errno; 138129470Spjd goto out; 139129470Spjd } 140129470Spjd sector = malloc(sectorsize); 141129470Spjd if (sector == NULL) { 142129470Spjd error = ENOMEM; 143129470Spjd goto out; 144129470Spjd } 145129470Spjd if (magic != NULL) { 146129470Spjd if (pread(fd, sector, sectorsize, mediasize - sectorsize) != 147129470Spjd (ssize_t)sectorsize) { 148129470Spjd error = errno; 149129470Spjd goto out; 150129470Spjd } 151129470Spjd std_metadata_decode(sector, &md); 152129470Spjd if (strcmp(md.md_magic, magic) != 0) { 153129470Spjd error = EINVAL; 154129470Spjd goto out; 155129470Spjd } 156129470Spjd } 157129470Spjd bzero(sector, sectorsize); 158129470Spjd if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) != 159129470Spjd (ssize_t)sectorsize) { 160129470Spjd error = errno; 161129470Spjd goto out; 162129470Spjd } 163129470Spjdout: 164129470Spjd if (sector != NULL) 165129470Spjd free(sector); 166129470Spjd close(fd); 167129470Spjd return (error); 168129470Spjd} 169129470Spjd 170129470Spjd/* 171129470Spjd * Set an error message, if one does not already exist. 172129470Spjd */ 173129470Spjdvoid 174129470Spjdgctl_error(struct gctl_req *req, const char *error, ...) 175129470Spjd{ 176129470Spjd va_list ap; 177129470Spjd 178129470Spjd if (req->error != NULL) 179129470Spjd return; 180129470Spjd va_start(ap, error); 181129470Spjd vasprintf(&req->error, error, ap); 182129470Spjd va_end(ap); 183129470Spjd} 184129470Spjd 185129470Spjdvoid * 186129470Spjdgctl_get_param(struct gctl_req *req, const char *param, int *len) 187129470Spjd{ 188129470Spjd unsigned i; 189129470Spjd void *p; 190129470Spjd struct gctl_req_arg *ap; 191129470Spjd 192129470Spjd for (i = 0; i < req->narg; i++) { 193129470Spjd ap = &req->arg[i]; 194129470Spjd if (strcmp(param, ap->name)) 195129470Spjd continue; 196129470Spjd if (!(ap->flag & GCTL_PARAM_RD)) 197129470Spjd continue; 198129470Spjd p = ap->value; 199129470Spjd if (len != NULL) 200129470Spjd *len = ap->len; 201129470Spjd return (p); 202129470Spjd } 203129470Spjd return (NULL); 204129470Spjd} 205129470Spjd 206129470Spjdchar const * 207129470Spjdgctl_get_asciiparam(struct gctl_req *req, const char *param) 208129470Spjd{ 209129470Spjd unsigned i; 210129470Spjd char const *p; 211129470Spjd struct gctl_req_arg *ap; 212129470Spjd 213129470Spjd for (i = 0; i < req->narg; i++) { 214129470Spjd ap = &req->arg[i]; 215129470Spjd if (strcmp(param, ap->name)) 216129470Spjd continue; 217129470Spjd if (!(ap->flag & GCTL_PARAM_RD)) 218129470Spjd continue; 219129470Spjd p = ap->value; 220129470Spjd if (ap->len < 1) { 221129470Spjd gctl_error(req, "No length argument (%s)", param); 222129470Spjd return (NULL); 223129470Spjd } 224129470Spjd if (p[ap->len - 1] != '\0') { 225129470Spjd gctl_error(req, "Unterminated argument (%s)", param); 226129470Spjd return (NULL); 227129470Spjd } 228129470Spjd return (p); 229129470Spjd } 230129470Spjd return (NULL); 231129470Spjd} 232129470Spjd 233129470Spjdvoid * 234129470Spjdgctl_get_paraml(struct gctl_req *req, const char *param, int len) 235129470Spjd{ 236129470Spjd int i; 237129470Spjd void *p; 238129470Spjd 239129470Spjd p = gctl_get_param(req, param, &i); 240129470Spjd if (p == NULL) 241129470Spjd gctl_error(req, "Missing %s argument", param); 242129470Spjd else if (i != len) { 243129470Spjd p = NULL; 244129470Spjd gctl_error(req, "Wrong length %s argument", param); 245129470Spjd } 246129470Spjd return (p); 247129470Spjd} 248