8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / hal / hald / util.c
blobb7dc075c499487e23a56e04a7875cfd59fceaa6b
1 /***************************************************************************
2 * CVSID: $Id$
4 * util.c - Various utilities
6 * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
8 * Licensed under the Academic Free License version 2.1
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 **************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <ctype.h>
36 #include <stdint.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <signal.h>
41 #include <sys/wait.h>
42 #include <sys/file.h>
44 #include <glib.h>
45 #include <dbus/dbus.h>
46 #include <dbus/dbus-glib.h>
48 #include "osspec.h"
49 #include "logger.h"
50 #include "hald.h"
51 #include "hald_runner.h"
52 #include "hald_dbus.h"
53 #include "device_info.h"
55 #include "util.h"
57 /** Determine whether the given character is valid as the first character
58 * in a name.
60 #define VALID_INITIAL_NAME_CHARACTER(c) \
61 (((c) >= 'A' && (c) <= 'Z') || \
62 ((c) >= 'a' && (c) <= 'z') || \
63 ((c) == '_'))
65 /** Determine whether the given character is valid as a second or later
66 * character in a name.
68 #define VALID_NAME_CHARACTER(c) \
69 (((c) >= '0' && (c) <= '9') || \
70 ((c) >= 'A' && (c) <= 'Z') || \
71 ((c) >= 'a' && (c) <= 'z') || \
72 ((c) == '_'))
74 gboolean
75 hal_util_remove_trailing_slash (gchar *path)
77 gchar *c = NULL;
79 if (path == NULL) {
80 return FALSE;
83 c = strrchr (path, '/');
84 if (c == NULL) {
85 HAL_WARNING (("Invalid path %s", path));
86 return 1;
88 if (*(c+1) == '\0')
89 *c = '\0';
91 return TRUE;
94 /** Given a path, /foo/bar/bat/foobar, return the last element, e.g.
95 * foobar.
97 * @param path Path
98 * @return Pointer into given string
100 const gchar *
101 hal_util_get_last_element (const gchar *s)
103 int len;
104 const gchar *p;
106 len = strlen (s);
107 for (p = s + len - 1; p > s; --p) {
108 if ((*p) == '/')
109 return p + 1;
112 return s;
115 /** Given a path, this functions finds the path representing the
116 * parent directory by truncation.
118 * @param path Path
119 * @return Path for parent or NULL. Must be freed by caller
121 gchar *
122 hal_util_get_parent_path (const gchar *path)
124 guint i;
125 guint len;
126 gchar *parent_path;
128 /* Find parent device by truncating our own path */
129 parent_path = g_strndup (path, HAL_PATH_MAX);
130 len = strlen (parent_path);
131 for (i = len - 1; parent_path[i] != '/'; --i) {
132 parent_path[i] = '\0';
134 parent_path[i] = '\0';
136 return parent_path;
139 gchar *
140 hal_util_get_normalized_path (const gchar *path1, const gchar *path2)
142 int len1;
143 int len2;
144 const gchar *p1;
145 const gchar *p2;
146 gchar buf[HAL_PATH_MAX];
148 len1 = strlen (path1);
149 len2 = strlen (path2);
151 p1 = path1 + len1;
153 p2 = path2;
154 while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) {
155 p2 += 3;
157 while (p1 >= path1 && *(--p1)!='/')
161 if ((p1-path1) < 0) {
162 HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2));
163 return NULL;
166 strncpy (buf, path1, (p1-path1));
167 buf[p1-path1] = '\0';
169 return g_strdup_printf ("%s/%s", buf, p2);
172 gboolean
173 hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base)
175 FILE *f;
176 char buf[64];
177 gchar path[HAL_PATH_MAX];
178 gboolean ret;
180 f = NULL;
181 ret = FALSE;
183 g_snprintf (path, sizeof (path), "%s/%s", directory, file);
185 f = fopen (path, "rb");
186 if (f == NULL) {
187 HAL_ERROR (("Cannot open '%s'", path));
188 goto out;
191 if (fgets (buf, sizeof (buf), f) == NULL) {
192 HAL_ERROR (("Cannot read from '%s'", path));
193 goto out;
196 /* TODO: handle error condition */
197 *result = strtol (buf, NULL, base);
198 ret = TRUE;
200 out:
201 if (f != NULL)
202 fclose (f);
204 return ret;
207 gboolean
208 hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
210 gint value;
211 gboolean ret;
213 ret = FALSE;
215 if (hal_util_get_int_from_file (directory, file, &value, base))
216 ret = hal_device_property_set_int (d, key, value);
218 return ret;
222 gboolean
223 hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base)
225 FILE *f;
226 char buf[64];
227 gchar path[HAL_PATH_MAX];
228 gboolean ret;
230 f = NULL;
231 ret = FALSE;
233 g_snprintf (path, sizeof (path), "%s/%s", directory, file);
235 f = fopen (path, "rb");
236 if (f == NULL) {
237 HAL_ERROR (("Cannot open '%s'", path));
238 goto out;
241 if (fgets (buf, sizeof (buf), f) == NULL) {
242 HAL_ERROR (("Cannot read from '%s'", path));
243 goto out;
246 /* TODO: handle error condition */
247 *result = strtoll (buf, NULL, base);
249 ret = TRUE;
251 out:
252 if (f != NULL)
253 fclose (f);
255 return ret;
258 gboolean
259 hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
261 guint64 value;
262 gboolean ret;
264 ret = FALSE;
266 if (hal_util_get_uint64_from_file (directory, file, &value, base))
267 ret = hal_device_property_set_uint64 (d, key, value);
269 return ret;
272 gboolean
273 hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result)
275 FILE *f;
276 char buf[64];
277 gchar path[HAL_PATH_MAX];
278 gboolean ret;
279 gint digit;
280 gint left, right;
281 gboolean passed_white_space;
282 gint num_prec;
283 gsize len;
284 gchar c;
285 guint i;
287 f = NULL;
288 ret = FALSE;
290 g_snprintf (path, sizeof (path), "%s/%s", directory, file);
292 f = fopen (path, "rb");
293 if (f == NULL) {
294 HAL_ERROR (("Cannot open '%s'", path));
295 goto out;
298 if (fgets (buf, sizeof (buf), f) == NULL) {
299 HAL_ERROR (("Cannot read from '%s'", path));
300 goto out;
303 left = 0;
304 len = strlen (buf);
305 passed_white_space = FALSE;
306 for (i = 0; i < len && buf[i] != '.'; i++) {
307 if (g_ascii_isspace (buf[i])) {
308 if (passed_white_space)
309 break;
310 else
311 continue;
313 passed_white_space = TRUE;
314 left *= 16;
315 c = buf[i];
316 digit = (int) (c - '0');
317 left += digit;
319 i++;
320 right = 0;
321 num_prec = 0;
322 for (; i < len; i++) {
323 if (g_ascii_isspace (buf[i]))
324 break;
325 if (num_prec == 2) /* Only care about two digits
326 * of precision */
327 break;
328 right *= 16;
329 c = buf[i];
330 digit = (int) (c - '0');
331 right += digit;
332 num_prec++;
335 for (; num_prec < 2; num_prec++)
336 right *= 16;
338 *result = left * 256 + (right & 255);
339 ret = TRUE;
341 out:
342 if (f != NULL)
343 fclose (f);
345 return ret;
348 gboolean
349 hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
351 gint value;
352 gboolean ret;
354 ret = FALSE;
356 if (hal_util_get_bcd2_from_file (directory, file, &value))
357 ret = hal_device_property_set_int (d, key, value);
359 return ret;
362 gchar *
363 hal_util_get_string_from_file (const gchar *directory, const gchar *file)
365 FILE *f;
366 static gchar buf[256];
367 gchar path[HAL_PATH_MAX];
368 gchar *result;
369 gsize len;
370 gint i;
372 f = NULL;
373 result = NULL;
375 g_snprintf (path, sizeof (path), "%s/%s", directory, file);
377 f = fopen (path, "rb");
378 if (f == NULL) {
379 HAL_ERROR (("Cannot open '%s'", path));
380 goto out;
383 buf[0] = '\0';
384 if (fgets (buf, sizeof (buf), f) == NULL) {
385 HAL_ERROR (("Cannot read from '%s'", path));
386 goto out;
389 len = strlen (buf);
390 if (len>0)
391 buf[len-1] = '\0';
393 /* Clear remaining whitespace */
394 for (i = len - 2; i >= 0; --i) {
395 if (!g_ascii_isspace (buf[i]))
396 break;
397 buf[i] = '\0';
400 result = buf;
402 out:
403 if (f != NULL)
404 fclose (f);
406 return result;
409 gboolean
410 hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
412 gchar *buf;
413 gboolean ret;
415 ret = FALSE;
417 if ((buf = hal_util_get_string_from_file (directory, file)) != NULL)
418 ret = hal_device_property_set_string (d, key, buf);
420 return ret;
423 void
424 hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...)
426 guint i;
427 va_list args;
428 gchar buf[256];
430 va_start (args, format);
431 g_vsnprintf (buf, sizeof (buf), format, args);
432 va_end (args);
434 g_strcanon (buf,
435 "/_"
436 "abcdefghijklmnopqrstuvwxyz"
437 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
438 "1234567890", '_');
440 g_strlcpy (dst, buf, dstsize);
441 if (hal_device_store_find (store, dst) == NULL)
442 goto out;
444 for (i = 0; ; i++) {
445 g_snprintf (dst, dstsize, "%s_%d", buf, i);
446 if (hal_device_store_find (store, dst) == NULL)
447 goto out;
450 out:
455 gboolean
456 hal_util_path_ascend (gchar *path)
458 gchar *p;
460 if (path == NULL)
461 return FALSE;
463 p = strrchr (path, '/');
464 if (p == NULL)
465 return FALSE;
467 *p = '\0';
468 return TRUE;
471 static gboolean _grep_can_reuse = FALSE;
473 void
474 hal_util_grep_discard_existing_data (void)
476 _grep_can_reuse = FALSE;
479 /** Given a directory and filename, open the file and search for the
480 * first line that starts with the given linestart string. Returns
481 * the rest of the line as a string if found.
483 * @param directory Directory, e.g. "/proc/acpi/battery/BAT0"
484 * @param file File, e.g. "info"
485 * @param linestart Start of line, e.g. "serial number"
486 * @param reuse Whether we should reuse the file contents
487 * if the file is the same; can be cleared
488 * with hal_util_grep_discard_existing_data()
489 * @return NULL if not found, otherwise the remainder
490 * of the line, e.g. ": 21805" if
491 * the file /proc/acpi/battery/BAT0 contains
492 * this line "serial number: 21805"
493 * The string is only valid until the next
494 * invocation of this function.
496 gchar *
497 hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse)
499 static gchar buf[2048];
500 static unsigned int bufsize;
501 static gchar filename[HAL_PATH_MAX];
502 static gchar oldfilename[HAL_PATH_MAX];
503 gchar *result;
504 gsize linestart_len;
505 gchar *p;
507 result = NULL;
509 /* TODO: use reuse and _grep_can_reuse parameters to avoid loading
510 * the file again and again
513 if (file != NULL && strlen (file) > 0)
514 snprintf (filename, sizeof (filename), "%s/%s", directory, file);
515 else
516 strncpy (filename, directory, sizeof (filename));
518 if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) {
519 /* just reuse old file; e.g. bufsize, buf */
520 /*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/
521 } else {
522 FILE *f;
524 f = fopen (filename, "r");
525 if (f == NULL)
526 goto out;
527 bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f);
528 buf[bufsize] = '\0';
529 fclose (f);
531 /*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/
534 /* book keeping */
535 _grep_can_reuse = TRUE;
536 strncpy (oldfilename, filename, sizeof(oldfilename));
538 linestart_len = strlen (linestart);
540 /* analyze buf */
541 p = buf;
542 do {
543 unsigned int linelen;
544 static char line[256];
546 for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++)
549 if (linelen < sizeof (line)) {
551 strncpy (line, p, linelen);
552 line[linelen] = '\0';
554 if (strncmp (line, linestart, linestart_len) == 0) {
555 result = line + linestart_len;
556 goto out;
560 p += linelen + 1;
562 } while (p < buf + bufsize);
564 out:
565 return result;
568 gchar *
569 hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file,
570 const gchar *linestart, guint elem, gboolean reuse)
572 gchar *line;
573 gchar *res;
574 static gchar buf[256];
575 gchar **tokens;
576 guint i, j;
578 res = NULL;
579 tokens = NULL;
581 if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
582 goto out;
584 tokens = g_strsplit_set (line, " \t:", 0);
585 for (i = 0, j = 0; tokens[i] != NULL; i++) {
586 if (strlen (tokens[i]) == 0)
587 continue;
588 if (j == elem) {
589 strncpy (buf, tokens[i], sizeof (buf));
590 res = buf;
591 goto out;
593 j++;
596 out:
597 if (tokens != NULL)
598 g_strfreev (tokens);
600 return res;
603 gint
604 hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file,
605 const gchar *linestart, guint elem, guint base, gboolean reuse)
607 gchar *endptr;
608 gchar *strvalue;
609 int value;
611 value = G_MAXINT;
613 strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
614 if (strvalue == NULL)
615 goto out;
617 value = strtol (strvalue, &endptr, base);
618 if (endptr == strvalue) {
619 value = G_MAXINT;
620 goto out;
623 out:
624 return value;
627 /** Get a string value from a formatted text file and assign it to
628 * a property on a device object.
630 * Example: Given that the file /proc/acpi/battery/BAT0/info contains
631 * the line
633 * "design voltage: 10800 mV"
635 * then hal_util_set_string_elem_from_file (d, "battery.foo",
636 * "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign
637 * the string "mV" to the property "battery.foo" on d.
639 * @param d Device object
640 * @param key Property name
641 * @param directory Directory, e.g. "/proc/acpi/battery/BAT0"
642 * @param file File, e.g. "info"
643 * @param linestart Start of line, e.g. "design voltage"
644 * @param elem Element number after linestart to extract
645 * excluding whitespace and ':' characters.
646 * @return TRUE, if, and only if, the value could be
647 * extracted and the property was set
649 gboolean
650 hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key,
651 const gchar *directory, const gchar *file,
652 const gchar *linestart, guint elem, gboolean reuse)
654 gboolean res;
655 gchar *value;
657 res = FALSE;
659 if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL)
660 goto out;
662 res = hal_device_property_set_string (d, key, value);
663 out:
664 return res;
667 /** Get an integer value from a formatted text file and assign it to
668 * a property on a device object.
670 * Example: Given that the file /proc/acpi/battery/BAT0/info contains
671 * the line
673 * "design voltage: 10800 mV"
675 * then hal_util_set_int_elem_from_file (d, "battery.foo",
676 * "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign
677 * the integer 10800 to the property "battery.foo" on d.
679 * @param d Device object
680 * @param key Property name
681 * @param directory Directory, e.g. "/proc/acpi/battery/BAT0"
682 * @param file File, e.g. "info"
683 * @param linestart Start of line, e.g. "design voltage"
684 * @param elem Element number after linestart to extract
685 * excluding whitespace and ':' characters.
686 * @return TRUE, if, and only if, the value could be
687 * extracted and the property was set
689 gboolean
690 hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key,
691 const gchar *directory, const gchar *file,
692 const gchar *linestart, guint elem, guint base, gboolean reuse)
694 gchar *endptr;
695 gboolean res;
696 gchar *strvalue;
697 int value;
699 res = FALSE;
701 strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse);
702 if (strvalue == NULL)
703 goto out;
705 value = strtol (strvalue, &endptr, base);
706 if (endptr == strvalue)
707 goto out;
709 res = hal_device_property_set_int (d, key, value);
711 out:
712 return res;
716 /** Get a value from a formatted text file, test it against a given
717 * value, and set a boolean property on a device object with the
718 * test result.
720 * Example: Given that the file /proc/acpi/battery/BAT0/info contains
721 * the line
723 * "present: yes"
725 * then hal_util_set_bool_elem_from_file (d, "battery.baz",
726 * "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign
727 * the boolean TRUE to the property "battery.baz" on d.
729 * If, instead, the line was
731 * "present: no"
733 * the value assigned will be FALSE.
735 * @param d Device object
736 * @param key Property name
737 * @param directory Directory, e.g. "/proc/acpi/battery/BAT0"
738 * @param file File, e.g. "info"
739 * @param linestart Start of line, e.g. "design voltage"
740 * @param elem Element number after linestart to extract
741 * excluding whitespace and ':' characters.
742 * @param expected Value to test against
743 * @return TRUE, if, and only if, the value could be
744 * extracted and the property was set
746 gboolean
747 hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key,
748 const gchar *directory, const gchar *file,
749 const gchar *linestart, guint elem, const gchar *expected, gboolean reuse)
751 gchar *line;
752 gboolean res;
753 gchar **tokens;
754 guint i, j;
756 res = FALSE;
757 tokens = NULL;
759 if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0))
760 goto out;
762 tokens = g_strsplit_set (line, " \t:", 0);
764 for (i = 0, j = 0; tokens[i] != NULL; i++) {
765 if (strlen (tokens[i]) == 0)
766 continue;
767 if (j == elem) {
768 hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0);
769 res = TRUE;
770 goto out;
772 j++;
776 out:
777 if (tokens != NULL)
778 g_strfreev (tokens);
780 return res;
783 gchar **
784 hal_util_dup_strv_from_g_slist (GSList *strlist)
786 guint j;
787 guint len;
788 gchar **strv;
789 GSList *i;
791 len = g_slist_length (strlist);
792 strv = g_new (char *, len + 1);
794 for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) {
795 strv[j] = g_strdup ((const gchar *) i->data);
797 strv[j] = NULL;
799 return strv;
802 /* -------------------------------------------------------------------------------------------------------------- */
804 typedef struct {
805 HalDevice *d;
806 gchar **programs;
807 gchar **extra_env;
808 guint next_program;
810 HalCalloutsDone callback;
811 gpointer userdata1;
812 gpointer userdata2;
814 } Callout;
816 static void callout_do_next (Callout *c);
818 static void
819 callout_terminated (HalDevice *d, guint32 exit_type,
820 gint return_code, gchar **error,
821 gpointer data1, gpointer data2)
823 Callout *c;
825 c = (Callout *) data1;
826 callout_do_next (c);
829 static void
830 callout_do_next (Callout *c)
833 /* Check if we're done */
834 if (c->programs[c->next_program] == NULL) {
835 HalDevice *d;
836 gpointer userdata1;
837 gpointer userdata2;
838 HalCalloutsDone callback;
840 d = c->d;
841 userdata1 = c->userdata1;
842 userdata2 = c->userdata2;
843 callback = c->callback;
845 g_strfreev (c->programs);
846 g_strfreev (c->extra_env);
847 g_free (c);
849 callback (d, userdata1, userdata2);
851 } else {
852 hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
853 HAL_HELPER_TIMEOUT, callout_terminated,
854 (gpointer)c, NULL);
855 c->next_program++;
859 static void
860 hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2,
861 GSList *programs, gchar **extra_env)
863 Callout *c;
865 c = g_new0 (Callout, 1);
866 c->d = d;
867 c->callback = callback;
868 c->userdata1 = userdata1;
869 c->userdata2 = userdata2;
870 c->programs = hal_util_dup_strv_from_g_slist (programs);
871 c->extra_env = g_strdupv (extra_env);
872 c->next_program = 0;
874 callout_do_next (c);
877 void
878 hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
880 GSList *programs;
881 gchar *extra_env[2] = {"HALD_ACTION=add", NULL};
883 if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) {
884 callback (d, userdata1, userdata2);
885 goto out;
888 HAL_INFO (("Add callouts for udi=%s", d->udi));
890 hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
891 out:
895 void
896 hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
898 GSList *programs;
899 gchar *extra_env[2] = {"HALD_ACTION=remove", NULL};
901 if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) {
902 callback (d, userdata1, userdata2);
903 goto out;
906 HAL_INFO (("Remove callouts for udi=%s", d->udi));
908 hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
909 out:
913 void
914 hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2)
916 GSList *programs;
917 gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL};
919 if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) {
920 callback (d, userdata1, userdata2);
921 goto out;
924 HAL_INFO (("Preprobe callouts for udi=%s", d->udi));
926 hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env);
927 out:
931 gchar *
932 hal_util_strdup_valid_utf8 (const char *str)
934 char *endchar;
935 char *newstr;
936 unsigned int count = 0;
938 if (str == NULL)
939 return NULL;
941 newstr = g_strdup (str);
943 while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
944 *endchar = '?';
945 count++;
948 if (strlen(newstr) == count)
949 return NULL;
950 else
951 return newstr;
954 void
955 hal_util_hexdump (const void *mem, unsigned int size)
957 unsigned int i;
958 unsigned int j;
959 unsigned int n;
960 const char *buf = (const char *) mem;
962 n = 0;
963 printf ("Dumping %d=0x%x bytes\n", size, size);
964 while (n < size) {
966 printf ("0x%04x: ", n);
968 j = n;
969 for (i = 0; i < 16; i++) {
970 if (j >= size)
971 break;
972 printf ("%02x ", buf[j]);
973 j++;
976 for ( ; i < 16; i++) {
977 printf (" ");
980 printf (" ");
982 j = n;
983 for (i = 0; i < 16; i++) {
984 if (j >= size)
985 break;
986 printf ("%c", isprint(buf[j]) ? buf[j] : '.');
987 j++;
990 printf ("\n");
992 n += 16;
996 gboolean
997 hal_util_is_mounted_by_hald (const char *mount_point)
999 int i;
1000 FILE *hal_mtab;
1001 int hal_mtab_len;
1002 int num_read;
1003 char *hal_mtab_buf;
1004 char **lines;
1005 gboolean found;
1007 hal_mtab = NULL;
1008 hal_mtab_buf = NULL;
1009 found = FALSE;
1011 /*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/
1013 hal_mtab = fopen ("/media/.hal-mtab", "r");
1014 if (hal_mtab == NULL) {
1015 HAL_ERROR (("Cannot open /media/.hal-mtab"));
1016 goto out;
1018 if (fseek (hal_mtab, 0L, SEEK_END) != 0) {
1019 HAL_ERROR (("Cannot seek to end of /media/.hal-mtab"));
1020 goto out;
1022 hal_mtab_len = ftell (hal_mtab);
1023 if (hal_mtab_len < 0) {
1024 HAL_ERROR (("Cannot determine size of /media/.hal-mtab"));
1025 goto out;
1027 rewind (hal_mtab);
1029 hal_mtab_buf = g_new0 (char, hal_mtab_len + 1);
1030 num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab);
1031 if (num_read != hal_mtab_len) {
1032 HAL_ERROR (("Cannot read from /media/.hal-mtab"));
1033 goto out;
1035 fclose (hal_mtab);
1036 hal_mtab = NULL;
1038 /*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/
1040 lines = g_strsplit (hal_mtab_buf, "\n", 0);
1041 g_free (hal_mtab_buf);
1042 hal_mtab_buf = NULL;
1044 /* find the entry we're going to unmount */
1045 for (i = 0; lines[i] != NULL && !found; i++) {
1046 char **line_elements;
1048 /*HAL_DEBUG ((" line = '%s'", lines[i]));*/
1050 if ((lines[i])[0] == '#')
1051 continue;
1053 line_elements = g_strsplit (lines[i], "\t", 6);
1054 if (g_strv_length (line_elements) == 6) {
1056 HAL_DEBUG ((" devfile = '%s'", line_elements[0]));
1057 HAL_DEBUG ((" uid = '%s'", line_elements[1]));
1058 HAL_DEBUG ((" session id = '%s'", line_elements[2]));
1059 HAL_DEBUG ((" fs = '%s'", line_elements[3]));
1060 HAL_DEBUG ((" options = '%s'", line_elements[4]));
1061 HAL_DEBUG ((" mount_point = '%s'", line_elements[5]));
1062 HAL_DEBUG ((" (comparing against '%s')", mount_point));
1065 if (strcmp (line_elements[5], mount_point) == 0) {
1066 found = TRUE;
1067 /*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/
1072 g_strfreev (line_elements);
1075 g_strfreev (lines);
1077 out:
1078 if (hal_mtab != NULL)
1079 fclose (hal_mtab);
1080 if (hal_mtab_buf != NULL)
1081 g_free (hal_mtab_buf);
1083 return found;
1086 void
1087 hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed,
1088 const char *service, int uid)
1090 GSList *children;
1091 GSList *i;
1092 HalDevice *d;
1094 if (claimed) {
1095 hal_device_property_set_bool (root, "info.claimed", claimed);
1096 hal_device_property_set_string (root, "info.claimed.service", service);
1097 hal_device_property_set_int (root, "info.claimed.uid", uid);
1098 } else {
1099 hal_device_property_remove (root, "info.claimed");
1100 hal_device_property_remove (root, "info.claimed.service");
1101 hal_device_property_remove (root, "info.claimed.uid");
1105 children = hal_device_store_match_multiple_key_value_string (store,
1106 "info.parent", root->udi);
1108 for (i = children; i != NULL; i = g_slist_next (i)) {
1109 d = HAL_DEVICE (i->data);
1110 hal_util_branch_claim (store, d, claimed, service, uid);
1113 g_slist_free (children);
1116 /** Given an interface name, check if it is valid.
1117 * @param name A given interface name
1118 * @return TRUE if name is valid, otherwise FALSE
1120 gboolean
1121 is_valid_interface_name(const char *name) {
1123 const char *end;
1124 const char *last_dot;
1126 last_dot = NULL;
1128 if (strlen(name) == 0)
1129 return FALSE;
1131 end = name + strlen(name);
1133 if (*name == '.') /* disallow starting with a . */
1134 return FALSE;
1135 else if (!VALID_INITIAL_NAME_CHARACTER (*name))
1136 return FALSE;
1137 else
1138 name++;
1140 while (name != end) {
1141 if (*name == '.') {
1142 if ((name + 1) == end)
1143 return FALSE;
1144 else if (!VALID_INITIAL_NAME_CHARACTER (*(name + 1)))
1145 return FALSE;
1146 last_dot = name;
1147 name++; /* we just validated the next char, so skip two */
1148 } else if (!VALID_NAME_CHARACTER (*name))
1149 return FALSE;
1150 name++;
1152 if (last_dot == NULL)
1153 return FALSE;
1155 return TRUE;