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