xref: /titanic_50/usr/src/cmd/rmvolmgr/rmvolmgr.c (revision 44991a1c1bb35cccb6bf99cb6dce14864dcee19c)
118c2aff7Sartem /*
218c2aff7Sartem  * CDDL HEADER START
318c2aff7Sartem  *
418c2aff7Sartem  * The contents of this file are subject to the terms of the
518c2aff7Sartem  * Common Development and Distribution License (the "License").
618c2aff7Sartem  * You may not use this file except in compliance with the License.
718c2aff7Sartem  *
818c2aff7Sartem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
918c2aff7Sartem  * or http://www.opensolaris.org/os/licensing.
1018c2aff7Sartem  * See the License for the specific language governing permissions
1118c2aff7Sartem  * and limitations under the License.
1218c2aff7Sartem  *
1318c2aff7Sartem  * When distributing Covered Code, include this CDDL HEADER in each
1418c2aff7Sartem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1518c2aff7Sartem  * If applicable, add the following below this CDDL HEADER, with the
1618c2aff7Sartem  * fields enclosed by brackets "[]" replaced with your own identifying
1718c2aff7Sartem  * information: Portions Copyright [yyyy] [name of copyright owner]
1818c2aff7Sartem  *
1918c2aff7Sartem  * CDDL HEADER END
2018c2aff7Sartem  */
2118c2aff7Sartem /*
22*97ddcdceSArtem Kachitchkine  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2318c2aff7Sartem  * Use is subject to license terms.
2418c2aff7Sartem  */
2518c2aff7Sartem 
2618c2aff7Sartem /*
2718c2aff7Sartem  * rmvolmgr daemon
2818c2aff7Sartem  */
2918c2aff7Sartem 
3018c2aff7Sartem #include <stdio.h>
3118c2aff7Sartem #include <stdlib.h>
3218c2aff7Sartem #include <sys/types.h>
3318c2aff7Sartem #include <sys/stat.h>
3418c2aff7Sartem #include <dirent.h>
3518c2aff7Sartem #include <signal.h>
3618c2aff7Sartem #include <unistd.h>
3718c2aff7Sartem #include <fcntl.h>
3818c2aff7Sartem #include <strings.h>
3918c2aff7Sartem #include <errno.h>
4018c2aff7Sartem #include <libintl.h>
4118c2aff7Sartem #include <sys/syscall.h>
4218c2aff7Sartem #include <libscf.h>
4318c2aff7Sartem #include <priv_utils.h>
4418c2aff7Sartem 
4518c2aff7Sartem #include <dbus/dbus.h>
4618c2aff7Sartem #include <dbus/dbus-glib.h>
4718c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
4818c2aff7Sartem #include <libhal.h>
4918c2aff7Sartem 
5018c2aff7Sartem #include "rmm_common.h"
5118c2aff7Sartem 
5218c2aff7Sartem char *progname = "rmvolmgr";
5318c2aff7Sartem 
5418c2aff7Sartem #define	RMVOLMGR_FMRI	"svc:/system/filesystem/rmvolmgr:default"
5518c2aff7Sartem 
5618c2aff7Sartem typedef struct managed_volume {
5718c2aff7Sartem 	char			*udi;
5818c2aff7Sartem 	boolean_t		my;
5918c2aff7Sartem 	struct action_arg	aa;
6018c2aff7Sartem } managed_volume_t;
6118c2aff7Sartem 
6218c2aff7Sartem static GSList		*managed_volumes;
6318c2aff7Sartem 
6418c2aff7Sartem static GMainLoop	*mainloop;
6518c2aff7Sartem static LibHalContext	*hal_ctx;
6618c2aff7Sartem static int		sigexit_pipe[2];
6718c2aff7Sartem static GIOChannel	*sigexit_ioch;
6818c2aff7Sartem 
6918c2aff7Sartem static boolean_t	opt_c;	/* disable CDE compatibility */
7018c2aff7Sartem static boolean_t	opt_n;	/* disable legacy mountpoint symlinks */
7118c2aff7Sartem static boolean_t	opt_s;	/* system instance */
7218c2aff7Sartem 
73*97ddcdceSArtem Kachitchkine /* SMF property "eject_button" */
74*97ddcdceSArtem Kachitchkine static boolean_t	rmm_prop_eject_button = B_TRUE;
75*97ddcdceSArtem Kachitchkine 
7618c2aff7Sartem static void	get_smf_properties();
7718c2aff7Sartem static void	rmm_device_added(LibHalContext *ctx, const char *udi);
7818c2aff7Sartem static void	rmm_device_removed(LibHalContext *ctx, const char *udi);
7918c2aff7Sartem static void	rmm_property_modified(LibHalContext *ctx, const char *udi,
8018c2aff7Sartem 		const char *key, dbus_bool_t is_removed, dbus_bool_t is_added);
81*97ddcdceSArtem Kachitchkine static void	rmm_device_condition(LibHalContext *ctx, const char *udi,
82*97ddcdceSArtem Kachitchkine 		const char *name, const char *detail);
8318c2aff7Sartem static void	rmm_mount_all();
8418c2aff7Sartem static void	rmm_unmount_all();
8518c2aff7Sartem static void	sigexit(int signo);
8618c2aff7Sartem static gboolean	sigexit_ioch_func(GIOChannel *source, GIOCondition condition,
8718c2aff7Sartem 		gpointer user_data);
8818c2aff7Sartem 
8918c2aff7Sartem static void
usage()9018c2aff7Sartem usage()
9118c2aff7Sartem {
9218c2aff7Sartem 	(void) fprintf(stderr, gettext("\nusage: rmvolmgr [-v]\n"));
9318c2aff7Sartem }
9418c2aff7Sartem 
9518c2aff7Sartem static int
rmvolmgr(int argc,char ** argv)9618c2aff7Sartem rmvolmgr(int argc, char **argv)
9718c2aff7Sartem {
9818c2aff7Sartem 	const char	*opts = "chnsv";
9918c2aff7Sartem 	DBusError	error;
10018c2aff7Sartem 	boolean_t	daemonize;
10118c2aff7Sartem 	rmm_error_t	rmm_error;
10218c2aff7Sartem 	int		c;
10318c2aff7Sartem 
10418c2aff7Sartem 	while ((c = getopt(argc, argv, opts)) != EOF) {
10518c2aff7Sartem 		switch (c) {
10618c2aff7Sartem 		case 'c':
10718c2aff7Sartem 			opt_c = B_TRUE;
10818c2aff7Sartem 			break;
10918c2aff7Sartem 		case 'n':
11018c2aff7Sartem 			opt_n = B_TRUE;
11118c2aff7Sartem 			break;
11218c2aff7Sartem 		case 's':
11318c2aff7Sartem 			opt_s = B_TRUE;
11418c2aff7Sartem 			break;
11518c2aff7Sartem 		case 'v':
11618c2aff7Sartem 			rmm_debug = 1;
11718c2aff7Sartem 			break;
11818c2aff7Sartem 		case '?':
11918c2aff7Sartem 		case 'h':
12018c2aff7Sartem 			usage();
12118c2aff7Sartem 			return (0);
12218c2aff7Sartem 		default:
12318c2aff7Sartem 			usage();
12418c2aff7Sartem 			return (1);
12518c2aff7Sartem 		}
12618c2aff7Sartem 	}
12718c2aff7Sartem 
12818c2aff7Sartem 	if (opt_s) {
12918c2aff7Sartem 		if (geteuid() != 0) {
13018c2aff7Sartem 			(void) fprintf(stderr,
13118c2aff7Sartem 			    gettext("system instance must have euid 0\n"));
13218c2aff7Sartem 			return (1);
13318c2aff7Sartem 		}
13418c2aff7Sartem 
13518c2aff7Sartem 		get_smf_properties();
13618c2aff7Sartem 
13718c2aff7Sartem 		if (opt_c) {
13818c2aff7Sartem 			rmm_vold_actions_enabled = B_FALSE;
13918c2aff7Sartem 		}
14018c2aff7Sartem 		if (opt_n) {
14118c2aff7Sartem 			rmm_vold_mountpoints_enabled = B_FALSE;
14218c2aff7Sartem 		}
14318c2aff7Sartem 
14418c2aff7Sartem 
14518c2aff7Sartem 		/*
14618c2aff7Sartem 		 * Drop unused privileges. Remain root for HAL interaction
14718c2aff7Sartem 		 * and to create legacy symlinks.
14818c2aff7Sartem 		 *
14918c2aff7Sartem 		 * Need PRIV_FILE_DAC_WRITE to write to users'
15018c2aff7Sartem 		 * /tmp/.removable/notify* files.
15118c2aff7Sartem 		 */
15218c2aff7Sartem 		if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
15318c2aff7Sartem 		    0, 0,
15418c2aff7Sartem 		    rmm_vold_actions_enabled ? PRIV_FILE_DAC_WRITE : NULL,
15518c2aff7Sartem 		    NULL) == -1) {
15618c2aff7Sartem 			(void) fprintf(stderr,
15718c2aff7Sartem 			    gettext("failed to drop privileges"));
15818c2aff7Sartem 			return (1);
15918c2aff7Sartem 		}
16018c2aff7Sartem 		/* basic privileges we don't need */
16118c2aff7Sartem 		(void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_PROC_EXEC,
16218c2aff7Sartem 		    PRIV_PROC_INFO, PRIV_FILE_LINK_ANY, PRIV_PROC_SESSION,
16318c2aff7Sartem 		    NULL);
16418c2aff7Sartem 
16518c2aff7Sartem 	} else {
16618c2aff7Sartem 		if (opt_c) {
16718c2aff7Sartem 			rmm_vold_actions_enabled = B_FALSE;
16818c2aff7Sartem 		}
16918c2aff7Sartem 		if (opt_n) {
17018c2aff7Sartem 			rmm_vold_mountpoints_enabled = B_FALSE;
17118c2aff7Sartem 		}
17218c2aff7Sartem 	}
17318c2aff7Sartem 
17418c2aff7Sartem 	daemonize = (getenv("RMVOLMGR_NODAEMON") == NULL);
17518c2aff7Sartem 
17618c2aff7Sartem 	if (daemonize && daemon(0, 0) < 0) {
17718c2aff7Sartem 		dprintf("daemonizing failed: %s", strerror(errno));
17818c2aff7Sartem 		return (1);
17918c2aff7Sartem 	}
18018c2aff7Sartem 
18118c2aff7Sartem 	if (opt_s) {
18218c2aff7Sartem 		__fini_daemon_priv(PRIV_PROC_FORK, NULL);
18318c2aff7Sartem 	}
18418c2aff7Sartem 
18518c2aff7Sartem 	/*
18618c2aff7Sartem 	 * signal mainloop integration using pipes
18718c2aff7Sartem 	 */
18818c2aff7Sartem 	if (pipe(sigexit_pipe) != 0) {
18918c2aff7Sartem 		dprintf("pipe failed %s\n", strerror(errno));
19018c2aff7Sartem 		return (1);
19118c2aff7Sartem 	}
19218c2aff7Sartem 	sigexit_ioch = g_io_channel_unix_new(sigexit_pipe[0]);
19318c2aff7Sartem 	if (sigexit_ioch == NULL) {
19418c2aff7Sartem 		dprintf("g_io_channel_unix_new failed\n");
19518c2aff7Sartem 		return (1);
19618c2aff7Sartem 	}
19718c2aff7Sartem 	g_io_add_watch(sigexit_ioch, G_IO_IN, sigexit_ioch_func, NULL);
19818c2aff7Sartem 	signal(SIGTERM, sigexit);
19918c2aff7Sartem 	signal(SIGINT, sigexit);
20018c2aff7Sartem 	signal(SIGHUP, SIG_IGN);
20118c2aff7Sartem 	signal(SIGUSR1, SIG_IGN);
20218c2aff7Sartem 	signal(SIGUSR2, SIG_IGN);
20318c2aff7Sartem 
20418c2aff7Sartem 	if ((hal_ctx = rmm_hal_init(rmm_device_added, rmm_device_removed,
205*97ddcdceSArtem Kachitchkine 	    rmm_property_modified, rmm_device_condition,
206*97ddcdceSArtem Kachitchkine 	    &error, &rmm_error)) == NULL) {
20718c2aff7Sartem 		dbus_error_free(&error);
20818c2aff7Sartem 		return (1);
20918c2aff7Sartem 	}
21018c2aff7Sartem 
21118c2aff7Sartem 	/* user instance should claim devices */
21218c2aff7Sartem 	if (!opt_s) {
21318c2aff7Sartem 		if (!rmm_hal_claim_branch(hal_ctx, HAL_BRANCH_LOCAL)) {
21418c2aff7Sartem 			(void) fprintf(stderr,
21518c2aff7Sartem 			    gettext("cannot claim branch\n"));
21618c2aff7Sartem 			return (1);
21718c2aff7Sartem 		}
21818c2aff7Sartem 	}
21918c2aff7Sartem 
22018c2aff7Sartem 	rmm_mount_all();
22118c2aff7Sartem 
22218c2aff7Sartem 	if ((mainloop = g_main_loop_new(NULL, B_FALSE)) == NULL) {
22318c2aff7Sartem 		dprintf("Cannot create main loop\n");
22418c2aff7Sartem 		return (1);
22518c2aff7Sartem 	}
22618c2aff7Sartem 
22718c2aff7Sartem 	g_main_loop_run(mainloop);
22818c2aff7Sartem 
22918c2aff7Sartem 	return (0);
23018c2aff7Sartem }
23118c2aff7Sartem 
23218c2aff7Sartem static void
get_smf_properties()23318c2aff7Sartem get_smf_properties()
23418c2aff7Sartem {
23518c2aff7Sartem 	scf_simple_prop_t *prop;
23618c2aff7Sartem 	uint8_t *val;
23718c2aff7Sartem 
23818c2aff7Sartem 	if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI,
23918c2aff7Sartem 	    "rmvolmgr", "legacy_mountpoints")) != NULL) {
24018c2aff7Sartem 		if ((val = scf_simple_prop_next_boolean(prop)) != NULL) {
24118c2aff7Sartem 			rmm_vold_mountpoints_enabled = (*val != 0);
24218c2aff7Sartem 		}
24318c2aff7Sartem 		scf_simple_prop_free(prop);
24418c2aff7Sartem 	}
24518c2aff7Sartem 
24618c2aff7Sartem 	if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI,
24718c2aff7Sartem 	    "rmvolmgr", "cde_compatible")) != NULL) {
24818c2aff7Sartem 		if ((val = scf_simple_prop_next_boolean(prop)) != NULL) {
24918c2aff7Sartem 			rmm_vold_actions_enabled = (*val != 0);
25018c2aff7Sartem 		}
25118c2aff7Sartem 		scf_simple_prop_free(prop);
25218c2aff7Sartem 	}
253*97ddcdceSArtem Kachitchkine 
254*97ddcdceSArtem Kachitchkine 	if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI,
255*97ddcdceSArtem Kachitchkine 	    "rmvolmgr", "eject_button")) != NULL) {
256*97ddcdceSArtem Kachitchkine 		if ((val = scf_simple_prop_next_boolean(prop)) != NULL) {
257*97ddcdceSArtem Kachitchkine 			rmm_prop_eject_button = (*val != 0);
258*97ddcdceSArtem Kachitchkine 		}
259*97ddcdceSArtem Kachitchkine 		scf_simple_prop_free(prop);
260*97ddcdceSArtem Kachitchkine 	}
26118c2aff7Sartem }
26218c2aff7Sartem 
26318c2aff7Sartem /* ARGSUSED */
26418c2aff7Sartem static void
sigexit(int signo)26518c2aff7Sartem sigexit(int signo)
26618c2aff7Sartem {
26718c2aff7Sartem 	dprintf("signal to exit %d\n", signo);
26818c2aff7Sartem 
26918c2aff7Sartem 	write(sigexit_pipe[1], "s", 1);
27018c2aff7Sartem }
27118c2aff7Sartem 
27218c2aff7Sartem /* ARGSUSED */
27318c2aff7Sartem static gboolean
sigexit_ioch_func(GIOChannel * source,GIOCondition condition,gpointer user_data)27418c2aff7Sartem sigexit_ioch_func(GIOChannel *source, GIOCondition condition,
27518c2aff7Sartem     gpointer user_data)
27618c2aff7Sartem {
27718c2aff7Sartem 	gchar	buf[1];
27818c2aff7Sartem 	gsize	bytes_read;
27918c2aff7Sartem 	GError	*error = NULL;
28018c2aff7Sartem 
28118c2aff7Sartem 	if (g_io_channel_read_chars(source, buf, 1, &bytes_read, &error) !=
28218c2aff7Sartem 	    G_IO_STATUS_NORMAL) {
28318c2aff7Sartem 		dprintf("g_io_channel_read_chars failed %s", error->message);
28418c2aff7Sartem 		g_error_free(error);
28518c2aff7Sartem 		return (TRUE);
28618c2aff7Sartem 	}
28718c2aff7Sartem 
28818c2aff7Sartem 	dprintf("signal to exit\n");
28918c2aff7Sartem 
29018c2aff7Sartem 	rmm_unmount_all();
29118c2aff7Sartem 
29218c2aff7Sartem 	g_main_loop_quit(mainloop);
29318c2aff7Sartem 
29418c2aff7Sartem 	return (TRUE);
29518c2aff7Sartem }
29618c2aff7Sartem 
29718c2aff7Sartem static managed_volume_t *
rmm_managed_alloc(LibHalContext * ctx,const char * udi)29818c2aff7Sartem rmm_managed_alloc(LibHalContext *ctx, const char *udi)
29918c2aff7Sartem {
30018c2aff7Sartem 	managed_volume_t *v;
30118c2aff7Sartem 
30218c2aff7Sartem 	if ((v = calloc(1, sizeof (managed_volume_t))) == NULL) {
30318c2aff7Sartem 		return (NULL);
30418c2aff7Sartem 	}
30518c2aff7Sartem 	if ((v->udi = strdup(udi)) == NULL) {
30618c2aff7Sartem 		free(v);
30718c2aff7Sartem 		return (NULL);
30818c2aff7Sartem 	}
30918c2aff7Sartem 	if (!rmm_volume_aa_from_prop(ctx, udi, NULL, &v->aa)) {
31018c2aff7Sartem 		free(v->udi);
31118c2aff7Sartem 		free(v);
31218c2aff7Sartem 		return (NULL);
31318c2aff7Sartem 	}
31418c2aff7Sartem 
31518c2aff7Sartem 	return (v);
31618c2aff7Sartem }
31718c2aff7Sartem 
31818c2aff7Sartem static void
rmm_managed_free(managed_volume_t * v)31918c2aff7Sartem rmm_managed_free(managed_volume_t *v)
32018c2aff7Sartem {
32118c2aff7Sartem 	rmm_volume_aa_free(&v->aa);
32218c2aff7Sartem 	free(v->udi);
32318c2aff7Sartem 	free(v);
32418c2aff7Sartem }
32518c2aff7Sartem 
32618c2aff7Sartem static gint
rmm_managed_compare_udi(gconstpointer a,gconstpointer b)32718c2aff7Sartem rmm_managed_compare_udi(gconstpointer a, gconstpointer b)
32818c2aff7Sartem {
32918c2aff7Sartem 	const managed_volume_t *va = a;
33018c2aff7Sartem 	const char *udi = b;
33118c2aff7Sartem 
33218c2aff7Sartem 	return (strcmp(va->udi, udi));
33318c2aff7Sartem }
33418c2aff7Sartem 
33518c2aff7Sartem static boolean_t
volume_should_mount(const char * udi)33618c2aff7Sartem volume_should_mount(const char *udi)
33718c2aff7Sartem {
33818c2aff7Sartem 	char	*storage_device = NULL;
33918c2aff7Sartem 	int	ret = B_FALSE;
34018c2aff7Sartem 
34118c2aff7Sartem 	if (libhal_device_get_property_bool(hal_ctx, udi,
34218c2aff7Sartem 	    "volume.ignore", NULL)) {
34318c2aff7Sartem 		goto out;
34418c2aff7Sartem 	}
34518c2aff7Sartem 
34618c2aff7Sartem 	/* get the backing storage device */
34718c2aff7Sartem 	if (!(storage_device = libhal_device_get_property_string(hal_ctx, udi,
34818c2aff7Sartem 	    "block.storage_device", NULL))) {
34918c2aff7Sartem 		dprintf("cannot get block.storage_device\n");
35018c2aff7Sartem 		goto out;
35118c2aff7Sartem 	}
35218c2aff7Sartem 
35318c2aff7Sartem 	/* we handle either removable or hotpluggable */
35418c2aff7Sartem 	if (!libhal_device_get_property_bool(hal_ctx, storage_device,
35518c2aff7Sartem 	    "storage.removable", NULL) &&
35618c2aff7Sartem 	    !libhal_device_get_property_bool(hal_ctx, storage_device,
35718c2aff7Sartem 	    "storage.hotpluggable", NULL)) {
35818c2aff7Sartem 		goto out;
35918c2aff7Sartem 	}
36018c2aff7Sartem 
36118c2aff7Sartem 	/* ignore if claimed by another volume manager */
36218c2aff7Sartem 	if (libhal_device_get_property_bool(hal_ctx, storage_device,
36318c2aff7Sartem 	    "info.claimed", NULL)) {
36418c2aff7Sartem 		goto out;
36518c2aff7Sartem 	}
36618c2aff7Sartem 
36718c2aff7Sartem 	ret = B_TRUE;
36818c2aff7Sartem 
36918c2aff7Sartem out:
37018c2aff7Sartem 	libhal_free_string(storage_device);
37118c2aff7Sartem 	return (ret);
37218c2aff7Sartem }
37318c2aff7Sartem 
37418c2aff7Sartem static void
volume_added(const char * udi)37518c2aff7Sartem volume_added(const char *udi)
37618c2aff7Sartem {
37718c2aff7Sartem 	GSList		*l;
37818c2aff7Sartem 	managed_volume_t *v;
37918c2aff7Sartem 
38018c2aff7Sartem 	dprintf("volume added %s\n", udi);
38118c2aff7Sartem 
38218c2aff7Sartem 	l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi);
38318c2aff7Sartem 	v = (l != NULL) ? l->data : NULL;
38418c2aff7Sartem 
38518c2aff7Sartem 	if (v != NULL) {
38618c2aff7Sartem 		dprintf("already managed %s\n", udi);
38718c2aff7Sartem 		return;
38818c2aff7Sartem 	}
38918c2aff7Sartem 	if (!volume_should_mount(udi)) {
39018c2aff7Sartem 		dprintf("should not mount %s\n", udi);
39118c2aff7Sartem 		return;
39218c2aff7Sartem 	}
39318c2aff7Sartem 	if ((v = rmm_managed_alloc(hal_ctx, udi)) == NULL) {
39418c2aff7Sartem 		return;
39518c2aff7Sartem 	}
39618c2aff7Sartem 	if (rmm_action(hal_ctx, udi, INSERT, &v->aa, 0, 0, 0)) {
39718c2aff7Sartem 		v->my = B_TRUE;
39818c2aff7Sartem 		managed_volumes = g_slist_prepend(managed_volumes, v);
39918c2aff7Sartem 	} else {
40018c2aff7Sartem 		dprintf("rmm_action failed %s\n", udi);
40118c2aff7Sartem 		rmm_managed_free(v);
40218c2aff7Sartem 	}
40318c2aff7Sartem }
40418c2aff7Sartem 
40518c2aff7Sartem static void
volume_removed(const char * udi)40618c2aff7Sartem volume_removed(const char *udi)
40718c2aff7Sartem {
40818c2aff7Sartem 	GSList		*l;
40918c2aff7Sartem 	managed_volume_t *v;
41018c2aff7Sartem 
41118c2aff7Sartem 	dprintf("volume removed %s\n", udi);
41218c2aff7Sartem 
41318c2aff7Sartem 	l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi);
41418c2aff7Sartem 	v = (l != NULL) ? l->data : NULL;
41518c2aff7Sartem 	if (v == NULL) {
41618c2aff7Sartem 		return;
41718c2aff7Sartem 	}
41818c2aff7Sartem 
41918c2aff7Sartem 	/* HAL will unmount, just do the vold legacy stuff */
42018c2aff7Sartem 	v->aa.aa_action = EJECT;
42118c2aff7Sartem 	(void) vold_postprocess(hal_ctx, udi, &v->aa);
42218c2aff7Sartem 
42318c2aff7Sartem 	rmm_managed_free(v);
42418c2aff7Sartem 	managed_volumes = g_slist_delete_link(managed_volumes, l);
42518c2aff7Sartem }
42618c2aff7Sartem 
42718c2aff7Sartem /* ARGSUSED */
42818c2aff7Sartem static void
rmm_device_added(LibHalContext * ctx,const char * udi)42918c2aff7Sartem rmm_device_added(LibHalContext *ctx, const char *udi)
43018c2aff7Sartem {
43118c2aff7Sartem 	if (libhal_device_query_capability(hal_ctx, udi, "volume", NULL)) {
43218c2aff7Sartem 		volume_added(udi);
43318c2aff7Sartem 	}
43418c2aff7Sartem }
43518c2aff7Sartem 
43618c2aff7Sartem /* ARGSUSED */
43718c2aff7Sartem static void
rmm_device_removed(LibHalContext * ctx,const char * udi)43818c2aff7Sartem rmm_device_removed(LibHalContext *ctx, const char *udi)
43918c2aff7Sartem {
44018c2aff7Sartem 	if (libhal_device_query_capability(hal_ctx, udi, "volume", NULL)) {
44118c2aff7Sartem 		volume_removed(udi);
44218c2aff7Sartem 	}
44318c2aff7Sartem }
44418c2aff7Sartem 
44518c2aff7Sartem /* ARGSUSED */
44618c2aff7Sartem static void
rmm_property_modified(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t is_removed,dbus_bool_t is_added)44718c2aff7Sartem rmm_property_modified(LibHalContext *ctx, const char *udi, const char *key,
44818c2aff7Sartem     dbus_bool_t is_removed, dbus_bool_t is_added)
44918c2aff7Sartem {
45018c2aff7Sartem 	DBusError		error;
45118c2aff7Sartem 	GSList			*l;
45218c2aff7Sartem 	managed_volume_t	*v;
45318c2aff7Sartem 	boolean_t		is_mounted;
45418c2aff7Sartem 
45518c2aff7Sartem 	if (strcmp(key, "volume.is_mounted") != 0) {
45618c2aff7Sartem 		return;
45718c2aff7Sartem 	}
45818c2aff7Sartem 	is_mounted = libhal_device_get_property_bool(hal_ctx, udi, key, NULL);
45918c2aff7Sartem 
46018c2aff7Sartem 	l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi);
46118c2aff7Sartem 	v = (l != NULL) ? l->data : NULL;
46218c2aff7Sartem 
46318c2aff7Sartem 	if (is_mounted) {
46418c2aff7Sartem 		dprintf("Mounted: %s\n", udi);
46518c2aff7Sartem 
46618c2aff7Sartem 		if (v != NULL) {
46718c2aff7Sartem 			/* volume mounted by us is already taken care of */
46818c2aff7Sartem 			if (v->my) {
46918c2aff7Sartem 				return;
47018c2aff7Sartem 			}
47118c2aff7Sartem 		} else {
47218c2aff7Sartem 			if ((v = rmm_managed_alloc(ctx, udi)) == NULL) {
47318c2aff7Sartem 				return;
47418c2aff7Sartem 			}
47518c2aff7Sartem 			managed_volumes = g_slist_prepend(managed_volumes, v);
47618c2aff7Sartem 		}
47718c2aff7Sartem 
47818c2aff7Sartem 		v->aa.aa_action = INSERT;
47918c2aff7Sartem 		(void) vold_postprocess(hal_ctx, udi, &v->aa);
48018c2aff7Sartem 
48118c2aff7Sartem 	} else {
48218c2aff7Sartem 		dprintf("Unmounted: %s\n", udi);
48318c2aff7Sartem 
48418c2aff7Sartem 		if (v == NULL) {
48518c2aff7Sartem 			return;
48618c2aff7Sartem 		}
48718c2aff7Sartem 
48818c2aff7Sartem 		v->aa.aa_action = EJECT;
48918c2aff7Sartem 		(void) vold_postprocess(hal_ctx, udi, &v->aa);
49018c2aff7Sartem 
49118c2aff7Sartem 		rmm_managed_free(v);
49218c2aff7Sartem 		managed_volumes = g_slist_delete_link(managed_volumes, l);
49318c2aff7Sartem 	}
49418c2aff7Sartem }
49518c2aff7Sartem 
496*97ddcdceSArtem Kachitchkine static void
storage_eject_pressed(const char * udi)497*97ddcdceSArtem Kachitchkine storage_eject_pressed(const char *udi)
498*97ddcdceSArtem Kachitchkine {
499*97ddcdceSArtem Kachitchkine 	DBusError	error;
500*97ddcdceSArtem Kachitchkine 
501*97ddcdceSArtem Kachitchkine 	/* ignore if disabled via SMF or claimed by another volume manager */
502*97ddcdceSArtem Kachitchkine 	if (!rmm_prop_eject_button ||
503*97ddcdceSArtem Kachitchkine 	    libhal_device_get_property_bool(hal_ctx, udi, "info.claimed",
504*97ddcdceSArtem Kachitchkine 	    NULL)) {
505*97ddcdceSArtem Kachitchkine 		return;
506*97ddcdceSArtem Kachitchkine 	}
507*97ddcdceSArtem Kachitchkine 
508*97ddcdceSArtem Kachitchkine 	dbus_error_init(&error);
509*97ddcdceSArtem Kachitchkine 	(void) rmm_hal_eject(hal_ctx, udi, &error);
510*97ddcdceSArtem Kachitchkine 	rmm_dbus_error_free(&error);
511*97ddcdceSArtem Kachitchkine }
512*97ddcdceSArtem Kachitchkine 
513*97ddcdceSArtem Kachitchkine /* ARGSUSED */
514*97ddcdceSArtem Kachitchkine static void
rmm_device_condition(LibHalContext * ctx,const char * udi,const char * name,const char * detail)515*97ddcdceSArtem Kachitchkine rmm_device_condition(LibHalContext *ctx, const char *udi,
516*97ddcdceSArtem Kachitchkine     const char *name, const char *detail)
517*97ddcdceSArtem Kachitchkine {
518*97ddcdceSArtem Kachitchkine 	if ((strcmp(name, "EjectPressed") == 0) &&
519*97ddcdceSArtem Kachitchkine 	    libhal_device_query_capability(hal_ctx, udi, "storage", NULL)) {
520*97ddcdceSArtem Kachitchkine 		storage_eject_pressed(udi);
521*97ddcdceSArtem Kachitchkine 	}
522*97ddcdceSArtem Kachitchkine }
523*97ddcdceSArtem Kachitchkine 
52418c2aff7Sartem /*
52518c2aff7Sartem  * Mount all mountable volumes
52618c2aff7Sartem  */
52718c2aff7Sartem static void
rmm_mount_all()52818c2aff7Sartem rmm_mount_all()
52918c2aff7Sartem {
53018c2aff7Sartem 	DBusError	error;
53118c2aff7Sartem 	char		**udis = NULL;
53218c2aff7Sartem 	int		num_udis;
53318c2aff7Sartem 	int		i;
53418c2aff7Sartem 	managed_volume_t *v;
53518c2aff7Sartem 
53618c2aff7Sartem 	dbus_error_init(&error);
53718c2aff7Sartem 
53818c2aff7Sartem 	/* get all volumes */
53918c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "volume",
54018c2aff7Sartem 	    &num_udis, &error)) == NULL) {
54118c2aff7Sartem 		dprintf("mount_all: no volumes found\n");
54218c2aff7Sartem 		goto out;
54318c2aff7Sartem 	}
54418c2aff7Sartem 
54518c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
54618c2aff7Sartem 		/* skip if already mounted */
54718c2aff7Sartem 		if (libhal_device_get_property_bool(hal_ctx, udis[i],
54818c2aff7Sartem 		    "volume.is_mounted", NULL)) {
54918c2aff7Sartem 			dprintf("mount_all: %s already mounted\n", udis[i]);
55018c2aff7Sartem 			continue;
55118c2aff7Sartem 		}
55218c2aff7Sartem 		if (!volume_should_mount(udis[i])) {
55318c2aff7Sartem 			continue;
55418c2aff7Sartem 		}
55518c2aff7Sartem 		if ((v = rmm_managed_alloc(hal_ctx, udis[i])) == NULL) {
55618c2aff7Sartem 			continue;
55718c2aff7Sartem 		}
55818c2aff7Sartem 		if (rmm_action(hal_ctx, udis[i], INSERT, &v->aa, 0, 0, 0)) {
55918c2aff7Sartem 			v->my = B_TRUE;
56018c2aff7Sartem 			managed_volumes = g_slist_prepend(managed_volumes, v);
56118c2aff7Sartem 		} else {
56218c2aff7Sartem 			rmm_managed_free(v);
56318c2aff7Sartem 		}
56418c2aff7Sartem 	}
56518c2aff7Sartem 
56618c2aff7Sartem out:
56718c2aff7Sartem 	if (udis != NULL) {
56818c2aff7Sartem 		libhal_free_string_array(udis);
56918c2aff7Sartem 	}
57018c2aff7Sartem 	rmm_dbus_error_free(&error);
57118c2aff7Sartem }
57218c2aff7Sartem 
57318c2aff7Sartem /*
57418c2aff7Sartem  * Mount all volumes mounted by this program
57518c2aff7Sartem  */
57618c2aff7Sartem static void
rmm_unmount_all()57718c2aff7Sartem rmm_unmount_all()
57818c2aff7Sartem {
57918c2aff7Sartem 	GSList		*i;
58018c2aff7Sartem 	managed_volume_t *v;
58118c2aff7Sartem 
58218c2aff7Sartem 	for (i = managed_volumes; i != NULL; i = managed_volumes) {
58318c2aff7Sartem 		v = (managed_volume_t *)i->data;
58418c2aff7Sartem 
58518c2aff7Sartem 		if (v->my && libhal_device_get_property_bool(hal_ctx, v->udi,
58618c2aff7Sartem 		    "volume.is_mounted", NULL)) {
58718c2aff7Sartem 			(void) rmm_action(hal_ctx, v->udi, UNMOUNT,
58818c2aff7Sartem 			    &v->aa, 0, 0, 0);
58918c2aff7Sartem 		}
59018c2aff7Sartem 
59118c2aff7Sartem 		managed_volumes = g_slist_remove(managed_volumes, v);
59218c2aff7Sartem 		rmm_managed_free(v);
59318c2aff7Sartem 	}
59418c2aff7Sartem }
59518c2aff7Sartem 
59618c2aff7Sartem int
main(int argc,char ** argv)59718c2aff7Sartem main(int argc, char **argv)
59818c2aff7Sartem {
59918c2aff7Sartem 	vold_init(argc, argv);
60018c2aff7Sartem 
60118c2aff7Sartem 	return (rmvolmgr(argc, argv));
60218c2aff7Sartem }
603