18c2aff776a775d34a4c9893a4c72e0434d68e36artem/***************************************************************************
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * addon-storage.c : watch removable media state changes
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Use is subject to license terms.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Licensed under the Academic Free License version 2.1
18c2aff776a775d34a4c9893a4c72e0434d68e36artem **************************************************************************/
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "../../hald/logger.h"
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkinestatic void sysevent_dev_handler(sysevent_t *);
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine shp = sysevent_bind_handle (sysevent_dev_handler);
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine HAL_DEBUG (("sysevent_bind_handle failed %d", errno));
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if (sysevent_subscribe_event (shp, EC_DEV_STATUS, subcl, 1) != 0) {
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine HAL_INFO (("subscribe(dev_status) failed %d", errno));
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if ((class = sysevent_get_class_name (ev)) == NULL)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if ((subclass = sysevent_get_subclass_name (ev)) == NULL)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if ((strcmp (class, EC_DEV_STATUS) != 0) ||
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine (strcmp (subclass, ESC_DEV_EJECT_REQUEST) != 0))
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if (sysevent_get_attr_list (ev, &attr_list) != 0)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if (nvlist_lookup_string (attr_list, DEV_PHYS_PATH, &phys_path) != 0) {
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine /* see if event belongs to our LUN (ignore slice and "/devices" ) */
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if (strncmp (phys_path, "/devices", sizeof ("/devices") - 1) == 0)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine path = phys_path + sizeof ("/devices") - 1;
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if (strncmp (path, devfs_path, len) != 0)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine HAL_DEBUG (("sysevent_dev_handler %s %s", subclass, phys_path));
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine /* we got it, tell the world */
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem dbus_connection = libhal_ctx_get_dbus_connection (ctx);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "org.freedesktop.Hal.Device.Volume",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem "Unmount");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Could not create dbus message for %s", udi));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem device_file = libhal_device_get_property_string (ctx, udi, "block.device", &error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Could not append args to dbus message for %s", udi));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* need to force unmount all partitions */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((volumes = libhal_manager_find_device_string_match (
18c2aff776a775d34a4c9893a4c72e0434d68e36artem ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for (i = 0; i < num_volumes; i++) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/** Check if a filesystem on a special device file is mounted
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @param device_file Special device file, e.g. /dev/cdrom
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * @return TRUE iff there is a filesystem system mounted
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * on the special device file
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (*fd > 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Start with the 'basic' privilege set and then remove any
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * of the 'basic' privileges that will not be needed.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Clear privileges we will not need from the 'basic' set */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* to open logindevperm'd devices */
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine /* to receive sysevents */
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine (void) priv_addset(pPrivSet, PRIV_SYS_CONFIG);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Set the permitted privilege set. */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Clear the limit set. */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
97ddcdce0091922bf2049977a3d42ba4fc0857a6Artem Kachitchkine if ((devfs_path = getenv ("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!libhal_device_addon_is_ready (ctx, udi, &error)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem printf ("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)\n", device_file, bus, drive_type, udi);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Linux version of this addon attempts to re-open the device O_EXCL
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * every 2 seconds, trying to figure out if some other app,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * like a cd burner, is using the device. Aside from questionable
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * value of this (apps should use HAL's locked property or/and
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Solaris in_use facility), but also frequent opens/closes
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * keeps media constantly spun up. All this needs more thought.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno)));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* Check if a disc is in the drive */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* XXX initial call always returns inserted
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * causing unnecessary rescan - optimize?
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("state has not changed %d %s", state, device_file));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Media removal detected on %s", device_file));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* attempt to unmount all childs */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* could have a fs on the main block device; do a rescan to remove it */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Media insertion detected on %s", device_file));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem /* could have a fs on the main block device; do a rescan to add it */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("Device gone detected on %s", device_file));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem HAL_DEBUG (("DKIOCSTATE failed: %s\n", strerror(errno)));