Beispiel #1
0
GSList *
hal_device_store_match_multiple_key_value_string (HalDeviceStore *store,
						  const char *key,
						  const char *value)
{
	GSList *iter;
	GSList *matches = NULL;

	g_return_val_if_fail (store != NULL, NULL);
	g_return_val_if_fail (key != NULL, NULL);
	g_return_val_if_fail (value != NULL, NULL);

	for (iter = store->devices; iter != NULL; iter = iter->next) {
		HalDevice *d = HAL_DEVICE (iter->data);
		int type;

		if (!hal_device_has_property (d, key))
			continue;

		type = hal_device_property_get_type (d, key);
		if (type != HAL_PROPERTY_TYPE_STRING)
			continue;

		if (strcmp (hal_device_property_get_string (d, key),
			    value) == 0)
			matches = g_slist_prepend (matches, d);
	}

	return matches;
}
Beispiel #2
0
static void
hf_volume_device_update_mount_properties (HalDevice *device,
					  const struct statfs *mounts,
					  int n_mounts)
{
  const struct statfs *mount = NULL;

  g_return_if_fail(HAL_IS_DEVICE(device));

  if (mounts)
    {
      const char *special;

      special = hal_device_property_get_string(device, "block.device");
      if (special)
	{
	  mount = hf_volume_mounts_find(mounts, n_mounts, special);
          if (mount && strcmp(special, mount->f_mntfromname))
            hal_device_property_set_string(device, "volume.freebsd.real_mounted_device", mount->f_mntfromname);
	  else
	    hal_device_property_remove(device, "volume.freebsd.real_mounted_device");
	}
    }

  hal_device_property_set_bool(device, "volume.is_mounted", mount != NULL);
  hal_device_property_set_bool(device, "volume.is_mounted_read_only", mount && (mount->f_flags & MNT_RDONLY) != 0);
  hal_device_property_set_string(device, "volume.mount_point", mount ? mount->f_mntonname : NULL);
}
Beispiel #3
0
/* generate hotplug event for each device in this branch */
void
devinfo_remove_branch (gchar *devfs_path, HalDevice *d)
{
	GSList *i;
	GSList *children;
	HalDevice *child;
	char *child_devfs_path;

	if (d == NULL) {
		d = hal_device_store_match_key_value_string (hald_get_gdl (),
			"solaris.devfs_path", devfs_path);
		if (d == NULL)
			return;
	}

	HAL_INFO (("remove_branch: %s %s\n", devfs_path, hal_device_get_udi (d)));

	/* first remove children */
	children = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
		"info.parent", hal_device_get_udi (d));
        for (i = children; i != NULL; i = g_slist_next (i)) {
                child = HAL_DEVICE (i->data);
		HAL_INFO (("remove_branch: child %s\n", hal_device_get_udi (child)));
		devinfo_remove_branch ((gchar *)hal_device_property_get_string (child, "solaris.devfs_path"), child);
	}
	g_slist_free (children);
	HAL_INFO (("remove_branch: done with children"));

	/* then remove self */
	HAL_INFO (("remove_branch: queueing %s", devfs_path));
	devinfo_remove_enqueue (devfs_path, NULL);
}
Beispiel #4
0
static void
hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d)
{
	HalDevice *parent;
	const gchar *parent_udi;
	void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *);

	if (d != NULL) {
		/* XXX */
		HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path));

		goto out;
	}

	/* find parent */
	parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent");
	if (parent_udi == NULL || strlen(parent_udi) == 0) {
		parent = NULL;
	} else {
		parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi);
	}
	/* only root node is allowed to be orphan */
	if (parent == NULL) {
		if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) {
			HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>"));

			goto out;
		}
	}

	/* children of ignored parent should be ignored */
	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
		HAL_INFO (("parent ignored %s", parent_udi));

		goto out;
	}

	/* custom or generic add function */
	begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add;
	if (begin_add_func == NULL) {
		begin_add_func = hotplug_event_begin_add_devinfo;
	}
	begin_add_func (hotplug_event->d, 
			 parent,
			 hotplug_event->un.devfs.handler, 
			 (void *) hotplug_event);
	 return;

