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: stable/11/lib/libgeom/geom_ctl.c 319017 2017-05-28 00:25:41Z ngie $ 30112510Sphk */ 31112510Sphk 32319017Sngie#include <sys/types.h> 33319017Sngie#include <sys/queue.h> 34112510Sphk#include <fcntl.h> 35112510Sphk#include <errno.h> 36319017Sngie#include <paths.h> 37319017Sngie#include <stdarg.h> 38112510Sphk#include <stdint.h> 39319017Sngie#include <stdio.h> 40319017Sngie#include <stdlib.h> 41319017Sngie#include <string.h> 42112709Sphk#include <unistd.h> 43112510Sphk 44112709Sphk#define GCTL_TABLE 1 45112510Sphk#include <libgeom.h> 46112510Sphk 47319017Sngie/* 48180369Slulf * Global pointer to a string that is used to avoid an errorneous free in 49180369Slulf * gctl_free. 50180369Slulf */ 51180369Slulfstatic char nomemmsg[] = "Could not allocate memory"; 52180369Slulf 53112510Sphkvoid 54112709Sphkgctl_dump(struct gctl_req *req, FILE *f) 55112510Sphk{ 56214128Spjd unsigned int i; 57112510Sphk int j; 58112709Sphk struct gctl_req_arg *ap; 59112510Sphk 60112510Sphk if (req == NULL) { 61112709Sphk fprintf(f, "Dump of gctl request at NULL\n"); 62112510Sphk return; 63112510Sphk } 64115625Sphk fprintf(f, "Dump of gctl request at %p:\n", req); 65112510Sphk if (req->error != NULL) 66112510Sphk fprintf(f, " error:\t\"%s\"\n", req->error); 67112510Sphk else 68112510Sphk fprintf(f, " error:\tNULL\n"); 69112510Sphk for (i = 0; i < req->narg; i++) { 70112510Sphk ap = &req->arg[i]; 71115625Sphk fprintf(f, " param:\t\"%s\" (%d)", ap->name, ap->nlen); 72112709Sphk fprintf(f, " [%s%s", 73112709Sphk ap->flag & GCTL_PARAM_RD ? "R" : "", 74112709Sphk ap->flag & GCTL_PARAM_WR ? "W" : ""); 75112510Sphk fflush(f); 76112709Sphk if (ap->flag & GCTL_PARAM_ASCII) 77112709Sphk fprintf(f, "%d] = \"%s\"", ap->len, (char *)ap->value); 78112510Sphk else if (ap->len > 0) { 79112709Sphk fprintf(f, "%d] = ", ap->len); 80112510Sphk fflush(f); 81112510Sphk for (j = 0; j < ap->len; j++) { 82112510Sphk fprintf(f, " %02x", ((u_char *)ap->value)[j]); 83112510Sphk } 84112510Sphk } else { 85112709Sphk fprintf(f, "0] = %p", ap->value); 86112510Sphk } 87112510Sphk fprintf(f, "\n"); 88112510Sphk } 89112510Sphk} 90112510Sphk 91112709Sphk/* 92112709Sphk * Set an error message, if one does not already exist. 93112709Sphk */ 94112510Sphkstatic void 95112709Sphkgctl_set_error(struct gctl_req *req, const char *error, ...) 96112510Sphk{ 97112510Sphk va_list ap; 98112510Sphk 99112510Sphk if (req->error != NULL) 100112510Sphk return; 101112510Sphk va_start(ap, error); 102112510Sphk vasprintf(&req->error, error, ap); 103112709Sphk va_end(ap); 104112510Sphk} 105112510Sphk 106112709Sphk/* 107112709Sphk * Check that a malloc operation succeeded, and set a consistent error 108112709Sphk * message if not. 109112709Sphk */ 110112510Sphkstatic void 111112709Sphkgctl_check_alloc(struct gctl_req *req, void *ptr) 112112510Sphk{ 113180369Slulf 114112510Sphk if (ptr != NULL) 115112510Sphk return; 116180369Slulf gctl_set_error(req, nomemmsg); 117112709Sphk if (req->error == NULL) 118180369Slulf req->error = nomemmsg; 119112510Sphk} 120112510Sphk 121112709Sphk/* 122112709Sphk * Allocate a new request handle of the specified type. 123112709Sphk * XXX: Why bother checking the type ? 124112709Sphk */ 125112709Sphkstruct gctl_req * 126115625Sphkgctl_get_handle(void) 127112510Sphk{ 128112510Sphk 129214128Spjd return (calloc(1, sizeof(struct gctl_req))); 130112510Sphk} 131112510Sphk 132112709Sphk/* 133112709Sphk * Allocate space for another argument. 134112709Sphk */ 135112709Sphkstatic struct gctl_req_arg * 136112709Sphkgctl_new_arg(struct gctl_req *req) 137112510Sphk{ 138112709Sphk struct gctl_req_arg *ap; 139112510Sphk 140112510Sphk req->narg++; 141180369Slulf req->arg = reallocf(req->arg, sizeof *ap * req->narg); 142112709Sphk gctl_check_alloc(req, req->arg); 143112709Sphk if (req->arg == NULL) { 144112510Sphk req->narg = 0; 145112709Sphk return (NULL); 146112510Sphk } 147112709Sphk ap = req->arg + (req->narg - 1); 148112709Sphk memset(ap, 0, sizeof *ap); 149112709Sphk return (ap); 150112510Sphk} 151112510Sphk 152214129Spjdstatic void 153214129Spjdgctl_param_add(struct gctl_req *req, const char *name, int len, void *value, 154214129Spjd int flag) 155112510Sphk{ 156112709Sphk struct gctl_req_arg *ap; 157112510Sphk 158112510Sphk if (req == NULL || req->error != NULL) 159112510Sphk return; 160112709Sphk ap = gctl_new_arg(req); 161112709Sphk if (ap == NULL) 162112510Sphk return; 163112709Sphk ap->name = strdup(name); 164112709Sphk gctl_check_alloc(req, ap->name); 165180369Slulf if (ap->name == NULL) 166180369Slulf return; 167112709Sphk ap->nlen = strlen(ap->name) + 1; 168214129Spjd ap->value = value; 169214129Spjd ap->flag = flag; 170112709Sphk if (len >= 0) 171112510Sphk ap->len = len; 172112709Sphk else if (len < 0) { 173112709Sphk ap->flag |= GCTL_PARAM_ASCII; 174319017Sngie ap->len = strlen(value) + 1; 175112510Sphk } 176112510Sphk} 177112510Sphk 178112709Sphkvoid 179214129Spjdgctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value) 180112709Sphk{ 181112709Sphk 182214129Spjd gctl_param_add(req, name, len, __DECONST(void *, value), GCTL_PARAM_RD); 183112709Sphk} 184112709Sphk 185214129Spjdvoid 186214129Spjdgctl_rw_param(struct gctl_req *req, const char *name, int len, void *value) 187214129Spjd{ 188214129Spjd 189214129Spjd gctl_param_add(req, name, len, value, GCTL_PARAM_RW); 190214129Spjd} 191214129Spjd 192112510Sphkconst char * 193112709Sphkgctl_issue(struct gctl_req *req) 194112510Sphk{ 195112510Sphk int fd, error; 196112510Sphk 197112510Sphk if (req == NULL) 198112510Sphk return ("NULL request pointer"); 199112510Sphk if (req->error != NULL) 200112510Sphk return (req->error); 201112510Sphk 202112709Sphk req->version = GCTL_VERSION; 203112510Sphk req->lerror = BUFSIZ; /* XXX: arbitrary number */ 204180369Slulf req->error = calloc(1, req->lerror); 205112709Sphk if (req->error == NULL) { 206112709Sphk gctl_check_alloc(req, req->error); 207112709Sphk return (req->error); 208112709Sphk } 209112510Sphk req->lerror--; 210112510Sphk fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY); 211112510Sphk if (fd < 0) 212112510Sphk return(strerror(errno)); 213112510Sphk error = ioctl(fd, GEOM_CTL, req); 214112709Sphk close(fd); 215112709Sphk if (req->error[0] != '\0') 216112510Sphk return (req->error); 217112510Sphk if (error != 0) 218112510Sphk return(strerror(errno)); 219112510Sphk return (NULL); 220112510Sphk} 221112510Sphk 222112510Sphkvoid 223112709Sphkgctl_free(struct gctl_req *req) 224112510Sphk{ 225214128Spjd unsigned int i; 226112510Sphk 227112709Sphk if (req == NULL) 228112709Sphk return; 229112510Sphk for (i = 0; i < req->narg; i++) { 230112510Sphk if (req->arg[i].name != NULL) 231112510Sphk free(req->arg[i].name); 232112510Sphk } 233112709Sphk free(req->arg); 234180369Slulf if (req->error != NULL && req->error != nomemmsg) 235112510Sphk free(req->error); 236112510Sphk free(req); 237112510Sphk} 238