xref: /illumos-gate/usr/src/lib/libcpc/common/subr.c (revision 1da57d55)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/syscall.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <strings.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <libnvpair.h>
36 #include <thread.h>
37 #include <synch.h>
38 
39 #include "libcpc.h"
40 #include "libcpc_impl.h"
41 
42 /*
43  * Pack a request set into a buffer using libnvpair. Size of buffer is returned
44  * in buflen.
45  */
46 char *
__cpc_pack_set(cpc_set_t * set,uint_t flags,size_t * buflen)47 __cpc_pack_set(cpc_set_t *set, uint_t flags, size_t *buflen)
48 {
49 	cpc_request_t	*req;
50 	nvlist_t	*setlist, **reqlist;
51 	size_t		packsize = 0;
52 	char		*buf = NULL;
53 	int		i;
54 	int		j;
55 
56 	if (nvlist_alloc(&setlist, 0, 0) == ENOMEM) {
57 		errno = ENOMEM;
58 		return (NULL);
59 	}
60 
61 	if ((reqlist = (nvlist_t **)malloc(set->cs_nreqs * sizeof (*reqlist)))
62 	    == NULL) {
63 		nvlist_free(setlist);
64 		errno = ENOMEM;
65 		return (NULL);
66 	}
67 
68 	bzero((void *)reqlist, set->cs_nreqs * sizeof (*reqlist));
69 
70 	i = 0;
71 	for (req = set->cs_request; req != NULL; req = req->cr_next) {
72 		if (nvlist_alloc(&reqlist[i], 0, 0) == ENOMEM)
73 			goto nomem;
74 
75 		if (nvlist_add_string(reqlist[i], "cr_event",
76 		    req->cr_event) != 0)
77 			goto nomem;
78 		if (nvlist_add_uint64(reqlist[i], "cr_preset",
79 		    req->cr_preset) != 0)
80 			goto nomem;
81 		if (nvlist_add_uint32(reqlist[i], "cr_flags",
82 		    req->cr_flags) != 0)
83 			goto nomem;
84 		if (nvlist_add_uint32(reqlist[i], "cr_index",
85 		    req->cr_index) != 0)
86 			goto nomem;
87 
88 		if (req->cr_nattrs != 0) {
89 			nvlist_t	*attrs;
90 
91 			if (nvlist_alloc(&attrs, NV_UNIQUE_NAME, 0) == ENOMEM)
92 				goto nomem;
93 
94 			for (j = 0; j < req->cr_nattrs; j++) {
95 				if (nvlist_add_uint64(attrs,
96 				    req->cr_attr[j].ka_name,
97 				    req->cr_attr[j].ka_val) != 0) {
98 					nvlist_free(attrs);
99 					goto nomem;
100 				}
101 			}
102 
103 			if (nvlist_add_nvlist(reqlist[i], "cr_attr",
104 			    attrs) != 0) {
105 				nvlist_free(attrs);
106 				goto nomem;
107 			}
108 
109 			nvlist_free(attrs);
110 		}
111 		i++;
112 	}
113 
114 	if (nvlist_add_nvlist_array(setlist, "reqs", reqlist,
115 	    set->cs_nreqs) != 0)
116 		goto nomem;
117 
118 	if (nvlist_add_uint32(setlist, "flags", flags) != 0)
119 		goto nomem;
120 
121 	if (nvlist_pack(setlist, &buf, &packsize, NV_ENCODE_NATIVE,
122 	    0) != 0)
123 		goto nomem;
124 
125 	for (i = 0; i < set->cs_nreqs; i++)
126 		nvlist_free(reqlist[i]);
127 
128 	nvlist_free(setlist);
129 	free(reqlist);
130 
131 	*buflen = packsize;
132 	return (buf);
133 
134 nomem:
135 	for (i = 0; i < set->cs_nreqs; i++) {
136 		if (reqlist[i] != 0)
137 			nvlist_free(reqlist[i]);
138 	}
139 	nvlist_free(setlist);
140 	free(reqlist);
141 	errno = ENOMEM;
142 	return (NULL);
143 }
144 
145 cpc_strhash_t *
__cpc_strhash_alloc(void)146 __cpc_strhash_alloc(void)
147 {
148 	cpc_strhash_t *p;
149 
150 	if ((p = malloc(sizeof (cpc_strhash_t))) == NULL)
151 		return (NULL);
152 
153 	p->str = "";
154 	p->cur = NULL;
155 	p->next = NULL;
156 
157 	return (p);
158 }
159 
160 void
__cpc_strhash_free(cpc_strhash_t * hash)161 __cpc_strhash_free(cpc_strhash_t *hash)
162 {
163 	cpc_strhash_t *p = hash, *f;
164 
165 	while (p != NULL) {
166 		f = p;
167 		p = p->next;
168 		free(f);
169 	}
170 }
171 
172 /*
173  * Insert a new key into the hash table.
174  *
175  * Returns 0 if key was unique and insert successful.
176  *
177  * Returns 1 if key was already in table and no insert took place.
178  *
179  * Returns -1 if out of memory.
180  */
181 int
__cpc_strhash_add(cpc_strhash_t * hash,char * key)182 __cpc_strhash_add(cpc_strhash_t *hash, char *key)
183 {
184 	cpc_strhash_t *p, *tmp;
185 
186 	for (p = hash; p != NULL; p = p->next) {
187 		if (strcmp(p->str, key) == 0)
188 			return (1);
189 	}
190 
191 	if ((p = malloc(sizeof (*p))) == NULL)
192 		return (-1);
193 
194 	p->str = key;
195 	tmp = hash->next;
196 	hash->next = p;
197 	p->next = tmp;
198 	/*
199 	 * The head node's current pointer must stay pointed at the first
200 	 * real node. We just inserted at the head.
201 	 */
202 	hash->cur = p;
203 
204 	return (0);
205 }
206 
207 char *
__cpc_strhash_next(cpc_strhash_t * hash)208 __cpc_strhash_next(cpc_strhash_t *hash)
209 {
210 	cpc_strhash_t *p;
211 
212 	if (hash->cur != NULL) {
213 		p = hash->cur;
214 		hash->cur = hash->cur->next;
215 		return (p->str);
216 	}
217 
218 	return (NULL);
219 }
220