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