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