xref: /titanic_53/usr/src/cmd/rmvolmgr/rmm_common.c (revision b941d3fc4e70b4411341c7aeb53517bbff5f2df4)
118c2aff7Sartem /*
218c2aff7Sartem  * CDDL HEADER START
318c2aff7Sartem  *
418c2aff7Sartem  * The contents of this file are subject to the terms of the
518c2aff7Sartem  * Common Development and Distribution License (the "License").
618c2aff7Sartem  * You may not use this file except in compliance with the License.
718c2aff7Sartem  *
818c2aff7Sartem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
918c2aff7Sartem  * or http://www.opensolaris.org/os/licensing.
1018c2aff7Sartem  * See the License for the specific language governing permissions
1118c2aff7Sartem  * and limitations under the License.
1218c2aff7Sartem  *
1318c2aff7Sartem  * When distributing Covered Code, include this CDDL HEADER in each
1418c2aff7Sartem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1518c2aff7Sartem  * If applicable, add the following below this CDDL HEADER, with the
1618c2aff7Sartem  * fields enclosed by brackets "[]" replaced with your own identifying
1718c2aff7Sartem  * information: Portions Copyright [yyyy] [name of copyright owner]
1818c2aff7Sartem  *
1918c2aff7Sartem  * CDDL HEADER END
2018c2aff7Sartem  */
2118c2aff7Sartem /*
22*b941d3fcSartem  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2318c2aff7Sartem  * Use is subject to license terms.
2418c2aff7Sartem  */
2518c2aff7Sartem 
2618c2aff7Sartem #pragma ident	"%Z%%M%	%I%	%E% SMI"
2718c2aff7Sartem 
2818c2aff7Sartem #include <stdio.h>
2918c2aff7Sartem #include <errno.h>
3018c2aff7Sartem #include <string.h>
3118c2aff7Sartem #include <strings.h>
3218c2aff7Sartem #include <stdarg.h>
3318c2aff7Sartem #include <fcntl.h>
3418c2aff7Sartem #include <libintl.h>
3518c2aff7Sartem #include <stdlib.h>
3618c2aff7Sartem #include <unistd.h>
3718c2aff7Sartem #include <ctype.h>
3818c2aff7Sartem #include <sys/param.h>
3918c2aff7Sartem #include <sys/types.h>
4018c2aff7Sartem #include <sys/stat.h>
4118c2aff7Sartem #include <sys/mnttab.h>
4218c2aff7Sartem 
4318c2aff7Sartem #include <dbus/dbus.h>
4418c2aff7Sartem #include <dbus/dbus-glib.h>
4518c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
4618c2aff7Sartem #include <libhal.h>
4718c2aff7Sartem #include <libhal-storage.h>
4818c2aff7Sartem 
4918c2aff7Sartem #include "rmm_common.h"
5018c2aff7Sartem 
510ebe3100Sartem #define	RMM_PRINT_DEVICE_WIDTH	20
520ebe3100Sartem 
5318c2aff7Sartem extern int rmm_debug;
5418c2aff7Sartem 
5518c2aff7Sartem static const char *action_strings[] = {
5618c2aff7Sartem 	"eject",
5718c2aff7Sartem 	"mount",
5818c2aff7Sartem 	"remount",
5918c2aff7Sartem 	"unmount",
6018c2aff7Sartem 	"clear_mounts",
6118c2aff7Sartem 	"closetray"
6218c2aff7Sartem };
6318c2aff7Sartem 
6418c2aff7Sartem 
6518c2aff7Sartem LibHalContext *
6618c2aff7Sartem rmm_hal_init(LibHalDeviceAdded devadd_cb, LibHalDeviceRemoved devrem_cb,
6718c2aff7Sartem     LibHalDevicePropertyModified propmod_cb,
6818c2aff7Sartem     DBusError *error, rmm_error_t *rmm_error)
6918c2aff7Sartem {
7018c2aff7Sartem 	DBusConnection	*dbus_conn;
7118c2aff7Sartem 	LibHalContext	*ctx;
7218c2aff7Sartem 	char		**devices;
7318c2aff7Sartem 	int		nr;
7418c2aff7Sartem 
7518c2aff7Sartem 	dbus_error_init(error);
7618c2aff7Sartem 
7718c2aff7Sartem 	/*
7818c2aff7Sartem 	 * setup D-Bus connection
7918c2aff7Sartem 	 */
8018c2aff7Sartem 	if (!(dbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, error))) {
8118c2aff7Sartem 		dprintf("cannot get system bus: %s\n", rmm_strerror(error, -1));
8218c2aff7Sartem 		*rmm_error = RMM_EDBUS_CONNECT;
8318c2aff7Sartem 		return (NULL);
8418c2aff7Sartem 	}
8518c2aff7Sartem 	rmm_dbus_error_free(error);
8618c2aff7Sartem 
8718c2aff7Sartem 	dbus_connection_setup_with_g_main(dbus_conn, NULL);
8818c2aff7Sartem 	dbus_connection_set_exit_on_disconnect(dbus_conn, B_TRUE);
8918c2aff7Sartem 
9018c2aff7Sartem 	if ((ctx = libhal_ctx_new()) == NULL) {
9118c2aff7Sartem 		dprintf("libhal_ctx_new failed");
9218c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
9318c2aff7Sartem 		return (NULL);
9418c2aff7Sartem 	}
9518c2aff7Sartem 
9618c2aff7Sartem 	libhal_ctx_set_dbus_connection(ctx, dbus_conn);
9718c2aff7Sartem 
9818c2aff7Sartem 	/*
9918c2aff7Sartem 	 * register callbacks
10018c2aff7Sartem 	 */
10118c2aff7Sartem 	if (devadd_cb != NULL) {
10218c2aff7Sartem 		libhal_ctx_set_device_added(ctx, devadd_cb);
10318c2aff7Sartem 	}
10418c2aff7Sartem 	if (devrem_cb != NULL) {
10518c2aff7Sartem 		libhal_ctx_set_device_removed(ctx, devrem_cb);
10618c2aff7Sartem 	}
10718c2aff7Sartem 	if (propmod_cb != NULL) {
10818c2aff7Sartem 		libhal_ctx_set_device_property_modified(ctx, propmod_cb);
10918c2aff7Sartem 		if (!libhal_device_property_watch_all(ctx, error)) {
11018c2aff7Sartem 			dprintf("property_watch_all failed %s",
11118c2aff7Sartem 			    rmm_strerror(error, -1));
11218c2aff7Sartem 			libhal_ctx_free(ctx);
11318c2aff7Sartem 			*rmm_error = RMM_EHAL_CONNECT;
11418c2aff7Sartem 			return (NULL);
11518c2aff7Sartem 		}
11618c2aff7Sartem 	}
11718c2aff7Sartem 
11818c2aff7Sartem 	if (!libhal_ctx_init(ctx, error)) {
11918c2aff7Sartem 		dprintf("libhal_ctx_init failed: %s", rmm_strerror(error, -1));
12018c2aff7Sartem 		libhal_ctx_free(ctx);
12118c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
12218c2aff7Sartem 		return (NULL);
12318c2aff7Sartem 	}
12418c2aff7Sartem 	rmm_dbus_error_free(error);
12518c2aff7Sartem 
12618c2aff7Sartem 	/*
12718c2aff7Sartem 	 * The above functions do not guarantee that HAL is actually running.
12818c2aff7Sartem 	 * Check by invoking a method.
12918c2aff7Sartem 	 */
13018c2aff7Sartem 	if (!(devices = libhal_get_all_devices(ctx, &nr, error))) {
13118c2aff7Sartem 		dprintf("HAL is not running: %s", rmm_strerror(error, -1));
13218c2aff7Sartem 		libhal_ctx_shutdown(ctx, NULL);
13318c2aff7Sartem 		libhal_ctx_free(ctx);
13418c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
13518c2aff7Sartem 		return (NULL);
13618c2aff7Sartem 	} else {
13718c2aff7Sartem 		rmm_dbus_error_free(error);
13818c2aff7Sartem 		libhal_free_string_array(devices);
13918c2aff7Sartem 	}
14018c2aff7Sartem 
14118c2aff7Sartem 	return (ctx);
14218c2aff7Sartem }
14318c2aff7Sartem 
14418c2aff7Sartem 
14518c2aff7Sartem void
14618c2aff7Sartem rmm_hal_fini(LibHalContext *hal_ctx)
14718c2aff7Sartem {
14818c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
14918c2aff7Sartem 
150*b941d3fcSartem 	(void) dbus_connection_unref(dbus_conn);
15118c2aff7Sartem 	(void) libhal_ctx_free(hal_ctx);
15218c2aff7Sartem }
15318c2aff7Sartem 
15418c2aff7Sartem 
15518c2aff7Sartem /*
15618c2aff7Sartem  * find volume from any type of name, similar to the old media_findname()
15718c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
15818c2aff7Sartem  */
15918c2aff7Sartem LibHalDrive *
16018c2aff7Sartem rmm_hal_volume_find(LibHalContext *hal_ctx, const char *name, DBusError *error,
16118c2aff7Sartem     GSList **volumes)
16218c2aff7Sartem {
16318c2aff7Sartem 	LibHalDrive	*drive;
16418c2aff7Sartem 	char		*p;
16518c2aff7Sartem 	char		lastc;
16618c2aff7Sartem 
16718c2aff7Sartem 	*volumes = NULL;
16818c2aff7Sartem 
16918c2aff7Sartem 	/* temporarily remove trailing slash */
17018c2aff7Sartem 	p = (char *)name + strlen(name) - 1;
17118c2aff7Sartem 	if (*p == '/') {
17218c2aff7Sartem 		lastc = *p;
17318c2aff7Sartem 		*p = '\0';
17418c2aff7Sartem 	} else {
17518c2aff7Sartem 		p = NULL;
17618c2aff7Sartem 	}
17718c2aff7Sartem 
17818c2aff7Sartem 	if (name[0] == '/') {
17918c2aff7Sartem 		if (((drive = rmm_hal_volume_findby(hal_ctx,
18018c2aff7Sartem 		    "info.udi", name, volumes)) != NULL) ||
18118c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18218c2aff7Sartem 		    "block.device", name, volumes)) != NULL) ||
18318c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18418c2aff7Sartem 		    "block.solaris.raw_device", name, volumes)) != NULL) ||
18518c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18618c2aff7Sartem 		    "volume.mount_point", name, volumes)) != NULL)) {
18718c2aff7Sartem 			goto out;
18818c2aff7Sartem 		} else {
18918c2aff7Sartem 			goto out;
19018c2aff7Sartem 		}
19118c2aff7Sartem 	}
19218c2aff7Sartem 
19318c2aff7Sartem 	/* try volume label */
19418c2aff7Sartem 	if ((drive = rmm_hal_volume_findby(hal_ctx,
19518c2aff7Sartem 	    "volume.label", name, volumes)) != NULL) {
19618c2aff7Sartem 		goto out;
19718c2aff7Sartem 	}
19818c2aff7Sartem 
19918c2aff7Sartem 	drive = rmm_hal_volume_findby_nickname(hal_ctx, name, volumes);
20018c2aff7Sartem 
20118c2aff7Sartem out:
20218c2aff7Sartem 	if (p != NULL) {
20318c2aff7Sartem 		*p = lastc;
20418c2aff7Sartem 	}
20518c2aff7Sartem 	return (drive);
20618c2aff7Sartem }
20718c2aff7Sartem 
20818c2aff7Sartem /*
20918c2aff7Sartem  * find default volume. Returns volume pointer and name in 'name'.
21018c2aff7Sartem  */
21118c2aff7Sartem LibHalDrive *
21218c2aff7Sartem rmm_hal_volume_find_default(LibHalContext *hal_ctx, DBusError *error,
21318c2aff7Sartem     const char **name_out, GSList **volumes)
21418c2aff7Sartem {
21518c2aff7Sartem 	LibHalDrive	*drive;
21618c2aff7Sartem 	static const char *names[] = { "floppy", "cdrom", "rmdisk" };
21718c2aff7Sartem 	int		i;
21818c2aff7Sartem 
21918c2aff7Sartem 	*volumes = NULL;
22018c2aff7Sartem 
22118c2aff7Sartem 	for (i = 0; i < NELEM(names); i++) {
22218c2aff7Sartem 		if ((drive = rmm_hal_volume_findby_nickname(hal_ctx,
22318c2aff7Sartem 		    names[i], volumes)) != NULL) {
22418c2aff7Sartem 			/*
22518c2aff7Sartem 			 * Skip floppy if it has no media.
22618c2aff7Sartem 			 * XXX might want to actually check for media
22718c2aff7Sartem 			 * every time instead of relying on volcheck.
22818c2aff7Sartem 			 */
22918c2aff7Sartem 			if ((strcmp(names[i], "floppy") != 0) ||
23018c2aff7Sartem 			    libhal_device_get_property_bool(hal_ctx,
23118c2aff7Sartem 			    libhal_drive_get_udi(drive),
23218c2aff7Sartem 			    "storage.removable.media_available", NULL)) {
23318c2aff7Sartem 				*name_out = names[i];
23418c2aff7Sartem 				break;
23518c2aff7Sartem 			}
23618c2aff7Sartem 		}
23718c2aff7Sartem 		rmm_dbus_error_free(error);
23818c2aff7Sartem 	}
23918c2aff7Sartem 
24018c2aff7Sartem 	return (drive);
24118c2aff7Sartem }
24218c2aff7Sartem 
24318c2aff7Sartem /*
24418c2aff7Sartem  * find volume by property=value
24518c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
24618c2aff7Sartem  * XXX add support for multiple properties, reduce D-Bus traffic
24718c2aff7Sartem  */
24818c2aff7Sartem LibHalDrive *
24918c2aff7Sartem rmm_hal_volume_findby(LibHalContext *hal_ctx, const char *property,
25018c2aff7Sartem     const char *value, GSList **volumes)
25118c2aff7Sartem {
25218c2aff7Sartem 	DBusError	error;
25318c2aff7Sartem 	LibHalDrive	*drive = NULL;
25418c2aff7Sartem 	LibHalVolume	*v = NULL;
25518c2aff7Sartem 	char		**udis;
25618c2aff7Sartem 	int		num_udis;
25718c2aff7Sartem 	int		i;
25818c2aff7Sartem 
25918c2aff7Sartem 	*volumes = NULL;
26018c2aff7Sartem 
26118c2aff7Sartem 	dbus_error_init(&error);
26218c2aff7Sartem 
26318c2aff7Sartem 	/* get all devices with property=value */
26418c2aff7Sartem 	if ((udis = libhal_manager_find_device_string_match(hal_ctx, property,
26518c2aff7Sartem 	    value, &num_udis, &error)) == NULL) {
26618c2aff7Sartem 		rmm_dbus_error_free(&error);
26718c2aff7Sartem 		return (NULL);
26818c2aff7Sartem 	}
26918c2aff7Sartem 
27018c2aff7Sartem 	/* find volumes among these devices */
27118c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
27218c2aff7Sartem 		rmm_dbus_error_free(&error);
27318c2aff7Sartem 		if (libhal_device_query_capability(hal_ctx, udis[i], "volume",
27418c2aff7Sartem 		    &error)) {
27518c2aff7Sartem 			v = libhal_volume_from_udi(hal_ctx, udis[i]);
27618c2aff7Sartem 			if (v != NULL) {
27718c2aff7Sartem 				*volumes = g_slist_prepend(*volumes, v);
27818c2aff7Sartem 			}
27918c2aff7Sartem 		}
28018c2aff7Sartem 	}
28118c2aff7Sartem 
28218c2aff7Sartem 	/* used prepend, preserve original order */
28318c2aff7Sartem 	if (*volumes != NULL) {
28418c2aff7Sartem 		*volumes = g_slist_reverse(*volumes);
28518c2aff7Sartem 
28618c2aff7Sartem 		v = (LibHalVolume *)(*volumes)->data;
28718c2aff7Sartem 		drive = libhal_drive_from_udi(hal_ctx,
28818c2aff7Sartem 		    libhal_volume_get_storage_device_udi(v));
28918c2aff7Sartem 		if (drive == NULL) {
29018c2aff7Sartem 			rmm_volumes_free (*volumes);
29118c2aff7Sartem 			*volumes = NULL;
29218c2aff7Sartem 		}
29318c2aff7Sartem 	}
29418c2aff7Sartem 
29518c2aff7Sartem 	libhal_free_string_array(udis);
29618c2aff7Sartem 	rmm_dbus_error_free(&error);
29718c2aff7Sartem 
29818c2aff7Sartem 	return (drive);
29918c2aff7Sartem }
30018c2aff7Sartem 
3010ebe3100Sartem static void
3020ebe3100Sartem rmm_print_nicknames_one(LibHalDrive *d, LibHalVolume *v,
3030ebe3100Sartem     const char *device, char **drive_nicknames)
30418c2aff7Sartem {
3050ebe3100Sartem 	const char	*volume_label = NULL;
3060ebe3100Sartem 	const char	*mount_point = NULL;
30718c2aff7Sartem 	boolean_t	comma;
3080ebe3100Sartem 	int		i;
30918c2aff7Sartem 
3100ebe3100Sartem 	(void) printf("%-*s ", RMM_PRINT_DEVICE_WIDTH, device);
31118c2aff7Sartem 	comma = B_FALSE;
31218c2aff7Sartem 
3130ebe3100Sartem 	if (drive_nicknames != NULL) {
3140ebe3100Sartem 		for (i = 0; drive_nicknames[i] != NULL; i++) {
31518c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "",
3160ebe3100Sartem 			    drive_nicknames[i]);
31718c2aff7Sartem 			comma = B_TRUE;
31818c2aff7Sartem 		}
31918c2aff7Sartem 	}
32018c2aff7Sartem 
3210ebe3100Sartem 	if ((v != NULL) &&
3220ebe3100Sartem 	    ((volume_label = libhal_volume_get_label(v)) != NULL) &&
32318c2aff7Sartem 	    (strlen(volume_label) > 0)) {
32418c2aff7Sartem 		(void) printf("%s%s", comma ? "," : "", volume_label);
32518c2aff7Sartem 		comma = B_TRUE;
32618c2aff7Sartem 	}
32718c2aff7Sartem 
3280ebe3100Sartem 	if ((v != NULL) &&
3290ebe3100Sartem 	    ((mount_point = libhal_volume_get_mount_point(v)) != NULL) &&
33018c2aff7Sartem 	    (strlen(mount_point) > 0)) {
33118c2aff7Sartem 		(void) printf("%s%s", comma ? "," : "", mount_point);
33218c2aff7Sartem 		comma = B_TRUE;
33318c2aff7Sartem 	}
33418c2aff7Sartem 
33518c2aff7Sartem 	(void) printf("\n");
3360ebe3100Sartem }
3370ebe3100Sartem 
3380ebe3100Sartem /*
3390ebe3100Sartem  * print nicknames for each available volume
3400ebe3100Sartem  *
3410ebe3100Sartem  * print_mask:
3420ebe3100Sartem  *   RMM_PRINT_MOUNTABLE	print only mountable volumes
3430ebe3100Sartem  *   RMM_PRINT_EJECTABLE	print volume-less ejectable drives
3440ebe3100Sartem  */
3450ebe3100Sartem void
3460ebe3100Sartem rmm_print_volume_nicknames(LibHalContext *hal_ctx, DBusError *error,
3470ebe3100Sartem     int print_mask)
3480ebe3100Sartem {
3490ebe3100Sartem 	char		**udis;
3500ebe3100Sartem 	int		num_udis;
3510ebe3100Sartem 	GSList		*volumes = NULL;
3520ebe3100Sartem 	LibHalDrive	*d, *d_tmp;
3530ebe3100Sartem 	LibHalVolume	*v;
3540ebe3100Sartem 	const char	*device;
3550ebe3100Sartem 	char		**nicknames;
3560ebe3100Sartem 	int		i;
3570ebe3100Sartem 	GSList		*j;
3580ebe3100Sartem 	int		nprinted;
3590ebe3100Sartem 
3600ebe3100Sartem 	dbus_error_init(error);
3610ebe3100Sartem 
3620ebe3100Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
3630ebe3100Sartem 	    &num_udis, error)) == NULL) {
3640ebe3100Sartem 		rmm_dbus_error_free(error);
3650ebe3100Sartem 		return;
3660ebe3100Sartem 	}
3670ebe3100Sartem 
3680ebe3100Sartem 	for (i = 0; i < num_udis; i++) {
3690ebe3100Sartem 		if ((d = libhal_drive_from_udi(hal_ctx, udis[i])) == NULL) {
3700ebe3100Sartem 			continue;
3710ebe3100Sartem 		}
3720ebe3100Sartem 
3730ebe3100Sartem 		/* find volumes belonging to this drive */
3740ebe3100Sartem 		if ((d_tmp = rmm_hal_volume_findby(hal_ctx,
3750ebe3100Sartem 		    "block.storage_device", udis[i], &volumes)) != NULL) {
3760ebe3100Sartem 			libhal_drive_free(d_tmp);
3770ebe3100Sartem 		}
3780ebe3100Sartem 
3790ebe3100Sartem 		nicknames = libhal_device_get_property_strlist(hal_ctx,
3800ebe3100Sartem 		    udis[i], "storage.solaris.nicknames", NULL);
3810ebe3100Sartem 
3820ebe3100Sartem 		nprinted = 0;
3830ebe3100Sartem 		for (j = volumes; j != NULL; j = g_slist_next(j)) {
3840ebe3100Sartem 			v = (LibHalVolume *)(j->data);
3850ebe3100Sartem 
3860ebe3100Sartem 			if ((device = libhal_volume_get_device_file(v)) ==
3870ebe3100Sartem 			    NULL) {
3880ebe3100Sartem 				continue;
3890ebe3100Sartem 			}
3900ebe3100Sartem 			if ((print_mask & RMM_PRINT_MOUNTABLE) &&
3910ebe3100Sartem 			    (libhal_volume_get_fsusage(v) !=
3920ebe3100Sartem 			    LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM)) {
3930ebe3100Sartem 				continue;
3940ebe3100Sartem 			}
3950ebe3100Sartem 
3960ebe3100Sartem 			rmm_print_nicknames_one(d, v, device, nicknames);
3970ebe3100Sartem 			nprinted++;
3980ebe3100Sartem 		}
3990ebe3100Sartem 
4000ebe3100Sartem 		if ((nprinted == 0) &&
4010ebe3100Sartem 		    (print_mask & RMM_PRINT_EJECTABLE) &&
4020ebe3100Sartem 		    libhal_drive_requires_eject(d) &&
4030ebe3100Sartem 		    ((device = libhal_drive_get_device_file(d)) != NULL)) {
4040ebe3100Sartem 			rmm_print_nicknames_one(d, NULL, device, nicknames);
4050ebe3100Sartem 		}
40618c2aff7Sartem 
40718c2aff7Sartem 		libhal_free_string_array(nicknames);
4080ebe3100Sartem 		libhal_drive_free(d);
4090ebe3100Sartem 		rmm_volumes_free(volumes);
4100ebe3100Sartem 		volumes = NULL;
41118c2aff7Sartem 	}
41218c2aff7Sartem 
4130ebe3100Sartem 	libhal_free_string_array(udis);
4140ebe3100Sartem }
41518c2aff7Sartem 
41618c2aff7Sartem /*
41718c2aff7Sartem  * find volume by nickname
41818c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
41918c2aff7Sartem  */
42018c2aff7Sartem LibHalDrive *
42118c2aff7Sartem rmm_hal_volume_findby_nickname(LibHalContext *hal_ctx, const char *name,
42218c2aff7Sartem     GSList **volumes)
42318c2aff7Sartem {
42418c2aff7Sartem 	DBusError	error;
42518c2aff7Sartem 	LibHalDrive	*drive = NULL;
42618c2aff7Sartem 	LibHalDrive	*drive_tmp;
42718c2aff7Sartem 	char		**udis;
42818c2aff7Sartem 	int		num_udis;
42918c2aff7Sartem 	char		**nicknames;
43018c2aff7Sartem 	int		i, j;
43118c2aff7Sartem 
43218c2aff7Sartem 	*volumes = NULL;
43318c2aff7Sartem 
43418c2aff7Sartem 	dbus_error_init(&error);
43518c2aff7Sartem 
43618c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
43718c2aff7Sartem 	    &num_udis, &error)) == NULL) {
43818c2aff7Sartem 		rmm_dbus_error_free(&error);
43918c2aff7Sartem 		return (NULL);
44018c2aff7Sartem 	}
44118c2aff7Sartem 
44218c2aff7Sartem 	/* find a drive by nickname */
44318c2aff7Sartem 	for (i = 0; (i < num_udis) && (drive == NULL); i++) {
44418c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
44518c2aff7Sartem 		    udis[i], "storage.solaris.nicknames", &error)) == NULL) {
44618c2aff7Sartem 			rmm_dbus_error_free(&error);
44718c2aff7Sartem 			continue;
44818c2aff7Sartem 		}
44918c2aff7Sartem 		for (j = 0; (nicknames[j] != NULL) && (drive == NULL); j++) {
45018c2aff7Sartem 			if (strcmp(nicknames[j], name) == 0) {
45118c2aff7Sartem 				drive = libhal_drive_from_udi(hal_ctx, udis[i]);
45218c2aff7Sartem 			}
45318c2aff7Sartem 		}
45418c2aff7Sartem 		libhal_free_string_array(nicknames);
45518c2aff7Sartem 	}
45618c2aff7Sartem 	libhal_free_string_array(udis);
45718c2aff7Sartem 
45818c2aff7Sartem 	if (drive != NULL) {
45918c2aff7Sartem 		/* found the drive, now find its volumes */
46018c2aff7Sartem 		if ((drive_tmp = rmm_hal_volume_findby(hal_ctx,
46118c2aff7Sartem 		    "block.storage_device", libhal_drive_get_udi(drive),
46218c2aff7Sartem 		    volumes)) != NULL) {
46318c2aff7Sartem 			libhal_drive_free(drive_tmp);
46418c2aff7Sartem 		}
46518c2aff7Sartem 	}
46618c2aff7Sartem 
46718c2aff7Sartem 	rmm_dbus_error_free(&error);
46818c2aff7Sartem 
46918c2aff7Sartem 	return (drive);
47018c2aff7Sartem }
47118c2aff7Sartem 
47218c2aff7Sartem void
47318c2aff7Sartem rmm_volumes_free(GSList *volumes)
47418c2aff7Sartem {
47518c2aff7Sartem 	GSList	*i;
47618c2aff7Sartem 
47718c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
47818c2aff7Sartem 		libhal_volume_free((LibHalVolume *)(i->data));
47918c2aff7Sartem 	}
48018c2aff7Sartem 	g_slist_free(volumes);
48118c2aff7Sartem }
48218c2aff7Sartem 
48318c2aff7Sartem /*
48418c2aff7Sartem  * Call HAL's Mount() method on the given device
48518c2aff7Sartem  */
48618c2aff7Sartem boolean_t
48718c2aff7Sartem rmm_hal_mount(LibHalContext *hal_ctx, const char *udi,
48818c2aff7Sartem     char **opts, int num_opts, char *mountpoint, DBusError *error)
48918c2aff7Sartem {
49018c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
49118c2aff7Sartem 	DBusMessage	*dmesg, *reply;
49218c2aff7Sartem 	char		*fstype;
49318c2aff7Sartem 
49418c2aff7Sartem 	dprintf("mounting %s...\n", udi);
49518c2aff7Sartem 
49618c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
49718c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Mount"))) {
49818c2aff7Sartem 		dprintf(
49918c2aff7Sartem 		    "mount failed for %s: cannot create dbus message\n", udi);
50018c2aff7Sartem 		return (B_FALSE);
50118c2aff7Sartem 	}
50218c2aff7Sartem 
50318c2aff7Sartem 	fstype = "";
50418c2aff7Sartem 	if (mountpoint == NULL) {
50518c2aff7Sartem 		mountpoint = "";
50618c2aff7Sartem 	}
50718c2aff7Sartem 
50818c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &mountpoint,
50918c2aff7Sartem 	    DBUS_TYPE_STRING, &fstype,
51018c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &opts, num_opts,
51118c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
51218c2aff7Sartem 		dprintf("mount failed for %s: cannot append args\n", udi);
51318c2aff7Sartem 		dbus_message_unref(dmesg);
51418c2aff7Sartem 		return (B_FALSE);
51518c2aff7Sartem 	}
51618c2aff7Sartem 
51718c2aff7Sartem 	dbus_error_init(error);
51818c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
519*b941d3fcSartem 	    dmesg, RMM_MOUNT_TIMEOUT, error))) {
52018c2aff7Sartem 		dprintf("mount failed for %s: %s\n", udi, error->message);
52118c2aff7Sartem 		dbus_message_unref(dmesg);
52218c2aff7Sartem 		return (B_FALSE);
52318c2aff7Sartem 	}
52418c2aff7Sartem 
52518c2aff7Sartem 	dprintf("mounted %s\n", udi);
52618c2aff7Sartem 
52718c2aff7Sartem 	dbus_message_unref(dmesg);
52818c2aff7Sartem 	dbus_message_unref(reply);
52918c2aff7Sartem 
53018c2aff7Sartem 	rmm_dbus_error_free(error);
53118c2aff7Sartem 
53218c2aff7Sartem 	return (B_TRUE);
53318c2aff7Sartem }
53418c2aff7Sartem 
53518c2aff7Sartem 
53618c2aff7Sartem /*
53718c2aff7Sartem  * Call HAL's Unmount() method on the given device
53818c2aff7Sartem  */
53918c2aff7Sartem boolean_t
54018c2aff7Sartem rmm_hal_unmount(LibHalContext *hal_ctx, const char *udi, DBusError *error)
54118c2aff7Sartem {
54218c2aff7Sartem 	DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
54318c2aff7Sartem 	DBusMessage *dmesg, *reply;
54418c2aff7Sartem 	char **opts = NULL;
54518c2aff7Sartem 
54618c2aff7Sartem 	dprintf("unmounting %s...\n", udi);
54718c2aff7Sartem 
54818c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
54918c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Unmount"))) {
55018c2aff7Sartem 		dprintf(
55118c2aff7Sartem 		    "unmount failed %s: cannot create dbus message\n", udi);
55218c2aff7Sartem 		return (B_FALSE);
55318c2aff7Sartem 	}
55418c2aff7Sartem 
55518c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
55618c2aff7Sartem 	    &opts, 0, DBUS_TYPE_INVALID)) {
55718c2aff7Sartem 		dprintf("unmount failed %s: cannot append args\n", udi);
55818c2aff7Sartem 		dbus_message_unref(dmesg);
55918c2aff7Sartem 		return (B_FALSE);
56018c2aff7Sartem 	}
56118c2aff7Sartem 
56218c2aff7Sartem 	dbus_error_init(error);
56318c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
564*b941d3fcSartem 	    dmesg, RMM_UNMOUNT_TIMEOUT, error))) {
56518c2aff7Sartem 		dprintf("unmount failed for %s: %s\n", udi, error->message);
56618c2aff7Sartem 		dbus_message_unref(dmesg);
56718c2aff7Sartem 		return (B_FALSE);
56818c2aff7Sartem 	}
56918c2aff7Sartem 
57018c2aff7Sartem 	dprintf("unmounted %s\n", udi);
57118c2aff7Sartem 
57218c2aff7Sartem 	dbus_message_unref(dmesg);
57318c2aff7Sartem 	dbus_message_unref(reply);
57418c2aff7Sartem 
57518c2aff7Sartem 	rmm_dbus_error_free(error);
57618c2aff7Sartem 
57718c2aff7Sartem 	return (B_TRUE);
57818c2aff7Sartem }
57918c2aff7Sartem 
58018c2aff7Sartem 
58118c2aff7Sartem /*
58218c2aff7Sartem  * Call HAL's Eject() method on the given device
58318c2aff7Sartem  */
58418c2aff7Sartem boolean_t
58518c2aff7Sartem rmm_hal_eject(LibHalContext *hal_ctx, const char *udi, DBusError *error)
58618c2aff7Sartem {
58718c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
58818c2aff7Sartem 	DBusMessage	*dmesg, *reply;
58918c2aff7Sartem 	char		**options = NULL;
59018c2aff7Sartem 	uint_t		num_options = 0;
59118c2aff7Sartem 
59218c2aff7Sartem 	dprintf("ejecting %s...\n", udi);
59318c2aff7Sartem 
59418c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
59518c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "Eject"))) {
59618c2aff7Sartem 		dprintf("eject %s: cannot create dbus message\n", udi);
59718c2aff7Sartem 		return (B_FALSE);
59818c2aff7Sartem 	}
59918c2aff7Sartem 
60018c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
60118c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
60218c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
60318c2aff7Sartem 		dprintf("eject %s: cannot append args to dbus message ", udi);
60418c2aff7Sartem 		dbus_message_unref(dmesg);
60518c2aff7Sartem 		return (B_FALSE);
60618c2aff7Sartem 	}
60718c2aff7Sartem 
60818c2aff7Sartem 	dbus_error_init(error);
60918c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
610*b941d3fcSartem 	    dmesg, RMM_EJECT_TIMEOUT, error))) {
61118c2aff7Sartem 		dprintf("eject %s: %s\n", udi, error->message);
61218c2aff7Sartem 		dbus_message_unref(dmesg);
61318c2aff7Sartem 		return (B_FALSE);
61418c2aff7Sartem 	}
61518c2aff7Sartem 
61618c2aff7Sartem 	dprintf("ejected %s\n", udi);
61718c2aff7Sartem 
61818c2aff7Sartem 	dbus_message_unref(dmesg);
61918c2aff7Sartem 	dbus_message_unref(reply);
62018c2aff7Sartem 
62118c2aff7Sartem 	rmm_dbus_error_free(error);
62218c2aff7Sartem 
62318c2aff7Sartem 	return (B_TRUE);
62418c2aff7Sartem }
62518c2aff7Sartem 
62618c2aff7Sartem /*
62718c2aff7Sartem  * Call HAL's CloseTray() method on the given device
62818c2aff7Sartem  */
62918c2aff7Sartem boolean_t
63018c2aff7Sartem rmm_hal_closetray(LibHalContext *hal_ctx, const char *udi, DBusError *error)
63118c2aff7Sartem {
63218c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
63318c2aff7Sartem 	DBusMessage	*dmesg, *reply;
63418c2aff7Sartem 	char		**options = NULL;
63518c2aff7Sartem 	uint_t		num_options = 0;
63618c2aff7Sartem 
63718c2aff7Sartem 	dprintf("closing tray %s...\n", udi);
63818c2aff7Sartem 
63918c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
64018c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "CloseTray"))) {
64118c2aff7Sartem 		dprintf(
64218c2aff7Sartem 		    "closetray failed for %s: cannot create dbus message\n",
64318c2aff7Sartem 		    udi);
64418c2aff7Sartem 		return (B_FALSE);
64518c2aff7Sartem 	}
64618c2aff7Sartem 
64718c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
64818c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
64918c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
65018c2aff7Sartem 		dprintf("closetray %s: cannot append args to dbus message ",
65118c2aff7Sartem 		    udi);
65218c2aff7Sartem 		dbus_message_unref(dmesg);
65318c2aff7Sartem 		return (B_FALSE);
65418c2aff7Sartem 	}
65518c2aff7Sartem 
65618c2aff7Sartem 	dbus_error_init(error);
65718c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
658*b941d3fcSartem 	    dmesg, RMM_CLOSETRAY_TIMEOUT, error))) {
65918c2aff7Sartem 		dprintf("closetray failed for %s: %s\n", udi, error->message);
66018c2aff7Sartem 		dbus_message_unref(dmesg);
66118c2aff7Sartem 		return (B_FALSE);
66218c2aff7Sartem 	}
66318c2aff7Sartem 
66418c2aff7Sartem 	dprintf("closetray ok %s\n", udi);
66518c2aff7Sartem 
66618c2aff7Sartem 	dbus_message_unref(dmesg);
66718c2aff7Sartem 	dbus_message_unref(reply);
66818c2aff7Sartem 
66918c2aff7Sartem 	rmm_dbus_error_free(error);
67018c2aff7Sartem 
67118c2aff7Sartem 	return (B_TRUE);
67218c2aff7Sartem }
67318c2aff7Sartem 
67418c2aff7Sartem /*
67518c2aff7Sartem  * Call HAL's Rescan() method on the given device
67618c2aff7Sartem  */
67718c2aff7Sartem boolean_t
67818c2aff7Sartem rmm_hal_rescan(LibHalContext *hal_ctx, const char *udi, DBusError *error)
67918c2aff7Sartem {
68018c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
68118c2aff7Sartem 	DBusMessage	*dmesg, *reply;
68218c2aff7Sartem 
68318c2aff7Sartem 	dprintf("rescanning %s...\n", udi);
68418c2aff7Sartem 
68518c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
68618c2aff7Sartem 	    "org.freedesktop.Hal.Device", "Rescan"))) {
68718c2aff7Sartem 		dprintf("rescan failed for %s: cannot create dbus message\n",
68818c2aff7Sartem 		    udi);
68918c2aff7Sartem 		return (B_FALSE);
69018c2aff7Sartem 	}
69118c2aff7Sartem 
69218c2aff7Sartem 	dbus_error_init(error);
69318c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
69418c2aff7Sartem 	    dmesg, -1, error))) {
69518c2aff7Sartem 		dprintf("rescan failed for %s: %s\n", udi, error->message);
69618c2aff7Sartem 		dbus_message_unref(dmesg);
69718c2aff7Sartem 		return (B_FALSE);
69818c2aff7Sartem 	}
69918c2aff7Sartem 
70018c2aff7Sartem 	dprintf("rescan ok %s\n", udi);
70118c2aff7Sartem 
70218c2aff7Sartem 	dbus_message_unref(dmesg);
70318c2aff7Sartem 	dbus_message_unref(reply);
70418c2aff7Sartem 
70518c2aff7Sartem 	rmm_dbus_error_free(error);
70618c2aff7Sartem 
70718c2aff7Sartem 	return (B_TRUE);
70818c2aff7Sartem }
70918c2aff7Sartem 
71018c2aff7Sartem boolean_t
71118c2aff7Sartem rmm_hal_claim_branch(LibHalContext *hal_ctx, const char *udi)
71218c2aff7Sartem {
71318c2aff7Sartem 	DBusError error;
71418c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
71518c2aff7Sartem 	DBusMessage *dmesg, *reply;
71618c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
71718c2aff7Sartem 
71818c2aff7Sartem 	dprintf("claiming branch %s...\n", udi);
71918c2aff7Sartem 
72018c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
72118c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
72218c2aff7Sartem 	    "ClaimBranch"))) {
72318c2aff7Sartem 		dprintf("cannot create dbus message\n");
72418c2aff7Sartem 		return (B_FALSE);
72518c2aff7Sartem 	}
72618c2aff7Sartem 
72718c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
72818c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
72918c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
73018c2aff7Sartem 		dbus_message_unref(dmesg);
73118c2aff7Sartem 		return (B_FALSE);
73218c2aff7Sartem 	}
73318c2aff7Sartem 
73418c2aff7Sartem 	dbus_error_init(&error);
73518c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
73618c2aff7Sartem 	    dmesg, -1, &error))) {
73718c2aff7Sartem 		dprintf("cannot send dbus message\n");
73818c2aff7Sartem 		dbus_message_unref(dmesg);
73918c2aff7Sartem 		rmm_dbus_error_free(&error);
74018c2aff7Sartem 		return (B_FALSE);
74118c2aff7Sartem 	}
74218c2aff7Sartem 
74318c2aff7Sartem 	dprintf("claim branch ok %s\n", udi);
74418c2aff7Sartem 
74518c2aff7Sartem 	dbus_message_unref(dmesg);
74618c2aff7Sartem 	dbus_message_unref(reply);
74718c2aff7Sartem 
74818c2aff7Sartem 	return (B_TRUE);
74918c2aff7Sartem }
75018c2aff7Sartem 
75118c2aff7Sartem boolean_t
75218c2aff7Sartem rmm_hal_unclaim_branch(LibHalContext *hal_ctx, const char *udi)
75318c2aff7Sartem {
75418c2aff7Sartem 	DBusError error;
75518c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
75618c2aff7Sartem 	DBusMessage *dmesg, *reply;
75718c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
75818c2aff7Sartem 
75918c2aff7Sartem 	dprintf("unclaiming branch %s...\n", udi);
76018c2aff7Sartem 
76118c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
76218c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
76318c2aff7Sartem 	    "UnclaimBranch"))) {
76418c2aff7Sartem 		dprintf("cannot create dbus message\n");
76518c2aff7Sartem 		return (B_FALSE);
76618c2aff7Sartem 	}
76718c2aff7Sartem 
76818c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
76918c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
77018c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
77118c2aff7Sartem 		dbus_message_unref(dmesg);
77218c2aff7Sartem 		return (B_FALSE);
77318c2aff7Sartem 	}
77418c2aff7Sartem 
77518c2aff7Sartem 	dbus_error_init(&error);
77618c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
77718c2aff7Sartem 	    dmesg, -1, &error))) {
77818c2aff7Sartem 		dprintf("cannot send dbus message\n");
77918c2aff7Sartem 		dbus_message_unref(dmesg);
78018c2aff7Sartem 		rmm_dbus_error_free(&error);
78118c2aff7Sartem 		return (B_FALSE);
78218c2aff7Sartem 	}
78318c2aff7Sartem 
78418c2aff7Sartem 	dprintf("unclaim branch ok %s\n", udi);
78518c2aff7Sartem 
78618c2aff7Sartem 	dbus_message_unref(dmesg);
78718c2aff7Sartem 	dbus_message_unref(reply);
78818c2aff7Sartem 
78918c2aff7Sartem 	return (B_TRUE);
79018c2aff7Sartem }
79118c2aff7Sartem 
79218c2aff7Sartem static boolean_t
79318c2aff7Sartem rmm_action_one(LibHalContext *hal_ctx, const char *name, action_t action,
79418c2aff7Sartem     const char *dev, const char *udi, LibHalVolume *v,
79518c2aff7Sartem     char **opts, int num_opts, char *mountpoint)
79618c2aff7Sartem {
79718c2aff7Sartem 	char		dev_str[MAXPATHLEN];
79818c2aff7Sartem 	char		*mountp;
79918c2aff7Sartem 	DBusError	error;
80018c2aff7Sartem 	boolean_t	ret = B_FALSE;
80118c2aff7Sartem 
80218c2aff7Sartem 	if (strcmp(name, dev) == 0) {
80318c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), name);
80418c2aff7Sartem 	} else {
80518c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), "%s %s", name, dev);
80618c2aff7Sartem 	}
80718c2aff7Sartem 
80818c2aff7Sartem 	dbus_error_init(&error);
80918c2aff7Sartem 
81018c2aff7Sartem 	switch (action) {
81118c2aff7Sartem 	case EJECT:
81218c2aff7Sartem 		ret = rmm_hal_eject(hal_ctx, udi, &error);
81318c2aff7Sartem 		break;
81418c2aff7Sartem 	case INSERT:
81518c2aff7Sartem 	case REMOUNT:
81618c2aff7Sartem 		if (libhal_volume_is_mounted(v)) {
81718c2aff7Sartem 			goto done;
81818c2aff7Sartem 		}
81918c2aff7Sartem 		ret = rmm_hal_mount(hal_ctx, udi,
82018c2aff7Sartem 		    opts, num_opts, mountpoint, &error);
82118c2aff7Sartem 		break;
82218c2aff7Sartem 	case UNMOUNT:
82318c2aff7Sartem 		if (!libhal_volume_is_mounted(v)) {
82418c2aff7Sartem 			goto done;
82518c2aff7Sartem 		}
82618c2aff7Sartem 		ret = rmm_hal_unmount(hal_ctx, udi, &error);
82718c2aff7Sartem 		break;
82818c2aff7Sartem 	case CLOSETRAY:
82918c2aff7Sartem 		ret = rmm_hal_closetray(hal_ctx, udi, &error);
83018c2aff7Sartem 		break;
83118c2aff7Sartem 	}
83218c2aff7Sartem 
83318c2aff7Sartem 	if (!ret) {
83418c2aff7Sartem 		(void) fprintf(stderr, gettext("%s of %s failed: %s\n"),
83518c2aff7Sartem 		    action_strings[action], dev_str, rmm_strerror(&error, -1));
83618c2aff7Sartem 		goto done;
83718c2aff7Sartem 	}
83818c2aff7Sartem 
83918c2aff7Sartem 	switch (action) {
84018c2aff7Sartem 	case EJECT:
84118c2aff7Sartem 		(void) printf(gettext("%s ejected\n"), dev_str);
84218c2aff7Sartem 		break;
84318c2aff7Sartem 	case INSERT:
84418c2aff7Sartem 	case REMOUNT:
84518c2aff7Sartem 		mountp = rmm_get_mnttab_mount_point(dev);
84618c2aff7Sartem 		if (mountp != NULL) {
84718c2aff7Sartem 			(void) printf(gettext("%s mounted at %s\n"),
84818c2aff7Sartem 			    dev_str, mountp);
84918c2aff7Sartem 			free(mountp);
85018c2aff7Sartem 		}
85118c2aff7Sartem 		break;
85218c2aff7Sartem 	case UNMOUNT:
85318c2aff7Sartem 		(void) printf(gettext("%s unmounted\n"), dev_str);
85418c2aff7Sartem 		break;
85518c2aff7Sartem 	case CLOSETRAY:
85618c2aff7Sartem 		(void) printf(gettext("%s tray closed\n"), dev_str);
85718c2aff7Sartem 		break;
85818c2aff7Sartem 	}
85918c2aff7Sartem 
86018c2aff7Sartem done:
86118c2aff7Sartem 	rmm_dbus_error_free(&error);
86218c2aff7Sartem 	return (ret);
86318c2aff7Sartem }
86418c2aff7Sartem 
86518c2aff7Sartem /*
86618c2aff7Sartem  * top level action routine
86718c2aff7Sartem  *
86818c2aff7Sartem  * If non-null 'aa' is passed, it will be used, otherwise a local copy
86918c2aff7Sartem  * will be created.
87018c2aff7Sartem  */
87118c2aff7Sartem boolean_t
87218c2aff7Sartem rmm_action(LibHalContext *hal_ctx, const char *name, action_t action,
87318c2aff7Sartem     struct action_arg *aap, char **opts, int num_opts, char *mountpoint)
87418c2aff7Sartem {
87518c2aff7Sartem 	DBusError	error;
87618c2aff7Sartem 	GSList		*volumes, *i;
87718c2aff7Sartem 	LibHalDrive	*d;
87818c2aff7Sartem 	LibHalVolume	*v;
87918c2aff7Sartem 	const char	*udi, *d_udi;
88018c2aff7Sartem 	const char	*dev, *d_dev;
88118c2aff7Sartem 	struct action_arg aa_local;
88218c2aff7Sartem 	boolean_t	ret = B_FALSE;
88318c2aff7Sartem 
88418c2aff7Sartem 	dprintf("rmm_action %s %s\n", name, action_strings[action]);
88518c2aff7Sartem 
88618c2aff7Sartem 	if (aap == NULL) {
8877544909dSartem 		bzero(&aa_local, sizeof (aa_local));
88818c2aff7Sartem 		aap = &aa_local;
88918c2aff7Sartem 	}
89018c2aff7Sartem 
89118c2aff7Sartem 	dbus_error_init(&error);
89218c2aff7Sartem 
89318c2aff7Sartem 	/* find the drive and its volumes */
89418c2aff7Sartem 	d = rmm_hal_volume_find(hal_ctx, name, &error, &volumes);
89518c2aff7Sartem 	rmm_dbus_error_free(&error);
89618c2aff7Sartem 	if (d == NULL) {
89718c2aff7Sartem 		(void) fprintf(stderr, gettext("cannot find '%s'\n"), name);
89818c2aff7Sartem 		return (B_FALSE);
89918c2aff7Sartem 	}
90018c2aff7Sartem 	d_udi = libhal_drive_get_udi(d);
90118c2aff7Sartem 	d_dev = libhal_drive_get_device_file(d);
90218c2aff7Sartem 	if ((d_udi == NULL) || (d_dev == NULL)) {
90318c2aff7Sartem 		goto out;
90418c2aff7Sartem 	}
90518c2aff7Sartem 
90618c2aff7Sartem 	/*
90718c2aff7Sartem 	 * For those drives that do not require media eject,
90818c2aff7Sartem 	 * EJECT turns into UNMOUNT.
90918c2aff7Sartem 	 */
91018c2aff7Sartem 	if ((action == EJECT) && !libhal_drive_requires_eject(d)) {
91118c2aff7Sartem 		action = UNMOUNT;
91218c2aff7Sartem 	}
91318c2aff7Sartem 
91418c2aff7Sartem 	/* per drive action */
91518c2aff7Sartem 	if ((action == EJECT) || (action == CLOSETRAY)) {
91618c2aff7Sartem 		ret = rmm_action_one(hal_ctx, name, action, d_dev, d_udi, NULL,
91718c2aff7Sartem 		    opts, num_opts, NULL);
91818c2aff7Sartem 
91918c2aff7Sartem 		if (!ret || (action == CLOSETRAY)) {
92018c2aff7Sartem 			goto out;
92118c2aff7Sartem 		}
92218c2aff7Sartem 	}
92318c2aff7Sartem 
92418c2aff7Sartem 	/* per volume action */
92518c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
92618c2aff7Sartem 		v = (LibHalVolume *)i->data;
92718c2aff7Sartem 		udi = libhal_volume_get_udi(v);
92818c2aff7Sartem 		dev = libhal_volume_get_device_file(v);
92918c2aff7Sartem 
93018c2aff7Sartem 		if ((udi == NULL) || (dev == NULL)) {
93118c2aff7Sartem 			continue;
93218c2aff7Sartem 		}
93318c2aff7Sartem 		if (aap == &aa_local) {
93418c2aff7Sartem 			if (!rmm_volume_aa_from_prop(hal_ctx, udi, v, aap)) {
93518c2aff7Sartem 				dprintf("rmm_volume_aa_from_prop failed %s\n",
93618c2aff7Sartem 				    udi);
93718c2aff7Sartem 				continue;
93818c2aff7Sartem 			}
93918c2aff7Sartem 		}
94018c2aff7Sartem 		aap->aa_action = action;
94118c2aff7Sartem 
94218c2aff7Sartem 		/* ejected above, just need postprocess */
94318c2aff7Sartem 		if (action != EJECT) {
94418c2aff7Sartem 			ret = rmm_action_one(hal_ctx, name, action, dev, udi, v,
94518c2aff7Sartem 			    opts, num_opts, mountpoint);
94618c2aff7Sartem 		}
94718c2aff7Sartem 		if (ret) {
94818c2aff7Sartem 			(void) vold_postprocess(hal_ctx, udi, aap);
94918c2aff7Sartem 		}
95018c2aff7Sartem 
95118c2aff7Sartem 		libhal_volume_free(v);
95218c2aff7Sartem 		if (aap == &aa_local) {
95318c2aff7Sartem 			rmm_volume_aa_free(aap);
95418c2aff7Sartem 		}
95518c2aff7Sartem 	}
95618c2aff7Sartem 
95718c2aff7Sartem out:
95818c2aff7Sartem 	g_slist_free(volumes);
95918c2aff7Sartem 	libhal_drive_free(d);
96018c2aff7Sartem 
96118c2aff7Sartem 	return (ret);
96218c2aff7Sartem }
96318c2aff7Sartem 
96418c2aff7Sartem 
96518c2aff7Sartem /*
96618c2aff7Sartem  * rescan by name
96718c2aff7Sartem  * if name is NULL, rescan all drives
96818c2aff7Sartem  */
96918c2aff7Sartem boolean_t
97018c2aff7Sartem rmm_rescan(LibHalContext *hal_ctx, const char *name, boolean_t query)
97118c2aff7Sartem {
97218c2aff7Sartem 	DBusError	error;
97318c2aff7Sartem 	GSList		*volumes;
97418c2aff7Sartem 	LibHalDrive	*drive = NULL;
97518c2aff7Sartem 	const char	*drive_udi;
97618c2aff7Sartem 	char		**udis;
97718c2aff7Sartem 	int		num_udis;
97818c2aff7Sartem 	char		*nickname;
97918c2aff7Sartem 	char		**nicks = NULL;
98018c2aff7Sartem 	boolean_t	do_free_udis = FALSE;
98118c2aff7Sartem 	int		i;
9827544909dSartem 	boolean_t	ret = B_FALSE;
98318c2aff7Sartem 
98418c2aff7Sartem 	dprintf("rmm_rescan %s\n", name != NULL ? name : "all");
98518c2aff7Sartem 
98618c2aff7Sartem 	dbus_error_init(&error);
98718c2aff7Sartem 
98818c2aff7Sartem 	if (name != NULL) {
98918c2aff7Sartem 		if ((drive = rmm_hal_volume_find(hal_ctx, name, &error,
99018c2aff7Sartem 		    &volumes)) == NULL) {
99118c2aff7Sartem 			rmm_dbus_error_free(&error);
99218c2aff7Sartem 			(void) fprintf(stderr,
99318c2aff7Sartem 			    gettext("cannot find '%s'\n"), name);
99418c2aff7Sartem 			return (B_FALSE);
99518c2aff7Sartem 		}
99618c2aff7Sartem 		rmm_dbus_error_free(&error);
99718c2aff7Sartem 		g_slist_free(volumes);
99818c2aff7Sartem 
99918c2aff7Sartem 		drive_udi = libhal_drive_get_udi(drive);
100018c2aff7Sartem 		udis = (char **)&drive_udi;
100118c2aff7Sartem 		num_udis = 1;
100218c2aff7Sartem 	} else {
100318c2aff7Sartem 		if ((udis = libhal_find_device_by_capability(hal_ctx,
100418c2aff7Sartem 		    "storage", &num_udis, &error)) == NULL) {
100518c2aff7Sartem 			rmm_dbus_error_free(&error);
100618c2aff7Sartem 			return (B_TRUE);
100718c2aff7Sartem 		}
100818c2aff7Sartem 		rmm_dbus_error_free(&error);
100918c2aff7Sartem 		do_free_udis = TRUE;
101018c2aff7Sartem 	}
101118c2aff7Sartem 
101218c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
101318c2aff7Sartem 		if (name == NULL) {
101418c2aff7Sartem 			nicks = libhal_device_get_property_strlist(hal_ctx,
101518c2aff7Sartem 			    udis[i], "storage.solaris.nicknames", NULL);
101618c2aff7Sartem 			if (nicks != NULL) {
101718c2aff7Sartem 				nickname = nicks[0];
101818c2aff7Sartem 			} else {
101918c2aff7Sartem 				nickname = "";
102018c2aff7Sartem 			}
102118c2aff7Sartem 		}
102218c2aff7Sartem 		if (!(ret = rmm_hal_rescan(hal_ctx, udis[i], &error))) {
102318c2aff7Sartem 			(void) fprintf(stderr,
102418c2aff7Sartem 			    gettext("rescan of %s failed: %s\n"),
102518c2aff7Sartem 			    name ? name : nickname,
102618c2aff7Sartem 			    rmm_strerror(&error, -1));
102718c2aff7Sartem 			libhal_free_string_array(nicks);
102818c2aff7Sartem 			continue;
102918c2aff7Sartem 		}
103018c2aff7Sartem 		if (query) {
10317544909dSartem 			ret = libhal_device_get_property_bool(hal_ctx, udis[i],
10327544909dSartem 			    "storage.removable.media_available", NULL);
10337544909dSartem 			if (ret) {
10347544909dSartem 				printf(gettext("%s is available\n"),
10357544909dSartem 				    name ? name : nickname);
10367544909dSartem 			} else {
10377544909dSartem 				printf(gettext("%s is not available\n"),
10387544909dSartem 				    name ? name : nickname);
10397544909dSartem 			}
104018c2aff7Sartem 		}
104118c2aff7Sartem 		libhal_free_string_array(nicks);
104218c2aff7Sartem 	}
104318c2aff7Sartem 
104418c2aff7Sartem 	if (drive != NULL) {
104518c2aff7Sartem 		libhal_drive_free(drive);
104618c2aff7Sartem 	}
104718c2aff7Sartem 	if (do_free_udis) {
104818c2aff7Sartem 		libhal_free_string_array(udis);
104918c2aff7Sartem 	}
105018c2aff7Sartem 
105118c2aff7Sartem 	return (ret);
105218c2aff7Sartem }
105318c2aff7Sartem 
105418c2aff7Sartem 
105518c2aff7Sartem /*
105618c2aff7Sartem  * set action_arg from volume properties
105718c2aff7Sartem  */
105818c2aff7Sartem boolean_t
105918c2aff7Sartem rmm_volume_aa_from_prop(LibHalContext *hal_ctx, const char *udi_arg,
106018c2aff7Sartem     LibHalVolume *volume_arg, struct action_arg *aap)
106118c2aff7Sartem {
106218c2aff7Sartem 	LibHalVolume	*volume = volume_arg;
106318c2aff7Sartem 	const char	*udi = udi_arg;
106418c2aff7Sartem 	const char	*drive_udi;
106518c2aff7Sartem 	char		*volume_label;
106618c2aff7Sartem 	char		*mountpoint;
106718c2aff7Sartem 	int		len;
106818c2aff7Sartem 	int		ret = B_FALSE;
106918c2aff7Sartem 
107018c2aff7Sartem 	/* at least udi or volume must be supplied */
107118c2aff7Sartem 	if ((udi == NULL) && (volume == NULL)) {
107218c2aff7Sartem 		return (B_FALSE);
107318c2aff7Sartem 	}
107418c2aff7Sartem 	if (volume == NULL) {
107518c2aff7Sartem 		if ((volume = libhal_volume_from_udi(hal_ctx, udi)) == NULL) {
107618c2aff7Sartem 			dprintf("cannot get volume %s\n", udi);
107718c2aff7Sartem 			goto out;
107818c2aff7Sartem 		}
107918c2aff7Sartem 	}
108018c2aff7Sartem 	if (udi == NULL) {
108118c2aff7Sartem 		if ((udi = libhal_volume_get_udi(volume)) == NULL) {
108218c2aff7Sartem 			dprintf("cannot get udi\n");
108318c2aff7Sartem 			goto out;
108418c2aff7Sartem 		}
108518c2aff7Sartem 	}
108618c2aff7Sartem 	drive_udi = libhal_volume_get_storage_device_udi(volume);
108718c2aff7Sartem 
108818c2aff7Sartem 	if (!(aap->aa_symdev = libhal_device_get_property_string(hal_ctx,
108918c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.symdev", NULL))) {
109018c2aff7Sartem 		dprintf("property %s not found %s\n",
109118c2aff7Sartem 		    "storage.solaris.legacy.symdev", drive_udi);
109218c2aff7Sartem 		goto out;
109318c2aff7Sartem 	}
109418c2aff7Sartem 	if (!(aap->aa_media = libhal_device_get_property_string(hal_ctx,
109518c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.media_type", NULL))) {
109618c2aff7Sartem 		dprintf("property %s not found %s\n",
109718c2aff7Sartem 		    "storage.solaris.legacy.media_type", drive_udi);
109818c2aff7Sartem 		goto out;
109918c2aff7Sartem 	}
110018c2aff7Sartem 
110118c2aff7Sartem 	/* name is derived from volume label */
110218c2aff7Sartem 	aap->aa_name = NULL;
110318c2aff7Sartem 	if ((volume_label = (char *)libhal_device_get_property_string(hal_ctx,
110418c2aff7Sartem 	    udi, "volume.label", NULL)) != NULL) {
110518c2aff7Sartem 		if ((len = strlen(volume_label)) > 0) {
110618c2aff7Sartem 			aap->aa_name = rmm_vold_convert_volume_label(
110718c2aff7Sartem 			    volume_label, len);
110818c2aff7Sartem 			if (strlen(aap->aa_name) == 0) {
110918c2aff7Sartem 				free(aap->aa_name);
111018c2aff7Sartem 				aap->aa_name = NULL;
111118c2aff7Sartem 			}
111218c2aff7Sartem 		}
111318c2aff7Sartem 		libhal_free_string(volume_label);
111418c2aff7Sartem 	}
111518c2aff7Sartem 	/* if no label, then unnamed_<mediatype> */
111618c2aff7Sartem 	if (aap->aa_name == NULL) {
111718c2aff7Sartem 		aap->aa_name = (char *)calloc(1, sizeof ("unnamed_floppyNNNN"));
111818c2aff7Sartem 		if (aap->aa_name == NULL) {
111918c2aff7Sartem 			goto out;
112018c2aff7Sartem 		}
112118c2aff7Sartem 		(void) snprintf(aap->aa_name, sizeof ("unnamed_floppyNNNN"),
112218c2aff7Sartem 		    "unnamed_%s", aap->aa_media);
112318c2aff7Sartem 	}
112418c2aff7Sartem 
112518c2aff7Sartem 	if (!(aap->aa_path = libhal_device_get_property_string(hal_ctx, udi,
112618c2aff7Sartem 	    "block.device", NULL))) {
112718c2aff7Sartem 		dprintf("property %s not found %s\n", "block.device", udi);
112818c2aff7Sartem 		goto out;
112918c2aff7Sartem 	}
113018c2aff7Sartem 	if (!(aap->aa_rawpath = libhal_device_get_property_string(hal_ctx, udi,
113118c2aff7Sartem 	    "block.solaris.raw_device", NULL))) {
113218c2aff7Sartem 		dprintf("property %s not found %s\n",
113318c2aff7Sartem 		    "block.solaris.raw_device", udi);
113418c2aff7Sartem 		goto out;
113518c2aff7Sartem 	}
113618c2aff7Sartem 	if (!(aap->aa_type = libhal_device_get_property_string(hal_ctx, udi,
113718c2aff7Sartem 	    "volume.fstype", NULL))) {
113818c2aff7Sartem 		dprintf("property %s not found %s\n", "volume.fstype", udi);
113918c2aff7Sartem 		goto out;
114018c2aff7Sartem 	}
114118c2aff7Sartem 	if (!libhal_device_get_property_bool(hal_ctx, udi,
114218c2aff7Sartem 	    "volume.is_partition", NULL)) {
114318c2aff7Sartem 		aap->aa_partname = NULL;
114418c2aff7Sartem 	} else if (!(aap->aa_partname = libhal_device_get_property_string(
114518c2aff7Sartem 	    hal_ctx, udi, "block.solaris.slice", NULL))) {
114618c2aff7Sartem 		dprintf("property %s not found %s\n",
114718c2aff7Sartem 		    "block.solaris.slice", udi);
114818c2aff7Sartem 		goto out;
114918c2aff7Sartem 	}
115018c2aff7Sartem 	if (!(mountpoint = libhal_device_get_property_string(hal_ctx, udi,
115118c2aff7Sartem 	    "volume.mount_point", NULL))) {
115218c2aff7Sartem 		dprintf("property %s not found %s\n",
115318c2aff7Sartem 		    "volume.mount_point", udi);
115418c2aff7Sartem 		goto out;
115518c2aff7Sartem 	}
115618c2aff7Sartem 	/*
115718c2aff7Sartem 	 * aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint()
115818c2aff7Sartem 	 * won't have to choose between free() or libhal_free_string() later on
115918c2aff7Sartem 	 */
116018c2aff7Sartem 	aap->aa_mountpoint = strdup(mountpoint);
116118c2aff7Sartem 	libhal_free_string(mountpoint);
116218c2aff7Sartem 	if (aap->aa_mountpoint == NULL) {
116318c2aff7Sartem 		dprintf("mountpoint is NULL %s\n", udi);
116418c2aff7Sartem 		goto out;
116518c2aff7Sartem 	}
116618c2aff7Sartem 
116718c2aff7Sartem 	ret = B_TRUE;
116818c2aff7Sartem 
116918c2aff7Sartem out:
117018c2aff7Sartem 	if ((volume != NULL) && (volume != volume_arg)) {
117118c2aff7Sartem 		libhal_volume_free(volume);
117218c2aff7Sartem 	}
117318c2aff7Sartem 	if (!ret) {
117418c2aff7Sartem 		rmm_volume_aa_free(aap);
117518c2aff7Sartem 	}
117618c2aff7Sartem 	return (ret);
117718c2aff7Sartem }
117818c2aff7Sartem 
117918c2aff7Sartem /* ARGSUSED */
118018c2aff7Sartem void
118118c2aff7Sartem rmm_volume_aa_update_mountpoint(LibHalContext *hal_ctx, const char *udi,
118218c2aff7Sartem     struct action_arg *aap)
118318c2aff7Sartem {
118418c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
118518c2aff7Sartem 		free(aap->aa_mountpoint);
118618c2aff7Sartem 	}
118718c2aff7Sartem 	aap->aa_mountpoint = rmm_get_mnttab_mount_point(aap->aa_path);
118818c2aff7Sartem }
118918c2aff7Sartem 
119018c2aff7Sartem void
119118c2aff7Sartem rmm_volume_aa_free(struct action_arg *aap)
119218c2aff7Sartem {
119318c2aff7Sartem 	if (aap->aa_symdev != NULL) {
119418c2aff7Sartem 		libhal_free_string(aap->aa_symdev);
119518c2aff7Sartem 		aap->aa_symdev = NULL;
119618c2aff7Sartem 	}
119718c2aff7Sartem 	if (aap->aa_name != NULL) {
119818c2aff7Sartem 		free(aap->aa_name);
119918c2aff7Sartem 		aap->aa_name = NULL;
120018c2aff7Sartem 	}
120118c2aff7Sartem 	if (aap->aa_path != NULL) {
120218c2aff7Sartem 		libhal_free_string(aap->aa_path);
120318c2aff7Sartem 		aap->aa_path = NULL;
120418c2aff7Sartem 	}
120518c2aff7Sartem 	if (aap->aa_rawpath != NULL) {
120618c2aff7Sartem 		libhal_free_string(aap->aa_rawpath);
120718c2aff7Sartem 		aap->aa_rawpath = NULL;
120818c2aff7Sartem 	}
120918c2aff7Sartem 	if (aap->aa_type != NULL) {
121018c2aff7Sartem 		libhal_free_string(aap->aa_type);
121118c2aff7Sartem 		aap->aa_type = NULL;
121218c2aff7Sartem 	}
121318c2aff7Sartem 	if (aap->aa_media != NULL) {
121418c2aff7Sartem 		libhal_free_string(aap->aa_media);
121518c2aff7Sartem 		aap->aa_media = NULL;
121618c2aff7Sartem 	}
121718c2aff7Sartem 	if (aap->aa_partname != NULL) {
121818c2aff7Sartem 		libhal_free_string(aap->aa_partname);
121918c2aff7Sartem 		aap->aa_partname = NULL;
122018c2aff7Sartem 	}
122118c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
122218c2aff7Sartem 		free(aap->aa_mountpoint);
122318c2aff7Sartem 		aap->aa_mountpoint = NULL;
122418c2aff7Sartem 	}
122518c2aff7Sartem }
122618c2aff7Sartem 
122718c2aff7Sartem /*
122818c2aff7Sartem  * get device's mount point from mnttab
122918c2aff7Sartem  */
123018c2aff7Sartem char *
123118c2aff7Sartem rmm_get_mnttab_mount_point(const char *special)
123218c2aff7Sartem {
123318c2aff7Sartem 	char		*mount_point = NULL;
123418c2aff7Sartem 	FILE		*f;
123518c2aff7Sartem 	struct mnttab	mnt;
123618c2aff7Sartem 	struct mnttab	mpref = { NULL, NULL, NULL, NULL, NULL };
123718c2aff7Sartem 
123818c2aff7Sartem 	if ((f = fopen(MNTTAB, "r")) != NULL) {
123918c2aff7Sartem 		mpref.mnt_special = (char *)special;
124018c2aff7Sartem 		if (getmntany(f, &mnt, &mpref) == 0) {
124118c2aff7Sartem 			mount_point = strdup(mnt.mnt_mountp);
124218c2aff7Sartem 		}
124318c2aff7Sartem 		fclose(f);
124418c2aff7Sartem 	}
124518c2aff7Sartem 
124618c2aff7Sartem 	return (mount_point);
124718c2aff7Sartem }
124818c2aff7Sartem 
124918c2aff7Sartem 
125018c2aff7Sartem /*
125118c2aff7Sartem  * get human readable string from error values
125218c2aff7Sartem  */
125318c2aff7Sartem const char *
125418c2aff7Sartem rmm_strerror(DBusError *dbus_error, int rmm_error)
125518c2aff7Sartem {
125618c2aff7Sartem 	const char	*str;
125718c2aff7Sartem 
125818c2aff7Sartem 	if ((dbus_error != NULL) && dbus_error_is_set(dbus_error)) {
125918c2aff7Sartem 		str = dbus_error->message;
126018c2aff7Sartem 	} else {
126118c2aff7Sartem 		switch (rmm_error) {
126218c2aff7Sartem 		case RMM_EOK:
126318c2aff7Sartem 			str = gettext("success");
126418c2aff7Sartem 			break;
126518c2aff7Sartem 		case RMM_EDBUS_CONNECT:
126618c2aff7Sartem 			str = gettext("cannot connect to D-Bus");
126718c2aff7Sartem 			break;
126818c2aff7Sartem 		case RMM_EHAL_CONNECT:
126918c2aff7Sartem 			str = gettext("cannot connect to HAL");
127018c2aff7Sartem 			break;
127118c2aff7Sartem 		default:
127218c2aff7Sartem 			str = gettext("undefined error");
127318c2aff7Sartem 			break;
127418c2aff7Sartem 		}
127518c2aff7Sartem 	}
127618c2aff7Sartem 
127718c2aff7Sartem 	return (str);
127818c2aff7Sartem }
127918c2aff7Sartem 
128018c2aff7Sartem void
128118c2aff7Sartem rmm_dbus_error_free(DBusError *error)
128218c2aff7Sartem {
128318c2aff7Sartem 	if (error != NULL && dbus_error_is_set(error)) {
128418c2aff7Sartem 		dbus_error_free(error);
128518c2aff7Sartem 	}
128618c2aff7Sartem }
128718c2aff7Sartem 
128818c2aff7Sartem static int
128918c2aff7Sartem rmm_vold_isbadchar(int c)
129018c2aff7Sartem {
129118c2aff7Sartem 	int	ret_val = 0;
129218c2aff7Sartem 
129318c2aff7Sartem 
129418c2aff7Sartem 	switch (c) {
129518c2aff7Sartem 	case '/':
129618c2aff7Sartem 	case ';':
129718c2aff7Sartem 	case '|':
129818c2aff7Sartem 		ret_val = 1;
129918c2aff7Sartem 		break;
130018c2aff7Sartem 	default:
130118c2aff7Sartem 		if (iscntrl(c) || isspace(c)) {
130218c2aff7Sartem 			ret_val = 1;
130318c2aff7Sartem 		}
130418c2aff7Sartem 	}
130518c2aff7Sartem 
130618c2aff7Sartem 	return (ret_val);
130718c2aff7Sartem }
130818c2aff7Sartem 
130918c2aff7Sartem char *
131018c2aff7Sartem rmm_vold_convert_volume_label(const char *name, size_t len)
131118c2aff7Sartem {
131218c2aff7Sartem 	char	buf[MAXNAMELEN+1];
131318c2aff7Sartem 	char	*s = buf;
131418c2aff7Sartem 	int	i;
131518c2aff7Sartem 
131618c2aff7Sartem 	if (len > MAXNAMELEN) {
131718c2aff7Sartem 		len = MAXNAMELEN;
131818c2aff7Sartem 	}
131918c2aff7Sartem 
132018c2aff7Sartem 	for (i = 0; i < len; i++) {
132118c2aff7Sartem 		if (name[i] == '\0') {
132218c2aff7Sartem 			break;
132318c2aff7Sartem 		}
132418c2aff7Sartem 		if (isgraph((int)name[i])) {
132518c2aff7Sartem 			if (isupper((int)name[i])) {
132618c2aff7Sartem 				*s++ = tolower((int)name[i]);
132718c2aff7Sartem 			} else if (rmm_vold_isbadchar((int)name[i])) {
132818c2aff7Sartem 				*s++ = '_';
132918c2aff7Sartem 			} else {
133018c2aff7Sartem 				*s++ = name[i];
133118c2aff7Sartem 			}
133218c2aff7Sartem 		}
133318c2aff7Sartem 	}
133418c2aff7Sartem 	*s = '\0';
133518c2aff7Sartem 	s = strdup(buf);
133618c2aff7Sartem 
133718c2aff7Sartem 	return (s);
133818c2aff7Sartem }
133918c2aff7Sartem 
134018c2aff7Sartem /*
134118c2aff7Sartem  * swiped from mkdir.c
134218c2aff7Sartem  */
134318c2aff7Sartem int
134418c2aff7Sartem makepath(char *dir, mode_t mode)
134518c2aff7Sartem {
134618c2aff7Sartem 	int		err;
134718c2aff7Sartem 	char		*slash;
134818c2aff7Sartem 
134918c2aff7Sartem 
135018c2aff7Sartem 	if ((mkdir(dir, mode) == 0) || (errno == EEXIST)) {
135118c2aff7Sartem 		return (0);
135218c2aff7Sartem 	}
135318c2aff7Sartem 	if (errno != ENOENT) {
135418c2aff7Sartem 		return (-1);
135518c2aff7Sartem 	}
135618c2aff7Sartem 	if ((slash = strrchr(dir, '/')) == NULL) {
135718c2aff7Sartem 		return (-1);
135818c2aff7Sartem 	}
135918c2aff7Sartem 	*slash = '\0';
136018c2aff7Sartem 	err = makepath(dir, mode);
136118c2aff7Sartem 	*slash++ = '/';
136218c2aff7Sartem 
136318c2aff7Sartem 	if (err || (*slash == '\0')) {
136418c2aff7Sartem 		return (err);
136518c2aff7Sartem 	}
136618c2aff7Sartem 
136718c2aff7Sartem 	return (mkdir(dir, mode));
136818c2aff7Sartem }
136918c2aff7Sartem 
137018c2aff7Sartem 
137118c2aff7Sartem void
137218c2aff7Sartem dprintf(const char *fmt, ...)
137318c2aff7Sartem {
137418c2aff7Sartem 
137518c2aff7Sartem 	va_list		ap;
137618c2aff7Sartem 	const char	*p;
137718c2aff7Sartem 	char		msg[BUFSIZ];
137818c2aff7Sartem 	char		*errmsg = strerror(errno);
137918c2aff7Sartem 	char		*s;
138018c2aff7Sartem 
138118c2aff7Sartem 	if (rmm_debug == 0) {
138218c2aff7Sartem 		return;
138318c2aff7Sartem 	}
138418c2aff7Sartem 
138518c2aff7Sartem 	(void) memset(msg, 0, BUFSIZ);
138618c2aff7Sartem 
138718c2aff7Sartem 	/* scan for %m and replace with errno msg */
138818c2aff7Sartem 	s = &msg[strlen(msg)];
138918c2aff7Sartem 	p = fmt;
139018c2aff7Sartem 
139118c2aff7Sartem 	while (*p != '\0') {
139218c2aff7Sartem 		if ((*p == '%') && (*(p+1) == 'm')) {
139318c2aff7Sartem 			(void) strcat(s, errmsg);
139418c2aff7Sartem 			p += 2;
139518c2aff7Sartem 			s += strlen(errmsg);
139618c2aff7Sartem 			continue;
139718c2aff7Sartem 		}
139818c2aff7Sartem 		*s++ = *p++;
139918c2aff7Sartem 	}
140018c2aff7Sartem 	*s = '\0';	/* don't forget the null byte */
140118c2aff7Sartem 
140218c2aff7Sartem 	va_start(ap, fmt);
140318c2aff7Sartem 	(void) vfprintf(stderr, msg, ap);
140418c2aff7Sartem 	va_end(ap);
140518c2aff7Sartem }
1406