xref: /illumos-gate/usr/src/cmd/hal/hald/property.c (revision d3d50737e566cade9a08d73d2af95105ac7cd960)
1 /***************************************************************************
2  * CVSID: $Id$
3  *
4  * property.c : HalProperty methods
5  *
6  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7  * Copyright (C) 2004 Novell, Inc.
8  *
9  * Licensed under the Academic Free License version 2.1
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  **************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30 
31 #include <string.h>
32 #include <glib.h>
33 
34 #include "logger.h"
35 #include "property.h"
36 
37 struct _HalProperty {
38 	char *key;
39 
40 	int type;
41 	union {
42 		char *str_value;
43 		dbus_int32_t int_value;
44  		dbus_uint64_t uint64_value;
45 		dbus_bool_t bool_value;
46 		double double_value;
47 		GSList *strlist_value;
48 	} v;
49 	gboolean readonly;
50 	gboolean persistence;
51 	gboolean callout;
52 };
53 
54 void
55 hal_property_free (HalProperty *prop)
56 {
57 
58 	g_free (prop->key);
59 
60 	if (prop->type == HAL_PROPERTY_TYPE_STRING) {
61 		g_free (prop->v.str_value);
62 	} else if (prop->type == HAL_PROPERTY_TYPE_STRLIST) {
63 		GSList *i;
64 		for (i = prop->v.strlist_value; i != NULL; i = g_slist_next (i)) {
65 			g_free (i->data);
66 		}
67 		g_slist_free (prop->v.strlist_value);
68 	}
69 
70 	g_free (prop);
71 }
72 
73 HalProperty *
74 hal_property_new_string (const char *key, const char *value)
75 {
76 	HalProperty *prop;
77 	char *endchar;
78 	gboolean validated = TRUE;
79 
80 	prop = g_new0 (HalProperty, 1);
81 
82 	prop->type = HAL_PROPERTY_TYPE_STRING;
83 	prop->key = g_strdup (key);
84 	prop->v.str_value = g_strdup (value != NULL ? value : "");
85 
86 	while (!g_utf8_validate (prop->v.str_value, -1,
87 				 (const char **) &endchar)) {
88 		validated = FALSE;
89 		*endchar = '?';
90 	}
91 
92 	if (!validated) {
93 		HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'",
94 			      key, prop->v.str_value));
95 	}
96 
97 	return prop;
98 }
99 
100 HalProperty *
101 hal_property_new_int (const char *key, dbus_int32_t value)
102 {
103 	HalProperty *prop;
104 
105 	prop = g_new0 (HalProperty, 1);
106 
107 	prop->type = HAL_PROPERTY_TYPE_INT32;
108 	prop->key = g_strdup (key);
109 	prop->v.int_value = value;
110 
111 	return prop;
112 }
113 
114 HalProperty *
115 hal_property_new_uint64 (const char *key, dbus_uint64_t value)
116 {
117 	HalProperty *prop;
118 
119 	prop = g_new0 (HalProperty, 1);
120 
121 	prop->type = HAL_PROPERTY_TYPE_UINT64;
122 	prop->key = g_strdup (key);
123 	prop->v.uint64_value = value;
124 
125 	return prop;
126 }
127 
128 HalProperty *
129 hal_property_new_bool (const char *key, dbus_bool_t value)
130 {
131 	HalProperty *prop;
132 
133 	prop = g_new0 (HalProperty, 1);
134 
135 	prop->type = HAL_PROPERTY_TYPE_BOOLEAN;
136 	prop->key = g_strdup (key);
137 	prop->v.bool_value = value;
138 
139 	return prop;
140 }
141 
142 HalProperty *
143 hal_property_new_double (const char *key, double value)
144 {
145 	HalProperty *prop;
146 
147 	prop = g_new0 (HalProperty, 1);
148 
149 	prop->type = HAL_PROPERTY_TYPE_DOUBLE;
150 	prop->key = g_strdup (key);
151 	prop->v.double_value = value;
152 
153 	return prop;
154 }
155 
156 const char *
157 hal_property_get_key (HalProperty *prop)
158 {
159 	g_return_val_if_fail (prop != NULL, NULL);
160 
161 	return prop->key;
162 }
163 
164 int
165 hal_property_get_type (HalProperty *prop)
166 {
167 	g_return_val_if_fail (prop != NULL, HAL_PROPERTY_TYPE_INVALID);
168 
169 	return prop->type;
170 }
171 
172 const char *
173 hal_property_get_string (HalProperty *prop)
174 {
175 	g_return_val_if_fail (prop != NULL, NULL);
176 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING, NULL);
177 
178 	return prop->v.str_value;
179 }
180 
181 dbus_int32_t
182 hal_property_get_int (HalProperty *prop)
183 {
184 	g_return_val_if_fail (prop != NULL, -1);
185 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32, -1);
186 
187 	return prop->v.int_value;
188 }
189 
190 dbus_uint64_t
191 hal_property_get_uint64 (HalProperty *prop)
192 {
193 	g_return_val_if_fail (prop != NULL, -1);
194 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64, -1);
195 
196 	return prop->v.uint64_value;
197 }
198 
199 dbus_bool_t
200 hal_property_get_bool (HalProperty *prop)
201 {
202 	g_return_val_if_fail (prop != NULL, FALSE);
203 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN, FALSE);
204 
205 	return prop->v.bool_value;
206 }
207 
208 char *
209 hal_property_to_string (HalProperty *prop)
210 {
211 	g_return_val_if_fail (prop != NULL, NULL);
212 
213 	switch (prop->type) {
214 	case HAL_PROPERTY_TYPE_STRING:
215 		return g_strdup (prop->v.str_value);
216 	case HAL_PROPERTY_TYPE_INT32:
217 		return g_strdup_printf ("%d", prop->v.int_value);
218 	case HAL_PROPERTY_TYPE_UINT64:
219 		return g_strdup_printf ("%llu", (long long unsigned int) prop->v.uint64_value);
220 	case HAL_PROPERTY_TYPE_BOOLEAN:
221 		/* FIXME: Maybe use 1 and 0 here instead? */
222 		return g_strdup (prop->v.bool_value ? "true" : "false");
223 	case HAL_PROPERTY_TYPE_DOUBLE:
224 		return g_strdup_printf ("%f", prop->v.double_value);
225 	case HAL_PROPERTY_TYPE_STRLIST:
226 	{
227 		GSList *iter;
228 		guint i;
229 		char buf[256];
230 
231 		i = 0;
232 		buf[0] = '\0';
233 		for (iter = hal_property_get_strlist (prop);
234 		     iter != NULL && i < sizeof(buf);
235 		     iter = g_slist_next (iter)) {
236 			guint len;
237 			const char *str;
238 
239 			str = (const char *) iter->data;
240 			len = strlen (str);
241 			strncpy (buf + i, str, sizeof(buf) - i);
242 			i += len;
243 
244 			if (g_slist_next (iter) != NULL && i < sizeof(buf)) {
245 				buf[i] = '\t';
246 				i++;
247 			}
248 		}
249 		return g_strdup (buf);
250 	}
251 
252 	default:
253 		return NULL;
254 	}
255 }
256 
257 double
258 hal_property_get_double (HalProperty *prop)
259 {
260 	g_return_val_if_fail (prop != NULL, -1.0);
261 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE, -1.0);
262 
263 	return prop->v.double_value;
264 }
265 
266 void
267 hal_property_set_string (HalProperty *prop, const char *value)
268 {
269 	char *endchar;
270 	gboolean validated = TRUE;
271 
272 	g_return_if_fail (prop != NULL);
273 	g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_STRING ||
274 			  prop->type == HAL_PROPERTY_TYPE_INVALID);
275 
276 	prop->type = HAL_PROPERTY_TYPE_STRING;
277 	if (prop->v.str_value != NULL)
278 		g_free (prop->v.str_value);
279 	prop->v.str_value = g_strdup (value);
280 
281 	while (!g_utf8_validate (prop->v.str_value, -1,
282 				 (const char **) &endchar)) {
283 		validated = FALSE;
284 		*endchar = '?';
285 	}
286 
287 	if (!validated) {
288 		HAL_WARNING (("Key '%s' has invalid UTF-8 string '%s'",
289 			      prop->key, value));
290 	}
291 }
292 
293 void
294 hal_property_set_int (HalProperty *prop, dbus_int32_t value)
295 {
296 	g_return_if_fail (prop != NULL);
297 	g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_INT32 ||
298 			  prop->type == HAL_PROPERTY_TYPE_INVALID);
299 
300 	prop->type = HAL_PROPERTY_TYPE_INT32;
301 	prop->v.int_value = value;
302 }
303 
304 void
305 hal_property_set_uint64 (HalProperty *prop, dbus_uint64_t value)
306 {
307 	g_return_if_fail (prop != NULL);
308 	g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_UINT64 ||
309 			  prop->type == HAL_PROPERTY_TYPE_INVALID);
310 
311 	prop->type = HAL_PROPERTY_TYPE_UINT64;
312 	prop->v.uint64_value = value;
313 }
314 
315 void
316 hal_property_set_bool (HalProperty *prop, dbus_bool_t value)
317 {
318 	g_return_if_fail (prop != NULL);
319 	g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_BOOLEAN ||
320 			  prop->type == HAL_PROPERTY_TYPE_INVALID);
321 
322 	prop->type = HAL_PROPERTY_TYPE_BOOLEAN;
323 	prop->v.bool_value = value;
324 }
325 
326 void
327 hal_property_set_double (HalProperty *prop, double value)
328 {
329 	g_return_if_fail (prop != NULL);
330 	g_return_if_fail (prop->type == HAL_PROPERTY_TYPE_DOUBLE ||
331 			  prop->type == HAL_PROPERTY_TYPE_INVALID);
332 
333 	prop->type = HAL_PROPERTY_TYPE_DOUBLE;
334 	prop->v.double_value = value;
335 }
336 
337 void
338 hal_property_set_attribute (HalProperty *prop,
339 			    enum PropertyAttribute attr,
340 			    gboolean val)
341 {
342 	g_return_if_fail (prop != NULL);
343 
344 	switch (attr) {
345 	case READONLY:
346 		prop->readonly = val;
347 		break;
348 	case PERSISTENCE:
349 		prop->persistence = val;
350 		break;
351 	case CALLOUT:
352 		prop->callout = val;
353 		break;
354 	}
355 }
356 
357 gboolean
358 hal_property_get_attribute (HalProperty *prop,
359 			    enum PropertyAttribute attr)
360 {
361 	g_return_val_if_fail (prop != NULL, -1);
362 
363 	switch (attr) {
364 	case READONLY:
365 		return prop->readonly;
366 	case PERSISTENCE:
367 		return prop->persistence;
368 	case CALLOUT:
369 		return prop->callout;
370 	default:
371 		return -1;
372 	}
373 }
374 
375 HalProperty *
376 hal_property_new_strlist (const char *key)
377 {
378 	HalProperty *prop;
379 
380 	prop = g_new0 (HalProperty, 1);
381 
382 	prop->type = HAL_PROPERTY_TYPE_STRLIST;
383 	prop->key = g_strdup (key);
384 	prop->v.strlist_value = NULL;
385 
386 	return prop;
387 }
388 
389 GSList *
390 hal_property_get_strlist (HalProperty *prop)
391 {
392 	g_return_val_if_fail (prop != NULL, NULL);
393 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, NULL);
394 
395 	return prop->v.strlist_value;
396 }
397 
398 gboolean
399 hal_property_strlist_append (HalProperty *prop, const char *value)
400 {
401 	g_return_val_if_fail (prop != NULL, FALSE);
402 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
403 
404 	prop->v.strlist_value = g_slist_append (prop->v.strlist_value, g_strdup (value));
405 
406 	return TRUE;
407 }
408 
409 gboolean
410 hal_property_strlist_prepend (HalProperty *prop, const char *value)
411 {
412 	g_return_val_if_fail (prop != NULL, FALSE);
413 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
414 
415 	prop->v.strlist_value = g_slist_prepend (prop->v.strlist_value, g_strdup (value));
416 
417 	return TRUE;
418 }
419 
420 gboolean
421 hal_property_strlist_remove_elem (HalProperty *prop, guint index)
422 {
423 	GSList *elem;
424 
425 	g_return_val_if_fail (prop != NULL, FALSE);
426 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
427 
428 	if (prop->v.strlist_value == NULL)
429 		return FALSE;
430 
431 	elem = g_slist_nth (prop->v.strlist_value, index);
432 	if (elem == NULL)
433 		return FALSE;
434 
435 	g_free (elem->data);
436 	prop->v.strlist_value = g_slist_delete_link (prop->v.strlist_value, elem);
437 	return TRUE;
438 }
439 
440 
441 gboolean
442 hal_property_strlist_add (HalProperty  *prop, const char *value)
443 {
444 	GSList *elem;
445 
446 	g_return_val_if_fail (prop != NULL, FALSE);
447 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
448 
449 	for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) {
450 		if (strcmp (elem->data, value) == 0) {
451 			return FALSE;
452 		}
453 	}
454 
455 	return hal_property_strlist_append (prop, value);
456 }
457 
458 gboolean
459 hal_property_strlist_remove (HalProperty *prop, const char *value)
460 {
461 	guint i;
462 	GSList *elem;
463 
464 	g_return_val_if_fail (prop != NULL, FALSE);
465 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
466 
467 	for (elem = prop->v.strlist_value, i = 0; elem != NULL; elem = g_slist_next (elem), i++) {
468 		if (strcmp (elem->data, value) == 0) {
469 			return hal_property_strlist_remove_elem (prop, i);
470 		}
471 	}
472 
473 	return FALSE;
474 }
475 
476 gboolean
477 hal_property_strlist_clear (HalProperty *prop)
478 {
479 	GSList *elem;
480 
481 	g_return_val_if_fail (prop != NULL, FALSE);
482 	g_return_val_if_fail (prop->type == HAL_PROPERTY_TYPE_STRLIST, FALSE);
483 
484 	for (elem = prop->v.strlist_value; elem != NULL; elem = g_slist_next (elem)) {
485 		g_free (elem->data);
486 	}
487 	g_slist_free (prop->v.strlist_value);
488 
489 	return FALSE;
490 }
491