1112510Sphk/*- 2112510Sphk * Copyright (c) 2003 Poul-Henning Kamp 3112510Sphk * All rights reserved. 4112510Sphk * 5112510Sphk * Redistribution and use in source and binary forms, with or without 6112510Sphk * modification, are permitted provided that the following conditions 7112510Sphk * are met: 8112510Sphk * 1. Redistributions of source code must retain the above copyright 9112510Sphk * notice, this list of conditions and the following disclaimer. 10112510Sphk * 2. Redistributions in binary form must reproduce the above copyright 11112510Sphk * notice, this list of conditions and the following disclaimer in the 12112510Sphk * documentation and/or other materials provided with the distribution. 13112510Sphk * 3. The names of the authors may not be used to endorse or promote 14112510Sphk * products derived from this software without specific prior written 15112510Sphk * permission. 16112510Sphk * 17112510Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18112510Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19112510Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20112510Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21112510Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22112510Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23112510Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24112510Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25112510Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26112510Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27112510Sphk * SUCH DAMAGE. 28112510Sphk * 29112510Sphk * $FreeBSD: releng/10.3/lib/libgeom/geom_ctl.c 214129 2010-10-21 10:38:14Z pjd $ 30112510Sphk */ 31112510Sphk 32112510Sphk#include <stdio.h> 33112510Sphk#include <fcntl.h> 34112510Sphk#include <errno.h> 35112510Sphk#include <stdint.h> 36112510Sphk#include <sys/types.h> 37112510Sphk#include <stdarg.h> 38112709Sphk#include <unistd.h> 39112510Sphk#include <string.h> 40112510Sphk#include <stdlib.h> 41112510Sphk#include <paths.h> 42112510Sphk 43112510Sphk#include <sys/queue.h> 44112510Sphk 45112709Sphk#define GCTL_TABLE 1 46112510Sphk#include <libgeom.h> 47112510Sphk 48180369Slulf/* 49180369Slulf * Global pointer to a string that is used to avoid an errorneous free in 50180369Slulf * gctl_free. 51180369Slulf */ 52180369Slulfstatic char nomemmsg[] = "Could not allocate memory"; 53180369Slulf 54112510Sphkvoid 55112709Sphkgctl_dump(struct gctl_req *req, FILE *f) 56112510Sphk{ 57214128Spjd unsigned int i; 58112510Sphk int j; 59112709Sphk struct gctl_req_arg *ap; 60112510Sphk 61112510Sphk if (req == NULL) { 62112709Sphk fprintf(f, "Dump of gctl request at NULL\n"); 63112510Sphk return; 64112510Sphk } 65115625Sphk fprintf(f, "Dump of gctl request at %p:\n", req); 66112510Sphk if (req->error != NULL) 67112510Sphk fprintf(f, " error:\t\"%s\"\n", req->error); 68112510Sphk else 69112510Sphk fprintf(f, " error:\tNULL\n"); 70112510Sphk for (i = 0; i < req->narg; i++) { 71112510Sphk ap = &req->arg[i]; 72115625Sphk fprintf(f, " param:\t\"%s\" (%d)", ap->name, ap->nlen); 73112709Sphk fprintf(f, " [%s%s", 74112709Sphk ap->flag & GCTL_PARAM_RD ? "R" : "", 75112709Sphk ap->flag & GCTL_PARAM_WR ? "W" : ""); 76112510Sphk fflush(f); 77112709Sphk if (ap->flag & GCTL_PARAM_ASCII) 78112709Sphk fprintf(f, "%d] = \"%s\"", ap->len, (char *)ap->value); 79112510Sphk else if (ap->len > 0) { 80112709Sphk fprintf(f, "%d] = ", ap->len); 81112510Sphk fflush(f); 82112510Sphk for (j = 0; j < ap->len; j++) { 83112510Sphk fprintf(f, " %02x", ((u_char *)ap->value)[j]); 84112510Sphk } 85112510Sphk } else { 86112709Sphk fprintf(f, "0] = %p", ap->value); 87112510Sphk } 88112510Sphk fprintf(f, "\n"); 89112510Sphk } 90112510Sphk} 91112510Sphk 92112709Sphk/* 93112709Sphk * Set an error message, if one does not already exist. 94112709Sphk */ 95112510Sphkstatic void 96112709Sphkgctl_set_error(struct gctl_req *req, const char *error, ...) 97112510Sphk{ 98112510Sphk va_list ap; 99112510Sphk 100112510Sphk if (req->error != NULL) 101112510Sphk return; 102112510Sphk va_start(ap, error); 103112510Sphk vasprintf(&req->error, error, ap); 104112709Sphk va_end(ap); 105112510Sphk} 106112510Sphk 107112709Sphk/* 108112709Sphk * Check that a malloc operation succeeded, and set a consistent error 109112709Sphk * message if not. 110112709Sphk */ 111112510Sphkstatic void 112112709Sphkgctl_check_alloc(struct gctl_req *req, void *ptr) 113112510Sphk{ 114180369Slulf 115112510Sphk if (ptr != NULL) 116112510Sphk return; 117180369Slulf gctl_set_error(req, nomemmsg); 118112709Sphk if (req->error == NULL) 119180369Slulf req->error = nomemmsg; 120112510Sphk} 121112510Sphk 122112709Sphk/* 123112709Sphk * Allocate a new request handle of the specified type. 124112709Sphk * XXX: Why bother checking the type ? 125112709Sphk */ 126112709Sphkstruct gctl_req * 127115625Sphkgctl_get_handle(void) 128112510Sphk{ 129112510Sphk 130214128Spjd return (calloc(1, sizeof(struct gctl_req))); 131112510Sphk} 132112510Sphk 133112709Sphk/* 134112709Sphk * Allocate space for another argument. 135112709Sphk */ 136112709Sphkstatic struct gctl_req_arg * 137112709Sphkgctl_new_arg(struct gctl_req *req) 138112510Sphk{ 139112709Sphk struct gctl_req_arg *ap; 140112510Sphk 141112510Sphk req->narg++; 142180369Slulf req->arg = reallocf(req->arg, sizeof *ap * req->narg); 143112709Sphk gctl_check_alloc(req, req->arg); 144112709Sphk if (req->arg == NULL) { 145112510Sphk req->narg = 0; 146112709Sphk return (NULL); 147112510Sphk } 148112709Sphk ap = req->arg + (req->narg - 1); 149112709Sphk memset(ap, 0, sizeof *ap); 150112709Sphk return (ap); 151112510Sphk} 152112510Sphk 153214129Spjdstatic void 154214129Spjdgctl_param_add(struct gctl_req *req, const char *name, int len, void *value, 155214129Spjd int flag) 156112510Sphk{ 157112709Sphk struct gctl_req_arg *ap; 158112510Sphk 159112510Sphk if (req == NULL || req->error != NULL) 160112510Sphk return; 161112709Sphk ap = gctl_new_arg(req); 162112709Sphk if (ap == NULL) 163112510Sphk return; 164112709Sphk ap->name = strdup(name); 165112709Sphk gctl_check_alloc(req, ap->name); 166180369Slulf if (ap->name == NULL) 167180369Slulf return; 168112709Sphk ap->nlen = strlen(ap->name) + 1; 169214129Spjd ap->value = value; 170214129Spjd ap->flag = flag; 171112709Sphk if (len >= 0) 172112510Sphk ap->len = len; 173112709Sphk else if (len < 0) { 174112709Sphk ap->flag |= GCTL_PARAM_ASCII; 175112709Sphk ap->len = strlen(value) + 1; 176112510Sphk } 177112510Sphk} 178112510Sphk 179112709Sphkvoid 180214129Spjdgctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value) 181112709Sphk{ 182112709Sphk 183214129Spjd gctl_param_add(req, name, len, __DECONST(void *, value), GCTL_PARAM_RD); 184112709Sphk} 185112709Sphk 186214129Spjdvoid 187214129Spjdgctl_rw_param(struct gctl_req *req, const char *name, int len, void *value) 188214129Spjd{ 189214129Spjd 190214129Spjd gctl_param_add(req, name, len, value, GCTL_PARAM_RW); 191214129Spjd} 192214129Spjd 193112510Sphkconst char * 194112709Sphkgctl_issue(struct gctl_req *req) 195112510Sphk{ 196112510Sphk int fd, error; 197112510Sphk 198112510Sphk if (req == NULL) 199112510Sphk return ("NULL request pointer"); 200112510Sphk if (req->error != NULL) 201112510Sphk return (req->error); 202112510Sphk 203112709Sphk req->version = GCTL_VERSION; 204112510Sphk req->lerror = BUFSIZ; /* XXX: arbitrary number */ 205180369Slulf req->error = calloc(1, req->lerror); 206112709Sphk if (req->error == NULL) { 207112709Sphk gctl_check_alloc(req, req->error); 208112709Sphk return (req->error); 209112709Sphk } 210112510Sphk req->lerror--; 211112510Sphk fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY); 212112510Sphk if (fd < 0) 213112510Sphk return(strerror(errno)); 214112510Sphk error = ioctl(fd, GEOM_CTL, req); 215112709Sphk close(fd); 216112709Sphk if (req->error[0] != '\0') 217112510Sphk return (req->error); 218112510Sphk if (error != 0) 219112510Sphk return(strerror(errno)); 220112510Sphk return (NULL); 221112510Sphk} 222112510Sphk 223112510Sphkvoid 224112709Sphkgctl_free(struct gctl_req *req) 225112510Sphk{ 226214128Spjd unsigned int i; 227112510Sphk 228112709Sphk if (req == NULL) 229112709Sphk return; 230112510Sphk for (i = 0; i < req->narg; i++) { 231112510Sphk if (req->arg[i].name != NULL) 232112510Sphk free(req->arg[i].name); 233112510Sphk } 234112709Sphk free(req->arg); 235180369Slulf if (req->error != NULL && req->error != nomemmsg) 236112510Sphk free(req->error); 237112510Sphk free(req); 238112510Sphk} 239