xref: /titanic_41/usr/src/cmd/rmvolmgr/rmm_common.c (revision 68e92846614d4b32eb1a814a5e8e77331cfaaa59)
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 /*
2297ddcdceSArtem 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 *
rmm_hal_init(LibHalDeviceAdded devadd_cb,LibHalDeviceRemoved devrem_cb,LibHalDevicePropertyModified propmod_cb,LibHalDeviceCondition cond_cb,DBusError * error,rmm_error_t * rmm_error)6418c2aff7Sartem rmm_hal_init(LibHalDeviceAdded devadd_cb, LibHalDeviceRemoved devrem_cb,
6597ddcdceSArtem 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 	}
11597ddcdceSArtem Kachitchkine 	if (cond_cb != NULL) {
11697ddcdceSArtem Kachitchkine 		libhal_ctx_set_device_condition(ctx, cond_cb);
11797ddcdceSArtem 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
rmm_hal_fini(LibHalContext * hal_ctx)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 *
rmm_hal_volume_find(LibHalContext * hal_ctx,const char * name,DBusError * error,GSList ** volumes)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 *
rmm_hal_volume_find_default(LibHalContext * hal_ctx,DBusError * error,const char ** name_out,GSList ** volumes)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 *
rmm_hal_volume_findby(LibHalContext * hal_ctx,const char * property,const char * value,GSList ** volumes)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;
259*68e92846Sfei feng - Sun Microsystems - Beijing China 	int		i_drive = -1;
26018c2aff7Sartem 
26118c2aff7Sartem 	*volumes = NULL;
26218c2aff7Sartem 
26318c2aff7Sartem 	dbus_error_init(&error);
26418c2aff7Sartem 
26518c2aff7Sartem 	/* get all devices with property=value */
26618c2aff7Sartem 	if ((udis = libhal_manager_find_device_string_match(hal_ctx, property,
26718c2aff7Sartem 	    value, &num_udis, &error)) == NULL) {
26818c2aff7Sartem 		rmm_dbus_error_free(&error);
26918c2aff7Sartem 		return (NULL);
27018c2aff7Sartem 	}
27118c2aff7Sartem 
272*68e92846Sfei feng - Sun Microsystems - Beijing China 	/* find volumes and drives among these devices */
27318c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
27418c2aff7Sartem 		rmm_dbus_error_free(&error);
27518c2aff7Sartem 		if (libhal_device_query_capability(hal_ctx, udis[i], "volume",
27618c2aff7Sartem 		    &error)) {
27718c2aff7Sartem 			v = libhal_volume_from_udi(hal_ctx, udis[i]);
27818c2aff7Sartem 			if (v != NULL) {
27918c2aff7Sartem 				*volumes = g_slist_prepend(*volumes, v);
28018c2aff7Sartem 			}
281*68e92846Sfei feng - Sun Microsystems - Beijing China 		} else if ((*volumes == NULL) &&
282*68e92846Sfei feng - Sun Microsystems - Beijing China 		    libhal_device_query_capability(hal_ctx, udis[i], "storage",
283*68e92846Sfei feng - Sun Microsystems - Beijing China 		    &error)) {
284*68e92846Sfei feng - Sun Microsystems - Beijing China 			i_drive = i;
28518c2aff7Sartem 		}
28618c2aff7Sartem 	}
28718c2aff7Sartem 
28818c2aff7Sartem 	if (*volumes != NULL) {
289*68e92846Sfei feng - Sun Microsystems - Beijing China 		/* used prepend, preserve original order */
29018c2aff7Sartem 		*volumes = g_slist_reverse(*volumes);
29118c2aff7Sartem 
29218c2aff7Sartem 		v = (LibHalVolume *)(*volumes)->data;
29318c2aff7Sartem 		drive = libhal_drive_from_udi(hal_ctx,
29418c2aff7Sartem 		    libhal_volume_get_storage_device_udi(v));
29518c2aff7Sartem 		if (drive == NULL) {
29618c2aff7Sartem 			rmm_volumes_free (*volumes);
29718c2aff7Sartem 			*volumes = NULL;
29818c2aff7Sartem 		}
299*68e92846Sfei feng - Sun Microsystems - Beijing China 	} else if (i_drive >= 0) {
300*68e92846Sfei feng - Sun Microsystems - Beijing China 		drive = libhal_drive_from_udi(hal_ctx, udis[i_drive]);
30118c2aff7Sartem 	}
30218c2aff7Sartem 
30318c2aff7Sartem 	libhal_free_string_array(udis);
30418c2aff7Sartem 	rmm_dbus_error_free(&error);
30518c2aff7Sartem 
30618c2aff7Sartem 	return (drive);
30718c2aff7Sartem }
30818c2aff7Sartem 
3090ebe3100Sartem static void
rmm_print_nicknames_one(LibHalDrive * d,LibHalVolume * v,const char * device,char ** drive_nicknames)3100ebe3100Sartem rmm_print_nicknames_one(LibHalDrive *d, LibHalVolume *v,
3110ebe3100Sartem     const char *device, char **drive_nicknames)
31218c2aff7Sartem {
3130ebe3100Sartem 	const char	*volume_label = NULL;
3140ebe3100Sartem 	const char	*mount_point = NULL;
31518c2aff7Sartem 	boolean_t	comma;
3160ebe3100Sartem 	int		i;
31718c2aff7Sartem 
3180ebe3100Sartem 	(void) printf("%-*s ", RMM_PRINT_DEVICE_WIDTH, device);
31918c2aff7Sartem 	comma = B_FALSE;
32018c2aff7Sartem 
3210ebe3100Sartem 	if (drive_nicknames != NULL) {
3220ebe3100Sartem 		for (i = 0; drive_nicknames[i] != NULL; i++) {
32318c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "",
3240ebe3100Sartem 			    drive_nicknames[i]);
32518c2aff7Sartem 			comma = B_TRUE;
32618c2aff7Sartem 		}
32718c2aff7Sartem 	}
32818c2aff7Sartem 
3290ebe3100Sartem 	if ((v != NULL) &&
3300ebe3100Sartem 	    ((volume_label = libhal_volume_get_label(v)) != NULL) &&
33118c2aff7Sartem 	    (strlen(volume_label) > 0)) {
33218c2aff7Sartem 		(void) printf("%s%s", comma ? "," : "", volume_label);
33318c2aff7Sartem 		comma = B_TRUE;
33418c2aff7Sartem 	}
33518c2aff7Sartem 
3360ebe3100Sartem 	if ((v != NULL) &&
3370ebe3100Sartem 	    ((mount_point = libhal_volume_get_mount_point(v)) != NULL) &&
33818c2aff7Sartem 	    (strlen(mount_point) > 0)) {
33918c2aff7Sartem 		(void) printf("%s%s", comma ? "," : "", mount_point);
34018c2aff7Sartem 		comma = B_TRUE;
34118c2aff7Sartem 	}
34218c2aff7Sartem 
34318c2aff7Sartem 	(void) printf("\n");
3440ebe3100Sartem }
3450ebe3100Sartem 
3460ebe3100Sartem /*
3470ebe3100Sartem  * print nicknames for each available volume
3480ebe3100Sartem  *
3490ebe3100Sartem  * print_mask:
3500ebe3100Sartem  *   RMM_PRINT_MOUNTABLE	print only mountable volumes
3510ebe3100Sartem  *   RMM_PRINT_EJECTABLE	print volume-less ejectable drives
3520ebe3100Sartem  */
3530ebe3100Sartem void
rmm_print_volume_nicknames(LibHalContext * hal_ctx,DBusError * error,int print_mask)3540ebe3100Sartem rmm_print_volume_nicknames(LibHalContext *hal_ctx, DBusError *error,
3550ebe3100Sartem     int print_mask)
3560ebe3100Sartem {
3570ebe3100Sartem 	char		**udis;
3580ebe3100Sartem 	int		num_udis;
3590ebe3100Sartem 	GSList		*volumes = NULL;
3600ebe3100Sartem 	LibHalDrive	*d, *d_tmp;
3610ebe3100Sartem 	LibHalVolume	*v;
3620ebe3100Sartem 	const char	*device;
3630ebe3100Sartem 	char		**nicknames;
3640ebe3100Sartem 	int		i;
3650ebe3100Sartem 	GSList		*j;
3660ebe3100Sartem 	int		nprinted;
3670ebe3100Sartem 
3680ebe3100Sartem 	dbus_error_init(error);
3690ebe3100Sartem 
3700ebe3100Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
3710ebe3100Sartem 	    &num_udis, error)) == NULL) {
3720ebe3100Sartem 		rmm_dbus_error_free(error);
3730ebe3100Sartem 		return;
3740ebe3100Sartem 	}
3750ebe3100Sartem 
3760ebe3100Sartem 	for (i = 0; i < num_udis; i++) {
3770ebe3100Sartem 		if ((d = libhal_drive_from_udi(hal_ctx, udis[i])) == NULL) {
3780ebe3100Sartem 			continue;
3790ebe3100Sartem 		}
3800ebe3100Sartem 
3810ebe3100Sartem 		/* find volumes belonging to this drive */
3820ebe3100Sartem 		if ((d_tmp = rmm_hal_volume_findby(hal_ctx,
3830ebe3100Sartem 		    "block.storage_device", udis[i], &volumes)) != NULL) {
3840ebe3100Sartem 			libhal_drive_free(d_tmp);
3850ebe3100Sartem 		}
3860ebe3100Sartem 
3870ebe3100Sartem 		nicknames = libhal_device_get_property_strlist(hal_ctx,
3880ebe3100Sartem 		    udis[i], "storage.solaris.nicknames", NULL);
3890ebe3100Sartem 
3900ebe3100Sartem 		nprinted = 0;
3910ebe3100Sartem 		for (j = volumes; j != NULL; j = g_slist_next(j)) {
3920ebe3100Sartem 			v = (LibHalVolume *)(j->data);
3930ebe3100Sartem 
3940ebe3100Sartem 			if ((device = libhal_volume_get_device_file(v)) ==
3950ebe3100Sartem 			    NULL) {
3960ebe3100Sartem 				continue;
3970ebe3100Sartem 			}
3980ebe3100Sartem 			if ((print_mask & RMM_PRINT_MOUNTABLE) &&
3990ebe3100Sartem 			    (libhal_volume_get_fsusage(v) !=
4000ebe3100Sartem 			    LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM)) {
4010ebe3100Sartem 				continue;
4020ebe3100Sartem 			}
4030ebe3100Sartem 
4040ebe3100Sartem 			rmm_print_nicknames_one(d, v, device, nicknames);
4050ebe3100Sartem 			nprinted++;
4060ebe3100Sartem 		}
4070ebe3100Sartem 
4080ebe3100Sartem 		if ((nprinted == 0) &&
4090ebe3100Sartem 		    (print_mask & RMM_PRINT_EJECTABLE) &&
4100ebe3100Sartem 		    libhal_drive_requires_eject(d) &&
4110ebe3100Sartem 		    ((device = libhal_drive_get_device_file(d)) != NULL)) {
4120ebe3100Sartem 			rmm_print_nicknames_one(d, NULL, device, nicknames);
4130ebe3100Sartem 		}
41418c2aff7Sartem 
41518c2aff7Sartem 		libhal_free_string_array(nicknames);
4160ebe3100Sartem 		libhal_drive_free(d);
4170ebe3100Sartem 		rmm_volumes_free(volumes);
4180ebe3100Sartem 		volumes = NULL;
41918c2aff7Sartem 	}
42018c2aff7Sartem 
4210ebe3100Sartem 	libhal_free_string_array(udis);
4220ebe3100Sartem }
42318c2aff7Sartem 
42418c2aff7Sartem /*
42518c2aff7Sartem  * find volume by nickname
42618c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
42718c2aff7Sartem  */
42818c2aff7Sartem LibHalDrive *
rmm_hal_volume_findby_nickname(LibHalContext * hal_ctx,const char * name,GSList ** volumes)42918c2aff7Sartem rmm_hal_volume_findby_nickname(LibHalContext *hal_ctx, const char *name,
43018c2aff7Sartem     GSList **volumes)
43118c2aff7Sartem {
43218c2aff7Sartem 	DBusError	error;
43318c2aff7Sartem 	LibHalDrive	*drive = NULL;
43418c2aff7Sartem 	LibHalDrive	*drive_tmp;
43518c2aff7Sartem 	char		**udis;
43618c2aff7Sartem 	int		num_udis;
43718c2aff7Sartem 	char		**nicknames;
43818c2aff7Sartem 	int		i, j;
43918c2aff7Sartem 
44018c2aff7Sartem 	*volumes = NULL;
44118c2aff7Sartem 
44218c2aff7Sartem 	dbus_error_init(&error);
44318c2aff7Sartem 
44418c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
44518c2aff7Sartem 	    &num_udis, &error)) == NULL) {
44618c2aff7Sartem 		rmm_dbus_error_free(&error);
44718c2aff7Sartem 		return (NULL);
44818c2aff7Sartem 	}
44918c2aff7Sartem 
45018c2aff7Sartem 	/* find a drive by nickname */
45118c2aff7Sartem 	for (i = 0; (i < num_udis) && (drive == NULL); i++) {
45218c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
45318c2aff7Sartem 		    udis[i], "storage.solaris.nicknames", &error)) == NULL) {
45418c2aff7Sartem 			rmm_dbus_error_free(&error);
45518c2aff7Sartem 			continue;
45618c2aff7Sartem 		}
45718c2aff7Sartem 		for (j = 0; (nicknames[j] != NULL) && (drive == NULL); j++) {
45818c2aff7Sartem 			if (strcmp(nicknames[j], name) == 0) {
45918c2aff7Sartem 				drive = libhal_drive_from_udi(hal_ctx, udis[i]);
46018c2aff7Sartem 			}
46118c2aff7Sartem 		}
46218c2aff7Sartem 		libhal_free_string_array(nicknames);
46318c2aff7Sartem 	}
46418c2aff7Sartem 	libhal_free_string_array(udis);
46518c2aff7Sartem 
46618c2aff7Sartem 	if (drive != NULL) {
46718c2aff7Sartem 		/* found the drive, now find its volumes */
46818c2aff7Sartem 		if ((drive_tmp = rmm_hal_volume_findby(hal_ctx,
46918c2aff7Sartem 		    "block.storage_device", libhal_drive_get_udi(drive),
47018c2aff7Sartem 		    volumes)) != NULL) {
47118c2aff7Sartem 			libhal_drive_free(drive_tmp);
47218c2aff7Sartem 		}
47318c2aff7Sartem 	}
47418c2aff7Sartem 
47518c2aff7Sartem 	rmm_dbus_error_free(&error);
47618c2aff7Sartem 
47718c2aff7Sartem 	return (drive);
47818c2aff7Sartem }
47918c2aff7Sartem 
48018c2aff7Sartem void
rmm_volumes_free(GSList * volumes)48118c2aff7Sartem rmm_volumes_free(GSList *volumes)
48218c2aff7Sartem {
48318c2aff7Sartem 	GSList	*i;
48418c2aff7Sartem 
48518c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
48618c2aff7Sartem 		libhal_volume_free((LibHalVolume *)(i->data));
48718c2aff7Sartem 	}
48818c2aff7Sartem 	g_slist_free(volumes);
48918c2aff7Sartem }
49018c2aff7Sartem 
49118c2aff7Sartem /*
49218c2aff7Sartem  * Call HAL's Mount() method on the given device
49318c2aff7Sartem  */
49418c2aff7Sartem boolean_t
rmm_hal_mount(LibHalContext * hal_ctx,const char * udi,char ** opts,int num_opts,char * mountpoint,DBusError * error)49518c2aff7Sartem rmm_hal_mount(LibHalContext *hal_ctx, const char *udi,
49618c2aff7Sartem     char **opts, int num_opts, char *mountpoint, DBusError *error)
49718c2aff7Sartem {
49818c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
49918c2aff7Sartem 	DBusMessage	*dmesg, *reply;
50018c2aff7Sartem 	char		*fstype;
50118c2aff7Sartem 
50218c2aff7Sartem 	dprintf("mounting %s...\n", udi);
50318c2aff7Sartem 
50418c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
50518c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Mount"))) {
50618c2aff7Sartem 		dprintf(
50718c2aff7Sartem 		    "mount failed for %s: cannot create dbus message\n", udi);
50818c2aff7Sartem 		return (B_FALSE);
50918c2aff7Sartem 	}
51018c2aff7Sartem 
51118c2aff7Sartem 	fstype = "";
51218c2aff7Sartem 	if (mountpoint == NULL) {
51318c2aff7Sartem 		mountpoint = "";
51418c2aff7Sartem 	}
51518c2aff7Sartem 
51618c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &mountpoint,
51718c2aff7Sartem 	    DBUS_TYPE_STRING, &fstype,
51818c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &opts, num_opts,
51918c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
52018c2aff7Sartem 		dprintf("mount failed for %s: cannot append args\n", udi);
52118c2aff7Sartem 		dbus_message_unref(dmesg);
52218c2aff7Sartem 		return (B_FALSE);
52318c2aff7Sartem 	}
52418c2aff7Sartem 
52518c2aff7Sartem 	dbus_error_init(error);
52618c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
527b941d3fcSartem 	    dmesg, RMM_MOUNT_TIMEOUT, error))) {
52818c2aff7Sartem 		dprintf("mount failed for %s: %s\n", udi, error->message);
52918c2aff7Sartem 		dbus_message_unref(dmesg);
53018c2aff7Sartem 		return (B_FALSE);
53118c2aff7Sartem 	}
53218c2aff7Sartem 
53318c2aff7Sartem 	dprintf("mounted %s\n", udi);
53418c2aff7Sartem 
53518c2aff7Sartem 	dbus_message_unref(dmesg);
53618c2aff7Sartem 	dbus_message_unref(reply);
53718c2aff7Sartem 
53818c2aff7Sartem 	rmm_dbus_error_free(error);
53918c2aff7Sartem 
54018c2aff7Sartem 	return (B_TRUE);
54118c2aff7Sartem }
54218c2aff7Sartem 
54318c2aff7Sartem 
54418c2aff7Sartem /*
54518c2aff7Sartem  * Call HAL's Unmount() method on the given device
54618c2aff7Sartem  */
54718c2aff7Sartem boolean_t
rmm_hal_unmount(LibHalContext * hal_ctx,const char * udi,DBusError * error)54818c2aff7Sartem rmm_hal_unmount(LibHalContext *hal_ctx, const char *udi, DBusError *error)
54918c2aff7Sartem {
55018c2aff7Sartem 	DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
55118c2aff7Sartem 	DBusMessage *dmesg, *reply;
55218c2aff7Sartem 	char **opts = NULL;
55318c2aff7Sartem 
55418c2aff7Sartem 	dprintf("unmounting %s...\n", udi);
55518c2aff7Sartem 
55618c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
55718c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Unmount"))) {
55818c2aff7Sartem 		dprintf(
55918c2aff7Sartem 		    "unmount failed %s: cannot create dbus message\n", udi);
56018c2aff7Sartem 		return (B_FALSE);
56118c2aff7Sartem 	}
56218c2aff7Sartem 
56318c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
56418c2aff7Sartem 	    &opts, 0, DBUS_TYPE_INVALID)) {
56518c2aff7Sartem 		dprintf("unmount failed %s: cannot append args\n", udi);
56618c2aff7Sartem 		dbus_message_unref(dmesg);
56718c2aff7Sartem 		return (B_FALSE);
56818c2aff7Sartem 	}
56918c2aff7Sartem 
57018c2aff7Sartem 	dbus_error_init(error);
57118c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
572b941d3fcSartem 	    dmesg, RMM_UNMOUNT_TIMEOUT, error))) {
57318c2aff7Sartem 		dprintf("unmount failed for %s: %s\n", udi, error->message);
57418c2aff7Sartem 		dbus_message_unref(dmesg);
57518c2aff7Sartem 		return (B_FALSE);
57618c2aff7Sartem 	}
57718c2aff7Sartem 
57818c2aff7Sartem 	dprintf("unmounted %s\n", udi);
57918c2aff7Sartem 
58018c2aff7Sartem 	dbus_message_unref(dmesg);
58118c2aff7Sartem 	dbus_message_unref(reply);
58218c2aff7Sartem 
58318c2aff7Sartem 	rmm_dbus_error_free(error);
58418c2aff7Sartem 
58518c2aff7Sartem 	return (B_TRUE);
58618c2aff7Sartem }
58718c2aff7Sartem 
58818c2aff7Sartem 
58918c2aff7Sartem /*
59018c2aff7Sartem  * Call HAL's Eject() method on the given device
59118c2aff7Sartem  */
59218c2aff7Sartem boolean_t
rmm_hal_eject(LibHalContext * hal_ctx,const char * udi,DBusError * error)59318c2aff7Sartem rmm_hal_eject(LibHalContext *hal_ctx, const char *udi, DBusError *error)
59418c2aff7Sartem {
59518c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
59618c2aff7Sartem 	DBusMessage	*dmesg, *reply;
59718c2aff7Sartem 	char		**options = NULL;
59818c2aff7Sartem 	uint_t		num_options = 0;
59918c2aff7Sartem 
60018c2aff7Sartem 	dprintf("ejecting %s...\n", udi);
60118c2aff7Sartem 
60218c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
60318c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "Eject"))) {
60418c2aff7Sartem 		dprintf("eject %s: cannot create dbus message\n", udi);
60518c2aff7Sartem 		return (B_FALSE);
60618c2aff7Sartem 	}
60718c2aff7Sartem 
60818c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
60918c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
61018c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
61118c2aff7Sartem 		dprintf("eject %s: cannot append args to dbus message ", udi);
61218c2aff7Sartem 		dbus_message_unref(dmesg);
61318c2aff7Sartem 		return (B_FALSE);
61418c2aff7Sartem 	}
61518c2aff7Sartem 
61618c2aff7Sartem 	dbus_error_init(error);
61718c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
618b941d3fcSartem 	    dmesg, RMM_EJECT_TIMEOUT, error))) {
61918c2aff7Sartem 		dprintf("eject %s: %s\n", udi, error->message);
62018c2aff7Sartem 		dbus_message_unref(dmesg);
62118c2aff7Sartem 		return (B_FALSE);
62218c2aff7Sartem 	}
62318c2aff7Sartem 
62418c2aff7Sartem 	dprintf("ejected %s\n", udi);
62518c2aff7Sartem 
62618c2aff7Sartem 	dbus_message_unref(dmesg);
62718c2aff7Sartem 	dbus_message_unref(reply);
62818c2aff7Sartem 
62918c2aff7Sartem 	rmm_dbus_error_free(error);
63018c2aff7Sartem 
63118c2aff7Sartem 	return (B_TRUE);
63218c2aff7Sartem }
63318c2aff7Sartem 
63418c2aff7Sartem /*
63518c2aff7Sartem  * Call HAL's CloseTray() method on the given device
63618c2aff7Sartem  */
63718c2aff7Sartem boolean_t
rmm_hal_closetray(LibHalContext * hal_ctx,const char * udi,DBusError * error)63818c2aff7Sartem rmm_hal_closetray(LibHalContext *hal_ctx, const char *udi, DBusError *error)
63918c2aff7Sartem {
64018c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
64118c2aff7Sartem 	DBusMessage	*dmesg, *reply;
64218c2aff7Sartem 	char		**options = NULL;
64318c2aff7Sartem 	uint_t		num_options = 0;
64418c2aff7Sartem 
64518c2aff7Sartem 	dprintf("closing tray %s...\n", udi);
64618c2aff7Sartem 
64718c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
64818c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "CloseTray"))) {
64918c2aff7Sartem 		dprintf(
65018c2aff7Sartem 		    "closetray failed for %s: cannot create dbus message\n",
65118c2aff7Sartem 		    udi);
65218c2aff7Sartem 		return (B_FALSE);
65318c2aff7Sartem 	}
65418c2aff7Sartem 
65518c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
65618c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
65718c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
65818c2aff7Sartem 		dprintf("closetray %s: cannot append args to dbus message ",
65918c2aff7Sartem 		    udi);
66018c2aff7Sartem 		dbus_message_unref(dmesg);
66118c2aff7Sartem 		return (B_FALSE);
66218c2aff7Sartem 	}
66318c2aff7Sartem 
66418c2aff7Sartem 	dbus_error_init(error);
66518c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
666b941d3fcSartem 	    dmesg, RMM_CLOSETRAY_TIMEOUT, error))) {
66718c2aff7Sartem 		dprintf("closetray failed for %s: %s\n", udi, error->message);
66818c2aff7Sartem 		dbus_message_unref(dmesg);
66918c2aff7Sartem 		return (B_FALSE);
67018c2aff7Sartem 	}
67118c2aff7Sartem 
67218c2aff7Sartem 	dprintf("closetray ok %s\n", udi);
67318c2aff7Sartem 
67418c2aff7Sartem 	dbus_message_unref(dmesg);
67518c2aff7Sartem 	dbus_message_unref(reply);
67618c2aff7Sartem 
67718c2aff7Sartem 	rmm_dbus_error_free(error);
67818c2aff7Sartem 
67918c2aff7Sartem 	return (B_TRUE);
68018c2aff7Sartem }
68118c2aff7Sartem 
68218c2aff7Sartem /*
68318c2aff7Sartem  * Call HAL's Rescan() method on the given device
68418c2aff7Sartem  */
68518c2aff7Sartem boolean_t
rmm_hal_rescan(LibHalContext * hal_ctx,const char * udi,DBusError * error)68618c2aff7Sartem rmm_hal_rescan(LibHalContext *hal_ctx, const char *udi, DBusError *error)
68718c2aff7Sartem {
68818c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
68918c2aff7Sartem 	DBusMessage	*dmesg, *reply;
69018c2aff7Sartem 
69118c2aff7Sartem 	dprintf("rescanning %s...\n", udi);
69218c2aff7Sartem 
69318c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
69418c2aff7Sartem 	    "org.freedesktop.Hal.Device", "Rescan"))) {
69518c2aff7Sartem 		dprintf("rescan failed for %s: cannot create dbus message\n",
69618c2aff7Sartem 		    udi);
69718c2aff7Sartem 		return (B_FALSE);
69818c2aff7Sartem 	}
69918c2aff7Sartem 
70018c2aff7Sartem 	dbus_error_init(error);
70118c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
70218c2aff7Sartem 	    dmesg, -1, error))) {
70318c2aff7Sartem 		dprintf("rescan failed for %s: %s\n", udi, error->message);
70418c2aff7Sartem 		dbus_message_unref(dmesg);
70518c2aff7Sartem 		return (B_FALSE);
70618c2aff7Sartem 	}
70718c2aff7Sartem 
70818c2aff7Sartem 	dprintf("rescan ok %s\n", udi);
70918c2aff7Sartem 
71018c2aff7Sartem 	dbus_message_unref(dmesg);
71118c2aff7Sartem 	dbus_message_unref(reply);
71218c2aff7Sartem 
71318c2aff7Sartem 	rmm_dbus_error_free(error);
71418c2aff7Sartem 
71518c2aff7Sartem 	return (B_TRUE);
71618c2aff7Sartem }
71718c2aff7Sartem 
71818c2aff7Sartem boolean_t
rmm_hal_claim_branch(LibHalContext * hal_ctx,const char * udi)71918c2aff7Sartem rmm_hal_claim_branch(LibHalContext *hal_ctx, const char *udi)
72018c2aff7Sartem {
72118c2aff7Sartem 	DBusError error;
72218c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
72318c2aff7Sartem 	DBusMessage *dmesg, *reply;
72418c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
72518c2aff7Sartem 
72618c2aff7Sartem 	dprintf("claiming branch %s...\n", udi);
72718c2aff7Sartem 
72818c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
72918c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
73018c2aff7Sartem 	    "ClaimBranch"))) {
73118c2aff7Sartem 		dprintf("cannot create dbus message\n");
73218c2aff7Sartem 		return (B_FALSE);
73318c2aff7Sartem 	}
73418c2aff7Sartem 
73518c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
73618c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
73718c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
73818c2aff7Sartem 		dbus_message_unref(dmesg);
73918c2aff7Sartem 		return (B_FALSE);
74018c2aff7Sartem 	}
74118c2aff7Sartem 
74218c2aff7Sartem 	dbus_error_init(&error);
74318c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
74418c2aff7Sartem 	    dmesg, -1, &error))) {
74518c2aff7Sartem 		dprintf("cannot send dbus message\n");
74618c2aff7Sartem 		dbus_message_unref(dmesg);
74718c2aff7Sartem 		rmm_dbus_error_free(&error);
74818c2aff7Sartem 		return (B_FALSE);
74918c2aff7Sartem 	}
75018c2aff7Sartem 
75118c2aff7Sartem 	dprintf("claim branch ok %s\n", udi);
75218c2aff7Sartem 
75318c2aff7Sartem 	dbus_message_unref(dmesg);
75418c2aff7Sartem 	dbus_message_unref(reply);
75518c2aff7Sartem 
75618c2aff7Sartem 	return (B_TRUE);
75718c2aff7Sartem }
75818c2aff7Sartem 
75918c2aff7Sartem boolean_t
rmm_hal_unclaim_branch(LibHalContext * hal_ctx,const char * udi)76018c2aff7Sartem rmm_hal_unclaim_branch(LibHalContext *hal_ctx, const char *udi)
76118c2aff7Sartem {
76218c2aff7Sartem 	DBusError error;
76318c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
76418c2aff7Sartem 	DBusMessage *dmesg, *reply;
76518c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
76618c2aff7Sartem 
76718c2aff7Sartem 	dprintf("unclaiming branch %s...\n", udi);
76818c2aff7Sartem 
76918c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
77018c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
77118c2aff7Sartem 	    "UnclaimBranch"))) {
77218c2aff7Sartem 		dprintf("cannot create dbus message\n");
77318c2aff7Sartem 		return (B_FALSE);
77418c2aff7Sartem 	}
77518c2aff7Sartem 
77618c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
77718c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
77818c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
77918c2aff7Sartem 		dbus_message_unref(dmesg);
78018c2aff7Sartem 		return (B_FALSE);
78118c2aff7Sartem 	}
78218c2aff7Sartem 
78318c2aff7Sartem 	dbus_error_init(&error);
78418c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
78518c2aff7Sartem 	    dmesg, -1, &error))) {
78618c2aff7Sartem 		dprintf("cannot send dbus message\n");
78718c2aff7Sartem 		dbus_message_unref(dmesg);
78818c2aff7Sartem 		rmm_dbus_error_free(&error);
78918c2aff7Sartem 		return (B_FALSE);
79018c2aff7Sartem 	}
79118c2aff7Sartem 
79218c2aff7Sartem 	dprintf("unclaim branch ok %s\n", udi);
79318c2aff7Sartem 
79418c2aff7Sartem 	dbus_message_unref(dmesg);
79518c2aff7Sartem 	dbus_message_unref(reply);
79618c2aff7Sartem 
79718c2aff7Sartem 	return (B_TRUE);
79818c2aff7Sartem }
79918c2aff7Sartem 
80018c2aff7Sartem static boolean_t
rmm_action_one(LibHalContext * hal_ctx,const char * name,action_t action,const char * dev,const char * udi,LibHalVolume * v,char ** opts,int num_opts,char * mountpoint)80118c2aff7Sartem rmm_action_one(LibHalContext *hal_ctx, const char *name, action_t action,
80218c2aff7Sartem     const char *dev, const char *udi, LibHalVolume *v,
80318c2aff7Sartem     char **opts, int num_opts, char *mountpoint)
80418c2aff7Sartem {
80518c2aff7Sartem 	char		dev_str[MAXPATHLEN];
80618c2aff7Sartem 	char		*mountp;
80718c2aff7Sartem 	DBusError	error;
80818c2aff7Sartem 	boolean_t	ret = B_FALSE;
80918c2aff7Sartem 
81018c2aff7Sartem 	if (strcmp(name, dev) == 0) {
81118c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), name);
81218c2aff7Sartem 	} else {
81318c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), "%s %s", name, dev);
81418c2aff7Sartem 	}
81518c2aff7Sartem 
81618c2aff7Sartem 	dbus_error_init(&error);
81718c2aff7Sartem 
81818c2aff7Sartem 	switch (action) {
81918c2aff7Sartem 	case EJECT:
82018c2aff7Sartem 		ret = rmm_hal_eject(hal_ctx, udi, &error);
82118c2aff7Sartem 		break;
82218c2aff7Sartem 	case INSERT:
82318c2aff7Sartem 	case REMOUNT:
82418c2aff7Sartem 		if (libhal_volume_is_mounted(v)) {
82518c2aff7Sartem 			goto done;
82618c2aff7Sartem 		}
82718c2aff7Sartem 		ret = rmm_hal_mount(hal_ctx, udi,
82818c2aff7Sartem 		    opts, num_opts, mountpoint, &error);
82918c2aff7Sartem 		break;
83018c2aff7Sartem 	case UNMOUNT:
83118c2aff7Sartem 		if (!libhal_volume_is_mounted(v)) {
83218c2aff7Sartem 			goto done;
83318c2aff7Sartem 		}
83418c2aff7Sartem 		ret = rmm_hal_unmount(hal_ctx, udi, &error);
83518c2aff7Sartem 		break;
83618c2aff7Sartem 	case CLOSETRAY:
83718c2aff7Sartem 		ret = rmm_hal_closetray(hal_ctx, udi, &error);
83818c2aff7Sartem 		break;
83918c2aff7Sartem 	}
84018c2aff7Sartem 
84118c2aff7Sartem 	if (!ret) {
84218c2aff7Sartem 		(void) fprintf(stderr, gettext("%s of %s failed: %s\n"),
84318c2aff7Sartem 		    action_strings[action], dev_str, rmm_strerror(&error, -1));
84418c2aff7Sartem 		goto done;
84518c2aff7Sartem 	}
84618c2aff7Sartem 
84718c2aff7Sartem 	switch (action) {
84818c2aff7Sartem 	case EJECT:
84918c2aff7Sartem 		(void) printf(gettext("%s ejected\n"), dev_str);
85018c2aff7Sartem 		break;
85118c2aff7Sartem 	case INSERT:
85218c2aff7Sartem 	case REMOUNT:
85318c2aff7Sartem 		mountp = rmm_get_mnttab_mount_point(dev);
85418c2aff7Sartem 		if (mountp != NULL) {
85518c2aff7Sartem 			(void) printf(gettext("%s mounted at %s\n"),
85618c2aff7Sartem 			    dev_str, mountp);
85718c2aff7Sartem 			free(mountp);
85818c2aff7Sartem 		}
85918c2aff7Sartem 		break;
86018c2aff7Sartem 	case UNMOUNT:
86118c2aff7Sartem 		(void) printf(gettext("%s unmounted\n"), dev_str);
86218c2aff7Sartem 		break;
86318c2aff7Sartem 	case CLOSETRAY:
86418c2aff7Sartem 		(void) printf(gettext("%s tray closed\n"), dev_str);
86518c2aff7Sartem 		break;
86618c2aff7Sartem 	}
86718c2aff7Sartem 
86818c2aff7Sartem done:
86918c2aff7Sartem 	rmm_dbus_error_free(&error);
87018c2aff7Sartem 	return (ret);
87118c2aff7Sartem }
87218c2aff7Sartem 
87318c2aff7Sartem /*
87418c2aff7Sartem  * top level action routine
87518c2aff7Sartem  *
87618c2aff7Sartem  * If non-null 'aa' is passed, it will be used, otherwise a local copy
87718c2aff7Sartem  * will be created.
87818c2aff7Sartem  */
87918c2aff7Sartem boolean_t
rmm_action(LibHalContext * hal_ctx,const char * name,action_t action,struct action_arg * aap,char ** opts,int num_opts,char * mountpoint)88018c2aff7Sartem rmm_action(LibHalContext *hal_ctx, const char *name, action_t action,
88118c2aff7Sartem     struct action_arg *aap, char **opts, int num_opts, char *mountpoint)
88218c2aff7Sartem {
88318c2aff7Sartem 	DBusError	error;
88418c2aff7Sartem 	GSList		*volumes, *i;
88518c2aff7Sartem 	LibHalDrive	*d;
88618c2aff7Sartem 	LibHalVolume	*v;
88718c2aff7Sartem 	const char	*udi, *d_udi;
88818c2aff7Sartem 	const char	*dev, *d_dev;
88918c2aff7Sartem 	struct action_arg aa_local;
89018c2aff7Sartem 	boolean_t	ret = B_FALSE;
89118c2aff7Sartem 
89218c2aff7Sartem 	dprintf("rmm_action %s %s\n", name, action_strings[action]);
89318c2aff7Sartem 
89418c2aff7Sartem 	if (aap == NULL) {
8957544909dSartem 		bzero(&aa_local, sizeof (aa_local));
89618c2aff7Sartem 		aap = &aa_local;
89718c2aff7Sartem 	}
89818c2aff7Sartem 
89918c2aff7Sartem 	dbus_error_init(&error);
90018c2aff7Sartem 
90118c2aff7Sartem 	/* find the drive and its volumes */
90218c2aff7Sartem 	d = rmm_hal_volume_find(hal_ctx, name, &error, &volumes);
90318c2aff7Sartem 	rmm_dbus_error_free(&error);
90418c2aff7Sartem 	if (d == NULL) {
90518c2aff7Sartem 		(void) fprintf(stderr, gettext("cannot find '%s'\n"), name);
90618c2aff7Sartem 		return (B_FALSE);
90718c2aff7Sartem 	}
90818c2aff7Sartem 	d_udi = libhal_drive_get_udi(d);
90918c2aff7Sartem 	d_dev = libhal_drive_get_device_file(d);
91018c2aff7Sartem 	if ((d_udi == NULL) || (d_dev == NULL)) {
91118c2aff7Sartem 		goto out;
91218c2aff7Sartem 	}
91318c2aff7Sartem 
91418c2aff7Sartem 	/*
91518c2aff7Sartem 	 * For those drives that do not require media eject,
91618c2aff7Sartem 	 * EJECT turns into UNMOUNT.
91718c2aff7Sartem 	 */
91818c2aff7Sartem 	if ((action == EJECT) && !libhal_drive_requires_eject(d)) {
91918c2aff7Sartem 		action = UNMOUNT;
92018c2aff7Sartem 	}
92118c2aff7Sartem 
92218c2aff7Sartem 	/* per drive action */
92318c2aff7Sartem 	if ((action == EJECT) || (action == CLOSETRAY)) {
92418c2aff7Sartem 		ret = rmm_action_one(hal_ctx, name, action, d_dev, d_udi, NULL,
92518c2aff7Sartem 		    opts, num_opts, NULL);
92618c2aff7Sartem 
92718c2aff7Sartem 		if (!ret || (action == CLOSETRAY)) {
92818c2aff7Sartem 			goto out;
92918c2aff7Sartem 		}
93018c2aff7Sartem 	}
93118c2aff7Sartem 
93218c2aff7Sartem 	/* per volume action */
93318c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
93418c2aff7Sartem 		v = (LibHalVolume *)i->data;
93518c2aff7Sartem 		udi = libhal_volume_get_udi(v);
93618c2aff7Sartem 		dev = libhal_volume_get_device_file(v);
93718c2aff7Sartem 
93818c2aff7Sartem 		if ((udi == NULL) || (dev == NULL)) {
93918c2aff7Sartem 			continue;
94018c2aff7Sartem 		}
94118c2aff7Sartem 		if (aap == &aa_local) {
94218c2aff7Sartem 			if (!rmm_volume_aa_from_prop(hal_ctx, udi, v, aap)) {
94318c2aff7Sartem 				dprintf("rmm_volume_aa_from_prop failed %s\n",
94418c2aff7Sartem 				    udi);
94518c2aff7Sartem 				continue;
94618c2aff7Sartem 			}
94718c2aff7Sartem 		}
94818c2aff7Sartem 		aap->aa_action = action;
94918c2aff7Sartem 
95018c2aff7Sartem 		/* ejected above, just need postprocess */
95118c2aff7Sartem 		if (action != EJECT) {
95218c2aff7Sartem 			ret = rmm_action_one(hal_ctx, name, action, dev, udi, v,
95318c2aff7Sartem 			    opts, num_opts, mountpoint);
95418c2aff7Sartem 		}
95518c2aff7Sartem 		if (ret) {
95618c2aff7Sartem 			(void) vold_postprocess(hal_ctx, udi, aap);
95718c2aff7Sartem 		}
95818c2aff7Sartem 
95918c2aff7Sartem 		if (aap == &aa_local) {
96018c2aff7Sartem 			rmm_volume_aa_free(aap);
96118c2aff7Sartem 		}
96218c2aff7Sartem 	}
96318c2aff7Sartem 
96418c2aff7Sartem out:
965*68e92846Sfei feng - Sun Microsystems - Beijing China 	rmm_volumes_free(volumes);
96618c2aff7Sartem 	libhal_drive_free(d);
96718c2aff7Sartem 
96818c2aff7Sartem 	return (ret);
96918c2aff7Sartem }
97018c2aff7Sartem 
97118c2aff7Sartem 
97218c2aff7Sartem /*
97318c2aff7Sartem  * rescan by name
97418c2aff7Sartem  * if name is NULL, rescan all drives
97518c2aff7Sartem  */
97618c2aff7Sartem boolean_t
rmm_rescan(LibHalContext * hal_ctx,const char * name,boolean_t query)97718c2aff7Sartem rmm_rescan(LibHalContext *hal_ctx, const char *name, boolean_t query)
97818c2aff7Sartem {
97918c2aff7Sartem 	DBusError	error;
98018c2aff7Sartem 	GSList		*volumes;
98118c2aff7Sartem 	LibHalDrive	*drive = NULL;
98218c2aff7Sartem 	const char	*drive_udi;
98318c2aff7Sartem 	char		**udis;
98418c2aff7Sartem 	int		num_udis;
98518c2aff7Sartem 	char		*nickname;
98618c2aff7Sartem 	char		**nicks = NULL;
98718c2aff7Sartem 	boolean_t	do_free_udis = FALSE;
98818c2aff7Sartem 	int		i;
9897544909dSartem 	boolean_t	ret = B_FALSE;
99018c2aff7Sartem 
99118c2aff7Sartem 	dprintf("rmm_rescan %s\n", name != NULL ? name : "all");
99218c2aff7Sartem 
99318c2aff7Sartem 	dbus_error_init(&error);
99418c2aff7Sartem 
99518c2aff7Sartem 	if (name != NULL) {
99618c2aff7Sartem 		if ((drive = rmm_hal_volume_find(hal_ctx, name, &error,
99718c2aff7Sartem 		    &volumes)) == NULL) {
99818c2aff7Sartem 			rmm_dbus_error_free(&error);
99918c2aff7Sartem 			(void) fprintf(stderr,
100018c2aff7Sartem 			    gettext("cannot find '%s'\n"), name);
100118c2aff7Sartem 			return (B_FALSE);
100218c2aff7Sartem 		}
100318c2aff7Sartem 		rmm_dbus_error_free(&error);
100418c2aff7Sartem 		g_slist_free(volumes);
100518c2aff7Sartem 
100618c2aff7Sartem 		drive_udi = libhal_drive_get_udi(drive);
100718c2aff7Sartem 		udis = (char **)&drive_udi;
100818c2aff7Sartem 		num_udis = 1;
100918c2aff7Sartem 	} else {
101018c2aff7Sartem 		if ((udis = libhal_find_device_by_capability(hal_ctx,
101118c2aff7Sartem 		    "storage", &num_udis, &error)) == NULL) {
101218c2aff7Sartem 			rmm_dbus_error_free(&error);
101318c2aff7Sartem 			return (B_TRUE);
101418c2aff7Sartem 		}
101518c2aff7Sartem 		rmm_dbus_error_free(&error);
101618c2aff7Sartem 		do_free_udis = TRUE;
101718c2aff7Sartem 	}
101818c2aff7Sartem 
101918c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
102018c2aff7Sartem 		if (name == NULL) {
102118c2aff7Sartem 			nicks = libhal_device_get_property_strlist(hal_ctx,
102218c2aff7Sartem 			    udis[i], "storage.solaris.nicknames", NULL);
102318c2aff7Sartem 			if (nicks != NULL) {
102418c2aff7Sartem 				nickname = nicks[0];
102518c2aff7Sartem 			} else {
102618c2aff7Sartem 				nickname = "";
102718c2aff7Sartem 			}
102818c2aff7Sartem 		}
102918c2aff7Sartem 		if (!(ret = rmm_hal_rescan(hal_ctx, udis[i], &error))) {
103018c2aff7Sartem 			(void) fprintf(stderr,
103118c2aff7Sartem 			    gettext("rescan of %s failed: %s\n"),
103218c2aff7Sartem 			    name ? name : nickname,
103318c2aff7Sartem 			    rmm_strerror(&error, -1));
103418c2aff7Sartem 			libhal_free_string_array(nicks);
103518c2aff7Sartem 			continue;
103618c2aff7Sartem 		}
103718c2aff7Sartem 		if (query) {
10387544909dSartem 			ret = libhal_device_get_property_bool(hal_ctx, udis[i],
10397544909dSartem 			    "storage.removable.media_available", NULL);
10407544909dSartem 			if (ret) {
10417544909dSartem 				printf(gettext("%s is available\n"),
10427544909dSartem 				    name ? name : nickname);
10437544909dSartem 			} else {
10447544909dSartem 				printf(gettext("%s is not available\n"),
10457544909dSartem 				    name ? name : nickname);
10467544909dSartem 			}
104718c2aff7Sartem 		}
104818c2aff7Sartem 		libhal_free_string_array(nicks);
104918c2aff7Sartem 	}
105018c2aff7Sartem 
105118c2aff7Sartem 	if (drive != NULL) {
105218c2aff7Sartem 		libhal_drive_free(drive);
105318c2aff7Sartem 	}
105418c2aff7Sartem 	if (do_free_udis) {
105518c2aff7Sartem 		libhal_free_string_array(udis);
105618c2aff7Sartem 	}
105718c2aff7Sartem 
105818c2aff7Sartem 	return (ret);
105918c2aff7Sartem }
106018c2aff7Sartem 
106118c2aff7Sartem 
106218c2aff7Sartem /*
106318c2aff7Sartem  * set action_arg from volume properties
106418c2aff7Sartem  */
106518c2aff7Sartem boolean_t
rmm_volume_aa_from_prop(LibHalContext * hal_ctx,const char * udi_arg,LibHalVolume * volume_arg,struct action_arg * aap)106618c2aff7Sartem rmm_volume_aa_from_prop(LibHalContext *hal_ctx, const char *udi_arg,
106718c2aff7Sartem     LibHalVolume *volume_arg, struct action_arg *aap)
106818c2aff7Sartem {
106918c2aff7Sartem 	LibHalVolume	*volume = volume_arg;
107018c2aff7Sartem 	const char	*udi = udi_arg;
107118c2aff7Sartem 	const char	*drive_udi;
107218c2aff7Sartem 	char		*volume_label;
107318c2aff7Sartem 	char		*mountpoint;
107418c2aff7Sartem 	int		len;
107518c2aff7Sartem 	int		ret = B_FALSE;
107618c2aff7Sartem 
107718c2aff7Sartem 	/* at least udi or volume must be supplied */
107818c2aff7Sartem 	if ((udi == NULL) && (volume == NULL)) {
107918c2aff7Sartem 		return (B_FALSE);
108018c2aff7Sartem 	}
108118c2aff7Sartem 	if (volume == NULL) {
108218c2aff7Sartem 		if ((volume = libhal_volume_from_udi(hal_ctx, udi)) == NULL) {
108318c2aff7Sartem 			dprintf("cannot get volume %s\n", udi);
108418c2aff7Sartem 			goto out;
108518c2aff7Sartem 		}
108618c2aff7Sartem 	}
108718c2aff7Sartem 	if (udi == NULL) {
108818c2aff7Sartem 		if ((udi = libhal_volume_get_udi(volume)) == NULL) {
108918c2aff7Sartem 			dprintf("cannot get udi\n");
109018c2aff7Sartem 			goto out;
109118c2aff7Sartem 		}
109218c2aff7Sartem 	}
109318c2aff7Sartem 	drive_udi = libhal_volume_get_storage_device_udi(volume);
109418c2aff7Sartem 
109518c2aff7Sartem 	if (!(aap->aa_symdev = libhal_device_get_property_string(hal_ctx,
109618c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.symdev", NULL))) {
109718c2aff7Sartem 		dprintf("property %s not found %s\n",
109818c2aff7Sartem 		    "storage.solaris.legacy.symdev", drive_udi);
109918c2aff7Sartem 		goto out;
110018c2aff7Sartem 	}
110118c2aff7Sartem 	if (!(aap->aa_media = libhal_device_get_property_string(hal_ctx,
110218c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.media_type", NULL))) {
110318c2aff7Sartem 		dprintf("property %s not found %s\n",
110418c2aff7Sartem 		    "storage.solaris.legacy.media_type", drive_udi);
110518c2aff7Sartem 		goto out;
110618c2aff7Sartem 	}
110718c2aff7Sartem 
110818c2aff7Sartem 	/* name is derived from volume label */
110918c2aff7Sartem 	aap->aa_name = NULL;
111018c2aff7Sartem 	if ((volume_label = (char *)libhal_device_get_property_string(hal_ctx,
111118c2aff7Sartem 	    udi, "volume.label", NULL)) != NULL) {
111218c2aff7Sartem 		if ((len = strlen(volume_label)) > 0) {
111318c2aff7Sartem 			aap->aa_name = rmm_vold_convert_volume_label(
111418c2aff7Sartem 			    volume_label, len);
111518c2aff7Sartem 			if (strlen(aap->aa_name) == 0) {
111618c2aff7Sartem 				free(aap->aa_name);
111718c2aff7Sartem 				aap->aa_name = NULL;
111818c2aff7Sartem 			}
111918c2aff7Sartem 		}
112018c2aff7Sartem 		libhal_free_string(volume_label);
112118c2aff7Sartem 	}
112218c2aff7Sartem 	/* if no label, then unnamed_<mediatype> */
112318c2aff7Sartem 	if (aap->aa_name == NULL) {
112418c2aff7Sartem 		aap->aa_name = (char *)calloc(1, sizeof ("unnamed_floppyNNNN"));
112518c2aff7Sartem 		if (aap->aa_name == NULL) {
112618c2aff7Sartem 			goto out;
112718c2aff7Sartem 		}
112818c2aff7Sartem 		(void) snprintf(aap->aa_name, sizeof ("unnamed_floppyNNNN"),
112918c2aff7Sartem 		    "unnamed_%s", aap->aa_media);
113018c2aff7Sartem 	}
113118c2aff7Sartem 
113218c2aff7Sartem 	if (!(aap->aa_path = libhal_device_get_property_string(hal_ctx, udi,
113318c2aff7Sartem 	    "block.device", NULL))) {
113418c2aff7Sartem 		dprintf("property %s not found %s\n", "block.device", udi);
113518c2aff7Sartem 		goto out;
113618c2aff7Sartem 	}
113718c2aff7Sartem 	if (!(aap->aa_rawpath = libhal_device_get_property_string(hal_ctx, udi,
113818c2aff7Sartem 	    "block.solaris.raw_device", NULL))) {
113918c2aff7Sartem 		dprintf("property %s not found %s\n",
114018c2aff7Sartem 		    "block.solaris.raw_device", udi);
114118c2aff7Sartem 		goto out;
114218c2aff7Sartem 	}
114318c2aff7Sartem 	if (!(aap->aa_type = libhal_device_get_property_string(hal_ctx, udi,
114418c2aff7Sartem 	    "volume.fstype", NULL))) {
114518c2aff7Sartem 		dprintf("property %s not found %s\n", "volume.fstype", udi);
114618c2aff7Sartem 		goto out;
114718c2aff7Sartem 	}
114818c2aff7Sartem 	if (!libhal_device_get_property_bool(hal_ctx, udi,
114918c2aff7Sartem 	    "volume.is_partition", NULL)) {
115018c2aff7Sartem 		aap->aa_partname = NULL;
115118c2aff7Sartem 	} else if (!(aap->aa_partname = libhal_device_get_property_string(
115218c2aff7Sartem 	    hal_ctx, udi, "block.solaris.slice", NULL))) {
115318c2aff7Sartem 		dprintf("property %s not found %s\n",
115418c2aff7Sartem 		    "block.solaris.slice", udi);
115518c2aff7Sartem 		goto out;
115618c2aff7Sartem 	}
115718c2aff7Sartem 	if (!(mountpoint = libhal_device_get_property_string(hal_ctx, udi,
115818c2aff7Sartem 	    "volume.mount_point", NULL))) {
115918c2aff7Sartem 		dprintf("property %s not found %s\n",
116018c2aff7Sartem 		    "volume.mount_point", udi);
116118c2aff7Sartem 		goto out;
116218c2aff7Sartem 	}
116318c2aff7Sartem 	/*
116418c2aff7Sartem 	 * aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint()
116518c2aff7Sartem 	 * won't have to choose between free() or libhal_free_string() later on
116618c2aff7Sartem 	 */
116718c2aff7Sartem 	aap->aa_mountpoint = strdup(mountpoint);
116818c2aff7Sartem 	libhal_free_string(mountpoint);
116918c2aff7Sartem 	if (aap->aa_mountpoint == NULL) {
117018c2aff7Sartem 		dprintf("mountpoint is NULL %s\n", udi);
117118c2aff7Sartem 		goto out;
117218c2aff7Sartem 	}
117318c2aff7Sartem 
117418c2aff7Sartem 	ret = B_TRUE;
117518c2aff7Sartem 
117618c2aff7Sartem out:
117718c2aff7Sartem 	if ((volume != NULL) && (volume != volume_arg)) {
117818c2aff7Sartem 		libhal_volume_free(volume);
117918c2aff7Sartem 	}
118018c2aff7Sartem 	if (!ret) {
118118c2aff7Sartem 		rmm_volume_aa_free(aap);
118218c2aff7Sartem 	}
118318c2aff7Sartem 	return (ret);
118418c2aff7Sartem }
118518c2aff7Sartem 
118618c2aff7Sartem /* ARGSUSED */
118718c2aff7Sartem void
rmm_volume_aa_update_mountpoint(LibHalContext * hal_ctx,const char * udi,struct action_arg * aap)118818c2aff7Sartem rmm_volume_aa_update_mountpoint(LibHalContext *hal_ctx, const char *udi,
118918c2aff7Sartem     struct action_arg *aap)
119018c2aff7Sartem {
119118c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
119218c2aff7Sartem 		free(aap->aa_mountpoint);
119318c2aff7Sartem 	}
119418c2aff7Sartem 	aap->aa_mountpoint = rmm_get_mnttab_mount_point(aap->aa_path);
119518c2aff7Sartem }
119618c2aff7Sartem 
119718c2aff7Sartem void
rmm_volume_aa_free(struct action_arg * aap)119818c2aff7Sartem rmm_volume_aa_free(struct action_arg *aap)
119918c2aff7Sartem {
120018c2aff7Sartem 	if (aap->aa_symdev != NULL) {
120118c2aff7Sartem 		libhal_free_string(aap->aa_symdev);
120218c2aff7Sartem 		aap->aa_symdev = NULL;
120318c2aff7Sartem 	}
120418c2aff7Sartem 	if (aap->aa_name != NULL) {
120518c2aff7Sartem 		free(aap->aa_name);
120618c2aff7Sartem 		aap->aa_name = NULL;
120718c2aff7Sartem 	}
120818c2aff7Sartem 	if (aap->aa_path != NULL) {
120918c2aff7Sartem 		libhal_free_string(aap->aa_path);
121018c2aff7Sartem 		aap->aa_path = NULL;
121118c2aff7Sartem 	}
121218c2aff7Sartem 	if (aap->aa_rawpath != NULL) {
121318c2aff7Sartem 		libhal_free_string(aap->aa_rawpath);
121418c2aff7Sartem 		aap->aa_rawpath = NULL;
121518c2aff7Sartem 	}
121618c2aff7Sartem 	if (aap->aa_type != NULL) {
121718c2aff7Sartem 		libhal_free_string(aap->aa_type);
121818c2aff7Sartem 		aap->aa_type = NULL;
121918c2aff7Sartem 	}
122018c2aff7Sartem 	if (aap->aa_media != NULL) {
122118c2aff7Sartem 		libhal_free_string(aap->aa_media);
122218c2aff7Sartem 		aap->aa_media = NULL;
122318c2aff7Sartem 	}
122418c2aff7Sartem 	if (aap->aa_partname != NULL) {
122518c2aff7Sartem 		libhal_free_string(aap->aa_partname);
122618c2aff7Sartem 		aap->aa_partname = NULL;
122718c2aff7Sartem 	}
122818c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
122918c2aff7Sartem 		free(aap->aa_mountpoint);
123018c2aff7Sartem 		aap->aa_mountpoint = NULL;
123118c2aff7Sartem 	}
123218c2aff7Sartem }
123318c2aff7Sartem 
123418c2aff7Sartem /*
123518c2aff7Sartem  * get device's mount point from mnttab
123618c2aff7Sartem  */
123718c2aff7Sartem char *
rmm_get_mnttab_mount_point(const char * special)123818c2aff7Sartem rmm_get_mnttab_mount_point(const char *special)
123918c2aff7Sartem {
124018c2aff7Sartem 	char		*mount_point = NULL;
124118c2aff7Sartem 	FILE		*f;
124218c2aff7Sartem 	struct mnttab	mnt;
124318c2aff7Sartem 	struct mnttab	mpref = { NULL, NULL, NULL, NULL, NULL };
124418c2aff7Sartem 
124518c2aff7Sartem 	if ((f = fopen(MNTTAB, "r")) != NULL) {
124618c2aff7Sartem 		mpref.mnt_special = (char *)special;
124718c2aff7Sartem 		if (getmntany(f, &mnt, &mpref) == 0) {
124818c2aff7Sartem 			mount_point = strdup(mnt.mnt_mountp);
124918c2aff7Sartem 		}
125018c2aff7Sartem 		fclose(f);
125118c2aff7Sartem 	}
125218c2aff7Sartem 
125318c2aff7Sartem 	return (mount_point);
125418c2aff7Sartem }
125518c2aff7Sartem 
125618c2aff7Sartem 
125718c2aff7Sartem /*
125818c2aff7Sartem  * get human readable string from error values
125918c2aff7Sartem  */
126018c2aff7Sartem const char *
rmm_strerror(DBusError * dbus_error,int rmm_error)126118c2aff7Sartem rmm_strerror(DBusError *dbus_error, int rmm_error)
126218c2aff7Sartem {
126318c2aff7Sartem 	const char	*str;
126418c2aff7Sartem 
126518c2aff7Sartem 	if ((dbus_error != NULL) && dbus_error_is_set(dbus_error)) {
126618c2aff7Sartem 		str = dbus_error->message;
126718c2aff7Sartem 	} else {
126818c2aff7Sartem 		switch (rmm_error) {
126918c2aff7Sartem 		case RMM_EOK:
127018c2aff7Sartem 			str = gettext("success");
127118c2aff7Sartem 			break;
127218c2aff7Sartem 		case RMM_EDBUS_CONNECT:
127318c2aff7Sartem 			str = gettext("cannot connect to D-Bus");
127418c2aff7Sartem 			break;
127518c2aff7Sartem 		case RMM_EHAL_CONNECT:
127618c2aff7Sartem 			str = gettext("cannot connect to HAL");
127718c2aff7Sartem 			break;
127818c2aff7Sartem 		default:
127918c2aff7Sartem 			str = gettext("undefined error");
128018c2aff7Sartem 			break;
128118c2aff7Sartem 		}
128218c2aff7Sartem 	}
128318c2aff7Sartem 
128418c2aff7Sartem 	return (str);
128518c2aff7Sartem }
128618c2aff7Sartem 
128718c2aff7Sartem void
rmm_dbus_error_free(DBusError * error)128818c2aff7Sartem rmm_dbus_error_free(DBusError *error)
128918c2aff7Sartem {
129018c2aff7Sartem 	if (error != NULL && dbus_error_is_set(error)) {
129118c2aff7Sartem 		dbus_error_free(error);
129218c2aff7Sartem 	}
129318c2aff7Sartem }
129418c2aff7Sartem 
129518c2aff7Sartem static int
rmm_vold_isbadchar(int c)129618c2aff7Sartem rmm_vold_isbadchar(int c)
129718c2aff7Sartem {
129818c2aff7Sartem 	int	ret_val = 0;
129918c2aff7Sartem 
130018c2aff7Sartem 
130118c2aff7Sartem 	switch (c) {
130218c2aff7Sartem 	case '/':
130318c2aff7Sartem 	case ';':
130418c2aff7Sartem 	case '|':
130518c2aff7Sartem 		ret_val = 1;
130618c2aff7Sartem 		break;
130718c2aff7Sartem 	default:
130818c2aff7Sartem 		if (iscntrl(c) || isspace(c)) {
130918c2aff7Sartem 			ret_val = 1;
131018c2aff7Sartem 		}
131118c2aff7Sartem 	}
131218c2aff7Sartem 
131318c2aff7Sartem 	return (ret_val);
131418c2aff7Sartem }
131518c2aff7Sartem 
131618c2aff7Sartem char *
rmm_vold_convert_volume_label(const char * name,size_t len)131718c2aff7Sartem rmm_vold_convert_volume_label(const char *name, size_t len)
131818c2aff7Sartem {
131918c2aff7Sartem 	char	buf[MAXNAMELEN+1];
132018c2aff7Sartem 	char	*s = buf;
132118c2aff7Sartem 	int	i;
132218c2aff7Sartem 
132318c2aff7Sartem 	if (len > MAXNAMELEN) {
132418c2aff7Sartem 		len = MAXNAMELEN;
132518c2aff7Sartem 	}
132618c2aff7Sartem 
132718c2aff7Sartem 	for (i = 0; i < len; i++) {
132818c2aff7Sartem 		if (name[i] == '\0') {
132918c2aff7Sartem 			break;
133018c2aff7Sartem 		}
133118c2aff7Sartem 		if (isgraph((int)name[i])) {
133218c2aff7Sartem 			if (isupper((int)name[i])) {
133318c2aff7Sartem 				*s++ = tolower((int)name[i]);
133418c2aff7Sartem 			} else if (rmm_vold_isbadchar((int)name[i])) {
133518c2aff7Sartem 				*s++ = '_';
133618c2aff7Sartem 			} else {
133718c2aff7Sartem 				*s++ = name[i];
133818c2aff7Sartem 			}
133918c2aff7Sartem 		}
134018c2aff7Sartem 	}
134118c2aff7Sartem 	*s = '\0';
134218c2aff7Sartem 	s = strdup(buf);
134318c2aff7Sartem 
134418c2aff7Sartem 	return (s);
134518c2aff7Sartem }
134618c2aff7Sartem 
134718c2aff7Sartem /*
134818c2aff7Sartem  * swiped from mkdir.c
134918c2aff7Sartem  */
135018c2aff7Sartem int
makepath(char * dir,mode_t mode)135118c2aff7Sartem makepath(char *dir, mode_t mode)
135218c2aff7Sartem {
135318c2aff7Sartem 	int		err;
135418c2aff7Sartem 	char		*slash;
135518c2aff7Sartem 
135618c2aff7Sartem 
135718c2aff7Sartem 	if ((mkdir(dir, mode) == 0) || (errno == EEXIST)) {
135818c2aff7Sartem 		return (0);
135918c2aff7Sartem 	}
136018c2aff7Sartem 	if (errno != ENOENT) {
136118c2aff7Sartem 		return (-1);
136218c2aff7Sartem 	}
136318c2aff7Sartem 	if ((slash = strrchr(dir, '/')) == NULL) {
136418c2aff7Sartem 		return (-1);
136518c2aff7Sartem 	}
136618c2aff7Sartem 	*slash = '\0';
136718c2aff7Sartem 	err = makepath(dir, mode);
136818c2aff7Sartem 	*slash++ = '/';
136918c2aff7Sartem 
137018c2aff7Sartem 	if (err || (*slash == '\0')) {
137118c2aff7Sartem 		return (err);
137218c2aff7Sartem 	}
137318c2aff7Sartem 
137418c2aff7Sartem 	return (mkdir(dir, mode));
137518c2aff7Sartem }
137618c2aff7Sartem 
137718c2aff7Sartem 
137818c2aff7Sartem void
dprintf(const char * fmt,...)137918c2aff7Sartem dprintf(const char *fmt, ...)
138018c2aff7Sartem {
138118c2aff7Sartem 
138218c2aff7Sartem 	va_list		ap;
138318c2aff7Sartem 	const char	*p;
138418c2aff7Sartem 	char		msg[BUFSIZ];
138518c2aff7Sartem 	char		*errmsg = strerror(errno);
138618c2aff7Sartem 	char		*s;
138718c2aff7Sartem 
138818c2aff7Sartem 	if (rmm_debug == 0) {
138918c2aff7Sartem 		return;
139018c2aff7Sartem 	}
139118c2aff7Sartem 
139218c2aff7Sartem 	(void) memset(msg, 0, BUFSIZ);
139318c2aff7Sartem 
139418c2aff7Sartem 	/* scan for %m and replace with errno msg */
139518c2aff7Sartem 	s = &msg[strlen(msg)];
139618c2aff7Sartem 	p = fmt;
139718c2aff7Sartem 
139818c2aff7Sartem 	while (*p != '\0') {
139918c2aff7Sartem 		if ((*p == '%') && (*(p+1) == 'm')) {
140018c2aff7Sartem 			(void) strcat(s, errmsg);
140118c2aff7Sartem 			p += 2;
140218c2aff7Sartem 			s += strlen(errmsg);
140318c2aff7Sartem 			continue;
140418c2aff7Sartem 		}
140518c2aff7Sartem 		*s++ = *p++;
140618c2aff7Sartem 	}
140718c2aff7Sartem 	*s = '\0';	/* don't forget the null byte */
140818c2aff7Sartem 
140918c2aff7Sartem 	va_start(ap, fmt);
141018c2aff7Sartem 	(void) vfprintf(stderr, msg, ap);
141118c2aff7Sartem 	va_end(ap);
141218c2aff7Sartem }
1413