118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * CVSID: $Id$ 318c2aff7Sartem * 418c2aff7Sartem * util.c - Various utilities 518c2aff7Sartem * 618c2aff7Sartem * Copyright (C) 2004 David Zeuthen, <david@fubar.dk> 718c2aff7Sartem * 818c2aff7Sartem * Licensed under the Academic Free License version 2.1 918c2aff7Sartem * 1018c2aff7Sartem * This program is free software; you can redistribute it and/or modify 1118c2aff7Sartem * it under the terms of the GNU General Public License as published by 1218c2aff7Sartem * the Free Software Foundation; either version 2 of the License, or 1318c2aff7Sartem * (at your option) any later version. 1418c2aff7Sartem * 1518c2aff7Sartem * This program is distributed in the hope that it will be useful, 1618c2aff7Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of 1718c2aff7Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1818c2aff7Sartem * GNU General Public License for more details. 1918c2aff7Sartem * 2018c2aff7Sartem * You should have received a copy of the GNU General Public License 2118c2aff7Sartem * along with this program; if not, write to the Free Software 2218c2aff7Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2318c2aff7Sartem * 2418c2aff7Sartem **************************************************************************/ 2518c2aff7Sartem 2618c2aff7Sartem #ifdef HAVE_CONFIG_H 2718c2aff7Sartem # include <config.h> 2818c2aff7Sartem #endif 2918c2aff7Sartem 3018c2aff7Sartem #include <stdio.h> 3118c2aff7Sartem #include <stdarg.h> 3218c2aff7Sartem #include <string.h> 3318c2aff7Sartem #include <errno.h> 3418c2aff7Sartem #include <time.h> 3518c2aff7Sartem #include <ctype.h> 3618c2aff7Sartem #include <stdint.h> 3718c2aff7Sartem #include <sys/stat.h> 3818c2aff7Sartem #include <unistd.h> 3918c2aff7Sartem #include <fcntl.h> 4018c2aff7Sartem #include <signal.h> 4118c2aff7Sartem #include <sys/wait.h> 4218c2aff7Sartem #include <sys/file.h> 4318c2aff7Sartem 4418c2aff7Sartem #include <glib.h> 4518c2aff7Sartem #include <dbus/dbus.h> 4618c2aff7Sartem #include <dbus/dbus-glib.h> 4718c2aff7Sartem 4818c2aff7Sartem #include "osspec.h" 4918c2aff7Sartem #include "logger.h" 5018c2aff7Sartem #include "hald.h" 5118c2aff7Sartem #include "hald_runner.h" 5218c2aff7Sartem #include "hald_dbus.h" 5318c2aff7Sartem #include "device_info.h" 5418c2aff7Sartem 5518c2aff7Sartem #include "util.h" 5618c2aff7Sartem 57*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Determine whether the given character is valid as the first character 58*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China * in a name. 59*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China */ 60*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China #define VALID_INITIAL_NAME_CHARACTER(c) \ 61*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China (((c) >= 'A' && (c) <= 'Z') || \ 62*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China ((c) >= 'a' && (c) <= 'z') || \ 63*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China ((c) == '_')) 64*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 65*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Determine whether the given character is valid as a second or later 66*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China * character in a name. 67*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China */ 68*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China #define VALID_NAME_CHARACTER(c) \ 69*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China (((c) >= '0' && (c) <= '9') || \ 70*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China ((c) >= 'A' && (c) <= 'Z') || \ 71*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China ((c) >= 'a' && (c) <= 'z') || \ 72*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China ((c) == '_')) 73*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 7418c2aff7Sartem gboolean 7518c2aff7Sartem hal_util_remove_trailing_slash (gchar *path) 7618c2aff7Sartem { 7718c2aff7Sartem gchar *c = NULL; 7818c2aff7Sartem 7918c2aff7Sartem if (path == NULL) { 8018c2aff7Sartem return FALSE; 8118c2aff7Sartem } 8218c2aff7Sartem 8318c2aff7Sartem c = strrchr (path, '/'); 8418c2aff7Sartem if (c == NULL) { 8518c2aff7Sartem HAL_WARNING (("Invalid path %s", path)); 8618c2aff7Sartem return 1; 8718c2aff7Sartem } 8818c2aff7Sartem if (*(c+1) == '\0') 8918c2aff7Sartem *c = '\0'; 9018c2aff7Sartem 9118c2aff7Sartem return TRUE; 9218c2aff7Sartem } 9318c2aff7Sartem 9418c2aff7Sartem /** Given a path, /foo/bar/bat/foobar, return the last element, e.g. 9518c2aff7Sartem * foobar. 9618c2aff7Sartem * 9718c2aff7Sartem * @param path Path 9818c2aff7Sartem * @return Pointer into given string 9918c2aff7Sartem */ 10018c2aff7Sartem const gchar * 10118c2aff7Sartem hal_util_get_last_element (const gchar *s) 10218c2aff7Sartem { 10318c2aff7Sartem int len; 10418c2aff7Sartem const gchar *p; 10518c2aff7Sartem 10618c2aff7Sartem len = strlen (s); 10718c2aff7Sartem for (p = s + len - 1; p > s; --p) { 10818c2aff7Sartem if ((*p) == '/') 10918c2aff7Sartem return p + 1; 11018c2aff7Sartem } 11118c2aff7Sartem 11218c2aff7Sartem return s; 11318c2aff7Sartem } 11418c2aff7Sartem 11518c2aff7Sartem /** Given a path, this functions finds the path representing the 11618c2aff7Sartem * parent directory by truncation. 11718c2aff7Sartem * 11818c2aff7Sartem * @param path Path 11918c2aff7Sartem * @return Path for parent or NULL. Must be freed by caller 12018c2aff7Sartem */ 12118c2aff7Sartem gchar * 12218c2aff7Sartem hal_util_get_parent_path (const gchar *path) 12318c2aff7Sartem { 12418c2aff7Sartem guint i; 12518c2aff7Sartem guint len; 12618c2aff7Sartem gchar *parent_path; 12718c2aff7Sartem 12818c2aff7Sartem /* Find parent device by truncating our own path */ 12918c2aff7Sartem parent_path = g_strndup (path, HAL_PATH_MAX); 13018c2aff7Sartem len = strlen (parent_path); 13118c2aff7Sartem for (i = len - 1; parent_path[i] != '/'; --i) { 13218c2aff7Sartem parent_path[i] = '\0'; 13318c2aff7Sartem } 13418c2aff7Sartem parent_path[i] = '\0'; 13518c2aff7Sartem 13618c2aff7Sartem return parent_path; 13718c2aff7Sartem } 13818c2aff7Sartem 13918c2aff7Sartem gchar * 14018c2aff7Sartem hal_util_get_normalized_path (const gchar *path1, const gchar *path2) 14118c2aff7Sartem { 14218c2aff7Sartem int len1; 14318c2aff7Sartem int len2; 14418c2aff7Sartem const gchar *p1; 14518c2aff7Sartem const gchar *p2; 14618c2aff7Sartem gchar buf[HAL_PATH_MAX]; 14718c2aff7Sartem 14818c2aff7Sartem len1 = strlen (path1); 14918c2aff7Sartem len2 = strlen (path2); 15018c2aff7Sartem 15118c2aff7Sartem p1 = path1 + len1; 15218c2aff7Sartem 15318c2aff7Sartem p2 = path2; 15418c2aff7Sartem while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) { 15518c2aff7Sartem p2 += 3; 15618c2aff7Sartem 15718c2aff7Sartem while (p1 >= path1 && *(--p1)!='/') 15818c2aff7Sartem ; 15918c2aff7Sartem } 16018c2aff7Sartem 16118c2aff7Sartem if ((p1-path1) < 0) { 16218c2aff7Sartem HAL_ERROR (("Could not normalize '%s' and '%s', return 'NULL'", path1, path2)); 16318c2aff7Sartem return NULL; 16418c2aff7Sartem } 16518c2aff7Sartem 16618c2aff7Sartem strncpy (buf, path1, (p1-path1)); 16718c2aff7Sartem buf[p1-path1] = '\0'; 16818c2aff7Sartem 16918c2aff7Sartem return g_strdup_printf ("%s/%s", buf, p2); 17018c2aff7Sartem } 17118c2aff7Sartem 17218c2aff7Sartem gboolean 17318c2aff7Sartem hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base) 17418c2aff7Sartem { 17518c2aff7Sartem FILE *f; 17618c2aff7Sartem char buf[64]; 17718c2aff7Sartem gchar path[HAL_PATH_MAX]; 17818c2aff7Sartem gboolean ret; 17918c2aff7Sartem 18018c2aff7Sartem f = NULL; 18118c2aff7Sartem ret = FALSE; 18218c2aff7Sartem 18318c2aff7Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 18418c2aff7Sartem 18518c2aff7Sartem f = fopen (path, "rb"); 18618c2aff7Sartem if (f == NULL) { 18718c2aff7Sartem HAL_ERROR (("Cannot open '%s'", path)); 18818c2aff7Sartem goto out; 18918c2aff7Sartem } 19018c2aff7Sartem 19118c2aff7Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 19218c2aff7Sartem HAL_ERROR (("Cannot read from '%s'", path)); 19318c2aff7Sartem goto out; 19418c2aff7Sartem } 19518c2aff7Sartem 19618c2aff7Sartem /* TODO: handle error condition */ 19718c2aff7Sartem *result = strtol (buf, NULL, base); 19818c2aff7Sartem ret = TRUE; 19918c2aff7Sartem 20018c2aff7Sartem out: 20118c2aff7Sartem if (f != NULL) 20218c2aff7Sartem fclose (f); 20318c2aff7Sartem 20418c2aff7Sartem return ret; 20518c2aff7Sartem } 20618c2aff7Sartem 20718c2aff7Sartem gboolean 20818c2aff7Sartem hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base) 20918c2aff7Sartem { 21018c2aff7Sartem gint value; 21118c2aff7Sartem gboolean ret; 21218c2aff7Sartem 21318c2aff7Sartem ret = FALSE; 21418c2aff7Sartem 21518c2aff7Sartem if (hal_util_get_int_from_file (directory, file, &value, base)) 21618c2aff7Sartem ret = hal_device_property_set_int (d, key, value); 21718c2aff7Sartem 21818c2aff7Sartem return ret; 21918c2aff7Sartem } 22018c2aff7Sartem 22118c2aff7Sartem 22218c2aff7Sartem gboolean 22318c2aff7Sartem hal_util_get_uint64_from_file (const gchar *directory, const gchar *file, guint64 *result, gint base) 22418c2aff7Sartem { 22518c2aff7Sartem FILE *f; 22618c2aff7Sartem char buf[64]; 22718c2aff7Sartem gchar path[HAL_PATH_MAX]; 22818c2aff7Sartem gboolean ret; 22918c2aff7Sartem 23018c2aff7Sartem f = NULL; 23118c2aff7Sartem ret = FALSE; 23218c2aff7Sartem 23318c2aff7Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 23418c2aff7Sartem 23518c2aff7Sartem f = fopen (path, "rb"); 23618c2aff7Sartem if (f == NULL) { 23718c2aff7Sartem HAL_ERROR (("Cannot open '%s'", path)); 23818c2aff7Sartem goto out; 23918c2aff7Sartem } 24018c2aff7Sartem 24118c2aff7Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 24218c2aff7Sartem HAL_ERROR (("Cannot read from '%s'", path)); 24318c2aff7Sartem goto out; 24418c2aff7Sartem } 24518c2aff7Sartem 24618c2aff7Sartem /* TODO: handle error condition */ 24718c2aff7Sartem *result = strtoll (buf, NULL, base); 24818c2aff7Sartem 24918c2aff7Sartem ret = TRUE; 25018c2aff7Sartem 25118c2aff7Sartem out: 25218c2aff7Sartem if (f != NULL) 25318c2aff7Sartem fclose (f); 25418c2aff7Sartem 25518c2aff7Sartem return ret; 25618c2aff7Sartem } 25718c2aff7Sartem 25818c2aff7Sartem gboolean 25918c2aff7Sartem hal_util_set_uint64_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base) 26018c2aff7Sartem { 26118c2aff7Sartem guint64 value; 26218c2aff7Sartem gboolean ret; 26318c2aff7Sartem 26418c2aff7Sartem ret = FALSE; 26518c2aff7Sartem 26618c2aff7Sartem if (hal_util_get_uint64_from_file (directory, file, &value, base)) 26718c2aff7Sartem ret = hal_device_property_set_uint64 (d, key, value); 26818c2aff7Sartem 26918c2aff7Sartem return ret; 27018c2aff7Sartem } 27118c2aff7Sartem 27218c2aff7Sartem gboolean 27318c2aff7Sartem hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result) 27418c2aff7Sartem { 27518c2aff7Sartem FILE *f; 27618c2aff7Sartem char buf[64]; 27718c2aff7Sartem gchar path[HAL_PATH_MAX]; 27818c2aff7Sartem gboolean ret; 27918c2aff7Sartem gint digit; 28018c2aff7Sartem gint left, right; 28118c2aff7Sartem gboolean passed_white_space; 28218c2aff7Sartem gint num_prec; 28318c2aff7Sartem gsize len; 28418c2aff7Sartem gchar c; 28518c2aff7Sartem guint i; 28618c2aff7Sartem 28718c2aff7Sartem f = NULL; 28818c2aff7Sartem ret = FALSE; 28918c2aff7Sartem 29018c2aff7Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 29118c2aff7Sartem 29218c2aff7Sartem f = fopen (path, "rb"); 29318c2aff7Sartem if (f == NULL) { 29418c2aff7Sartem HAL_ERROR (("Cannot open '%s'", path)); 29518c2aff7Sartem goto out; 29618c2aff7Sartem } 29718c2aff7Sartem 29818c2aff7Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 29918c2aff7Sartem HAL_ERROR (("Cannot read from '%s'", path)); 30018c2aff7Sartem goto out; 30118c2aff7Sartem } 30218c2aff7Sartem 30318c2aff7Sartem left = 0; 30418c2aff7Sartem len = strlen (buf); 30518c2aff7Sartem passed_white_space = FALSE; 30618c2aff7Sartem for (i = 0; i < len && buf[i] != '.'; i++) { 30718c2aff7Sartem if (g_ascii_isspace (buf[i])) { 30818c2aff7Sartem if (passed_white_space) 30918c2aff7Sartem break; 31018c2aff7Sartem else 31118c2aff7Sartem continue; 31218c2aff7Sartem } 31318c2aff7Sartem passed_white_space = TRUE; 31418c2aff7Sartem left *= 16; 31518c2aff7Sartem c = buf[i]; 31618c2aff7Sartem digit = (int) (c - '0'); 31718c2aff7Sartem left += digit; 31818c2aff7Sartem } 31918c2aff7Sartem i++; 32018c2aff7Sartem right = 0; 32118c2aff7Sartem num_prec = 0; 32218c2aff7Sartem for (; i < len; i++) { 32318c2aff7Sartem if (g_ascii_isspace (buf[i])) 32418c2aff7Sartem break; 32518c2aff7Sartem if (num_prec == 2) /* Only care about two digits 32618c2aff7Sartem * of precision */ 32718c2aff7Sartem break; 32818c2aff7Sartem right *= 16; 32918c2aff7Sartem c = buf[i]; 33018c2aff7Sartem digit = (int) (c - '0'); 33118c2aff7Sartem right += digit; 33218c2aff7Sartem num_prec++; 33318c2aff7Sartem } 33418c2aff7Sartem 33518c2aff7Sartem for (; num_prec < 2; num_prec++) 33618c2aff7Sartem right *= 16; 33718c2aff7Sartem 33818c2aff7Sartem *result = left * 256 + (right & 255); 33918c2aff7Sartem ret = TRUE; 34018c2aff7Sartem 34118c2aff7Sartem out: 34218c2aff7Sartem if (f != NULL) 34318c2aff7Sartem fclose (f); 34418c2aff7Sartem 34518c2aff7Sartem return ret; 34618c2aff7Sartem } 34718c2aff7Sartem 34818c2aff7Sartem gboolean 34918c2aff7Sartem hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file) 35018c2aff7Sartem { 35118c2aff7Sartem gint value; 35218c2aff7Sartem gboolean ret; 35318c2aff7Sartem 35418c2aff7Sartem ret = FALSE; 35518c2aff7Sartem 35618c2aff7Sartem if (hal_util_get_bcd2_from_file (directory, file, &value)) 35718c2aff7Sartem ret = hal_device_property_set_int (d, key, value); 35818c2aff7Sartem 35918c2aff7Sartem return ret; 36018c2aff7Sartem } 36118c2aff7Sartem 36218c2aff7Sartem gchar * 36318c2aff7Sartem hal_util_get_string_from_file (const gchar *directory, const gchar *file) 36418c2aff7Sartem { 36518c2aff7Sartem FILE *f; 36618c2aff7Sartem static gchar buf[256]; 36718c2aff7Sartem gchar path[HAL_PATH_MAX]; 36818c2aff7Sartem gchar *result; 36918c2aff7Sartem gsize len; 37018c2aff7Sartem gint i; 37118c2aff7Sartem 37218c2aff7Sartem f = NULL; 37318c2aff7Sartem result = NULL; 37418c2aff7Sartem 37518c2aff7Sartem g_snprintf (path, sizeof (path), "%s/%s", directory, file); 37618c2aff7Sartem 37718c2aff7Sartem f = fopen (path, "rb"); 37818c2aff7Sartem if (f == NULL) { 37918c2aff7Sartem HAL_ERROR (("Cannot open '%s'", path)); 38018c2aff7Sartem goto out; 38118c2aff7Sartem } 38218c2aff7Sartem 38318c2aff7Sartem buf[0] = '\0'; 38418c2aff7Sartem if (fgets (buf, sizeof (buf), f) == NULL) { 38518c2aff7Sartem HAL_ERROR (("Cannot read from '%s'", path)); 38618c2aff7Sartem goto out; 38718c2aff7Sartem } 38818c2aff7Sartem 38918c2aff7Sartem len = strlen (buf); 39018c2aff7Sartem if (len>0) 39118c2aff7Sartem buf[len-1] = '\0'; 39218c2aff7Sartem 39318c2aff7Sartem /* Clear remaining whitespace */ 39418c2aff7Sartem for (i = len - 2; i >= 0; --i) { 39518c2aff7Sartem if (!g_ascii_isspace (buf[i])) 39618c2aff7Sartem break; 39718c2aff7Sartem buf[i] = '\0'; 39818c2aff7Sartem } 39918c2aff7Sartem 40018c2aff7Sartem result = buf; 40118c2aff7Sartem 40218c2aff7Sartem out: 40318c2aff7Sartem if (f != NULL) 40418c2aff7Sartem fclose (f); 40518c2aff7Sartem 40618c2aff7Sartem return result; 40718c2aff7Sartem } 40818c2aff7Sartem 40918c2aff7Sartem gboolean 41018c2aff7Sartem hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file) 41118c2aff7Sartem { 41218c2aff7Sartem gchar *buf; 41318c2aff7Sartem gboolean ret; 41418c2aff7Sartem 41518c2aff7Sartem ret = FALSE; 41618c2aff7Sartem 41718c2aff7Sartem if ((buf = hal_util_get_string_from_file (directory, file)) != NULL) 41818c2aff7Sartem ret = hal_device_property_set_string (d, key, buf); 41918c2aff7Sartem 42018c2aff7Sartem return ret; 42118c2aff7Sartem } 42218c2aff7Sartem 42318c2aff7Sartem void 42418c2aff7Sartem hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...) 42518c2aff7Sartem { 42618c2aff7Sartem guint i; 42718c2aff7Sartem va_list args; 42818c2aff7Sartem gchar buf[256]; 42918c2aff7Sartem 43018c2aff7Sartem va_start (args, format); 43118c2aff7Sartem g_vsnprintf (buf, sizeof (buf), format, args); 43218c2aff7Sartem va_end (args); 43318c2aff7Sartem 43418c2aff7Sartem g_strcanon (buf, 43518c2aff7Sartem "/_" 43618c2aff7Sartem "abcdefghijklmnopqrstuvwxyz" 43718c2aff7Sartem "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 43818c2aff7Sartem "1234567890", '_'); 43918c2aff7Sartem 44018c2aff7Sartem g_strlcpy (dst, buf, dstsize); 44118c2aff7Sartem if (hal_device_store_find (store, dst) == NULL) 44218c2aff7Sartem goto out; 44318c2aff7Sartem 44418c2aff7Sartem for (i = 0; ; i++) { 44518c2aff7Sartem g_snprintf (dst, dstsize, "%s_%d", buf, i); 44618c2aff7Sartem if (hal_device_store_find (store, dst) == NULL) 44718c2aff7Sartem goto out; 44818c2aff7Sartem } 44918c2aff7Sartem 45018c2aff7Sartem out: 45118c2aff7Sartem ; 45218c2aff7Sartem } 45318c2aff7Sartem 45418c2aff7Sartem 45518c2aff7Sartem gboolean 45618c2aff7Sartem hal_util_path_ascend (gchar *path) 45718c2aff7Sartem { 45818c2aff7Sartem gchar *p; 45918c2aff7Sartem 46018c2aff7Sartem if (path == NULL) 46118c2aff7Sartem return FALSE; 46218c2aff7Sartem 46318c2aff7Sartem p = strrchr (path, '/'); 46418c2aff7Sartem if (p == NULL) 46518c2aff7Sartem return FALSE; 46618c2aff7Sartem 46718c2aff7Sartem *p = '\0'; 46818c2aff7Sartem return TRUE; 46918c2aff7Sartem } 47018c2aff7Sartem 47118c2aff7Sartem static gboolean _grep_can_reuse = FALSE; 47218c2aff7Sartem 47318c2aff7Sartem void 47418c2aff7Sartem hal_util_grep_discard_existing_data (void) 47518c2aff7Sartem { 47618c2aff7Sartem _grep_can_reuse = FALSE; 47718c2aff7Sartem } 47818c2aff7Sartem 47918c2aff7Sartem /** Given a directory and filename, open the file and search for the 48018c2aff7Sartem * first line that starts with the given linestart string. Returns 48118c2aff7Sartem * the rest of the line as a string if found. 48218c2aff7Sartem * 48318c2aff7Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 48418c2aff7Sartem * @param file File, e.g. "info" 48518c2aff7Sartem * @param linestart Start of line, e.g. "serial number" 48618c2aff7Sartem * @param reuse Whether we should reuse the file contents 48718c2aff7Sartem * if the file is the same; can be cleared 48818c2aff7Sartem * with hal_util_grep_discard_existing_data() 48918c2aff7Sartem * @return NULL if not found, otherwise the remainder 49018c2aff7Sartem * of the line, e.g. ": 21805" if 49118c2aff7Sartem * the file /proc/acpi/battery/BAT0 contains 49218c2aff7Sartem * this line "serial number: 21805" 49318c2aff7Sartem * The string is only valid until the next 49418c2aff7Sartem * invocation of this function. 49518c2aff7Sartem */ 49618c2aff7Sartem gchar * 49718c2aff7Sartem hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart, gboolean reuse) 49818c2aff7Sartem { 49918c2aff7Sartem static gchar buf[2048]; 50018c2aff7Sartem static unsigned int bufsize; 50118c2aff7Sartem static gchar filename[HAL_PATH_MAX]; 50218c2aff7Sartem static gchar oldfilename[HAL_PATH_MAX]; 50318c2aff7Sartem gchar *result; 50418c2aff7Sartem gsize linestart_len; 50518c2aff7Sartem gchar *p; 50618c2aff7Sartem 50718c2aff7Sartem result = NULL; 50818c2aff7Sartem 50918c2aff7Sartem /* TODO: use reuse and _grep_can_reuse parameters to avoid loading 51018c2aff7Sartem * the file again and again 51118c2aff7Sartem */ 51218c2aff7Sartem 51318c2aff7Sartem if (file != NULL && strlen (file) > 0) 51418c2aff7Sartem snprintf (filename, sizeof (filename), "%s/%s", directory, file); 51518c2aff7Sartem else 51618c2aff7Sartem strncpy (filename, directory, sizeof (filename)); 51718c2aff7Sartem 51818c2aff7Sartem if (_grep_can_reuse && reuse && strcmp (oldfilename, filename) == 0) { 51918c2aff7Sartem /* just reuse old file; e.g. bufsize, buf */ 52018c2aff7Sartem /*HAL_INFO (("hal_util_grep_file: reusing buf for %s", filename));*/ 52118c2aff7Sartem } else { 52218c2aff7Sartem FILE *f; 52318c2aff7Sartem 52418c2aff7Sartem f = fopen (filename, "r"); 52518c2aff7Sartem if (f == NULL) 52618c2aff7Sartem goto out; 52718c2aff7Sartem bufsize = fread (buf, sizeof (char), sizeof (buf) - 1, f); 52818c2aff7Sartem buf[bufsize] = '\0'; 52918c2aff7Sartem fclose (f); 53018c2aff7Sartem 53118c2aff7Sartem /*HAL_INFO (("hal_util_grep_file: read %s of %d bytes", filename, bufsize));*/ 53218c2aff7Sartem } 53318c2aff7Sartem 53418c2aff7Sartem /* book keeping */ 53518c2aff7Sartem _grep_can_reuse = TRUE; 53618c2aff7Sartem strncpy (oldfilename, filename, sizeof(oldfilename)); 53718c2aff7Sartem 53818c2aff7Sartem linestart_len = strlen (linestart); 53918c2aff7Sartem 54018c2aff7Sartem /* analyze buf */ 54118c2aff7Sartem p = buf; 54218c2aff7Sartem do { 54318c2aff7Sartem unsigned int linelen; 54418c2aff7Sartem static char line[256]; 54518c2aff7Sartem 54618c2aff7Sartem for (linelen = 0; p[linelen] != '\n' && p[linelen] != '\0'; linelen++) 54718c2aff7Sartem ; 54818c2aff7Sartem 54918c2aff7Sartem if (linelen < sizeof (line)) { 55018c2aff7Sartem 55118c2aff7Sartem strncpy (line, p, linelen); 55218c2aff7Sartem line[linelen] = '\0'; 55318c2aff7Sartem 55418c2aff7Sartem if (strncmp (line, linestart, linestart_len) == 0) { 55518c2aff7Sartem result = line + linestart_len; 55618c2aff7Sartem goto out; 55718c2aff7Sartem } 55818c2aff7Sartem } 55918c2aff7Sartem 56018c2aff7Sartem p += linelen + 1; 56118c2aff7Sartem 56218c2aff7Sartem } while (p < buf + bufsize); 56318c2aff7Sartem 56418c2aff7Sartem out: 56518c2aff7Sartem return result; 56618c2aff7Sartem } 56718c2aff7Sartem 56818c2aff7Sartem gchar * 56918c2aff7Sartem hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file, 57018c2aff7Sartem const gchar *linestart, guint elem, gboolean reuse) 57118c2aff7Sartem { 57218c2aff7Sartem gchar *line; 57318c2aff7Sartem gchar *res; 57418c2aff7Sartem static gchar buf[256]; 57518c2aff7Sartem gchar **tokens; 57618c2aff7Sartem guint i, j; 57718c2aff7Sartem 57818c2aff7Sartem res = NULL; 57918c2aff7Sartem tokens = NULL; 58018c2aff7Sartem 58118c2aff7Sartem if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0)) 58218c2aff7Sartem goto out; 58318c2aff7Sartem 58418c2aff7Sartem tokens = g_strsplit_set (line, " \t:", 0); 58518c2aff7Sartem for (i = 0, j = 0; tokens[i] != NULL; i++) { 58618c2aff7Sartem if (strlen (tokens[i]) == 0) 58718c2aff7Sartem continue; 58818c2aff7Sartem if (j == elem) { 58918c2aff7Sartem strncpy (buf, tokens[i], sizeof (buf)); 59018c2aff7Sartem res = buf; 59118c2aff7Sartem goto out; 59218c2aff7Sartem } 59318c2aff7Sartem j++; 59418c2aff7Sartem } 59518c2aff7Sartem 59618c2aff7Sartem out: 59718c2aff7Sartem if (tokens != NULL) 59818c2aff7Sartem g_strfreev (tokens); 59918c2aff7Sartem 60018c2aff7Sartem return res; 60118c2aff7Sartem } 60218c2aff7Sartem 60318c2aff7Sartem gint 60418c2aff7Sartem hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file, 60518c2aff7Sartem const gchar *linestart, guint elem, guint base, gboolean reuse) 60618c2aff7Sartem { 60718c2aff7Sartem gchar *endptr; 60818c2aff7Sartem gchar *strvalue; 60918c2aff7Sartem int value; 61018c2aff7Sartem 61118c2aff7Sartem value = G_MAXINT; 61218c2aff7Sartem 61318c2aff7Sartem strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse); 61418c2aff7Sartem if (strvalue == NULL) 61518c2aff7Sartem goto out; 61618c2aff7Sartem 61718c2aff7Sartem value = strtol (strvalue, &endptr, base); 61818c2aff7Sartem if (endptr == strvalue) { 61918c2aff7Sartem value = G_MAXINT; 62018c2aff7Sartem goto out; 62118c2aff7Sartem } 62218c2aff7Sartem 62318c2aff7Sartem out: 62418c2aff7Sartem return value; 62518c2aff7Sartem } 62618c2aff7Sartem 62718c2aff7Sartem /** Get a string value from a formatted text file and assign it to 62818c2aff7Sartem * a property on a device object. 62918c2aff7Sartem * 63018c2aff7Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 63118c2aff7Sartem * the line 63218c2aff7Sartem * 63318c2aff7Sartem * "design voltage: 10800 mV" 63418c2aff7Sartem * 63518c2aff7Sartem * then hal_util_set_string_elem_from_file (d, "battery.foo", 63618c2aff7Sartem * "/proc/acpi/battery/BAT0", "info", "design voltage", 1) will assign 63718c2aff7Sartem * the string "mV" to the property "battery.foo" on d. 63818c2aff7Sartem * 63918c2aff7Sartem * @param d Device object 64018c2aff7Sartem * @param key Property name 64118c2aff7Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 64218c2aff7Sartem * @param file File, e.g. "info" 64318c2aff7Sartem * @param linestart Start of line, e.g. "design voltage" 64418c2aff7Sartem * @param elem Element number after linestart to extract 64518c2aff7Sartem * excluding whitespace and ':' characters. 64618c2aff7Sartem * @return TRUE, if, and only if, the value could be 64718c2aff7Sartem * extracted and the property was set 64818c2aff7Sartem */ 64918c2aff7Sartem gboolean 65018c2aff7Sartem hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key, 65118c2aff7Sartem const gchar *directory, const gchar *file, 65218c2aff7Sartem const gchar *linestart, guint elem, gboolean reuse) 65318c2aff7Sartem { 65418c2aff7Sartem gboolean res; 65518c2aff7Sartem gchar *value; 65618c2aff7Sartem 65718c2aff7Sartem res = FALSE; 65818c2aff7Sartem 65918c2aff7Sartem if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse)) == NULL) 66018c2aff7Sartem goto out; 66118c2aff7Sartem 66218c2aff7Sartem res = hal_device_property_set_string (d, key, value); 66318c2aff7Sartem out: 66418c2aff7Sartem return res; 66518c2aff7Sartem } 66618c2aff7Sartem 66718c2aff7Sartem /** Get an integer value from a formatted text file and assign it to 66818c2aff7Sartem * a property on a device object. 66918c2aff7Sartem * 67018c2aff7Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 67118c2aff7Sartem * the line 67218c2aff7Sartem * 67318c2aff7Sartem * "design voltage: 10800 mV" 67418c2aff7Sartem * 67518c2aff7Sartem * then hal_util_set_int_elem_from_file (d, "battery.foo", 67618c2aff7Sartem * "/proc/acpi/battery/BAT0", "info", "design voltage", 0) will assign 67718c2aff7Sartem * the integer 10800 to the property "battery.foo" on d. 67818c2aff7Sartem * 67918c2aff7Sartem * @param d Device object 68018c2aff7Sartem * @param key Property name 68118c2aff7Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 68218c2aff7Sartem * @param file File, e.g. "info" 68318c2aff7Sartem * @param linestart Start of line, e.g. "design voltage" 68418c2aff7Sartem * @param elem Element number after linestart to extract 68518c2aff7Sartem * excluding whitespace and ':' characters. 68618c2aff7Sartem * @return TRUE, if, and only if, the value could be 68718c2aff7Sartem * extracted and the property was set 68818c2aff7Sartem */ 68918c2aff7Sartem gboolean 69018c2aff7Sartem hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key, 69118c2aff7Sartem const gchar *directory, const gchar *file, 69218c2aff7Sartem const gchar *linestart, guint elem, guint base, gboolean reuse) 69318c2aff7Sartem { 69418c2aff7Sartem gchar *endptr; 69518c2aff7Sartem gboolean res; 69618c2aff7Sartem gchar *strvalue; 69718c2aff7Sartem int value; 69818c2aff7Sartem 69918c2aff7Sartem res = FALSE; 70018c2aff7Sartem 70118c2aff7Sartem strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem, reuse); 70218c2aff7Sartem if (strvalue == NULL) 70318c2aff7Sartem goto out; 70418c2aff7Sartem 70518c2aff7Sartem value = strtol (strvalue, &endptr, base); 70618c2aff7Sartem if (endptr == strvalue) 70718c2aff7Sartem goto out; 70818c2aff7Sartem 70918c2aff7Sartem res = hal_device_property_set_int (d, key, value); 71018c2aff7Sartem 71118c2aff7Sartem out: 71218c2aff7Sartem return res; 71318c2aff7Sartem 71418c2aff7Sartem } 71518c2aff7Sartem 71618c2aff7Sartem /** Get a value from a formatted text file, test it against a given 71718c2aff7Sartem * value, and set a boolean property on a device object with the 71818c2aff7Sartem * test result. 71918c2aff7Sartem * 72018c2aff7Sartem * Example: Given that the file /proc/acpi/battery/BAT0/info contains 72118c2aff7Sartem * the line 72218c2aff7Sartem * 72318c2aff7Sartem * "present: yes" 72418c2aff7Sartem * 72518c2aff7Sartem * then hal_util_set_bool_elem_from_file (d, "battery.baz", 72618c2aff7Sartem * "/proc/acpi/battery/BAT0", "info", "present", 0, "yes") will assign 72718c2aff7Sartem * the boolean TRUE to the property "battery.baz" on d. 72818c2aff7Sartem * 72918c2aff7Sartem * If, instead, the line was 73018c2aff7Sartem * 73118c2aff7Sartem * "present: no" 73218c2aff7Sartem * 73318c2aff7Sartem * the value assigned will be FALSE. 73418c2aff7Sartem * 73518c2aff7Sartem * @param d Device object 73618c2aff7Sartem * @param key Property name 73718c2aff7Sartem * @param directory Directory, e.g. "/proc/acpi/battery/BAT0" 73818c2aff7Sartem * @param file File, e.g. "info" 73918c2aff7Sartem * @param linestart Start of line, e.g. "design voltage" 74018c2aff7Sartem * @param elem Element number after linestart to extract 74118c2aff7Sartem * excluding whitespace and ':' characters. 74218c2aff7Sartem * @param expected Value to test against 74318c2aff7Sartem * @return TRUE, if, and only if, the value could be 74418c2aff7Sartem * extracted and the property was set 74518c2aff7Sartem */ 74618c2aff7Sartem gboolean 74718c2aff7Sartem hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key, 74818c2aff7Sartem const gchar *directory, const gchar *file, 74918c2aff7Sartem const gchar *linestart, guint elem, const gchar *expected, gboolean reuse) 75018c2aff7Sartem { 75118c2aff7Sartem gchar *line; 75218c2aff7Sartem gboolean res; 75318c2aff7Sartem gchar **tokens; 75418c2aff7Sartem guint i, j; 75518c2aff7Sartem 75618c2aff7Sartem res = FALSE; 75718c2aff7Sartem tokens = NULL; 75818c2aff7Sartem 75918c2aff7Sartem if (((line = hal_util_grep_file (directory, file, linestart, reuse)) == NULL) || (strlen (line) == 0)) 76018c2aff7Sartem goto out; 76118c2aff7Sartem 76218c2aff7Sartem tokens = g_strsplit_set (line, " \t:", 0); 76318c2aff7Sartem 76418c2aff7Sartem for (i = 0, j = 0; tokens[i] != NULL; i++) { 76518c2aff7Sartem if (strlen (tokens[i]) == 0) 76618c2aff7Sartem continue; 76718c2aff7Sartem if (j == elem) { 76818c2aff7Sartem hal_device_property_set_bool (d, key, strcmp (tokens[i], expected) == 0); 76918c2aff7Sartem res = TRUE; 77018c2aff7Sartem goto out; 77118c2aff7Sartem } 77218c2aff7Sartem j++; 77318c2aff7Sartem } 77418c2aff7Sartem 77518c2aff7Sartem 77618c2aff7Sartem out: 77718c2aff7Sartem if (tokens != NULL) 77818c2aff7Sartem g_strfreev (tokens); 77918c2aff7Sartem 78018c2aff7Sartem return res; 78118c2aff7Sartem } 78218c2aff7Sartem 78318c2aff7Sartem gchar ** 78418c2aff7Sartem hal_util_dup_strv_from_g_slist (GSList *strlist) 78518c2aff7Sartem { 78618c2aff7Sartem guint j; 78718c2aff7Sartem guint len; 78818c2aff7Sartem gchar **strv; 78918c2aff7Sartem GSList *i; 79018c2aff7Sartem 79118c2aff7Sartem len = g_slist_length (strlist); 79218c2aff7Sartem strv = g_new (char *, len + 1); 79318c2aff7Sartem 79418c2aff7Sartem for (i = strlist, j = 0; i != NULL; i = g_slist_next (i), j++) { 79518c2aff7Sartem strv[j] = g_strdup ((const gchar *) i->data); 79618c2aff7Sartem } 79718c2aff7Sartem strv[j] = NULL; 79818c2aff7Sartem 79918c2aff7Sartem return strv; 80018c2aff7Sartem } 80118c2aff7Sartem 80218c2aff7Sartem /* -------------------------------------------------------------------------------------------------------------- */ 80318c2aff7Sartem 80418c2aff7Sartem typedef struct { 80518c2aff7Sartem HalDevice *d; 80618c2aff7Sartem gchar **programs; 80718c2aff7Sartem gchar **extra_env; 80818c2aff7Sartem guint next_program; 80918c2aff7Sartem 81018c2aff7Sartem HalCalloutsDone callback; 81118c2aff7Sartem gpointer userdata1; 81218c2aff7Sartem gpointer userdata2; 81318c2aff7Sartem 81418c2aff7Sartem } Callout; 81518c2aff7Sartem 81618c2aff7Sartem static void callout_do_next (Callout *c); 81718c2aff7Sartem 81818c2aff7Sartem static void 81918c2aff7Sartem callout_terminated (HalDevice *d, guint32 exit_type, 82018c2aff7Sartem gint return_code, gchar **error, 82118c2aff7Sartem gpointer data1, gpointer data2) 82218c2aff7Sartem { 82318c2aff7Sartem Callout *c; 82418c2aff7Sartem 82518c2aff7Sartem c = (Callout *) data1; 82618c2aff7Sartem callout_do_next (c); 82718c2aff7Sartem } 82818c2aff7Sartem 82918c2aff7Sartem static void 83018c2aff7Sartem callout_do_next (Callout *c) 83118c2aff7Sartem { 83218c2aff7Sartem 83318c2aff7Sartem /* Check if we're done */ 83418c2aff7Sartem if (c->programs[c->next_program] == NULL) { 83518c2aff7Sartem HalDevice *d; 83618c2aff7Sartem gpointer userdata1; 83718c2aff7Sartem gpointer userdata2; 83818c2aff7Sartem HalCalloutsDone callback; 83918c2aff7Sartem 84018c2aff7Sartem d = c->d; 84118c2aff7Sartem userdata1 = c->userdata1; 84218c2aff7Sartem userdata2 = c->userdata2; 84318c2aff7Sartem callback = c->callback; 84418c2aff7Sartem 84518c2aff7Sartem g_strfreev (c->programs); 84618c2aff7Sartem g_strfreev (c->extra_env); 84718c2aff7Sartem g_free (c); 84818c2aff7Sartem 84918c2aff7Sartem callback (d, userdata1, userdata2); 85018c2aff7Sartem 85118c2aff7Sartem } else { 85218c2aff7Sartem hald_runner_run(c->d, c->programs[c->next_program], c->extra_env, 85318c2aff7Sartem HAL_HELPER_TIMEOUT, callout_terminated, 85418c2aff7Sartem (gpointer)c, NULL); 85518c2aff7Sartem c->next_program++; 85618c2aff7Sartem } 85718c2aff7Sartem } 85818c2aff7Sartem 85918c2aff7Sartem static void 86018c2aff7Sartem hal_callout_device (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2, 86118c2aff7Sartem GSList *programs, gchar **extra_env) 86218c2aff7Sartem { 86318c2aff7Sartem Callout *c; 86418c2aff7Sartem 86518c2aff7Sartem c = g_new0 (Callout, 1); 86618c2aff7Sartem c->d = d; 86718c2aff7Sartem c->callback = callback; 86818c2aff7Sartem c->userdata1 = userdata1; 86918c2aff7Sartem c->userdata2 = userdata2; 87018c2aff7Sartem c->programs = hal_util_dup_strv_from_g_slist (programs); 87118c2aff7Sartem c->extra_env = g_strdupv (extra_env); 87218c2aff7Sartem c->next_program = 0; 87318c2aff7Sartem 87418c2aff7Sartem callout_do_next (c); 87518c2aff7Sartem } 87618c2aff7Sartem 87718c2aff7Sartem void 87818c2aff7Sartem hal_util_callout_device_add (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 87918c2aff7Sartem { 88018c2aff7Sartem GSList *programs; 88118c2aff7Sartem gchar *extra_env[2] = {"HALD_ACTION=add", NULL}; 88218c2aff7Sartem 88318c2aff7Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.add")) == NULL) { 88418c2aff7Sartem callback (d, userdata1, userdata2); 88518c2aff7Sartem goto out; 88618c2aff7Sartem } 88718c2aff7Sartem 88818c2aff7Sartem HAL_INFO (("Add callouts for udi=%s", d->udi)); 88918c2aff7Sartem 89018c2aff7Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 89118c2aff7Sartem out: 89218c2aff7Sartem ; 89318c2aff7Sartem } 89418c2aff7Sartem 89518c2aff7Sartem void 89618c2aff7Sartem hal_util_callout_device_remove (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 89718c2aff7Sartem { 89818c2aff7Sartem GSList *programs; 89918c2aff7Sartem gchar *extra_env[2] = {"HALD_ACTION=remove", NULL}; 90018c2aff7Sartem 90118c2aff7Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.remove")) == NULL) { 90218c2aff7Sartem callback (d, userdata1, userdata2); 90318c2aff7Sartem goto out; 90418c2aff7Sartem } 90518c2aff7Sartem 90618c2aff7Sartem HAL_INFO (("Remove callouts for udi=%s", d->udi)); 90718c2aff7Sartem 90818c2aff7Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 90918c2aff7Sartem out: 91018c2aff7Sartem ; 91118c2aff7Sartem } 91218c2aff7Sartem 91318c2aff7Sartem void 91418c2aff7Sartem hal_util_callout_device_preprobe (HalDevice *d, HalCalloutsDone callback, gpointer userdata1, gpointer userdata2) 91518c2aff7Sartem { 91618c2aff7Sartem GSList *programs; 91718c2aff7Sartem gchar *extra_env[2] = {"HALD_ACTION=preprobe", NULL}; 91818c2aff7Sartem 91918c2aff7Sartem if ((programs = hal_device_property_get_strlist (d, "info.callouts.preprobe")) == NULL) { 92018c2aff7Sartem callback (d, userdata1, userdata2); 92118c2aff7Sartem goto out; 92218c2aff7Sartem } 92318c2aff7Sartem 92418c2aff7Sartem HAL_INFO (("Preprobe callouts for udi=%s", d->udi)); 92518c2aff7Sartem 92618c2aff7Sartem hal_callout_device (d, callback, userdata1, userdata2, programs, extra_env); 92718c2aff7Sartem out: 92818c2aff7Sartem ; 92918c2aff7Sartem } 93018c2aff7Sartem 93118c2aff7Sartem gchar * 93218c2aff7Sartem hal_util_strdup_valid_utf8 (const char *str) 93318c2aff7Sartem { 93418c2aff7Sartem char *endchar; 93518c2aff7Sartem char *newstr; 93618c2aff7Sartem unsigned int count = 0; 93718c2aff7Sartem 93818c2aff7Sartem if (str == NULL) 93918c2aff7Sartem return NULL; 94018c2aff7Sartem 94118c2aff7Sartem newstr = g_strdup (str); 94218c2aff7Sartem 94318c2aff7Sartem while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) { 94418c2aff7Sartem *endchar = '?'; 94518c2aff7Sartem count++; 94618c2aff7Sartem } 94718c2aff7Sartem 94818c2aff7Sartem if (strlen(newstr) == count) 94918c2aff7Sartem return NULL; 95018c2aff7Sartem else 95118c2aff7Sartem return newstr; 95218c2aff7Sartem } 95318c2aff7Sartem 95418c2aff7Sartem void 95518c2aff7Sartem hal_util_hexdump (const void *mem, unsigned int size) 95618c2aff7Sartem { 95718c2aff7Sartem unsigned int i; 95818c2aff7Sartem unsigned int j; 95918c2aff7Sartem unsigned int n; 96018c2aff7Sartem const char *buf = (const char *) mem; 96118c2aff7Sartem 96218c2aff7Sartem n = 0; 96318c2aff7Sartem printf ("Dumping %d=0x%x bytes\n", size, size); 96418c2aff7Sartem while (n < size) { 96518c2aff7Sartem 96618c2aff7Sartem printf ("0x%04x: ", n); 96718c2aff7Sartem 96818c2aff7Sartem j = n; 96918c2aff7Sartem for (i = 0; i < 16; i++) { 97018c2aff7Sartem if (j >= size) 97118c2aff7Sartem break; 97218c2aff7Sartem printf ("%02x ", buf[j]); 97318c2aff7Sartem j++; 97418c2aff7Sartem } 97518c2aff7Sartem 97618c2aff7Sartem for ( ; i < 16; i++) { 97718c2aff7Sartem printf (" "); 97818c2aff7Sartem } 97918c2aff7Sartem 98018c2aff7Sartem printf (" "); 98118c2aff7Sartem 98218c2aff7Sartem j = n; 98318c2aff7Sartem for (i = 0; i < 16; i++) { 98418c2aff7Sartem if (j >= size) 98518c2aff7Sartem break; 98618c2aff7Sartem printf ("%c", isprint(buf[j]) ? buf[j] : '.'); 98718c2aff7Sartem j++; 98818c2aff7Sartem } 98918c2aff7Sartem 99018c2aff7Sartem printf ("\n"); 99118c2aff7Sartem 99218c2aff7Sartem n += 16; 99318c2aff7Sartem } 99418c2aff7Sartem } 99518c2aff7Sartem 99618c2aff7Sartem gboolean 99718c2aff7Sartem hal_util_is_mounted_by_hald (const char *mount_point) 99818c2aff7Sartem { 99918c2aff7Sartem int i; 100018c2aff7Sartem FILE *hal_mtab; 100118c2aff7Sartem int hal_mtab_len; 100218c2aff7Sartem int num_read; 100318c2aff7Sartem char *hal_mtab_buf; 100418c2aff7Sartem char **lines; 100518c2aff7Sartem gboolean found; 100618c2aff7Sartem 100718c2aff7Sartem hal_mtab = NULL; 100818c2aff7Sartem hal_mtab_buf = NULL; 100918c2aff7Sartem found = FALSE; 101018c2aff7Sartem 101118c2aff7Sartem /*HAL_DEBUG (("examining /media/.hal-mtab for %s", mount_point));*/ 101218c2aff7Sartem 101318c2aff7Sartem hal_mtab = fopen ("/media/.hal-mtab", "r"); 101418c2aff7Sartem if (hal_mtab == NULL) { 101518c2aff7Sartem HAL_ERROR (("Cannot open /media/.hal-mtab")); 101618c2aff7Sartem goto out; 101718c2aff7Sartem } 101818c2aff7Sartem if (fseek (hal_mtab, 0L, SEEK_END) != 0) { 101918c2aff7Sartem HAL_ERROR (("Cannot seek to end of /media/.hal-mtab")); 102018c2aff7Sartem goto out; 102118c2aff7Sartem } 102218c2aff7Sartem hal_mtab_len = ftell (hal_mtab); 102318c2aff7Sartem if (hal_mtab_len < 0) { 102418c2aff7Sartem HAL_ERROR (("Cannot determine size of /media/.hal-mtab")); 102518c2aff7Sartem goto out; 102618c2aff7Sartem } 102718c2aff7Sartem rewind (hal_mtab); 102818c2aff7Sartem 102918c2aff7Sartem hal_mtab_buf = g_new0 (char, hal_mtab_len + 1); 103018c2aff7Sartem num_read = fread (hal_mtab_buf, 1, hal_mtab_len, hal_mtab); 103118c2aff7Sartem if (num_read != hal_mtab_len) { 103218c2aff7Sartem HAL_ERROR (("Cannot read from /media/.hal-mtab")); 103318c2aff7Sartem goto out; 103418c2aff7Sartem } 103518c2aff7Sartem fclose (hal_mtab); 103618c2aff7Sartem hal_mtab = NULL; 103718c2aff7Sartem 103818c2aff7Sartem /*HAL_DEBUG (("hal_mtab = '%s'\n", hal_mtab_buf));*/ 103918c2aff7Sartem 104018c2aff7Sartem lines = g_strsplit (hal_mtab_buf, "\n", 0); 104118c2aff7Sartem g_free (hal_mtab_buf); 104218c2aff7Sartem hal_mtab_buf = NULL; 104318c2aff7Sartem 104418c2aff7Sartem /* find the entry we're going to unmount */ 104518c2aff7Sartem for (i = 0; lines[i] != NULL && !found; i++) { 104618c2aff7Sartem char **line_elements; 104718c2aff7Sartem 104818c2aff7Sartem /*HAL_DEBUG ((" line = '%s'", lines[i]));*/ 104918c2aff7Sartem 105018c2aff7Sartem if ((lines[i])[0] == '#') 105118c2aff7Sartem continue; 105218c2aff7Sartem 105318c2aff7Sartem line_elements = g_strsplit (lines[i], "\t", 6); 105418c2aff7Sartem if (g_strv_length (line_elements) == 6) { 105518c2aff7Sartem /* 105618c2aff7Sartem HAL_DEBUG ((" devfile = '%s'", line_elements[0])); 105718c2aff7Sartem HAL_DEBUG ((" uid = '%s'", line_elements[1])); 105818c2aff7Sartem HAL_DEBUG ((" session id = '%s'", line_elements[2])); 105918c2aff7Sartem HAL_DEBUG ((" fs = '%s'", line_elements[3])); 106018c2aff7Sartem HAL_DEBUG ((" options = '%s'", line_elements[4])); 106118c2aff7Sartem HAL_DEBUG ((" mount_point = '%s'", line_elements[5])); 106218c2aff7Sartem HAL_DEBUG ((" (comparing against '%s')", mount_point)); 106318c2aff7Sartem */ 106418c2aff7Sartem 106518c2aff7Sartem if (strcmp (line_elements[5], mount_point) == 0) { 106618c2aff7Sartem found = TRUE; 106718c2aff7Sartem /*HAL_INFO (("device at '%s' is indeed mounted by HAL's Mount()", mount_point));*/ 106818c2aff7Sartem } 106918c2aff7Sartem 107018c2aff7Sartem } 107118c2aff7Sartem 107218c2aff7Sartem g_strfreev (line_elements); 107318c2aff7Sartem } 107418c2aff7Sartem 107518c2aff7Sartem g_strfreev (lines); 107618c2aff7Sartem 107718c2aff7Sartem out: 107818c2aff7Sartem if (hal_mtab != NULL) 107918c2aff7Sartem fclose (hal_mtab); 108018c2aff7Sartem if (hal_mtab_buf != NULL) 108118c2aff7Sartem g_free (hal_mtab_buf); 108218c2aff7Sartem 108318c2aff7Sartem return found; 108418c2aff7Sartem } 108518c2aff7Sartem 108618c2aff7Sartem void 108718c2aff7Sartem hal_util_branch_claim (HalDeviceStore *store, HalDevice *root, dbus_bool_t claimed, 108818c2aff7Sartem const char *service, int uid) 108918c2aff7Sartem { 109018c2aff7Sartem GSList *children; 109118c2aff7Sartem GSList *i; 109218c2aff7Sartem HalDevice *d; 109318c2aff7Sartem 109418c2aff7Sartem if (claimed) { 109518c2aff7Sartem hal_device_property_set_bool (root, "info.claimed", claimed); 109618c2aff7Sartem hal_device_property_set_string (root, "info.claimed.service", service); 109718c2aff7Sartem hal_device_property_set_int (root, "info.claimed.uid", uid); 109818c2aff7Sartem } else { 109918c2aff7Sartem hal_device_property_remove (root, "info.claimed"); 110018c2aff7Sartem hal_device_property_remove (root, "info.claimed.service"); 110118c2aff7Sartem hal_device_property_remove (root, "info.claimed.uid"); 110218c2aff7Sartem } 110318c2aff7Sartem 110418c2aff7Sartem 110518c2aff7Sartem children = hal_device_store_match_multiple_key_value_string (store, 110618c2aff7Sartem "info.parent", root->udi); 110718c2aff7Sartem 110818c2aff7Sartem for (i = children; i != NULL; i = g_slist_next (i)) { 110918c2aff7Sartem d = HAL_DEVICE (i->data); 111018c2aff7Sartem hal_util_branch_claim (store, d, claimed, service, uid); 111118c2aff7Sartem } 111218c2aff7Sartem 111318c2aff7Sartem g_slist_free (children); 111418c2aff7Sartem } 1115*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1116*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China /** Given an interface name, check if it is valid. 1117*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China * @param name A given interface name 1118*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China * @return TRUE if name is valid, otherwise FALSE 1119*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China */ 1120*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China gboolean 1121*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China is_valid_interface_name(const char *name) { 1122*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1123*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China const char *end; 1124*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China const char *last_dot; 1125*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1126*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China last_dot = NULL; 1127*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1128*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China if (strlen(name) == 0) 1129*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1130*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1131*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China end = name + strlen(name); 1132*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1133*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China if (*name == '.') /* disallow starting with a . */ 1134*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1135*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China else if (!VALID_INITIAL_NAME_CHARACTER (*name)) 1136*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1137*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China else 1138*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China name++; 1139*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1140*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China while (name != end) { 1141*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China if (*name == '.') { 1142*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China if ((name + 1) == end) 1143*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1144*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China else if (!VALID_INITIAL_NAME_CHARACTER (*(name + 1))) 1145*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1146*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China last_dot = name; 1147*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China name++; /* we just validated the next char, so skip two */ 1148*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China } else if (!VALID_NAME_CHARACTER (*name)) 1149*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1150*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China name++; 1151*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China } 1152*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China if (last_dot == NULL) 1153*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return FALSE; 1154*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China 1155*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China return TRUE; 1156*97191cecSXiaolin Zhang - Sun Microsystems - Beijing China } 1157