xref: /illumos-gate/usr/src/cmd/hal/addons/storage/addon-storage.c (revision 97ddcdce0091922bf2049977a3d42ba4fc0857a6)
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