xref: /titanic_53/usr/src/cmd/rmvolmgr/rmm_common.c (revision 7544909da5f7d5b467625910225a72e142c4b6b7)
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 /*
2218c2aff7Sartem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2318c2aff7Sartem  * Use is subject to license terms.
2418c2aff7Sartem  */
2518c2aff7Sartem 
2618c2aff7Sartem #pragma ident	"%Z%%M%	%I%	%E% SMI"
2718c2aff7Sartem 
2818c2aff7Sartem #include <stdio.h>
2918c2aff7Sartem #include <errno.h>
3018c2aff7Sartem #include <string.h>
3118c2aff7Sartem #include <strings.h>
3218c2aff7Sartem #include <stdarg.h>
3318c2aff7Sartem #include <fcntl.h>
3418c2aff7Sartem #include <libintl.h>
3518c2aff7Sartem #include <stdlib.h>
3618c2aff7Sartem #include <unistd.h>
3718c2aff7Sartem #include <ctype.h>
3818c2aff7Sartem #include <sys/param.h>
3918c2aff7Sartem #include <sys/types.h>
4018c2aff7Sartem #include <sys/stat.h>
4118c2aff7Sartem #include <sys/mnttab.h>
4218c2aff7Sartem 
4318c2aff7Sartem #include <dbus/dbus.h>
4418c2aff7Sartem #include <dbus/dbus-glib.h>
4518c2aff7Sartem #include <dbus/dbus-glib-lowlevel.h>
4618c2aff7Sartem #include <libhal.h>
4718c2aff7Sartem #include <libhal-storage.h>
4818c2aff7Sartem 
4918c2aff7Sartem #include "rmm_common.h"
5018c2aff7Sartem 
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,
6518c2aff7Sartem     LibHalDevicePropertyModified propmod_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 	}
11518c2aff7Sartem 
11618c2aff7Sartem 	if (!libhal_ctx_init(ctx, error)) {
11718c2aff7Sartem 		dprintf("libhal_ctx_init failed: %s", rmm_strerror(error, -1));
11818c2aff7Sartem 		libhal_ctx_free(ctx);
11918c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
12018c2aff7Sartem 		return (NULL);
12118c2aff7Sartem 	}
12218c2aff7Sartem 	rmm_dbus_error_free(error);
12318c2aff7Sartem 
12418c2aff7Sartem 	/*
12518c2aff7Sartem 	 * The above functions do not guarantee that HAL is actually running.
12618c2aff7Sartem 	 * Check by invoking a method.
12718c2aff7Sartem 	 */
12818c2aff7Sartem 	if (!(devices = libhal_get_all_devices(ctx, &nr, error))) {
12918c2aff7Sartem 		dprintf("HAL is not running: %s", rmm_strerror(error, -1));
13018c2aff7Sartem 		libhal_ctx_shutdown(ctx, NULL);
13118c2aff7Sartem 		libhal_ctx_free(ctx);
13218c2aff7Sartem 		*rmm_error = RMM_EHAL_CONNECT;
13318c2aff7Sartem 		return (NULL);
13418c2aff7Sartem 	} else {
13518c2aff7Sartem 		rmm_dbus_error_free(error);
13618c2aff7Sartem 		libhal_free_string_array(devices);
13718c2aff7Sartem 	}
13818c2aff7Sartem 
13918c2aff7Sartem 	return (ctx);
14018c2aff7Sartem }
14118c2aff7Sartem 
14218c2aff7Sartem 
14318c2aff7Sartem void
14418c2aff7Sartem rmm_hal_fini(LibHalContext *hal_ctx)
14518c2aff7Sartem {
14618c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
14718c2aff7Sartem 
14818c2aff7Sartem 	(void) dbus_connection_close(dbus_conn);
14918c2aff7Sartem 	(void) libhal_ctx_free(hal_ctx);
15018c2aff7Sartem }
15118c2aff7Sartem 
15218c2aff7Sartem 
15318c2aff7Sartem /*
15418c2aff7Sartem  * find volume from any type of name, similar to the old media_findname()
15518c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
15618c2aff7Sartem  */
15718c2aff7Sartem LibHalDrive *
15818c2aff7Sartem rmm_hal_volume_find(LibHalContext *hal_ctx, const char *name, DBusError *error,
15918c2aff7Sartem     GSList **volumes)
16018c2aff7Sartem {
16118c2aff7Sartem 	LibHalDrive	*drive;
16218c2aff7Sartem 	char		*p;
16318c2aff7Sartem 	char		lastc;
16418c2aff7Sartem 
16518c2aff7Sartem 	*volumes = NULL;
16618c2aff7Sartem 
16718c2aff7Sartem 	/* temporarily remove trailing slash */
16818c2aff7Sartem 	p = (char *)name + strlen(name) - 1;
16918c2aff7Sartem 	if (*p == '/') {
17018c2aff7Sartem 		lastc = *p;
17118c2aff7Sartem 		*p = '\0';
17218c2aff7Sartem 	} else {
17318c2aff7Sartem 		p = NULL;
17418c2aff7Sartem 	}
17518c2aff7Sartem 
17618c2aff7Sartem 	if (name[0] == '/') {
17718c2aff7Sartem 		if (((drive = rmm_hal_volume_findby(hal_ctx,
17818c2aff7Sartem 		    "info.udi", name, volumes)) != NULL) ||
17918c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18018c2aff7Sartem 		    "block.device", name, volumes)) != NULL) ||
18118c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18218c2aff7Sartem 		    "block.solaris.raw_device", name, volumes)) != NULL) ||
18318c2aff7Sartem 		    ((drive = rmm_hal_volume_findby(hal_ctx,
18418c2aff7Sartem 		    "volume.mount_point", name, volumes)) != NULL)) {
18518c2aff7Sartem 			goto out;
18618c2aff7Sartem 		} else {
18718c2aff7Sartem 			goto out;
18818c2aff7Sartem 		}
18918c2aff7Sartem 	}
19018c2aff7Sartem 
19118c2aff7Sartem 	/* try volume label */
19218c2aff7Sartem 	if ((drive = rmm_hal_volume_findby(hal_ctx,
19318c2aff7Sartem 	    "volume.label", name, volumes)) != NULL) {
19418c2aff7Sartem 		goto out;
19518c2aff7Sartem 	}
19618c2aff7Sartem 
19718c2aff7Sartem 	drive = rmm_hal_volume_findby_nickname(hal_ctx, name, volumes);
19818c2aff7Sartem 
19918c2aff7Sartem out:
20018c2aff7Sartem 	if (p != NULL) {
20118c2aff7Sartem 		*p = lastc;
20218c2aff7Sartem 	}
20318c2aff7Sartem 	return (drive);
20418c2aff7Sartem }
20518c2aff7Sartem 
20618c2aff7Sartem /*
20718c2aff7Sartem  * find default volume. Returns volume pointer and name in 'name'.
20818c2aff7Sartem  */
20918c2aff7Sartem LibHalDrive *
21018c2aff7Sartem rmm_hal_volume_find_default(LibHalContext *hal_ctx, DBusError *error,
21118c2aff7Sartem     const char **name_out, GSList **volumes)
21218c2aff7Sartem {
21318c2aff7Sartem 	LibHalDrive	*drive;
21418c2aff7Sartem 	static const char *names[] = { "floppy", "cdrom", "rmdisk" };
21518c2aff7Sartem 	int		i;
21618c2aff7Sartem 
21718c2aff7Sartem 	*volumes = NULL;
21818c2aff7Sartem 
21918c2aff7Sartem 	for (i = 0; i < NELEM(names); i++) {
22018c2aff7Sartem 		if ((drive = rmm_hal_volume_findby_nickname(hal_ctx,
22118c2aff7Sartem 		    names[i], volumes)) != NULL) {
22218c2aff7Sartem 			/*
22318c2aff7Sartem 			 * Skip floppy if it has no media.
22418c2aff7Sartem 			 * XXX might want to actually check for media
22518c2aff7Sartem 			 * every time instead of relying on volcheck.
22618c2aff7Sartem 			 */
22718c2aff7Sartem 			if ((strcmp(names[i], "floppy") != 0) ||
22818c2aff7Sartem 			    libhal_device_get_property_bool(hal_ctx,
22918c2aff7Sartem 			    libhal_drive_get_udi(drive),
23018c2aff7Sartem 			    "storage.removable.media_available", NULL)) {
23118c2aff7Sartem 				*name_out = names[i];
23218c2aff7Sartem 				break;
23318c2aff7Sartem 			}
23418c2aff7Sartem 		}
23518c2aff7Sartem 		rmm_dbus_error_free(error);
23618c2aff7Sartem 	}
23718c2aff7Sartem 
23818c2aff7Sartem 	return (drive);
23918c2aff7Sartem }
24018c2aff7Sartem 
24118c2aff7Sartem /*
24218c2aff7Sartem  * find volume by property=value
24318c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
24418c2aff7Sartem  * XXX add support for multiple properties, reduce D-Bus traffic
24518c2aff7Sartem  */
24618c2aff7Sartem LibHalDrive *
24718c2aff7Sartem rmm_hal_volume_findby(LibHalContext *hal_ctx, const char *property,
24818c2aff7Sartem     const char *value, GSList **volumes)
24918c2aff7Sartem {
25018c2aff7Sartem 	DBusError	error;
25118c2aff7Sartem 	LibHalDrive	*drive = NULL;
25218c2aff7Sartem 	LibHalVolume	*v = NULL;
25318c2aff7Sartem 	char		**udis;
25418c2aff7Sartem 	int		num_udis;
25518c2aff7Sartem 	int		i;
25618c2aff7Sartem 
25718c2aff7Sartem 	*volumes = NULL;
25818c2aff7Sartem 
25918c2aff7Sartem 	dbus_error_init(&error);
26018c2aff7Sartem 
26118c2aff7Sartem 	/* get all devices with property=value */
26218c2aff7Sartem 	if ((udis = libhal_manager_find_device_string_match(hal_ctx, property,
26318c2aff7Sartem 	    value, &num_udis, &error)) == NULL) {
26418c2aff7Sartem 		rmm_dbus_error_free(&error);
26518c2aff7Sartem 		return (NULL);
26618c2aff7Sartem 	}
26718c2aff7Sartem 
26818c2aff7Sartem 	/* find volumes among these devices */
26918c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
27018c2aff7Sartem 		rmm_dbus_error_free(&error);
27118c2aff7Sartem 		if (libhal_device_query_capability(hal_ctx, udis[i], "volume",
27218c2aff7Sartem 		    &error)) {
27318c2aff7Sartem 			v = libhal_volume_from_udi(hal_ctx, udis[i]);
27418c2aff7Sartem 			if (v != NULL) {
27518c2aff7Sartem 				*volumes = g_slist_prepend(*volumes, v);
27618c2aff7Sartem 			}
27718c2aff7Sartem 		}
27818c2aff7Sartem 	}
27918c2aff7Sartem 
28018c2aff7Sartem 	/* used prepend, preserve original order */
28118c2aff7Sartem 	if (*volumes != NULL) {
28218c2aff7Sartem 		*volumes = g_slist_reverse(*volumes);
28318c2aff7Sartem 
28418c2aff7Sartem 		v = (LibHalVolume *)(*volumes)->data;
28518c2aff7Sartem 		drive = libhal_drive_from_udi(hal_ctx,
28618c2aff7Sartem 		    libhal_volume_get_storage_device_udi(v));
28718c2aff7Sartem 		if (drive == NULL) {
28818c2aff7Sartem 			rmm_volumes_free (*volumes);
28918c2aff7Sartem 			*volumes = NULL;
29018c2aff7Sartem 		}
29118c2aff7Sartem 	}
29218c2aff7Sartem 
29318c2aff7Sartem 	libhal_free_string_array(udis);
29418c2aff7Sartem 	rmm_dbus_error_free(&error);
29518c2aff7Sartem 
29618c2aff7Sartem 	return (drive);
29718c2aff7Sartem }
29818c2aff7Sartem 
29918c2aff7Sartem 
30018c2aff7Sartem /*
30118c2aff7Sartem  * print nicknames for each available volume
30218c2aff7Sartem  */
30318c2aff7Sartem void
30418c2aff7Sartem rmm_print_volume_nicknames(LibHalContext *hal_ctx, DBusError *error)
30518c2aff7Sartem {
30618c2aff7Sartem 	char		**udis;
30718c2aff7Sartem 	int		num_udis;
30818c2aff7Sartem 	char		*block_device;
30918c2aff7Sartem 	char		*drive_udi;
31018c2aff7Sartem 	char		*volume_label;
31118c2aff7Sartem 	char		*mount_point;
31218c2aff7Sartem 	boolean_t	comma;
31318c2aff7Sartem 	char		**nicknames;
31418c2aff7Sartem 	int		i, j;
31518c2aff7Sartem 
31618c2aff7Sartem 	dbus_error_init(error);
31718c2aff7Sartem 
31818c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "volume",
31918c2aff7Sartem 	    &num_udis, error)) == NULL) {
32018c2aff7Sartem 		return;
32118c2aff7Sartem 	}
32218c2aff7Sartem 
32318c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
32418c2aff7Sartem 		if ((block_device = libhal_device_get_property_string(hal_ctx,
32518c2aff7Sartem 		    udis[i], "block.device", NULL)) == NULL) {
32618c2aff7Sartem 			continue;
32718c2aff7Sartem 		}
32818c2aff7Sartem 		if ((drive_udi = libhal_device_get_property_string(hal_ctx,
32918c2aff7Sartem 		    udis[i], "block.storage_device", NULL)) == NULL) {
33018c2aff7Sartem 			libhal_free_string(block_device);
33118c2aff7Sartem 			continue;
33218c2aff7Sartem 		}
33318c2aff7Sartem 		(void) printf("%s\t", block_device);
33418c2aff7Sartem 		comma = B_FALSE;
33518c2aff7Sartem 
33618c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
33718c2aff7Sartem 		    drive_udi, "storage.solaris.nicknames", NULL)) != NULL) {
33818c2aff7Sartem 			for (j = 0; nicknames[j] != NULL; j++) {
33918c2aff7Sartem 				(void) printf("%s%s", comma ? "," : "",
34018c2aff7Sartem 				    nicknames[j]);
34118c2aff7Sartem 				comma = B_TRUE;
34218c2aff7Sartem 			}
34318c2aff7Sartem 		}
34418c2aff7Sartem 
34518c2aff7Sartem 		if (((volume_label = libhal_device_get_property_string(hal_ctx,
34618c2aff7Sartem 		    udis[i], "volume.label", NULL)) != NULL) &&
34718c2aff7Sartem 		    (strlen(volume_label) > 0)) {
34818c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "", volume_label);
34918c2aff7Sartem 			comma = B_TRUE;
35018c2aff7Sartem 		}
35118c2aff7Sartem 
35218c2aff7Sartem 		if (((mount_point = libhal_device_get_property_string(hal_ctx,
35318c2aff7Sartem 		    udis[i], "volume.mount_point", NULL)) != NULL) &&
35418c2aff7Sartem 		    (strlen(mount_point) > 0)) {
35518c2aff7Sartem 			(void) printf("%s%s", comma ? "," : "", mount_point);
35618c2aff7Sartem 			comma = B_TRUE;
35718c2aff7Sartem 		}
35818c2aff7Sartem 
35918c2aff7Sartem 		(void) printf("\n");
36018c2aff7Sartem 
36118c2aff7Sartem 		libhal_free_string_array(nicknames);
36218c2aff7Sartem 		libhal_free_string(drive_udi);
36318c2aff7Sartem 		libhal_free_string(volume_label);
36418c2aff7Sartem 		libhal_free_string(mount_point);
36518c2aff7Sartem 		libhal_free_string(block_device);
36618c2aff7Sartem 	}
36718c2aff7Sartem 	libhal_free_string_array(udis);
36818c2aff7Sartem }
36918c2aff7Sartem 
37018c2aff7Sartem 
37118c2aff7Sartem /*
37218c2aff7Sartem  * find volume by nickname
37318c2aff7Sartem  * returns the LibHalDrive object and a list of LibHalVolume objects.
37418c2aff7Sartem  */
37518c2aff7Sartem LibHalDrive *
37618c2aff7Sartem rmm_hal_volume_findby_nickname(LibHalContext *hal_ctx, const char *name,
37718c2aff7Sartem     GSList **volumes)
37818c2aff7Sartem {
37918c2aff7Sartem 	DBusError	error;
38018c2aff7Sartem 	LibHalDrive	*drive = NULL;
38118c2aff7Sartem 	LibHalDrive	*drive_tmp;
38218c2aff7Sartem 	char		**udis;
38318c2aff7Sartem 	int		num_udis;
38418c2aff7Sartem 	char		**nicknames;
38518c2aff7Sartem 	int		i, j;
38618c2aff7Sartem 
38718c2aff7Sartem 	*volumes = NULL;
38818c2aff7Sartem 
38918c2aff7Sartem 	dbus_error_init(&error);
39018c2aff7Sartem 
39118c2aff7Sartem 	if ((udis = libhal_find_device_by_capability(hal_ctx, "storage",
39218c2aff7Sartem 	    &num_udis, &error)) == NULL) {
39318c2aff7Sartem 		rmm_dbus_error_free(&error);
39418c2aff7Sartem 		return (NULL);
39518c2aff7Sartem 	}
39618c2aff7Sartem 
39718c2aff7Sartem 	/* find a drive by nickname */
39818c2aff7Sartem 	for (i = 0; (i < num_udis) && (drive == NULL); i++) {
39918c2aff7Sartem 		if ((nicknames = libhal_device_get_property_strlist(hal_ctx,
40018c2aff7Sartem 		    udis[i], "storage.solaris.nicknames", &error)) == NULL) {
40118c2aff7Sartem 			rmm_dbus_error_free(&error);
40218c2aff7Sartem 			continue;
40318c2aff7Sartem 		}
40418c2aff7Sartem 		for (j = 0; (nicknames[j] != NULL) && (drive == NULL); j++) {
40518c2aff7Sartem 			if (strcmp(nicknames[j], name) == 0) {
40618c2aff7Sartem 				drive = libhal_drive_from_udi(hal_ctx, udis[i]);
40718c2aff7Sartem 			}
40818c2aff7Sartem 		}
40918c2aff7Sartem 		libhal_free_string_array(nicknames);
41018c2aff7Sartem 	}
41118c2aff7Sartem 	libhal_free_string_array(udis);
41218c2aff7Sartem 
41318c2aff7Sartem 	if (drive != NULL) {
41418c2aff7Sartem 		/* found the drive, now find its volumes */
41518c2aff7Sartem 		if ((drive_tmp = rmm_hal_volume_findby(hal_ctx,
41618c2aff7Sartem 		    "block.storage_device", libhal_drive_get_udi(drive),
41718c2aff7Sartem 		    volumes)) != NULL) {
41818c2aff7Sartem 			libhal_drive_free(drive_tmp);
41918c2aff7Sartem 		}
42018c2aff7Sartem 	}
42118c2aff7Sartem 
42218c2aff7Sartem 	rmm_dbus_error_free(&error);
42318c2aff7Sartem 
42418c2aff7Sartem 	return (drive);
42518c2aff7Sartem }
42618c2aff7Sartem 
42718c2aff7Sartem void
42818c2aff7Sartem rmm_volumes_free(GSList *volumes)
42918c2aff7Sartem {
43018c2aff7Sartem 	GSList	*i;
43118c2aff7Sartem 
43218c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
43318c2aff7Sartem 		libhal_volume_free((LibHalVolume *)(i->data));
43418c2aff7Sartem 	}
43518c2aff7Sartem 	g_slist_free(volumes);
43618c2aff7Sartem }
43718c2aff7Sartem 
43818c2aff7Sartem /*
43918c2aff7Sartem  * Call HAL's Mount() method on the given device
44018c2aff7Sartem  */
44118c2aff7Sartem boolean_t
44218c2aff7Sartem rmm_hal_mount(LibHalContext *hal_ctx, const char *udi,
44318c2aff7Sartem     char **opts, int num_opts, char *mountpoint, DBusError *error)
44418c2aff7Sartem {
44518c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
44618c2aff7Sartem 	DBusMessage	*dmesg, *reply;
44718c2aff7Sartem 	char		*fstype;
44818c2aff7Sartem 
44918c2aff7Sartem 	dprintf("mounting %s...\n", udi);
45018c2aff7Sartem 
45118c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
45218c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Mount"))) {
45318c2aff7Sartem 		dprintf(
45418c2aff7Sartem 		    "mount failed for %s: cannot create dbus message\n", udi);
45518c2aff7Sartem 		return (B_FALSE);
45618c2aff7Sartem 	}
45718c2aff7Sartem 
45818c2aff7Sartem 	fstype = "";
45918c2aff7Sartem 	if (mountpoint == NULL) {
46018c2aff7Sartem 		mountpoint = "";
46118c2aff7Sartem 	}
46218c2aff7Sartem 
46318c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &mountpoint,
46418c2aff7Sartem 	    DBUS_TYPE_STRING, &fstype,
46518c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &opts, num_opts,
46618c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
46718c2aff7Sartem 		dprintf("mount failed for %s: cannot append args\n", udi);
46818c2aff7Sartem 		dbus_message_unref(dmesg);
46918c2aff7Sartem 		return (B_FALSE);
47018c2aff7Sartem 	}
47118c2aff7Sartem 
47218c2aff7Sartem 	dbus_error_init(error);
47318c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
47418c2aff7Sartem 	    dmesg, -1, error))) {
47518c2aff7Sartem 		dprintf("mount failed for %s: %s\n", udi, error->message);
47618c2aff7Sartem 		dbus_message_unref(dmesg);
47718c2aff7Sartem 		return (B_FALSE);
47818c2aff7Sartem 	}
47918c2aff7Sartem 
48018c2aff7Sartem 	dprintf("mounted %s\n", udi);
48118c2aff7Sartem 
48218c2aff7Sartem 	dbus_message_unref(dmesg);
48318c2aff7Sartem 	dbus_message_unref(reply);
48418c2aff7Sartem 
48518c2aff7Sartem 	rmm_dbus_error_free(error);
48618c2aff7Sartem 
48718c2aff7Sartem 	return (B_TRUE);
48818c2aff7Sartem }
48918c2aff7Sartem 
49018c2aff7Sartem 
49118c2aff7Sartem /*
49218c2aff7Sartem  * Call HAL's Unmount() method on the given device
49318c2aff7Sartem  */
49418c2aff7Sartem boolean_t
49518c2aff7Sartem rmm_hal_unmount(LibHalContext *hal_ctx, const char *udi, DBusError *error)
49618c2aff7Sartem {
49718c2aff7Sartem 	DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
49818c2aff7Sartem 	DBusMessage *dmesg, *reply;
49918c2aff7Sartem 	char **opts = NULL;
50018c2aff7Sartem 
50118c2aff7Sartem 	dprintf("unmounting %s...\n", udi);
50218c2aff7Sartem 
50318c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
50418c2aff7Sartem 	    "org.freedesktop.Hal.Device.Volume", "Unmount"))) {
50518c2aff7Sartem 		dprintf(
50618c2aff7Sartem 		    "unmount failed %s: cannot create dbus message\n", udi);
50718c2aff7Sartem 		return (B_FALSE);
50818c2aff7Sartem 	}
50918c2aff7Sartem 
51018c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
51118c2aff7Sartem 	    &opts, 0, DBUS_TYPE_INVALID)) {
51218c2aff7Sartem 		dprintf("unmount failed %s: cannot append args\n", udi);
51318c2aff7Sartem 		dbus_message_unref(dmesg);
51418c2aff7Sartem 		return (B_FALSE);
51518c2aff7Sartem 	}
51618c2aff7Sartem 
51718c2aff7Sartem 	dbus_error_init(error);
51818c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
51918c2aff7Sartem 	    dmesg, -1, error))) {
52018c2aff7Sartem 		dprintf("unmount failed for %s: %s\n", udi, error->message);
52118c2aff7Sartem 		dbus_message_unref(dmesg);
52218c2aff7Sartem 		return (B_FALSE);
52318c2aff7Sartem 	}
52418c2aff7Sartem 
52518c2aff7Sartem 	dprintf("unmounted %s\n", udi);
52618c2aff7Sartem 
52718c2aff7Sartem 	dbus_message_unref(dmesg);
52818c2aff7Sartem 	dbus_message_unref(reply);
52918c2aff7Sartem 
53018c2aff7Sartem 	rmm_dbus_error_free(error);
53118c2aff7Sartem 
53218c2aff7Sartem 	return (B_TRUE);
53318c2aff7Sartem }
53418c2aff7Sartem 
53518c2aff7Sartem 
53618c2aff7Sartem /*
53718c2aff7Sartem  * Call HAL's Eject() method on the given device
53818c2aff7Sartem  */
53918c2aff7Sartem boolean_t
54018c2aff7Sartem rmm_hal_eject(LibHalContext *hal_ctx, const char *udi, DBusError *error)
54118c2aff7Sartem {
54218c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
54318c2aff7Sartem 	DBusMessage	*dmesg, *reply;
54418c2aff7Sartem 	char		**options = NULL;
54518c2aff7Sartem 	uint_t		num_options = 0;
54618c2aff7Sartem 
54718c2aff7Sartem 	dprintf("ejecting %s...\n", udi);
54818c2aff7Sartem 
54918c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
55018c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "Eject"))) {
55118c2aff7Sartem 		dprintf("eject %s: cannot create dbus message\n", udi);
55218c2aff7Sartem 		return (B_FALSE);
55318c2aff7Sartem 	}
55418c2aff7Sartem 
55518c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
55618c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
55718c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
55818c2aff7Sartem 		dprintf("eject %s: cannot append args to dbus message ", 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,
56518c2aff7Sartem 	    dmesg, -1, error))) {
56618c2aff7Sartem 		dprintf("eject %s: %s\n", udi, error->message);
56718c2aff7Sartem 		dbus_message_unref(dmesg);
56818c2aff7Sartem 		return (B_FALSE);
56918c2aff7Sartem 	}
57018c2aff7Sartem 
57118c2aff7Sartem 	dprintf("ejected %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  * Call HAL's CloseTray() method on the given device
58318c2aff7Sartem  */
58418c2aff7Sartem boolean_t
58518c2aff7Sartem rmm_hal_closetray(LibHalContext *hal_ctx, const char *udi, DBusError *error)
58618c2aff7Sartem {
58718c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
58818c2aff7Sartem 	DBusMessage	*dmesg, *reply;
58918c2aff7Sartem 	char		**options = NULL;
59018c2aff7Sartem 	uint_t		num_options = 0;
59118c2aff7Sartem 
59218c2aff7Sartem 	dprintf("closing tray %s...\n", udi);
59318c2aff7Sartem 
59418c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
59518c2aff7Sartem 	    "org.freedesktop.Hal.Device.Storage", "CloseTray"))) {
59618c2aff7Sartem 		dprintf(
59718c2aff7Sartem 		    "closetray failed for %s: cannot create dbus message\n",
59818c2aff7Sartem 		    udi);
59918c2aff7Sartem 		return (B_FALSE);
60018c2aff7Sartem 	}
60118c2aff7Sartem 
60218c2aff7Sartem 	if (!dbus_message_append_args(dmesg,
60318c2aff7Sartem 	    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
60418c2aff7Sartem 	    DBUS_TYPE_INVALID)) {
60518c2aff7Sartem 		dprintf("closetray %s: cannot append args to dbus message ",
60618c2aff7Sartem 		    udi);
60718c2aff7Sartem 		dbus_message_unref(dmesg);
60818c2aff7Sartem 		return (B_FALSE);
60918c2aff7Sartem 	}
61018c2aff7Sartem 
61118c2aff7Sartem 	dbus_error_init(error);
61218c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
61318c2aff7Sartem 	    dmesg, -1, error))) {
61418c2aff7Sartem 		dprintf("closetray failed for %s: %s\n", udi, error->message);
61518c2aff7Sartem 		dbus_message_unref(dmesg);
61618c2aff7Sartem 		return (B_FALSE);
61718c2aff7Sartem 	}
61818c2aff7Sartem 
61918c2aff7Sartem 	dprintf("closetray ok %s\n", udi);
62018c2aff7Sartem 
62118c2aff7Sartem 	dbus_message_unref(dmesg);
62218c2aff7Sartem 	dbus_message_unref(reply);
62318c2aff7Sartem 
62418c2aff7Sartem 	rmm_dbus_error_free(error);
62518c2aff7Sartem 
62618c2aff7Sartem 	return (B_TRUE);
62718c2aff7Sartem }
62818c2aff7Sartem 
62918c2aff7Sartem /*
63018c2aff7Sartem  * Call HAL's Rescan() method on the given device
63118c2aff7Sartem  */
63218c2aff7Sartem boolean_t
63318c2aff7Sartem rmm_hal_rescan(LibHalContext *hal_ctx, const char *udi, DBusError *error)
63418c2aff7Sartem {
63518c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
63618c2aff7Sartem 	DBusMessage	*dmesg, *reply;
63718c2aff7Sartem 
63818c2aff7Sartem 	dprintf("rescanning %s...\n", udi);
63918c2aff7Sartem 
64018c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
64118c2aff7Sartem 	    "org.freedesktop.Hal.Device", "Rescan"))) {
64218c2aff7Sartem 		dprintf("rescan failed for %s: cannot create dbus message\n",
64318c2aff7Sartem 		    udi);
64418c2aff7Sartem 		return (B_FALSE);
64518c2aff7Sartem 	}
64618c2aff7Sartem 
64718c2aff7Sartem 	dbus_error_init(error);
64818c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
64918c2aff7Sartem 	    dmesg, -1, error))) {
65018c2aff7Sartem 		dprintf("rescan failed for %s: %s\n", udi, error->message);
65118c2aff7Sartem 		dbus_message_unref(dmesg);
65218c2aff7Sartem 		return (B_FALSE);
65318c2aff7Sartem 	}
65418c2aff7Sartem 
65518c2aff7Sartem 	dprintf("rescan ok %s\n", udi);
65618c2aff7Sartem 
65718c2aff7Sartem 	dbus_message_unref(dmesg);
65818c2aff7Sartem 	dbus_message_unref(reply);
65918c2aff7Sartem 
66018c2aff7Sartem 	rmm_dbus_error_free(error);
66118c2aff7Sartem 
66218c2aff7Sartem 	return (B_TRUE);
66318c2aff7Sartem }
66418c2aff7Sartem 
66518c2aff7Sartem boolean_t
66618c2aff7Sartem rmm_hal_claim_branch(LibHalContext *hal_ctx, const char *udi)
66718c2aff7Sartem {
66818c2aff7Sartem 	DBusError error;
66918c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
67018c2aff7Sartem 	DBusMessage *dmesg, *reply;
67118c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
67218c2aff7Sartem 
67318c2aff7Sartem 	dprintf("claiming branch %s...\n", udi);
67418c2aff7Sartem 
67518c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
67618c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
67718c2aff7Sartem 	    "ClaimBranch"))) {
67818c2aff7Sartem 		dprintf("cannot create dbus message\n");
67918c2aff7Sartem 		return (B_FALSE);
68018c2aff7Sartem 	}
68118c2aff7Sartem 
68218c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
68318c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
68418c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
68518c2aff7Sartem 		dbus_message_unref(dmesg);
68618c2aff7Sartem 		return (B_FALSE);
68718c2aff7Sartem 	}
68818c2aff7Sartem 
68918c2aff7Sartem 	dbus_error_init(&error);
69018c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
69118c2aff7Sartem 	    dmesg, -1, &error))) {
69218c2aff7Sartem 		dprintf("cannot send dbus message\n");
69318c2aff7Sartem 		dbus_message_unref(dmesg);
69418c2aff7Sartem 		rmm_dbus_error_free(&error);
69518c2aff7Sartem 		return (B_FALSE);
69618c2aff7Sartem 	}
69718c2aff7Sartem 
69818c2aff7Sartem 	dprintf("claim branch ok %s\n", udi);
69918c2aff7Sartem 
70018c2aff7Sartem 	dbus_message_unref(dmesg);
70118c2aff7Sartem 	dbus_message_unref(reply);
70218c2aff7Sartem 
70318c2aff7Sartem 	return (B_TRUE);
70418c2aff7Sartem }
70518c2aff7Sartem 
70618c2aff7Sartem boolean_t
70718c2aff7Sartem rmm_hal_unclaim_branch(LibHalContext *hal_ctx, const char *udi)
70818c2aff7Sartem {
70918c2aff7Sartem 	DBusError error;
71018c2aff7Sartem 	DBusConnection	*dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
71118c2aff7Sartem 	DBusMessage *dmesg, *reply;
71218c2aff7Sartem 	const char *claimed_by = "rmvolmgr";
71318c2aff7Sartem 
71418c2aff7Sartem 	dprintf("unclaiming branch %s...\n", udi);
71518c2aff7Sartem 
71618c2aff7Sartem 	if (!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal",
71718c2aff7Sartem 	    "/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
71818c2aff7Sartem 	    "UnclaimBranch"))) {
71918c2aff7Sartem 		dprintf("cannot create dbus message\n");
72018c2aff7Sartem 		return (B_FALSE);
72118c2aff7Sartem 	}
72218c2aff7Sartem 
72318c2aff7Sartem 	if (!dbus_message_append_args(dmesg, DBUS_TYPE_STRING, &udi,
72418c2aff7Sartem 	    DBUS_TYPE_STRING, &claimed_by, DBUS_TYPE_INVALID)) {
72518c2aff7Sartem 		dprintf("cannot append args to dbus message\n");
72618c2aff7Sartem 		dbus_message_unref(dmesg);
72718c2aff7Sartem 		return (B_FALSE);
72818c2aff7Sartem 	}
72918c2aff7Sartem 
73018c2aff7Sartem 	dbus_error_init(&error);
73118c2aff7Sartem 	if (!(reply = dbus_connection_send_with_reply_and_block(dbus_conn,
73218c2aff7Sartem 	    dmesg, -1, &error))) {
73318c2aff7Sartem 		dprintf("cannot send dbus message\n");
73418c2aff7Sartem 		dbus_message_unref(dmesg);
73518c2aff7Sartem 		rmm_dbus_error_free(&error);
73618c2aff7Sartem 		return (B_FALSE);
73718c2aff7Sartem 	}
73818c2aff7Sartem 
73918c2aff7Sartem 	dprintf("unclaim branch ok %s\n", udi);
74018c2aff7Sartem 
74118c2aff7Sartem 	dbus_message_unref(dmesg);
74218c2aff7Sartem 	dbus_message_unref(reply);
74318c2aff7Sartem 
74418c2aff7Sartem 	return (B_TRUE);
74518c2aff7Sartem }
74618c2aff7Sartem 
74718c2aff7Sartem static boolean_t
74818c2aff7Sartem rmm_action_one(LibHalContext *hal_ctx, const char *name, action_t action,
74918c2aff7Sartem     const char *dev, const char *udi, LibHalVolume *v,
75018c2aff7Sartem     char **opts, int num_opts, char *mountpoint)
75118c2aff7Sartem {
75218c2aff7Sartem 	char		dev_str[MAXPATHLEN];
75318c2aff7Sartem 	char		*mountp;
75418c2aff7Sartem 	DBusError	error;
75518c2aff7Sartem 	boolean_t	ret = B_FALSE;
75618c2aff7Sartem 
75718c2aff7Sartem 	if (strcmp(name, dev) == 0) {
75818c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), name);
75918c2aff7Sartem 	} else {
76018c2aff7Sartem 		(void) snprintf(dev_str, sizeof (dev_str), "%s %s", name, dev);
76118c2aff7Sartem 	}
76218c2aff7Sartem 
76318c2aff7Sartem 	dbus_error_init(&error);
76418c2aff7Sartem 
76518c2aff7Sartem 	switch (action) {
76618c2aff7Sartem 	case EJECT:
76718c2aff7Sartem 		ret = rmm_hal_eject(hal_ctx, udi, &error);
76818c2aff7Sartem 		break;
76918c2aff7Sartem 	case INSERT:
77018c2aff7Sartem 	case REMOUNT:
77118c2aff7Sartem 		if (libhal_volume_is_mounted(v)) {
77218c2aff7Sartem 			goto done;
77318c2aff7Sartem 		}
77418c2aff7Sartem 		ret = rmm_hal_mount(hal_ctx, udi,
77518c2aff7Sartem 		    opts, num_opts, mountpoint, &error);
77618c2aff7Sartem 		break;
77718c2aff7Sartem 	case UNMOUNT:
77818c2aff7Sartem 		if (!libhal_volume_is_mounted(v)) {
77918c2aff7Sartem 			goto done;
78018c2aff7Sartem 		}
78118c2aff7Sartem 		ret = rmm_hal_unmount(hal_ctx, udi, &error);
78218c2aff7Sartem 		break;
78318c2aff7Sartem 	case CLOSETRAY:
78418c2aff7Sartem 		ret = rmm_hal_closetray(hal_ctx, udi, &error);
78518c2aff7Sartem 		break;
78618c2aff7Sartem 	}
78718c2aff7Sartem 
78818c2aff7Sartem 	if (!ret) {
78918c2aff7Sartem 		(void) fprintf(stderr, gettext("%s of %s failed: %s\n"),
79018c2aff7Sartem 		    action_strings[action], dev_str, rmm_strerror(&error, -1));
79118c2aff7Sartem 		goto done;
79218c2aff7Sartem 	}
79318c2aff7Sartem 
79418c2aff7Sartem 	switch (action) {
79518c2aff7Sartem 	case EJECT:
79618c2aff7Sartem 		(void) printf(gettext("%s ejected\n"), dev_str);
79718c2aff7Sartem 		break;
79818c2aff7Sartem 	case INSERT:
79918c2aff7Sartem 	case REMOUNT:
80018c2aff7Sartem 		mountp = rmm_get_mnttab_mount_point(dev);
80118c2aff7Sartem 		if (mountp != NULL) {
80218c2aff7Sartem 			(void) printf(gettext("%s mounted at %s\n"),
80318c2aff7Sartem 			    dev_str, mountp);
80418c2aff7Sartem 			free(mountp);
80518c2aff7Sartem 		}
80618c2aff7Sartem 		break;
80718c2aff7Sartem 	case UNMOUNT:
80818c2aff7Sartem 		(void) printf(gettext("%s unmounted\n"), dev_str);
80918c2aff7Sartem 		break;
81018c2aff7Sartem 	case CLOSETRAY:
81118c2aff7Sartem 		(void) printf(gettext("%s tray closed\n"), dev_str);
81218c2aff7Sartem 		break;
81318c2aff7Sartem 	}
81418c2aff7Sartem 
81518c2aff7Sartem done:
81618c2aff7Sartem 	rmm_dbus_error_free(&error);
81718c2aff7Sartem 	return (ret);
81818c2aff7Sartem }
81918c2aff7Sartem 
82018c2aff7Sartem /*
82118c2aff7Sartem  * top level action routine
82218c2aff7Sartem  *
82318c2aff7Sartem  * If non-null 'aa' is passed, it will be used, otherwise a local copy
82418c2aff7Sartem  * will be created.
82518c2aff7Sartem  */
82618c2aff7Sartem boolean_t
82718c2aff7Sartem rmm_action(LibHalContext *hal_ctx, const char *name, action_t action,
82818c2aff7Sartem     struct action_arg *aap, char **opts, int num_opts, char *mountpoint)
82918c2aff7Sartem {
83018c2aff7Sartem 	DBusError	error;
83118c2aff7Sartem 	GSList		*volumes, *i;
83218c2aff7Sartem 	LibHalDrive	*d;
83318c2aff7Sartem 	LibHalVolume	*v;
83418c2aff7Sartem 	const char	*udi, *d_udi;
83518c2aff7Sartem 	const char	*dev, *d_dev;
83618c2aff7Sartem 	struct action_arg aa_local;
83718c2aff7Sartem 	boolean_t	ret = B_FALSE;
83818c2aff7Sartem 
83918c2aff7Sartem 	dprintf("rmm_action %s %s\n", name, action_strings[action]);
84018c2aff7Sartem 
84118c2aff7Sartem 	if (aap == NULL) {
842*7544909dSartem 		bzero(&aa_local, sizeof (aa_local));
84318c2aff7Sartem 		aap = &aa_local;
84418c2aff7Sartem 	}
84518c2aff7Sartem 
84618c2aff7Sartem 	dbus_error_init(&error);
84718c2aff7Sartem 
84818c2aff7Sartem 	/* find the drive and its volumes */
84918c2aff7Sartem 	d = rmm_hal_volume_find(hal_ctx, name, &error, &volumes);
85018c2aff7Sartem 	rmm_dbus_error_free(&error);
85118c2aff7Sartem 	if (d == NULL) {
85218c2aff7Sartem 		(void) fprintf(stderr, gettext("cannot find '%s'\n"), name);
85318c2aff7Sartem 		return (B_FALSE);
85418c2aff7Sartem 	}
85518c2aff7Sartem 	d_udi = libhal_drive_get_udi(d);
85618c2aff7Sartem 	d_dev = libhal_drive_get_device_file(d);
85718c2aff7Sartem 	if ((d_udi == NULL) || (d_dev == NULL)) {
85818c2aff7Sartem 		goto out;
85918c2aff7Sartem 	}
86018c2aff7Sartem 
86118c2aff7Sartem 	/*
86218c2aff7Sartem 	 * For those drives that do not require media eject,
86318c2aff7Sartem 	 * EJECT turns into UNMOUNT.
86418c2aff7Sartem 	 */
86518c2aff7Sartem 	if ((action == EJECT) && !libhal_drive_requires_eject(d)) {
86618c2aff7Sartem 		action = UNMOUNT;
86718c2aff7Sartem 	}
86818c2aff7Sartem 
86918c2aff7Sartem 	/* per drive action */
87018c2aff7Sartem 	if ((action == EJECT) || (action == CLOSETRAY)) {
87118c2aff7Sartem 		ret = rmm_action_one(hal_ctx, name, action, d_dev, d_udi, NULL,
87218c2aff7Sartem 		    opts, num_opts, NULL);
87318c2aff7Sartem 
87418c2aff7Sartem 		if (!ret || (action == CLOSETRAY)) {
87518c2aff7Sartem 			goto out;
87618c2aff7Sartem 		}
87718c2aff7Sartem 	}
87818c2aff7Sartem 
87918c2aff7Sartem 	/* per volume action */
88018c2aff7Sartem 	for (i = volumes; i != NULL; i = g_slist_next(i)) {
88118c2aff7Sartem 		v = (LibHalVolume *)i->data;
88218c2aff7Sartem 		udi = libhal_volume_get_udi(v);
88318c2aff7Sartem 		dev = libhal_volume_get_device_file(v);
88418c2aff7Sartem 
88518c2aff7Sartem 		if ((udi == NULL) || (dev == NULL)) {
88618c2aff7Sartem 			continue;
88718c2aff7Sartem 		}
88818c2aff7Sartem 		if (aap == &aa_local) {
88918c2aff7Sartem 			if (!rmm_volume_aa_from_prop(hal_ctx, udi, v, aap)) {
89018c2aff7Sartem 				dprintf("rmm_volume_aa_from_prop failed %s\n",
89118c2aff7Sartem 				    udi);
89218c2aff7Sartem 				continue;
89318c2aff7Sartem 			}
89418c2aff7Sartem 		}
89518c2aff7Sartem 		aap->aa_action = action;
89618c2aff7Sartem 
89718c2aff7Sartem 		/* ejected above, just need postprocess */
89818c2aff7Sartem 		if (action != EJECT) {
89918c2aff7Sartem 			ret = rmm_action_one(hal_ctx, name, action, dev, udi, v,
90018c2aff7Sartem 			    opts, num_opts, mountpoint);
90118c2aff7Sartem 		}
90218c2aff7Sartem 		if (ret) {
90318c2aff7Sartem 			(void) vold_postprocess(hal_ctx, udi, aap);
90418c2aff7Sartem 		}
90518c2aff7Sartem 
90618c2aff7Sartem 		libhal_volume_free(v);
90718c2aff7Sartem 		if (aap == &aa_local) {
90818c2aff7Sartem 			rmm_volume_aa_free(aap);
90918c2aff7Sartem 		}
91018c2aff7Sartem 	}
91118c2aff7Sartem 
91218c2aff7Sartem out:
91318c2aff7Sartem 	g_slist_free(volumes);
91418c2aff7Sartem 	libhal_drive_free(d);
91518c2aff7Sartem 
91618c2aff7Sartem 	return (ret);
91718c2aff7Sartem }
91818c2aff7Sartem 
91918c2aff7Sartem 
92018c2aff7Sartem /*
92118c2aff7Sartem  * rescan by name
92218c2aff7Sartem  * if name is NULL, rescan all drives
92318c2aff7Sartem  */
92418c2aff7Sartem boolean_t
92518c2aff7Sartem rmm_rescan(LibHalContext *hal_ctx, const char *name, boolean_t query)
92618c2aff7Sartem {
92718c2aff7Sartem 	DBusError	error;
92818c2aff7Sartem 	GSList		*volumes;
92918c2aff7Sartem 	LibHalDrive	*drive = NULL;
93018c2aff7Sartem 	const char	*drive_udi;
93118c2aff7Sartem 	char		**udis;
93218c2aff7Sartem 	int		num_udis;
93318c2aff7Sartem 	char		*nickname;
93418c2aff7Sartem 	char		**nicks = NULL;
93518c2aff7Sartem 	boolean_t	do_free_udis = FALSE;
93618c2aff7Sartem 	int		i;
937*7544909dSartem 	boolean_t	ret = B_FALSE;
93818c2aff7Sartem 
93918c2aff7Sartem 	dprintf("rmm_rescan %s\n", name != NULL ? name : "all");
94018c2aff7Sartem 
94118c2aff7Sartem 	dbus_error_init(&error);
94218c2aff7Sartem 
94318c2aff7Sartem 	if (name != NULL) {
94418c2aff7Sartem 		if ((drive = rmm_hal_volume_find(hal_ctx, name, &error,
94518c2aff7Sartem 		    &volumes)) == NULL) {
94618c2aff7Sartem 			rmm_dbus_error_free(&error);
94718c2aff7Sartem 			(void) fprintf(stderr,
94818c2aff7Sartem 			    gettext("cannot find '%s'\n"), name);
94918c2aff7Sartem 			return (B_FALSE);
95018c2aff7Sartem 		}
95118c2aff7Sartem 		rmm_dbus_error_free(&error);
95218c2aff7Sartem 		g_slist_free(volumes);
95318c2aff7Sartem 
95418c2aff7Sartem 		drive_udi = libhal_drive_get_udi(drive);
95518c2aff7Sartem 		udis = (char **)&drive_udi;
95618c2aff7Sartem 		num_udis = 1;
95718c2aff7Sartem 	} else {
95818c2aff7Sartem 		if ((udis = libhal_find_device_by_capability(hal_ctx,
95918c2aff7Sartem 		    "storage", &num_udis, &error)) == NULL) {
96018c2aff7Sartem 			rmm_dbus_error_free(&error);
96118c2aff7Sartem 			return (B_TRUE);
96218c2aff7Sartem 		}
96318c2aff7Sartem 		rmm_dbus_error_free(&error);
96418c2aff7Sartem 		do_free_udis = TRUE;
96518c2aff7Sartem 	}
96618c2aff7Sartem 
96718c2aff7Sartem 	for (i = 0; i < num_udis; i++) {
96818c2aff7Sartem 		if (name == NULL) {
96918c2aff7Sartem 			nicks = libhal_device_get_property_strlist(hal_ctx,
97018c2aff7Sartem 			    udis[i], "storage.solaris.nicknames", NULL);
97118c2aff7Sartem 			if (nicks != NULL) {
97218c2aff7Sartem 				nickname = nicks[0];
97318c2aff7Sartem 			} else {
97418c2aff7Sartem 				nickname = "";
97518c2aff7Sartem 			}
97618c2aff7Sartem 		}
97718c2aff7Sartem 		if (!(ret = rmm_hal_rescan(hal_ctx, udis[i], &error))) {
97818c2aff7Sartem 			(void) fprintf(stderr,
97918c2aff7Sartem 			    gettext("rescan of %s failed: %s\n"),
98018c2aff7Sartem 			    name ? name : nickname,
98118c2aff7Sartem 			    rmm_strerror(&error, -1));
98218c2aff7Sartem 			libhal_free_string_array(nicks);
98318c2aff7Sartem 			continue;
98418c2aff7Sartem 		}
98518c2aff7Sartem 		if (query) {
986*7544909dSartem 			ret = libhal_device_get_property_bool(hal_ctx, udis[i],
987*7544909dSartem 			    "storage.removable.media_available", NULL);
988*7544909dSartem 			if (ret) {
989*7544909dSartem 				printf(gettext("%s is available\n"),
990*7544909dSartem 				    name ? name : nickname);
991*7544909dSartem 			} else {
992*7544909dSartem 				printf(gettext("%s is not available\n"),
993*7544909dSartem 				    name ? name : nickname);
994*7544909dSartem 			}
99518c2aff7Sartem 		}
99618c2aff7Sartem 		libhal_free_string_array(nicks);
99718c2aff7Sartem 	}
99818c2aff7Sartem 
99918c2aff7Sartem 	if (drive != NULL) {
100018c2aff7Sartem 		libhal_drive_free(drive);
100118c2aff7Sartem 	}
100218c2aff7Sartem 	if (do_free_udis) {
100318c2aff7Sartem 		libhal_free_string_array(udis);
100418c2aff7Sartem 	}
100518c2aff7Sartem 
100618c2aff7Sartem 	return (ret);
100718c2aff7Sartem }
100818c2aff7Sartem 
100918c2aff7Sartem 
101018c2aff7Sartem /*
101118c2aff7Sartem  * set action_arg from volume properties
101218c2aff7Sartem  */
101318c2aff7Sartem boolean_t
101418c2aff7Sartem rmm_volume_aa_from_prop(LibHalContext *hal_ctx, const char *udi_arg,
101518c2aff7Sartem     LibHalVolume *volume_arg, struct action_arg *aap)
101618c2aff7Sartem {
101718c2aff7Sartem 	LibHalVolume	*volume = volume_arg;
101818c2aff7Sartem 	const char	*udi = udi_arg;
101918c2aff7Sartem 	const char	*drive_udi;
102018c2aff7Sartem 	char		*volume_label;
102118c2aff7Sartem 	char		*mountpoint;
102218c2aff7Sartem 	int		len;
102318c2aff7Sartem 	int		ret = B_FALSE;
102418c2aff7Sartem 
102518c2aff7Sartem 	/* at least udi or volume must be supplied */
102618c2aff7Sartem 	if ((udi == NULL) && (volume == NULL)) {
102718c2aff7Sartem 		return (B_FALSE);
102818c2aff7Sartem 	}
102918c2aff7Sartem 	if (volume == NULL) {
103018c2aff7Sartem 		if ((volume = libhal_volume_from_udi(hal_ctx, udi)) == NULL) {
103118c2aff7Sartem 			dprintf("cannot get volume %s\n", udi);
103218c2aff7Sartem 			goto out;
103318c2aff7Sartem 		}
103418c2aff7Sartem 	}
103518c2aff7Sartem 	if (udi == NULL) {
103618c2aff7Sartem 		if ((udi = libhal_volume_get_udi(volume)) == NULL) {
103718c2aff7Sartem 			dprintf("cannot get udi\n");
103818c2aff7Sartem 			goto out;
103918c2aff7Sartem 		}
104018c2aff7Sartem 	}
104118c2aff7Sartem 	drive_udi = libhal_volume_get_storage_device_udi(volume);
104218c2aff7Sartem 
104318c2aff7Sartem 	if (!(aap->aa_symdev = libhal_device_get_property_string(hal_ctx,
104418c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.symdev", NULL))) {
104518c2aff7Sartem 		dprintf("property %s not found %s\n",
104618c2aff7Sartem 		    "storage.solaris.legacy.symdev", drive_udi);
104718c2aff7Sartem 		goto out;
104818c2aff7Sartem 	}
104918c2aff7Sartem 	if (!(aap->aa_media = libhal_device_get_property_string(hal_ctx,
105018c2aff7Sartem 	    drive_udi, "storage.solaris.legacy.media_type", NULL))) {
105118c2aff7Sartem 		dprintf("property %s not found %s\n",
105218c2aff7Sartem 		    "storage.solaris.legacy.media_type", drive_udi);
105318c2aff7Sartem 		goto out;
105418c2aff7Sartem 	}
105518c2aff7Sartem 
105618c2aff7Sartem 	/* name is derived from volume label */
105718c2aff7Sartem 	aap->aa_name = NULL;
105818c2aff7Sartem 	if ((volume_label = (char *)libhal_device_get_property_string(hal_ctx,
105918c2aff7Sartem 	    udi, "volume.label", NULL)) != NULL) {
106018c2aff7Sartem 		if ((len = strlen(volume_label)) > 0) {
106118c2aff7Sartem 			aap->aa_name = rmm_vold_convert_volume_label(
106218c2aff7Sartem 			    volume_label, len);
106318c2aff7Sartem 			if (strlen(aap->aa_name) == 0) {
106418c2aff7Sartem 				free(aap->aa_name);
106518c2aff7Sartem 				aap->aa_name = NULL;
106618c2aff7Sartem 			}
106718c2aff7Sartem 		}
106818c2aff7Sartem 		libhal_free_string(volume_label);
106918c2aff7Sartem 	}
107018c2aff7Sartem 	/* if no label, then unnamed_<mediatype> */
107118c2aff7Sartem 	if (aap->aa_name == NULL) {
107218c2aff7Sartem 		aap->aa_name = (char *)calloc(1, sizeof ("unnamed_floppyNNNN"));
107318c2aff7Sartem 		if (aap->aa_name == NULL) {
107418c2aff7Sartem 			goto out;
107518c2aff7Sartem 		}
107618c2aff7Sartem 		(void) snprintf(aap->aa_name, sizeof ("unnamed_floppyNNNN"),
107718c2aff7Sartem 		    "unnamed_%s", aap->aa_media);
107818c2aff7Sartem 	}
107918c2aff7Sartem 
108018c2aff7Sartem 	if (!(aap->aa_path = libhal_device_get_property_string(hal_ctx, udi,
108118c2aff7Sartem 	    "block.device", NULL))) {
108218c2aff7Sartem 		dprintf("property %s not found %s\n", "block.device", udi);
108318c2aff7Sartem 		goto out;
108418c2aff7Sartem 	}
108518c2aff7Sartem 	if (!(aap->aa_rawpath = libhal_device_get_property_string(hal_ctx, udi,
108618c2aff7Sartem 	    "block.solaris.raw_device", NULL))) {
108718c2aff7Sartem 		dprintf("property %s not found %s\n",
108818c2aff7Sartem 		    "block.solaris.raw_device", udi);
108918c2aff7Sartem 		goto out;
109018c2aff7Sartem 	}
109118c2aff7Sartem 	if (!(aap->aa_type = libhal_device_get_property_string(hal_ctx, udi,
109218c2aff7Sartem 	    "volume.fstype", NULL))) {
109318c2aff7Sartem 		dprintf("property %s not found %s\n", "volume.fstype", udi);
109418c2aff7Sartem 		goto out;
109518c2aff7Sartem 	}
109618c2aff7Sartem 	if (!libhal_device_get_property_bool(hal_ctx, udi,
109718c2aff7Sartem 	    "volume.is_partition", NULL)) {
109818c2aff7Sartem 		aap->aa_partname = NULL;
109918c2aff7Sartem 	} else if (!(aap->aa_partname = libhal_device_get_property_string(
110018c2aff7Sartem 	    hal_ctx, udi, "block.solaris.slice", NULL))) {
110118c2aff7Sartem 		dprintf("property %s not found %s\n",
110218c2aff7Sartem 		    "block.solaris.slice", udi);
110318c2aff7Sartem 		goto out;
110418c2aff7Sartem 	}
110518c2aff7Sartem 	if (!(mountpoint = libhal_device_get_property_string(hal_ctx, udi,
110618c2aff7Sartem 	    "volume.mount_point", NULL))) {
110718c2aff7Sartem 		dprintf("property %s not found %s\n",
110818c2aff7Sartem 		    "volume.mount_point", udi);
110918c2aff7Sartem 		goto out;
111018c2aff7Sartem 	}
111118c2aff7Sartem 	/*
111218c2aff7Sartem 	 * aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint()
111318c2aff7Sartem 	 * won't have to choose between free() or libhal_free_string() later on
111418c2aff7Sartem 	 */
111518c2aff7Sartem 	aap->aa_mountpoint = strdup(mountpoint);
111618c2aff7Sartem 	libhal_free_string(mountpoint);
111718c2aff7Sartem 	if (aap->aa_mountpoint == NULL) {
111818c2aff7Sartem 		dprintf("mountpoint is NULL %s\n", udi);
111918c2aff7Sartem 		goto out;
112018c2aff7Sartem 	}
112118c2aff7Sartem 
112218c2aff7Sartem 	ret = B_TRUE;
112318c2aff7Sartem 
112418c2aff7Sartem out:
112518c2aff7Sartem 	if ((volume != NULL) && (volume != volume_arg)) {
112618c2aff7Sartem 		libhal_volume_free(volume);
112718c2aff7Sartem 	}
112818c2aff7Sartem 	if (!ret) {
112918c2aff7Sartem 		rmm_volume_aa_free(aap);
113018c2aff7Sartem 	}
113118c2aff7Sartem 	return (ret);
113218c2aff7Sartem }
113318c2aff7Sartem 
113418c2aff7Sartem /* ARGSUSED */
113518c2aff7Sartem void
113618c2aff7Sartem rmm_volume_aa_update_mountpoint(LibHalContext *hal_ctx, const char *udi,
113718c2aff7Sartem     struct action_arg *aap)
113818c2aff7Sartem {
113918c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
114018c2aff7Sartem 		free(aap->aa_mountpoint);
114118c2aff7Sartem 	}
114218c2aff7Sartem 	aap->aa_mountpoint = rmm_get_mnttab_mount_point(aap->aa_path);
114318c2aff7Sartem }
114418c2aff7Sartem 
114518c2aff7Sartem void
114618c2aff7Sartem rmm_volume_aa_free(struct action_arg *aap)
114718c2aff7Sartem {
114818c2aff7Sartem 	if (aap->aa_symdev != NULL) {
114918c2aff7Sartem 		libhal_free_string(aap->aa_symdev);
115018c2aff7Sartem 		aap->aa_symdev = NULL;
115118c2aff7Sartem 	}
115218c2aff7Sartem 	if (aap->aa_name != NULL) {
115318c2aff7Sartem 		free(aap->aa_name);
115418c2aff7Sartem 		aap->aa_name = NULL;
115518c2aff7Sartem 	}
115618c2aff7Sartem 	if (aap->aa_path != NULL) {
115718c2aff7Sartem 		libhal_free_string(aap->aa_path);
115818c2aff7Sartem 		aap->aa_path = NULL;
115918c2aff7Sartem 	}
116018c2aff7Sartem 	if (aap->aa_rawpath != NULL) {
116118c2aff7Sartem 		libhal_free_string(aap->aa_rawpath);
116218c2aff7Sartem 		aap->aa_rawpath = NULL;
116318c2aff7Sartem 	}
116418c2aff7Sartem 	if (aap->aa_type != NULL) {
116518c2aff7Sartem 		libhal_free_string(aap->aa_type);
116618c2aff7Sartem 		aap->aa_type = NULL;
116718c2aff7Sartem 	}
116818c2aff7Sartem 	if (aap->aa_media != NULL) {
116918c2aff7Sartem 		libhal_free_string(aap->aa_media);
117018c2aff7Sartem 		aap->aa_media = NULL;
117118c2aff7Sartem 	}
117218c2aff7Sartem 	if (aap->aa_partname != NULL) {
117318c2aff7Sartem 		libhal_free_string(aap->aa_partname);
117418c2aff7Sartem 		aap->aa_partname = NULL;
117518c2aff7Sartem 	}
117618c2aff7Sartem 	if (aap->aa_mountpoint != NULL) {
117718c2aff7Sartem 		free(aap->aa_mountpoint);
117818c2aff7Sartem 		aap->aa_mountpoint = NULL;
117918c2aff7Sartem 	}
118018c2aff7Sartem }
118118c2aff7Sartem 
118218c2aff7Sartem /*
118318c2aff7Sartem  * get device's mount point from mnttab
118418c2aff7Sartem  */
118518c2aff7Sartem char *
118618c2aff7Sartem rmm_get_mnttab_mount_point(const char *special)
118718c2aff7Sartem {
118818c2aff7Sartem 	char		*mount_point = NULL;
118918c2aff7Sartem 	FILE		*f;
119018c2aff7Sartem 	struct mnttab	mnt;
119118c2aff7Sartem 	struct mnttab	mpref = { NULL, NULL, NULL, NULL, NULL };
119218c2aff7Sartem 
119318c2aff7Sartem 	if ((f = fopen(MNTTAB, "r")) != NULL) {
119418c2aff7Sartem 		mpref.mnt_special = (char *)special;
119518c2aff7Sartem 		if (getmntany(f, &mnt, &mpref) == 0) {
119618c2aff7Sartem 			mount_point = strdup(mnt.mnt_mountp);
119718c2aff7Sartem 		}
119818c2aff7Sartem 		fclose(f);
119918c2aff7Sartem 	}
120018c2aff7Sartem 
120118c2aff7Sartem 	return (mount_point);
120218c2aff7Sartem }
120318c2aff7Sartem 
120418c2aff7Sartem 
120518c2aff7Sartem /*
120618c2aff7Sartem  * get human readable string from error values
120718c2aff7Sartem  */
120818c2aff7Sartem const char *
120918c2aff7Sartem rmm_strerror(DBusError *dbus_error, int rmm_error)
121018c2aff7Sartem {
121118c2aff7Sartem 	const char	*str;
121218c2aff7Sartem 
121318c2aff7Sartem 	if ((dbus_error != NULL) && dbus_error_is_set(dbus_error)) {
121418c2aff7Sartem 		str = dbus_error->message;
121518c2aff7Sartem 	} else {
121618c2aff7Sartem 		switch (rmm_error) {
121718c2aff7Sartem 		case RMM_EOK:
121818c2aff7Sartem 			str = gettext("success");
121918c2aff7Sartem 			break;
122018c2aff7Sartem 		case RMM_EDBUS_CONNECT:
122118c2aff7Sartem 			str = gettext("cannot connect to D-Bus");
122218c2aff7Sartem 			break;
122318c2aff7Sartem 		case RMM_EHAL_CONNECT:
122418c2aff7Sartem 			str = gettext("cannot connect to HAL");
122518c2aff7Sartem 			break;
122618c2aff7Sartem 		default:
122718c2aff7Sartem 			str = gettext("undefined error");
122818c2aff7Sartem 			break;
122918c2aff7Sartem 		}
123018c2aff7Sartem 	}
123118c2aff7Sartem 
123218c2aff7Sartem 	return (str);
123318c2aff7Sartem }
123418c2aff7Sartem 
123518c2aff7Sartem void
123618c2aff7Sartem rmm_dbus_error_free(DBusError *error)
123718c2aff7Sartem {
123818c2aff7Sartem 	if (error != NULL && dbus_error_is_set(error)) {
123918c2aff7Sartem 		dbus_error_free(error);
124018c2aff7Sartem 	}
124118c2aff7Sartem }
124218c2aff7Sartem 
124318c2aff7Sartem static int
124418c2aff7Sartem rmm_vold_isbadchar(int c)
124518c2aff7Sartem {
124618c2aff7Sartem 	int	ret_val = 0;
124718c2aff7Sartem 
124818c2aff7Sartem 
124918c2aff7Sartem 	switch (c) {
125018c2aff7Sartem 	case '/':
125118c2aff7Sartem 	case ';':
125218c2aff7Sartem 	case '|':
125318c2aff7Sartem 		ret_val = 1;
125418c2aff7Sartem 		break;
125518c2aff7Sartem 	default:
125618c2aff7Sartem 		if (iscntrl(c) || isspace(c)) {
125718c2aff7Sartem 			ret_val = 1;
125818c2aff7Sartem 		}
125918c2aff7Sartem 	}
126018c2aff7Sartem 
126118c2aff7Sartem 	return (ret_val);
126218c2aff7Sartem }
126318c2aff7Sartem 
126418c2aff7Sartem char *
126518c2aff7Sartem rmm_vold_convert_volume_label(const char *name, size_t len)
126618c2aff7Sartem {
126718c2aff7Sartem 	char	buf[MAXNAMELEN+1];
126818c2aff7Sartem 	char	*s = buf;
126918c2aff7Sartem 	int	i;
127018c2aff7Sartem 
127118c2aff7Sartem 	if (len > MAXNAMELEN) {
127218c2aff7Sartem 		len = MAXNAMELEN;
127318c2aff7Sartem 	}
127418c2aff7Sartem 
127518c2aff7Sartem 	for (i = 0; i < len; i++) {
127618c2aff7Sartem 		if (name[i] == '\0') {
127718c2aff7Sartem 			break;
127818c2aff7Sartem 		}
127918c2aff7Sartem 		if (isgraph((int)name[i])) {
128018c2aff7Sartem 			if (isupper((int)name[i])) {
128118c2aff7Sartem 				*s++ = tolower((int)name[i]);
128218c2aff7Sartem 			} else if (rmm_vold_isbadchar((int)name[i])) {
128318c2aff7Sartem 				*s++ = '_';
128418c2aff7Sartem 			} else {
128518c2aff7Sartem 				*s++ = name[i];
128618c2aff7Sartem 			}
128718c2aff7Sartem 		}
128818c2aff7Sartem 	}
128918c2aff7Sartem 	*s = '\0';
129018c2aff7Sartem 	s = strdup(buf);
129118c2aff7Sartem 
129218c2aff7Sartem 	return (s);
129318c2aff7Sartem }
129418c2aff7Sartem 
129518c2aff7Sartem /*
129618c2aff7Sartem  * swiped from mkdir.c
129718c2aff7Sartem  */
129818c2aff7Sartem int
129918c2aff7Sartem makepath(char *dir, mode_t mode)
130018c2aff7Sartem {
130118c2aff7Sartem 	int		err;
130218c2aff7Sartem 	char		*slash;
130318c2aff7Sartem 
130418c2aff7Sartem 
130518c2aff7Sartem 	if ((mkdir(dir, mode) == 0) || (errno == EEXIST)) {
130618c2aff7Sartem 		return (0);
130718c2aff7Sartem 	}
130818c2aff7Sartem 	if (errno != ENOENT) {
130918c2aff7Sartem 		return (-1);
131018c2aff7Sartem 	}
131118c2aff7Sartem 	if ((slash = strrchr(dir, '/')) == NULL) {
131218c2aff7Sartem 		return (-1);
131318c2aff7Sartem 	}
131418c2aff7Sartem 	*slash = '\0';
131518c2aff7Sartem 	err = makepath(dir, mode);
131618c2aff7Sartem 	*slash++ = '/';
131718c2aff7Sartem 
131818c2aff7Sartem 	if (err || (*slash == '\0')) {
131918c2aff7Sartem 		return (err);
132018c2aff7Sartem 	}
132118c2aff7Sartem 
132218c2aff7Sartem 	return (mkdir(dir, mode));
132318c2aff7Sartem }
132418c2aff7Sartem 
132518c2aff7Sartem 
132618c2aff7Sartem void
132718c2aff7Sartem dprintf(const char *fmt, ...)
132818c2aff7Sartem {
132918c2aff7Sartem 
133018c2aff7Sartem 	va_list		ap;
133118c2aff7Sartem 	const char	*p;
133218c2aff7Sartem 	char		msg[BUFSIZ];
133318c2aff7Sartem 	char		*errmsg = strerror(errno);
133418c2aff7Sartem 	char		*s;
133518c2aff7Sartem 
133618c2aff7Sartem 	if (rmm_debug == 0) {
133718c2aff7Sartem 		return;
133818c2aff7Sartem 	}
133918c2aff7Sartem 
134018c2aff7Sartem 	(void) memset(msg, 0, BUFSIZ);
134118c2aff7Sartem 
134218c2aff7Sartem 	/* scan for %m and replace with errno msg */
134318c2aff7Sartem 	s = &msg[strlen(msg)];
134418c2aff7Sartem 	p = fmt;
134518c2aff7Sartem 
134618c2aff7Sartem 	while (*p != '\0') {
134718c2aff7Sartem 		if ((*p == '%') && (*(p+1) == 'm')) {
134818c2aff7Sartem 			(void) strcat(s, errmsg);
134918c2aff7Sartem 			p += 2;
135018c2aff7Sartem 			s += strlen(errmsg);
135118c2aff7Sartem 			continue;
135218c2aff7Sartem 		}
135318c2aff7Sartem 		*s++ = *p++;
135418c2aff7Sartem 	}
135518c2aff7Sartem 	*s = '\0';	/* don't forget the null byte */
135618c2aff7Sartem 
135718c2aff7Sartem 	va_start(ap, fmt);
135818c2aff7Sartem 	(void) vfprintf(stderr, msg, ap);
135918c2aff7Sartem 	va_end(ap);
136018c2aff7Sartem }
1361