118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * addon-storage.c : watch removable media state changes 418c2aff7Sartem * 5*97ddcdceSArtem Kachitchkine * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 618c2aff7Sartem * Use is subject to license terms. 718c2aff7Sartem * 818c2aff7Sartem * Licensed under the Academic Free License version 2.1 918c2aff7Sartem * 1018c2aff7Sartem **************************************************************************/ 1118c2aff7Sartem 1218c2aff7Sartem #ifdef HAVE_CONFIG_H 1318c2aff7Sartem # include <config.h> 1418c2aff7Sartem #endif 1518c2aff7Sartem 1618c2aff7Sartem #include <errno.h> 1718c2aff7Sartem #include <string.h> 1818c2aff7Sartem #include <strings.h> 1918c2aff7Sartem #include <stdlib.h> 2018c2aff7Sartem #include <stdio.h> 2118c2aff7Sartem #include <sys/ioctl.h> 2218c2aff7Sartem #include <sys/types.h> 2318c2aff7Sartem #include <sys/stat.h> 2418c2aff7Sartem #include <sys/types.h> 2518c2aff7Sartem #include <sys/wait.h> 2618c2aff7Sartem #include <fcntl.h> 2718c2aff7Sartem #include <unistd.h> 2818c2aff7Sartem #include <sys/mnttab.h> 2918c2aff7Sartem #include <sys/dkio.h> 3018c2aff7Sartem #include <priv.h> 31*97ddcdceSArtem Kachitchkine #include <libsysevent.h> 32*97ddcdceSArtem Kachitchkine #include <sys/sysevent/dev.h> 3318c2aff7Sartem 3418c2aff7Sartem #include <libhal.h> 3518c2aff7Sartem 3618c2aff7Sartem #include "../../hald/logger.h" 3718c2aff7Sartem 3818c2aff7Sartem #define SLEEP_PERIOD 5 3918c2aff7Sartem 40*97ddcdceSArtem Kachitchkine static char *udi; 41*97ddcdceSArtem Kachitchkine static char *devfs_path; 42*97ddcdceSArtem Kachitchkine LibHalContext *ctx = NULL; 43*97ddcdceSArtem Kachitchkine static sysevent_handle_t *shp = NULL; 44*97ddcdceSArtem Kachitchkine 45*97ddcdceSArtem Kachitchkine static void sysevent_dev_handler(sysevent_t *); 46*97ddcdceSArtem Kachitchkine 4718c2aff7Sartem static void 4818c2aff7Sartem my_dbus_error_free(DBusError *error) 4918c2aff7Sartem { 5018c2aff7Sartem if (dbus_error_is_set(error)) { 5118c2aff7Sartem dbus_error_free(error); 5218c2aff7Sartem } 5318c2aff7Sartem } 5418c2aff7Sartem 55*97ddcdceSArtem Kachitchkine static void 56*97ddcdceSArtem Kachitchkine sysevent_init () 57*97ddcdceSArtem Kachitchkine { 58*97ddcdceSArtem Kachitchkine const char *subcl[1]; 59*97ddcdceSArtem Kachitchkine 60*97ddcdceSArtem Kachitchkine shp = sysevent_bind_handle (sysevent_dev_handler); 61*97ddcdceSArtem Kachitchkine if (shp == NULL) { 62*97ddcdceSArtem Kachitchkine HAL_DEBUG (("sysevent_bind_handle failed %d", errno)); 63*97ddcdceSArtem Kachitchkine return; 64*97ddcdceSArtem Kachitchkine } 65*97ddcdceSArtem Kachitchkine 66*97ddcdceSArtem Kachitchkine subcl[0] = ESC_DEV_EJECT_REQUEST; 67*97ddcdceSArtem Kachitchkine if (sysevent_subscribe_event (shp, EC_DEV_STATUS, subcl, 1) != 0) { 68*97ddcdceSArtem Kachitchkine HAL_INFO (("subscribe(dev_status) failed %d", errno)); 69*97ddcdceSArtem Kachitchkine sysevent_unbind_handle (shp); 70*97ddcdceSArtem Kachitchkine return; 71*97ddcdceSArtem Kachitchkine } 72*97ddcdceSArtem Kachitchkine } 73*97ddcdceSArtem Kachitchkine 74*97ddcdceSArtem Kachitchkine static void 75*97ddcdceSArtem Kachitchkine sysevent_fini () 76*97ddcdceSArtem Kachitchkine { 77*97ddcdceSArtem Kachitchkine if (shp != NULL) { 78*97ddcdceSArtem Kachitchkine sysevent_unbind_handle (shp); 79*97ddcdceSArtem Kachitchkine shp = NULL; 80*97ddcdceSArtem Kachitchkine } 81*97ddcdceSArtem Kachitchkine } 82*97ddcdceSArtem Kachitchkine 83*97ddcdceSArtem Kachitchkine static void 84*97ddcdceSArtem Kachitchkine sysevent_dev_handler (sysevent_t *ev) 85*97ddcdceSArtem Kachitchkine { 86*97ddcdceSArtem Kachitchkine char *class; 87*97ddcdceSArtem Kachitchkine char *subclass; 88*97ddcdceSArtem Kachitchkine nvlist_t *attr_list; 89*97ddcdceSArtem Kachitchkine char *phys_path, *path; 90*97ddcdceSArtem Kachitchkine char *p; 91*97ddcdceSArtem Kachitchkine int len; 92*97ddcdceSArtem Kachitchkine DBusError error; 93*97ddcdceSArtem Kachitchkine 94*97ddcdceSArtem Kachitchkine if ((class = sysevent_get_class_name (ev)) == NULL) 95*97ddcdceSArtem Kachitchkine return; 96*97ddcdceSArtem Kachitchkine 97*97ddcdceSArtem Kachitchkine if ((subclass = sysevent_get_subclass_name (ev)) == NULL) 98*97ddcdceSArtem Kachitchkine return; 99*97ddcdceSArtem Kachitchkine 100*97ddcdceSArtem Kachitchkine if ((strcmp (class, EC_DEV_STATUS) != 0) || 101*97ddcdceSArtem Kachitchkine (strcmp (subclass, ESC_DEV_EJECT_REQUEST) != 0)) 102*97ddcdceSArtem Kachitchkine return; 103*97ddcdceSArtem Kachitchkine 104*97ddcdceSArtem Kachitchkine if (sysevent_get_attr_list (ev, &attr_list) != 0) 105*97ddcdceSArtem Kachitchkine return; 106*97ddcdceSArtem Kachitchkine 107*97ddcdceSArtem Kachitchkine if (nvlist_lookup_string (attr_list, DEV_PHYS_PATH, &phys_path) != 0) { 108*97ddcdceSArtem Kachitchkine goto out; 109*97ddcdceSArtem Kachitchkine } 110*97ddcdceSArtem Kachitchkine 111*97ddcdceSArtem Kachitchkine /* see if event belongs to our LUN (ignore slice and "/devices" ) */ 112*97ddcdceSArtem Kachitchkine if (strncmp (phys_path, "/devices", sizeof ("/devices") - 1) == 0) 113*97ddcdceSArtem Kachitchkine path = phys_path + sizeof ("/devices") - 1; 114*97ddcdceSArtem Kachitchkine else 115*97ddcdceSArtem Kachitchkine path = phys_path; 116*97ddcdceSArtem Kachitchkine 117*97ddcdceSArtem Kachitchkine if ((p = strrchr (path, ':')) == NULL) 118*97ddcdceSArtem Kachitchkine goto out; 119*97ddcdceSArtem Kachitchkine len = (uintptr_t)p - (uintptr_t)path; 120*97ddcdceSArtem Kachitchkine if (strncmp (path, devfs_path, len) != 0) 121*97ddcdceSArtem Kachitchkine goto out; 122*97ddcdceSArtem Kachitchkine 123*97ddcdceSArtem Kachitchkine HAL_DEBUG (("sysevent_dev_handler %s %s", subclass, phys_path)); 124*97ddcdceSArtem Kachitchkine 125*97ddcdceSArtem Kachitchkine /* we got it, tell the world */ 126*97ddcdceSArtem Kachitchkine dbus_error_init (&error); 127*97ddcdceSArtem Kachitchkine libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error); 128*97ddcdceSArtem Kachitchkine dbus_error_free (&error); 129*97ddcdceSArtem Kachitchkine 130*97ddcdceSArtem Kachitchkine out: 131*97ddcdceSArtem Kachitchkine nvlist_free(attr_list); 132*97ddcdceSArtem Kachitchkine } 133*97ddcdceSArtem Kachitchkine 13418c2aff7Sartem static void 13518c2aff7Sartem force_unmount (LibHalContext *ctx, const char *udi) 13618c2aff7Sartem { 13718c2aff7Sartem DBusError error; 13818c2aff7Sartem DBusMessage *msg = NULL; 13918c2aff7Sartem DBusMessage *reply = NULL; 14018c2aff7Sartem char **options = NULL; 14118c2aff7Sartem unsigned int num_options = 0; 14218c2aff7Sartem DBusConnection *dbus_connection; 14318c2aff7Sartem char *device_file; 14418c2aff7Sartem 14518c2aff7Sartem dbus_error_init (&error); 14618c2aff7Sartem 14718c2aff7Sartem dbus_connection = libhal_ctx_get_dbus_connection (ctx); 14818c2aff7Sartem 14918c2aff7Sartem msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi, 15018c2aff7Sartem "org.freedesktop.Hal.Device.Volume", 15118c2aff7Sartem "Unmount"); 15218c2aff7Sartem if (msg == NULL) { 15318c2aff7Sartem HAL_DEBUG (("Could not create dbus message for %s", udi)); 15418c2aff7Sartem goto out; 15518c2aff7Sartem } 15618c2aff7Sartem 15718c2aff7Sartem 15818c2aff7Sartem options = calloc (1, sizeof (char *)); 15918c2aff7Sartem if (options == NULL) { 16018c2aff7Sartem HAL_DEBUG (("Could not allocate options array")); 16118c2aff7Sartem goto out; 16218c2aff7Sartem } 16318c2aff7Sartem 16418c2aff7Sartem device_file = libhal_device_get_property_string (ctx, udi, "block.device", &error); 16518c2aff7Sartem if (device_file != NULL) { 16618c2aff7Sartem libhal_free_string (device_file); 16718c2aff7Sartem } 16818c2aff7Sartem dbus_error_free (&error); 16918c2aff7Sartem 17018c2aff7Sartem if (!dbus_message_append_args (msg, 17118c2aff7Sartem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options, 17218c2aff7Sartem DBUS_TYPE_INVALID)) { 17318c2aff7Sartem HAL_DEBUG (("Could not append args to dbus message for %s", udi)); 17418c2aff7Sartem goto out; 17518c2aff7Sartem } 17618c2aff7Sartem 17718c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) { 17818c2aff7Sartem HAL_DEBUG (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message)); 17918c2aff7Sartem goto out; 18018c2aff7Sartem } 18118c2aff7Sartem 18218c2aff7Sartem if (dbus_error_is_set (&error)) { 18318c2aff7Sartem HAL_DEBUG (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message)); 18418c2aff7Sartem goto out; 18518c2aff7Sartem } 18618c2aff7Sartem 18718c2aff7Sartem HAL_DEBUG (("Succesfully unmounted udi '%s'", udi)); 18818c2aff7Sartem 18918c2aff7Sartem out: 19018c2aff7Sartem dbus_error_free (&error); 19118c2aff7Sartem if (options != NULL) 19218c2aff7Sartem free (options); 19318c2aff7Sartem if (msg != NULL) 19418c2aff7Sartem dbus_message_unref (msg); 19518c2aff7Sartem if (reply != NULL) 19618c2aff7Sartem dbus_message_unref (reply); 19718c2aff7Sartem } 19818c2aff7Sartem 19918c2aff7Sartem static void 20018c2aff7Sartem unmount_childs (LibHalContext *ctx, const char *udi) 20118c2aff7Sartem { 20218c2aff7Sartem DBusError error; 20318c2aff7Sartem int num_volumes; 20418c2aff7Sartem char **volumes; 20518c2aff7Sartem 20618c2aff7Sartem dbus_error_init (&error); 20718c2aff7Sartem 20818c2aff7Sartem /* need to force unmount all partitions */ 20918c2aff7Sartem if ((volumes = libhal_manager_find_device_string_match ( 21018c2aff7Sartem ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) { 21118c2aff7Sartem dbus_error_free (&error); 21218c2aff7Sartem int i; 21318c2aff7Sartem 21418c2aff7Sartem for (i = 0; i < num_volumes; i++) { 21518c2aff7Sartem char *vol_udi; 21618c2aff7Sartem 21718c2aff7Sartem vol_udi = volumes[i]; 21818c2aff7Sartem if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) { 21918c2aff7Sartem dbus_error_free (&error); 22018c2aff7Sartem if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) { 22118c2aff7Sartem dbus_error_free (&error); 22218c2aff7Sartem HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi)); 22318c2aff7Sartem force_unmount (ctx, vol_udi); 22418c2aff7Sartem } 22518c2aff7Sartem } 22618c2aff7Sartem } 22718c2aff7Sartem libhal_free_string_array (volumes); 22818c2aff7Sartem } 22918c2aff7Sartem my_dbus_error_free (&error); 23018c2aff7Sartem } 23118c2aff7Sartem 23218c2aff7Sartem /** Check if a filesystem on a special device file is mounted 23318c2aff7Sartem * 23418c2aff7Sartem * @param device_file Special device file, e.g. /dev/cdrom 23518c2aff7Sartem * @return TRUE iff there is a filesystem system mounted 23618c2aff7Sartem * on the special device file 23718c2aff7Sartem */ 23818c2aff7Sartem static dbus_bool_t 23918c2aff7Sartem is_mounted (const char *device_file) 24018c2aff7Sartem { 24118c2aff7Sartem FILE *f; 24218c2aff7Sartem dbus_bool_t rc = FALSE; 24318c2aff7Sartem struct mnttab mp; 24418c2aff7Sartem struct mnttab mpref; 24518c2aff7Sartem 24618c2aff7Sartem if ((f = fopen ("/etc/mnttab", "r")) == NULL) 24718c2aff7Sartem return rc; 24818c2aff7Sartem 24918c2aff7Sartem bzero(&mp, sizeof (mp)); 25018c2aff7Sartem bzero(&mpref, sizeof (mpref)); 25118c2aff7Sartem mpref.mnt_special = (char *)device_file; 25218c2aff7Sartem if (getmntany(f, &mp, &mpref) == 0) { 25318c2aff7Sartem rc = TRUE; 25418c2aff7Sartem } 25518c2aff7Sartem 25618c2aff7Sartem fclose (f); 25718c2aff7Sartem return rc; 25818c2aff7Sartem } 25918c2aff7Sartem 26018c2aff7Sartem void 26118c2aff7Sartem close_device (int *fd) 26218c2aff7Sartem { 26318c2aff7Sartem if (*fd > 0) { 26418c2aff7Sartem close (*fd); 26518c2aff7Sartem *fd = -1; 26618c2aff7Sartem } 26718c2aff7Sartem } 26818c2aff7Sartem 26918c2aff7Sartem void 27018c2aff7Sartem drop_privileges () 27118c2aff7Sartem { 27218c2aff7Sartem priv_set_t *pPrivSet = NULL; 27318c2aff7Sartem priv_set_t *lPrivSet = NULL; 27418c2aff7Sartem 27518c2aff7Sartem /* 27618c2aff7Sartem * Start with the 'basic' privilege set and then remove any 27718c2aff7Sartem * of the 'basic' privileges that will not be needed. 27818c2aff7Sartem */ 27918c2aff7Sartem if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) { 28018c2aff7Sartem return; 28118c2aff7Sartem } 28218c2aff7Sartem 28318c2aff7Sartem /* Clear privileges we will not need from the 'basic' set */ 28418c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY); 28518c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_INFO); 28618c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_SESSION); 28718c2aff7Sartem 28818c2aff7Sartem /* to open logindevperm'd devices */ 28918c2aff7Sartem (void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ); 29018c2aff7Sartem 291*97ddcdceSArtem Kachitchkine /* to receive sysevents */ 292*97ddcdceSArtem Kachitchkine (void) priv_addset(pPrivSet, PRIV_SYS_CONFIG); 293*97ddcdceSArtem Kachitchkine 29418c2aff7Sartem /* Set the permitted privilege set. */ 29518c2aff7Sartem if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) { 29618c2aff7Sartem return; 29718c2aff7Sartem } 29818c2aff7Sartem 29918c2aff7Sartem /* Clear the limit set. */ 30018c2aff7Sartem if ((lPrivSet = priv_allocset()) == NULL) { 30118c2aff7Sartem return; 30218c2aff7Sartem } 30318c2aff7Sartem 30418c2aff7Sartem priv_emptyset(lPrivSet); 30518c2aff7Sartem 30618c2aff7Sartem if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) { 30718c2aff7Sartem return; 30818c2aff7Sartem } 30918c2aff7Sartem 31018c2aff7Sartem priv_freeset(lPrivSet); 31118c2aff7Sartem } 31218c2aff7Sartem 31318c2aff7Sartem int 31418c2aff7Sartem main (int argc, char *argv[]) 31518c2aff7Sartem { 31618c2aff7Sartem char *device_file, *raw_device_file; 31718c2aff7Sartem DBusError error; 31818c2aff7Sartem char *bus; 31918c2aff7Sartem char *drive_type; 32018c2aff7Sartem int state, last_state; 32118c2aff7Sartem char *support_media_changed_str; 32218c2aff7Sartem int support_media_changed; 32318c2aff7Sartem int fd = -1; 32418c2aff7Sartem 32518c2aff7Sartem if ((udi = getenv ("UDI")) == NULL) 32618c2aff7Sartem goto out; 32718c2aff7Sartem if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL) 32818c2aff7Sartem goto out; 32918c2aff7Sartem if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL) 33018c2aff7Sartem goto out; 33118c2aff7Sartem if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL) 33218c2aff7Sartem goto out; 33318c2aff7Sartem if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL) 33418c2aff7Sartem goto out; 335*97ddcdceSArtem Kachitchkine if ((devfs_path = getenv ("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL) 336*97ddcdceSArtem Kachitchkine goto out; 33718c2aff7Sartem 33818c2aff7Sartem drop_privileges (); 33918c2aff7Sartem 34018c2aff7Sartem setup_logger (); 34118c2aff7Sartem 342*97ddcdceSArtem Kachitchkine sysevent_init (); 343*97ddcdceSArtem Kachitchkine 34418c2aff7Sartem support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED"); 34518c2aff7Sartem if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0) 34618c2aff7Sartem support_media_changed = TRUE; 34718c2aff7Sartem else 34818c2aff7Sartem support_media_changed = FALSE; 34918c2aff7Sartem 35018c2aff7Sartem dbus_error_init (&error); 35118c2aff7Sartem 35218c2aff7Sartem if ((ctx = libhal_ctx_init_direct (&error)) == NULL) { 35318c2aff7Sartem goto out; 35418c2aff7Sartem } 35518c2aff7Sartem my_dbus_error_free (&error); 35618c2aff7Sartem 35718c2aff7Sartem if (!libhal_device_addon_is_ready (ctx, udi, &error)) { 35818c2aff7Sartem goto out; 35918c2aff7Sartem } 36018c2aff7Sartem my_dbus_error_free (&error); 36118c2aff7Sartem 36218c2aff7Sartem printf ("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)\n", device_file, bus, drive_type, udi); 36318c2aff7Sartem 36418c2aff7Sartem last_state = state = DKIO_NONE; 36518c2aff7Sartem 36618c2aff7Sartem /* Linux version of this addon attempts to re-open the device O_EXCL 36718c2aff7Sartem * every 2 seconds, trying to figure out if some other app, 36818c2aff7Sartem * like a cd burner, is using the device. Aside from questionable 36918c2aff7Sartem * value of this (apps should use HAL's locked property or/and 37018c2aff7Sartem * Solaris in_use facility), but also frequent opens/closes 37118c2aff7Sartem * keeps media constantly spun up. All this needs more thought. 37218c2aff7Sartem */ 37318c2aff7Sartem for (;;) { 37418c2aff7Sartem if (is_mounted (device_file)) { 37518c2aff7Sartem close_device (&fd); 37618c2aff7Sartem sleep (SLEEP_PERIOD); 37718c2aff7Sartem } else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) { 37818c2aff7Sartem HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno))); 37918c2aff7Sartem sleep (SLEEP_PERIOD); 38018c2aff7Sartem } else { 38118c2aff7Sartem /* Check if a disc is in the drive */ 38218c2aff7Sartem /* XXX initial call always returns inserted 38318c2aff7Sartem * causing unnecessary rescan - optimize? 38418c2aff7Sartem */ 38518c2aff7Sartem if (ioctl (fd, DKIOCSTATE, &state) == 0) { 38618c2aff7Sartem if (state == last_state) { 38718c2aff7Sartem HAL_DEBUG (("state has not changed %d %s", state, device_file)); 38818c2aff7Sartem continue; 38918c2aff7Sartem } else { 39018c2aff7Sartem HAL_DEBUG (("new state %d %s", state, device_file)); 39118c2aff7Sartem } 39218c2aff7Sartem 39318c2aff7Sartem switch (state) { 39418c2aff7Sartem case DKIO_EJECTED: 39518c2aff7Sartem HAL_DEBUG (("Media removal detected on %s", device_file)); 39618c2aff7Sartem last_state = state; 39718c2aff7Sartem 39818c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error); 39918c2aff7Sartem my_dbus_error_free (&error); 40018c2aff7Sartem 40118c2aff7Sartem /* attempt to unmount all childs */ 40218c2aff7Sartem unmount_childs (ctx, udi); 40318c2aff7Sartem 40418c2aff7Sartem /* could have a fs on the main block device; do a rescan to remove it */ 40518c2aff7Sartem libhal_device_rescan (ctx, udi, &error); 40618c2aff7Sartem my_dbus_error_free (&error); 40718c2aff7Sartem break; 40818c2aff7Sartem 40918c2aff7Sartem case DKIO_INSERTED: 41018c2aff7Sartem HAL_DEBUG (("Media insertion detected on %s", device_file)); 41118c2aff7Sartem last_state = state; 41218c2aff7Sartem 41318c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error); 41418c2aff7Sartem my_dbus_error_free (&error); 41518c2aff7Sartem 41618c2aff7Sartem /* could have a fs on the main block device; do a rescan to add it */ 41718c2aff7Sartem libhal_device_rescan (ctx, udi, &error); 41818c2aff7Sartem my_dbus_error_free (&error); 41918c2aff7Sartem break; 42018c2aff7Sartem 42118c2aff7Sartem case DKIO_DEV_GONE: 42218c2aff7Sartem HAL_DEBUG (("Device gone detected on %s", device_file)); 42318c2aff7Sartem last_state = state; 42418c2aff7Sartem 42518c2aff7Sartem unmount_childs (ctx, udi); 42618c2aff7Sartem close_device (&fd); 42718c2aff7Sartem goto out; 42818c2aff7Sartem 42918c2aff7Sartem case DKIO_NONE: 43018c2aff7Sartem default: 43118c2aff7Sartem break; 43218c2aff7Sartem } 43318c2aff7Sartem } else { 43418c2aff7Sartem HAL_DEBUG (("DKIOCSTATE failed: %s\n", strerror(errno))); 43518c2aff7Sartem sleep (SLEEP_PERIOD); 43618c2aff7Sartem } 43718c2aff7Sartem } 43818c2aff7Sartem } 43918c2aff7Sartem 44018c2aff7Sartem out: 441*97ddcdceSArtem Kachitchkine sysevent_fini (); 44218c2aff7Sartem if (ctx != NULL) { 44318c2aff7Sartem my_dbus_error_free (&error); 44418c2aff7Sartem libhal_ctx_shutdown (ctx, &error); 44518c2aff7Sartem libhal_ctx_free (ctx); 44618c2aff7Sartem } 44718c2aff7Sartem 44818c2aff7Sartem return 0; 44918c2aff7Sartem } 450