out:
	g_object_unref (hotplug_event->d);
	hotplug_event_end ((void *) hotplug_event);

	return;
}
Beispiel #5
0
HalDevice *
devinfo_audio_dsp_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
{
	HalDevice *d = NULL;
	char *device_file, *parent_udi, *card_id, *device_id;
	int16_t unit;

	if (strstr (devnode, "oss_dsp_") != devnode)
		return NULL;

	d = hal_device_new ();

	devinfo_set_default_properties (d, parent, devnode, devfs_path);
	hal_device_add_capability (d, "oss");
	hal_device_property_set_string (d, "info.category", "oss");
	hal_device_property_set_string (d, "info.subsystem", "sound");

	card_id = hal_device_property_get_string (parent, "sound.card_id");
	hal_device_property_set_string (d, "oss.card_id", card_id);
	unit = hal_device_property_get_int (parent, "sound.card");
	hal_device_property_set_int (d, "oss.card", unit);
	hal_device_property_set_int (d, "oss.device", unit);
	device_id = hal_device_property_get_string (parent, "netbsd.sound.hardware");
	hal_device_property_set_string (d, "oss.device_id", device_id);
	hal_device_property_set_string (d, "oss.type", "pcm");

	device_file = g_strdup_printf (_PATH_SOUND "%d", unit);
	hal_device_property_set_string (d, "oss.device_file", device_file);
	g_free (device_file);

	parent_udi = hal_device_property_get_string (parent, "info.udi");
	if (parent_udi)
		hal_device_property_set_string (d, "sound.originating_device", parent_udi);

	devinfo_add_enqueue (d, devfs_path, &devinfo_audio_dsp_handler);

	return d;
}
Beispiel #6
0
void
devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path)
{
	char	*driver_name, *s;
	const char *s1;
	char	udi[HAL_PATH_MAX];

	if (parent != NULL) {
		hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent));
	} else {
		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local");
	}

	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
				"/org/freedesktop/Hal/devices%s_%d",
				devfs_path,
				di_instance (node));
	hal_device_set_udi (d, udi);
	hal_device_property_set_string (d, "info.udi", udi);

	if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) {
		hal_device_property_set_string (d, "info.product", s);
	} else {
		hal_device_property_set_string (d, "info.product", di_node_name (node));
	}

	hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);

	if ((driver_name = di_driver_name (node)) != NULL) {
		hal_device_property_set_string (d, "info.solaris.driver",
						driver_name);
	}


	/* inherit parent's claim attributes */
	if (hal_device_property_get_bool (parent, "info.claimed")) {
		s1 = hal_device_property_get_string (parent, "info.claimed.service");
		if (s1 != NULL) {
			hal_device_property_set_bool (d, "info.claimed", TRUE);
			hal_device_property_set_string (d, "info.claimed.service", s1);
		}
	}
}
Beispiel #7
0
static void
store_changed (HalDeviceStore *store, HalDevice *device,
	       gboolean added, gpointer user_data)
{
	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;

	if (!added)
		return;

	if (!hal_device_has_property (device, info->key))
		return;

	if (strcmp (hal_device_property_get_string (device, info->key),
		    info->value) != 0)
		return;

	info->callback (store, device, info->user_data);

	destroy_async_match_info (info);
}
Beispiel #8
0
HalDevice *
hal_device_store_match_key_value_string (HalDeviceStore *store,
					 const char *key,
					 const char *value)
{
	GSList *iter;
	GSList *devices;
	GHashTable *index;

	g_return_val_if_fail (store != NULL, NULL);
	g_return_val_if_fail (key != NULL, NULL);
	g_return_val_if_fail (value != NULL, NULL);

	index = g_hash_table_lookup (store->property_index, key);

	if (index) {
		devices = g_hash_table_lookup (index, value);
		if (devices)
			return (HalDevice*) devices->data;
		else
			return NULL;
	} else {
		for (iter = store->devices; iter != NULL; iter = iter->next) {
			HalDevice *d = HAL_DEVICE (iter->data);
			int type;

			if (!hal_device_has_property (d, key))
				continue;

			type = hal_device_property_get_type (d, key);
			if (type != HAL_PROPERTY_TYPE_STRING)
				continue;

			if (strcmp (hal_device_property_get_string (d, key),
				    value) == 0)
				return d;
		}
	}

	return NULL;
}
Beispiel #9
0
static gboolean
hf_net_update_timeout_cb (gpointer data)
{
  GSList *l;

  if (hf_is_waiting)
    return TRUE;

  HF_LIST_FOREACH(l, hald_get_gdl()->devices)
    {
      HalDevice *device = l->data;
      const char *interface;

      interface = hal_device_property_get_string(device, "net.interface");
      if (interface)
	{
	  device_property_atomic_update_begin();
	  hf_net_device_set_link_up(device, hf_net_get_link_up(interface));
	  device_property_atomic_update_end();
	}
    }
Beispiel #10
0
static void
drvctl_lofi_add(gchar *devfs_path, gchar *name)
{
	di_node_t node;
	const char *parent_udi;
	HalDevice *d, *parent;

	HAL_INFO (("lofi_add: %s %s", name, devfs_path));

	if ((d = hal_device_store_match_key_value_string (hald_get_gdl (),
	    "solaris.devfs_path", devfs_path)) == NULL) {
		HAL_INFO (("device not found in GDL %s", devfs_path));
		return;
	}
	parent_udi = hal_device_property_get_string (d, "info.parent");
	if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) {
		HAL_INFO (("parent not found in GDL %s", parent_udi));
		return;
	}
	if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (),
	    "info.udi", parent_udi)) == NULL) {
		HAL_INFO (("parent not found in GDL %s", parent_udi));
		return;
	}

	if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
		HAL_INFO (("device not found in devinfo %s", devfs_path));
		return;
	}

	HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi));
	devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d);

	di_fini (node);

	hotplug_event_process_queue ();
}
Beispiel #11
0
static void
property_index_modify_string (HalDeviceStore *store, HalDevice *device,
			      const char *key, gboolean added)
{
	GHashTable *index;
	const char *value;
	GSList *devices;

	value = hal_device_property_get_string (device, key);
	index = g_hash_table_lookup (store->property_index, key);

	if (!index) return;

	devices = g_hash_table_lookup (index, value);

	if (added) { /*add*/
		HAL_DEBUG (("adding %p to (%s,%s)", device, key, value));
		devices = g_slist_prepend (devices, device);
	} else { /*remove*/
		HAL_DEBUG (("removing %p from (%s,%s)", device, key, value));
		devices = g_slist_remove_all (devices, device);
	}
	g_hash_table_insert (index, (gpointer) value, devices);
}
Beispiel #12
0
static void
match_device_async (HalDeviceStore *store, HalDevice *device,
		    const char *key, gboolean removed, gboolean added,
		    gpointer user_data)
{
	AsyncMatchInfo *info = (AsyncMatchInfo *) user_data;

	/* Only want to do it for added or changed properties */
	if (removed)
		return;

	/* Keys have to match */
	if (strcmp (info->key, key) != 0)
		return;

	/* Values have to match */
	if (strcmp (hal_device_property_get_string (device, key),
		    info->value) != 0)
		return;

	info->callback (store, device, info->user_data);

	destroy_async_match_info (info);
}
Beispiel #13
0
HalDevice *
devinfo_audio_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
{
	HalDevice *d = NULL, *mixer, *dsp;
	prop_dictionary_t dict;
	const char *driver, *parent_udi;
	char *childnode;
	int16_t unit;
	char *audioctl;
	struct audio_device audiodev;
	int fd;

	if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL)
		return NULL;

	if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false ||
	    prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) {
		prop_object_release (dict);
		return NULL;
	}

	if (strcmp (driver, "audio") != 0) {
		prop_object_release (dict);
		return NULL;
	}

	audioctl = g_strdup_printf (_PATH_AUDIOCTL "%d", unit);
	fd = open (audioctl, O_RDONLY);
	if (fd < 0) {
		HAL_WARNING (("couldn't open %s: %s", audioctl, strerror(errno)));
		goto done;
	}

	if (ioctl (fd, AUDIO_GETDEV, &audiodev) == -1) {
		HAL_WARNING (("couldn't query %s: %s", audioctl, strerror(errno)));
		goto done;
	}

	d = hal_device_new ();

	devinfo_set_default_properties (d, parent, devnode, devfs_path);
	hal_device_add_capability (d, "sound");
	hal_device_property_set_string (d, "info.category", "sound");
	hal_device_property_set_string (d, "info.subsystem", "sound");

	hal_device_property_set_int (d, "sound.card", unit);
	hal_device_property_set_string (d, "sound.card_id", audiodev.name);
	hal_device_property_set_string (d, "netbsd.sound.hardware", audiodev.config);

	parent_udi = hal_device_property_get_string (parent, "info.udi");
	if (parent_udi)
		hal_device_property_set_string (d, "sound.originating_device", parent_udi);

	devinfo_add_enqueue (d, devfs_path, &devinfo_audio_handler);

	childnode = g_strdup_printf ("oss_mixer_%d", unit);
	devinfo_add_node (d, childnode);
	g_free (childnode);

	childnode = g_strdup_printf ("oss_dsp_%d", unit);
	devinfo_add_node (d, childnode);
	g_free (childnode);

