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