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