118c2aff7Sartem /***************************************************************************
218c2aff7Sartem *
318c2aff7Sartem * addon-storage.c : watch removable media state changes
418c2aff7Sartem *
5d7c57852SGary Mills * Copyright 2017 Gary Mills
697ddcdceSArtem Kachitchkine * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
718c2aff7Sartem * Use is subject to license terms.
818c2aff7Sartem *
918c2aff7Sartem * Licensed under the Academic Free License version 2.1
1018c2aff7Sartem *
1118c2aff7Sartem **************************************************************************/
1218c2aff7Sartem
1318c2aff7Sartem #ifdef HAVE_CONFIG_H
1418c2aff7Sartem # include <config.h>
1518c2aff7Sartem #endif
1618c2aff7Sartem
1718c2aff7Sartem #include <errno.h>
1818c2aff7Sartem #include <string.h>
1918c2aff7Sartem #include <strings.h>
2018c2aff7Sartem #include <stdlib.h>
2118c2aff7Sartem #include <stdio.h>
2218c2aff7Sartem #include <sys/ioctl.h>
2318c2aff7Sartem #include <sys/types.h>
2418c2aff7Sartem #include <sys/stat.h>
2518c2aff7Sartem #include <sys/types.h>
2618c2aff7Sartem #include <sys/wait.h>
2718c2aff7Sartem #include <fcntl.h>
2818c2aff7Sartem #include <unistd.h>
2918c2aff7Sartem #include <sys/mnttab.h>
3018c2aff7Sartem #include <sys/dkio.h>
3118c2aff7Sartem #include <priv.h>
3297ddcdceSArtem Kachitchkine #include <libsysevent.h>
3397ddcdceSArtem Kachitchkine #include <sys/sysevent/dev.h>
3418c2aff7Sartem
3518c2aff7Sartem #include <libhal.h>
3618c2aff7Sartem
3718c2aff7Sartem #include "../../hald/logger.h"
3818c2aff7Sartem
3918c2aff7Sartem #define SLEEP_PERIOD 5
4018c2aff7Sartem
4197ddcdceSArtem Kachitchkine static char *udi;
4297ddcdceSArtem Kachitchkine static char *devfs_path;
4397ddcdceSArtem Kachitchkine LibHalContext *ctx = NULL;
4497ddcdceSArtem Kachitchkine static sysevent_handle_t *shp = NULL;
4597ddcdceSArtem Kachitchkine
4697ddcdceSArtem Kachitchkine static void sysevent_dev_handler(sysevent_t *);
4797ddcdceSArtem Kachitchkine
4818c2aff7Sartem static void
my_dbus_error_free(DBusError * error)4918c2aff7Sartem my_dbus_error_free(DBusError *error)
5018c2aff7Sartem {
5118c2aff7Sartem if (dbus_error_is_set(error)) {
5218c2aff7Sartem dbus_error_free(error);
5318c2aff7Sartem }
5418c2aff7Sartem }
5518c2aff7Sartem
5697ddcdceSArtem Kachitchkine static void
sysevent_init()5797ddcdceSArtem Kachitchkine sysevent_init ()
5897ddcdceSArtem Kachitchkine {
5997ddcdceSArtem Kachitchkine const char *subcl[1];
6097ddcdceSArtem Kachitchkine
6197ddcdceSArtem Kachitchkine shp = sysevent_bind_handle (sysevent_dev_handler);
6297ddcdceSArtem Kachitchkine if (shp == NULL) {
6397ddcdceSArtem Kachitchkine HAL_DEBUG (("sysevent_bind_handle failed %d", errno));
6497ddcdceSArtem Kachitchkine return;
6597ddcdceSArtem Kachitchkine }
6697ddcdceSArtem Kachitchkine
6797ddcdceSArtem Kachitchkine subcl[0] = ESC_DEV_EJECT_REQUEST;
6897ddcdceSArtem Kachitchkine if (sysevent_subscribe_event (shp, EC_DEV_STATUS, subcl, 1) != 0) {
6997ddcdceSArtem Kachitchkine HAL_INFO (("subscribe(dev_status) failed %d", errno));
7097ddcdceSArtem Kachitchkine sysevent_unbind_handle (shp);
7197ddcdceSArtem Kachitchkine return;
7297ddcdceSArtem Kachitchkine }
7397ddcdceSArtem Kachitchkine }
7497ddcdceSArtem Kachitchkine
7597ddcdceSArtem Kachitchkine static void
sysevent_fini()7697ddcdceSArtem Kachitchkine sysevent_fini ()
7797ddcdceSArtem Kachitchkine {
7897ddcdceSArtem Kachitchkine if (shp != NULL) {
7997ddcdceSArtem Kachitchkine sysevent_unbind_handle (shp);
8097ddcdceSArtem Kachitchkine shp = NULL;
8197ddcdceSArtem Kachitchkine }
8297ddcdceSArtem Kachitchkine }
8397ddcdceSArtem Kachitchkine
8497ddcdceSArtem Kachitchkine static void
sysevent_dev_handler(sysevent_t * ev)8597ddcdceSArtem Kachitchkine sysevent_dev_handler (sysevent_t *ev)
8697ddcdceSArtem Kachitchkine {
8797ddcdceSArtem Kachitchkine char *class;
8897ddcdceSArtem Kachitchkine char *subclass;
8997ddcdceSArtem Kachitchkine nvlist_t *attr_list;
9097ddcdceSArtem Kachitchkine char *phys_path, *path;
9197ddcdceSArtem Kachitchkine char *p;
9297ddcdceSArtem Kachitchkine int len;
9397ddcdceSArtem Kachitchkine DBusError error;
9497ddcdceSArtem Kachitchkine
9597ddcdceSArtem Kachitchkine if ((class = sysevent_get_class_name (ev)) == NULL)
9697ddcdceSArtem Kachitchkine return;
9797ddcdceSArtem Kachitchkine
9897ddcdceSArtem Kachitchkine if ((subclass = sysevent_get_subclass_name (ev)) == NULL)
9997ddcdceSArtem Kachitchkine return;
10097ddcdceSArtem Kachitchkine
10197ddcdceSArtem Kachitchkine if ((strcmp (class, EC_DEV_STATUS) != 0) ||
10297ddcdceSArtem Kachitchkine (strcmp (subclass, ESC_DEV_EJECT_REQUEST) != 0))
10397ddcdceSArtem Kachitchkine return;
10497ddcdceSArtem Kachitchkine
10597ddcdceSArtem Kachitchkine if (sysevent_get_attr_list (ev, &attr_list) != 0)
10697ddcdceSArtem Kachitchkine return;
10797ddcdceSArtem Kachitchkine
10897ddcdceSArtem Kachitchkine if (nvlist_lookup_string (attr_list, DEV_PHYS_PATH, &phys_path) != 0) {
10997ddcdceSArtem Kachitchkine goto out;
11097ddcdceSArtem Kachitchkine }
11197ddcdceSArtem Kachitchkine
11297ddcdceSArtem Kachitchkine /* see if event belongs to our LUN (ignore slice and "/devices" ) */
11397ddcdceSArtem Kachitchkine if (strncmp (phys_path, "/devices", sizeof ("/devices") - 1) == 0)
11497ddcdceSArtem Kachitchkine path = phys_path + sizeof ("/devices") - 1;
11597ddcdceSArtem Kachitchkine else
11697ddcdceSArtem Kachitchkine path = phys_path;
11797ddcdceSArtem Kachitchkine
11897ddcdceSArtem Kachitchkine if ((p = strrchr (path, ':')) == NULL)
11997ddcdceSArtem Kachitchkine goto out;
12097ddcdceSArtem Kachitchkine len = (uintptr_t)p - (uintptr_t)path;
12197ddcdceSArtem Kachitchkine if (strncmp (path, devfs_path, len) != 0)
12297ddcdceSArtem Kachitchkine goto out;
12397ddcdceSArtem Kachitchkine
12497ddcdceSArtem Kachitchkine HAL_DEBUG (("sysevent_dev_handler %s %s", subclass, phys_path));
12597ddcdceSArtem Kachitchkine
12697ddcdceSArtem Kachitchkine /* we got it, tell the world */
12797ddcdceSArtem Kachitchkine dbus_error_init (&error);
12897ddcdceSArtem Kachitchkine libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
12997ddcdceSArtem Kachitchkine dbus_error_free (&error);
13097ddcdceSArtem Kachitchkine
13197ddcdceSArtem Kachitchkine out:
13297ddcdceSArtem Kachitchkine nvlist_free(attr_list);
13397ddcdceSArtem Kachitchkine }
13497ddcdceSArtem Kachitchkine
13518c2aff7Sartem static void
force_unmount(LibHalContext * ctx,const char * udi)13618c2aff7Sartem force_unmount (LibHalContext *ctx, const char *udi)
13718c2aff7Sartem {
13818c2aff7Sartem DBusError error;
13918c2aff7Sartem DBusMessage *msg = NULL;
14018c2aff7Sartem DBusMessage *reply = NULL;
14118c2aff7Sartem char **options = NULL;
14218c2aff7Sartem unsigned int num_options = 0;
14318c2aff7Sartem DBusConnection *dbus_connection;
14418c2aff7Sartem char *device_file;
14518c2aff7Sartem
14618c2aff7Sartem dbus_error_init (&error);
14718c2aff7Sartem
14818c2aff7Sartem dbus_connection = libhal_ctx_get_dbus_connection (ctx);
14918c2aff7Sartem
15018c2aff7Sartem msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
15118c2aff7Sartem "org.freedesktop.Hal.Device.Volume",
15218c2aff7Sartem "Unmount");
15318c2aff7Sartem if (msg == NULL) {
15418c2aff7Sartem HAL_DEBUG (("Could not create dbus message for %s", udi));
15518c2aff7Sartem goto out;
15618c2aff7Sartem }
15718c2aff7Sartem
15818c2aff7Sartem
15918c2aff7Sartem options = calloc (1, sizeof (char *));
16018c2aff7Sartem if (options == NULL) {
16118c2aff7Sartem HAL_DEBUG (("Could not allocate options array"));
16218c2aff7Sartem goto out;
16318c2aff7Sartem }
16418c2aff7Sartem
16518c2aff7Sartem device_file = libhal_device_get_property_string (ctx, udi, "block.device", &error);
16618c2aff7Sartem if (device_file != NULL) {
16718c2aff7Sartem libhal_free_string (device_file);
16818c2aff7Sartem }
16918c2aff7Sartem dbus_error_free (&error);
17018c2aff7Sartem
171*55fea89dSDan Cross if (!dbus_message_append_args (msg,
17218c2aff7Sartem DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
17318c2aff7Sartem DBUS_TYPE_INVALID)) {
17418c2aff7Sartem HAL_DEBUG (("Could not append args to dbus message for %s", udi));
17518c2aff7Sartem goto out;
17618c2aff7Sartem }
177*55fea89dSDan Cross
17818c2aff7Sartem if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
17918c2aff7Sartem HAL_DEBUG (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
18018c2aff7Sartem goto out;
18118c2aff7Sartem }
18218c2aff7Sartem
18318c2aff7Sartem if (dbus_error_is_set (&error)) {
18418c2aff7Sartem HAL_DEBUG (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
18518c2aff7Sartem goto out;
18618c2aff7Sartem }
18718c2aff7Sartem
18818c2aff7Sartem HAL_DEBUG (("Succesfully unmounted udi '%s'", udi));
18918c2aff7Sartem
19018c2aff7Sartem out:
19118c2aff7Sartem dbus_error_free (&error);
19218c2aff7Sartem if (options != NULL)
19318c2aff7Sartem free (options);
19418c2aff7Sartem if (msg != NULL)
19518c2aff7Sartem dbus_message_unref (msg);
19618c2aff7Sartem if (reply != NULL)
19718c2aff7Sartem dbus_message_unref (reply);
19818c2aff7Sartem }
19918c2aff7Sartem
200*55fea89dSDan Cross static void
unmount_childs(LibHalContext * ctx,const char * udi)20118c2aff7Sartem unmount_childs (LibHalContext *ctx, const char *udi)
20218c2aff7Sartem {
20318c2aff7Sartem DBusError error;
20418c2aff7Sartem int num_volumes;
20518c2aff7Sartem char **volumes;
20618c2aff7Sartem
20718c2aff7Sartem dbus_error_init (&error);
20818c2aff7Sartem
20918c2aff7Sartem /* need to force unmount all partitions */
21018c2aff7Sartem if ((volumes = libhal_manager_find_device_string_match (
21118c2aff7Sartem ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
21218c2aff7Sartem dbus_error_free (&error);
21318c2aff7Sartem int i;
21418c2aff7Sartem
21518c2aff7Sartem for (i = 0; i < num_volumes; i++) {
21618c2aff7Sartem char *vol_udi;
21718c2aff7Sartem
21818c2aff7Sartem vol_udi = volumes[i];
21918c2aff7Sartem if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
22018c2aff7Sartem dbus_error_free (&error);
22118c2aff7Sartem if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
22218c2aff7Sartem dbus_error_free (&error);
22318c2aff7Sartem HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
22418c2aff7Sartem force_unmount (ctx, vol_udi);
22518c2aff7Sartem }
22618c2aff7Sartem }
22718c2aff7Sartem }
22818c2aff7Sartem libhal_free_string_array (volumes);
22918c2aff7Sartem }
23018c2aff7Sartem my_dbus_error_free (&error);
23118c2aff7Sartem }
23218c2aff7Sartem
23318c2aff7Sartem /** Check if a filesystem on a special device file is mounted
23418c2aff7Sartem *
23518c2aff7Sartem * @param device_file Special device file, e.g. /dev/cdrom
23618c2aff7Sartem * @return TRUE iff there is a filesystem system mounted
23718c2aff7Sartem * on the special device file
23818c2aff7Sartem */
23918c2aff7Sartem static dbus_bool_t
is_mounted(const char * device_file)24018c2aff7Sartem is_mounted (const char *device_file)
24118c2aff7Sartem {
24218c2aff7Sartem FILE *f;
24318c2aff7Sartem dbus_bool_t rc = FALSE;
24418c2aff7Sartem struct mnttab mp;
24518c2aff7Sartem struct mnttab mpref;
24618c2aff7Sartem
24718c2aff7Sartem if ((f = fopen ("/etc/mnttab", "r")) == NULL)
24818c2aff7Sartem return rc;
24918c2aff7Sartem
25018c2aff7Sartem bzero(&mp, sizeof (mp));
25118c2aff7Sartem bzero(&mpref, sizeof (mpref));
25218c2aff7Sartem mpref.mnt_special = (char *)device_file;
25318c2aff7Sartem if (getmntany(f, &mp, &mpref) == 0) {
25418c2aff7Sartem rc = TRUE;
25518c2aff7Sartem }
25618c2aff7Sartem
25718c2aff7Sartem fclose (f);
25818c2aff7Sartem return rc;
25918c2aff7Sartem }
26018c2aff7Sartem
26118c2aff7Sartem void
close_device(int * fd)26218c2aff7Sartem close_device (int *fd)
26318c2aff7Sartem {
26418c2aff7Sartem if (*fd > 0) {
26518c2aff7Sartem close (*fd);
26618c2aff7Sartem *fd = -1;
26718c2aff7Sartem }
26818c2aff7Sartem }
26918c2aff7Sartem
27018c2aff7Sartem void
drop_privileges()27118c2aff7Sartem drop_privileges ()
27218c2aff7Sartem {
27318c2aff7Sartem priv_set_t *pPrivSet = NULL;
27418c2aff7Sartem priv_set_t *lPrivSet = NULL;
27518c2aff7Sartem
27618c2aff7Sartem /*
27718c2aff7Sartem * Start with the 'basic' privilege set and then remove any
27818c2aff7Sartem * of the 'basic' privileges that will not be needed.
27918c2aff7Sartem */
28018c2aff7Sartem if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
28118c2aff7Sartem return;
28218c2aff7Sartem }
28318c2aff7Sartem
28418c2aff7Sartem /* Clear privileges we will not need from the 'basic' set */
28518c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
28618c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_INFO);
28718c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
28818c2aff7Sartem
28918c2aff7Sartem /* to open logindevperm'd devices */
29018c2aff7Sartem (void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ);
29118c2aff7Sartem
29297ddcdceSArtem Kachitchkine /* to receive sysevents */
29397ddcdceSArtem Kachitchkine (void) priv_addset(pPrivSet, PRIV_SYS_CONFIG);
29497ddcdceSArtem Kachitchkine
29518c2aff7Sartem /* Set the permitted privilege set. */
29618c2aff7Sartem if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
29718c2aff7Sartem return;
29818c2aff7Sartem }
29918c2aff7Sartem
30018c2aff7Sartem /* Clear the limit set. */
30118c2aff7Sartem if ((lPrivSet = priv_allocset()) == NULL) {
30218c2aff7Sartem return;
30318c2aff7Sartem }
30418c2aff7Sartem
30518c2aff7Sartem priv_emptyset(lPrivSet);
30618c2aff7Sartem
30718c2aff7Sartem if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
30818c2aff7Sartem return;
30918c2aff7Sartem }
31018c2aff7Sartem
31118c2aff7Sartem priv_freeset(lPrivSet);
31218c2aff7Sartem }
31318c2aff7Sartem
314*55fea89dSDan Cross int
main(int argc,char * argv[])31518c2aff7Sartem main (int argc, char *argv[])
31618c2aff7Sartem {
31718c2aff7Sartem char *device_file, *raw_device_file;
31818c2aff7Sartem DBusError error;
31918c2aff7Sartem char *bus;
32018c2aff7Sartem char *drive_type;
32118c2aff7Sartem int state, last_state;
32218c2aff7Sartem int fd = -1;
32318c2aff7Sartem
32418c2aff7Sartem if ((udi = getenv ("UDI")) == NULL)
32518c2aff7Sartem goto out;
32618c2aff7Sartem if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
32718c2aff7Sartem goto out;
32818c2aff7Sartem if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL)
32918c2aff7Sartem goto out;
33018c2aff7Sartem if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
33118c2aff7Sartem goto out;
33218c2aff7Sartem if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
33318c2aff7Sartem goto out;
33497ddcdceSArtem Kachitchkine if ((devfs_path = getenv ("HAL_PROP_SOLARIS_DEVFS_PATH")) == NULL)
33597ddcdceSArtem Kachitchkine goto out;
33618c2aff7Sartem
33718c2aff7Sartem drop_privileges ();
33818c2aff7Sartem
33918c2aff7Sartem setup_logger ();
34018c2aff7Sartem
34197ddcdceSArtem Kachitchkine sysevent_init ();
34297ddcdceSArtem Kachitchkine
34318c2aff7Sartem dbus_error_init (&error);
34418c2aff7Sartem
34518c2aff7Sartem if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
34618c2aff7Sartem goto out;
34718c2aff7Sartem }
34818c2aff7Sartem my_dbus_error_free (&error);
34918c2aff7Sartem
35018c2aff7Sartem if (!libhal_device_addon_is_ready (ctx, udi, &error)) {
35118c2aff7Sartem goto out;
35218c2aff7Sartem }
35318c2aff7Sartem my_dbus_error_free (&error);
35418c2aff7Sartem
35518c2aff7Sartem printf ("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)\n", device_file, bus, drive_type, udi);
35618c2aff7Sartem
35718c2aff7Sartem last_state = state = DKIO_NONE;
35818c2aff7Sartem
35918c2aff7Sartem /* Linux version of this addon attempts to re-open the device O_EXCL
36018c2aff7Sartem * every 2 seconds, trying to figure out if some other app,
36118c2aff7Sartem * like a cd burner, is using the device. Aside from questionable
36218c2aff7Sartem * value of this (apps should use HAL's locked property or/and
36318c2aff7Sartem * Solaris in_use facility), but also frequent opens/closes
36418c2aff7Sartem * keeps media constantly spun up. All this needs more thought.
36518c2aff7Sartem */
36618c2aff7Sartem for (;;) {
36718c2aff7Sartem if (is_mounted (device_file)) {
36818c2aff7Sartem close_device (&fd);
36918c2aff7Sartem sleep (SLEEP_PERIOD);
37018c2aff7Sartem } else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) {
37118c2aff7Sartem HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno)));
37218c2aff7Sartem sleep (SLEEP_PERIOD);
37318c2aff7Sartem } else {
37418c2aff7Sartem /* Check if a disc is in the drive */
37518c2aff7Sartem /* XXX initial call always returns inserted
37618c2aff7Sartem * causing unnecessary rescan - optimize?
37718c2aff7Sartem */
37818c2aff7Sartem if (ioctl (fd, DKIOCSTATE, &state) == 0) {
37918c2aff7Sartem if (state == last_state) {
38018c2aff7Sartem HAL_DEBUG (("state has not changed %d %s", state, device_file));
38118c2aff7Sartem continue;
38218c2aff7Sartem } else {
38318c2aff7Sartem HAL_DEBUG (("new state %d %s", state, device_file));
38418c2aff7Sartem }
38518c2aff7Sartem
38618c2aff7Sartem switch (state) {
38718c2aff7Sartem case DKIO_EJECTED:
38818c2aff7Sartem HAL_DEBUG (("Media removal detected on %s", device_file));
38918c2aff7Sartem last_state = state;
39018c2aff7Sartem
39118c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
39218c2aff7Sartem my_dbus_error_free (&error);
39318c2aff7Sartem
39418c2aff7Sartem /* attempt to unmount all childs */
39518c2aff7Sartem unmount_childs (ctx, udi);
39618c2aff7Sartem
39718c2aff7Sartem /* could have a fs on the main block device; do a rescan to remove it */
39818c2aff7Sartem libhal_device_rescan (ctx, udi, &error);
39918c2aff7Sartem my_dbus_error_free (&error);
40018c2aff7Sartem break;
40118c2aff7Sartem
40218c2aff7Sartem case DKIO_INSERTED:
40318c2aff7Sartem HAL_DEBUG (("Media insertion detected on %s", device_file));
40418c2aff7Sartem last_state = state;
40518c2aff7Sartem
40618c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
40718c2aff7Sartem my_dbus_error_free (&error);
40818c2aff7Sartem
40918c2aff7Sartem /* could have a fs on the main block device; do a rescan to add it */
41018c2aff7Sartem libhal_device_rescan (ctx, udi, &error);
41118c2aff7Sartem my_dbus_error_free (&error);
41218c2aff7Sartem break;
41318c2aff7Sartem
41418c2aff7Sartem case DKIO_DEV_GONE:
41518c2aff7Sartem HAL_DEBUG (("Device gone detected on %s", device_file));
41618c2aff7Sartem last_state = state;
41718c2aff7Sartem
41818c2aff7Sartem unmount_childs (ctx, udi);
41918c2aff7Sartem close_device (&fd);
42018c2aff7Sartem goto out;
42118c2aff7Sartem
42218c2aff7Sartem case DKIO_NONE:
42318c2aff7Sartem default:
42418c2aff7Sartem break;
42518c2aff7Sartem }
42618c2aff7Sartem } else {
42718c2aff7Sartem HAL_DEBUG (("DKIOCSTATE failed: %s\n", strerror(errno)));
42818c2aff7Sartem sleep (SLEEP_PERIOD);
42918c2aff7Sartem }
43018c2aff7Sartem }
43118c2aff7Sartem }
43218c2aff7Sartem
43318c2aff7Sartem out:
43497ddcdceSArtem Kachitchkine sysevent_fini ();
43518c2aff7Sartem if (ctx != NULL) {
43618c2aff7Sartem my_dbus_error_free (&error);
43718c2aff7Sartem libhal_ctx_shutdown (ctx, &error);
43818c2aff7Sartem libhal_ctx_free (ctx);
43918c2aff7Sartem }
44018c2aff7Sartem
44118c2aff7Sartem return 0;
44218c2aff7Sartem }
443