6659 nvlist_free(NULL) is a no-op
[illumos-gate.git] / usr / src / lib / libcontract / common / libcontract.c
blob3a3bf4a76a074ce47d13a5e9ae895c089d98ed26
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/ctfs.h>
27 #include <sys/contract.h>
28 #include <string.h>
29 #include <libnvpair.h>
30 #include <assert.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <libcontract.h>
34 #include "libcontract_impl.h"
37 * Common template routines
40 int
41 ct_tmpl_activate(int fd)
43 if (ioctl(fd, CT_TACTIVATE) == -1)
44 return (errno);
45 return (0);
48 int
49 ct_tmpl_clear(int fd)
51 if (ioctl(fd, CT_TCLEAR) == -1)
52 return (errno);
53 return (0);
56 int
57 ct_tmpl_create(int fd, ctid_t *ctidp)
59 ctid_t ctid = ioctl(fd, CT_TCREATE);
60 if (ctid == -1)
61 return (errno);
62 *ctidp = ctid;
63 return (0);
66 int
67 ct_tmpl_set_internal(int fd, uint_t id, uintptr_t value)
69 ct_param_t param;
70 uint64_t param_value = value;
72 param.ctpm_id = id;
73 param.ctpm_size = sizeof (uint64_t);
74 param.ctpm_value = &param_value;
75 if (ioctl(fd, CT_TSET, &param) == -1)
76 return (errno);
78 return (0);
81 int
82 ct_tmpl_set_internal_string(int fd, uint_t id, const char *value)
84 ct_param_t param;
86 if (value == NULL)
87 return (EINVAL);
88 param.ctpm_id = id;
89 param.ctpm_size = strlen(value) + 1;
90 param.ctpm_value = (void *)value;
91 if (ioctl(fd, CT_TSET, &param) == -1)
92 return (errno);
94 return (0);
97 int
98 ct_tmpl_set_critical(int fd, uint_t events)
100 return (ct_tmpl_set_internal(fd, CTP_EV_CRITICAL, events));
104 ct_tmpl_set_informative(int fd, uint_t events)
106 return (ct_tmpl_set_internal(fd, CTP_EV_INFO, events));
110 ct_tmpl_set_cookie(int fd, uint64_t cookie)
112 ct_param_t param;
113 uint64_t param_value = cookie;
115 param.ctpm_id = CTP_COOKIE;
116 param.ctpm_size = sizeof (uint64_t);
117 param.ctpm_value = &param_value;
118 if (ioctl(fd, CT_TSET, &param) == -1)
119 return (errno);
120 return (0);
124 ct_tmpl_get_internal(int fd, uint_t id, uint_t *value)
126 ct_param_t param;
127 uint64_t param_value;
129 param.ctpm_id = id;
130 param.ctpm_size = sizeof (uint64_t);
131 param.ctpm_value = &param_value;
132 if (ioctl(fd, CT_TGET, &param) == -1)
133 return (errno);
134 *value = param_value;
135 return (0);
139 ct_tmpl_get_internal_string(int fd, uint32_t id, char *buf, size_t size)
141 ct_param_t param;
143 param.ctpm_id = id;
144 param.ctpm_size = size;
145 param.ctpm_value = buf;
146 if (ioctl(fd, CT_TGET, &param) == -1)
147 return (-1);
148 return (param.ctpm_size);
152 ct_tmpl_get_critical(int fd, uint_t *events)
154 return (ct_tmpl_get_internal(fd, CTP_EV_CRITICAL, events));
158 ct_tmpl_get_informative(int fd, uint_t *events)
160 return (ct_tmpl_get_internal(fd, CTP_EV_INFO, events));
164 ct_tmpl_get_cookie(int fd, uint64_t *cookie)
166 ct_param_t param;
168 param.ctpm_id = CTP_COOKIE;
169 param.ctpm_size = sizeof (uint64_t);
170 param.ctpm_value = cookie;
171 if (ioctl(fd, CT_TGET, &param) == -1)
172 return (errno);
173 return (0);
177 * Common ctl routines
181 ct_ctl_adopt(int fd)
183 if (ioctl(fd, CT_CADOPT) == -1)
184 return (errno);
185 return (0);
189 ct_ctl_abandon(int fd)
191 if (ioctl(fd, CT_CABANDON) == -1)
192 return (errno);
193 return (0);
196 /*ARGSUSED*/
198 ct_ctl_newct(int cfd, ctevid_t evid, int tfd)
200 if (ioctl(cfd, CT_CNEWCT, tfd) == -1)
201 return (errno);
202 return (0);
206 ct_ctl_ack(int fd, ctevid_t event)
208 if (ioctl(fd, CT_CACK, &event) == -1)
209 return (errno);
210 return (0);
214 ct_ctl_nack(int fd, ctevid_t event)
216 if (ioctl(fd, CT_CNACK, &event) == -1)
217 return (errno);
218 return (0);
222 ct_ctl_qack(int fd, ctevid_t event)
224 if (ioctl(fd, CT_CQREQ, &event) == -1)
225 return (errno);
226 return (0);
230 * Common status routines
234 ct_status_read(int fd, int detail, ct_stathdl_t *stathdl)
236 char *status_buffer = NULL;
237 int status_nbytes = 0;
238 struct ctlib_status_info *info;
239 int error;
241 info = malloc(sizeof (struct ctlib_status_info));
242 if (info == NULL)
243 return (errno);
245 info->status.ctst_detail = detail;
246 if (detail != CTD_COMMON) {
247 for (;;) {
248 info->status.ctst_nbytes = status_nbytes;
249 info->status.ctst_buffer = status_buffer;
251 error = ioctl(fd, CT_SSTATUS, &info->status);
252 while (error == -1 && errno == EINTR);
253 if (error == -1)
254 goto errout;
255 if (info->status.ctst_nbytes <= status_nbytes)
256 break;
258 if (status_buffer)
259 free(status_buffer);
260 status_nbytes = info->status.ctst_nbytes;
261 status_buffer = malloc(status_nbytes);
262 if (status_buffer == NULL)
263 goto errout;
265 if ((errno = nvlist_unpack(info->status.ctst_buffer,
266 info->status.ctst_nbytes, &info->nvl, 0)) != 0)
267 goto errout;
269 free(status_buffer);
270 status_buffer = NULL;
272 } else {
273 info->status.ctst_nbytes = 0;
274 info->nvl = NULL;
275 if (ioctl(fd, CT_SSTATUS, &info->status) == -1)
276 goto errout;
279 *stathdl = info;
280 return (0);
282 errout:
283 error = errno;
284 if (status_buffer)
285 free(status_buffer);
286 if (info)
287 free(info);
288 return (error);
291 void
292 ct_status_free(ct_stathdl_t stathdl)
294 struct ctlib_status_info *info = stathdl;
296 if (info->nvl) {
297 assert(info->status.ctst_detail != CTD_COMMON);
298 nvlist_free(info->nvl);
301 free(info);
304 ctid_t
305 ct_status_get_id(ct_stathdl_t stathdl)
307 struct ctlib_status_info *info = stathdl;
308 return (info->status.ctst_id);
311 zoneid_t
312 ct_status_get_zoneid(ct_stathdl_t stathdl)
314 struct ctlib_status_info *info = stathdl;
315 return (info->status.ctst_zoneid);
318 const char *
319 ct_status_get_type(ct_stathdl_t stathdl)
321 struct ctlib_status_info *info = stathdl;
322 return (types[info->status.ctst_type].type_name);
325 id_t
326 ct_status_get_holder(ct_stathdl_t stathdl)
328 struct ctlib_status_info *info = stathdl;
329 return (info->status.ctst_holder);
332 ctstate_t
333 ct_status_get_state(ct_stathdl_t stathdl)
335 struct ctlib_status_info *info = stathdl;
336 return (info->status.ctst_state);
340 ct_status_get_nevents(ct_stathdl_t stathdl)
342 struct ctlib_status_info *info = stathdl;
343 return (info->status.ctst_nevents);
347 ct_status_get_ntime(ct_stathdl_t stathdl)
349 struct ctlib_status_info *info = stathdl;
350 return (info->status.ctst_ntime);
354 ct_status_get_qtime(ct_stathdl_t stathdl)
356 struct ctlib_status_info *info = stathdl;
357 return (info->status.ctst_qtime);
360 ctevid_t
361 ct_status_get_nevid(ct_stathdl_t stathdl)
363 struct ctlib_status_info *info = stathdl;
364 return (info->status.ctst_nevid);
367 uint_t
368 ct_status_get_informative(ct_stathdl_t stathdl)
370 struct ctlib_status_info *info = stathdl;
371 return (info->status.ctst_informative);
374 uint_t
375 ct_status_get_critical(ct_stathdl_t stathdl)
377 struct ctlib_status_info *info = stathdl;
378 return (info->status.ctst_critical);
381 uint64_t
382 ct_status_get_cookie(ct_stathdl_t stathdl)
384 struct ctlib_status_info *info = stathdl;
385 return (info->status.ctst_cookie);
389 * Common event routines
392 static int
393 unpack_and_merge(nvlist_t **nvl, char *buffer, size_t len)
395 nvlist_t *tmpnvl;
396 int error;
398 if ((error = nvlist_unpack(buffer, len, &tmpnvl, 0)) != 0)
399 return (error);
401 if (*nvl == NULL) {
402 *nvl = tmpnvl;
403 return (0);
406 error = nvlist_merge(*nvl, tmpnvl, 0);
407 nvlist_free(tmpnvl);
408 return (error);
411 static int
412 ct_event_read_internal(int fd, int cmd, ct_evthdl_t *evt)
414 char *event_buffer = NULL;
415 int event_nbytes = 0;
416 struct ctlib_event_info *info;
417 ct_event_t *event;
418 int error;
420 info = malloc(sizeof (struct ctlib_event_info));
421 if (info == NULL)
422 return (errno);
423 info->nvl = NULL;
424 event = &info->event;
426 for (;;) {
427 event->ctev_nbytes = event_nbytes;
428 event->ctev_buffer = event_buffer;
430 error = ioctl(fd, cmd, event);
431 while (error == -1 && errno == EINTR);
432 if (error == -1) {
433 error = errno;
434 goto errout;
436 if (event->ctev_nbytes <= event_nbytes)
437 break;
439 if (event_buffer)
440 free(event_buffer);
441 event_nbytes = event->ctev_nbytes;
442 event_buffer = malloc(event_nbytes);
443 if (event_buffer == NULL) {
444 error = errno;
445 goto errout;
449 if (event->ctev_goffset > 0 && (error = unpack_and_merge(&info->nvl,
450 event->ctev_buffer, event->ctev_goffset)) != 0)
451 goto errout;
453 if (event->ctev_goffset < event->ctev_nbytes &&
454 (error = unpack_and_merge(&info->nvl,
455 event->ctev_buffer + event->ctev_goffset,
456 event->ctev_nbytes - event->ctev_goffset)) != 0)
457 goto errout;
459 free(event_buffer);
461 *evt = info;
462 return (0);
464 errout:
465 if (event_buffer)
466 free(event_buffer);
467 if (info) {
468 nvlist_free(info->nvl);
469 free(info);
471 return (error);
475 ct_event_read(int fd, ct_evthdl_t *evthdl)
477 return (ct_event_read_internal(fd, CT_ERECV, evthdl));
481 ct_event_read_critical(int fd, ct_evthdl_t *evthdl)
483 return (ct_event_read_internal(fd, CT_ECRECV, evthdl));
487 ct_event_reset(int fd)
489 if (ioctl(fd, CT_ERESET) == -1)
490 return (errno);
491 return (0);
495 ct_event_reliable(int fd)
497 if (ioctl(fd, CT_ERELIABLE) == -1)
498 return (errno);
499 return (0);
502 void
503 ct_event_free(ct_evthdl_t evthdl)
505 struct ctlib_event_info *info = evthdl;
507 nvlist_free(info->nvl);
508 free(info);
512 uint_t
513 ct_event_get_flags(ct_evthdl_t evthdl)
515 struct ctlib_event_info *info = evthdl;
516 return (info->event.ctev_flags);
519 ctid_t
520 ct_event_get_ctid(ct_evthdl_t evthdl)
522 struct ctlib_event_info *info = evthdl;
523 return (info->event.ctev_id);
526 ctevid_t
527 ct_event_get_evid(ct_evthdl_t evthdl)
529 struct ctlib_event_info *info = evthdl;
530 return (info->event.ctev_evid);
533 uint_t
534 ct_event_get_type(ct_evthdl_t evthdl)
536 struct ctlib_event_info *info = evthdl;
537 return (info->event.ctev_type);
541 ct_event_get_nevid(ct_evthdl_t evthdl, ctevid_t *evidp)
543 struct ctlib_event_info *info = evthdl;
544 if (info->nvl == NULL ||
545 nvlist_lookup_uint64(info->nvl, CTS_NEVID, evidp))
546 return (EINVAL);
547 return (0);
551 ct_event_get_newct(ct_evthdl_t evthdl, ctid_t *ctidp)
553 struct ctlib_event_info *info = evthdl;
554 if (info->nvl == NULL ||
555 nvlist_lookup_int32(info->nvl, CTS_NEWCT, (int *)ctidp))
556 return (EINVAL);
557 return (0);