geom_ctl.c (7b6942a110f1c489c295ac85be8737c2955a737a) geom_ctl.c (4b8938c1d5c3d77402e85ec9017773bd52aa6dbb)
1/*-
2 * Copyright (c) 2003 Poul-Henning Kamp
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

--- 21 unchanged lines hidden (view full) ---

30 */
31
32#include <stdio.h>
33#include <fcntl.h>
34#include <errno.h>
35#include <stdint.h>
36#include <sys/types.h>
37#include <stdarg.h>
1/*-
2 * Copyright (c) 2003 Poul-Henning Kamp
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

--- 21 unchanged lines hidden (view full) ---

30 */
31
32#include <stdio.h>
33#include <fcntl.h>
34#include <errno.h>
35#include <stdint.h>
36#include <sys/types.h>
37#include <stdarg.h>
38#include <unistd.h>
39#include <string.h>
40#include <stdlib.h>
41#include <paths.h>
42
43#include <sys/queue.h>
44
38#include <string.h>
39#include <stdlib.h>
40#include <paths.h>
41
42#include <sys/queue.h>
43
45#define GCTL_TABLE 1
44#define GEOM_CTL_TABLE 1
46#include <libgeom.h>
47
45#include <libgeom.h>
46
48/*
49 * Global pointer to a string that is used to avoid an errorneous free in
50 * gctl_free.
51 */
52static char nomemmsg[] = "Could not allocate memory";
47#include <geom/geom_ext.h>
53
54void
48
49void
55gctl_dump(struct gctl_req *req, FILE *f)
50geom_ctl_dump(struct geom_ctl_req *req, FILE *f)
56{
57 u_int i;
58 int j;
51{
52 u_int i;
53 int j;
59 struct gctl_req_arg *ap;
54 struct geom_ctl_req_arg *ap;
60
61 if (req == NULL) {
55
56 if (req == NULL) {
62 fprintf(f, "Dump of gctl request at NULL\n");
57 fprintf(f, "Dump of geom_ctl request at NULL\n");
63 return;
64 }
58 return;
59 }
65 fprintf(f, "Dump of gctl request at %p:\n", req);
60 fprintf(f, "Dump of geom_ctl %s request at %p:\n", req->reqt->name, req);
66 if (req->error != NULL)
67 fprintf(f, " error:\t\"%s\"\n", req->error);
68 else
69 fprintf(f, " error:\tNULL\n");
70 for (i = 0; i < req->narg; i++) {
71 ap = &req->arg[i];
61 if (req->error != NULL)
62 fprintf(f, " error:\t\"%s\"\n", req->error);
63 else
64 fprintf(f, " error:\tNULL\n");
65 for (i = 0; i < req->narg; i++) {
66 ap = &req->arg[i];
72 fprintf(f, " param:\t\"%s\" (%d)", ap->name, ap->nlen);
73 fprintf(f, " [%s%s",
74 ap->flag & GCTL_PARAM_RD ? "R" : "",
75 ap->flag & GCTL_PARAM_WR ? "W" : "");
67 if (ap->name != NULL)
68 fprintf(f, " param:\t\"%s\"", ap->name);
69 else
70 fprintf(f, " meta:\t@%jd", (intmax_t)ap->offset);
76 fflush(f);
71 fflush(f);
77 if (ap->flag & GCTL_PARAM_ASCII)
78 fprintf(f, "%d] = \"%s\"", ap->len, (char *)ap->value);
72 if (ap->len < 0)
73 fprintf(f, " = [%d] \"%s\"", -ap->len, (char *)ap->value);
79 else if (ap->len > 0) {
74 else if (ap->len > 0) {
80 fprintf(f, "%d] = ", ap->len);
75 fprintf(f, " = [%d]", ap->len);
81 fflush(f);
82 for (j = 0; j < ap->len; j++) {
83 fprintf(f, " %02x", ((u_char *)ap->value)[j]);
84 }
85 } else {
76 fflush(f);
77 for (j = 0; j < ap->len; j++) {
78 fprintf(f, " %02x", ((u_char *)ap->value)[j]);
79 }
80 } else {
86 fprintf(f, "0] = %p", ap->value);
81 fprintf(f, " = [0] %p", ap->value);
87 }
88 fprintf(f, "\n");
89 }
90}
91
82 }
83 fprintf(f, "\n");
84 }
85}
86
92/*
93 * Set an error message, if one does not already exist.
94 */
95static void
87static void
96gctl_set_error(struct gctl_req *req, const char *error, ...)
88geom_ctl_set_error(struct geom_ctl_req *req, const char *error, ...)
97{
98 va_list ap;
99
100 if (req->error != NULL)
101 return;
102 va_start(ap, error);
103 vasprintf(&req->error, error, ap);
89{
90 va_list ap;
91
92 if (req->error != NULL)
93 return;
94 va_start(ap, error);
95 vasprintf(&req->error, error, ap);
104 va_end(ap);
105}
106
96}
97
107/*
108 * Check that a malloc operation succeeded, and set a consistent error
109 * message if not.
110 */
111static void
98static void
112gctl_check_alloc(struct gctl_req *req, void *ptr)
99geom_ctl_check_alloc(struct geom_ctl_req *req, void *ptr)
113{
100{
114
115 if (ptr != NULL)
116 return;
101 if (ptr != NULL)
102 return;
117 gctl_set_error(req, nomemmsg);
118 if (req->error == NULL)
119 req->error = nomemmsg;
103 geom_ctl_set_error(req, "Could not allocate memory");
120}
121
104}
105
122/*
123 * Allocate a new request handle of the specified type.
124 * XXX: Why bother checking the type ?
125 */
126struct gctl_req *
127gctl_get_handle(void)
106struct geom_ctl_req *
107geom_ctl_get_handle(enum geom_ctl_request req)
128{
108{
129 struct gctl_req *rp;
109 struct geom_ctl_req_table *gtp;
110 struct geom_ctl_req *rp;
130
131 rp = calloc(1, sizeof *rp);
111
112 rp = calloc(1, sizeof *rp);
113 if (rp == NULL)
114 return (NULL);
115 for (gtp = gcrt; gtp->request != req; gtp++)
116 if (gtp->request == GEOM_INVALID_REQUEST)
117 break;
118
119 rp->request = req;
120 rp->reqt = gtp;
121 if (rp->reqt->request == GEOM_INVALID_REQUEST)
122 geom_ctl_set_error(rp, "Invalid request");
132 return (rp);
133}
134
123 return (rp);
124}
125
135/*
136 * Allocate space for another argument.
137 */
138static struct gctl_req_arg *
139gctl_new_arg(struct gctl_req *req)
140{
141 struct gctl_req_arg *ap;
142
143 req->narg++;
144 req->arg = reallocf(req->arg, sizeof *ap * req->narg);
145 gctl_check_alloc(req, req->arg);
146 if (req->arg == NULL) {
147 req->narg = 0;
148 return (NULL);
149 }
150 ap = req->arg + (req->narg - 1);
151 memset(ap, 0, sizeof *ap);
152 return (ap);
153}
154
155void
126void
156gctl_ro_param(struct gctl_req *req, const char *name, int len, const void* value)
127geom_ctl_set_param(struct geom_ctl_req *req, const char *name, int len, void* value)
157{
128{
158 struct gctl_req_arg *ap;
129 struct geom_ctl_req_arg *ap;
159
160 if (req == NULL || req->error != NULL)
161 return;
130
131 if (req == NULL || req->error != NULL)
132 return;
162 ap = gctl_new_arg(req);
163 if (ap == NULL)
164 return;
165 ap->name = strdup(name);
166 gctl_check_alloc(req, ap->name);
167 if (ap->name == NULL)
168 return;
169 ap->nlen = strlen(ap->name) + 1;
170 ap->value = __DECONST(void *, value);
171 ap->flag = GCTL_PARAM_RD;
172 if (len >= 0)
133 if (req->reqt->params == 0)
134 geom_ctl_set_error(req, "Request takes no parameters");
135 req->narg++;
136 req->arg = realloc(req->arg, sizeof *ap * req->narg);
137 geom_ctl_check_alloc(req, req->arg);
138 if (req->arg != NULL) {
139 ap = req->arg + (req->narg - 1);
140 memset(ap, 0, sizeof *ap);
141 ap->name = strdup(name);
142 geom_ctl_check_alloc(req, ap->name);
143 ap->nlen = strlen(ap->name);
173 ap->len = len;
144 ap->len = len;
174 else if (len < 0) {
175 ap->flag |= GCTL_PARAM_ASCII;
176 ap->len = strlen(value) + 1;
145 if (len > 0) {
146 ap->value = value;
147 } else if (len < 0) {
148 ap->len = -strlen(value);
149 ap->value = strdup(value);
150 } else {
151 ap->value = value;
152 }
153 if (len != 0)
154 geom_ctl_check_alloc(req, ap->value);
155 } else {
156 req->narg = 0;
177 }
178}
179
180void
157 }
158}
159
160void
181gctl_rw_param(struct gctl_req *req, const char *name, int len, void* value)
161geom_ctl_set_meta(struct geom_ctl_req *req, off_t offset, u_int len, void* value)
182{
162{
183 struct gctl_req_arg *ap;
163 struct geom_ctl_req_arg *ap;
164 u_int i;
184
185 if (req == NULL || req->error != NULL)
186 return;
165
166 if (req == NULL || req->error != NULL)
167 return;
187 ap = gctl_new_arg(req);
188 if (ap == NULL)
168 if (req->reqt->meta == 0)
169 geom_ctl_set_error(req, "Request takes no meta data");
170 for (i = 0; i < req->narg; i++) {
171 ap = &req->arg[i];
172 if (ap->name != NULL)
173 continue;
174 if (ap->offset >= offset + len)
175 continue;
176 if (ap->offset + ap->len <= offset)
177 continue;
178 geom_ctl_set_error(req, "Overlapping meta data");
189 return;
179 return;
190 ap->name = strdup(name);
191 gctl_check_alloc(req, ap->name);
192 if (ap->name == NULL)
193 return;
194 ap->nlen = strlen(ap->name) + 1;
195 ap->value = value;
196 ap->flag = GCTL_PARAM_RW;
197 if (len >= 0)
180 }
181 req->narg++;
182 req->arg = realloc(req->arg, sizeof *ap * req->narg);
183 geom_ctl_check_alloc(req, req->arg);
184 if (req->arg != NULL) {
185 ap = req->arg + (req->narg - 1);
186 memset(ap, 0, sizeof *ap);
187 ap->value = value;
188 ap->offset = offset;
198 ap->len = len;
189 ap->len = len;
199 else if (len < 0)
200 ap->len = strlen(value) + 1;
190 } else {
191 req->narg = 0;
192 }
201}
202
203const char *
193}
194
195const char *
204gctl_issue(struct gctl_req *req)
196geom_ctl_issue(struct geom_ctl_req *req)
205{
206 int fd, error;
207
208 if (req == NULL)
209 return ("NULL request pointer");
210 if (req->error != NULL)
211 return (req->error);
212
197{
198 int fd, error;
199
200 if (req == NULL)
201 return ("NULL request pointer");
202 if (req->error != NULL)
203 return (req->error);
204
213 req->version = GCTL_VERSION;
205 req->version = GEOM_CTL_VERSION;
214 req->lerror = BUFSIZ; /* XXX: arbitrary number */
206 req->lerror = BUFSIZ; /* XXX: arbitrary number */
215 req->error = calloc(1, req->lerror);
216 if (req->error == NULL) {
217 gctl_check_alloc(req, req->error);
218 return (req->error);
219 }
207 req->error = malloc(req->lerror);
208 memset(req->error, 0, req->lerror);
220 req->lerror--;
221 fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY);
222 if (fd < 0)
223 return(strerror(errno));
224 error = ioctl(fd, GEOM_CTL, req);
209 req->lerror--;
210 fd = open(_PATH_DEV PATH_GEOM_CTL, O_RDONLY);
211 if (fd < 0)
212 return(strerror(errno));
213 error = ioctl(fd, GEOM_CTL, req);
225 close(fd);
226 if (req->error[0] != '\0')
214 if (error && errno == EINVAL && req->error[0] != '\0')
227 return (req->error);
228 if (error != 0)
229 return(strerror(errno));
230 return (NULL);
231}
232
233void
215 return (req->error);
216 if (error != 0)
217 return(strerror(errno));
218 return (NULL);
219}
220
221void
234gctl_free(struct gctl_req *req)
222geom_ctl_free(struct geom_ctl_req *req)
235{
236 u_int i;
237
223{
224 u_int i;
225
238 if (req == NULL)
239 return;
240 for (i = 0; i < req->narg; i++) {
241 if (req->arg[i].name != NULL)
242 free(req->arg[i].name);
226 for (i = 0; i < req->narg; i++) {
227 if (req->arg[i].name != NULL)
228 free(req->arg[i].name);
229 if (req->arg[i].len < 0)
230 free(req->arg[i].value);
243 }
231 }
244 free(req->arg);
245 if (req->error != NULL && req->error != nomemmsg)
232 if (req->error != NULL)
246 free(req->error);
233 free(req->error);
234 free(req->arg);
247 free(req);
248}
235 free(req);
236}
237