14b8938c1SPoul-Henning Kamp /*- 24b8938c1SPoul-Henning Kamp * Copyright (c) 2003 Poul-Henning Kamp 34b8938c1SPoul-Henning Kamp * All rights reserved. 44b8938c1SPoul-Henning Kamp * 54b8938c1SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 64b8938c1SPoul-Henning Kamp * modification, are permitted provided that the following conditions 74b8938c1SPoul-Henning Kamp * are met: 84b8938c1SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 94b8938c1SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 104b8938c1SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 114b8938c1SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 124b8938c1SPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 134b8938c1SPoul-Henning Kamp * 3. The names of the authors may not be used to endorse or promote 144b8938c1SPoul-Henning Kamp * products derived from this software without specific prior written 154b8938c1SPoul-Henning Kamp * permission. 164b8938c1SPoul-Henning Kamp * 174b8938c1SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 184b8938c1SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194b8938c1SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204b8938c1SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 214b8938c1SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224b8938c1SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234b8938c1SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244b8938c1SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254b8938c1SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264b8938c1SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274b8938c1SPoul-Henning Kamp * SUCH DAMAGE. 284b8938c1SPoul-Henning Kamp * 294b8938c1SPoul-Henning Kamp * $FreeBSD$ 304b8938c1SPoul-Henning Kamp */ 314b8938c1SPoul-Henning Kamp 324b8938c1SPoul-Henning Kamp #include <stdio.h> 334b8938c1SPoul-Henning Kamp #include <fcntl.h> 344b8938c1SPoul-Henning Kamp #include <errno.h> 354b8938c1SPoul-Henning Kamp #include <stdint.h> 364b8938c1SPoul-Henning Kamp #include <sys/types.h> 374b8938c1SPoul-Henning Kamp #include <stdarg.h> 3863728c47SPoul-Henning Kamp #include <unistd.h> 394b8938c1SPoul-Henning Kamp #include <string.h> 404b8938c1SPoul-Henning Kamp #include <stdlib.h> 414b8938c1SPoul-Henning Kamp #include <paths.h> 424b8938c1SPoul-Henning Kamp 434b8938c1SPoul-Henning Kamp #include <sys/queue.h> 444b8938c1SPoul-Henning Kamp 4563728c47SPoul-Henning Kamp #define GCTL_TABLE 1 464b8938c1SPoul-Henning Kamp #include <libgeom.h> 474b8938c1SPoul-Henning Kamp 484b8938c1SPoul-Henning Kamp void 4963728c47SPoul-Henning Kamp gctl_dump(struct gctl_req *req, FILE *f) 504b8938c1SPoul-Henning Kamp { 514b8938c1SPoul-Henning Kamp u_int i; 524b8938c1SPoul-Henning Kamp int j; 5363728c47SPoul-Henning Kamp struct gctl_req_arg *ap; 544b8938c1SPoul-Henning Kamp 554b8938c1SPoul-Henning Kamp if (req == NULL) { 5663728c47SPoul-Henning Kamp fprintf(f, "Dump of gctl request at NULL\n"); 574b8938c1SPoul-Henning Kamp return; 584b8938c1SPoul-Henning Kamp } 597e02e189SPoul-Henning Kamp fprintf(f, "Dump of gctl request at %p:\n", req); 604b8938c1SPoul-Henning Kamp if (req->error != NULL) 614b8938c1SPoul-Henning Kamp fprintf(f, " error:\t\"%s\"\n", req->error); 624b8938c1SPoul-Henning Kamp else 634b8938c1SPoul-Henning Kamp fprintf(f, " error:\tNULL\n"); 644b8938c1SPoul-Henning Kamp for (i = 0; i < req->narg; i++) { 654b8938c1SPoul-Henning Kamp ap = &req->arg[i]; 667e02e189SPoul-Henning Kamp fprintf(f, " param:\t\"%s\" (%d)", ap->name, ap->nlen); 6763728c47SPoul-Henning Kamp fprintf(f, " [%s%s", 6863728c47SPoul-Henning Kamp ap->flag & GCTL_PARAM_RD ? "R" : "", 6963728c47SPoul-Henning Kamp ap->flag & GCTL_PARAM_WR ? "W" : ""); 704b8938c1SPoul-Henning Kamp fflush(f); 7163728c47SPoul-Henning Kamp if (ap->flag & GCTL_PARAM_ASCII) 7263728c47SPoul-Henning Kamp fprintf(f, "%d] = \"%s\"", ap->len, (char *)ap->value); 734b8938c1SPoul-Henning Kamp else if (ap->len > 0) { 7463728c47SPoul-Henning Kamp fprintf(f, "%d] = ", ap->len); 754b8938c1SPoul-Henning Kamp fflush(f); 764b8938c1SPoul-Henning Kamp for (j = 0; j < ap->len; j++) { 774b8938c1SPoul-Henning Kamp fprintf(f, " %02x", ((u_char *)ap->value)[j]); 784b8938c1SPoul-Henning Kamp } 794b8938c1SPoul-Henning Kamp } else { 8063728c47SPoul-Henning Kamp fprintf(f, "0] = %p", ap->value); 814b8938c1SPoul-Henning Kamp } 824b8938c1SPoul-Henning Kamp fprintf(f, "\n"); 834b8938c1SPoul-Henning Kamp } 844b8938c1SPoul-Henning Kamp } 854b8938c1SPoul-Henning Kamp 8663728c47SPoul-Henning Kamp /* 8763728c47SPoul-Henning Kamp * Set an error message, if one does not already exist. 8863728c47SPoul-Henning Kamp */ 894b8938c1SPoul-Henning Kamp static void 9063728c47SPoul-Henning Kamp gctl_set_error(struct gctl_req *req, const char *error, ...) 914b8938c1SPoul-Henning Kamp { 924b8938c1SPoul-Henning Kamp va_list ap; 934b8938c1SPoul-Henning Kamp 944b8938c1SPoul-Henning Kamp if (req->error != NULL) 954b8938c1SPoul-Henning Kamp return; 964b8938c1SPoul-Henning Kamp va_start(ap, error); 974b8938c1SPoul-Henning Kamp vasprintf(&req->error, error, ap); 9863728c47SPoul-Henning Kamp va_end(ap); 994b8938c1SPoul-Henning Kamp } 1004b8938c1SPoul-Henning Kamp 10163728c47SPoul-Henning Kamp /* 10263728c47SPoul-Henning Kamp * Check that a malloc operation succeeded, and set a consistent error 10363728c47SPoul-Henning Kamp * message if not. 10463728c47SPoul-Henning Kamp */ 1054b8938c1SPoul-Henning Kamp static void 10663728c47SPoul-Henning Kamp gctl_check_alloc(struct gctl_req *req, void *ptr) 1074b8938c1SPoul-Henning Kamp { 1084b8938c1SPoul-Henning Kamp if (ptr != NULL) 1094b8938c1SPoul-Henning Kamp return; 11063728c47SPoul-Henning Kamp gctl_set_error(req, "Could not allocate memory"); 11163728c47SPoul-Henning Kamp if (req->error == NULL) 11263728c47SPoul-Henning Kamp req->error = "Could not allocate memory"; 1134b8938c1SPoul-Henning Kamp } 1144b8938c1SPoul-Henning Kamp 11563728c47SPoul-Henning Kamp /* 11663728c47SPoul-Henning Kamp * Allocate a new request handle of the specified type. 11763728c47SPoul-Henning Kamp * XXX: Why bother checking the type ? 11863728c47SPoul-Henning Kamp */ 11963728c47SPoul-Henning Kamp struct gctl_req * 1207e02e189SPoul-Henning Kamp gctl_get_handle(void) 1214b8938c1SPoul-Henning Kamp { 12263728c47SPoul-Henning Kamp struct gctl_req *rp; 1234b8938c1SPoul-Henning Kamp 1244b8938c1SPoul-Henning Kamp rp = calloc(1, sizeof *rp); 1254b8938c1SPoul-Henning Kamp return (rp); 1264b8938c1SPoul-Henning Kamp } 1274b8938c1SPoul-Henning Kamp 12863728c47SPoul-Henning Kamp /* 12963728c47SPoul-Henning Kamp * Allocate space for another argument. 13063728c47SPoul-Henning Kamp */ 13163728c47SPoul-Henning Kamp static struct gctl_req_arg * 13263728c47SPoul-Henning Kamp gctl_new_arg(struct gctl_req *req) 1334b8938c1SPoul-Henning Kamp { 13463728c47SPoul-Henning Kamp struct gctl_req_arg *ap; 1354b8938c1SPoul-Henning Kamp 1364b8938c1SPoul-Henning Kamp req->narg++; 1374b8938c1SPoul-Henning Kamp req->arg = realloc(req->arg, sizeof *ap * req->narg); 13863728c47SPoul-Henning Kamp gctl_check_alloc(req, req->arg); 13963728c47SPoul-Henning Kamp if (req->arg == NULL) { 1404b8938c1SPoul-Henning Kamp req->narg = 0; 14163728c47SPoul-Henning Kamp return (NULL); 14263728c47SPoul-Henning Kamp } 14363728c47SPoul-Henning Kamp ap = req->arg + (req->narg - 1); 14463728c47SPoul-Henning Kamp memset(ap, 0, sizeof *ap); 14563728c47SPoul-Henning Kamp return (ap); 14663728c47SPoul-Henning Kamp } 14763728c47SPoul-Henning Kamp 14863728c47SPoul-Henning Kamp void 14963728c47SPoul-Henning Kamp gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value) 15063728c47SPoul-Henning Kamp { 15163728c47SPoul-Henning Kamp struct gctl_req_arg *ap; 15263728c47SPoul-Henning Kamp 15363728c47SPoul-Henning Kamp if (req == NULL || req->error != NULL) 15463728c47SPoul-Henning Kamp return; 15563728c47SPoul-Henning Kamp ap = gctl_new_arg(req); 15663728c47SPoul-Henning Kamp if (ap == NULL) 15763728c47SPoul-Henning Kamp return; 15863728c47SPoul-Henning Kamp ap->name = strdup(name); 15963728c47SPoul-Henning Kamp gctl_check_alloc(req, ap->name); 16063728c47SPoul-Henning Kamp ap->nlen = strlen(ap->name) + 1; 16163728c47SPoul-Henning Kamp ap->value = __DECONST(void *, value); 16263728c47SPoul-Henning Kamp ap->flag = GCTL_PARAM_RD; 16363728c47SPoul-Henning Kamp if (len >= 0) 16463728c47SPoul-Henning Kamp ap->len = len; 16563728c47SPoul-Henning Kamp else if (len < 0) { 16663728c47SPoul-Henning Kamp ap->flag |= GCTL_PARAM_ASCII; 16763728c47SPoul-Henning Kamp ap->len = strlen(value) + 1; 1684b8938c1SPoul-Henning Kamp } 1694b8938c1SPoul-Henning Kamp } 1704b8938c1SPoul-Henning Kamp 1714b8938c1SPoul-Henning Kamp void 17263728c47SPoul-Henning Kamp gctl_rw_param(struct gctl_req *req, const char *name, int len, void* value) 1734b8938c1SPoul-Henning Kamp { 17463728c47SPoul-Henning Kamp struct gctl_req_arg *ap; 1754b8938c1SPoul-Henning Kamp 1764b8938c1SPoul-Henning Kamp if (req == NULL || req->error != NULL) 1774b8938c1SPoul-Henning Kamp return; 17863728c47SPoul-Henning Kamp ap = gctl_new_arg(req); 17963728c47SPoul-Henning Kamp if (ap == NULL) 1804b8938c1SPoul-Henning Kamp return; 18163728c47SPoul-Henning Kamp ap->name = strdup(name); 18263728c47SPoul-Henning Kamp gctl_check_alloc(req, ap->name); 18363728c47SPoul-Henning Kamp ap->nlen = strlen(ap->name) + 1; 1844b8938c1SPoul-Henning Kamp ap->value = value; 18563728c47SPoul-Henning Kamp ap->flag = GCTL_PARAM_RW; 18663728c47SPoul-Henning Kamp if (len >= 0) 18763728c47SPoul-Henning Kamp ap->len = len; 18863728c47SPoul-Henning Kamp else if (len < 0) 18963728c47SPoul-Henning Kamp ap->len = strlen(value) + 1; 19063728c47SPoul-Henning Kamp } 19163728c47SPoul-Henning Kamp 1924b8938c1SPoul-Henning Kamp const char * 19363728c47SPoul-Henning Kamp gctl_issue(struct gctl_req *req) 1944b8938c1SPoul-Henning Kamp { 1954b8938c1SPoul-Henning Kamp int fd, error; 1964b8938c1SPoul-Henning Kamp 1974b8938c1SPoul-Henning Kamp if (req == NULL) 1984b8938c1SPoul-Henning Kamp return ("NULL request pointer"); 1994b8938c1SPoul-Henning Kamp if (req->error != NULL) 2004b8938c1SPoul-Henning Kamp return (req->error); 2014b8938c1SPoul-Henning Kamp 20263728c47SPoul-Henning Kamp req->version = GCTL_VERSION; 2034b8938c1SPoul-Henning Kamp req->lerror = BUFSIZ; /* XXX: arbitrary number */ 2044b8938c1SPoul-Henning Kamp req->error = malloc(req->lerror); 20563728c47SPoul-Henning Kamp if (req->error == NULL) { 20663728c47SPoul-Henning Kamp gctl_check_alloc(req, req->error); 20763728c47SPoul-Henning Kamp return (req->error); 20863728c47SPoul-Henning Kamp } 2094b8938c1SPoul-Henning Kamp memset(req->error, 0, req->lerror); 2104b8938c1SPoul-Henning Kamp req->lerror--; 2114b8938c1SPoul-Henning Kamp fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY); 2124b8938c1SPoul-Henning Kamp if (fd < 0) 2134b8938c1SPoul-Henning Kamp return(strerror(errno)); 2144b8938c1SPoul-Henning Kamp error = ioctl(fd, GEOM_CTL, req); 21563728c47SPoul-Henning Kamp close(fd); 21663728c47SPoul-Henning Kamp if (req->error[0] != '\0') 2174b8938c1SPoul-Henning Kamp return (req->error); 2184b8938c1SPoul-Henning Kamp if (error != 0) 2194b8938c1SPoul-Henning Kamp return(strerror(errno)); 2204b8938c1SPoul-Henning Kamp return (NULL); 2214b8938c1SPoul-Henning Kamp } 2224b8938c1SPoul-Henning Kamp 2234b8938c1SPoul-Henning Kamp void 22463728c47SPoul-Henning Kamp gctl_free(struct gctl_req *req) 2254b8938c1SPoul-Henning Kamp { 2264b8938c1SPoul-Henning Kamp u_int i; 2274b8938c1SPoul-Henning Kamp 22863728c47SPoul-Henning Kamp if (req == NULL) 22963728c47SPoul-Henning Kamp return; 2304b8938c1SPoul-Henning Kamp for (i = 0; i < req->narg; i++) { 2314b8938c1SPoul-Henning Kamp if (req->arg[i].name != NULL) 2324b8938c1SPoul-Henning Kamp free(req->arg[i].name); 2334b8938c1SPoul-Henning Kamp } 23463728c47SPoul-Henning Kamp free(req->arg); 2354b8938c1SPoul-Henning Kamp if (req->error != NULL) 2364b8938c1SPoul-Henning Kamp free(req->error); 2374b8938c1SPoul-Henning Kamp free(req); 2384b8938c1SPoul-Henning Kamp } 239