1*18c2aff7Sartem /* 2*18c2aff7Sartem * CDDL HEADER START 3*18c2aff7Sartem * 4*18c2aff7Sartem * The contents of this file are subject to the terms of the 5*18c2aff7Sartem * Common Development and Distribution License (the "License"). 6*18c2aff7Sartem * You may not use this file except in compliance with the License. 7*18c2aff7Sartem * 8*18c2aff7Sartem * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*18c2aff7Sartem * or http://www.opensolaris.org/os/licensing. 10*18c2aff7Sartem * See the License for the specific language governing permissions 11*18c2aff7Sartem * and limitations under the License. 12*18c2aff7Sartem * 13*18c2aff7Sartem * When distributing Covered Code, include this CDDL HEADER in each 14*18c2aff7Sartem * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*18c2aff7Sartem * If applicable, add the following below this CDDL HEADER, with the 16*18c2aff7Sartem * fields enclosed by brackets "[]" replaced with your own identifying 17*18c2aff7Sartem * information: Portions Copyright [yyyy] [name of copyright owner] 18*18c2aff7Sartem * 19*18c2aff7Sartem * CDDL HEADER END 20*18c2aff7Sartem */ 21*18c2aff7Sartem /* 22*18c2aff7Sartem * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*18c2aff7Sartem * Use is subject to license terms. 24*18c2aff7Sartem */ 25*18c2aff7Sartem 26*18c2aff7Sartem #pragma ident "%Z%%M% %I% %E% SMI" 27*18c2aff7Sartem 28*18c2aff7Sartem /* 29*18c2aff7Sartem * rmvolmgr daemon 30*18c2aff7Sartem */ 31*18c2aff7Sartem 32*18c2aff7Sartem #include <stdio.h> 33*18c2aff7Sartem #include <stdlib.h> 34*18c2aff7Sartem #include <sys/types.h> 35*18c2aff7Sartem #include <sys/stat.h> 36*18c2aff7Sartem #include <dirent.h> 37*18c2aff7Sartem #include <signal.h> 38*18c2aff7Sartem #include <unistd.h> 39*18c2aff7Sartem #include <fcntl.h> 40*18c2aff7Sartem #include <strings.h> 41*18c2aff7Sartem #include <errno.h> 42*18c2aff7Sartem #include <libintl.h> 43*18c2aff7Sartem #include <sys/syscall.h> 44*18c2aff7Sartem #include <libscf.h> 45*18c2aff7Sartem #include <priv_utils.h> 46*18c2aff7Sartem 47*18c2aff7Sartem #include <dbus/dbus.h> 48*18c2aff7Sartem #include <dbus/dbus-glib.h> 49*18c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h> 50*18c2aff7Sartem #include <libhal.h> 51*18c2aff7Sartem 52*18c2aff7Sartem #include "rmm_common.h" 53*18c2aff7Sartem 54*18c2aff7Sartem char *progname = "rmvolmgr"; 55*18c2aff7Sartem 56*18c2aff7Sartem #define RMVOLMGR_FMRI "svc:/system/filesystem/rmvolmgr:default" 57*18c2aff7Sartem 58*18c2aff7Sartem typedef struct managed_volume { 59*18c2aff7Sartem char *udi; 60*18c2aff7Sartem boolean_t my; 61*18c2aff7Sartem struct action_arg aa; 62*18c2aff7Sartem } managed_volume_t; 63*18c2aff7Sartem 64*18c2aff7Sartem static GSList *managed_volumes; 65*18c2aff7Sartem 66*18c2aff7Sartem static GMainLoop *mainloop; 67*18c2aff7Sartem static LibHalContext *hal_ctx; 68*18c2aff7Sartem static int sigexit_pipe[2]; 69*18c2aff7Sartem static GIOChannel *sigexit_ioch; 70*18c2aff7Sartem 71*18c2aff7Sartem static boolean_t opt_c; /* disable CDE compatibility */ 72*18c2aff7Sartem static boolean_t opt_n; /* disable legacy mountpoint symlinks */ 73*18c2aff7Sartem static boolean_t opt_s; /* system instance */ 74*18c2aff7Sartem 75*18c2aff7Sartem static void get_smf_properties(); 76*18c2aff7Sartem static int daemon(int nochdir, int noclose); 77*18c2aff7Sartem static void rmm_device_added(LibHalContext *ctx, const char *udi); 78*18c2aff7Sartem static void rmm_device_removed(LibHalContext *ctx, const char *udi); 79*18c2aff7Sartem static void rmm_property_modified(LibHalContext *ctx, const char *udi, 80*18c2aff7Sartem const char *key, dbus_bool_t is_removed, dbus_bool_t is_added); 81*18c2aff7Sartem static void rmm_mount_all(); 82*18c2aff7Sartem static void rmm_unmount_all(); 83*18c2aff7Sartem static void sigexit(int signo); 84*18c2aff7Sartem static gboolean sigexit_ioch_func(GIOChannel *source, GIOCondition condition, 85*18c2aff7Sartem gpointer user_data); 86*18c2aff7Sartem 87*18c2aff7Sartem static void 88*18c2aff7Sartem usage() 89*18c2aff7Sartem { 90*18c2aff7Sartem (void) fprintf(stderr, gettext("\nusage: rmvolmgr [-v]\n")); 91*18c2aff7Sartem } 92*18c2aff7Sartem 93*18c2aff7Sartem static int 94*18c2aff7Sartem rmvolmgr(int argc, char **argv) 95*18c2aff7Sartem { 96*18c2aff7Sartem const char *opts = "chnsv"; 97*18c2aff7Sartem DBusError error; 98*18c2aff7Sartem boolean_t daemonize; 99*18c2aff7Sartem rmm_error_t rmm_error; 100*18c2aff7Sartem int c; 101*18c2aff7Sartem 102*18c2aff7Sartem while ((c = getopt(argc, argv, opts)) != EOF) { 103*18c2aff7Sartem switch (c) { 104*18c2aff7Sartem case 'c': 105*18c2aff7Sartem opt_c = B_TRUE; 106*18c2aff7Sartem break; 107*18c2aff7Sartem case 'n': 108*18c2aff7Sartem opt_n = B_TRUE; 109*18c2aff7Sartem break; 110*18c2aff7Sartem case 's': 111*18c2aff7Sartem opt_s = B_TRUE; 112*18c2aff7Sartem break; 113*18c2aff7Sartem case 'v': 114*18c2aff7Sartem rmm_debug = 1; 115*18c2aff7Sartem break; 116*18c2aff7Sartem case '?': 117*18c2aff7Sartem case 'h': 118*18c2aff7Sartem usage(); 119*18c2aff7Sartem return (0); 120*18c2aff7Sartem default: 121*18c2aff7Sartem usage(); 122*18c2aff7Sartem return (1); 123*18c2aff7Sartem } 124*18c2aff7Sartem } 125*18c2aff7Sartem 126*18c2aff7Sartem if (opt_s) { 127*18c2aff7Sartem if (geteuid() != 0) { 128*18c2aff7Sartem (void) fprintf(stderr, 129*18c2aff7Sartem gettext("system instance must have euid 0\n")); 130*18c2aff7Sartem return (1); 131*18c2aff7Sartem } 132*18c2aff7Sartem 133*18c2aff7Sartem get_smf_properties(); 134*18c2aff7Sartem 135*18c2aff7Sartem if (opt_c) { 136*18c2aff7Sartem rmm_vold_actions_enabled = B_FALSE; 137*18c2aff7Sartem } 138*18c2aff7Sartem if (opt_n) { 139*18c2aff7Sartem rmm_vold_mountpoints_enabled = B_FALSE; 140*18c2aff7Sartem } 141*18c2aff7Sartem 142*18c2aff7Sartem 143*18c2aff7Sartem /* 144*18c2aff7Sartem * Drop unused privileges. Remain root for HAL interaction 145*18c2aff7Sartem * and to create legacy symlinks. 146*18c2aff7Sartem * 147*18c2aff7Sartem * Need PRIV_FILE_DAC_WRITE to write to users' 148*18c2aff7Sartem * /tmp/.removable/notify* files. 149*18c2aff7Sartem */ 150*18c2aff7Sartem if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 151*18c2aff7Sartem 0, 0, 152*18c2aff7Sartem rmm_vold_actions_enabled ? PRIV_FILE_DAC_WRITE : NULL, 153*18c2aff7Sartem NULL) == -1) { 154*18c2aff7Sartem (void) fprintf(stderr, 155*18c2aff7Sartem gettext("failed to drop privileges")); 156*18c2aff7Sartem return (1); 157*18c2aff7Sartem } 158*18c2aff7Sartem /* basic privileges we don't need */ 159*18c2aff7Sartem (void) priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_PROC_EXEC, 160*18c2aff7Sartem PRIV_PROC_INFO, PRIV_FILE_LINK_ANY, PRIV_PROC_SESSION, 161*18c2aff7Sartem NULL); 162*18c2aff7Sartem 163*18c2aff7Sartem } else { 164*18c2aff7Sartem if (opt_c) { 165*18c2aff7Sartem rmm_vold_actions_enabled = B_FALSE; 166*18c2aff7Sartem } 167*18c2aff7Sartem if (opt_n) { 168*18c2aff7Sartem rmm_vold_mountpoints_enabled = B_FALSE; 169*18c2aff7Sartem } 170*18c2aff7Sartem } 171*18c2aff7Sartem 172*18c2aff7Sartem daemonize = (getenv("RMVOLMGR_NODAEMON") == NULL); 173*18c2aff7Sartem 174*18c2aff7Sartem if (daemonize && daemon(0, 0) < 0) { 175*18c2aff7Sartem dprintf("daemonizing failed: %s", strerror(errno)); 176*18c2aff7Sartem return (1); 177*18c2aff7Sartem } 178*18c2aff7Sartem 179*18c2aff7Sartem if (opt_s) { 180*18c2aff7Sartem __fini_daemon_priv(PRIV_PROC_FORK, NULL); 181*18c2aff7Sartem } 182*18c2aff7Sartem 183*18c2aff7Sartem /* 184*18c2aff7Sartem * signal mainloop integration using pipes 185*18c2aff7Sartem */ 186*18c2aff7Sartem if (pipe(sigexit_pipe) != 0) { 187*18c2aff7Sartem dprintf("pipe failed %s\n", strerror(errno)); 188*18c2aff7Sartem return (1); 189*18c2aff7Sartem } 190*18c2aff7Sartem sigexit_ioch = g_io_channel_unix_new(sigexit_pipe[0]); 191*18c2aff7Sartem if (sigexit_ioch == NULL) { 192*18c2aff7Sartem dprintf("g_io_channel_unix_new failed\n"); 193*18c2aff7Sartem return (1); 194*18c2aff7Sartem } 195*18c2aff7Sartem g_io_add_watch(sigexit_ioch, G_IO_IN, sigexit_ioch_func, NULL); 196*18c2aff7Sartem signal(SIGTERM, sigexit); 197*18c2aff7Sartem signal(SIGINT, sigexit); 198*18c2aff7Sartem signal(SIGHUP, SIG_IGN); 199*18c2aff7Sartem signal(SIGUSR1, SIG_IGN); 200*18c2aff7Sartem signal(SIGUSR2, SIG_IGN); 201*18c2aff7Sartem 202*18c2aff7Sartem if ((hal_ctx = rmm_hal_init(rmm_device_added, rmm_device_removed, 203*18c2aff7Sartem rmm_property_modified, &error, &rmm_error)) == NULL) { 204*18c2aff7Sartem dbus_error_free(&error); 205*18c2aff7Sartem return (1); 206*18c2aff7Sartem } 207*18c2aff7Sartem 208*18c2aff7Sartem /* user instance should claim devices */ 209*18c2aff7Sartem if (!opt_s) { 210*18c2aff7Sartem if (!rmm_hal_claim_branch(hal_ctx, HAL_BRANCH_LOCAL)) { 211*18c2aff7Sartem (void) fprintf(stderr, 212*18c2aff7Sartem gettext("cannot claim branch\n")); 213*18c2aff7Sartem return (1); 214*18c2aff7Sartem } 215*18c2aff7Sartem } 216*18c2aff7Sartem 217*18c2aff7Sartem rmm_mount_all(); 218*18c2aff7Sartem 219*18c2aff7Sartem if ((mainloop = g_main_loop_new(NULL, B_FALSE)) == NULL) { 220*18c2aff7Sartem dprintf("Cannot create main loop\n"); 221*18c2aff7Sartem return (1); 222*18c2aff7Sartem } 223*18c2aff7Sartem 224*18c2aff7Sartem g_main_loop_run(mainloop); 225*18c2aff7Sartem 226*18c2aff7Sartem return (0); 227*18c2aff7Sartem } 228*18c2aff7Sartem 229*18c2aff7Sartem static void 230*18c2aff7Sartem get_smf_properties() 231*18c2aff7Sartem { 232*18c2aff7Sartem scf_simple_prop_t *prop; 233*18c2aff7Sartem uint8_t *val; 234*18c2aff7Sartem 235*18c2aff7Sartem if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI, 236*18c2aff7Sartem "rmvolmgr", "legacy_mountpoints")) != NULL) { 237*18c2aff7Sartem if ((val = scf_simple_prop_next_boolean(prop)) != NULL) { 238*18c2aff7Sartem rmm_vold_mountpoints_enabled = (*val != 0); 239*18c2aff7Sartem } 240*18c2aff7Sartem scf_simple_prop_free(prop); 241*18c2aff7Sartem } 242*18c2aff7Sartem 243*18c2aff7Sartem if ((prop = scf_simple_prop_get(NULL, RMVOLMGR_FMRI, 244*18c2aff7Sartem "rmvolmgr", "cde_compatible")) != NULL) { 245*18c2aff7Sartem if ((val = scf_simple_prop_next_boolean(prop)) != NULL) { 246*18c2aff7Sartem rmm_vold_actions_enabled = (*val != 0); 247*18c2aff7Sartem } 248*18c2aff7Sartem scf_simple_prop_free(prop); 249*18c2aff7Sartem } 250*18c2aff7Sartem } 251*18c2aff7Sartem 252*18c2aff7Sartem /* ARGSUSED */ 253*18c2aff7Sartem static void 254*18c2aff7Sartem sigexit(int signo) 255*18c2aff7Sartem { 256*18c2aff7Sartem dprintf("signal to exit %d\n", signo); 257*18c2aff7Sartem 258*18c2aff7Sartem write(sigexit_pipe[1], "s", 1); 259*18c2aff7Sartem } 260*18c2aff7Sartem 261*18c2aff7Sartem /* ARGSUSED */ 262*18c2aff7Sartem static gboolean 263*18c2aff7Sartem sigexit_ioch_func(GIOChannel *source, GIOCondition condition, 264*18c2aff7Sartem gpointer user_data) 265*18c2aff7Sartem { 266*18c2aff7Sartem gchar buf[1]; 267*18c2aff7Sartem gsize bytes_read; 268*18c2aff7Sartem GError *error = NULL; 269*18c2aff7Sartem 270*18c2aff7Sartem if (g_io_channel_read_chars(source, buf, 1, &bytes_read, &error) != 271*18c2aff7Sartem G_IO_STATUS_NORMAL) { 272*18c2aff7Sartem dprintf("g_io_channel_read_chars failed %s", error->message); 273*18c2aff7Sartem g_error_free(error); 274*18c2aff7Sartem return (TRUE); 275*18c2aff7Sartem } 276*18c2aff7Sartem 277*18c2aff7Sartem dprintf("signal to exit\n"); 278*18c2aff7Sartem 279*18c2aff7Sartem rmm_unmount_all(); 280*18c2aff7Sartem 281*18c2aff7Sartem g_main_loop_quit(mainloop); 282*18c2aff7Sartem 283*18c2aff7Sartem return (TRUE); 284*18c2aff7Sartem } 285*18c2aff7Sartem 286*18c2aff7Sartem static managed_volume_t * 287*18c2aff7Sartem rmm_managed_alloc(LibHalContext *ctx, const char *udi) 288*18c2aff7Sartem { 289*18c2aff7Sartem managed_volume_t *v; 290*18c2aff7Sartem 291*18c2aff7Sartem if ((v = calloc(1, sizeof (managed_volume_t))) == NULL) { 292*18c2aff7Sartem return (NULL); 293*18c2aff7Sartem } 294*18c2aff7Sartem if ((v->udi = strdup(udi)) == NULL) { 295*18c2aff7Sartem free(v); 296*18c2aff7Sartem return (NULL); 297*18c2aff7Sartem } 298*18c2aff7Sartem if (!rmm_volume_aa_from_prop(ctx, udi, NULL, &v->aa)) { 299*18c2aff7Sartem free(v->udi); 300*18c2aff7Sartem free(v); 301*18c2aff7Sartem return (NULL); 302*18c2aff7Sartem } 303*18c2aff7Sartem 304*18c2aff7Sartem return (v); 305*18c2aff7Sartem } 306*18c2aff7Sartem 307*18c2aff7Sartem static void 308*18c2aff7Sartem rmm_managed_free(managed_volume_t *v) 309*18c2aff7Sartem { 310*18c2aff7Sartem rmm_volume_aa_free(&v->aa); 311*18c2aff7Sartem free(v->udi); 312*18c2aff7Sartem free(v); 313*18c2aff7Sartem } 314*18c2aff7Sartem 315*18c2aff7Sartem static gint 316*18c2aff7Sartem rmm_managed_compare_udi(gconstpointer a, gconstpointer b) 317*18c2aff7Sartem { 318*18c2aff7Sartem const managed_volume_t *va = a; 319*18c2aff7Sartem const char *udi = b; 320*18c2aff7Sartem 321*18c2aff7Sartem return (strcmp(va->udi, udi)); 322*18c2aff7Sartem } 323*18c2aff7Sartem 324*18c2aff7Sartem static boolean_t 325*18c2aff7Sartem volume_should_mount(const char *udi) 326*18c2aff7Sartem { 327*18c2aff7Sartem char *storage_device = NULL; 328*18c2aff7Sartem int ret = B_FALSE; 329*18c2aff7Sartem 330*18c2aff7Sartem if (libhal_device_get_property_bool(hal_ctx, udi, 331*18c2aff7Sartem "volume.ignore", NULL)) { 332*18c2aff7Sartem goto out; 333*18c2aff7Sartem } 334*18c2aff7Sartem 335*18c2aff7Sartem /* get the backing storage device */ 336*18c2aff7Sartem if (!(storage_device = libhal_device_get_property_string(hal_ctx, udi, 337*18c2aff7Sartem "block.storage_device", NULL))) { 338*18c2aff7Sartem dprintf("cannot get block.storage_device\n"); 339*18c2aff7Sartem goto out; 340*18c2aff7Sartem } 341*18c2aff7Sartem 342*18c2aff7Sartem /* we handle either removable or hotpluggable */ 343*18c2aff7Sartem if (!libhal_device_get_property_bool(hal_ctx, storage_device, 344*18c2aff7Sartem "storage.removable", NULL) && 345*18c2aff7Sartem !libhal_device_get_property_bool(hal_ctx, storage_device, 346*18c2aff7Sartem "storage.hotpluggable", NULL)) { 347*18c2aff7Sartem goto out; 348*18c2aff7Sartem } 349*18c2aff7Sartem 350*18c2aff7Sartem /* ignore if claimed by another volume manager */ 351*18c2aff7Sartem if (libhal_device_get_property_bool(hal_ctx, storage_device, 352*18c2aff7Sartem "info.claimed", NULL)) { 353*18c2aff7Sartem goto out; 354*18c2aff7Sartem } 355*18c2aff7Sartem 356*18c2aff7Sartem ret = B_TRUE; 357*18c2aff7Sartem 358*18c2aff7Sartem out: 359*18c2aff7Sartem libhal_free_string(storage_device); 360*18c2aff7Sartem return (ret); 361*18c2aff7Sartem } 362*18c2aff7Sartem 363*18c2aff7Sartem static void 364*18c2aff7Sartem volume_added(const char *udi) 365*18c2aff7Sartem { 366*18c2aff7Sartem GSList *l; 367*18c2aff7Sartem managed_volume_t *v; 368*18c2aff7Sartem 369*18c2aff7Sartem dprintf("volume added %s\n", udi); 370*18c2aff7Sartem 371*18c2aff7Sartem l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi); 372*18c2aff7Sartem v = (l != NULL) ? l->data : NULL; 373*18c2aff7Sartem 374*18c2aff7Sartem if (v != NULL) { 375*18c2aff7Sartem dprintf("already managed %s\n", udi); 376*18c2aff7Sartem return; 377*18c2aff7Sartem } 378*18c2aff7Sartem if (!volume_should_mount(udi)) { 379*18c2aff7Sartem dprintf("should not mount %s\n", udi); 380*18c2aff7Sartem return; 381*18c2aff7Sartem } 382*18c2aff7Sartem if ((v = rmm_managed_alloc(hal_ctx, udi)) == NULL) { 383*18c2aff7Sartem return; 384*18c2aff7Sartem } 385*18c2aff7Sartem if (rmm_action(hal_ctx, udi, INSERT, &v->aa, 0, 0, 0)) { 386*18c2aff7Sartem v->my = B_TRUE; 387*18c2aff7Sartem managed_volumes = g_slist_prepend(managed_volumes, v); 388*18c2aff7Sartem } else { 389*18c2aff7Sartem dprintf("rmm_action failed %s\n", udi); 390*18c2aff7Sartem rmm_managed_free(v); 391*18c2aff7Sartem } 392*18c2aff7Sartem } 393*18c2aff7Sartem 394*18c2aff7Sartem static void 395*18c2aff7Sartem volume_removed(const char *udi) 396*18c2aff7Sartem { 397*18c2aff7Sartem GSList *l; 398*18c2aff7Sartem managed_volume_t *v; 399*18c2aff7Sartem 400*18c2aff7Sartem dprintf("volume removed %s\n", udi); 401*18c2aff7Sartem 402*18c2aff7Sartem l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi); 403*18c2aff7Sartem v = (l != NULL) ? l->data : NULL; 404*18c2aff7Sartem if (v == NULL) { 405*18c2aff7Sartem return; 406*18c2aff7Sartem } 407*18c2aff7Sartem 408*18c2aff7Sartem /* HAL will unmount, just do the vold legacy stuff */ 409*18c2aff7Sartem v->aa.aa_action = EJECT; 410*18c2aff7Sartem (void) vold_postprocess(hal_ctx, udi, &v->aa); 411*18c2aff7Sartem 412*18c2aff7Sartem rmm_managed_free(v); 413*18c2aff7Sartem managed_volumes = g_slist_delete_link(managed_volumes, l); 414*18c2aff7Sartem } 415*18c2aff7Sartem 416*18c2aff7Sartem /* ARGSUSED */ 417*18c2aff7Sartem static void 418*18c2aff7Sartem rmm_device_added(LibHalContext *ctx, const char *udi) 419*18c2aff7Sartem { 420*18c2aff7Sartem if (libhal_device_query_capability(hal_ctx, udi, "volume", NULL)) { 421*18c2aff7Sartem volume_added(udi); 422*18c2aff7Sartem } 423*18c2aff7Sartem } 424*18c2aff7Sartem 425*18c2aff7Sartem /* ARGSUSED */ 426*18c2aff7Sartem static void 427*18c2aff7Sartem rmm_device_removed(LibHalContext *ctx, const char *udi) 428*18c2aff7Sartem { 429*18c2aff7Sartem if (libhal_device_query_capability(hal_ctx, udi, "volume", NULL)) { 430*18c2aff7Sartem volume_removed(udi); 431*18c2aff7Sartem } 432*18c2aff7Sartem } 433*18c2aff7Sartem 434*18c2aff7Sartem /* ARGSUSED */ 435*18c2aff7Sartem static void 436*18c2aff7Sartem rmm_property_modified(LibHalContext *ctx, const char *udi, const char *key, 437*18c2aff7Sartem dbus_bool_t is_removed, dbus_bool_t is_added) 438*18c2aff7Sartem { 439*18c2aff7Sartem DBusError error; 440*18c2aff7Sartem GSList *l; 441*18c2aff7Sartem managed_volume_t *v; 442*18c2aff7Sartem boolean_t is_mounted; 443*18c2aff7Sartem 444*18c2aff7Sartem if (strcmp(key, "volume.is_mounted") != 0) { 445*18c2aff7Sartem return; 446*18c2aff7Sartem } 447*18c2aff7Sartem is_mounted = libhal_device_get_property_bool(hal_ctx, udi, key, NULL); 448*18c2aff7Sartem 449*18c2aff7Sartem l = g_slist_find_custom(managed_volumes, udi, rmm_managed_compare_udi); 450*18c2aff7Sartem v = (l != NULL) ? l->data : NULL; 451*18c2aff7Sartem 452*18c2aff7Sartem if (is_mounted) { 453*18c2aff7Sartem dprintf("Mounted: %s\n", udi); 454*18c2aff7Sartem 455*18c2aff7Sartem if (v != NULL) { 456*18c2aff7Sartem /* volume mounted by us is already taken care of */ 457*18c2aff7Sartem if (v->my) { 458*18c2aff7Sartem return; 459*18c2aff7Sartem } 460*18c2aff7Sartem } else { 461*18c2aff7Sartem if ((v = rmm_managed_alloc(ctx, udi)) == NULL) { 462*18c2aff7Sartem return; 463*18c2aff7Sartem } 464*18c2aff7Sartem managed_volumes = g_slist_prepend(managed_volumes, v); 465*18c2aff7Sartem } 466*18c2aff7Sartem 467*18c2aff7Sartem v->aa.aa_action = INSERT; 468*18c2aff7Sartem (void) vold_postprocess(hal_ctx, udi, &v->aa); 469*18c2aff7Sartem 470*18c2aff7Sartem } else { 471*18c2aff7Sartem dprintf("Unmounted: %s\n", udi); 472*18c2aff7Sartem 473*18c2aff7Sartem if (v == NULL) { 474*18c2aff7Sartem return; 475*18c2aff7Sartem } 476*18c2aff7Sartem 477*18c2aff7Sartem v->aa.aa_action = EJECT; 478*18c2aff7Sartem (void) vold_postprocess(hal_ctx, udi, &v->aa); 479*18c2aff7Sartem 480*18c2aff7Sartem rmm_managed_free(v); 481*18c2aff7Sartem managed_volumes = g_slist_delete_link(managed_volumes, l); 482*18c2aff7Sartem } 483*18c2aff7Sartem } 484*18c2aff7Sartem 485*18c2aff7Sartem /* 486*18c2aff7Sartem * Mount all mountable volumes 487*18c2aff7Sartem */ 488*18c2aff7Sartem static void 489*18c2aff7Sartem rmm_mount_all() 490*18c2aff7Sartem { 491*18c2aff7Sartem DBusError error; 492*18c2aff7Sartem char **udis = NULL; 493*18c2aff7Sartem int num_udis; 494*18c2aff7Sartem int i; 495*18c2aff7Sartem managed_volume_t *v; 496*18c2aff7Sartem 497*18c2aff7Sartem dbus_error_init(&error); 498*18c2aff7Sartem 499*18c2aff7Sartem /* get all volumes */ 500*18c2aff7Sartem if ((udis = libhal_find_device_by_capability(hal_ctx, "volume", 501*18c2aff7Sartem &num_udis, &error)) == NULL) { 502*18c2aff7Sartem dprintf("mount_all: no volumes found\n"); 503*18c2aff7Sartem goto out; 504*18c2aff7Sartem } 505*18c2aff7Sartem 506*18c2aff7Sartem for (i = 0; i < num_udis; i++) { 507*18c2aff7Sartem /* skip if already mounted */ 508*18c2aff7Sartem if (libhal_device_get_property_bool(hal_ctx, udis[i], 509*18c2aff7Sartem "volume.is_mounted", NULL)) { 510*18c2aff7Sartem dprintf("mount_all: %s already mounted\n", udis[i]); 511*18c2aff7Sartem continue; 512*18c2aff7Sartem } 513*18c2aff7Sartem if (!volume_should_mount(udis[i])) { 514*18c2aff7Sartem continue; 515*18c2aff7Sartem } 516*18c2aff7Sartem if ((v = rmm_managed_alloc(hal_ctx, udis[i])) == NULL) { 517*18c2aff7Sartem continue; 518*18c2aff7Sartem } 519*18c2aff7Sartem if (rmm_action(hal_ctx, udis[i], INSERT, &v->aa, 0, 0, 0)) { 520*18c2aff7Sartem v->my = B_TRUE; 521*18c2aff7Sartem managed_volumes = g_slist_prepend(managed_volumes, v); 522*18c2aff7Sartem } else { 523*18c2aff7Sartem rmm_managed_free(v); 524*18c2aff7Sartem } 525*18c2aff7Sartem } 526*18c2aff7Sartem 527*18c2aff7Sartem out: 528*18c2aff7Sartem if (udis != NULL) { 529*18c2aff7Sartem libhal_free_string_array(udis); 530*18c2aff7Sartem } 531*18c2aff7Sartem rmm_dbus_error_free(&error); 532*18c2aff7Sartem } 533*18c2aff7Sartem 534*18c2aff7Sartem /* 535*18c2aff7Sartem * Mount all volumes mounted by this program 536*18c2aff7Sartem */ 537*18c2aff7Sartem static void 538*18c2aff7Sartem rmm_unmount_all() 539*18c2aff7Sartem { 540*18c2aff7Sartem GSList *i; 541*18c2aff7Sartem managed_volume_t *v; 542*18c2aff7Sartem 543*18c2aff7Sartem for (i = managed_volumes; i != NULL; i = managed_volumes) { 544*18c2aff7Sartem v = (managed_volume_t *)i->data; 545*18c2aff7Sartem 546*18c2aff7Sartem if (v->my && libhal_device_get_property_bool(hal_ctx, v->udi, 547*18c2aff7Sartem "volume.is_mounted", NULL)) { 548*18c2aff7Sartem (void) rmm_action(hal_ctx, v->udi, UNMOUNT, 549*18c2aff7Sartem &v->aa, 0, 0, 0); 550*18c2aff7Sartem } 551*18c2aff7Sartem 552*18c2aff7Sartem managed_volumes = g_slist_remove(managed_volumes, v); 553*18c2aff7Sartem rmm_managed_free(v); 554*18c2aff7Sartem } 555*18c2aff7Sartem } 556*18c2aff7Sartem 557*18c2aff7Sartem static int 558*18c2aff7Sartem daemon(int nochdir, int noclose) 559*18c2aff7Sartem { 560*18c2aff7Sartem int fd; 561*18c2aff7Sartem 562*18c2aff7Sartem switch (fork()) { 563*18c2aff7Sartem case -1: 564*18c2aff7Sartem return (-1); 565*18c2aff7Sartem case 0: 566*18c2aff7Sartem break; 567*18c2aff7Sartem default: 568*18c2aff7Sartem exit(0); 569*18c2aff7Sartem } 570*18c2aff7Sartem 571*18c2aff7Sartem if (setsid() == -1) 572*18c2aff7Sartem return (-1); 573*18c2aff7Sartem 574*18c2aff7Sartem if (!nochdir) 575*18c2aff7Sartem (void) chdir("/"); 576*18c2aff7Sartem 577*18c2aff7Sartem if (!noclose) { 578*18c2aff7Sartem struct stat64 st; 579*18c2aff7Sartem 580*18c2aff7Sartem if (((fd = open("/dev/null", O_RDWR, 0)) != -1) && 581*18c2aff7Sartem (fstat64(fd, &st) == 0)) { 582*18c2aff7Sartem if (S_ISCHR(st.st_mode) != 0) { 583*18c2aff7Sartem (void) dup2(fd, STDIN_FILENO); 584*18c2aff7Sartem (void) dup2(fd, STDOUT_FILENO); 585*18c2aff7Sartem (void) dup2(fd, STDERR_FILENO); 586*18c2aff7Sartem if (fd > 2) 587*18c2aff7Sartem (void) close(fd); 588*18c2aff7Sartem } else { 589*18c2aff7Sartem (void) close(fd); 590*18c2aff7Sartem (void) __set_errno(ENODEV); 591*18c2aff7Sartem return (-1); 592*18c2aff7Sartem } 593*18c2aff7Sartem } else { 594*18c2aff7Sartem (void) close(fd); 595*18c2aff7Sartem return (-1); 596*18c2aff7Sartem } 597*18c2aff7Sartem } 598*18c2aff7Sartem return (0); 599*18c2aff7Sartem } 600*18c2aff7Sartem 601*18c2aff7Sartem int 602*18c2aff7Sartem main(int argc, char **argv) 603*18c2aff7Sartem { 604*18c2aff7Sartem vold_init(argc, argv); 605*18c2aff7Sartem 606*18c2aff7Sartem return (rmvolmgr(argc, argv)); 607*18c2aff7Sartem } 608