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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * evnv.c -- eversholt specific nvpair manipulation functions
27  *
28  * this module provides the simulated fault management exercise.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <libnvpair.h>
36 #include "evnv.h"
37 #include "out.h"
38 
39 #define	min(a, b)	(((a) <= (b)) ? (a) : (b))
40 
41 extern nv_alloc_t Eft_nv_hdl;
42 
43 static void
44 outindent(int depth)
45 {
46 	while (depth-- > 0)
47 		out(O_ALTFP|O_VERB3|O_NONL, "   ");
48 }
49 
50 /*
51  * evnv_cmpnvl -- compare two asrus in their nvlist form
52  */
53 int
54 evnv_cmpnvl(nvlist_t *nvl1, nvlist_t *nvl2, int depth)
55 {
56 	/*
57 	 * an assumption here is that each list was constructed in the
58 	 * same order, which is a safe assumption since we built the
59 	 * list of ourself (well, libtopo did at any rate)
60 	 */
61 	data_type_t t1, t2;
62 	nvlist_t **la1 = NULL;
63 	nvlist_t **la2 = NULL;
64 	nvlist_t *l1 = NULL;
65 	nvlist_t *l2 = NULL;
66 	nvpair_t *p1 = NULL;
67 	nvpair_t *p2 = NULL;
68 	uint64_t lv1, lv2;
69 	uint_t m, na1, na2;
70 	char *s1, *s2;
71 	int ret, i;
72 
73 	for (;;) {
74 		p1 = nvlist_next_nvpair(nvl1, p1);
75 		p2 = nvlist_next_nvpair(nvl2, p2);
76 		if (p1 == NULL && p2 == NULL) {
77 			outindent(depth);
78 			out(O_ALTFP|O_VERB3, "equal nvls\n");
79 			return (0);
80 		}
81 		if (p1 == NULL)
82 			return (-1);
83 		if (p2 == NULL)
84 			return (1);
85 		s1 = nvpair_name(p1);
86 		s2 = nvpair_name(p2);
87 		outindent(depth);
88 		out(O_ALTFP|O_VERB3, "cmpnvl: pair %s vs %s", s1, s2);
89 		if ((ret = strcmp(s1, s2)) != 0)
90 			return (ret);
91 		t1 = nvpair_type(p1);
92 		t2 = nvpair_type(p2);
93 		if (t1 != t2)
94 			return (t1 - t2);
95 		/*
96 		 * We don't compare all possible types, just the
97 		 * ones we know are likely to actually be present
98 		 * in nvlists we've generated.
99 		 */
100 		switch (t1) {
101 		case DATA_TYPE_NVLIST:
102 			(void) nvpair_value_nvlist(p1, &l1);
103 			(void) nvpair_value_nvlist(p2, &l2);
104 			if ((ret = evnv_cmpnvl(l1, l2, depth + 1)) != 0)
105 				return (ret);
106 			break;
107 		case DATA_TYPE_NVLIST_ARRAY:
108 			(void) nvpair_value_nvlist_array(p1, &la1, &na1);
109 			(void) nvpair_value_nvlist_array(p2, &la2, &na2);
110 			m = min(na1, na2);
111 			for (i = 0; i < m; i++) {
112 				if ((ret =
113 				    evnv_cmpnvl(*la1, *la2, depth + 1)) != 0)
114 					return (ret);
115 				la1++;
116 				la2++;
117 			}
118 			if (na1 < na2)
119 				return (-1);
120 			else if (na2 < na1)
121 				return (1);
122 			break;
123 		case DATA_TYPE_STRING:
124 			(void) nvpair_value_string(p1, &s1);
125 			(void) nvpair_value_string(p2, &s2);
126 			if ((ret = strcmp(s1, s2)) != 0) {
127 				outindent(depth);
128 				if (ret < 0)
129 					out(O_ALTFP|O_VERB3,
130 					    "cmpnvl: %s < %s", s1, s2);
131 				else
132 					out(O_ALTFP|O_VERB3,
133 					    "cmpnvl: %s > %s", s1, s2);
134 				return (ret);
135 			}
136 			break;
137 		case DATA_TYPE_UINT64:
138 			lv1 = lv2 = 0;
139 			(void) nvpair_value_uint64(p1, &lv1);
140 			(void) nvpair_value_uint64(p2, &lv2);
141 			outindent(depth);
142 			out(O_ALTFP|O_VERB3, "cmpnvl: %llu vs %llu", lv1, lv2);
143 			if (lv1 > lv2)
144 				return (1);
145 			else if (lv2 > lv1)
146 				return (-1);
147 			break;
148 		case DATA_TYPE_INT64:
149 			lv1 = lv2 = 0;
150 			(void) nvpair_value_int64(p1, (int64_t *)&lv1);
151 			(void) nvpair_value_int64(p2, (int64_t *)&lv2);
152 			outindent(depth);
153 			out(O_ALTFP|O_VERB3, "cmpnvl: %lld vs %lld", lv1, lv2);
154 			if (lv1 > lv2)
155 				return (1);
156 			else if (lv2 > lv1)
157 				return (-1);
158 			break;
159 		case DATA_TYPE_UINT32:
160 			lv1 = lv2 = 0;
161 			(void) nvpair_value_uint32(p1, (uint32_t *)&lv1);
162 			(void) nvpair_value_uint32(p2, (uint32_t *)&lv2);
163 			outindent(depth);
164 			out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
165 			    *(uint32_t *)&lv1, *(uint32_t *)&lv2);
166 			if (lv1 > lv2)
167 				return (1);
168 			else if (lv2 > lv1)
169 				return (-1);
170 			break;
171 		case DATA_TYPE_INT32:
172 			lv1 = lv2 = 0;
173 			(void) nvpair_value_int32(p1, (int32_t *)&lv1);
174 			(void) nvpair_value_int32(p2, (int32_t *)&lv2);
175 			outindent(depth);
176 			out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
177 			    *(int32_t *)&lv1, *(int32_t *)&lv2);
178 			if (lv1 > lv2)
179 				return (1);
180 			else if (lv2 > lv1)
181 				return (-1);
182 			break;
183 		case DATA_TYPE_UINT16:
184 			lv1 = lv2 = 0;
185 			(void) nvpair_value_uint16(p1, (uint16_t *)&lv1);
186 			(void) nvpair_value_uint16(p2, (uint16_t *)&lv2);
187 			outindent(depth);
188 			out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
189 			    *(uint16_t *)&lv1, *(uint16_t *)&lv2);
190 			if (lv1 > lv2)
191 				return (1);
192 			else if (lv2 > lv1)
193 				return (-1);
194 			break;
195 		case DATA_TYPE_INT16:
196 			lv1 = lv2 = 0;
197 			(void) nvpair_value_int16(p1, (int16_t *)&lv1);
198 			(void) nvpair_value_int16(p2, (int16_t *)&lv2);
199 			outindent(depth);
200 			out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
201 			    *(int16_t *)&lv1, *(int16_t *)&lv2);
202 			if (lv1 > lv2)
203 				return (1);
204 			else if (lv2 > lv1)
205 				return (-1);
206 			break;
207 		case DATA_TYPE_UINT8:
208 			lv1 = lv2 = 0;
209 			(void) nvpair_value_uint8(p1, (uint8_t *)&lv1);
210 			(void) nvpair_value_uint8(p2, (uint8_t *)&lv2);
211 			outindent(depth);
212 			out(O_ALTFP|O_VERB3, "cmpnvl: %u vs %u",
213 			    *(uint8_t *)&lv1, *(uint8_t *)&lv2);
214 			if (lv1 > lv2)
215 				return (1);
216 			else if (lv2 > lv1)
217 				return (-1);
218 			break;
219 		case DATA_TYPE_INT8:
220 			lv1 = lv2 = 0;
221 			(void) nvpair_value_int8(p1, (int8_t *)&lv1);
222 			(void) nvpair_value_int8(p2, (int8_t *)&lv2);
223 			outindent(depth);
224 			out(O_ALTFP|O_VERB3, "cmpnvl: %d vs %d",
225 			    *(int8_t *)&lv1, *(int8_t *)&lv2);
226 			if (lv1 > lv2)
227 				return (1);
228 			else if (lv2 > lv1)
229 				return (-1);
230 			break;
231 		}
232 	}
233 }
234 
235 /*
236  * evnv_dupnvl -- duplicate a payload nvlist, keeping only the interesting stuff
237  */
238 nvlist_t *
239 evnv_dupnvl(nvlist_t *nvp)
240 {
241 	nvlist_t *retval = NULL;
242 	int nvret;
243 
244 	if (nvp == NULL)
245 		return (NULL);
246 
247 	if ((nvret = nvlist_xdup(nvp, &retval, &Eft_nv_hdl)) != 0)
248 		out(O_DIE, "dupnvl: dup failed: %d", nvret);
249 
250 	return (retval);
251 }
252