xref: /titanic_54/usr/src/cmd/rmvolmgr/rmvolmgr.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
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