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