xref: /titanic_53/usr/src/cmd/hal/hald/util.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
1*18c2aff7Sartem /***************************************************************************
2*18c2aff7Sartem  * CVSID: $Id$
3*18c2aff7Sartem  *
4*18c2aff7Sartem  * util.c - Various utilities
5*18c2aff7Sartem  *
6*18c2aff7Sartem  * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
7*18c2aff7Sartem  *
8*18c2aff7Sartem  * Licensed under the Academic Free License version 2.1
9*18c2aff7Sartem  *
10*18c2aff7Sartem  * This program is free software; you can redistribute it and/or modify
11*18c2aff7Sartem  * it under the terms of the GNU General Public License as published by
12*18c2aff7Sartem  * the Free Software Foundation; either version 2 of the License, or
13*18c2aff7Sartem  * (at your option) any later version.
14*18c2aff7Sartem  *
15*18c2aff7Sartem  * This program is distributed in the hope that it will be useful,
16*18c2aff7Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*18c2aff7Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*18c2aff7Sartem  * GNU General Public License for more details.
19*18c2aff7Sartem  *
20*18c2aff7Sartem  * You should have received a copy of the GNU General Public License
21*18c2aff7Sartem  * along with this program; if not, write to the Free Software
22*18c2aff7Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23*18c2aff7Sartem  *
24*18c2aff7Sartem  **************************************************************************/
25*18c2aff7Sartem 
26*18c2aff7Sartem #ifdef HAVE_CONFIG_H
27*18c2aff7Sartem #  include <config.h>
28*18c2aff7Sartem #endif
29*18c2aff7Sartem 
30*18c2aff7Sartem #include <stdio.h>
31*18c2aff7Sartem #include <stdarg.h>
32*18c2aff7Sartem #include <string.h>
33*18c2aff7Sartem #include <errno.h>
34*18c2aff7Sartem #include <time.h>
35*18c2aff7Sartem #include <ctype.h>
36*18c2aff7Sartem #include <stdint.h>
37*18c2aff7Sartem #include <sys/stat.h>
38*18c2aff7Sartem #include <unistd.h>
39*18c2aff7Sartem #include <fcntl.h>
40*18c2aff7Sartem #include <signal.h>
41*18c2aff7Sartem #include <sys/wait.h>
42*18c2aff7Sartem #include <sys/file.h>
43*18c2aff7Sartem 
44*18c2aff7Sartem #include <glib.h>
45*18c2aff7Sartem #include <dbus/dbus.h>
46*18c2aff7Sartem #include <dbus/dbus-glib.h>
47*18c2aff7Sartem 
48*18c2aff7Sartem #include "osspec.h"
49*18c2aff7Sartem #include "logger.h"
50*18c2aff7Sartem #include "hald.h"
51*18c2aff7Sartem #include "hald_runner.h"
52*18c2aff7Sartem #include "hald_dbus.h"
53*18c2aff7Sartem #include "device_info.h"
54*18c2aff7Sartem 
55*18c2aff7Sartem #include "util.h"
56*18c2aff7Sartem 
57*18c2aff7Sartem gboolean
58*18c2aff7Sartem hal_util_remove_trailing_slash (gchar *path)
59*18c2aff7Sartem {
60*18c2aff7Sartem 	gchar *c = NULL;
61*18c2aff7Sartem 
62*18c2aff7Sartem 	if (path == NULL) {
63*18c2aff7Sartem 		return FALSE;
64*18c2aff7Sartem 	}
65*18c2aff7Sartem 
66*18c2aff7Sartem 	c = strrchr (path, '/');
67*18c2aff7Sartem 	if (c == NULL) {
68*18c2aff7Sartem 		HAL_WARNING (("Invalid path %s", path));
69*18c2aff7Sartem 		return 1;
70*18c2aff7Sartem 	}
71*18c2aff7Sartem 	if (*(c+1) == '\0')
72*18c2aff7Sartem 		*c = '\0';
73*18c2aff7Sartem 
74*18c2aff7Sartem 	return TRUE;
75*18c2aff7Sartem }
76*18c2aff7Sartem 
77*18c2aff7Sartem /** Given a path, /foo/bar/bat/foobar, return the last element, e.g.
78*18c2aff7Sartem  *  foobar.
79*18c2aff7Sartem  *
80*18c2aff7Sartem  *  @param  path                Path
81*18c2aff7Sartem  *  @return                     Pointer into given string
82*18c2aff7Sartem  */
83*18c2aff7Sartem const gchar *
84*18c2aff7Sartem hal_util_get_last_element (const gchar *s)
85*18c2aff7Sartem {
86*18c2aff7Sartem 	int len;
87*18c2aff7Sartem 	const gchar *p;
88*18c2aff7Sartem 
89*18c2aff7Sartem 	len = strlen (s);
90*18c2aff7Sartem 	for (p = s + len - 1; p > s; --p) {
91*18c2aff7Sartem 		if ((*p) == '/')
92*18c2aff7Sartem 			return p + 1;
93*18c2aff7Sartem 	}
94*18c2aff7Sartem 
95*18c2aff7Sartem 	return s;
96*18c2aff7Sartem }
97*18c2aff7Sartem 
98*18c2aff7Sartem /** Given a path, this functions finds the path representing the
99*18c2aff7Sartem  *  parent directory by truncation.
100*18c2aff7Sartem  *
101*18c2aff7Sartem  *  @param  path                Path
102*18c2aff7Sartem  *  @return                     Path for parent or NULL. Must be freed by caller
103*18c2aff7Sartem  */
104*18c2aff7Sartem gchar *
105*18c2aff7Sartem hal_util_get_parent_path (const gchar *path)
106*18c2aff7Sartem {
107*18c2aff7Sartem 	guint i;
108*18c2aff7Sartem 	guint len;
109*18c2aff7Sartem 	gchar *parent_path;
110*18c2aff7Sartem 
111*18c2aff7Sartem 	/* Find parent device by truncating our own path */
112*18c2aff7Sartem 	parent_path = g_strndup (path, HAL_PATH_MAX);
113*18c2aff7Sartem 	len = strlen (parent_path);
114*18c2aff7Sartem 	for (i = len - 1; parent_path[i] != '/'; --i) {
115*18c2aff7Sartem 		parent_path[i] = '\0';
116*18c2aff7Sartem 	}
117*18c2aff7Sartem 	parent_path[i] = '\0';
118*18c2aff7Sartem 
119*18c2aff7Sartem 	return parent_path;
120*18c2aff7Sartem }
121*18c2aff7Sartem 
122*18c2aff7Sartem gchar *
123*18c2aff7Sartem hal_util_get_normalized_path (const gchar *path1, const gchar *path2)
124*18c2aff7Sartem {
125*18c2aff7Sartem 	int len1;
126*18c2aff7Sartem 	int len2;
127*18c2aff7Sartem 	const gchar *p1;
128*18c2aff7Sartem 	const gchar *p2;
129*18c2aff7Sartem 	gchar buf[HAL_PATH_MAX];
130*18c2aff7Sartem 
131*18c2aff7Sartem 	len1 = strlen (path1);
132*18c2aff7Sartem 	len2 = strlen (path2);
133*18c2aff7Sartem 
134*18c2aff7Sartem 	p1 = path1 + len1;
135*18c2aff7Sartem 
136*18c2aff7Sartem 	p2 = path2;
137*18c2aff7Sartem 	while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) {
138*18c2aff7Sartem 		p2 += 3;
139*18c2aff7Sartem 
140*18c2aff7Sartem 		while (p1 >= path1 && *(--p1)!='/')
141*18c2aff7Sartem 			;
142*18c2aff7Sartem 	}
143*18c2aff7Sartem 
144*18c2aff7Sartem 	if ((p1-path1) < 0) {
145*18c2aff7Sartem 		HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2));
146*18c2aff7Sartem 		return NULL;
147*18c2aff7Sartem 	}
148*18c2aff7Sartem 
149*18c2aff7Sartem 	strncpy (buf, path1, (p1-path1));
150*18c2aff7Sartem 	buf[p1-path1] = '\0';
151*18c2aff7Sartem 
152*18c2aff7Sartem 	return g_strdup_printf ("%s/%s", buf, p2);
153*18c2aff7Sartem }
154*18c2aff7Sartem 
155*18c2aff7Sartem gboolean
156*18c2aff7Sartem hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base)
157*18c2aff7Sartem {
158*18c2aff7Sartem 	FILE *f;
159*18c2aff7Sartem 	char buf[64];
160*18c2aff7Sartem 	gchar path[HAL_PATH_MAX];
161*18c2aff7Sartem 	gboolean ret;
162*18c2aff7Sartem 
163*18c2aff7Sartem 	f = NULL;
164*18c2aff7Sartem 	ret = FALSE;
165*18c2aff7Sartem 
166*18c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
167*18c2aff7Sartem 
168*18c2aff7Sartem 	f = fopen (path, "rb");
169*18c2aff7Sartem 	if (f == NULL) {
170*18c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
171*18c2aff7Sartem 		goto out;
172*18c2aff7Sartem 	}
173*18c2aff7Sartem 
174*18c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
175*18c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
176*18c2aff7Sartem 		goto out;
177*18c2aff7Sartem 	}
178*18c2aff7Sartem 
179*18c2aff7Sartem 	/* TODO: handle error condition */
180*18c2aff7Sartem 	*result = strtol (buf, NULL, base);
181*18c2aff7Sartem 	ret = TRUE;
182*18c2aff7Sartem 
183*18c2aff7Sartem out:
184*18c2aff7Sartem 	if (f != NULL)
185*18c2aff7Sartem 		fclose (f);
186*18c2aff7Sartem 
187*18c2aff7Sartem 	return ret;
188*18c2aff7Sartem }
189*18c2aff7Sartem 
190*18c2aff7Sartem gboolean
191*18c2aff7Sartem hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
192*18c2aff7Sartem {
193*18c2aff7Sartem 	gint value;
194*18c2aff7Sartem 	gboolean ret;
195*18c2aff7Sartem 
196*18c2aff7Sartem 	ret = FALSE;
197*18c2aff7Sartem 
198*18c2aff7Sartem 	if (hal_util_get_int_from_file (directory, file, &value, base))
199*18c2aff7Sartem 		ret = hal_device_property_set_int (d, key, value);
200*18c2aff7Sartem 
201*18c2aff7Sartem 	return ret;
202*18c2aff7Sartem }
203*18c2aff7Sartem 
204*18c2aff7Sartem 
205*18c2aff7Sartem gboolean
206*18c2aff7Sartem hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base)
207*18c2aff7Sartem {
208*18c2aff7Sartem 	FILE *f;
209*18c2aff7Sartem 	char buf[64];
210*18c2aff7Sartem 	gchar path[HAL_PATH_MAX];
211*18c2aff7Sartem 	gboolean ret;
212*18c2aff7Sartem 
213*18c2aff7Sartem 	f = NULL;
214*18c2aff7Sartem 	ret = FALSE;
215*18c2aff7Sartem 
216*18c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
217*18c2aff7Sartem 
218*18c2aff7Sartem 	f = fopen (path, "rb");
219*18c2aff7Sartem 	if (f == NULL) {
220*18c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
221*18c2aff7Sartem 		goto out;
222*18c2aff7Sartem 	}
223*18c2aff7Sartem 
224*18c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
225*18c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
226*18c2aff7Sartem 		goto out;
227*18c2aff7Sartem 	}
228*18c2aff7Sartem 
229*18c2aff7Sartem 	/* TODO: handle error condition */
230*18c2aff7Sartem 	*result = strtoll (buf, NULL, base);
231*18c2aff7Sartem 
232*18c2aff7Sartem 	ret = TRUE;
233*18c2aff7Sartem 
234*18c2aff7Sartem out:
235*18c2aff7Sartem 	if (f != NULL)
236*18c2aff7Sartem 		fclose (f);
237*18c2aff7Sartem 
238*18c2aff7Sartem 	return ret;
239*18c2aff7Sartem }
240*18c2aff7Sartem 
241*18c2aff7Sartem gboolean
242*18c2aff7Sartem hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
243*18c2aff7Sartem {
244*18c2aff7Sartem 	guint64 value;
245*18c2aff7Sartem 	gboolean ret;
246*18c2aff7Sartem 
247*18c2aff7Sartem 	ret = FALSE;
248*18c2aff7Sartem 
249*18c2aff7Sartem 	if (hal_util_get_uint64_from_file (directory, file, &value, base))
250*18c2aff7Sartem 		ret = hal_device_property_set_uint64 (d, key, value);
251*18c2aff7Sartem 
252*18c2aff7Sartem 	return ret;
253*18c2aff7Sartem }
254*18c2aff7Sartem 
255*18c2aff7Sartem gboolean
256*18c2aff7Sartem hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result)
257*18c2aff7Sartem {
258*18c2aff7Sartem 	FILE *f;
259*18c2aff7Sartem 	char buf[64];
260*18c2aff7Sartem 	gchar path[HAL_PATH_MAX];
261*18c2aff7Sartem 	gboolean ret;
262*18c2aff7Sartem 	gint digit;
263*18c2aff7Sartem 	gint left, right;
264*18c2aff7Sartem 	gboolean passed_white_space;
265*18c2aff7Sartem 	gint num_prec;
266*18c2aff7Sartem 	gsize len;
267*18c2aff7Sartem 	gchar c;
268*18c2aff7Sartem 	guint i;
269*18c2aff7Sartem 
270*18c2aff7Sartem 	f = NULL;
271*18c2aff7Sartem 	ret = FALSE;
272*18c2aff7Sartem 
273*18c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
274*18c2aff7Sartem 
275*18c2aff7Sartem 	f = fopen (path, "rb");
276*18c2aff7Sartem 	if (f == NULL) {
277*18c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
278*18c2aff7Sartem 		goto out;
279*18c2aff7Sartem 	}
280*18c2aff7Sartem 
281*18c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
282*18c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
283*18c2aff7Sartem 		goto out;
284*18c2aff7Sartem 	}
285*18c2aff7Sartem 
286*18c2aff7Sartem 	left = 0;
287*18c2aff7Sartem 	len = strlen (buf);
288*18c2aff7Sartem 	passed_white_space = FALSE;
289*18c2aff7Sartem 	for (i = 0; i < len && buf[i] != '.'; i++) {
290*18c2aff7Sartem 		if (g_ascii_isspace (buf[i])) {
291*18c2aff7Sartem 			if (passed_white_space)
292*18c2aff7Sartem 				break;
293*18c2aff7Sartem 			else
294*18c2aff7Sartem 				continue;
295*18c2aff7Sartem 		}
296*18c2aff7Sartem 		passed_white_space = TRUE;
297*18c2aff7Sartem 		left *= 16;
298*18c2aff7Sartem 		c = buf[i];
299*18c2aff7Sartem 		digit = (int) (c - '0');
300*18c2aff7Sartem 		left += digit;
301*18c2aff7Sartem 	}
302*18c2aff7Sartem 	i++;
303*18c2aff7Sartem 	right = 0;
304*18c2aff7Sartem 	num_prec = 0;
305*18c2aff7Sartem 	for (; i < len; i++) {
306*18c2aff7Sartem 		if (g_ascii_isspace (buf[i]))
307*18c2aff7Sartem 			break;
308*18c2aff7Sartem 		if (num_prec == 2)	        /* Only care about two digits
309*18c2aff7Sartem 						 * of precision */
310*18c2aff7Sartem 			break;
311*18c2aff7Sartem 		right *= 16;
312*18c2aff7Sartem 		c = buf[i];
313*18c2aff7Sartem 		digit = (int) (c - '0');
314*18c2aff7Sartem 		right += digit;
315*18c2aff7Sartem 		num_prec++;
316*18c2aff7Sartem 	}
317*18c2aff7Sartem 
318*18c2aff7Sartem 	for (; num_prec < 2; num_prec++)
319*18c2aff7Sartem 		right *= 16;
320*18c2aff7Sartem 
321*18c2aff7Sartem 	*result = left * 256 + (right & 255);
322*18c2aff7Sartem 	ret = TRUE;
323*18c2aff7Sartem 
324*18c2aff7Sartem out:
325*18c2aff7Sartem 	if (f != NULL)
326*18c2aff7Sartem 		fclose (f);
327*18c2aff7Sartem 
328*18c2aff7Sartem 	return ret;
329*18c2aff7Sartem }
330*18c2aff7Sartem 
331*18c2aff7Sartem gboolean
332*18c2aff7Sartem hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
333*18c2aff7Sartem {
334*18c2aff7Sartem 	gint value;
335*18c2aff7Sartem 	gboolean ret;
336*18c2aff7Sartem 
337*18c2aff7Sartem 	ret = FALSE;
338*18c2aff7Sartem 
339*18c2aff7Sartem 	if (hal_util_get_bcd2_from_file (directory, file, &value))
340*18c2aff7Sartem 		ret = hal_device_property_set_int (d, key, value);
341*18c2aff7Sartem 
342*18c2aff7Sartem 	return ret;
343*18c2aff7Sartem }
344*18c2aff7Sartem 
345*18c2aff7Sartem gchar *
346*18c2aff7Sartem hal_util_get_string_from_file (const gchar *directory, const gchar *file)
347*18c2aff7Sartem {
348*18c2aff7Sartem 	FILE *f;
349*18c2aff7Sartem 	static gchar buf[256];
350*18c2aff7Sartem 	gchar path[HAL_PATH_MAX];
351*18c2aff7Sartem 	gchar *result;
352*18c2aff7Sartem 	gsize len;
353*18c2aff7Sartem 	gint i;
354*18c2aff7Sartem 
355*18c2aff7Sartem 	f = NULL;
356*18c2aff7Sartem 	result = NULL;
357*18c2aff7Sartem 
358*18c2aff7Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
359*18c2aff7Sartem 
360*18c2aff7Sartem 	f = fopen (path, "rb");
361*18c2aff7Sartem 	if (f == NULL) {
362*18c2aff7Sartem 		HAL_ERROR (("Cannot open '%s'", path));
363*18c2aff7Sartem 		goto out;
364*18c2aff7Sartem 	}
365*18c2aff7Sartem 
366*18c2aff7Sartem 	buf[0] = '\0';
367*18c2aff7Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
368*18c2aff7Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
369*18c2aff7Sartem 		goto out;
370*18c2aff7Sartem 	}
371*18c2aff7Sartem 
372*18c2aff7Sartem 	len = strlen (buf);
373*18c2aff7Sartem 	if (len>0)
374*18c2aff7Sartem 		buf[len-1] = '\0';
375*18c2aff7Sartem 
376*18c2aff7Sartem 	/* Clear remaining whitespace */
377*18c2aff7Sartem 	for (i = len - 2; i >= 0; --i) {
378*18c2aff7Sartem 		if (!g_ascii_isspace (buf[i]))
379*18c2aff7Sartem 			break;
380*18c2aff7Sartem 		buf[i] = '\0';
381*18c2aff7Sartem 	}
382*18c2aff7Sartem 
383*18c2aff7Sartem 	result = buf;
384*18c2aff7Sartem 
385*18c2aff7Sartem out:
386*18c2aff7Sartem 	if (f != NULL)
387*18c2aff7Sartem 		fclose (f);
388*18c2aff7Sartem 
389*18c2aff7Sartem 	return result;
390*18c2aff7Sartem }
391*18c2aff7Sartem 
392*18c2aff7Sartem gboolean
393*18c2aff7Sartem hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
394*18c2aff7Sartem {
395*18c2aff7Sartem 	gchar *buf;
396*18c2aff7Sartem 	gboolean ret;
397*18c2aff7Sartem 
398*18c2aff7Sartem 	ret = FALSE;
399*18c2aff7Sartem 
400*18c2aff7Sartem 	if ((buf = hal_util_get_string_from_file (directory, file)) != NULL)
401*18c2aff7Sartem 		ret = hal_device_property_set_string (d, key, buf);
402*18c2aff7Sartem 
403*18c2aff7Sartem 	return ret;
404*18c2aff7Sartem }
405*18c2aff7Sartem 
406*18c2aff7Sartem void
407*18c2aff7Sartem hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...)
408*18c2aff7Sartem {
409*18c2aff7Sartem 	guint i;
410*18c2aff7Sartem 	va_list args;
411*18c2aff7Sartem 	gchar buf[256];
412*18c2aff7Sartem 
413*18c2aff7Sartem 	va_start (args, format);
414*18c2aff7Sartem 	g_vsnprintf (buf, sizeof (buf), format, args);
415*18c2aff7Sartem 	va_end (args);
416*18c2aff7Sartem 
417*18c2aff7Sartem 	g_strcanon (buf,
418*18c2aff7Sartem 		    "/_"
419*18c2aff7Sartem 		    "abcdefghijklmnopqrstuvwxyz"
420*18c2aff7Sartem 		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
421*18c2aff7Sartem 		    "1234567890", '_');
422*18c2aff7Sartem 
423*18c2aff7Sartem 	g_strlcpy (dst, buf, dstsize);
424*18c2aff7Sartem 	if (hal_device_store_find (store, dst) == NULL)
425*18c2aff7Sartem 		goto out;
426*18c2aff7Sartem 
427*18c2aff7Sartem 	for (i = 0; ; i++) {
428*18c2aff7Sartem 		g_snprintf (dst, dstsize, "%s_%d", buf, i);
429*18c2aff7Sartem 		if (hal_device_store_find (store, dst) == NULL)
430*18c2aff7Sartem 			goto out;
431*18c2aff7Sartem 	}
432*18c2aff7Sartem 
433*18c2aff7Sartem out:
434*18c2aff7Sartem 	;
435*18c2aff7Sartem }
436*18c2aff7Sartem 
437*18c2aff7Sartem 
438*18c2aff7Sartem gboolean
439*18c2aff7Sartem hal_util_path_ascend (gchar *path)
440*18c2aff7Sartem {
441*18c2aff7Sartem 	gchar *p;
442*18c2aff7Sartem 
443*18c2aff7Sartem 	if (path == NULL)
444*18c2aff7Sartem 		return FALSE;
445*18c2aff7Sartem 
446*18c2aff7Sartem 	p = strrchr (path, '/');
447*18c2aff7Sartem 	if (p == NULL)
448*18c2aff7Sartem 		return FALSE;
449*18c2aff7Sartem 
450*18c2aff7Sartem 	*p = '\0';
451*18c2aff7Sartem 	return TRUE;
452*18c2aff7Sartem }
453*18c2aff7Sartem 
454*18c2aff7Sartem static gboolean _grep_can_reuse = FALSE;
455*18c2aff7Sartem 
456*18c2aff7Sartem void
457*18c2aff7Sartem hal_util_grep_discard_existing_data (void)
458*18c2aff7Sartem {
459*18c2aff7Sartem 	_grep_can_reuse = FALSE;
460*18c2aff7Sartem }
461*18c2aff7Sartem 
462*18c2aff7Sartem /** Given a directory and filename, open the file and search for the
463*18c2aff7Sartem  *  first line that starts with the given linestart string. Returns
464*18c2aff7Sartem  *  the rest of the line as a string if found.
465*18c2aff7Sartem  *
466*18c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
467*18c2aff7Sartem  *  @param  file                File, e.g. "info"
468*18c2aff7Sartem  *  @param  linestart           Start of line, e.g. "serial number"
469*18c2aff7Sartem  *  @param  reuse               Whether we should reuse the file contents
470*18c2aff7Sartem  *                              if the file is the same; can be cleared
471*18c2aff7Sartem  *                              with hal_util_grep_discard_existing_data()
472*18c2aff7Sartem  *  @return                     NULL if not found, otherwise the remainder
473*18c2aff7Sartem  *                              of the line, e.g. ":           21805" if
474*18c2aff7Sartem  *                              the file /proc/acpi/battery/BAT0 contains
475*18c2aff7Sartem  *                              this line "serial number:           21805"
476*18c2aff7Sartem  *                              The string is only valid until the next
477*18c2aff7Sartem  *                              invocation of this function.
478*18c2aff7Sartem  */
479*18c2aff7Sartem gchar *
480*18c2aff7Sartem hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse)
481*18c2aff7Sartem {
482*18c2aff7Sartem 	static gchar buf[2048];
483*18c2aff7Sartem 	static unsigned int bufsize;
484*18c2aff7Sartem 	static gchar filename[HAL_PATH_MAX];
485*18c2aff7Sartem 	static gchar oldfilename[HAL_PATH_MAX];
486*18c2aff7Sartem 	gchar *result;
487*18c2aff7Sartem 	gsize linestart_len;
488*18c2aff7Sartem 	gchar *p;
489*18c2aff7Sartem 
490*18c2aff7Sartem 	result = NULL;
491*18c2aff7Sartem 
492*18c2aff7Sartem 	/* TODO: use reuse and _grep_can_reuse parameters to avoid loading
493*18c2aff7Sartem 	 *       the file again and again
494*18c2aff7Sartem 	 */
495*18c2aff7Sartem 
496*18c2aff7Sartem 	if (file != NULL && strlen (file) > 0)
497*18c2aff7Sartem 		snprintf (filename, sizeof (filename), "%s/%s", directory, file);
498*18c2aff7Sartem 	else
499*18c2aff7Sartem 		strncpy (filename, directory, sizeof (filename));
500*18c2aff7Sartem 
501*18c2aff7Sartem 	if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) {
502*18c2aff7Sartem 		/* just reuse old file; e.g. bufsize, buf */
503*18c2aff7Sartem 		/*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/
504*18c2aff7Sartem 	} else {
505*18c2aff7Sartem 		FILE *f;
506*18c2aff7Sartem 
507*18c2aff7Sartem 		f = fopen (filename, "r");
508*18c2aff7Sartem 		if (f == NULL)
509*18c2aff7Sartem 			goto out;
510*18c2aff7Sartem 		bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f);
511*18c2aff7Sartem 		buf[bufsize] = '\0';
512*18c2aff7Sartem 		fclose (f);
513*18c2aff7Sartem 
514*18c2aff7Sartem 		/*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/
515*18c2aff7Sartem 	}
516*18c2aff7Sartem 
517*18c2aff7Sartem 	/* book keeping */
518*18c2aff7Sartem 	_grep_can_reuse = TRUE;
519*18c2aff7Sartem 	strncpy (oldfilename, filename, sizeof(oldfilename));
520*18c2aff7Sartem 
521*18c2aff7Sartem 	linestart_len = strlen (linestart);
522*18c2aff7Sartem 
523*18c2aff7Sartem 	/* analyze buf */
524*18c2aff7Sartem 	p = buf;
525*18c2aff7Sartem 	do {
526*18c2aff7Sartem 		unsigned int linelen;
527*18c2aff7Sartem 		static char line[256];
528*18c2aff7Sartem 
529*18c2aff7Sartem 		for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++)
530*18c2aff7Sartem 			;
531*18c2aff7Sartem 
532*18c2aff7Sartem 		if (linelen < sizeof (line)) {
533*18c2aff7Sartem 
534*18c2aff7Sartem 			strncpy (line, p, linelen);
535*18c2aff7Sartem 			line[linelen] = '\0';
536*18c2aff7Sartem 
537*18c2aff7Sartem 			if (strncmp (line, linestart, linestart_len) == 0) {
538*18c2aff7Sartem 				result = line + linestart_len;
539*18c2aff7Sartem 				goto out;
540*18c2aff7Sartem 			}
541*18c2aff7Sartem 		}
542*18c2aff7Sartem 
543*18c2aff7Sartem 		p += linelen + 1;
544*18c2aff7Sartem 
545*18c2aff7Sartem 	} while (p < buf + bufsize);
546*18c2aff7Sartem 
547*18c2aff7Sartem out:
548*18c2aff7Sartem 	return result;
549*18c2aff7Sartem }
550*18c2aff7Sartem 
551*18c2aff7Sartem gchar *
552*18c2aff7Sartem hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file,
553*18c2aff7Sartem 				     const gchar *linestart, guint elem, gboolean reuse)
554*18c2aff7Sartem {
555*18c2aff7Sartem 	gchar *line;
556*18c2aff7Sartem 	gchar *res;
557*18c2aff7Sartem 	static gchar buf[256];
558*18c2aff7Sartem 	gchar **tokens;
559*18c2aff7Sartem 	guint i, j;
560*18c2aff7Sartem 
561*18c2aff7Sartem 	res = NULL;
562*18c2aff7Sartem 	tokens = NULL;
563*18c2aff7Sartem 
564*18c2aff7Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
565*18c2aff7Sartem 		goto out;
566*18c2aff7Sartem 
567*18c2aff7Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
568*18c2aff7Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
569*18c2aff7Sartem 		if (strlen (tokens[i]) == 0)
570*18c2aff7Sartem 			continue;
571*18c2aff7Sartem 		if (j == elem) {
572*18c2aff7Sartem 			strncpy (buf, tokens[i], sizeof (buf));
573*18c2aff7Sartem 			res = buf;
574*18c2aff7Sartem 			goto out;
575*18c2aff7Sartem 		}
576*18c2aff7Sartem 		j++;
577*18c2aff7Sartem 	}
578*18c2aff7Sartem 
579*18c2aff7Sartem out:
580*18c2aff7Sartem 	if (tokens != NULL)
581*18c2aff7Sartem 		g_strfreev (tokens);
582*18c2aff7Sartem 
583*18c2aff7Sartem 	return res;
584*18c2aff7Sartem }
585*18c2aff7Sartem 
586*18c2aff7Sartem gint
587*18c2aff7Sartem hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file,
588*18c2aff7Sartem 				  const gchar *linestart, guint elem, guint base, gboolean reuse)
589*18c2aff7Sartem {
590*18c2aff7Sartem 	gchar *endptr;
591*18c2aff7Sartem 	gchar *strvalue;
592*18c2aff7Sartem 	int value;
593*18c2aff7Sartem 
594*18c2aff7Sartem 	value = G_MAXINT;
595*18c2aff7Sartem 
596*18c2aff7Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
597*18c2aff7Sartem 	if (strvalue == NULL)
598*18c2aff7Sartem 		goto out;
599*18c2aff7Sartem 
600*18c2aff7Sartem 	value = strtol (strvalue, &endptr, base);
601*18c2aff7Sartem 	if (endptr == strvalue) {
602*18c2aff7Sartem 		value = G_MAXINT;
603*18c2aff7Sartem 		goto out;
604*18c2aff7Sartem 	}
605*18c2aff7Sartem 
606*18c2aff7Sartem out:
607*18c2aff7Sartem 	return value;
608*18c2aff7Sartem }
609*18c2aff7Sartem 
610*18c2aff7Sartem /** Get a string value from a formatted text file and assign it to
611*18c2aff7Sartem  *  a property on a device object.
612*18c2aff7Sartem  *
613*18c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
614*18c2aff7Sartem  *  the line
615*18c2aff7Sartem  *
616*18c2aff7Sartem  *    "design voltage:          10800 mV"
617*18c2aff7Sartem  *
618*18c2aff7Sartem  *  then hal_util_set_string_elem_from_file (d, "battery.foo",
619*18c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign
620*18c2aff7Sartem  *  the string "mV" to the property "battery.foo" on d.
621*18c2aff7Sartem  *
622*18c2aff7Sartem  *  @param  d                   Device object
623*18c2aff7Sartem  *  @param  key                 Property name
624*18c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
625*18c2aff7Sartem  *  @param  file                File, e.g. "info"
626*18c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
627*18c2aff7Sartem  *  @param  elem                Element number after linestart to extract
628*18c2aff7Sartem  *                              excluding whitespace and ':' characters.
629*18c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
630*18c2aff7Sartem  *                              extracted and the property was set
631*18c2aff7Sartem  */
632*18c2aff7Sartem gboolean
633*18c2aff7Sartem hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key,
634*18c2aff7Sartem 				    const gchar *directory, const gchar *file,
635*18c2aff7Sartem 				    const gchar *linestart, guint elem, gboolean reuse)
636*18c2aff7Sartem {
637*18c2aff7Sartem 	gboolean res;
638*18c2aff7Sartem 	gchar *value;
639*18c2aff7Sartem 
640*18c2aff7Sartem 	res = FALSE;
641*18c2aff7Sartem 
642*18c2aff7Sartem 	if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL)
643*18c2aff7Sartem 		goto out;
644*18c2aff7Sartem 
645*18c2aff7Sartem 	res = hal_device_property_set_string (d, key, value);
646*18c2aff7Sartem out:
647*18c2aff7Sartem 	return res;
648*18c2aff7Sartem }
649*18c2aff7Sartem 
650*18c2aff7Sartem /** Get an integer value from a formatted text file and assign it to
651*18c2aff7Sartem  *  a property on a device object.
652*18c2aff7Sartem  *
653*18c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
654*18c2aff7Sartem  *  the line
655*18c2aff7Sartem  *
656*18c2aff7Sartem  *    "design voltage:          10800 mV"
657*18c2aff7Sartem  *
658*18c2aff7Sartem  *  then hal_util_set_int_elem_from_file (d, "battery.foo",
659*18c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign
660*18c2aff7Sartem  *  the integer 10800 to the property "battery.foo" on d.
661*18c2aff7Sartem  *
662*18c2aff7Sartem  *  @param  d                   Device object
663*18c2aff7Sartem  *  @param  key                 Property name
664*18c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
665*18c2aff7Sartem  *  @param  file                File, e.g. "info"
666*18c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
667*18c2aff7Sartem  *  @param  elem                Element number after linestart to extract
668*18c2aff7Sartem  *                              excluding whitespace and ':' characters.
669*18c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
670*18c2aff7Sartem  *                              extracted and the property was set
671*18c2aff7Sartem  */
672*18c2aff7Sartem gboolean
673*18c2aff7Sartem hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key,
674*18c2aff7Sartem 				 const gchar *directory, const gchar *file,
675*18c2aff7Sartem 				 const gchar *linestart, guint elem, guint base, gboolean reuse)
676*18c2aff7Sartem {
677*18c2aff7Sartem 	gchar *endptr;
678*18c2aff7Sartem 	gboolean res;
679*18c2aff7Sartem 	gchar *strvalue;
680*18c2aff7Sartem 	int value;
681*18c2aff7Sartem 
682*18c2aff7Sartem 	res = FALSE;
683*18c2aff7Sartem 
684*18c2aff7Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
685*18c2aff7Sartem 	if (strvalue == NULL)
686*18c2aff7Sartem 		goto out;
687*18c2aff7Sartem 
688*18c2aff7Sartem 	value = strtol (strvalue, &endptr, base);
689*18c2aff7Sartem 	if (endptr == strvalue)
690*18c2aff7Sartem 		goto out;
691*18c2aff7Sartem 
692*18c2aff7Sartem 	res = hal_device_property_set_int (d, key, value);
693*18c2aff7Sartem 
694*18c2aff7Sartem out:
695*18c2aff7Sartem 	return res;
696*18c2aff7Sartem 
697*18c2aff7Sartem }
698*18c2aff7Sartem 
699*18c2aff7Sartem /** Get a value from a formatted text file, test it against a given
700*18c2aff7Sartem  *  value, and set a boolean property on a device object with the
701*18c2aff7Sartem  *  test result.
702*18c2aff7Sartem  *
703*18c2aff7Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
704*18c2aff7Sartem  *  the line
705*18c2aff7Sartem  *
706*18c2aff7Sartem  *    "present:                 yes"
707*18c2aff7Sartem  *
708*18c2aff7Sartem  *  then hal_util_set_bool_elem_from_file (d, "battery.baz",
709*18c2aff7Sartem  *  "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign
710*18c2aff7Sartem  *  the boolean TRUE to the property "battery.baz" on d.
711*18c2aff7Sartem  *
712*18c2aff7Sartem  *  If, instead, the line was
713*18c2aff7Sartem  *
714*18c2aff7Sartem  *    "present:                 no"
715*18c2aff7Sartem  *
716*18c2aff7Sartem  *  the value assigned will be FALSE.
717*18c2aff7Sartem  *
718*18c2aff7Sartem  *  @param  d                   Device object
719*18c2aff7Sartem  *  @param  key                 Property name
720*18c2aff7Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
721*18c2aff7Sartem  *  @param  file                File, e.g. "info"
722*18c2aff7Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
723*18c2aff7Sartem  *  @param  elem                Element number after linestart to extract
724*18c2aff7Sartem  *                              excluding whitespace and ':' characters.
725*18c2aff7Sartem  *  @param  expected            Value to test against
726*18c2aff7Sartem  *  @return                     TRUE, if, and only if, the value could be
727*18c2aff7Sartem  *                              extracted and the property was set
728*18c2aff7Sartem  */
729*18c2aff7Sartem gboolean
730*18c2aff7Sartem hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key,
731*18c2aff7Sartem 				  const gchar *directory, const gchar *file,
732*18c2aff7Sartem 				  const gchar *linestart, guint elem, const gchar *expected, gboolean reuse)
733*18c2aff7Sartem {
734*18c2aff7Sartem 	gchar *line;
735*18c2aff7Sartem 	gboolean res;
736*18c2aff7Sartem 	gchar **tokens;
737*18c2aff7Sartem 	guint i, j;
738*18c2aff7Sartem 
739*18c2aff7Sartem 	res = FALSE;
740*18c2aff7Sartem 	tokens = NULL;
741*18c2aff7Sartem 
742*18c2aff7Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
743*18c2aff7Sartem 		goto out;
744*18c2aff7Sartem 
745*18c2aff7Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
746*18c2aff7Sartem 
747*18c2aff7Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
748*18c2aff7Sartem 		if (strlen (tokens[i]) == 0)
749*18c2aff7Sartem 			continue;
750*18c2aff7Sartem 		if (j == elem) {
751*18c2aff7Sartem 			hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0);
752*18c2aff7Sartem 			res = TRUE;
753*18c2aff7Sartem 			goto out;
754*18c2aff7Sartem 		}
755*18c2aff7Sartem 		j++;
756*18c2aff7Sartem 	}
757*18c2aff7Sartem 
758*18c2aff7Sartem 
759*18c2aff7Sartem out:
760*18c2aff7Sartem 	if (tokens != NULL)
761*18c2aff7Sartem 		g_strfreev (tokens);
762*18c2aff7Sartem 
763*18c2aff7Sartem 	return res;
764*18c2aff7Sartem }
765*18c2aff7Sartem 
766*18c2aff7Sartem gchar **
767*18c2aff7Sartem hal_util_dup_strv_from_g_slist (GSList *strlist)
768*18c2aff7Sartem {
769*18c2aff7Sartem 	guint j;
770*18c2aff7Sartem 	guint len;
771*18c2aff7Sartem 	gchar **strv;
772*18c2aff7Sartem 	GSList *i;
773*18c2aff7Sartem 
774*18c2aff7Sartem 	len = g_slist_length (strlist);
775*18c2aff7Sartem 	strv = g_new (char *, len + 1);
776*18c2aff7Sartem 
777*18c2aff7Sartem 	for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) {
778*18c2aff7Sartem 		strv[j] = g_strdup ((const gchar *) i->data);
779*18c2aff7Sartem 	}
780*18c2aff7Sartem 	strv[j] = NULL;
781*18c2aff7Sartem 
782*18c2aff7Sartem 	return strv;
783*18c2aff7Sartem }
784*18c2aff7Sartem 
785*18c2aff7Sartem /* -------------------------------------------------------------------------------------------------------------- */
786*18c2aff7Sartem 
787*18c2aff7Sartem typedef struct {
788*18c2aff7Sartem 	HalDevice *d;
789*18c2aff7Sartem 	gchar **programs;
790*18c2aff7Sartem 	gchar **extra_env;
791*18c2aff7Sartem 	guint next_program;
792*18c2aff7Sartem 
793*18c2aff7Sartem 	HalCalloutsDone callback;
794*18c2aff7Sartem 	gpointer userdata1;
795*18c2aff7Sartem 	gpointer userdata2;
796*18c2aff7Sartem 
797*18c2aff7Sartem } Callout;
798*18c2aff7Sartem 
799*18c2aff7Sartem static void callout_do_next (Callout *c);
800*18c2aff7Sartem 
801*18c2aff7Sartem static void
802*18c2aff7Sartem callout_terminated (HalDevice *d, guint32 exit_type,
803*18c2aff7Sartem                    gint return_code, gchar **error,
804*18c2aff7Sartem                    gpointer data1, gpointer data2)
805*18c2aff7Sartem {
806*18c2aff7Sartem 	Callout *c;
807*18c2aff7Sartem 
808*18c2aff7Sartem 	c = (Callout *) data1;
809*18c2aff7Sartem 	callout_do_next (c);
810*18c2aff7Sartem }
811*18c2aff7Sartem 
812*18c2aff7Sartem static void
813*18c2aff7Sartem callout_do_next (Callout *c)
814*18c2aff7Sartem {
815*18c2aff7Sartem 
816*18c2aff7Sartem 	/* Check if we're done */
817*18c2aff7Sartem 	if (c->programs[c->next_program] == NULL) {
818*18c2aff7Sartem 		HalDevice *d;
819*18c2aff7Sartem 		gpointer userdata1;
820*18c2aff7Sartem 		gpointer userdata2;
821*18c2aff7Sartem 		HalCalloutsDone callback;
822*18c2aff7Sartem 
823*18c2aff7Sartem 		d = c->d;
824*18c2aff7Sartem 		userdata1 = c->userdata1;
825*18c2aff7Sartem 		userdata2 = c->userdata2;
826*18c2aff7Sartem 		callback = c->callback;
827*18c2aff7Sartem 
828*18c2aff7Sartem 		g_strfreev (c->programs);
829*18c2aff7Sartem 		g_strfreev (c->extra_env);
830*18c2aff7Sartem 		g_free (c);
831*18c2aff7Sartem 
832*18c2aff7Sartem 		callback (d, userdata1, userdata2);
833*18c2aff7Sartem 
834*18c2aff7Sartem 	} else {
835*18c2aff7Sartem     hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
836*18c2aff7Sartem                     HAL_HELPER_TIMEOUT, callout_terminated,
837*18c2aff7Sartem                     (gpointer)c, NULL);
838*18c2aff7Sartem 		c->next_program++;
839*18c2aff7Sartem 	}
840*18c2aff7Sartem }
841*18c2aff7Sartem 
842*18c2aff7Sartem static void
843*18c2aff7Sartem hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2,
844*18c2aff7Sartem 		    GSList *programs, gchar **extra_env)
845*18c2aff7Sartem {
846*18c2aff7Sartem 	Callout *c;
847*18c2aff7Sartem 
848*18c2aff7Sartem 	c = g_new0 (Callout, 1);
849*18c2aff7Sartem 	c->d = d;
850*18c2aff7Sartem 	c->callback = callback;
851*18c2aff7Sartem 	c->userdata1 = userdata1;
852*18c2aff7Sartem 	c->userdata2 = userdata2;
853*18c2aff7Sartem 	c->programs = hal_util_dup_strv_from_g_slist (programs);
854*18c2aff7Sartem 	c->extra_env = g_strdupv (extra_env);
855*18c2aff7Sartem 	c->next_program = 0;
856*18c2aff7Sartem 
857*18c2aff7Sartem 	callout_do_next (c);
858*18c2aff7Sartem }
859*18c2aff7Sartem 
860*18c2aff7Sartem void
861*18c2aff7Sartem hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
862*18c2aff7Sartem {
863*18c2aff7Sartem 	GSList *programs;
864*18c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=add", NULL};
865*18c2aff7Sartem 
866*18c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) {
867*18c2aff7Sartem 		callback (d, userdata1, userdata2);
868*18c2aff7Sartem 		goto out;
869*18c2aff7Sartem 	}
870*18c2aff7Sartem 
871*18c2aff7Sartem 	HAL_INFO (("Add callouts for udi=%s", d->udi));
872*18c2aff7Sartem 
873*18c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
874*18c2aff7Sartem out:
875*18c2aff7Sartem 	;
876*18c2aff7Sartem }
877*18c2aff7Sartem 
878*18c2aff7Sartem void
879*18c2aff7Sartem hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
880*18c2aff7Sartem {
881*18c2aff7Sartem 	GSList *programs;
882*18c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=remove", NULL};
883*18c2aff7Sartem 
884*18c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) {
885*18c2aff7Sartem 		callback (d, userdata1, userdata2);
886*18c2aff7Sartem 		goto out;
887*18c2aff7Sartem 	}
888*18c2aff7Sartem 
889*18c2aff7Sartem 	HAL_INFO (("Remove callouts for udi=%s", d->udi));
890*18c2aff7Sartem 
891*18c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
892*18c2aff7Sartem out:
893*18c2aff7Sartem 	;
894*18c2aff7Sartem }
895*18c2aff7Sartem 
896*18c2aff7Sartem void
897*18c2aff7Sartem hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
898*18c2aff7Sartem {
899*18c2aff7Sartem 	GSList *programs;
900*18c2aff7Sartem 	gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL};
901*18c2aff7Sartem 
902*18c2aff7Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) {
903*18c2aff7Sartem 		callback (d, userdata1, userdata2);
904*18c2aff7Sartem 		goto out;
905*18c2aff7Sartem 	}
906*18c2aff7Sartem 
907*18c2aff7Sartem 	HAL_INFO (("Preprobe callouts for udi=%s", d->udi));
908*18c2aff7Sartem 
909*18c2aff7Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
910*18c2aff7Sartem out:
911*18c2aff7Sartem 	;
912*18c2aff7Sartem }
913*18c2aff7Sartem 
914*18c2aff7Sartem gchar *
915*18c2aff7Sartem hal_util_strdup_valid_utf8 (const char *str)
916*18c2aff7Sartem {
917*18c2aff7Sartem 	char *endchar;
918*18c2aff7Sartem 	char *newstr;
919*18c2aff7Sartem 	unsigned int count = 0;
920*18c2aff7Sartem 
921*18c2aff7Sartem 	if (str == NULL)
922*18c2aff7Sartem 		return NULL;
923*18c2aff7Sartem 
924*18c2aff7Sartem 	newstr = g_strdup (str);
925*18c2aff7Sartem 
926*18c2aff7Sartem 	while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
927*18c2aff7Sartem 		*endchar = '?';
928*18c2aff7Sartem 		count++;
929*18c2aff7Sartem 	}
930*18c2aff7Sartem 
931*18c2aff7Sartem 	if (strlen(newstr) == count)
932*18c2aff7Sartem 		return NULL;
933*18c2aff7Sartem 	else
934*18c2aff7Sartem 		return newstr;
935*18c2aff7Sartem }
936*18c2aff7Sartem 
937*18c2aff7Sartem void
938*18c2aff7Sartem hal_util_hexdump (const void *mem, unsigned int size)
939*18c2aff7Sartem {
940*18c2aff7Sartem 	unsigned int i;
941*18c2aff7Sartem 	unsigned int j;
942*18c2aff7Sartem 	unsigned int n;
943*18c2aff7Sartem 	const char *buf = (const char *) mem;
944*18c2aff7Sartem 
945*18c2aff7Sartem 	n = 0;
946*18c2aff7Sartem 	printf ("Dumping %d=0x%x bytes\n", size, size);
947*18c2aff7Sartem 	while (n < size) {
948*18c2aff7Sartem 
949*18c2aff7Sartem 		printf ("0x%04x: ", n);
950*18c2aff7Sartem 
951*18c2aff7Sartem 		j = n;
952*18c2aff7Sartem 		for (i = 0; i < 16; i++) {
953*18c2aff7Sartem 			if (j >= size)
954*18c2aff7Sartem 				break;
955*18c2aff7Sartem 			printf ("%02x ", buf[j]);
956*18c2aff7Sartem 			j++;
957*18c2aff7Sartem 		}
958*18c2aff7Sartem 
959*18c2aff7Sartem 		for ( ; i < 16; i++) {
960*18c2aff7Sartem 			printf ("   ");
961*18c2aff7Sartem 		}
962*18c2aff7Sartem 
963*18c2aff7Sartem 		printf ("   ");
964*18c2aff7Sartem 
965*18c2aff7Sartem 		j = n;
966*18c2aff7Sartem 		for (i = 0; i < 16; i++) {
967*18c2aff7Sartem 			if (j >= size)
968*18c2aff7Sartem 				break;
969*18c2aff7Sartem 			printf ("%c", isprint(buf[j]) ? buf[j] : '.');
970*18c2aff7Sartem 			j++;
971*18c2aff7Sartem 		}
972*18c2aff7Sartem 
973*18c2aff7Sartem 		printf ("\n");
974*18c2aff7Sartem 
975*18c2aff7Sartem 		n += 16;
976*18c2aff7Sartem 	}
977*18c2aff7Sartem }
978*18c2aff7Sartem 
979*18c2aff7Sartem gboolean
980*18c2aff7Sartem hal_util_is_mounted_by_hald (const char *mount_point)
981*18c2aff7Sartem {
982*18c2aff7Sartem 	int i;
983*18c2aff7Sartem 	FILE *hal_mtab;
984*18c2aff7Sartem 	int hal_mtab_len;
985*18c2aff7Sartem 	int num_read;
986*18c2aff7Sartem 	char *hal_mtab_buf;
987*18c2aff7Sartem 	char **lines;
988*18c2aff7Sartem 	gboolean found;
989*18c2aff7Sartem 
990*18c2aff7Sartem 	hal_mtab = NULL;
991*18c2aff7Sartem 	hal_mtab_buf = NULL;
992*18c2aff7Sartem 	found = FALSE;
993*18c2aff7Sartem 
994*18c2aff7Sartem 	/*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/
995*18c2aff7Sartem 
996*18c2aff7Sartem 	hal_mtab = fopen ("/media/.hal-mtab", "r");
997*18c2aff7Sartem 	if (hal_mtab == NULL) {
998*18c2aff7Sartem 		HAL_ERROR (("Cannot open /media/.hal-mtab"));
999*18c2aff7Sartem 		goto out;
1000*18c2aff7Sartem 	}
1001*18c2aff7Sartem 	if (fseek (hal_mtab, 0L, SEEK_END) != 0) {
1002*18c2aff7Sartem 		HAL_ERROR (("Cannot seek to end of /media/.hal-mtab"));
1003*18c2aff7Sartem 		goto out;
1004*18c2aff7Sartem 	}
1005*18c2aff7Sartem 	hal_mtab_len = ftell (hal_mtab);
1006*18c2aff7Sartem 	if (hal_mtab_len < 0) {
1007*18c2aff7Sartem 		HAL_ERROR (("Cannot determine size of /media/.hal-mtab"));
1008*18c2aff7Sartem 		goto out;
1009*18c2aff7Sartem 	}
1010*18c2aff7Sartem 	rewind (hal_mtab);
1011*18c2aff7Sartem 
1012*18c2aff7Sartem 	hal_mtab_buf = g_new0 (char, hal_mtab_len + 1);
1013*18c2aff7Sartem 	num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab);
1014*18c2aff7Sartem 	if (num_read != hal_mtab_len) {
1015*18c2aff7Sartem 		HAL_ERROR (("Cannot read from /media/.hal-mtab"));
1016*18c2aff7Sartem 		goto out;
1017*18c2aff7Sartem 	}
1018*18c2aff7Sartem 	fclose (hal_mtab);
1019*18c2aff7Sartem 	hal_mtab = NULL;
1020*18c2aff7Sartem 
1021*18c2aff7Sartem 	/*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/
1022*18c2aff7Sartem 
1023*18c2aff7Sartem 	lines = g_strsplit (hal_mtab_buf, "\n", 0);
1024*18c2aff7Sartem 	g_free (hal_mtab_buf);
1025*18c2aff7Sartem 	hal_mtab_buf = NULL;
1026*18c2aff7Sartem 
1027*18c2aff7Sartem 	/* find the entry we're going to unmount */
1028*18c2aff7Sartem 	for (i = 0; lines[i] != NULL && !found; i++) {
1029*18c2aff7Sartem 		char **line_elements;
1030*18c2aff7Sartem 
1031*18c2aff7Sartem 		/*HAL_DEBUG ((" line = '%s'", lines[i]));*/
1032*18c2aff7Sartem 
1033*18c2aff7Sartem 		if ((lines[i])[0] == '#')
1034*18c2aff7Sartem 			continue;
1035*18c2aff7Sartem 
1036*18c2aff7Sartem 		line_elements = g_strsplit (lines[i], "\t", 6);
1037*18c2aff7Sartem 		if (g_strv_length (line_elements) == 6) {
1038*18c2aff7Sartem /*
1039*18c2aff7Sartem 			HAL_DEBUG (("  devfile     = '%s'", line_elements[0]));
1040*18c2aff7Sartem 			HAL_DEBUG (("  uid         = '%s'", line_elements[1]));
1041*18c2aff7Sartem 			HAL_DEBUG (("  session id  = '%s'", line_elements[2]));
1042*18c2aff7Sartem 			HAL_DEBUG (("  fs          = '%s'", line_elements[3]));
1043*18c2aff7Sartem 			HAL_DEBUG (("  options     = '%s'", line_elements[4]));
1044*18c2aff7Sartem 			HAL_DEBUG (("  mount_point = '%s'", line_elements[5]));
1045*18c2aff7Sartem 			HAL_DEBUG (("  (comparing against '%s')", mount_point));
1046*18c2aff7Sartem */
1047*18c2aff7Sartem 
1048*18c2aff7Sartem 			if (strcmp (line_elements[5], mount_point) == 0) {
1049*18c2aff7Sartem 				found = TRUE;
1050*18c2aff7Sartem 				/*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/
1051*18c2aff7Sartem 			}
1052*18c2aff7Sartem 
1053*18c2aff7Sartem 		}
1054*18c2aff7Sartem 
1055*18c2aff7Sartem 		g_strfreev (line_elements);
1056*18c2aff7Sartem 	}
1057*18c2aff7Sartem 
1058*18c2aff7Sartem 	g_strfreev (lines);
1059*18c2aff7Sartem 
1060*18c2aff7Sartem out:
1061*18c2aff7Sartem 	if (hal_mtab != NULL)
1062*18c2aff7Sartem 		fclose (hal_mtab);
1063*18c2aff7Sartem 	if (hal_mtab_buf != NULL)
1064*18c2aff7Sartem 		g_free (hal_mtab_buf);
1065*18c2aff7Sartem 
1066*18c2aff7Sartem 	return found;
1067*18c2aff7Sartem }
1068*18c2aff7Sartem 
1069*18c2aff7Sartem void
1070*18c2aff7Sartem hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed,
1071*18c2aff7Sartem     const char *service, int uid)
1072*18c2aff7Sartem {
1073*18c2aff7Sartem 	GSList *children;
1074*18c2aff7Sartem 	GSList *i;
1075*18c2aff7Sartem 	HalDevice *d;
1076*18c2aff7Sartem 
1077*18c2aff7Sartem 	if (claimed) {
1078*18c2aff7Sartem 		hal_device_property_set_bool (root, "info.claimed", claimed);
1079*18c2aff7Sartem 		hal_device_property_set_string (root, "info.claimed.service", service);
1080*18c2aff7Sartem 		hal_device_property_set_int (root, "info.claimed.uid", uid);
1081*18c2aff7Sartem 	} else {
1082*18c2aff7Sartem 		hal_device_property_remove (root, "info.claimed");
1083*18c2aff7Sartem 		hal_device_property_remove (root, "info.claimed.service");
1084*18c2aff7Sartem 		hal_device_property_remove (root, "info.claimed.uid");
1085*18c2aff7Sartem 	}
1086*18c2aff7Sartem 
1087*18c2aff7Sartem 
1088*18c2aff7Sartem 	children = hal_device_store_match_multiple_key_value_string (store,
1089*18c2aff7Sartem 	    "info.parent", root->udi);
1090*18c2aff7Sartem 
1091*18c2aff7Sartem 	for (i = children; i != NULL; i = g_slist_next (i)) {
1092*18c2aff7Sartem 		d = HAL_DEVICE (i->data);
1093*18c2aff7Sartem 		hal_util_branch_claim (store, d, claimed, service, uid);
1094*18c2aff7Sartem 	}
1095*18c2aff7Sartem 
1096*18c2aff7Sartem 	g_slist_free (children);
1097*18c2aff7Sartem }
1098