[PATCH] add tool to add/remove HAL devices

Kay Sievers kay.sievers at vrfy.org
Sat Jul 2 09:46:23 PDT 2005


This adds a tool to add/remove devices to/from the HAL store.
It depends on the patch to implement the corresponding functions
in hald.

usage: hal-device [--help] [--add udi] [--remove udi] [udi]
  -a, --add udi         Add new device.
                        Reads property list in 'lshal' syntax from stdin.
  -r, --remove udi      Remove device.
  -h, --help            Show this text.

Thanks to Steffen Winterfeldt <snwint at suse.de>.

Ok to commit?

Thanks,
Kay
-------------- next part --------------
Index: tools/Makefile.am
===================================================================
RCS file: /cvs/hal/hal/tools/Makefile.am,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile.am
--- tools/Makefile.am	13 May 2005 15:56:23 -0000	1.15
+++ tools/Makefile.am	2 Jul 2005 13:37:29 -0000
@@ -9,7 +9,7 @@ INCLUDES = \
 	-I$(top_srcdir) -I$(top_srcdir)/libhal \
 	@PACKAGE_CFLAGS@
 
-bin_PROGRAMS = lshal hal-get-property hal-set-property hal-find-by-capability hal-find-by-property
+bin_PROGRAMS = lshal hal-get-property hal-set-property hal-find-by-capability hal-find-by-property hal-device
 
 if FSTAB_SYNC_ENABLED
 sbin_PROGRAMS = fstab-sync
@@ -30,6 +30,9 @@ hal_find_by_capability_LDADD = @DBUS_LIB
 hal_find_by_property_SOURCES = hal_find_by_property.c
 hal_find_by_property_LDADD = @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la
 
+hal_device_SOURCES = hal-device.c
+hal_device_LDADD = @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la
+
 if FSTAB_SYNC_ENABLED
 fstab_sync_SOURCES = fstab-sync.c
 fstab_sync_LDADD = -lpopt $(top_builddir)/libhal/libhal.la $(top_builddir)/libhal-storage/libhal-storage.la
