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 9018c2aff7Sartem usage() 9118c2aff7Sartem { 9218c2aff7Sartem (void) fprintf(stderr, gettext("\nusage: rmvolmgr [-v]\n")); 9318c2aff7Sartem } 9418c2aff7Sartem 9518c2aff7Sartem static int 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 59718c2aff7Sartem main(int argc, char **argv) 59818c2aff7Sartem { 59918c2aff7Sartem vold_init(argc, argv); 60018c2aff7Sartem 60118c2aff7Sartem return (rmvolmgr(argc, argv)); 60218c2aff7Sartem } 603