xref: /onnv-gate/usr/src/cmd/hal/hald/util.c (revision 10659:933eae95189d)
12912Sartem /***************************************************************************
22912Sartem  * CVSID: $Id$
32912Sartem  *
42912Sartem  * util.c - Various utilities
52912Sartem  *
62912Sartem  * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
72912Sartem  *
82912Sartem  * Licensed under the Academic Free License version 2.1
92912Sartem  *
102912Sartem  * This program is free software; you can redistribute it and/or modify
112912Sartem  * it under the terms of the GNU General Public License as published by
122912Sartem  * the Free Software Foundation; either version 2 of the License, or
132912Sartem  * (at your option) any later version.
142912Sartem  *
152912Sartem  * This program is distributed in the hope that it will be useful,
162912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
172912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
182912Sartem  * GNU General Public License for more details.
192912Sartem  *
202912Sartem  * You should have received a copy of the GNU General Public License
212912Sartem  * along with this program; if not, write to the Free Software
222912Sartem  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
232912Sartem  *
242912Sartem  **************************************************************************/
252912Sartem 
262912Sartem #ifdef HAVE_CONFIG_H
272912Sartem #  include <config.h>
282912Sartem #endif
292912Sartem 
302912Sartem #include <stdio.h>
312912Sartem #include <stdarg.h>
322912Sartem #include <string.h>
332912Sartem #include <errno.h>
342912Sartem #include <time.h>
352912Sartem #include <ctype.h>
362912Sartem #include <stdint.h>
372912Sartem #include <sys/stat.h>
382912Sartem #include <unistd.h>
392912Sartem #include <fcntl.h>
402912Sartem #include <signal.h>
412912Sartem #include <sys/wait.h>
422912Sartem #include <sys/file.h>
432912Sartem 
442912Sartem #include <glib.h>
452912Sartem #include <dbus/dbus.h>
462912Sartem #include <dbus/dbus-glib.h>
472912Sartem 
482912Sartem #include "osspec.h"
492912Sartem #include "logger.h"
502912Sartem #include "hald.h"
512912Sartem #include "hald_runner.h"
522912Sartem #include "hald_dbus.h"
532912Sartem #include "device_info.h"
542912Sartem 
552912Sartem #include "util.h"
562912Sartem 
57*10659SXiao-Lin.Zhang@Sun.COM /** Determine whether the given character is valid as the first character
58*10659SXiao-Lin.Zhang@Sun.COM  *  in a name.
59*10659SXiao-Lin.Zhang@Sun.COM  */
60*10659SXiao-Lin.Zhang@Sun.COM #define VALID_INITIAL_NAME_CHARACTER(c)          \
61*10659SXiao-Lin.Zhang@Sun.COM 	(((c) >= 'A' && (c) <= 'Z') ||           \
62*10659SXiao-Lin.Zhang@Sun.COM 	((c) >= 'a' && (c) <= 'z') ||            \
63*10659SXiao-Lin.Zhang@Sun.COM 	((c) == '_'))
64*10659SXiao-Lin.Zhang@Sun.COM 
65*10659SXiao-Lin.Zhang@Sun.COM /** Determine whether the given character is valid as a second or later
66*10659SXiao-Lin.Zhang@Sun.COM  *  character in a name.
67*10659SXiao-Lin.Zhang@Sun.COM  */
68*10659SXiao-Lin.Zhang@Sun.COM #define VALID_NAME_CHARACTER(c)                  \
69*10659SXiao-Lin.Zhang@Sun.COM 	(((c) >= '0' && (c) <= '9') ||           \
70*10659SXiao-Lin.Zhang@Sun.COM 	((c) >= 'A' && (c) <= 'Z') ||            \
71*10659SXiao-Lin.Zhang@Sun.COM 	((c) >= 'a' && (c) <= 'z') ||            \
72*10659SXiao-Lin.Zhang@Sun.COM 	((c) == '_'))
73*10659SXiao-Lin.Zhang@Sun.COM 
742912Sartem gboolean
hal_util_remove_trailing_slash(gchar * path)752912Sartem hal_util_remove_trailing_slash (gchar *path)
762912Sartem {
772912Sartem 	gchar *c = NULL;
782912Sartem 
792912Sartem 	if (path == NULL) {
802912Sartem 		return FALSE;
812912Sartem 	}
822912Sartem 
832912Sartem 	c = strrchr (path, '/');
842912Sartem 	if (c == NULL) {
852912Sartem 		HAL_WARNING (("Invalid path %s", path));
862912Sartem 		return 1;
872912Sartem 	}
882912Sartem 	if (*(c+1) == '\0')
892912Sartem 		*c = '\0';
902912Sartem 
912912Sartem 	return TRUE;
922912Sartem }
932912Sartem 
942912Sartem /** Given a path, /foo/bar/bat/foobar, return the last element, e.g.
952912Sartem  *  foobar.
962912Sartem  *
972912Sartem  *  @param  path                Path
982912Sartem  *  @return                     Pointer into given string
992912Sartem  */
1002912Sartem const gchar *
hal_util_get_last_element(const gchar * s)1012912Sartem hal_util_get_last_element (const gchar *s)
1022912Sartem {
1032912Sartem 	int len;
1042912Sartem 	const gchar *p;
1052912Sartem 
1062912Sartem 	len = strlen (s);
1072912Sartem 	for (p = s + len - 1; p > s; --p) {
1082912Sartem 		if ((*p) == '/')
1092912Sartem 			return p + 1;
1102912Sartem 	}
1112912Sartem 
1122912Sartem 	return s;
1132912Sartem }
1142912Sartem 
1152912Sartem /** Given a path, this functions finds the path representing the
1162912Sartem  *  parent directory by truncation.
1172912Sartem  *
1182912Sartem  *  @param  path                Path
1192912Sartem  *  @return                     Path for parent or NULL. Must be freed by caller
1202912Sartem  */
1212912Sartem gchar *
hal_util_get_parent_path(const gchar * path)1222912Sartem hal_util_get_parent_path (const gchar *path)
1232912Sartem {
1242912Sartem 	guint i;
1252912Sartem 	guint len;
1262912Sartem 	gchar *parent_path;
1272912Sartem 
1282912Sartem 	/* Find parent device by truncating our own path */
1292912Sartem 	parent_path = g_strndup (path, HAL_PATH_MAX);
1302912Sartem 	len = strlen (parent_path);
1312912Sartem 	for (i = len - 1; parent_path[i] != '/'; --i) {
1322912Sartem 		parent_path[i] = '\0';
1332912Sartem 	}
1342912Sartem 	parent_path[i] = '\0';
1352912Sartem 
1362912Sartem 	return parent_path;
1372912Sartem }
1382912Sartem 
1392912Sartem gchar *
hal_util_get_normalized_path(const gchar * path1,const gchar * path2)1402912Sartem hal_util_get_normalized_path (const gchar *path1, const gchar *path2)
1412912Sartem {
1422912Sartem 	int len1;
1432912Sartem 	int len2;
1442912Sartem 	const gchar *p1;
1452912Sartem 	const gchar *p2;
1462912Sartem 	gchar buf[HAL_PATH_MAX];
1472912Sartem 
1482912Sartem 	len1 = strlen (path1);
1492912Sartem 	len2 = strlen (path2);
1502912Sartem 
1512912Sartem 	p1 = path1 + len1;
1522912Sartem 
1532912Sartem 	p2 = path2;
1542912Sartem 	while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) {
1552912Sartem 		p2 += 3;
1562912Sartem 
1572912Sartem 		while (p1 >= path1 && *(--p1)!='/')
1582912Sartem 			;
1592912Sartem 	}
1602912Sartem 
1612912Sartem 	if ((p1-path1) < 0) {
1622912Sartem 		HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2));
1632912Sartem 		return NULL;
1642912Sartem 	}
1652912Sartem 
1662912Sartem 	strncpy (buf, path1, (p1-path1));
1672912Sartem 	buf[p1-path1] = '\0';
1682912Sartem 
1692912Sartem 	return g_strdup_printf ("%s/%s", buf, p2);
1702912Sartem }
1712912Sartem 
1722912Sartem gboolean
hal_util_get_int_from_file(const gchar * directory,const gchar * file,gint * result,gint base)1732912Sartem hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base)
1742912Sartem {
1752912Sartem 	FILE *f;
1762912Sartem 	char buf[64];
1772912Sartem 	gchar path[HAL_PATH_MAX];
1782912Sartem 	gboolean ret;
1792912Sartem 
1802912Sartem 	f = NULL;
1812912Sartem 	ret = FALSE;
1822912Sartem 
1832912Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
1842912Sartem 
1852912Sartem 	f = fopen (path, "rb");
1862912Sartem 	if (f == NULL) {
1872912Sartem 		HAL_ERROR (("Cannot open '%s'", path));
1882912Sartem 		goto out;
1892912Sartem 	}
1902912Sartem 
1912912Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
1922912Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
1932912Sartem 		goto out;
1942912Sartem 	}
1952912Sartem 
1962912Sartem 	/* TODO: handle error condition */
1972912Sartem 	*result = strtol (buf, NULL, base);
1982912Sartem 	ret = TRUE;
1992912Sartem 
2002912Sartem out:
2012912Sartem 	if (f != NULL)
2022912Sartem 		fclose (f);
2032912Sartem 
2042912Sartem 	return ret;
2052912Sartem }
2062912Sartem 
2072912Sartem gboolean
hal_util_set_int_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,gint base)2082912Sartem hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
2092912Sartem {
2102912Sartem 	gint value;
2112912Sartem 	gboolean ret;
2122912Sartem 
2132912Sartem 	ret = FALSE;
2142912Sartem 
2152912Sartem 	if (hal_util_get_int_from_file (directory, file, &value, base))
2162912Sartem 		ret = hal_device_property_set_int (d, key, value);
2172912Sartem 
2182912Sartem 	return ret;
2192912Sartem }
2202912Sartem 
2212912Sartem 
2222912Sartem gboolean
hal_util_get_uint64_from_file(const gchar * directory,const gchar * file,guint64 * result,gint base)2232912Sartem hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base)
2242912Sartem {
2252912Sartem 	FILE *f;
2262912Sartem 	char buf[64];
2272912Sartem 	gchar path[HAL_PATH_MAX];
2282912Sartem 	gboolean ret;
2292912Sartem 
2302912Sartem 	f = NULL;
2312912Sartem 	ret = FALSE;
2322912Sartem 
2332912Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
2342912Sartem 
2352912Sartem 	f = fopen (path, "rb");
2362912Sartem 	if (f == NULL) {
2372912Sartem 		HAL_ERROR (("Cannot open '%s'", path));
2382912Sartem 		goto out;
2392912Sartem 	}
2402912Sartem 
2412912Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
2422912Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
2432912Sartem 		goto out;
2442912Sartem 	}
2452912Sartem 
2462912Sartem 	/* TODO: handle error condition */
2472912Sartem 	*result = strtoll (buf, NULL, base);
2482912Sartem 
2492912Sartem 	ret = TRUE;
2502912Sartem 
2512912Sartem out:
2522912Sartem 	if (f != NULL)
2532912Sartem 		fclose (f);
2542912Sartem 
2552912Sartem 	return ret;
2562912Sartem }
2572912Sartem 
2582912Sartem gboolean
hal_util_set_uint64_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,gint base)2592912Sartem hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
2602912Sartem {
2612912Sartem 	guint64 value;
2622912Sartem 	gboolean ret;
2632912Sartem 
2642912Sartem 	ret = FALSE;
2652912Sartem 
2662912Sartem 	if (hal_util_get_uint64_from_file (directory, file, &value, base))
2672912Sartem 		ret = hal_device_property_set_uint64 (d, key, value);
2682912Sartem 
2692912Sartem 	return ret;
2702912Sartem }
2712912Sartem 
2722912Sartem gboolean
hal_util_get_bcd2_from_file(const gchar * directory,const gchar * file,gint * result)2732912Sartem hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result)
2742912Sartem {
2752912Sartem 	FILE *f;
2762912Sartem 	char buf[64];
2772912Sartem 	gchar path[HAL_PATH_MAX];
2782912Sartem 	gboolean ret;
2792912Sartem 	gint digit;
2802912Sartem 	gint left, right;
2812912Sartem 	gboolean passed_white_space;
2822912Sartem 	gint num_prec;
2832912Sartem 	gsize len;
2842912Sartem 	gchar c;
2852912Sartem 	guint i;
2862912Sartem 
2872912Sartem 	f = NULL;
2882912Sartem 	ret = FALSE;
2892912Sartem 
2902912Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
2912912Sartem 
2922912Sartem 	f = fopen (path, "rb");
2932912Sartem 	if (f == NULL) {
2942912Sartem 		HAL_ERROR (("Cannot open '%s'", path));
2952912Sartem 		goto out;
2962912Sartem 	}
2972912Sartem 
2982912Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
2992912Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
3002912Sartem 		goto out;
3012912Sartem 	}
3022912Sartem 
3032912Sartem 	left = 0;
3042912Sartem 	len = strlen (buf);
3052912Sartem 	passed_white_space = FALSE;
3062912Sartem 	for (i = 0; i < len && buf[i] != '.'; i++) {
3072912Sartem 		if (g_ascii_isspace (buf[i])) {
3082912Sartem 			if (passed_white_space)
3092912Sartem 				break;
3102912Sartem 			else
3112912Sartem 				continue;
3122912Sartem 		}
3132912Sartem 		passed_white_space = TRUE;
3142912Sartem 		left *= 16;
3152912Sartem 		c = buf[i];
3162912Sartem 		digit = (int) (c - '0');
3172912Sartem 		left += digit;
3182912Sartem 	}
3192912Sartem 	i++;
3202912Sartem 	right = 0;
3212912Sartem 	num_prec = 0;
3222912Sartem 	for (; i < len; i++) {
3232912Sartem 		if (g_ascii_isspace (buf[i]))
3242912Sartem 			break;
3252912Sartem 		if (num_prec == 2)	        /* Only care about two digits
3262912Sartem 						 * of precision */
3272912Sartem 			break;
3282912Sartem 		right *= 16;
3292912Sartem 		c = buf[i];
3302912Sartem 		digit = (int) (c - '0');
3312912Sartem 		right += digit;
3322912Sartem 		num_prec++;
3332912Sartem 	}
3342912Sartem 
3352912Sartem 	for (; num_prec < 2; num_prec++)
3362912Sartem 		right *= 16;
3372912Sartem 
3382912Sartem 	*result = left * 256 + (right & 255);
3392912Sartem 	ret = TRUE;
3402912Sartem 
3412912Sartem out:
3422912Sartem 	if (f != NULL)
3432912Sartem 		fclose (f);
3442912Sartem 
3452912Sartem 	return ret;
3462912Sartem }
3472912Sartem 
3482912Sartem gboolean
hal_util_set_bcd2_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file)3492912Sartem hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
3502912Sartem {
3512912Sartem 	gint value;
3522912Sartem 	gboolean ret;
3532912Sartem 
3542912Sartem 	ret = FALSE;
3552912Sartem 
3562912Sartem 	if (hal_util_get_bcd2_from_file (directory, file, &value))
3572912Sartem 		ret = hal_device_property_set_int (d, key, value);
3582912Sartem 
3592912Sartem 	return ret;
3602912Sartem }
3612912Sartem 
3622912Sartem gchar *
hal_util_get_string_from_file(const gchar * directory,const gchar * file)3632912Sartem hal_util_get_string_from_file (const gchar *directory, const gchar *file)
3642912Sartem {
3652912Sartem 	FILE *f;
3662912Sartem 	static gchar buf[256];
3672912Sartem 	gchar path[HAL_PATH_MAX];
3682912Sartem 	gchar *result;
3692912Sartem 	gsize len;
3702912Sartem 	gint i;
3712912Sartem 
3722912Sartem 	f = NULL;
3732912Sartem 	result = NULL;
3742912Sartem 
3752912Sartem 	g_snprintf (path, sizeof (path), "%s/%s", directory, file);
3762912Sartem 
3772912Sartem 	f = fopen (path, "rb");
3782912Sartem 	if (f == NULL) {
3792912Sartem 		HAL_ERROR (("Cannot open '%s'", path));
3802912Sartem 		goto out;
3812912Sartem 	}
3822912Sartem 
3832912Sartem 	buf[0] = '\0';
3842912Sartem 	if (fgets (buf, sizeof (buf), f) == NULL) {
3852912Sartem 		HAL_ERROR (("Cannot read from '%s'", path));
3862912Sartem 		goto out;
3872912Sartem 	}
3882912Sartem 
3892912Sartem 	len = strlen (buf);
3902912Sartem 	if (len>0)
3912912Sartem 		buf[len-1] = '\0';
3922912Sartem 
3932912Sartem 	/* Clear remaining whitespace */
3942912Sartem 	for (i = len - 2; i >= 0; --i) {
3952912Sartem 		if (!g_ascii_isspace (buf[i]))
3962912Sartem 			break;
3972912Sartem 		buf[i] = '\0';
3982912Sartem 	}
3992912Sartem 
4002912Sartem 	result = buf;
4012912Sartem 
4022912Sartem out:
4032912Sartem 	if (f != NULL)
4042912Sartem 		fclose (f);
4052912Sartem 
4062912Sartem 	return result;
4072912Sartem }
4082912Sartem 
4092912Sartem gboolean
hal_util_set_string_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file)4102912Sartem hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
4112912Sartem {
4122912Sartem 	gchar *buf;
4132912Sartem 	gboolean ret;
4142912Sartem 
4152912Sartem 	ret = FALSE;
4162912Sartem 
4172912Sartem 	if ((buf = hal_util_get_string_from_file (directory, file)) != NULL)
4182912Sartem 		ret = hal_device_property_set_string (d, key, buf);
4192912Sartem 
4202912Sartem 	return ret;
4212912Sartem }
4222912Sartem 
4232912Sartem void
hal_util_compute_udi(HalDeviceStore * store,gchar * dst,gsize dstsize,const gchar * format,...)4242912Sartem hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...)
4252912Sartem {
4262912Sartem 	guint i;
4272912Sartem 	va_list args;
4282912Sartem 	gchar buf[256];
4292912Sartem 
4302912Sartem 	va_start (args, format);
4312912Sartem 	g_vsnprintf (buf, sizeof (buf), format, args);
4322912Sartem 	va_end (args);
4332912Sartem 
4342912Sartem 	g_strcanon (buf,
4352912Sartem 		    "/_"
4362912Sartem 		    "abcdefghijklmnopqrstuvwxyz"
4372912Sartem 		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4382912Sartem 		    "1234567890", '_');
4392912Sartem 
4402912Sartem 	g_strlcpy (dst, buf, dstsize);
4412912Sartem 	if (hal_device_store_find (store, dst) == NULL)
4422912Sartem 		goto out;
4432912Sartem 
4442912Sartem 	for (i = 0; ; i++) {
4452912Sartem 		g_snprintf (dst, dstsize, "%s_%d", buf, i);
4462912Sartem 		if (hal_device_store_find (store, dst) == NULL)
4472912Sartem 			goto out;
4482912Sartem 	}
4492912Sartem 
4502912Sartem out:
4512912Sartem 	;
4522912Sartem }
4532912Sartem 
4542912Sartem 
4552912Sartem gboolean
hal_util_path_ascend(gchar * path)4562912Sartem hal_util_path_ascend (gchar *path)
4572912Sartem {
4582912Sartem 	gchar *p;
4592912Sartem 
4602912Sartem 	if (path == NULL)
4612912Sartem 		return FALSE;
4622912Sartem 
4632912Sartem 	p = strrchr (path, '/');
4642912Sartem 	if (p == NULL)
4652912Sartem 		return FALSE;
4662912Sartem 
4672912Sartem 	*p = '\0';
4682912Sartem 	return TRUE;
4692912Sartem }
4702912Sartem 
4712912Sartem static gboolean _grep_can_reuse = FALSE;
4722912Sartem 
4732912Sartem void
hal_util_grep_discard_existing_data(void)4742912Sartem hal_util_grep_discard_existing_data (void)
4752912Sartem {
4762912Sartem 	_grep_can_reuse = FALSE;
4772912Sartem }
4782912Sartem 
4792912Sartem /** Given a directory and filename, open the file and search for the
4802912Sartem  *  first line that starts with the given linestart string. Returns
4812912Sartem  *  the rest of the line as a string if found.
4822912Sartem  *
4832912Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
4842912Sartem  *  @param  file                File, e.g. "info"
4852912Sartem  *  @param  linestart           Start of line, e.g. "serial number"
4862912Sartem  *  @param  reuse               Whether we should reuse the file contents
4872912Sartem  *                              if the file is the same; can be cleared
4882912Sartem  *                              with hal_util_grep_discard_existing_data()
4892912Sartem  *  @return                     NULL if not found, otherwise the remainder
4902912Sartem  *                              of the line, e.g. ":           21805" if
4912912Sartem  *                              the file /proc/acpi/battery/BAT0 contains
4922912Sartem  *                              this line "serial number:           21805"
4932912Sartem  *                              The string is only valid until the next
4942912Sartem  *                              invocation of this function.
4952912Sartem  */
4962912Sartem gchar *
hal_util_grep_file(const gchar * directory,const gchar * file,const gchar * linestart,gboolean reuse)4972912Sartem hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse)
4982912Sartem {
4992912Sartem 	static gchar buf[2048];
5002912Sartem 	static unsigned int bufsize;
5012912Sartem 	static gchar filename[HAL_PATH_MAX];
5022912Sartem 	static gchar oldfilename[HAL_PATH_MAX];
5032912Sartem 	gchar *result;
5042912Sartem 	gsize linestart_len;
5052912Sartem 	gchar *p;
5062912Sartem 
5072912Sartem 	result = NULL;
5082912Sartem 
5092912Sartem 	/* TODO: use reuse and _grep_can_reuse parameters to avoid loading
5102912Sartem 	 *       the file again and again
5112912Sartem 	 */
5122912Sartem 
5132912Sartem 	if (file != NULL && strlen (file) > 0)
5142912Sartem 		snprintf (filename, sizeof (filename), "%s/%s", directory, file);
5152912Sartem 	else
5162912Sartem 		strncpy (filename, directory, sizeof (filename));
5172912Sartem 
5182912Sartem 	if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) {
5192912Sartem 		/* just reuse old file; e.g. bufsize, buf */
5202912Sartem 		/*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/
5212912Sartem 	} else {
5222912Sartem 		FILE *f;
5232912Sartem 
5242912Sartem 		f = fopen (filename, "r");
5252912Sartem 		if (f == NULL)
5262912Sartem 			goto out;
5272912Sartem 		bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f);
5282912Sartem 		buf[bufsize] = '\0';
5292912Sartem 		fclose (f);
5302912Sartem 
5312912Sartem 		/*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/
5322912Sartem 	}
5332912Sartem 
5342912Sartem 	/* book keeping */
5352912Sartem 	_grep_can_reuse = TRUE;
5362912Sartem 	strncpy (oldfilename, filename, sizeof(oldfilename));
5372912Sartem 
5382912Sartem 	linestart_len = strlen (linestart);
5392912Sartem 
5402912Sartem 	/* analyze buf */
5412912Sartem 	p = buf;
5422912Sartem 	do {
5432912Sartem 		unsigned int linelen;
5442912Sartem 		static char line[256];
5452912Sartem 
5462912Sartem 		for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++)
5472912Sartem 			;
5482912Sartem 
5492912Sartem 		if (linelen < sizeof (line)) {
5502912Sartem 
5512912Sartem 			strncpy (line, p, linelen);
5522912Sartem 			line[linelen] = '\0';
5532912Sartem 
5542912Sartem 			if (strncmp (line, linestart, linestart_len) == 0) {
5552912Sartem 				result = line + linestart_len;
5562912Sartem 				goto out;
5572912Sartem 			}
5582912Sartem 		}
5592912Sartem 
5602912Sartem 		p += linelen + 1;
5612912Sartem 
5622912Sartem 	} while (p < buf + bufsize);
5632912Sartem 
5642912Sartem out:
5652912Sartem 	return result;
5662912Sartem }
5672912Sartem 
5682912Sartem gchar *
hal_util_grep_string_elem_from_file(const gchar * directory,const gchar * file,const gchar * linestart,guint elem,gboolean reuse)5692912Sartem hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file,
5702912Sartem 				     const gchar *linestart, guint elem, gboolean reuse)
5712912Sartem {
5722912Sartem 	gchar *line;
5732912Sartem 	gchar *res;
5742912Sartem 	static gchar buf[256];
5752912Sartem 	gchar **tokens;
5762912Sartem 	guint i, j;
5772912Sartem 
5782912Sartem 	res = NULL;
5792912Sartem 	tokens = NULL;
5802912Sartem 
5812912Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
5822912Sartem 		goto out;
5832912Sartem 
5842912Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
5852912Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
5862912Sartem 		if (strlen (tokens[i]) == 0)
5872912Sartem 			continue;
5882912Sartem 		if (j == elem) {
5892912Sartem 			strncpy (buf, tokens[i], sizeof (buf));
5902912Sartem 			res = buf;
5912912Sartem 			goto out;
5922912Sartem 		}
5932912Sartem 		j++;
5942912Sartem 	}
5952912Sartem 
5962912Sartem out:
5972912Sartem 	if (tokens != NULL)
5982912Sartem 		g_strfreev (tokens);
5992912Sartem 
6002912Sartem 	return res;
6012912Sartem }
6022912Sartem 
6032912Sartem gint
hal_util_grep_int_elem_from_file(const gchar * directory,const gchar * file,const gchar * linestart,guint elem,guint base,gboolean reuse)6042912Sartem hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file,
6052912Sartem 				  const gchar *linestart, guint elem, guint base, gboolean reuse)
6062912Sartem {
6072912Sartem 	gchar *endptr;
6082912Sartem 	gchar *strvalue;
6092912Sartem 	int value;
6102912Sartem 
6112912Sartem 	value = G_MAXINT;
6122912Sartem 
6132912Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
6142912Sartem 	if (strvalue == NULL)
6152912Sartem 		goto out;
6162912Sartem 
6172912Sartem 	value = strtol (strvalue, &endptr, base);
6182912Sartem 	if (endptr == strvalue) {
6192912Sartem 		value = G_MAXINT;
6202912Sartem 		goto out;
6212912Sartem 	}
6222912Sartem 
6232912Sartem out:
6242912Sartem 	return value;
6252912Sartem }
6262912Sartem 
6272912Sartem /** Get a string value from a formatted text file and assign it to
6282912Sartem  *  a property on a device object.
6292912Sartem  *
6302912Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
6312912Sartem  *  the line
6322912Sartem  *
6332912Sartem  *    "design voltage:          10800 mV"
6342912Sartem  *
6352912Sartem  *  then hal_util_set_string_elem_from_file (d, "battery.foo",
6362912Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign
6372912Sartem  *  the string "mV" to the property "battery.foo" on d.
6382912Sartem  *
6392912Sartem  *  @param  d                   Device object
6402912Sartem  *  @param  key                 Property name
6412912Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
6422912Sartem  *  @param  file                File, e.g. "info"
6432912Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
6442912Sartem  *  @param  elem                Element number after linestart to extract
6452912Sartem  *                              excluding whitespace and ':' characters.
6462912Sartem  *  @return                     TRUE, if, and only if, the value could be
6472912Sartem  *                              extracted and the property was set
6482912Sartem  */
6492912Sartem gboolean
hal_util_set_string_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,gboolean reuse)6502912Sartem hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key,
6512912Sartem 				    const gchar *directory, const gchar *file,
6522912Sartem 				    const gchar *linestart, guint elem, gboolean reuse)
6532912Sartem {
6542912Sartem 	gboolean res;
6552912Sartem 	gchar *value;
6562912Sartem 
6572912Sartem 	res = FALSE;
6582912Sartem 
6592912Sartem 	if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL)
6602912Sartem 		goto out;
6612912Sartem 
6622912Sartem 	res = hal_device_property_set_string (d, key, value);
6632912Sartem out:
6642912Sartem 	return res;
6652912Sartem }
6662912Sartem 
6672912Sartem /** Get an integer value from a formatted text file and assign it to
6682912Sartem  *  a property on a device object.
6692912Sartem  *
6702912Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
6712912Sartem  *  the line
6722912Sartem  *
6732912Sartem  *    "design voltage:          10800 mV"
6742912Sartem  *
6752912Sartem  *  then hal_util_set_int_elem_from_file (d, "battery.foo",
6762912Sartem  *  "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign
6772912Sartem  *  the integer 10800 to the property "battery.foo" on d.
6782912Sartem  *
6792912Sartem  *  @param  d                   Device object
6802912Sartem  *  @param  key                 Property name
6812912Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
6822912Sartem  *  @param  file                File, e.g. "info"
6832912Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
6842912Sartem  *  @param  elem                Element number after linestart to extract
6852912Sartem  *                              excluding whitespace and ':' characters.
6862912Sartem  *  @return                     TRUE, if, and only if, the value could be
6872912Sartem  *                              extracted and the property was set
6882912Sartem  */
6892912Sartem gboolean
hal_util_set_int_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,guint base,gboolean reuse)6902912Sartem hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key,
6912912Sartem 				 const gchar *directory, const gchar *file,
6922912Sartem 				 const gchar *linestart, guint elem, guint base, gboolean reuse)
6932912Sartem {
6942912Sartem 	gchar *endptr;
6952912Sartem 	gboolean res;
6962912Sartem 	gchar *strvalue;
6972912Sartem 	int value;
6982912Sartem 
6992912Sartem 	res = FALSE;
7002912Sartem 
7012912Sartem 	strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
7022912Sartem 	if (strvalue == NULL)
7032912Sartem 		goto out;
7042912Sartem 
7052912Sartem 	value = strtol (strvalue, &endptr, base);
7062912Sartem 	if (endptr == strvalue)
7072912Sartem 		goto out;
7082912Sartem 
7092912Sartem 	res = hal_device_property_set_int (d, key, value);
7102912Sartem 
7112912Sartem out:
7122912Sartem 	return res;
7132912Sartem 
7142912Sartem }
7152912Sartem 
7162912Sartem /** Get a value from a formatted text file, test it against a given
7172912Sartem  *  value, and set a boolean property on a device object with the
7182912Sartem  *  test result.
7192912Sartem  *
7202912Sartem  *  Example: Given that the file /proc/acpi/battery/BAT0/info contains
7212912Sartem  *  the line
7222912Sartem  *
7232912Sartem  *    "present:                 yes"
7242912Sartem  *
7252912Sartem  *  then hal_util_set_bool_elem_from_file (d, "battery.baz",
7262912Sartem  *  "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign
7272912Sartem  *  the boolean TRUE to the property "battery.baz" on d.
7282912Sartem  *
7292912Sartem  *  If, instead, the line was
7302912Sartem  *
7312912Sartem  *    "present:                 no"
7322912Sartem  *
7332912Sartem  *  the value assigned will be FALSE.
7342912Sartem  *
7352912Sartem  *  @param  d                   Device object
7362912Sartem  *  @param  key                 Property name
7372912Sartem  *  @param  directory           Directory, e.g. "/proc/acpi/battery/BAT0"
7382912Sartem  *  @param  file                File, e.g. "info"
7392912Sartem  *  @param  linestart           Start of line, e.g. "design voltage"
7402912Sartem  *  @param  elem                Element number after linestart to extract
7412912Sartem  *                              excluding whitespace and ':' characters.
7422912Sartem  *  @param  expected            Value to test against
7432912Sartem  *  @return                     TRUE, if, and only if, the value could be
7442912Sartem  *                              extracted and the property was set
7452912Sartem  */
7462912Sartem gboolean
hal_util_set_bool_elem_from_file(HalDevice * d,const gchar * key,const gchar * directory,const gchar * file,const gchar * linestart,guint elem,const gchar * expected,gboolean reuse)7472912Sartem hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key,
7482912Sartem 				  const gchar *directory, const gchar *file,
7492912Sartem 				  const gchar *linestart, guint elem, const gchar *expected, gboolean reuse)
7502912Sartem {
7512912Sartem 	gchar *line;
7522912Sartem 	gboolean res;
7532912Sartem 	gchar **tokens;
7542912Sartem 	guint i, j;
7552912Sartem 
7562912Sartem 	res = FALSE;
7572912Sartem 	tokens = NULL;
7582912Sartem 
7592912Sartem 	if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
7602912Sartem 		goto out;
7612912Sartem 
7622912Sartem 	tokens = g_strsplit_set (line, " \t:", 0);
7632912Sartem 
7642912Sartem 	for (i = 0, j = 0; tokens[i] != NULL; i++) {
7652912Sartem 		if (strlen (tokens[i]) == 0)
7662912Sartem 			continue;
7672912Sartem 		if (j == elem) {
7682912Sartem 			hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0);
7692912Sartem 			res = TRUE;
7702912Sartem 			goto out;
7712912Sartem 		}
7722912Sartem 		j++;
7732912Sartem 	}
7742912Sartem 
7752912Sartem 
7762912Sartem out:
7772912Sartem 	if (tokens != NULL)
7782912Sartem 		g_strfreev (tokens);
7792912Sartem 
7802912Sartem 	return res;
7812912Sartem }
7822912Sartem 
7832912Sartem gchar **
hal_util_dup_strv_from_g_slist(GSList * strlist)7842912Sartem hal_util_dup_strv_from_g_slist (GSList *strlist)
7852912Sartem {
7862912Sartem 	guint j;
7872912Sartem 	guint len;
7882912Sartem 	gchar **strv;
7892912Sartem 	GSList *i;
7902912Sartem 
7912912Sartem 	len = g_slist_length (strlist);
7922912Sartem 	strv = g_new (char *, len + 1);
7932912Sartem 
7942912Sartem 	for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) {
7952912Sartem 		strv[j] = g_strdup ((const gchar *) i->data);
7962912Sartem 	}
7972912Sartem 	strv[j] = NULL;
7982912Sartem 
7992912Sartem 	return strv;
8002912Sartem }
8012912Sartem 
8022912Sartem /* -------------------------------------------------------------------------------------------------------------- */
8032912Sartem 
8042912Sartem typedef struct {
8052912Sartem 	HalDevice *d;
8062912Sartem 	gchar **programs;
8072912Sartem 	gchar **extra_env;
8082912Sartem 	guint next_program;
8092912Sartem 
8102912Sartem 	HalCalloutsDone callback;
8112912Sartem 	gpointer userdata1;
8122912Sartem 	gpointer userdata2;
8132912Sartem 
8142912Sartem } Callout;
8152912Sartem 
8162912Sartem static void callout_do_next (Callout *c);
8172912Sartem 
8182912Sartem static void
callout_terminated(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)8192912Sartem callout_terminated (HalDevice *d, guint32 exit_type,
8202912Sartem                    gint return_code, gchar **error,
8212912Sartem                    gpointer data1, gpointer data2)
8222912Sartem {
8232912Sartem 	Callout *c;
8242912Sartem 
8252912Sartem 	c = (Callout *) data1;
8262912Sartem 	callout_do_next (c);
8272912Sartem }
8282912Sartem 
8292912Sartem static void
callout_do_next(Callout * c)8302912Sartem callout_do_next (Callout *c)
8312912Sartem {
8322912Sartem 
8332912Sartem 	/* Check if we're done */
8342912Sartem 	if (c->programs[c->next_program] == NULL) {
8352912Sartem 		HalDevice *d;
8362912Sartem 		gpointer userdata1;
8372912Sartem 		gpointer userdata2;
8382912Sartem 		HalCalloutsDone callback;
8392912Sartem 
8402912Sartem 		d = c->d;
8412912Sartem 		userdata1 = c->userdata1;
8422912Sartem 		userdata2 = c->userdata2;
8432912Sartem 		callback = c->callback;
8442912Sartem 
8452912Sartem 		g_strfreev (c->programs);
8462912Sartem 		g_strfreev (c->extra_env);
8472912Sartem 		g_free (c);
8482912Sartem 
8492912Sartem 		callback (d, userdata1, userdata2);
8502912Sartem 
8512912Sartem 	} else {
8522912Sartem     hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
8532912Sartem                     HAL_HELPER_TIMEOUT, callout_terminated,
8542912Sartem                     (gpointer)c, NULL);
8552912Sartem 		c->next_program++;
8562912Sartem 	}
8572912Sartem }
8582912Sartem 
8592912Sartem static void
hal_callout_device(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2,GSList * programs,gchar ** extra_env)8602912Sartem hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2,
8612912Sartem 		    GSList *programs, gchar **extra_env)
8622912Sartem {
8632912Sartem 	Callout *c;
8642912Sartem 
8652912Sartem 	c = g_new0 (Callout, 1);
8662912Sartem 	c->d = d;
8672912Sartem 	c->callback = callback;
8682912Sartem 	c->userdata1 = userdata1;
8692912Sartem 	c->userdata2 = userdata2;
8702912Sartem 	c->programs = hal_util_dup_strv_from_g_slist (programs);
8712912Sartem 	c->extra_env = g_strdupv (extra_env);
8722912Sartem 	c->next_program = 0;
8732912Sartem 
8742912Sartem 	callout_do_next (c);
8752912Sartem }
8762912Sartem 
8772912Sartem void
hal_util_callout_device_add(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)8782912Sartem hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
8792912Sartem {
8802912Sartem 	GSList *programs;
8812912Sartem 	gchar *extra_env[2] = {"HALD_ACTION=add", NULL};
8822912Sartem 
8832912Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) {
8842912Sartem 		callback (d, userdata1, userdata2);
8852912Sartem 		goto out;
8862912Sartem 	}
8872912Sartem 
8882912Sartem 	HAL_INFO (("Add callouts for udi=%s", d->udi));
8892912Sartem 
8902912Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
8912912Sartem out:
8922912Sartem 	;
8932912Sartem }
8942912Sartem 
8952912Sartem void
hal_util_callout_device_remove(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)8962912Sartem hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
8972912Sartem {
8982912Sartem 	GSList *programs;
8992912Sartem 	gchar *extra_env[2] = {"HALD_ACTION=remove", NULL};
9002912Sartem 
9012912Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) {
9022912Sartem 		callback (d, userdata1, userdata2);
9032912Sartem 		goto out;
9042912Sartem 	}
9052912Sartem 
9062912Sartem 	HAL_INFO (("Remove callouts for udi=%s", d->udi));
9072912Sartem 
9082912Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
9092912Sartem out:
9102912Sartem 	;
9112912Sartem }
9122912Sartem 
9132912Sartem void
hal_util_callout_device_preprobe(HalDevice * d,HalCalloutsDone callback,gpointer userdata1,gpointer userdata2)9142912Sartem hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
9152912Sartem {
9162912Sartem 	GSList *programs;
9172912Sartem 	gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL};
9182912Sartem 
9192912Sartem 	if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) {
9202912Sartem 		callback (d, userdata1, userdata2);
9212912Sartem 		goto out;
9222912Sartem 	}
9232912Sartem 
9242912Sartem 	HAL_INFO (("Preprobe callouts for udi=%s", d->udi));
9252912Sartem 
9262912Sartem 	hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
9272912Sartem out:
9282912Sartem 	;
9292912Sartem }
9302912Sartem 
9312912Sartem gchar *
hal_util_strdup_valid_utf8(const char * str)9322912Sartem hal_util_strdup_valid_utf8 (const char *str)
9332912Sartem {
9342912Sartem 	char *endchar;
9352912Sartem 	char *newstr;
9362912Sartem 	unsigned int count = 0;
9372912Sartem 
9382912Sartem 	if (str == NULL)
9392912Sartem 		return NULL;
9402912Sartem 
9412912Sartem 	newstr = g_strdup (str);
9422912Sartem 
9432912Sartem 	while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
9442912Sartem 		*endchar = '?';
9452912Sartem 		count++;
9462912Sartem 	}
9472912Sartem 
9482912Sartem 	if (strlen(newstr) == count)
9492912Sartem 		return NULL;
9502912Sartem 	else
9512912Sartem 		return newstr;
9522912Sartem }
9532912Sartem 
9542912Sartem void
hal_util_hexdump(const void * mem,unsigned int size)9552912Sartem hal_util_hexdump (const void *mem, unsigned int size)
9562912Sartem {
9572912Sartem 	unsigned int i;
9582912Sartem 	unsigned int j;
9592912Sartem 	unsigned int n;
9602912Sartem 	const char *buf = (const char *) mem;
9612912Sartem 
9622912Sartem 	n = 0;
9632912Sartem 	printf ("Dumping %d=0x%x bytes\n", size, size);
9642912Sartem 	while (n < size) {
9652912Sartem 
9662912Sartem 		printf ("0x%04x: ", n);
9672912Sartem 
9682912Sartem 		j = n;
9692912Sartem 		for (i = 0; i < 16; i++) {
9702912Sartem 			if (j >= size)
9712912Sartem 				break;
9722912Sartem 			printf ("%02x ", buf[j]);
9732912Sartem 			j++;
9742912Sartem 		}
9752912Sartem 
9762912Sartem 		for ( ; i < 16; i++) {
9772912Sartem 			printf ("   ");
9782912Sartem 		}
9792912Sartem 
9802912Sartem 		printf ("   ");
9812912Sartem 
9822912Sartem 		j = n;
9832912Sartem 		for (i = 0; i < 16; i++) {
9842912Sartem 			if (j >= size)
9852912Sartem 				break;
9862912Sartem 			printf ("%c", isprint(buf[j]) ? buf[j] : '.');
9872912Sartem 			j++;
9882912Sartem 		}
9892912Sartem 
9902912Sartem 		printf ("\n");
9912912Sartem 
9922912Sartem 		n += 16;
9932912Sartem 	}
9942912Sartem }
9952912Sartem 
9962912Sartem gboolean
hal_util_is_mounted_by_hald(const char * mount_point)9972912Sartem hal_util_is_mounted_by_hald (const char *mount_point)
9982912Sartem {
9992912Sartem 	int i;
10002912Sartem 	FILE *hal_mtab;
10012912Sartem 	int hal_mtab_len;
10022912Sartem 	int num_read;
10032912Sartem 	char *hal_mtab_buf;
10042912Sartem 	char **lines;
10052912Sartem 	gboolean found;
10062912Sartem 
10072912Sartem 	hal_mtab = NULL;
10082912Sartem 	hal_mtab_buf = NULL;
10092912Sartem 	found = FALSE;
10102912Sartem 
10112912Sartem 	/*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/
10122912Sartem 
10132912Sartem 	hal_mtab = fopen ("/media/.hal-mtab", "r");
10142912Sartem 	if (hal_mtab == NULL) {
10152912Sartem 		HAL_ERROR (("Cannot open /media/.hal-mtab"));
10162912Sartem 		goto out;
10172912Sartem 	}
10182912Sartem 	if (fseek (hal_mtab, 0L, SEEK_END) != 0) {
10192912Sartem 		HAL_ERROR (("Cannot seek to end of /media/.hal-mtab"));
10202912Sartem 		goto out;
10212912Sartem 	}
10222912Sartem 	hal_mtab_len = ftell (hal_mtab);
10232912Sartem 	if (hal_mtab_len < 0) {
10242912Sartem 		HAL_ERROR (("Cannot determine size of /media/.hal-mtab"));
10252912Sartem 		goto out;
10262912Sartem 	}
10272912Sartem 	rewind (hal_mtab);
10282912Sartem 
10292912Sartem 	hal_mtab_buf = g_new0 (char, hal_mtab_len + 1);
10302912Sartem 	num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab);
10312912Sartem 	if (num_read != hal_mtab_len) {
10322912Sartem 		HAL_ERROR (("Cannot read from /media/.hal-mtab"));
10332912Sartem 		goto out;
10342912Sartem 	}
10352912Sartem 	fclose (hal_mtab);
10362912Sartem 	hal_mtab = NULL;
10372912Sartem 
10382912Sartem 	/*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/
10392912Sartem 
10402912Sartem 	lines = g_strsplit (hal_mtab_buf, "\n", 0);
10412912Sartem 	g_free (hal_mtab_buf);
10422912Sartem 	hal_mtab_buf = NULL;
10432912Sartem 
10442912Sartem 	/* find the entry we're going to unmount */
10452912Sartem 	for (i = 0; lines[i] != NULL && !found; i++) {
10462912Sartem 		char **line_elements;
10472912Sartem 
10482912Sartem 		/*HAL_DEBUG ((" line = '%s'", lines[i]));*/
10492912Sartem 
10502912Sartem 		if ((lines[i])[0] == '#')
10512912Sartem 			continue;
10522912Sartem 
10532912Sartem 		line_elements = g_strsplit (lines[i], "\t", 6);
10542912Sartem 		if (g_strv_length (line_elements) == 6) {
10552912Sartem /*
10562912Sartem 			HAL_DEBUG (("  devfile     = '%s'", line_elements[0]));
10572912Sartem 			HAL_DEBUG (("  uid         = '%s'", line_elements[1]));
10582912Sartem 			HAL_DEBUG (("  session id  = '%s'", line_elements[2]));
10592912Sartem 			HAL_DEBUG (("  fs          = '%s'", line_elements[3]));
10602912Sartem 			HAL_DEBUG (("  options     = '%s'", line_elements[4]));
10612912Sartem 			HAL_DEBUG (("  mount_point = '%s'", line_elements[5]));
10622912Sartem 			HAL_DEBUG (("  (comparing against '%s')", mount_point));
10632912Sartem */
10642912Sartem 
10652912Sartem 			if (strcmp (line_elements[5], mount_point) == 0) {
10662912Sartem 				found = TRUE;
10672912Sartem 				/*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/
10682912Sartem 			}
10692912Sartem 
10702912Sartem 		}
10712912Sartem 
10722912Sartem 		g_strfreev (line_elements);
10732912Sartem 	}
10742912Sartem 
10752912Sartem 	g_strfreev (lines);
10762912Sartem 
10772912Sartem out:
10782912Sartem 	if (hal_mtab != NULL)
10792912Sartem 		fclose (hal_mtab);
10802912Sartem 	if (hal_mtab_buf != NULL)
10812912Sartem 		g_free (hal_mtab_buf);
10822912Sartem 
10832912Sartem 	return found;
10842912Sartem }
10852912Sartem 
10862912Sartem void
hal_util_branch_claim(HalDeviceStore * store,HalDevice * root,dbus_bool_t claimed,const char * service,int uid)10872912Sartem hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed,
10882912Sartem     const char *service, int uid)
10892912Sartem {
10902912Sartem 	GSList *children;
10912912Sartem 	GSList *i;
10922912Sartem 	HalDevice *d;
10932912Sartem 
10942912Sartem 	if (claimed) {
10952912Sartem 		hal_device_property_set_bool (root, "info.claimed", claimed);
10962912Sartem 		hal_device_property_set_string (root, "info.claimed.service", service);
10972912Sartem 		hal_device_property_set_int (root, "info.claimed.uid", uid);
10982912Sartem 	} else {
10992912Sartem 		hal_device_property_remove (root, "info.claimed");
11002912Sartem 		hal_device_property_remove (root, "info.claimed.service");
11012912Sartem 		hal_device_property_remove (root, "info.claimed.uid");
11022912Sartem 	}
11032912Sartem 
11042912Sartem 
11052912Sartem 	children = hal_device_store_match_multiple_key_value_string (store,
11062912Sartem 	    "info.parent", root->udi);
11072912Sartem 
11082912Sartem 	for (i = children; i != NULL; i = g_slist_next (i)) {
11092912Sartem 		d = HAL_DEVICE (i->data);
11102912Sartem 		hal_util_branch_claim (store, d, claimed, service, uid);
11112912Sartem 	}
11122912Sartem 
11132912Sartem 	g_slist_free (children);
11142912Sartem }
1115*10659SXiao-Lin.Zhang@Sun.COM 
1116*10659SXiao-Lin.Zhang@Sun.COM /** Given an interface name, check if it is valid.
1117*10659SXiao-Lin.Zhang@Sun.COM  *  @param  name	A given interface name
1118*10659SXiao-Lin.Zhang@Sun.COM  *  @return		TRUE if name is valid, otherwise FALSE
1119*10659SXiao-Lin.Zhang@Sun.COM  */
1120*10659SXiao-Lin.Zhang@Sun.COM gboolean
is_valid_interface_name(const char * name)1121*10659SXiao-Lin.Zhang@Sun.COM is_valid_interface_name(const char *name) {
1122*10659SXiao-Lin.Zhang@Sun.COM 
1123*10659SXiao-Lin.Zhang@Sun.COM 	const char *end;
1124*10659SXiao-Lin.Zhang@Sun.COM 	const char *last_dot;
1125*10659SXiao-Lin.Zhang@Sun.COM 
1126*10659SXiao-Lin.Zhang@Sun.COM 	last_dot = NULL;
1127*10659SXiao-Lin.Zhang@Sun.COM 
1128*10659SXiao-Lin.Zhang@Sun.COM 	if (strlen(name) == 0)
1129*10659SXiao-Lin.Zhang@Sun.COM 		return FALSE;
1130*10659SXiao-Lin.Zhang@Sun.COM 
1131*10659SXiao-Lin.Zhang@Sun.COM 	end = name + strlen(name);
1132*10659SXiao-Lin.Zhang@Sun.COM 
1133*10659SXiao-Lin.Zhang@Sun.COM 	if (*name == '.')    /* disallow starting with a . */
1134*10659SXiao-Lin.Zhang@Sun.COM 		return FALSE;
1135*10659SXiao-Lin.Zhang@Sun.COM 	else if (!VALID_INITIAL_NAME_CHARACTER (*name))
1136*10659SXiao-Lin.Zhang@Sun.COM 		return FALSE;
1137*10659SXiao-Lin.Zhang@Sun.COM 	else
1138*10659SXiao-Lin.Zhang@Sun.COM 		name++;
1139*10659SXiao-Lin.Zhang@Sun.COM 
1140*10659SXiao-Lin.Zhang@Sun.COM 	while (name != end) {
1141*10659SXiao-Lin.Zhang@Sun.COM 		if (*name == '.') {
1142*10659SXiao-Lin.Zhang@Sun.COM 			if ((name + 1) == end)
1143*10659SXiao-Lin.Zhang@Sun.COM 				return FALSE;
1144*10659SXiao-Lin.Zhang@Sun.COM 			else if (!VALID_INITIAL_NAME_CHARACTER (*(name + 1)))
1145*10659SXiao-Lin.Zhang@Sun.COM 				return FALSE;
1146*10659SXiao-Lin.Zhang@Sun.COM 			last_dot = name;
1147*10659SXiao-Lin.Zhang@Sun.COM 			name++;    /* we just validated the next char, so skip two */
1148*10659SXiao-Lin.Zhang@Sun.COM 		} else if (!VALID_NAME_CHARACTER (*name))
1149*10659SXiao-Lin.Zhang@Sun.COM 			return FALSE;
1150*10659SXiao-Lin.Zhang@Sun.COM 		name++;
1151*10659SXiao-Lin.Zhang@Sun.COM 	}
1152*10659SXiao-Lin.Zhang@Sun.COM 	if (last_dot == NULL)
1153*10659SXiao-Lin.Zhang@Sun.COM 		return FALSE;
1154*10659SXiao-Lin.Zhang@Sun.COM 
1155*10659SXiao-Lin.Zhang@Sun.COM 	return TRUE;
1156*10659SXiao-Lin.Zhang@Sun.COM }
1157