Index: tools/hal-device.c
===================================================================
--- /dev/null	2005-06-29 03:39:32.000000000 +0200
+++ tools/hal-device.c	2005-07-02 15:46:10.000000000 +0200
@@ -0,0 +1,618 @@
+/***************************************************************************
+ * CVSID: $Id: $
+ *
+ * hal-device.c : add devices HAL
+ *
+ * Copyright (C) 2005 SuSE Linux Gmbh
+ *
+ * Authors:
+ *	Steffen Winterfeldt <snwint at suse.de>
+ *
+ * Licensed under the Academic Free License version 2.0
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#ifndef DBUS_API_SUBJECT_TO_CHANGE
+#define DBUS_API_SUBJECT_TO_CHANGE 1
+#endif
+
+#include <dbus/dbus.h>
+#include <libhal/libhal.h>
+
+typedef struct {
+	char *udi;
+	char *real_udi;
+} new_dev_t;
+
+typedef struct lh_prop_s {
+	struct lh_prop_s *next;
+	LibHalPropertyType type;
+	char *key;
+	union {
+		char *str_value;
+		dbus_int32_t int_value;
+		dbus_uint64_t uint64_value;
+		double double_value;
+		dbus_bool_t bool_value;
+		char **strlist_value;
+	};
+} lh_prop_t;
+
+
+void help(void);
+int dump_devices(LibHalContext *hal_ctx, char *arg);
+int remove_udi(LibHalContext *hal_ctx, char *arg);
+int add_udi(LibHalContext *hal_ctx, char *arg);
+void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop);
+int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop);
+lh_prop_t *free_properties(lh_prop_t *prop);
+static char *skip_space(char *s);
+static char *skip_non_eq_or_space(char *s);
+static char *skip_number(char *s);
+static char *skip_nonquote(char *s);
+
+
+new_dev_t new_dev;
+
+struct {
+	unsigned remove:1;
+	unsigned add:1;
+	unsigned list:1;
+	char *udi;
+} opt;
+
+struct option options[] = {
+	{ "remove", 1, NULL, 'r' },
+	{ "add", 1, NULL, 'a' },
+	{ "help", 0, NULL, 'h' },
+	{}
+};
+
+
+int main(int argc, char **argv)
+{
+	DBusError error;
+	DBusConnection *conn;
+	LibHalContext *hal_ctx;
+	int i, err;
+
+	opterr = 0;
+	opt.list = 1;
+
+	while ((i = getopt_long(argc, argv, "a:hr:", options, NULL)) != -1) {
+		switch (i) {
+		case 'a':
+			opt.add = 1;
+			opt.list = 0;
+			opt.udi = optarg;
+			break;
+		case 'r':
+			opt.remove = 1;
+			opt.list = 0;
+			opt.udi = optarg;
+			break;
+		case 'h':
+			help();
+			return 0;
+		default:
+			help();
+			return 1;
+		}
+	}
+
+	dbus_error_init(&error);
+
+	if (!(conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
+		fprintf(stderr, "error: dbus_bus_get: %s: %s\n", error.name, error.message);
+		return 2;
+	}
+
+	// fprintf(stderr, "connected to: %s\n", dbus_bus_get_unique_name(conn));
+	if (!(hal_ctx = libhal_ctx_new())) return 3;
+	if (!libhal_ctx_set_dbus_connection(hal_ctx, conn)) return 4;
+	if (!libhal_ctx_init(hal_ctx, &error)) {
+		fprintf(stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message);
+		return 5;
+	}
+
+	err = 0;
+	if (opt.list)
+		err = dump_devices(hal_ctx, argv[optind]);
+	else if (opt.remove)
+		err = remove_udi(hal_ctx, opt.udi);
+	else if (opt.add)
+		err = add_udi(hal_ctx, opt.udi);
+	else
+		err = 6;
+
+	libhal_ctx_shutdown(hal_ctx, &error);
+	libhal_ctx_free(hal_ctx);
+	dbus_connection_disconnect(conn);
+	dbus_connection_unref(conn);
+	dbus_error_free(&error);
+
+	return err;
+}
+
+
+void help()
+{
+	fprintf(stderr,
+		"usage: hal-device [--help] [--add udi] [--remove udi] [udi]\n"
+		"Create, remove, or show HAL device. If no udi is given, shows all devices.\n"
+		"If udi doesn't start with a '/', '/org/freedesktop/Hal/devices/' is prepended.\n"
+		"  -a, --add udi\t\tAdd new device.\n"
+		"  \t\t\tReads property list in 'lshal' syntax from stdin.\n"
+		"  -r, --remove udi\tRemove device.\n"
+		"  -h, --help\t\tShow this text.\n"
+	);
+}
+
+
+/*
+ * Dump all devices.
+ */
+int dump_devices(LibHalContext *hal_ctx, char *arg)
+{
+	int i;
+	int num_devices;
+	char **device_names;
+	DBusError error;
+	char *udi = NULL;
+
+	if (arg) {
+		if (*arg == '/') {
+			udi = arg;
+		} else {
+			asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
+		}
+	}
+
+	dbus_error_init(&error);
+
+	if (!udi) {
+		if (!(device_names = libhal_get_all_devices(hal_ctx, &num_devices, &error))) {
+			fprintf(stderr, "Empty HAL device list.\n");
+			return 31;
+		}
+	} else {
+		device_names = calloc(2, sizeof *device_names);
+		device_names[0] = strdup(udi);
+		num_devices = 1;
+	}
+
+	for(i = 0; i < num_devices; i++) {
+		LibHalPropertySet *props;
+		LibHalPropertySetIterator it;
+		int type;
+
+		if (!(props = libhal_device_get_all_properties(hal_ctx, device_names[i], &error))) {
+			fprintf(stderr, "%s: %s\n", error.name, error.message);
+			dbus_error_init(&error);
+			continue;
+		}
+
+		if (!udi)
+			printf("%d: ", i);
+		printf("udi = '%s'\n", device_names[i]);
+
+		for(libhal_psi_init(&it, props); libhal_psi_has_more(&it); libhal_psi_next(&it)) {
+			type = libhal_psi_get_type(&it);
+			switch (type) {
+			case LIBHAL_PROPERTY_TYPE_STRING:
+				printf("  %s = '%s'  (string)\n",
+					libhal_psi_get_key(&it),
+					libhal_psi_get_string(&it)
+				);
+				break;
+			case LIBHAL_PROPERTY_TYPE_INT32:
+				printf("  %s = %d  (0x%x)  (int)\n",
+					libhal_psi_get_key(&it),
+					libhal_psi_get_int(&it),
+					libhal_psi_get_int(&it)
+				);
+				break;
+			case LIBHAL_PROPERTY_TYPE_UINT64:
+				printf("  %s = %lld  (0x%llx)  (uint64)\n",
+					libhal_psi_get_key(&it),
+					(long long) libhal_psi_get_uint64(&it),
+					(long long) libhal_psi_get_uint64(&it)
+				);
+				break;
+			case LIBHAL_PROPERTY_TYPE_DOUBLE:
+				printf("  %s = %g  (double)\n",
+					libhal_psi_get_key(&it),
+					libhal_psi_get_double(&it)
+				);
+				break;
+			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
+				printf("  %s = %s  (bool)\n",
+					libhal_psi_get_key(&it),
+					libhal_psi_get_bool(&it) ? "true" : "false"
+				);
+				break;
+			case LIBHAL_PROPERTY_TYPE_STRLIST:
+				{
+					char **strlist;
+
+					printf ("  %s = { ", libhal_psi_get_key(&it));
+					strlist = libhal_psi_get_strlist(&it);
+					while (*strlist) {
+						printf("'%s'%s", *strlist, strlist[1] ? ", " : "");
+						strlist++;
+					}
+					printf(" } (string list)\n");
+				}
+				break;
+			default:
+				printf("Unknown type %d = 0x%02x\n", type, type);
+				break;
+			}
+		}
+
+		libhal_free_property_set(props);
+		printf("\n");
+	}
+
+	libhal_free_string_array(device_names);
+	dbus_error_free(&error);
+
+	return 0;
+}
+
+
+int remove_udi(LibHalContext *hal_ctx, char *arg)
+{
+	DBusError error;
+	char *udi;
+
+	if (!arg) return 11;
+
+	if (*arg == '/') {
+		udi = arg;
+	} else {
+		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
+	}
+
+	dbus_error_init(&error);
+
+	if (remove) {
+		if (!libhal_agent_remove_device(hal_ctx, udi, &error)) {
+			fprintf(stderr, "%s: %s\n", error.name, error.message);
+			return 12;
+		}
+
+		fprintf(stderr, "removed: %s\n", udi);
+		return 13;
+	}
+
+	return 0;
+}
+
+
+int add_udi(LibHalContext *hal_ctx, char *arg)
+{
+	DBusError error;
+	dbus_bool_t dev_exists = FALSE;
+	char *udi = NULL, buf[1024];
+	lh_prop_t *prop;
+	int err;
+
+	if (!arg)
+		return 21;
+
+	if (*arg == '/') {
+		udi = arg;
+	} else {
+		asprintf(&udi, "/org/freedesktop/Hal/devices/%s", arg);
+	}
+
+	if (udi)
+		new_dev.udi = strdup(udi);
+
+	dbus_error_init(&error);
+
+	if (udi)
+		dev_exists = libhal_device_exists(hal_ctx, udi, &error);
+
+	if (dev_exists) {
+		new_dev.real_udi = strdup(new_dev.udi);
+	} else {
+		new_dev.real_udi = libhal_agent_new_device(hal_ctx, &error);
+
+		if (!new_dev.real_udi) {
+			fprintf(stderr, "%s: %s\n", error.name, error.message);
+			free(new_dev.real_udi);
+
+			return 22;
+		}
+
+		printf("tmp udi: %s\n", new_dev.real_udi);
+	}
+
+	prop = NULL;
+
+	while (fgets(buf, sizeof buf, stdin)) {
+		process_property(hal_ctx, buf, &prop);
+	}
+
+	err = add_properties(hal_ctx, &new_dev, prop);
+
+	prop = free_properties(prop);
+
+	if (!dev_exists) {
+		if (!libhal_agent_commit_to_gdl(hal_ctx, new_dev.real_udi, new_dev.udi, &error)) {
+			fprintf(stderr, "%s: %s\n", error.name, error.message);
+			free(new_dev.real_udi);
+
+			err = err ?: 23;
+		}
+	}
+
+	printf("%s: %s\n", dev_exists ? "merged": "created", new_dev.udi);
+
+	return err;
+}
+
+
+char *skip_space(char *s)
+{
+	while (isspace(*s)) s++;
+
+	return s;
+}
+
+
+char *skip_non_eq_or_space(char *s)
+{
+	while (*s && *s != '=' && !isspace(*s))
+		s++;
+
+	return s;
+}
+
+
+char *skip_number(char *s)
+{
+	while (*s == '-' || *s == '+' || *s == '.' || isdigit(*s))
+		s++;
+
+	return s;
+}
+
+
+char *skip_nonquote(char *s)
+{
+	while (*s && *s != '\'')
+		s++;
+
+	return s;
+}
+
+
+void process_property(LibHalContext *hal_ctx, char *buf, lh_prop_t **prop)
+{
+	char *s, *s1;
+	char *key, *s_val = NULL;
+	lh_prop_t *p;
+	unsigned len;
+	int remove = 0;
+
+	s = skip_space(buf);
+
+	if (*s == '-') {
+		remove = 1;
+		s = skip_space(s + 1);
+	}
+
+	if ((s1 = skip_number(s), s1 != s) && *s1 == ':') s = skip_space(s1 + 1);
+
+	s = skip_non_eq_or_space(key = s);
+	*s++ = 0;
+	if (!*key)
+		return;
+
+	if (*key == '#')
+		return;
+
+	if (*s == '=')
+		s++;
+	s = skip_space(s);
+
+	if (!*s)
+		remove = 1;
+
+	p = calloc(1, sizeof *p);
+	p->type = LIBHAL_PROPERTY_TYPE_INVALID;
+	p->key = strdup(key);
+
+	if (remove) {
+		p->next = *prop;
+		*prop = p;
+		return;
+	}
+
+	if (*s == '\'') {
+		s_val = s + 1;
+		s = strrchr(s_val, '\'');
+		*(s ?: s_val) = 0;
+		p->type = LIBHAL_PROPERTY_TYPE_STRING;
+		p->str_value = strdup(s_val);
+	} else if (*s == '{') {
+		s_val = s + 1;
+		s1 = strrchr(s_val, '}');
+		if (s1) *s1 = 0;
+		p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
+		len = 0;
+		p->strlist_value = calloc(1, sizeof *p->strlist_value);
+		while (*s_val++ == '\'') {
+			s = skip_nonquote(s_val);
+			if (*s) *s++ = 0;
+			p->strlist_value = realloc(p->strlist_value, (len + 2) * sizeof *p->strlist_value);
+			p->strlist_value[len] = strdup(s_val);
+			p->strlist_value[++len] = NULL;
+			s_val = skip_nonquote(s);
+		}
+	} else if (!strncmp(s, "true", 4)) {
+		s += 4;
+		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
+		p->bool_value = TRUE;
+	} else if (!strncmp(s, "false", 5)) {
+		s += 5;
+		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
+		p->bool_value = FALSE;
+	} else if ((s1 = skip_number(s)) != s) {
+		if (strstr(s1, "(int)")) {
+			*s1++ = 0;
+			p->type = LIBHAL_PROPERTY_TYPE_INT32;
+			p->int_value = strtol(s, NULL, 10);;
+		} else if (strstr(s1, "(uint64)")) {
+			*s1++ = 0;
+			p->type = LIBHAL_PROPERTY_TYPE_UINT64;
+			p->uint64_value = strtoull(s, NULL, 10);
+		} else if (strstr(s1, "(double)")) {
+			p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
+			p->double_value = strtod(s, NULL);
+		}
+
+		s = s1;
+	}
+
+	if (p->type == LIBHAL_PROPERTY_TYPE_INVALID) {
+		free(p->key);
+		free(p);
+	} else {
+		p->next = *prop;
+		*prop = p;
+	}
+}
+
+
+int add_properties(LibHalContext *hal_ctx, new_dev_t *nd, lh_prop_t *prop)
+{
+	DBusError error;
+	lh_prop_t *p;
+	char *udi2 = NULL, *udi3 = NULL, **s;
+	LibHalPropertyType old_type;
+
+	dbus_error_init(&error);
+
+	for(p = prop; p; p = p->next) {
+		if (!strcmp(p->key, "udi") && p->type == LIBHAL_PROPERTY_TYPE_STRING) {
+			udi2 = p->str_value;
+			continue;
+		}
+
+		old_type = libhal_device_get_property_type(hal_ctx, nd->real_udi, p->key, &error);
+		dbus_error_init(&error);
+
+		if (old_type != LIBHAL_PROPERTY_TYPE_INVALID &&
+		    ( p->type != old_type || p->type == LIBHAL_PROPERTY_TYPE_STRLIST)) {
+			if (!libhal_device_remove_property(hal_ctx, nd->real_udi, p->key, &error)) {
+				fprintf(stderr, "%s: %s\n", error.name, error.message);
+				return 41;
+			}
+		}
+
+		switch (p->type) {
+			case LIBHAL_PROPERTY_TYPE_INVALID:
+				break;
+			case LIBHAL_PROPERTY_TYPE_BOOLEAN:
+				if (!libhal_device_set_property_bool(hal_ctx, nd->real_udi, p->key, p->bool_value, &error)) {
+					fprintf(stderr, "%s: %s\n", error.name, error.message);
+					return 42;
+				}
+				break;
+			case LIBHAL_PROPERTY_TYPE_INT32:
+				if (!libhal_device_set_property_int(hal_ctx, nd->real_udi, p->key, p->int_value, &error)) {
+					fprintf(stderr, "%s: %s\n", error.name, error.message);
+					return 42;
+				}
+				break;
+			case LIBHAL_PROPERTY_TYPE_UINT64:
+				if (!libhal_device_set_property_uint64(hal_ctx, nd->real_udi, p->key, p->uint64_value, &error)) {
+					fprintf(stderr, "%s: %s\n", error.name, error.message);
+					return 42;
+				}
+				break;
+			case LIBHAL_PROPERTY_TYPE_DOUBLE:
+				if (!libhal_device_set_property_double(hal_ctx, nd->real_udi, p->key, p->double_value, &error)) {
+					fprintf(stderr, "%s: %s\n", error.name, error.message);
+					return 42;
+				}
+				break;
+			case LIBHAL_PROPERTY_TYPE_STRING:
+				if (!strcmp(p->key, "info.udi")) udi3 = p->str_value;
+				if (!libhal_device_set_property_string(hal_ctx, nd->real_udi, p->key, p->str_value, &error)) {
+					fprintf(stderr, "%s: %s\n", error.name, error.message);
+					return 42;
+				}
+				break;
+			case LIBHAL_PROPERTY_TYPE_STRLIST:
+				for(s = p->strlist_value; *s; s++) {
+					if (!libhal_device_property_strlist_append(hal_ctx, nd->real_udi, p->key, *s, &error)) {
+						fprintf(stderr, "%s: %s\n", error.name, error.message);
+						return 42;
+					}
+				}
+				break;
+		}
+	}
+
+	if (udi2) udi3 = NULL;
+	if (udi3) udi2 = udi3;
+
+	if (udi2 && !nd->udi)
+		nd->udi = strdup(udi2);
+
+	return 0;
+}
+
+
+lh_prop_t *free_properties(lh_prop_t *prop)
+{
+	lh_prop_t *next;
+	char **s;
+
+	for(; prop; prop = next) {
+		next = prop->next;
+
+		free(prop->key);
+		if (prop->type == LIBHAL_PROPERTY_TYPE_STRING) free(prop->str_value);
+		if (prop->type == LIBHAL_PROPERTY_TYPE_STRLIST && prop->strlist_value) {
+			for(s = prop->strlist_value; *s; ) free(*s++);
+			free(prop->strlist_value);
+		}
+		free(prop);
+	}
+
+	return NULL;
+}
-------------- next part --------------
_______________________________________________
hal mailing list
hal at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/hal


More information about the Hal mailing list