xref: /titanic_53/usr/src/cmd/rmvolmgr/rmm_common.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 #include <stdio.h>
29*18c2aff7Sartem #include <errno.h>
30*18c2aff7Sartem #include <string.h>
31*18c2aff7Sartem #include <strings.h>
32*18c2aff7Sartem #include <stdarg.h>
33*18c2aff7Sartem #include <fcntl.h>
34*18c2aff7Sartem #include <libintl.h>
35*18c2aff7Sartem #include <stdlib.h>
36*18c2aff7Sartem #include <unistd.h>
37*18c2aff7Sartem #include <ctype.h>
38*18c2aff7Sartem #include <sys/param.h>
39*18c2aff7Sartem #include <sys/types.h>
40*18c2aff7Sartem #include <sys/stat.h>
41*18c2aff7Sartem #include <sys/mnttab.h>
42*18c2aff7Sartem 
43*18c2aff7Sartem #include <dbus/dbus.h>
44*18c2aff7Sartem #include <dbus/dbus-glib.h>
45*18c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
46*18c2aff7Sartem #include <libhal.h>
47*18c2aff7Sartem #include <libhal-storage.h>
48*18c2aff7Sartem 
49*18c2aff7Sartem #include "rmm_common.h"
50*18c2aff7Sartem 
51*18c2aff7Sartem extern int rmm_debug;
52*18c2aff7Sartem 
53*18c2aff7Sartem static const char *action_strings[] = {
54*18c2aff7Sartem 	"eject",
55*18c2aff7Sartem 	"mount",
56*18c2aff7Sartem 	"remount",
57*18c2aff7Sartem 	"unmount",
58*18c2aff7Sartem 	"clear_mounts",
59*18c2aff7Sartem 	"closetray"
60*18c2aff7Sartem };
61*18c2aff7Sartem 
62*18c2aff7Sartem 
63*18c2aff7Sartem LibHalContext *
64*18c2aff7Sartem rmm_hal_init(LibHalDeviceAdded devadd_cb, LibHalDeviceRemoved devrem_cb,
65*18c2aff7Sartem     LibHalDevicePropertyModified propmod_cb,
66*18c2aff7Sartem     DBusError *error, rmm_error_t *rmm_error)
67*18c2aff7Sartem {
68*18c2aff7Sartem 	DBusConnection	*dbus_conn;
69*18c2aff7Sartem 	LibHalContext	*ctx;
70*18c2aff7Sartem 	char		**devices;
71*18c2aff7Sartem 	int		nr;
72*18c2aff7Sartem 
73*18c2aff7Sartem 	dbus_error_init(error);
74*18c2aff7Sartem 
75*18c2aff7Sartem 	/*
76*18c2aff7Sartem 	 * setup D-Bus connection
77*18c2aff7Sartem 	 */
78*18c2aff7Sartem 	if (!(dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, error))) {
79*18c2aff7Sartem 		dprintf("cannot get system bus: %s\n", rmm_strerror(error, -1));
80*18c2aff7Sartem 		*rmm_error = RMM_EDBUS_CONNECT;
81*18c2aff7Sartem 		return (NULL);
82*18c2aff7Sartem 	}
83*18c2aff7Sartem 	rmm_dbus_error_free(error);
84*18c2aff7Sartem 
85*18c2aff7Sartem 	dbus_connection_setup_with_g_main(dbus_conn, NULL);
86*18c2aff7Sartem 	dbus_connection_set_exit_on_disconnect(dbus_conn, B_TRUE);
87*18c2aff7Sartem 
88*18c2aff7Sartem 	if ((ctx = libhal_ctx_new()) == NULL) {
89*18c2aff7Sartem 		dprintf("libhal_ctx_new failed");
90*18c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
91*18c2aff7Sartem 		return (NULL);
92*18c2aff7Sartem 	}
93*18c2aff7Sartem 
94*18c2aff7Sartem 	libhal_ctx_set_dbus_connection(ctx, dbus_conn);
95*18c2aff7Sartem 
96*18c2aff7Sartem 	/*
97*18c2aff7Sartem 	 * register callbacks
98*18c2aff7Sartem 	 */
99*18c2aff7Sartem 	if (devadd_cb != NULL) {
100*18c2aff7Sartem 		libhal_ctx_set_device_added(ctx, devadd_cb);
101*18c2aff7Sartem 	}
102*18c2aff7Sartem 	if (devrem_cb != NULL) {
103*18c2aff7Sartem 		libhal_ctx_set_device_removed(ctx, devrem_cb);
104*18c2aff7Sartem 	}
105*18c2aff7Sartem 	if (propmod_cb != NULL) {
106*18c2aff7Sartem 		libhal_ctx_set_device_property_modified(ctx, propmod_cb);
107*18c2aff7Sartem 		if (!libhal_device_property_watch_all(ctx, error)) {
108*18c2aff7Sartem 			dprintf("property_watch_all failed %s",
109*18c2aff7Sartem 			    rmm_strerror(error, -1));
110*18c2aff7Sartem 			libhal_ctx_free(ctx);
111*18c2aff7Sartem 			*rmm_error = RMM_EHAL_CONNECT;
112*18c2aff7Sartem 			return (NULL);
113*18c2aff7Sartem 		}
114*18c2aff7Sartem 	}
115*18c2aff7Sartem 
116*18c2aff7Sartem 	if (!libhal_ctx_init(ctx, error)) {
117*18c2aff7Sartem 		dprintf("libhal_ctx_init failed: %s", rmm_strerror(error, -1));
118*18c2aff7Sartem 		libhal_ctx_free(ctx);
119*18c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
120*18c2aff7Sartem 		return (NULL);
121*18c2aff7Sartem 	}
122*18c2aff7Sartem 	rmm_dbus_error_free(error);
123*18c2aff7Sartem 
124*18c2aff7Sartem 	/*
125*18c2aff7Sartem 	 * The above functions do not guarantee that HAL is actually running.
126*18c2aff7Sartem 	 * Check by invoking a method.
127*18c2aff7Sartem 	 */
128*18c2aff7Sartem 	if (!(devices = libhal_get_all_devices(ctx, &nr, error))) {
129*18c2aff7Sartem 		dprintf("HAL is not running: %s", rmm_strerror(error, -1));
130*18c2aff7Sartem 		libhal_ctx_shutdown(ctx, NULL);
131*18c2aff7Sartem 		libhal_ctx_free(ctx);
132*18c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
133*18c2aff7Sartem 		return (NULL);
134*18c2aff7Sartem 	} else {
135*18c2aff7Sartem 		rmm_dbus_error_free(error);
136*18c2aff7Sartem 		libhal_free_string_array(devices);
137*18c2aff7Sartem 	}
138*18c2aff7Sartem 
139*18c2aff7Sartem 	return (ctx);
140*18c2aff7Sartem }
141*18c2aff7Sartem 
142*18c2aff7Sartem 
143*18c2aff7Sartem void
144*18c2aff7Sartem rmm_hal_fini(LibHalContext *hal_ctx)
145*18c2aff7Sartem {
146*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
147*18c2aff7Sartem 
148*18c2aff7Sartem 	(void) dbus_connection_close(dbus_conn);
149*18c2aff7Sartem 	(void) libhal_ctx_free(hal_ctx);
150*18c2aff7Sartem }
151*18c2aff7Sartem 
152*18c2aff7Sartem 
153*18c2aff7Sartem /*
154*18c2aff7Sartem  * find volume from any type of name, similar to the old media_findname()
155*18c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
156*18c2aff7Sartem  */
157*18c2aff7Sartem LibHalDrive *
158*18c2aff7Sartem rmm_hal_volume_find(LibHalContext *hal_ctx, const char *name, DBusError *error,
159*18c2aff7Sartem     GSList **volumes)
160*18c2aff7Sartem {
161*18c2aff7Sartem 	LibHalDrive	*drive;
162*18c2aff7Sartem 	char		*p;
163*18c2aff7Sartem 	char		lastc;
164*18c2aff7Sartem 
165*18c2aff7Sartem 	*volumes = NULL;
166*18c2aff7Sartem 
167*18c2aff7Sartem 	/* temporarily remove trailing slash */
168*18c2aff7Sartem 	p = (char *)name + strlen(name) - 1;
169*18c2aff7Sartem 	if (*p == '/') {
170*18c2aff7Sartem 		lastc = *p;
171*18c2aff7Sartem 		*p = '\0';
172*18c2aff7Sartem 	} else {
173*18c2aff7Sartem 		p = NULL;
174*18c2aff7Sartem 	}
175*18c2aff7Sartem 
176*18c2aff7Sartem 	if (name[0] == '/') {
177*18c2aff7Sartem 		if (((drive = rmm_hal_volume_findby(hal_ctx,
178*18c2aff7Sartem 		    "info.udi", name, volumes)) != NULL) ||
179*18c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
180*18c2aff7Sartem 		    "block.device", name, volumes)) != NULL) ||
181*18c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
182*18c2aff7Sartem 		    "block.solaris.raw_device", name, volumes)) != NULL) ||
183*18c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
184*18c2aff7Sartem 		    "volume.mount_point", name, volumes)) != NULL)) {
185*18c2aff7Sartem 			goto out;
186*18c2aff7Sartem 		} else {
187*18c2aff7Sartem 			goto out;
188*18c2aff7Sartem 		}
189*18c2aff7Sartem 	}
190*18c2aff7Sartem 
191*18c2aff7Sartem 	/* try volume label */
192*18c2aff7Sartem 	if ((drive = rmm_hal_volume_findby(hal_ctx,
193*18c2aff7Sartem 	    "volume.label", name, volumes)) != NULL) {
194*18c2aff7Sartem 		goto out;
195*18c2aff7Sartem 	}
196*18c2aff7Sartem 
197*18c2aff7Sartem 	drive = rmm_hal_volume_findby_nickname(hal_ctx, name, volumes);
198*18c2aff7Sartem 
199*18c2aff7Sartem out:
200*18c2aff7Sartem 	if (p != NULL) {
201*18c2aff7Sartem 		*p = lastc;
202*18c2aff7Sartem 	}
203*18c2aff7Sartem 	return (drive);
204*18c2aff7Sartem }
205*18c2aff7Sartem 
206*18c2aff7Sartem /*
207*18c2aff7Sartem  * find default volume. Returns volume pointer and name in 'name'.
208*18c2aff7Sartem  */
209*18c2aff7Sartem LibHalDrive *
210*18c2aff7Sartem rmm_hal_volume_find_default(LibHalContext *hal_ctx, DBusError *error,
211*18c2aff7Sartem     const char **name_out, GSList **volumes)
212*18c2aff7Sartem {
213*18c2aff7Sartem 	LibHalDrive	*drive;
214*18c2aff7Sartem 	static const char *names[] = { "floppy", "cdrom", "rmdisk" };
215*18c2aff7Sartem 	int		i;
216*18c2aff7Sartem 
217*18c2aff7Sartem 	*volumes = NULL;
218*18c2aff7Sartem 
219*18c2aff7Sartem 	for (i = 0; i < NELEM(names); i++) {
220*18c2aff7Sartem 		if ((drive = rmm_hal_volume_findby_nickname(hal_ctx,
221*18c2aff7Sartem 		    names[i], volumes)) != NULL) {
222*18c2aff7Sartem 			/*
223*18c2aff7Sartem 			 * Skip floppy if it has no media.
224*18c2aff7Sartem 			 * XXX might want to actually check for media
225*18c2aff7Sartem 			 * every time instead of relying on volcheck.
226*18c2aff7Sartem 			 */
227*18c2aff7Sartem 			if ((strcmp(names[i], "floppy") != 0) ||
228*18c2aff7Sartem 			    libhal_device_get_property_bool(hal_ctx,
229*18c2aff7Sartem 			    libhal_drive_get_udi(drive),
230*18c2aff7Sartem 			    "storage.removable.media_available", NULL)) {
231*18c2aff7Sartem 				*name_out = names[i];
232*18c2aff7Sartem 				break;
233*18c2aff7Sartem 			}
234*18c2aff7Sartem 		}
235*18c2aff7Sartem 		rmm_dbus_error_free(error);
236*18c2aff7Sartem 	}
237*18c2aff7Sartem 
238*18c2aff7Sartem 	return (drive);
239*18c2aff7Sartem }
240*18c2aff7Sartem 
241*18c2aff7Sartem /*
242*18c2aff7Sartem  * find volume by property=value
243*18c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
244*18c2aff7Sartem  * XXX add support for multiple properties, reduce D-Bus traffic
245*18c2aff7Sartem  */
246*18c2aff7Sartem LibHalDrive *
247*18c2aff7Sartem rmm_hal_volume_findby(LibHalContext *hal_ctx, const char *property,
248*18c2aff7Sartem     const char *value, GSList **volumes)
249*18c2aff7Sartem {
250*18c2aff7Sartem 	DBusError	error;
251*18c2aff7Sartem 	LibHalDrive	*drive = NULL;
252*18c2aff7Sartem 	LibHalVolume	*v = NULL;
253*18c2aff7Sartem 	char		**udis;
254*18c2aff7Sartem 	int		num_udis;
255*18c2aff7Sartem 	int		i;
256*18c2aff7Sartem 
257*18c2aff7Sartem 	*volumes = NULL;
258*18c2aff7Sartem 
259*18c2aff7Sartem 	dbus_error_init(&error);
260*18c2aff7Sartem 
261*18c2aff7Sartem 	/* get all devices with property=value */
262*18c2aff7Sartem 	if ((udis = libhal_manager_find_device_string_match(hal_ctx, property,
263*18c2aff7Sartem 	    value, &num_udis, &error)) == NULL) {
264*18c2aff7Sartem 		rmm_dbus_error_free(&error);
265*18c2aff7Sartem 		return (NULL);
266*18c2aff7Sartem 	}
267*18c2aff7Sartem 
268*18c2aff7Sartem 	/* find volumes among these devices */
269*18c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
270*18c2aff7Sartem 		rmm_dbus_error_free(&error);
271*18c2aff7Sartem 		if (libhal_device_query_capability(hal_ctx, udis[i], "volume",
272*18c2aff7Sartem 		    &error)) {
273*18c2aff7Sartem 			v = libhal_volume_from_udi(hal_ctx, udis[i]);
274*18c2aff7Sartem 			if (v != NULL) {
275*18c2aff7Sartem 				*volumes = g_slist_prepend(*volumes, v);
276*18c2aff7Sartem 			}
277*18c2aff7Sartem 		}
278*18c2aff7Sartem 	}
279*18c2aff7Sartem 
280*18c2aff7Sartem 	/* used prepend, preserve original order */
281*18c2aff7Sartem 	if (*volumes != NULL) {
282*18c2aff7Sartem 		*volumes = g_slist_reverse(*volumes);
283*18c2aff7Sartem 
284*18c2aff7Sartem 		v = (LibHalVolume *)(*volumes)->data;
285*18c2aff7Sartem 		drive = libhal_drive_from_udi(hal_ctx,
286*18c2aff7Sartem 		    libhal_volume_get_storage_device_udi(v));
287*18c2aff7Sartem 		if (drive == NULL) {
288*18c2aff7Sartem 			rmm_volumes_free (*volumes);
289*18c2aff7Sartem 			*volumes = NULL;
290*18c2aff7Sartem 		}
291*18c2aff7Sartem 	}
292*18c2aff7Sartem 
293*18c2aff7Sartem 	libhal_free_string_array(udis);
294*18c2aff7Sartem 	rmm_dbus_error_free(&error);
295*18c2aff7Sartem 
296*18c2aff7Sartem 	return (drive);
297*18c2aff7Sartem }
298*18c2aff7Sartem 
299*18c2aff7Sartem 
300*18c2aff7Sartem /*
301*18c2aff7Sartem  * print nicknames for each available volume
302*18c2aff7Sartem  */
303*18c2aff7Sartem void
304*18c2aff7Sartem rmm_print_volume_nicknames(LibHalContext *hal_ctx, DBusError *error)
305*18c2aff7Sartem {
306*18c2aff7Sartem 	char		**udis;
307*18c2aff7Sartem 	int		num_udis;
308*18c2aff7Sartem 	char		*block_device;
309*18c2aff7Sartem 	char		*drive_udi;
310*18c2aff7Sartem 	char		*volume_label;
311*18c2aff7Sartem 	char		*mount_point;
312*18c2aff7Sartem 	boolean_t	comma;
313*18c2aff7Sartem 	char		**nicknames;
314*18c2aff7Sartem 	int		i, j;
315*18c2aff7Sartem 
316*18c2aff7Sartem 	dbus_error_init(error);
317*18c2aff7Sartem 
318*18c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "volume",
319*18c2aff7Sartem 	    &num_udis, error)) == NULL) {
320*18c2aff7Sartem 		return;
321*18c2aff7Sartem 	}
322*18c2aff7Sartem 
323*18c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
324*18c2aff7Sartem 		if ((block_device = libhal_device_get_property_string(hal_ctx,
325*18c2aff7Sartem 		    udis[i], "block.device", NULL)) == NULL) {
326*18c2aff7Sartem 			continue;
327*18c2aff7Sartem 		}
328*18c2aff7Sartem 		if ((drive_udi = libhal_device_get_property_string(hal_ctx,
329*18c2aff7Sartem 		    udis[i], "block.storage_device", NULL)) == NULL) {
330*18c2aff7Sartem 			libhal_free_string(block_device);
331*18c2aff7Sartem 			continue;
332*18c2aff7Sartem 		}
333*18c2aff7Sartem 		(void) printf("%s\t", block_device);
334*18c2aff7Sartem 		comma = B_FALSE;
335*18c2aff7Sartem 
336*18c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
337*18c2aff7Sartem 		    drive_udi, "storage.solaris.nicknames", NULL)) != NULL) {
338*18c2aff7Sartem 			for (j = 0; nicknames[j] != NULL; j++) {
339*18c2aff7Sartem 				(void) printf("%s%s", comma ? "," : "",
340*18c2aff7Sartem 				    nicknames[j]);
341*18c2aff7Sartem 				comma = B_TRUE;
342*18c2aff7Sartem 			}
343*18c2aff7Sartem 		}
344*18c2aff7Sartem 
345*18c2aff7Sartem 		if (((volume_label = libhal_device_get_property_string(hal_ctx,
346*18c2aff7Sartem 		    udis[i], "volume.label", NULL)) != NULL) &&
347*18c2aff7Sartem 		    (strlen(volume_label) > 0)) {
348*18c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "", volume_label);
349*18c2aff7Sartem 			comma = B_TRUE;
350*18c2aff7Sartem 		}
351*18c2aff7Sartem 
352*18c2aff7Sartem 		if (((mount_point = libhal_device_get_property_string(hal_ctx,
353*18c2aff7Sartem 		    udis[i], "volume.mount_point", NULL)) != NULL) &&
354*18c2aff7Sartem 		    (strlen(mount_point) > 0)) {
355*18c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "", mount_point);
356*18c2aff7Sartem 			comma = B_TRUE;
357*18c2aff7Sartem 		}
358*18c2aff7Sartem 
359*18c2aff7Sartem 		(void) printf("\n");
360*18c2aff7Sartem 
361*18c2aff7Sartem 		libhal_free_string_array(nicknames);
362*18c2aff7Sartem 		libhal_free_string(drive_udi);
363*18c2aff7Sartem 		libhal_free_string(volume_label);
364*18c2aff7Sartem 		libhal_free_string(mount_point);
365*18c2aff7Sartem 		libhal_free_string(block_device);
366*18c2aff7Sartem 	}
367*18c2aff7Sartem 	libhal_free_string_array(udis);
368*18c2aff7Sartem }
369*18c2aff7Sartem 
370*18c2aff7Sartem 
371*18c2aff7Sartem /*
372*18c2aff7Sartem  * find volume by nickname
373*18c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
374*18c2aff7Sartem  */
375*18c2aff7Sartem LibHalDrive *
376*18c2aff7Sartem rmm_hal_volume_findby_nickname(LibHalContext *hal_ctx, const char *name,
377*18c2aff7Sartem     GSList **volumes)
378*18c2aff7Sartem {
379*18c2aff7Sartem 	DBusError	error;
380*18c2aff7Sartem 	LibHalDrive	*drive = NULL;
381*18c2aff7Sartem 	LibHalDrive	*drive_tmp;
382*18c2aff7Sartem 	char		**udis;
383*18c2aff7Sartem 	int		num_udis;
384*18c2aff7Sartem 	char		**nicknames;
385*18c2aff7Sartem 	int		i, j;
386*18c2aff7Sartem 
387*18c2aff7Sartem 	*volumes = NULL;
388*18c2aff7Sartem 
389*18c2aff7Sartem 	dbus_error_init(&error);
390*18c2aff7Sartem 
391*18c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
392*18c2aff7Sartem 	    &num_udis, &error)) == NULL) {
393*18c2aff7Sartem 		rmm_dbus_error_free(&error);
394*18c2aff7Sartem 		return (NULL);
395*18c2aff7Sartem 	}
396*18c2aff7Sartem 
397*18c2aff7Sartem 	/* find a drive by nickname */
398*18c2aff7Sartem 	for (i = 0; (i < num_udis) && (drive == NULL); i++) {
399*18c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
400*18c2aff7Sartem 		    udis[i], "storage.solaris.nicknames", &error)) == NULL) {
401*18c2aff7Sartem 			rmm_dbus_error_free(&error);
402*18c2aff7Sartem 			continue;
403*18c2aff7Sartem 		}
404*18c2aff7Sartem 		for (j = 0; (nicknames[j] != NULL) && (drive == NULL); j++) {
405*18c2aff7Sartem 			if (strcmp(nicknames[j], name) == 0) {
406*18c2aff7Sartem 				drive = libhal_drive_from_udi(hal_ctx, udis[i]);
407*18c2aff7Sartem 			}
408*18c2aff7Sartem 		}
409*18c2aff7Sartem 		libhal_free_string_array(nicknames);
410*18c2aff7Sartem 	}
411*18c2aff7Sartem 	libhal_free_string_array(udis);
412*18c2aff7Sartem 
413*18c2aff7Sartem 	if (drive != NULL) {
414*18c2aff7Sartem 		/* found the drive, now find its volumes */
415*18c2aff7Sartem 		if ((drive_tmp = rmm_hal_volume_findby(hal_ctx,
416*18c2aff7Sartem 		    "block.storage_device", libhal_drive_get_udi(drive),
417*18c2aff7Sartem 		    volumes)) != NULL) {
418*18c2aff7Sartem 			libhal_drive_free(drive_tmp);
419*18c2aff7Sartem 		}
420*18c2aff7Sartem 	}
421*18c2aff7Sartem 
422*18c2aff7Sartem 	rmm_dbus_error_free(&error);
423*18c2aff7Sartem 
424*18c2aff7Sartem 	return (drive);
425*18c2aff7Sartem }
426*18c2aff7Sartem 
427*18c2aff7Sartem void
428*18c2aff7Sartem rmm_volumes_free(GSList *volumes)
429*18c2aff7Sartem {
430*18c2aff7Sartem 	GSList	*i;
431*18c2aff7Sartem 
432*18c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
433*18c2aff7Sartem 		libhal_volume_free((LibHalVolume *)(i->data));
434*18c2aff7Sartem 	}
435*18c2aff7Sartem 	g_slist_free(volumes);
436*18c2aff7Sartem }
437*18c2aff7Sartem 
438*18c2aff7Sartem /*
439*18c2aff7Sartem  * Call HAL's Mount() method on the given device
440*18c2aff7Sartem  */
441*18c2aff7Sartem boolean_t
442*18c2aff7Sartem rmm_hal_mount(LibHalContext *hal_ctx, const char *udi,
443*18c2aff7Sartem     char **opts, int num_opts, char *mountpoint, DBusError *error)
444*18c2aff7Sartem {
445*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
446*18c2aff7Sartem 	DBusMessage	*dmesg, *reply;
447*18c2aff7Sartem 	char		*fstype;
448*18c2aff7Sartem 
449*18c2aff7Sartem 	dprintf("mounting %s...\n", udi);
450*18c2aff7Sartem 
451*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
452*18c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Mount"))) {
453*18c2aff7Sartem 		dprintf(
454*18c2aff7Sartem 		    "mount failed for %s: cannot create dbus message\n", udi);
455*18c2aff7Sartem 		return (B_FALSE);
456*18c2aff7Sartem 	}
457*18c2aff7Sartem 
458*18c2aff7Sartem 	fstype = "";
459*18c2aff7Sartem 	if (mountpoint == NULL) {
460*18c2aff7Sartem 		mountpoint = "";
461*18c2aff7Sartem 	}
462*18c2aff7Sartem 
463*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &mountpoint,
464*18c2aff7Sartem 	    DBUS_TYPE_STRING, &fstype,
465*18c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &opts, num_opts,
466*18c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
467*18c2aff7Sartem 		dprintf("mount failed for %s: cannot append args\n", udi);
468*18c2aff7Sartem 		dbus_message_unref(dmesg);
469*18c2aff7Sartem 		return (B_FALSE);
470*18c2aff7Sartem 	}
471*18c2aff7Sartem 
472*18c2aff7Sartem 	dbus_error_init(error);
473*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
474*18c2aff7Sartem 	    dmesg, -1, error))) {
475*18c2aff7Sartem 		dprintf("mount failed for %s: %s\n", udi, error->message);
476*18c2aff7Sartem 		dbus_message_unref(dmesg);
477*18c2aff7Sartem 		return (B_FALSE);
478*18c2aff7Sartem 	}
479*18c2aff7Sartem 
480*18c2aff7Sartem 	dprintf("mounted %s\n", udi);
481*18c2aff7Sartem 
482*18c2aff7Sartem 	dbus_message_unref(dmesg);
483*18c2aff7Sartem 	dbus_message_unref(reply);
484*18c2aff7Sartem 
485*18c2aff7Sartem 	rmm_dbus_error_free(error);
486*18c2aff7Sartem 
487*18c2aff7Sartem 	return (B_TRUE);
488*18c2aff7Sartem }
489*18c2aff7Sartem 
490*18c2aff7Sartem 
491*18c2aff7Sartem /*
492*18c2aff7Sartem  * Call HAL's Unmount() method on the given device
493*18c2aff7Sartem  */
494*18c2aff7Sartem boolean_t
495*18c2aff7Sartem rmm_hal_unmount(LibHalContext *hal_ctx, const char *udi, DBusError *error)
496*18c2aff7Sartem {
497*18c2aff7Sartem 	DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
498*18c2aff7Sartem 	DBusMessage *dmesg, *reply;
499*18c2aff7Sartem 	char **opts = NULL;
500*18c2aff7Sartem 
501*18c2aff7Sartem 	dprintf("unmounting %s...\n", udi);
502*18c2aff7Sartem 
503*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
504*18c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Unmount"))) {
505*18c2aff7Sartem 		dprintf(
506*18c2aff7Sartem 		    "unmount failed %s: cannot create dbus message\n", udi);
507*18c2aff7Sartem 		return (B_FALSE);
508*18c2aff7Sartem 	}
509*18c2aff7Sartem 
510*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
511*18c2aff7Sartem 	    &opts, 0, DBUS_TYPE_INVALID)) {
512*18c2aff7Sartem 		dprintf("unmount failed %s: cannot append args\n", udi);
513*18c2aff7Sartem 		dbus_message_unref(dmesg);
514*18c2aff7Sartem 		return (B_FALSE);
515*18c2aff7Sartem 	}
516*18c2aff7Sartem 
517*18c2aff7Sartem 	dbus_error_init(error);
518*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
519*18c2aff7Sartem 	    dmesg, -1, error))) {
520*18c2aff7Sartem 		dprintf("unmount failed for %s: %s\n", udi, error->message);
521*18c2aff7Sartem 		dbus_message_unref(dmesg);
522*18c2aff7Sartem 		return (B_FALSE);
523*18c2aff7Sartem 	}
524*18c2aff7Sartem 
525*18c2aff7Sartem 	dprintf("unmounted %s\n", udi);
526*18c2aff7Sartem 
527*18c2aff7Sartem 	dbus_message_unref(dmesg);
528*18c2aff7Sartem 	dbus_message_unref(reply);
529*18c2aff7Sartem 
530*18c2aff7Sartem 	rmm_dbus_error_free(error);
531*18c2aff7Sartem 
532*18c2aff7Sartem 	return (B_TRUE);
533*18c2aff7Sartem }
534*18c2aff7Sartem 
535*18c2aff7Sartem 
536*18c2aff7Sartem /*
537*18c2aff7Sartem  * Call HAL's Eject() method on the given device
538*18c2aff7Sartem  */
539*18c2aff7Sartem boolean_t
540*18c2aff7Sartem rmm_hal_eject(LibHalContext *hal_ctx, const char *udi, DBusError *error)
541*18c2aff7Sartem {
542*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
543*18c2aff7Sartem 	DBusMessage	*dmesg, *reply;
544*18c2aff7Sartem 	char		**options = NULL;
545*18c2aff7Sartem 	uint_t		num_options = 0;
546*18c2aff7Sartem 
547*18c2aff7Sartem 	dprintf("ejecting %s...\n", udi);
548*18c2aff7Sartem 
549*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
550*18c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "Eject"))) {
551*18c2aff7Sartem 		dprintf("eject %s: cannot create dbus message\n", udi);
552*18c2aff7Sartem 		return (B_FALSE);
553*18c2aff7Sartem 	}
554*18c2aff7Sartem 
555*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
556*18c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
557*18c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
558*18c2aff7Sartem 		dprintf("eject %s: cannot append args to dbus message ", udi);
559*18c2aff7Sartem 		dbus_message_unref(dmesg);
560*18c2aff7Sartem 		return (B_FALSE);
561*18c2aff7Sartem 	}
562*18c2aff7Sartem 
563*18c2aff7Sartem 	dbus_error_init(error);
564*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
565*18c2aff7Sartem 	    dmesg, -1, error))) {
566*18c2aff7Sartem 		dprintf("eject %s: %s\n", udi, error->message);
567*18c2aff7Sartem 		dbus_message_unref(dmesg);
568*18c2aff7Sartem 		return (B_FALSE);
569*18c2aff7Sartem 	}
570*18c2aff7Sartem 
571*18c2aff7Sartem 	dprintf("ejected %s\n", udi);
572*18c2aff7Sartem 
573*18c2aff7Sartem 	dbus_message_unref(dmesg);
574*18c2aff7Sartem 	dbus_message_unref(reply);
575*18c2aff7Sartem 
576*18c2aff7Sartem 	rmm_dbus_error_free(error);
577*18c2aff7Sartem 
578*18c2aff7Sartem 	return (B_TRUE);
579*18c2aff7Sartem }
580*18c2aff7Sartem 
581*18c2aff7Sartem /*
582*18c2aff7Sartem  * Call HAL's CloseTray() method on the given device
583*18c2aff7Sartem  */
584*18c2aff7Sartem boolean_t
585*18c2aff7Sartem rmm_hal_closetray(LibHalContext *hal_ctx, const char *udi, DBusError *error)
586*18c2aff7Sartem {
587*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
588*18c2aff7Sartem 	DBusMessage	*dmesg, *reply;
589*18c2aff7Sartem 	char		**options = NULL;
590*18c2aff7Sartem 	uint_t		num_options = 0;
591*18c2aff7Sartem 
592*18c2aff7Sartem 	dprintf("closing tray %s...\n", udi);
593*18c2aff7Sartem 
594*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
595*18c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "CloseTray"))) {
596*18c2aff7Sartem 		dprintf(
597*18c2aff7Sartem 		    "closetray failed for %s: cannot create dbus message\n",
598*18c2aff7Sartem 		    udi);
599*18c2aff7Sartem 		return (B_FALSE);
600*18c2aff7Sartem 	}
601*18c2aff7Sartem 
602*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
603*18c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
604*18c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
605*18c2aff7Sartem 		dprintf("closetray %s: cannot append args to dbus message ",
606*18c2aff7Sartem 		    udi);
607*18c2aff7Sartem 		dbus_message_unref(dmesg);
608*18c2aff7Sartem 		return (B_FALSE);
609*18c2aff7Sartem 	}
610*18c2aff7Sartem 
611*18c2aff7Sartem 	dbus_error_init(error);
612*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
613*18c2aff7Sartem 	    dmesg, -1, error))) {
614*18c2aff7Sartem 		dprintf("closetray failed for %s: %s\n", udi, error->message);
615*18c2aff7Sartem 		dbus_message_unref(dmesg);
616*18c2aff7Sartem 		return (B_FALSE);
617*18c2aff7Sartem 	}
618*18c2aff7Sartem 
619*18c2aff7Sartem 	dprintf("closetray ok %s\n", udi);
620*18c2aff7Sartem 
621*18c2aff7Sartem 	dbus_message_unref(dmesg);
622*18c2aff7Sartem 	dbus_message_unref(reply);
623*18c2aff7Sartem 
624*18c2aff7Sartem 	rmm_dbus_error_free(error);
625*18c2aff7Sartem 
626*18c2aff7Sartem 	return (B_TRUE);
627*18c2aff7Sartem }
628*18c2aff7Sartem 
629*18c2aff7Sartem /*
630*18c2aff7Sartem  * Call HAL's Rescan() method on the given device
631*18c2aff7Sartem  */
632*18c2aff7Sartem boolean_t
633*18c2aff7Sartem rmm_hal_rescan(LibHalContext *hal_ctx, const char *udi, DBusError *error)
634*18c2aff7Sartem {
635*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
636*18c2aff7Sartem 	DBusMessage	*dmesg, *reply;
637*18c2aff7Sartem 
638*18c2aff7Sartem 	dprintf("rescanning %s...\n", udi);
639*18c2aff7Sartem 
640*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
641*18c2aff7Sartem 	    "org.freedesktop.Hal.Device", "Rescan"))) {
642*18c2aff7Sartem 		dprintf("rescan failed for %s: cannot create dbus message\n",
643*18c2aff7Sartem 		    udi);
644*18c2aff7Sartem 		return (B_FALSE);
645*18c2aff7Sartem 	}
646*18c2aff7Sartem 
647*18c2aff7Sartem 	dbus_error_init(error);
648*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
649*18c2aff7Sartem 	    dmesg, -1, error))) {
650*18c2aff7Sartem 		dprintf("rescan failed for %s: %s\n", udi, error->message);
651*18c2aff7Sartem 		dbus_message_unref(dmesg);
652*18c2aff7Sartem 		return (B_FALSE);
653*18c2aff7Sartem 	}
654*18c2aff7Sartem 
655*18c2aff7Sartem 	dprintf("rescan ok %s\n", udi);
656*18c2aff7Sartem 
657*18c2aff7Sartem 	dbus_message_unref(dmesg);
658*18c2aff7Sartem 	dbus_message_unref(reply);
659*18c2aff7Sartem 
660*18c2aff7Sartem 	rmm_dbus_error_free(error);
661*18c2aff7Sartem 
662*18c2aff7Sartem 	return (B_TRUE);
663*18c2aff7Sartem }
664*18c2aff7Sartem 
665*18c2aff7Sartem boolean_t
666*18c2aff7Sartem rmm_hal_claim_branch(LibHalContext *hal_ctx, const char *udi)
667*18c2aff7Sartem {
668*18c2aff7Sartem 	DBusError error;
669*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
670*18c2aff7Sartem 	DBusMessage *dmesg, *reply;
671*18c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
672*18c2aff7Sartem 
673*18c2aff7Sartem 	dprintf("claiming branch %s...\n", udi);
674*18c2aff7Sartem 
675*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
676*18c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
677*18c2aff7Sartem 	    "ClaimBranch"))) {
678*18c2aff7Sartem 		dprintf("cannot create dbus message\n");
679*18c2aff7Sartem 		return (B_FALSE);
680*18c2aff7Sartem 	}
681*18c2aff7Sartem 
682*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
683*18c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
684*18c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
685*18c2aff7Sartem 		dbus_message_unref(dmesg);
686*18c2aff7Sartem 		return (B_FALSE);
687*18c2aff7Sartem 	}
688*18c2aff7Sartem 
689*18c2aff7Sartem 	dbus_error_init(&error);
690*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
691*18c2aff7Sartem 	    dmesg, -1, &error))) {
692*18c2aff7Sartem 		dprintf("cannot send dbus message\n");
693*18c2aff7Sartem 		dbus_message_unref(dmesg);
694*18c2aff7Sartem 		rmm_dbus_error_free(&error);
695*18c2aff7Sartem 		return (B_FALSE);
696*18c2aff7Sartem 	}
697*18c2aff7Sartem 
698*18c2aff7Sartem 	dprintf("claim branch ok %s\n", udi);
699*18c2aff7Sartem 
700*18c2aff7Sartem 	dbus_message_unref(dmesg);
701*18c2aff7Sartem 	dbus_message_unref(reply);
702*18c2aff7Sartem 
703*18c2aff7Sartem 	return (B_TRUE);
704*18c2aff7Sartem }
705*18c2aff7Sartem 
706*18c2aff7Sartem boolean_t
707*18c2aff7Sartem rmm_hal_unclaim_branch(LibHalContext *hal_ctx, const char *udi)
708*18c2aff7Sartem {
709*18c2aff7Sartem 	DBusError error;
710*18c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
711*18c2aff7Sartem 	DBusMessage *dmesg, *reply;
712*18c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
713*18c2aff7Sartem 
714*18c2aff7Sartem 	dprintf("unclaiming branch %s...\n", udi);
715*18c2aff7Sartem 
716*18c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
717*18c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
718*18c2aff7Sartem 	    "UnclaimBranch"))) {
719*18c2aff7Sartem 		dprintf("cannot create dbus message\n");
720*18c2aff7Sartem 		return (B_FALSE);
721*18c2aff7Sartem 	}
722*18c2aff7Sartem 
723*18c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
724*18c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
725*18c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
726*18c2aff7Sartem 		dbus_message_unref(dmesg);
727*18c2aff7Sartem 		return (B_FALSE);
728*18c2aff7Sartem 	}
729*18c2aff7Sartem 
730*18c2aff7Sartem 	dbus_error_init(&error);
731*18c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
732*18c2aff7Sartem 	    dmesg, -1, &error))) {
733*18c2aff7Sartem 		dprintf("cannot send dbus message\n");
734*18c2aff7Sartem 		dbus_message_unref(dmesg);
735*18c2aff7Sartem 		rmm_dbus_error_free(&error);
736*18c2aff7Sartem 		return (B_FALSE);
737*18c2aff7Sartem 	}
738*18c2aff7Sartem 
739*18c2aff7Sartem 	dprintf("unclaim branch ok %s\n", udi);
740*18c2aff7Sartem 
741*18c2aff7Sartem 	dbus_message_unref(dmesg);
742*18c2aff7Sartem 	dbus_message_unref(reply);
743*18c2aff7Sartem 
744*18c2aff7Sartem 	return (B_TRUE);
745*18c2aff7Sartem }
746*18c2aff7Sartem 
747*18c2aff7Sartem static boolean_t
748*18c2aff7Sartem rmm_action_one(LibHalContext *hal_ctx, const char *name, action_t action,
749*18c2aff7Sartem     const char *dev, const char *udi, LibHalVolume *v,
750*18c2aff7Sartem     char **opts, int num_opts, char *mountpoint)
751*18c2aff7Sartem {
752*18c2aff7Sartem 	char		dev_str[MAXPATHLEN];
753*18c2aff7Sartem 	char		*mountp;
754*18c2aff7Sartem 	DBusError	error;
755*18c2aff7Sartem 	boolean_t	ret = B_FALSE;
756*18c2aff7Sartem 
757*18c2aff7Sartem 	if (strcmp(name, dev) == 0) {
758*18c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), name);
759*18c2aff7Sartem 	} else {
760*18c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), "%s %s", name, dev);
761*18c2aff7Sartem 	}
762*18c2aff7Sartem 
763*18c2aff7Sartem 	dbus_error_init(&error);
764*18c2aff7Sartem 
765*18c2aff7Sartem 	switch (action) {
766*18c2aff7Sartem 	case EJECT:
767*18c2aff7Sartem 		ret = rmm_hal_eject(hal_ctx, udi, &error);
768*18c2aff7Sartem 		break;
769*18c2aff7Sartem 	case INSERT:
770*18c2aff7Sartem 	case REMOUNT:
771*18c2aff7Sartem 		if (libhal_volume_is_mounted(v)) {
772*18c2aff7Sartem 			goto done;
773*18c2aff7Sartem 		}
774*18c2aff7Sartem 		ret = rmm_hal_mount(hal_ctx, udi,
775*18c2aff7Sartem 		    opts, num_opts, mountpoint, &error);
776*18c2aff7Sartem 		break;
777*18c2aff7Sartem 	case UNMOUNT:
778*18c2aff7Sartem 		if (!libhal_volume_is_mounted(v)) {
779*18c2aff7Sartem 			goto done;
780*18c2aff7Sartem 		}
781*18c2aff7Sartem 		ret = rmm_hal_unmount(hal_ctx, udi, &error);
782*18c2aff7Sartem 		break;
783*18c2aff7Sartem 	case CLOSETRAY:
784*18c2aff7Sartem 		ret = rmm_hal_closetray(hal_ctx, udi, &error);
785*18c2aff7Sartem 		break;
786*18c2aff7Sartem 	}
787*18c2aff7Sartem 
788*18c2aff7Sartem 	if (!ret) {
789*18c2aff7Sartem 		(void) fprintf(stderr, gettext("%s of %s failed: %s\n"),
790*18c2aff7Sartem 		    action_strings[action], dev_str, rmm_strerror(&error, -1));
791*18c2aff7Sartem 		goto done;
792*18c2aff7Sartem 	}
793*18c2aff7Sartem 
794*18c2aff7Sartem 	switch (action) {
795*18c2aff7Sartem 	case EJECT:
796*18c2aff7Sartem 		(void) printf(gettext("%s ejected\n"), dev_str);
797*18c2aff7Sartem 		break;
798*18c2aff7Sartem 	case INSERT:
799*18c2aff7Sartem 	case REMOUNT:
800*18c2aff7Sartem 		mountp = rmm_get_mnttab_mount_point(dev);
801*18c2aff7Sartem 		if (mountp != NULL) {
802*18c2aff7Sartem 			(void) printf(gettext("%s mounted at %s\n"),
803*18c2aff7Sartem 			    dev_str, mountp);
804*18c2aff7Sartem 			free(mountp);
805*18c2aff7Sartem 		}
806*18c2aff7Sartem 		break;
807*18c2aff7Sartem 	case UNMOUNT:
808*18c2aff7Sartem 		(void) printf(gettext("%s unmounted\n"), dev_str);
809*18c2aff7Sartem 		break;
810*18c2aff7Sartem 	case CLOSETRAY:
811*18c2aff7Sartem 		(void) printf(gettext("%s tray closed\n"), dev_str);
812*18c2aff7Sartem 		break;
813*18c2aff7Sartem 	}
814*18c2aff7Sartem 
815*18c2aff7Sartem done:
816*18c2aff7Sartem 	rmm_dbus_error_free(&error);
817*18c2aff7Sartem 	return (ret);
818*18c2aff7Sartem }
819*18c2aff7Sartem 
820*18c2aff7Sartem /*
821*18c2aff7Sartem  * top level action routine
822*18c2aff7Sartem  *
823*18c2aff7Sartem  * If non-null 'aa' is passed, it will be used, otherwise a local copy
824*18c2aff7Sartem  * will be created.
825*18c2aff7Sartem  */
826*18c2aff7Sartem boolean_t
827*18c2aff7Sartem rmm_action(LibHalContext *hal_ctx, const char *name, action_t action,
828*18c2aff7Sartem     struct action_arg *aap, char **opts, int num_opts, char *mountpoint)
829*18c2aff7Sartem {
830*18c2aff7Sartem 	DBusError	error;
831*18c2aff7Sartem 	GSList		*volumes, *i;
832*18c2aff7Sartem 	LibHalDrive	*d;
833*18c2aff7Sartem 	LibHalVolume	*v;
834*18c2aff7Sartem 	const char	*udi, *d_udi;
835*18c2aff7Sartem 	const char	*dev, *d_dev;
836*18c2aff7Sartem 	struct action_arg aa_local;
837*18c2aff7Sartem 	boolean_t	ret = B_FALSE;
838*18c2aff7Sartem 
839*18c2aff7Sartem 	dprintf("rmm_action %s %s\n", name, action_strings[action]);
840*18c2aff7Sartem 
841*18c2aff7Sartem 	if (aap == NULL) {
842*18c2aff7Sartem 		aap = &aa_local;
843*18c2aff7Sartem 	}
844*18c2aff7Sartem 
845*18c2aff7Sartem 	dbus_error_init(&error);
846*18c2aff7Sartem 
847*18c2aff7Sartem 	/* find the drive and its volumes */
848*18c2aff7Sartem 	d = rmm_hal_volume_find(hal_ctx, name, &error, &volumes);
849*18c2aff7Sartem 	rmm_dbus_error_free(&error);
850*18c2aff7Sartem 	if (d == NULL) {
851*18c2aff7Sartem 		(void) fprintf(stderr, gettext("cannot find '%s'\n"), name);
852*18c2aff7Sartem 		return (B_FALSE);
853*18c2aff7Sartem 	}
854*18c2aff7Sartem 	d_udi = libhal_drive_get_udi(d);
855*18c2aff7Sartem 	d_dev = libhal_drive_get_device_file(d);
856*18c2aff7Sartem 	if ((d_udi == NULL) || (d_dev == NULL)) {
857*18c2aff7Sartem 		goto out;
858*18c2aff7Sartem 	}
859*18c2aff7Sartem 
860*18c2aff7Sartem 	/*
861*18c2aff7Sartem 	 * For those drives that do not require media eject,
862*18c2aff7Sartem 	 * EJECT turns into UNMOUNT.
863*18c2aff7Sartem 	 */
864*18c2aff7Sartem 	if ((action == EJECT) && !libhal_drive_requires_eject(d)) {
865*18c2aff7Sartem 		action = UNMOUNT;
866*18c2aff7Sartem 	}
867*18c2aff7Sartem 
868*18c2aff7Sartem 	/* per drive action */
869*18c2aff7Sartem 	if ((action == EJECT) || (action == CLOSETRAY)) {
870*18c2aff7Sartem 		ret = rmm_action_one(hal_ctx, name, action, d_dev, d_udi, NULL,
871*18c2aff7Sartem 		    opts, num_opts, NULL);
872*18c2aff7Sartem 
873*18c2aff7Sartem 		if (!ret || (action == CLOSETRAY)) {
874*18c2aff7Sartem 			goto out;
875*18c2aff7Sartem 		}
876*18c2aff7Sartem 	}
877*18c2aff7Sartem 
878*18c2aff7Sartem 	/* per volume action */
879*18c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
880*18c2aff7Sartem 		v = (LibHalVolume *)i->data;
881*18c2aff7Sartem 		udi = libhal_volume_get_udi(v);
882*18c2aff7Sartem 		dev = libhal_volume_get_device_file(v);
883*18c2aff7Sartem 
884*18c2aff7Sartem 		if ((udi == NULL) || (dev == NULL)) {
885*18c2aff7Sartem 			continue;
886*18c2aff7Sartem 		}
887*18c2aff7Sartem 		if (aap == &aa_local) {
888*18c2aff7Sartem 			if (!rmm_volume_aa_from_prop(hal_ctx, udi, v, aap)) {
889*18c2aff7Sartem 				dprintf("rmm_volume_aa_from_prop failed %s\n",
890*18c2aff7Sartem 				    udi);
891*18c2aff7Sartem 				continue;
892*18c2aff7Sartem 			}
893*18c2aff7Sartem 		}
894*18c2aff7Sartem 		aap->aa_action = action;
895*18c2aff7Sartem 
896*18c2aff7Sartem 		/* ejected above, just need postprocess */
897*18c2aff7Sartem 		if (action != EJECT) {
898*18c2aff7Sartem 			ret = rmm_action_one(hal_ctx, name, action, dev, udi, v,
899*18c2aff7Sartem 			    opts, num_opts, mountpoint);
900*18c2aff7Sartem 		}
901*18c2aff7Sartem 		if (ret) {
902*18c2aff7Sartem 			(void) vold_postprocess(hal_ctx, udi, aap);
903*18c2aff7Sartem 		}
904*18c2aff7Sartem 
905*18c2aff7Sartem 		libhal_volume_free(v);
906*18c2aff7Sartem 		if (aap == &aa_local) {
907*18c2aff7Sartem 			rmm_volume_aa_free(aap);
908*18c2aff7Sartem 		}
909*18c2aff7Sartem 	}
910*18c2aff7Sartem 
911*18c2aff7Sartem out:
912*18c2aff7Sartem 	g_slist_free(volumes);
913*18c2aff7Sartem 	libhal_drive_free(d);
914*18c2aff7Sartem 
915*18c2aff7Sartem 	return (ret);
916*18c2aff7Sartem }
917*18c2aff7Sartem 
918*18c2aff7Sartem 
919*18c2aff7Sartem /*
920*18c2aff7Sartem  * rescan by name
921*18c2aff7Sartem  * if name is NULL, rescan all drives
922*18c2aff7Sartem  */
923*18c2aff7Sartem boolean_t
924*18c2aff7Sartem rmm_rescan(LibHalContext *hal_ctx, const char *name, boolean_t query)
925*18c2aff7Sartem {
926*18c2aff7Sartem 	DBusError	error;
927*18c2aff7Sartem 	GSList		*volumes;
928*18c2aff7Sartem 	LibHalDrive	*drive = NULL;
929*18c2aff7Sartem 	const char	*drive_udi;
930*18c2aff7Sartem 	char		**udis;
931*18c2aff7Sartem 	int		num_udis;
932*18c2aff7Sartem 	char		*nickname;
933*18c2aff7Sartem 	char		**nicks = NULL;
934*18c2aff7Sartem 	boolean_t	do_free_udis = FALSE;
935*18c2aff7Sartem 	int		i;
936*18c2aff7Sartem 	int		ret = 0;
937*18c2aff7Sartem 
938*18c2aff7Sartem 	dprintf("rmm_rescan %s\n", name != NULL ? name : "all");
939*18c2aff7Sartem 
940*18c2aff7Sartem 	dbus_error_init(&error);
941*18c2aff7Sartem 
942*18c2aff7Sartem 	if (name != NULL) {
943*18c2aff7Sartem 		if ((drive = rmm_hal_volume_find(hal_ctx, name, &error,
944*18c2aff7Sartem 		    &volumes)) == NULL) {
945*18c2aff7Sartem 			rmm_dbus_error_free(&error);
946*18c2aff7Sartem 			(void) fprintf(stderr,
947*18c2aff7Sartem 			    gettext("cannot find '%s'\n"), name);
948*18c2aff7Sartem 			return (B_FALSE);
949*18c2aff7Sartem 		}
950*18c2aff7Sartem 		rmm_dbus_error_free(&error);
951*18c2aff7Sartem 		g_slist_free(volumes);
952*18c2aff7Sartem 
953*18c2aff7Sartem 		drive_udi = libhal_drive_get_udi(drive);
954*18c2aff7Sartem 		udis = (char **)&drive_udi;
955*18c2aff7Sartem 		num_udis = 1;
956*18c2aff7Sartem 	} else {
957*18c2aff7Sartem 		if ((udis = libhal_find_device_by_capability(hal_ctx,
958*18c2aff7Sartem 		    "storage", &num_udis, &error)) == NULL) {
959*18c2aff7Sartem 			rmm_dbus_error_free(&error);
960*18c2aff7Sartem 			return (B_TRUE);
961*18c2aff7Sartem 		}
962*18c2aff7Sartem 		rmm_dbus_error_free(&error);
963*18c2aff7Sartem 		do_free_udis = TRUE;
964*18c2aff7Sartem 	}
965*18c2aff7Sartem 
966*18c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
967*18c2aff7Sartem 		if (name == NULL) {
968*18c2aff7Sartem 			nicks = libhal_device_get_property_strlist(hal_ctx,
969*18c2aff7Sartem 			    udis[i], "storage.solaris.nicknames", NULL);
970*18c2aff7Sartem 			if (nicks != NULL) {
971*18c2aff7Sartem 				nickname = nicks[0];
972*18c2aff7Sartem 			} else {
973*18c2aff7Sartem 				nickname = "";
974*18c2aff7Sartem 			}
975*18c2aff7Sartem 		}
976*18c2aff7Sartem 		if (!(ret = rmm_hal_rescan(hal_ctx, udis[i], &error))) {
977*18c2aff7Sartem 			(void) fprintf(stderr,
978*18c2aff7Sartem 			    gettext("rescan of %s failed: %s\n"),
979*18c2aff7Sartem 			    name ? name : nickname,
980*18c2aff7Sartem 			    rmm_strerror(&error, -1));
981*18c2aff7Sartem 			libhal_free_string_array(nicks);
982*18c2aff7Sartem 			continue;
983*18c2aff7Sartem 		}
984*18c2aff7Sartem 		if (query) {
985*18c2aff7Sartem 			printf(gettext("%s is%s available\n"),
986*18c2aff7Sartem 			    name ? name : nickname,
987*18c2aff7Sartem 			    libhal_device_get_property_bool(hal_ctx, udis[i],
988*18c2aff7Sartem 			    "storage.removable.media_available", NULL) ?
989*18c2aff7Sartem 			    "" : " not");
990*18c2aff7Sartem 		}
991*18c2aff7Sartem 		libhal_free_string_array(nicks);
992*18c2aff7Sartem 	}
993*18c2aff7Sartem 
994*18c2aff7Sartem 	if (drive != NULL) {
995*18c2aff7Sartem 		libhal_drive_free(drive);
996*18c2aff7Sartem 	}
997*18c2aff7Sartem 	if (do_free_udis) {
998*18c2aff7Sartem 		libhal_free_string_array(udis);
999*18c2aff7Sartem 	}
1000*18c2aff7Sartem 
1001*18c2aff7Sartem 	return (ret);
1002*18c2aff7Sartem }
1003*18c2aff7Sartem 
1004*18c2aff7Sartem 
1005*18c2aff7Sartem /*
1006*18c2aff7Sartem  * set action_arg from volume properties
1007*18c2aff7Sartem  */
1008*18c2aff7Sartem boolean_t
1009*18c2aff7Sartem rmm_volume_aa_from_prop(LibHalContext *hal_ctx, const char *udi_arg,
1010*18c2aff7Sartem     LibHalVolume *volume_arg, struct action_arg *aap)
1011*18c2aff7Sartem {
1012*18c2aff7Sartem 	LibHalVolume	*volume = volume_arg;
1013*18c2aff7Sartem 	const char	*udi = udi_arg;
1014*18c2aff7Sartem 	const char	*drive_udi;
1015*18c2aff7Sartem 	char		*volume_label;
1016*18c2aff7Sartem 	char		*mountpoint;
1017*18c2aff7Sartem 	int		len;
1018*18c2aff7Sartem 	int		ret = B_FALSE;
1019*18c2aff7Sartem 
1020*18c2aff7Sartem 	/* at least udi or volume must be supplied */
1021*18c2aff7Sartem 	if ((udi == NULL) && (volume == NULL)) {
1022*18c2aff7Sartem 		return (B_FALSE);
1023*18c2aff7Sartem 	}
1024*18c2aff7Sartem 	if (volume == NULL) {
1025*18c2aff7Sartem 		if ((volume = libhal_volume_from_udi(hal_ctx, udi)) == NULL) {
1026*18c2aff7Sartem 			dprintf("cannot get volume %s\n", udi);
1027*18c2aff7Sartem 			goto out;
1028*18c2aff7Sartem 		}
1029*18c2aff7Sartem 	}
1030*18c2aff7Sartem 	if (udi == NULL) {
1031*18c2aff7Sartem 		if ((udi = libhal_volume_get_udi(volume)) == NULL) {
1032*18c2aff7Sartem 			dprintf("cannot get udi\n");
1033*18c2aff7Sartem 			goto out;
1034*18c2aff7Sartem 		}
1035*18c2aff7Sartem 	}
1036*18c2aff7Sartem 	drive_udi = libhal_volume_get_storage_device_udi(volume);
1037*18c2aff7Sartem 
1038*18c2aff7Sartem 	if (!(aap->aa_symdev = libhal_device_get_property_string(hal_ctx,
1039*18c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.symdev", NULL))) {
1040*18c2aff7Sartem 		dprintf("property %s not found %s\n",
1041*18c2aff7Sartem 		    "storage.solaris.legacy.symdev", drive_udi);
1042*18c2aff7Sartem 		goto out;
1043*18c2aff7Sartem 	}
1044*18c2aff7Sartem 	if (!(aap->aa_media = libhal_device_get_property_string(hal_ctx,
1045*18c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.media_type", NULL))) {
1046*18c2aff7Sartem 		dprintf("property %s not found %s\n",
1047*18c2aff7Sartem 		    "storage.solaris.legacy.media_type", drive_udi);
1048*18c2aff7Sartem 		goto out;
1049*18c2aff7Sartem 	}
1050*18c2aff7Sartem 
1051*18c2aff7Sartem 	/* name is derived from volume label */
1052*18c2aff7Sartem 	aap->aa_name = NULL;
1053*18c2aff7Sartem 	if ((volume_label = (char *)libhal_device_get_property_string(hal_ctx,
1054*18c2aff7Sartem 	    udi, "volume.label", NULL)) != NULL) {
1055*18c2aff7Sartem 		if ((len = strlen(volume_label)) > 0) {
1056*18c2aff7Sartem 			aap->aa_name = rmm_vold_convert_volume_label(
1057*18c2aff7Sartem 			    volume_label, len);
1058*18c2aff7Sartem 			if (strlen(aap->aa_name) == 0) {
1059*18c2aff7Sartem 				free(aap->aa_name);
1060*18c2aff7Sartem 				aap->aa_name = NULL;
1061*18c2aff7Sartem 			}
1062*18c2aff7Sartem 		}
1063*18c2aff7Sartem 		libhal_free_string(volume_label);
1064*18c2aff7Sartem 	}
1065*18c2aff7Sartem 	/* if no label, then unnamed_<mediatype> */
1066*18c2aff7Sartem 	if (aap->aa_name == NULL) {
1067*18c2aff7Sartem 		aap->aa_name = (char *)calloc(1, sizeof ("unnamed_floppyNNNN"));
1068*18c2aff7Sartem 		if (aap->aa_name == NULL) {
1069*18c2aff7Sartem 			goto out;
1070*18c2aff7Sartem 		}
1071*18c2aff7Sartem 		(void) snprintf(aap->aa_name, sizeof ("unnamed_floppyNNNN"),
1072*18c2aff7Sartem 		    "unnamed_%s", aap->aa_media);
1073*18c2aff7Sartem 	}
1074*18c2aff7Sartem 
1075*18c2aff7Sartem 	if (!(aap->aa_path = libhal_device_get_property_string(hal_ctx, udi,
1076*18c2aff7Sartem 	    "block.device", NULL))) {
1077*18c2aff7Sartem 		dprintf("property %s not found %s\n", "block.device", udi);
1078*18c2aff7Sartem 		goto out;
1079*18c2aff7Sartem 	}
1080*18c2aff7Sartem 	if (!(aap->aa_rawpath = libhal_device_get_property_string(hal_ctx, udi,
1081*18c2aff7Sartem 	    "block.solaris.raw_device", NULL))) {
1082*18c2aff7Sartem 		dprintf("property %s not found %s\n",
1083*18c2aff7Sartem 		    "block.solaris.raw_device", udi);
1084*18c2aff7Sartem 		goto out;
1085*18c2aff7Sartem 	}
1086*18c2aff7Sartem 	if (!(aap->aa_type = libhal_device_get_property_string(hal_ctx, udi,
1087*18c2aff7Sartem 	    "volume.fstype", NULL))) {
1088*18c2aff7Sartem 		dprintf("property %s not found %s\n", "volume.fstype", udi);
1089*18c2aff7Sartem 		goto out;
1090*18c2aff7Sartem 	}
1091*18c2aff7Sartem 	if (!libhal_device_get_property_bool(hal_ctx, udi,
1092*18c2aff7Sartem 	    "volume.is_partition", NULL)) {
1093*18c2aff7Sartem 		aap->aa_partname = NULL;
1094*18c2aff7Sartem 	} else if (!(aap->aa_partname = libhal_device_get_property_string(
1095*18c2aff7Sartem 	    hal_ctx, udi, "block.solaris.slice", NULL))) {
1096*18c2aff7Sartem 		dprintf("property %s not found %s\n",
1097*18c2aff7Sartem 		    "block.solaris.slice", udi);
1098*18c2aff7Sartem 		goto out;
1099*18c2aff7Sartem 	}
1100*18c2aff7Sartem 	if (!(mountpoint = libhal_device_get_property_string(hal_ctx, udi,
1101*18c2aff7Sartem 	    "volume.mount_point", NULL))) {
1102*18c2aff7Sartem 		dprintf("property %s not found %s\n",
1103*18c2aff7Sartem 		    "volume.mount_point", udi);
1104*18c2aff7Sartem 		goto out;
1105*18c2aff7Sartem 	}
1106*18c2aff7Sartem 	/*
1107*18c2aff7Sartem 	 * aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint()
1108*18c2aff7Sartem 	 * won't have to choose between free() or libhal_free_string() later on
1109*18c2aff7Sartem 	 */
1110*18c2aff7Sartem 	aap->aa_mountpoint = strdup(mountpoint);
1111*18c2aff7Sartem 	libhal_free_string(mountpoint);
1112*18c2aff7Sartem 	if (aap->aa_mountpoint == NULL) {
1113*18c2aff7Sartem 		dprintf("mountpoint is NULL %s\n", udi);
1114*18c2aff7Sartem 		goto out;
1115*18c2aff7Sartem 	}
1116*18c2aff7Sartem 
1117*18c2aff7Sartem 	ret = B_TRUE;
1118*18c2aff7Sartem 
1119*18c2aff7Sartem out:
1120*18c2aff7Sartem 	if ((volume != NULL) && (volume != volume_arg)) {
1121*18c2aff7Sartem 		libhal_volume_free(volume);
1122*18c2aff7Sartem 	}
1123*18c2aff7Sartem 	if (!ret) {
1124*18c2aff7Sartem 		rmm_volume_aa_free(aap);
1125*18c2aff7Sartem 	}
1126*18c2aff7Sartem 	return (ret);
1127*18c2aff7Sartem }
1128*18c2aff7Sartem 
1129*18c2aff7Sartem /* ARGSUSED */
1130*18c2aff7Sartem void
1131*18c2aff7Sartem rmm_volume_aa_update_mountpoint(LibHalContext *hal_ctx, const char *udi,
1132*18c2aff7Sartem     struct action_arg *aap)
1133*18c2aff7Sartem {
1134*18c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
1135*18c2aff7Sartem 		free(aap->aa_mountpoint);
1136*18c2aff7Sartem 	}
1137*18c2aff7Sartem 	aap->aa_mountpoint = rmm_get_mnttab_mount_point(aap->aa_path);
1138*18c2aff7Sartem }
1139*18c2aff7Sartem 
1140*18c2aff7Sartem void
1141*18c2aff7Sartem rmm_volume_aa_free(struct action_arg *aap)
1142*18c2aff7Sartem {
1143*18c2aff7Sartem 	if (aap->aa_symdev != NULL) {
1144*18c2aff7Sartem 		libhal_free_string(aap->aa_symdev);
1145*18c2aff7Sartem 		aap->aa_symdev = NULL;
1146*18c2aff7Sartem 	}
1147*18c2aff7Sartem 	if (aap->aa_name != NULL) {
1148*18c2aff7Sartem 		free(aap->aa_name);
1149*18c2aff7Sartem 		aap->aa_name = NULL;
1150*18c2aff7Sartem 	}
1151*18c2aff7Sartem 	if (aap->aa_path != NULL) {
1152*18c2aff7Sartem 		libhal_free_string(aap->aa_path);
1153*18c2aff7Sartem 		aap->aa_path = NULL;
1154*18c2aff7Sartem 	}
1155*18c2aff7Sartem 	if (aap->aa_rawpath != NULL) {
1156*18c2aff7Sartem 		libhal_free_string(aap->aa_rawpath);
1157*18c2aff7Sartem 		aap->aa_rawpath = NULL;
1158*18c2aff7Sartem 	}
1159*18c2aff7Sartem 	if (aap->aa_type != NULL) {
1160*18c2aff7Sartem 		libhal_free_string(aap->aa_type);
1161*18c2aff7Sartem 		aap->aa_type = NULL;
1162*18c2aff7Sartem 	}
1163*18c2aff7Sartem 	if (aap->aa_media != NULL) {
1164*18c2aff7Sartem 		libhal_free_string(aap->aa_media);
1165*18c2aff7Sartem 		aap->aa_media = NULL;
1166*18c2aff7Sartem 	}
1167*18c2aff7Sartem 	if (aap->aa_partname != NULL) {
1168*18c2aff7Sartem 		libhal_free_string(aap->aa_partname);
1169*18c2aff7Sartem 		aap->aa_partname = NULL;
1170*18c2aff7Sartem 	}
1171*18c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
1172*18c2aff7Sartem 		free(aap->aa_mountpoint);
1173*18c2aff7Sartem 		aap->aa_mountpoint = NULL;
1174*18c2aff7Sartem 	}
1175*18c2aff7Sartem }
1176*18c2aff7Sartem 
1177*18c2aff7Sartem /*
1178*18c2aff7Sartem  * get device's mount point from mnttab
1179*18c2aff7Sartem  */
1180*18c2aff7Sartem char *
1181*18c2aff7Sartem rmm_get_mnttab_mount_point(const char *special)
1182*18c2aff7Sartem {
1183*18c2aff7Sartem 	char		*mount_point = NULL;
1184*18c2aff7Sartem 	FILE		*f;
1185*18c2aff7Sartem 	struct mnttab	mnt;
1186*18c2aff7Sartem 	struct mnttab	mpref = { NULL, NULL, NULL, NULL, NULL };
1187*18c2aff7Sartem 
1188*18c2aff7Sartem 	if ((f = fopen(MNTTAB, "r")) != NULL) {
1189*18c2aff7Sartem 		mpref.mnt_special = (char *)special;
1190*18c2aff7Sartem 		if (getmntany(f, &mnt, &mpref) == 0) {
1191*18c2aff7Sartem 			mount_point = strdup(mnt.mnt_mountp);
1192*18c2aff7Sartem 		}
1193*18c2aff7Sartem 		fclose(f);
1194*18c2aff7Sartem 	}
1195*18c2aff7Sartem 
1196*18c2aff7Sartem 	return (mount_point);
1197*18c2aff7Sartem }
1198*18c2aff7Sartem 
1199*18c2aff7Sartem 
1200*18c2aff7Sartem /*
1201*18c2aff7Sartem  * get human readable string from error values
1202*18c2aff7Sartem  */
1203*18c2aff7Sartem const char *
1204*18c2aff7Sartem rmm_strerror(DBusError *dbus_error, int rmm_error)
1205*18c2aff7Sartem {
1206*18c2aff7Sartem 	const char	*str;
1207*18c2aff7Sartem 
1208*18c2aff7Sartem 	if ((dbus_error != NULL) && dbus_error_is_set(dbus_error)) {
1209*18c2aff7Sartem 		str = dbus_error->message;
1210*18c2aff7Sartem 	} else {
1211*18c2aff7Sartem 		switch (rmm_error) {
1212*18c2aff7Sartem 		case RMM_EOK:
1213*18c2aff7Sartem 			str = gettext("success");
1214*18c2aff7Sartem 			break;
1215*18c2aff7Sartem 		case RMM_EDBUS_CONNECT:
1216*18c2aff7Sartem 			str = gettext("cannot connect to D-Bus");
1217*18c2aff7Sartem 			break;
1218*18c2aff7Sartem 		case RMM_EHAL_CONNECT:
1219*18c2aff7Sartem 			str = gettext("cannot connect to HAL");
1220*18c2aff7Sartem 			break;
1221*18c2aff7Sartem 		default:
1222*18c2aff7Sartem 			str = gettext("undefined error");
1223*18c2aff7Sartem 			break;
1224*18c2aff7Sartem 		}
1225*18c2aff7Sartem 	}
1226*18c2aff7Sartem 
1227*18c2aff7Sartem 	return (str);
1228*18c2aff7Sartem }
1229*18c2aff7Sartem 
1230*18c2aff7Sartem void
1231*18c2aff7Sartem rmm_dbus_error_free(DBusError *error)
1232*18c2aff7Sartem {
1233*18c2aff7Sartem 	if (error != NULL && dbus_error_is_set(error)) {
1234*18c2aff7Sartem 		dbus_error_free(error);
1235*18c2aff7Sartem 	}
1236*18c2aff7Sartem }
1237*18c2aff7Sartem 
1238*18c2aff7Sartem static int
1239*18c2aff7Sartem rmm_vold_isbadchar(int c)
1240*18c2aff7Sartem {
1241*18c2aff7Sartem 	int	ret_val = 0;
1242*18c2aff7Sartem 
1243*18c2aff7Sartem 
1244*18c2aff7Sartem 	switch (c) {
1245*18c2aff7Sartem 	case '/':
1246*18c2aff7Sartem 	case ';':
1247*18c2aff7Sartem 	case '|':
1248*18c2aff7Sartem 		ret_val = 1;
1249*18c2aff7Sartem 		break;
1250*18c2aff7Sartem 	default:
1251*18c2aff7Sartem 		if (iscntrl(c) || isspace(c)) {
1252*18c2aff7Sartem 			ret_val = 1;
1253*18c2aff7Sartem 		}
1254*18c2aff7Sartem 	}
1255*18c2aff7Sartem 
1256*18c2aff7Sartem 	return (ret_val);
1257*18c2aff7Sartem }
1258*18c2aff7Sartem 
1259*18c2aff7Sartem char *
1260*18c2aff7Sartem rmm_vold_convert_volume_label(const char *name, size_t len)
1261*18c2aff7Sartem {
1262*18c2aff7Sartem 	char	buf[MAXNAMELEN+1];
1263*18c2aff7Sartem 	char	*s = buf;
1264*18c2aff7Sartem 	int	i;
1265*18c2aff7Sartem 
1266*18c2aff7Sartem 	if (len > MAXNAMELEN) {
1267*18c2aff7Sartem 		len = MAXNAMELEN;
1268*18c2aff7Sartem 	}
1269*18c2aff7Sartem 
1270*18c2aff7Sartem 	for (i = 0; i < len; i++) {
1271*18c2aff7Sartem 		if (name[i] == '\0') {
1272*18c2aff7Sartem 			break;
1273*18c2aff7Sartem 		}
1274*18c2aff7Sartem 		if (isgraph((int)name[i])) {
1275*18c2aff7Sartem 			if (isupper((int)name[i])) {
1276*18c2aff7Sartem 				*s++ = tolower((int)name[i]);
1277*18c2aff7Sartem 			} else if (rmm_vold_isbadchar((int)name[i])) {
1278*18c2aff7Sartem 				*s++ = '_';
1279*18c2aff7Sartem 			} else {
1280*18c2aff7Sartem 				*s++ = name[i];
1281*18c2aff7Sartem 			}
1282*18c2aff7Sartem 		}
1283*18c2aff7Sartem 	}
1284*18c2aff7Sartem 	*s = '\0';
1285*18c2aff7Sartem 	s = strdup(buf);
1286*18c2aff7Sartem 
1287*18c2aff7Sartem 	return (s);
1288*18c2aff7Sartem }
1289*18c2aff7Sartem 
1290*18c2aff7Sartem /*
1291*18c2aff7Sartem  * swiped from mkdir.c
1292*18c2aff7Sartem  */
1293*18c2aff7Sartem int
1294*18c2aff7Sartem makepath(char *dir, mode_t mode)
1295*18c2aff7Sartem {
1296*18c2aff7Sartem 	int		err;
1297*18c2aff7Sartem 	char		*slash;
1298*18c2aff7Sartem 
1299*18c2aff7Sartem 
1300*18c2aff7Sartem 	if ((mkdir(dir, mode) == 0) || (errno == EEXIST)) {
1301*18c2aff7Sartem 		return (0);
1302*18c2aff7Sartem 	}
1303*18c2aff7Sartem 	if (errno != ENOENT) {
1304*18c2aff7Sartem 		return (-1);
1305*18c2aff7Sartem 	}
1306*18c2aff7Sartem 	if ((slash = strrchr(dir, '/')) == NULL) {
1307*18c2aff7Sartem 		return (-1);
1308*18c2aff7Sartem 	}
1309*18c2aff7Sartem 	*slash = '\0';
1310*18c2aff7Sartem 	err = makepath(dir, mode);
1311*18c2aff7Sartem 	*slash++ = '/';
1312*18c2aff7Sartem 
1313*18c2aff7Sartem 	if (err || (*slash == '\0')) {
1314*18c2aff7Sartem 		return (err);
1315*18c2aff7Sartem 	}
1316*18c2aff7Sartem 
1317*18c2aff7Sartem 	return (mkdir(dir, mode));
1318*18c2aff7Sartem }
1319*18c2aff7Sartem 
1320*18c2aff7Sartem 
1321*18c2aff7Sartem void
1322*18c2aff7Sartem dprintf(const char *fmt, ...)
1323*18c2aff7Sartem {
1324*18c2aff7Sartem 
1325*18c2aff7Sartem 	va_list		ap;
1326*18c2aff7Sartem 	const char	*p;
1327*18c2aff7Sartem 	char		msg[BUFSIZ];
1328*18c2aff7Sartem 	char		*errmsg = strerror(errno);
1329*18c2aff7Sartem 	char		*s;
1330*18c2aff7Sartem 
1331*18c2aff7Sartem 	if (rmm_debug == 0) {
1332*18c2aff7Sartem 		return;
1333*18c2aff7Sartem 	}
1334*18c2aff7Sartem 
1335*18c2aff7Sartem 	(void) memset(msg, 0, BUFSIZ);
1336*18c2aff7Sartem 
1337*18c2aff7Sartem 	/* scan for %m and replace with errno msg */
1338*18c2aff7Sartem 	s = &msg[strlen(msg)];
1339*18c2aff7Sartem 	p = fmt;
1340*18c2aff7Sartem 
1341*18c2aff7Sartem 	while (*p != '\0') {
1342*18c2aff7Sartem 		if ((*p == '%') && (*(p+1) == 'm')) {
1343*18c2aff7Sartem 			(void) strcat(s, errmsg);
1344*18c2aff7Sartem 			p += 2;
1345*18c2aff7Sartem 			s += strlen(errmsg);
1346*18c2aff7Sartem 			continue;
1347*18c2aff7Sartem 		}
1348*18c2aff7Sartem 		*s++ = *p++;
1349*18c2aff7Sartem 	}
1350*18c2aff7Sartem 	*s = '\0';	/* don't forget the null byte */
1351*18c2aff7Sartem 
1352*18c2aff7Sartem 	va_start(ap, fmt);
1353*18c2aff7Sartem 	(void) vfprintf(stderr, msg, ap);
1354*18c2aff7Sartem 	va_end(ap);
1355*18c2aff7Sartem }
1356