subr.c revision 129470
1/*- 2 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sbin/geom/misc/subr.c 129470 2004-05-20 10:09:56Z pjd $"); 29 30#include <sys/param.h> 31#include <sys/disk.h> 32#include <sys/endian.h> 33#include <sys/uio.h> 34#include <errno.h> 35#include <fcntl.h> 36#include <paths.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <stdarg.h> 40#include <string.h> 41#include <strings.h> 42#include <unistd.h> 43#include <assert.h> 44#include <libgeom.h> 45 46#include "misc/subr.h" 47 48 49struct std_metadata { 50 char md_magic[16]; 51 uint32_t md_version; 52}; 53 54static void 55std_metadata_decode(const u_char *data, struct std_metadata *md) 56{ 57 58 bcopy(data, md->md_magic, sizeof(md->md_magic)); 59 md->md_version = le32dec(data + 16); 60} 61 62static void 63pathgen(const char *name, char *path, size_t size) 64{ 65 66 if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) != 0) 67 snprintf(path, size, "%s%s", _PATH_DEV, name); 68 else 69 strlcpy(path, name, size); 70} 71 72int 73g_metadata_store(const char *name, u_char *md, size_t size) 74{ 75 char path[MAXPATHLEN]; 76 unsigned sectorsize; 77 off_t mediasize; 78 u_char *sector; 79 int error, fd; 80 81 pathgen(name, path, sizeof(path)); 82 sector = NULL; 83 error = 0; 84 85 fd = open(path, O_WRONLY); 86 if (fd == -1) 87 return (errno); 88 if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) { 89 error = errno; 90 goto out; 91 } 92 if (ioctl(fd, DIOCGSECTORSIZE, §orsize) < 0) { 93 error = errno; 94 goto out; 95 } 96 assert(sectorsize >= size); 97 sector = malloc(sectorsize); 98 if (sector == NULL) { 99 error = ENOMEM; 100 goto out; 101 } 102 bcopy(md, sector, size); 103 if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) != 104 (ssize_t)sectorsize) { 105 error = errno; 106 goto out; 107 } 108out: 109 if (sector != NULL) 110 free(sector); 111 close(fd); 112 return (error); 113} 114 115int 116g_metadata_clear(const char *name, const char *magic) 117{ 118 struct std_metadata md; 119 char path[MAXPATHLEN]; 120 unsigned sectorsize; 121 off_t mediasize; 122 u_char *sector; 123 int error, fd; 124 125 pathgen(name, path, sizeof(path)); 126 sector = NULL; 127 error = 0; 128 129 fd = open(path, O_RDWR); 130 if (fd == -1) 131 return (errno); 132 if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) < 0) { 133 error = errno; 134 goto out; 135 } 136 if (ioctl(fd, DIOCGSECTORSIZE, §orsize) < 0) { 137 error = errno; 138 goto out; 139 } 140 sector = malloc(sectorsize); 141 if (sector == NULL) { 142 error = ENOMEM; 143 goto out; 144 } 145 if (magic != NULL) { 146 if (pread(fd, sector, sectorsize, mediasize - sectorsize) != 147 (ssize_t)sectorsize) { 148 error = errno; 149 goto out; 150 } 151 std_metadata_decode(sector, &md); 152 if (strcmp(md.md_magic, magic) != 0) { 153 error = EINVAL; 154 goto out; 155 } 156 } 157 bzero(sector, sectorsize); 158 if (pwrite(fd, sector, sectorsize, mediasize - sectorsize) != 159 (ssize_t)sectorsize) { 160 error = errno; 161 goto out; 162 } 163out: 164 if (sector != NULL) 165 free(sector); 166 close(fd); 167 return (error); 168} 169 170/* 171 * Set an error message, if one does not already exist. 172 */ 173void 174gctl_error(struct gctl_req *req, const char *error, ...) 175{ 176 va_list ap; 177 178 if (req->error != NULL) 179 return; 180 va_start(ap, error); 181 vasprintf(&req->error, error, ap); 182 va_end(ap); 183} 184 185void * 186gctl_get_param(struct gctl_req *req, const char *param, int *len) 187{ 188 unsigned i; 189 void *p; 190 struct gctl_req_arg *ap; 191 192 for (i = 0; i < req->narg; i++) { 193 ap = &req->arg[i]; 194 if (strcmp(param, ap->name)) 195 continue; 196 if (!(ap->flag & GCTL_PARAM_RD)) 197 continue; 198 p = ap->value; 199 if (len != NULL) 200 *len = ap->len; 201 return (p); 202 } 203 return (NULL); 204} 205 206char const * 207gctl_get_asciiparam(struct gctl_req *req, const char *param) 208{ 209 unsigned i; 210 char const *p; 211 struct gctl_req_arg *ap; 212 213 for (i = 0; i < req->narg; i++) { 214 ap = &req->arg[i]; 215 if (strcmp(param, ap->name)) 216 continue; 217 if (!(ap->flag & GCTL_PARAM_RD)) 218 continue; 219 p = ap->value; 220 if (ap->len < 1) { 221 gctl_error(req, "No length argument (%s)", param); 222 return (NULL); 223 } 224 if (p[ap->len - 1] != '\0') { 225 gctl_error(req, "Unterminated argument (%s)", param); 226 return (NULL); 227 } 228 return (p); 229 } 230 return (NULL); 231} 232 233void * 234gctl_get_paraml(struct gctl_req *req, const char *param, int len) 235{ 236 int i; 237 void *p; 238 239 p = gctl_get_param(req, param, &i); 240 if (p == NULL) 241 gctl_error(req, "Missing %s argument", param); 242 else if (i != len) { 243 p = NULL; 244 gctl_error(req, "Wrong length %s argument", param); 245 } 246 return (p); 247} 248