done:
	if (dict)
		prop_object_release (dict);
	if (audioctl)
		g_free (audioctl);
	if (fd >= 0)
		close (fd);

	return d;
}
Beispiel #14
0
HalDevice *
devinfo_mass_disklabel_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
{
	HalDevice *d = NULL;
	struct disklabel label;
	struct partition *part;
	struct stat st;
	const char *driver;
	char *devpath, *rdevpath, *partname;
	char *childnode;
	char unit;
	struct volume_id *vid;
	uint64_t psize, msize;
	int i, fd;

	partname = devnode;
	unit = partname[strlen (partname) - 1] - 'a';

	if (unit >= MAXPARTITIONS)
		return NULL;

	devpath = g_strdup_printf ("/dev/%s", partname);
	rdevpath = g_strdup_printf ("/dev/r%s", partname);
	fd = open (rdevpath, O_RDONLY);
	if (fd < 0) {
		HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno)));
		g_free (rdevpath);
		return NULL;
	}

	if (ioctl (fd, DIOCGDINFO, &label) == -1) {
		HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno)));
		g_free (rdevpath);
		close (fd);
		return NULL;
	}
	part = &label.d_partitions[unit];

	d = hal_device_new ();

	devinfo_set_default_properties (d, parent, devnode, devfs_path);

	hal_device_add_capability (d, "block");
	hal_device_property_set_string (d, "info.subsystem", "block");
	hal_device_property_set_string (d, "info.category", "volume");
	hal_device_property_set_string (d, "block.device", devpath);
	hal_device_property_set_string (d, "block.storage_device",
	    hal_device_property_get_string (parent, "info.udi"));

	if (stat (devpath, &st) == 0) {
		hal_device_property_set_int (d, "block.major", major (st.st_rdev));
		hal_device_property_set_int (d, "block.minor", minor (st.st_rdev));
	}

	hal_device_property_set_bool (d, "block.is_volume", TRUE);
	hal_device_property_set_bool (d, "block.no_partitions", FALSE);
	hal_device_property_set_bool (d, "block.have_scanned", TRUE);

	hal_device_add_capability (d, "volume");
	hal_device_property_set_bool (d, "volume.ignore", FALSE);
	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
	hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
	hal_device_property_set_string (d, "volume.mount_point", "");
	hal_device_property_set_string (d, "volume.fsusage", "filesystem");
	hal_device_property_set_string (d, "volume.fstype", devinfo_mass_get_fstype (part->p_fstype));
	hal_device_property_set_bool (d, "volume.is_disc", FALSE);

	hal_device_property_set_string (d, "volume.label", "");
	hal_device_property_set_string (d, "volume.partition.label", "");
	hal_device_property_set_string (d, "volume.uuid", "");
	hal_device_property_set_string (d, "volume.partition.uuid", "");

	psize = (uint64_t)part->p_size * (uint64_t)label.d_secsize;
	msize = (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit;

	hal_device_property_set_uint64 (d, "volume.size", psize);
	hal_device_property_set_int (d, "volume.block_size", label.d_secsize);
	hal_device_property_set_uint64 (d, "volume.num_blocks", part->p_size);
	hal_device_property_set_uint64 (d, "volume.partition.media_size", msize);

	hal_device_property_set_bool (d, "volume.is_partition", TRUE);
	hal_device_property_set_int (d, "volume.partition.number", unit);
	hal_device_property_set_string (d, "volume.partition.scheme", "mbr");

	vid = volume_id_open_fd (fd);
	if (vid) {
		if (volume_id_probe_all (vid, 0, psize) == 0) {
			const char *type,*fstype;

			hal_device_property_set_string (d, "volume.label", vid->label);
			hal_device_property_set_string (d, "volume.partition.label", vid->label);
			hal_device_property_set_string (d, "volume.uuid", vid->uuid);
			hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid);

			if ( type && volume_id_get_type (vid, &type)) {
				fstype=devinfo_mass_get_fstype (part->p_fstype);
				if (strcmp (type, fstype)) {
					HAL_INFO (("%s disklabel reports [%s] but libvolume_id says it is "
					    "[%s], assuming disklabel is incorrect",
					    devpath, fstype, type));
					hal_device_property_set_string (d, "volume.fstype", type);
				}
			}
		}
		volume_id_close (vid);
	}

	devinfo_add_enqueue (d, devfs_path, &devinfo_mass_disklabel_handler);

	close (fd);

	g_free (rdevpath);
	g_free (devpath);

	return d;
}
Beispiel #15
0
HalDevice *
devinfo_mass_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
{
	HalDevice *d = NULL, *gparent = NULL;
	prop_dictionary_t dict;
	struct disklabel label;
	struct stat st;
	const char *driver;
	char *rdevpath, *devpath;
	char *childnode;
	char *parent_devnode, *gparent_devnode = NULL;
	char *gparent_udi;
	int16_t unit;
	int i, fd;
	struct scsipi_inquiry_data inqbuf;
	struct scsipi_inquiry cmd;
	bool scsiinq_status;
	char *storage_model = NULL, *storage_vendor = NULL;

	if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL)
		return NULL;

	if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false ||
	    prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) {
		prop_object_release (dict);
		return NULL;
	}

	if (strcmp (driver, "wd") != 0 && strcmp (driver, "sd") != 0 &&
	    strcmp (driver, "ld") != 0) {
		prop_object_release (dict);
		return NULL;
	}

	sleep (1);

	devpath = g_strdup_printf ("/dev/%s%c", devnode, RAW_PART + 'a');
	rdevpath = g_strdup_printf ("/dev/r%s%c", devnode, RAW_PART + 'a');
	HAL_INFO (("  going to open %s", rdevpath));
	fd = open (rdevpath, O_RDONLY);
	if (fd < 0) {
		HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno)));
		g_free (rdevpath);
		g_free (devpath);
		return NULL;
	}

	HAL_INFO (("  going to DIOCGDINFO %s", rdevpath));
	if (ioctl (fd, DIOCGDINFO, &label) == -1) {
		HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno)));
		g_free (rdevpath);
		g_free (devpath);
		close (fd);
		return NULL;
	}

	if (strcmp (driver, "sd") == 0) {
		memset(&cmd, 0, sizeof (cmd));
		memset(&inqbuf, 0, sizeof (inqbuf));
		cmd.opcode = INQUIRY;
		cmd.length = sizeof (inqbuf);

		scsiinq_status = scsi_command (fd, &cmd, sizeof (cmd), &inqbuf, sizeof (inqbuf), 10000, SCCMD_READ);
	} else
		scsiinq_status = false;

	close (fd);

	d = hal_device_new ();

	devinfo_set_default_properties (d, parent, devnode, devfs_path);

	hal_device_add_capability (d, "block");
	hal_device_property_set_string (d, "info.subsystem", "block");
	hal_device_property_set_string (d, "block.device", devpath);
	if (stat (devpath, &st) == 0) {
		hal_device_property_set_int (d, "block.major", major (st.st_rdev));
		hal_device_property_set_int (d, "block.minor", minor (st.st_rdev));
	}
	hal_device_property_set_bool (d, "block.is_volume", FALSE);
	hal_device_property_set_bool (d, "block.no_partitions", FALSE);
	hal_device_property_set_bool (d, "block.have_scanned", TRUE);

	hal_device_add_capability (d, "storage");
	hal_device_property_set_string (d, "info.category", "storage");
	parent_devnode = hal_device_property_get_string (parent, "netbsd.device");
	gparent_udi = hal_device_property_get_string (parent, "info.parent");
	if (gparent_udi) {
		gparent = hal_device_store_find (hald_get_gdl (), gparent_udi);
		if (gparent)
			gparent_devnode = hal_device_property_get_string (gparent, "netbsd.device");
	}
	if (gparent_devnode && strstr (gparent_devnode, "umass") == gparent_devnode)
		hal_device_property_set_string (d, "storage.bus", "usb");
	else if (parent_devnode && strstr (parent_devnode, "atabus") == parent_devnode)
		hal_device_property_set_string (d, "storage.bus", "ide");
	else
		hal_device_property_set_string (d, "storage.bus", "scsi");
	hal_device_property_set_string (d, "storage.device_type", "disk");
	hal_device_property_set_bool (d, "storage.removable", label.d_flags & D_REMOVABLE ? TRUE : FALSE);
	if (label.d_flags & D_REMOVABLE) {
		hal_device_property_set_bool (d, "storage.removable.media_available", TRUE);
		hal_device_property_set_uint64 (d, "storage.removable.media_size",
		    (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit);
		hal_device_property_set_uint64 (d, "storage.size", 0);
		hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
	} else {
		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
		hal_device_property_set_uint64 (d, "storage.size",
		    (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit);
		hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
		hal_device_property_set_bool (d, "storage.automount_enabled_hint", FALSE);
	}
	hal_device_property_set_bool (d, "storage.no_partitions_hint", FALSE);
	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
	hal_device_property_set_bool (d, "storage.removable.support_async_notification", FALSE);
	hal_device_property_set_string (d, "storage.partitioning_scheme", "mbr");
	hal_device_property_set_string (d, "storage.originating_device",
	    hal_device_property_get_string (d, "info.udi"));

	if (scsiinq_status == true) {
		storage_model = rtrim_copy(inqbuf.product, sizeof (inqbuf.product));
		storage_vendor = rtrim_copy(inqbuf.vendor, sizeof (inqbuf.vendor));
	}

	if (storage_model) {
		hal_device_property_set_string (d, "storage.model", storage_model);
		free (storage_model);
	} else
		hal_device_property_set_string (d, "storage.model", label.d_packname);

	if (storage_vendor) {
		hal_device_property_set_string (d, "storage.vendor", storage_vendor);
		free (storage_vendor);
	} else
		hal_device_property_set_string (d, "storage.vendor", label.d_typename);

	devinfo_add_enqueue (d, devfs_path, &devinfo_mass_handler);

	for (i = 0; i < MAXPARTITIONS; i++) {
		const char *fstype;

		fstype = devinfo_mass_get_fstype(label.d_partitions[i].p_fstype);
		if (fstype == NULL)
			continue;

		childnode = g_strdup_printf ("%s%c", devnode, 'a' + i);
		HAL_INFO (("  adding %s on %s", childnode, rdevpath));
		devinfo_mass_disklabel_add (d, childnode, childnode, childnode);
		g_free (childnode);
	}

	HAL_INFO (("  returning"));
	g_free (rdevpath);
	g_free (devpath);

done:
	prop_object_release (dict);

	return d;
}